Skip to content

Commit 89b94bb

Browse files
Sakshamsdevdeep
authored andcommitted
CLOUDSTACK-3382. Alert should be raised if a vm is migrated from dedicated to non-dedicated resource and vice versa.
Alerts are generated for VM migration between: 1) Source host is dedicated and destination host is not. 2) Source host is not dedicated and destination host is dedicated. 3) Both hosts are dedicated to different accounts/domains
1 parent f5023af commit 89b94bb

3 files changed

Lines changed: 236 additions & 19 deletions

File tree

server/src/com/cloud/deploy/dao/PlannerHostReservationDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ public interface PlannerHostReservationDao extends GenericDao<PlannerHostReserva
2727

2828
List<PlannerHostReservationVO> listAllReservedHosts();
2929

30+
List<PlannerHostReservationVO> listAllDedicatedHosts();
31+
3032
}

server/src/com/cloud/deploy/dao/PlannerHostReservationDaoImpl.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import javax.annotation.PostConstruct;
2222
import javax.ejb.Local;
23+
24+
import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage;
2325
import com.cloud.deploy.PlannerHostReservationVO;
2426
import com.cloud.utils.db.GenericDaoBase;
2527
import com.cloud.utils.db.SearchBuilder;
@@ -31,6 +33,7 @@ public class PlannerHostReservationDaoImpl extends GenericDaoBase<PlannerHostRes
3133

3234
private SearchBuilder<PlannerHostReservationVO> _hostIdSearch;
3335
private SearchBuilder<PlannerHostReservationVO> _reservedHostSearch;
36+
private SearchBuilder<PlannerHostReservationVO> _dedicatedHostSearch;;
3437

3538
public PlannerHostReservationDaoImpl() {
3639

@@ -45,6 +48,10 @@ protected void init() {
4548
_reservedHostSearch = createSearchBuilder();
4649
_reservedHostSearch.and("usage", _reservedHostSearch.entity().getResourceUsage(), SearchCriteria.Op.NNULL);
4750
_reservedHostSearch.done();
51+
52+
_dedicatedHostSearch = createSearchBuilder();
53+
_dedicatedHostSearch.and("usage", _dedicatedHostSearch.entity().getResourceUsage(), SearchCriteria.Op.EQ);
54+
_dedicatedHostSearch.done();
4855
}
4956

5057
@Override
@@ -60,4 +67,10 @@ public List<PlannerHostReservationVO> listAllReservedHosts() {
6067
return listBy(sc);
6168
}
6269

63-
}
70+
@Override
71+
public List<PlannerHostReservationVO> listAllDedicatedHosts() {
72+
SearchCriteria<PlannerHostReservationVO> sc = _dedicatedHostSearch.create();
73+
sc.setParameters("usage", PlannerResourceUsage.Dedicated);
74+
return listBy(sc);
75+
}
76+
}

server/src/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 220 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@
3333
import javax.inject.Inject;
3434
import javax.naming.ConfigurationException;
3535

36-
import org.apache.commons.codec.binary.Base64;
37-
import org.apache.log4j.Logger;
38-
3936
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
4037
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
4138
import org.apache.cloudstack.affinity.AffinityGroupService;
@@ -69,6 +66,8 @@
6966
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
7067
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
7168
import org.apache.cloudstack.storage.to.TemplateObjectTO;
69+
import org.apache.commons.codec.binary.Base64;
70+
import org.apache.log4j.Logger;
7271

7372
import com.cloud.agent.AgentManager;
7473
import com.cloud.agent.api.Answer;
@@ -107,6 +106,8 @@
107106
import com.cloud.deploy.DataCenterDeployment;
108107
import com.cloud.deploy.DeployDestination;
109108
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
109+
import com.cloud.deploy.PlannerHostReservationVO;
110+
import com.cloud.deploy.dao.PlannerHostReservationDao;
110111
import com.cloud.domain.DomainVO;
111112
import com.cloud.domain.dao.DomainDao;
112113
import com.cloud.event.ActionEvent;
@@ -178,6 +179,7 @@
178179
import com.cloud.server.Criteria;
179180
import com.cloud.service.ServiceOfferingVO;
180181
import com.cloud.service.dao.ServiceOfferingDao;
182+
import com.cloud.service.dao.ServiceOfferingDetailsDao;
181183
import com.cloud.storage.DiskOfferingVO;
182184
import com.cloud.storage.GuestOSCategoryVO;
183185
import com.cloud.storage.GuestOSVO;
@@ -221,6 +223,7 @@
221223
import com.cloud.user.dao.UserDao;
222224
import com.cloud.user.dao.VmDiskStatisticsDao;
223225
import com.cloud.uservm.UserVm;
226+
import com.cloud.utils.DateUtil;
224227
import com.cloud.utils.Journal;
225228
import com.cloud.utils.NumbersUtil;
226229
import com.cloud.utils.Pair;
@@ -418,11 +421,16 @@ public enum UserVmCloneType {
418421
ConfigurationServer _configServer;
419422
@Inject
420423
AffinityGroupService _affinityGroupService;
424+
@Inject
425+
PlannerHostReservationDao _plannerHostReservationDao;
426+
@Inject
427+
private ServiceOfferingDetailsDao serviceOfferingDetailsDao;
421428

422429
protected ScheduledExecutorService _executor = null;
423430
protected int _expungeInterval;
424431
protected int _expungeDelay;
425432
protected boolean _dailyOrHourly = false;
433+
private int capacityReleaseInterval;
426434

427435
protected String _name;
428436
protected String _instance;
@@ -1424,6 +1432,7 @@ public boolean configure(String name, Map<String, Object> params)
14241432

14251433
String workers = configs.get("expunge.workers");
14261434
int wrks = NumbersUtil.parseInt(workers, 10);
1435+
capacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()), 3600);
14271436

