|
33 | 33 | import javax.inject.Inject; |
34 | 34 | import javax.naming.ConfigurationException; |
35 | 35 |
|
36 | | -import org.apache.commons.codec.binary.Base64; |
37 | | -import org.apache.log4j.Logger; |
38 | | - |
39 | 36 | import org.apache.cloudstack.acl.ControlledEntity.ACLType; |
40 | 37 | import org.apache.cloudstack.acl.SecurityChecker.AccessType; |
41 | 38 | import org.apache.cloudstack.affinity.AffinityGroupService; |
|
69 | 66 | import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; |
70 | 67 | import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; |
71 | 68 | import org.apache.cloudstack.storage.to.TemplateObjectTO; |
| 69 | +import org.apache.commons.codec.binary.Base64; |
| 70 | +import org.apache.log4j.Logger; |
72 | 71 |
|
73 | 72 | import com.cloud.agent.AgentManager; |
74 | 73 | import com.cloud.agent.api.Answer; |
|
107 | 106 | import com.cloud.deploy.DataCenterDeployment; |
108 | 107 | import com.cloud.deploy.DeployDestination; |
109 | 108 | import com.cloud.deploy.DeploymentPlanner.ExcludeList; |
| 109 | +import com.cloud.deploy.PlannerHostReservationVO; |
| 110 | +import com.cloud.deploy.dao.PlannerHostReservationDao; |
110 | 111 | import com.cloud.domain.DomainVO; |
111 | 112 | import com.cloud.domain.dao.DomainDao; |
112 | 113 | import com.cloud.event.ActionEvent; |
|
178 | 179 | import com.cloud.server.Criteria; |
179 | 180 | import com.cloud.service.ServiceOfferingVO; |
180 | 181 | import com.cloud.service.dao.ServiceOfferingDao; |
| 182 | +import com.cloud.service.dao.ServiceOfferingDetailsDao; |
181 | 183 | import com.cloud.storage.DiskOfferingVO; |
182 | 184 | import com.cloud.storage.GuestOSCategoryVO; |
183 | 185 | import com.cloud.storage.GuestOSVO; |
|
221 | 223 | import com.cloud.user.dao.UserDao; |
222 | 224 | import com.cloud.user.dao.VmDiskStatisticsDao; |
223 | 225 | import com.cloud.uservm.UserVm; |
| 226 | +import com.cloud.utils.DateUtil; |
224 | 227 | import com.cloud.utils.Journal; |
225 | 228 | import com.cloud.utils.NumbersUtil; |
226 | 229 | import com.cloud.utils.Pair; |
@@ -418,11 +421,16 @@ public enum UserVmCloneType { |
418 | 421 | ConfigurationServer _configServer; |
419 | 422 | @Inject |
420 | 423 | AffinityGroupService _affinityGroupService; |
| 424 | + @Inject |
| 425 | + PlannerHostReservationDao _plannerHostReservationDao; |
| 426 | + @Inject |
| 427 | + private ServiceOfferingDetailsDao serviceOfferingDetailsDao; |
421 | 428 |
|
422 | 429 | protected ScheduledExecutorService _executor = null; |
423 | 430 | protected int _expungeInterval; |
424 | 431 | protected int _expungeDelay; |
425 | 432 | protected boolean _dailyOrHourly = false; |
| 433 | + private int capacityReleaseInterval; |
426 | 434 |
|
427 | 435 | protected String _name; |
428 | 436 | protected String _instance; |
@@ -1424,6 +1432,7 @@ public boolean configure(String name, Map<String, Object> params) |
1424 | 1432 |
|
1425 | 1433 | String workers = configs.get("expunge.workers"); |
1426 | 1434 | int wrks = NumbersUtil.parseInt(workers, 10); |
| 1435 | + capacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()), 3600); |
1427 | 1436 |
|
1428 | 1437 | String time = configs.get("expunge.interval"); |
1429 | 1438 | _expungeInterval = NumbersUtil.parseInt(time, 86400); |
@@ -3833,22 +3842,9 @@ public VirtualMachine migrateVirtualMachine(Long vmId, Host destinationHost) |
3833 | 3842 | + destinationHost.getResourceState()); |
3834 | 3843 | } |
3835 | 3844 |
|
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()); |
3850 | 3846 |
|
3851 | | - // call to core process |
| 3847 | + // call to core process |
3852 | 3848 | DataCenterVO dcVO = _dcDao.findById(destinationHost.getDataCenterId()); |
3853 | 3849 | HostPodVO pod = _podDao.findById(destinationHost.getPodId()); |
3854 | 3850 | Cluster cluster = _clusterDao.findById(destinationHost.getClusterId()); |
@@ -3891,6 +3887,210 @@ private boolean checkIfHostIsDedicated(HostVO host) { |
3891 | 3887 | } |
3892 | 3888 | } |
3893 | 3889 |
|
| 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 | + |
3894 | 4094 | @Override |
3895 | 4095 | @ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true) |
3896 | 4096 | public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, |
@@ -4008,6 +4208,8 @@ public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinatio |
4008 | 4208 | " migrate to this host"); |
4009 | 4209 | } |
4010 | 4210 |
|
| 4211 | + checkHostsDedication(vm, srcHostId, destinationHost.getId()); |
| 4212 | + |
4011 | 4213 | VMInstanceVO migratedVm = _itMgr.migrateWithStorage(vm, srcHostId, destinationHost.getId(), volToPoolObjectMap); |
4012 | 4214 | return migratedVm; |
4013 | 4215 | } |
|
0 commit comments