14281437
String time = configs.get("expunge.interval");
14291438
_expungeInterval = NumbersUtil.parseInt(time, 86400);
@@ -3833,22 +3842,9 @@ public VirtualMachine migrateVirtualMachine(Long vmId, Host destinationHost)
38333842
+ destinationHost.getResourceState());
38343843
}
38353844

3836-
HostVO srcHost = _hostDao.findById(srcHostId);
3837-
HostVO destHost = _hostDao.findById(destinationHost.getId());
3838-
//if srcHost is dedicated and destination Host is not
3839-
if (checkIfHostIsDedicated(srcHost) && !checkIfHostIsDedicated(destHost)) {
3840-
//raise an alert
3841-
String msg = "VM is migrated on a non-dedicated host " + destinationHost.getName();
3842-
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
3843-
}
3844-
//if srcHost is non dedicated but destination Host is.
3845-
if (!checkIfHostIsDedicated(srcHost) && checkIfHostIsDedicated(destHost)) {
3846-
//raise an alert
3847-
String msg = "VM is migrated on a dedicated host " + destinationHost.getName();
3848-
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
3849-
}
3845+
checkHostsDedication(vm, srcHostId, destinationHost.getId());
38503846

3851-
// call to core process
3847+
// call to core process
38523848
DataCenterVO dcVO = _dcDao.findById(destinationHost.getDataCenterId());
38533849
HostPodVO pod = _podDao.findById(destinationHost.getPodId());
38543850
Cluster cluster = _clusterDao.findById(destinationHost.getClusterId());
@@ -3891,6 +3887,210 @@ private boolean checkIfHostIsDedicated(HostVO host) {
38913887
}
38923888
}
38933889

3890+
private Long accountOfDedicatedHost(HostVO host) {
3891+
long hostId = host.getId();
3892+
DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId);
3893+
DedicatedResourceVO dedicatedClusterOfHost = _dedicatedDao.findByClusterId(host.getClusterId());
3894+
DedicatedResourceVO dedicatedPodOfHost = _dedicatedDao.findByPodId(host.getPodId());
3895+
if(dedicatedHost != null) {
3896+
return dedicatedHost.getAccountId();
3897+
}
3898+
if(dedicatedClusterOfHost != null) {
3899+
return dedicatedClusterOfHost.getAccountId();
3900+
}
3901+
if(dedicatedPodOfHost != null) {
3902+
return dedicatedPodOfHost.getAccountId();
3903+
}
3904+
return null;
3905+
}
3906+
3907+
private Long domainOfDedicatedHost(HostVO host) {
3908+
long hostId = host.getId();
3909+
DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId);
3910+
DedicatedResourceVO dedicatedClusterOfHost = _dedicatedDao.findByClusterId(host.getClusterId());
3911+
DedicatedResourceVO dedicatedPodOfHost = _dedicatedDao.findByPodId(host.getPodId());
3912+
if(dedicatedHost != null) {
3913+
return dedicatedHost.getDomainId();
3914+
}
3915+
if(dedicatedClusterOfHost != null) {
3916+
return dedicatedClusterOfHost.getDomainId();
3917+
}
3918+
if(dedicatedPodOfHost != null) {
3919+
return dedicatedPodOfHost.getDomainId();
3920+
}
3921+
return null;
3922+
}
3923+
3924+
public void checkHostsDedication (VMInstanceVO vm, long srcHostId, long destHostId) {
3925+
HostVO srcHost = _hostDao.findById(srcHostId);
3926+
HostVO destHost = _hostDao.findById(destHostId);
3927+
boolean srcExplDedicated = checkIfHostIsDedicated(srcHost);
3928+
boolean destExplDedicated = checkIfHostIsDedicated(destHost);
3929+
//if srcHost is explicitly dedicated and destination Host is not
3930+
if (srcExplDedicated && !destExplDedicated) {
3931+
//raise an alert
3932+
String msg = "VM is being migrated from a explicitly dedicated host " + srcHost.getName() +" to non-dedicated host " + destHost.getName();
3933+
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
3934+
s_logger.warn(msg);
3935+
}
3936+
//if srcHost is non dedicated but destination Host is explicitly dedicated
3937+
if (!srcExplDedicated && destExplDedicated) {
3938+
//raise an alert
3939+
String msg = "VM is being migrated from a non dedicated host " + srcHost.getName() + " to a explicitly dedicated host "+ destHost.getName();
3940+
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
3941+
s_logger.warn(msg);
3942+
}
3943+
3944+
//if hosts are dedicated to different account/domains, raise an alert
3945+
if (srcExplDedicated && destExplDedicated) {
3946+
if((accountOfDedicatedHost(srcHost) != null) && (accountOfDedicatedHost(srcHost)!= accountOfDedicatedHost(destHost))) {
3947+
String msg = "VM is being migrated from host " + srcHost.getName() + " explicitly dedicated to account " + accountOfDedicatedHost(srcHost) +
3948+
" to host " + destHost.getName() + " explicitly dedicated to account " + accountOfDedicatedHost(destHost);
3949+
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
3950+
s_logger.warn(msg);
3951+
}
3952+
if((domainOfDedicatedHost(srcHost) != null) && (domainOfDedicatedHost(srcHost)!= domainOfDedicatedHost(destHost))) {
3953+
String msg = "VM is being migrated from host " + srcHost.getName() + " explicitly dedicated to domain " + domainOfDedicatedHost(srcHost) +
3954+
" to host " + destHost.getName() + " explicitly dedicated to domain " + domainOfDedicatedHost(destHost);
3955+
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
3956+
s_logger.warn(msg);
3957+
}
3958+
}
3959+
3960+
// Checks for implicitly dedicated hosts
3961+
ServiceOfferingVO deployPlanner = _offeringDao.findById(vm.getServiceOfferingId());
3962+
if(deployPlanner.getDeploymentPlanner() != null && deployPlanner.getDeploymentPlanner().equals("ImplicitDedicationPlanner")) {
3963+
//VM is deployed using implicit planner
3964+
long accountOfVm = vm.getAccountId();
3965+
String msg = "VM of account " + accountOfVm + " with implicit deployment planner being migrated to host " + destHost.getName();
3966+
//Get all vms on destination host
3967+
boolean emptyDestination = false;
3968+
List<VMInstanceVO> vmsOnDest= getVmsOnHost(destHostId);
3969+
if (vmsOnDest == null || vmsOnDest.isEmpty()) {
3970+
emptyDestination = true;
3971+
}
3972+
3973+
if (!emptyDestination) {
3974+
//Check if vm is deployed using strict implicit planner
3975+
if(!isServiceOfferingUsingPlannerInPreferredMode(vm.getServiceOfferingId())) {
3976+
//Check if all vms on destination host are created using strict implicit mode
3977+
if(!checkIfAllVmsCreatedInStrictMode(accountOfVm, vmsOnDest)) {
3978+
msg = "VM of account " + accountOfVm + " with strict implicit deployment planner being migrated to host " + destHost.getName() +
3979+
" not having all vms strict implicitly dedicated to account " + accountOfVm;
3980+
}
3981+
} else {
3982+
//If vm is deployed using preferred implicit planner, check if all vms on destination host must be
3983+
//using implicit planner and must belong to same account
3984+
for (VMInstanceVO vmsDest : vmsOnDest) {
3985+
ServiceOfferingVO destPlanner = _offeringDao.findById(vmsDest.getServiceOfferingId());
3986+
if (!((destPlanner.getDeploymentPlanner() != null && destPlanner.getDeploymentPlanner().equals("ImplicitDedicationPlanner")) &&
3987+
vmsDest.getAccountId()==accountOfVm)) {
3988+
msg = "VM of account " + accountOfVm + " with preffered implicit deployment planner being migrated to host " + destHost.getName() +
3989+
" not having all vms implicitly dedicated to account " + accountOfVm;
3990+
}
3991+
}
3992+
}
3993+
}
3994+
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
3995+
s_logger.warn(msg);
3996+
3997+
} else {
3998+
//VM is not deployed using implicit planner, check if it migrated between dedicated hosts
3999+
List<PlannerHostReservationVO> reservedHosts = _plannerHostReservationDao.listAllDedicatedHosts();
4000+
boolean srcImplDedicated = false;
4001+
boolean destImplDedicated = false;
4002+
String msg = null;
4003+
for (PlannerHostReservationVO reservedHost : reservedHosts) {
4004+
if(reservedHost.getHostId() == srcHostId) {
4005+
srcImplDedicated = true;
4006+
}
4007+
if(reservedHost.getHostId() == destHostId) {
4008+
destImplDedicated = true;
4009+
}
4010+
}
4011+
if(srcImplDedicated) {
4012+
if(destImplDedicated){
4013+
msg = "VM is being migrated from implicitly dedicated host " + srcHost.getName() + " to another implicitly dedicated host " + destHost.getName();
4014+
} else {
4015+
msg = "VM is being migrated from implicitly dedicated host " + srcHost.getName() + " to shared host " + destHost.getName();
4016+
}
4017+
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
4018+
s_logger.warn(msg);
4019+
} else {
4020+
if (destImplDedicated) {
4021+
msg = "VM is being migrated from shared host " + srcHost.getName() + " to implicitly dedicated host " + destHost.getName();
4022+
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
4023+
s_logger.warn(msg);
4024+
}
4025+
}
4026+
}
4027+
}
4028+
4029+
private List<VMInstanceVO> getVmsOnHost(long hostId) {
4030+
List<VMInstanceVO> vms = _vmInstanceDao.listUpByHostId(hostId);
4031+
List<VMInstanceVO> vmsByLastHostId = _vmInstanceDao.listByLastHostId(hostId);
4032+
if (vmsByLastHostId.size() > 0) {
4033+
// check if any VMs are within skip.counting.hours, if yes we have to consider the host.
4034+
for (VMInstanceVO stoppedVM : vmsByLastHostId) {
4035+
long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - stoppedVM.getUpdateTime()
4036+
.getTime()) / 1000;
4037+
if (secondsSinceLastUpdate < capacityReleaseInterval) {
4038+
vms.add(stoppedVM);
4039+
}
4040+
}
4041+
}
4042+
4043+
return vms;
4044+
}
4045+
private boolean isServiceOfferingUsingPlannerInPreferredMode(long serviceOfferingId) {
4046+
boolean preferred = false;
4047+
Map<String, String> details = serviceOfferingDetailsDao.findDetails(serviceOfferingId);
4048+
if (details != null && !details.isEmpty()) {
4049+
String preferredAttribute = details.get("ImplicitDedicationMode");
4050+
if (preferredAttribute != null && preferredAttribute.equals("Preferred")) {
4051+
preferred = true;
4052+
}
4053+
}
4054+
return preferred;
4055+
}
4056+
4057+
private boolean checkIfAllVmsCreatedInStrictMode(Long accountId, List<VMInstanceVO> allVmsOnHost) {
4058+
boolean createdByImplicitStrict = true;
4059+
if (allVmsOnHost.isEmpty())
4060+
return false;
4061+
for (VMInstanceVO vm : allVmsOnHost) {
4062+
if (!isImplicitPlannerUsedByOffering(vm.getServiceOfferingId()) || vm.getAccountId()!= accountId) {
4063+
s_logger.info("Host " + vm.getHostId() + " found to be running a vm created by a planner other" +
4064+
" than implicit, or running vms of other account");
4065+
createdByImplicitStrict = false;
4066+
break;
4067+
} else if (isServiceOfferingUsingPlannerInPreferredMode(vm.getServiceOfferingId()) || vm.getAccountId()!= accountId) {
4068+
s_logger.info("Host " + vm.getHostId() + " found to be running a vm created by an implicit planner" +
4069+
" in preferred mode, or running vms of other account");
4070+
createdByImplicitStrict = false;
4071+
break;
4072+
}
4073+
}
4074+
return createdByImplicitStrict;
4075+
}
4076+
4077+
private boolean isImplicitPlannerUsedByOffering(long offeringId) {
4078+
boolean implicitPlannerUsed = false;
4079+
ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(offeringId);
4080+
if (offering == null) {
4081+
s_logger.error("Couldn't retrieve the offering by the given id : " + offeringId);
4082+
} else {
4083+
String plannerName = offering.getDeploymentPlanner();
4084+
if (plannerName != null) {
4085+
if(plannerName.equals("ImplicitDedicationPlanner")) {
4086+
implicitPlannerUsed = true;
4087+
}
4088+
}
4089+
}
4090+
4091+
return implicitPlannerUsed;
4092+
}
4093+
38944094
@Override
38954095
@ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true)
38964096
public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost,
@@ -4008,6 +4208,8 @@ public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinatio
40084208
" migrate to this host");
40094209
}
40104210

4211+
checkHostsDedication(vm, srcHostId, destinationHost.getId());
4212+
40114213
VMInstanceVO migratedVm = _itMgr.migrateWithStorage(vm, srcHostId, destinationHost.getId(), volToPoolObjectMap);
40124214
return migratedVm;
40134215
}

0 commit comments

Comments
 (0)