mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	Allow deploy Admin VMs and VRs in disabled zones/pods/clusters (#3600)
This commit is contained in:
		
							parent
							
								
									6531ee5871
								
							
						
					
					
						commit
						a3cdd1f836
					
				| @ -22,9 +22,17 @@ import com.cloud.exception.AffinityConflictException; | |||||||
| import com.cloud.exception.InsufficientServerCapacityException; | import com.cloud.exception.InsufficientServerCapacityException; | ||||||
| import com.cloud.utils.component.Manager; | import com.cloud.utils.component.Manager; | ||||||
| import com.cloud.vm.VirtualMachineProfile; | import com.cloud.vm.VirtualMachineProfile; | ||||||
|  | import org.apache.cloudstack.framework.config.ConfigKey; | ||||||
| 
 | 
 | ||||||
| public interface DeploymentPlanningManager extends Manager { | public interface DeploymentPlanningManager extends Manager { | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     static final ConfigKey<Boolean> allowRouterOnDisabledResource = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.router.on.disabled.resources", "false", | ||||||
|  |             "Allow deploying VR in disabled Zones, Pods, and Clusters", true); | ||||||
|  | 
 | ||||||
|  |     static final ConfigKey<Boolean> allowAdminVmOnDisabledResource = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.admin.vm.on.disabled.resources", "false", | ||||||
|  |             "Allow deploying VMs owned by the admin account in disabled Clusters, Pods, and Zones", true); | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Manages vm deployment stages: First Process Affinity/Anti-affinity - Call |      * Manages vm deployment stages: First Process Affinity/Anti-affinity - Call | ||||||
|      * the chain of AffinityGroupProcessor adapters to set deploymentplan scope |      * the chain of AffinityGroupProcessor adapters to set deploymentplan scope | ||||||
|  | |||||||
| @ -83,8 +83,21 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat | |||||||
| 
 | 
 | ||||||
|     List<HostVO> findByClusterId(Long clusterId); |     List<HostVO> findByClusterId(Long clusterId); | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns hosts that are 'Up' and 'Enabled' from the given Data Center/Zone | ||||||
|  |      */ | ||||||
|     List<HostVO> listByDataCenterId(long id); |     List<HostVO> listByDataCenterId(long id); | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns hosts that are from the given Data Center/Zone and at a given state (e.g. Creating, Enabled, Disabled, etc). | ||||||
|  |      */ | ||||||
|  |     List<HostVO> listByDataCenterIdAndState(long id, ResourceState state); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns hosts that are 'Up' and 'Disabled' from the given Data Center/Zone | ||||||
|  |      */ | ||||||
|  |     List<HostVO> listDisabledByDataCenterId(long id); | ||||||
|  | 
 | ||||||
|     List<HostVO> listByDataCenterIdAndHypervisorType(long zoneId, Hypervisor.HypervisorType hypervisorType); |     List<HostVO> listByDataCenterIdAndHypervisorType(long zoneId, Hypervisor.HypervisorType hypervisorType); | ||||||
| 
 | 
 | ||||||
|     List<Long> listAllHosts(long zoneId); |     List<Long> listAllHosts(long zoneId); | ||||||
|  | |||||||
| @ -463,13 +463,27 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public List<HostVO> listByDataCenterId(long id) { |     public List<HostVO> listByDataCenterId(long id) { | ||||||
|  |         return listByDataCenterIdAndState(id, ResourceState.Enabled); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<HostVO> listByDataCenterIdAndState(long id, ResourceState state) { | ||||||
|  |         SearchCriteria<HostVO> sc = scHostsFromZoneUpRouting(id); | ||||||
|  |         sc.setParameters("resourceState", state); | ||||||
|  |         return listBy(sc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<HostVO> listDisabledByDataCenterId(long id) { | ||||||
|  |         return listByDataCenterIdAndState(id, ResourceState.Disabled); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private SearchCriteria<HostVO> scHostsFromZoneUpRouting(long id) { | ||||||
|         SearchCriteria<HostVO> sc = DcSearch.create(); |         SearchCriteria<HostVO> sc = DcSearch.create(); | ||||||
|         sc.setParameters("dc", id); |         sc.setParameters("dc", id); | ||||||
|         sc.setParameters("status", Status.Up); |         sc.setParameters("status", Status.Up); | ||||||
|         sc.setParameters("type", Host.Type.Routing); |         sc.setParameters("type", Host.Type.Routing); | ||||||
|         sc.setParameters("resourceState", ResourceState.Enabled); |         return sc; | ||||||
| 
 |  | ||||||
|         return listBy(sc); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
| @ -238,7 +238,7 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, Vi | |||||||
|         this.diskOfferingId = diskOfferingId; |         this.diskOfferingId = diskOfferingId; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     protected VMInstanceVO() { |     public VMInstanceVO() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Date getRemoved() { |     public Date getRemoved() { | ||||||
|  | |||||||
| @ -45,7 +45,6 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList; | |||||||
| import com.cloud.host.Host; | import com.cloud.host.Host; | ||||||
| import com.cloud.host.Host.Type; | import com.cloud.host.Host.Type; | ||||||
| import com.cloud.host.dao.HostDao; | import com.cloud.host.dao.HostDao; | ||||||
| import com.cloud.org.Grouping; |  | ||||||
| import com.cloud.resource.ResourceManager; | import com.cloud.resource.ResourceManager; | ||||||
| import com.cloud.storage.VolumeVO; | import com.cloud.storage.VolumeVO; | ||||||
| import com.cloud.storage.dao.VolumeDao; | import com.cloud.storage.dao.VolumeDao; | ||||||
| @ -122,21 +121,7 @@ public class RecreateHostAllocator extends FirstFitRoutingAllocator { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         for (PodCluster p : pcs) { |         for (PodCluster p : pcs) { | ||||||
|             if (p.getPod().getAllocationState() != Grouping.AllocationState.Enabled) { |  | ||||||
|                 if (s_logger.isDebugEnabled()) { |  | ||||||
|                     s_logger.debug("Pod name: " + p.getPod().getName() + ", podId: " + p.getPod().getId() + " is in " + p.getPod().getAllocationState().name() + |  | ||||||
|                         " state, skipping this and trying other pods"); |  | ||||||
|                 } |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|             Long clusterId = p.getCluster() == null ? null : p.getCluster().getId(); |             Long clusterId = p.getCluster() == null ? null : p.getCluster().getId(); | ||||||
|             if (p.getCluster() != null && p.getCluster().getAllocationState() != Grouping.AllocationState.Enabled) { |  | ||||||
|                 if (s_logger.isDebugEnabled()) { |  | ||||||
|                     s_logger.debug("Cluster name: " + p.getCluster().getName() + ", clusterId: " + clusterId + " is in " + p.getCluster().getAllocationState().name() + |  | ||||||
|                         " state, skipping this and trying other pod-clusters"); |  | ||||||
|                 } |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|             DataCenterDeployment newPlan = new DataCenterDeployment(plan.getDataCenterId(), p.getPod().getId(), clusterId, null, null, null); |             DataCenterDeployment newPlan = new DataCenterDeployment(plan.getDataCenterId(), p.getPod().getId(), clusterId, null, null, null); | ||||||
|             hosts = super.allocateTo(vm, newPlan, type, avoid, returnUpTo); |             hosts = super.allocateTo(vm, newPlan, type, avoid, returnUpTo); | ||||||
|             if (hosts != null && !hosts.isEmpty()) { |             if (hosts != null && !hosts.isEmpty()) { | ||||||
|  | |||||||
| @ -31,6 +31,20 @@ import javax.inject.Inject; | |||||||
| import javax.naming.ConfigurationException; | import javax.naming.ConfigurationException; | ||||||
| 
 | 
 | ||||||
| import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO; | import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO; | ||||||
|  | import com.cloud.storage.VMTemplateVO; | ||||||
|  | import com.cloud.storage.dao.VMTemplateDao; | ||||||
|  | import com.cloud.user.AccountVO; | ||||||
|  | import com.cloud.user.dao.AccountDao; | ||||||
|  | import com.cloud.utils.StringUtils; | ||||||
|  | import com.cloud.exception.StorageUnavailableException; | ||||||
|  | import com.cloud.utils.db.Filter; | ||||||
|  | import com.cloud.utils.fsm.StateMachine2; | ||||||
|  | 
 | ||||||
|  | import org.apache.cloudstack.framework.config.ConfigKey; | ||||||
|  | import org.apache.cloudstack.framework.config.Configurable; | ||||||
|  | import org.apache.commons.collections.CollectionUtils; | ||||||
|  | import org.apache.commons.collections.MapUtils; | ||||||
|  | import org.apache.log4j.Logger; | ||||||
| import org.apache.cloudstack.affinity.AffinityGroupProcessor; | import org.apache.cloudstack.affinity.AffinityGroupProcessor; | ||||||
| import org.apache.cloudstack.affinity.AffinityGroupService; | import org.apache.cloudstack.affinity.AffinityGroupService; | ||||||
| import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; | import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; | ||||||
| @ -50,9 +64,6 @@ import org.apache.cloudstack.managed.context.ManagedContextTimerTask; | |||||||
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; | import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; | ||||||
| import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; | import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; | ||||||
| import org.apache.cloudstack.utils.identity.ManagementServerNode; | import org.apache.cloudstack.utils.identity.ManagementServerNode; | ||||||
| import org.apache.commons.collections.CollectionUtils; |  | ||||||
| import org.apache.commons.collections.MapUtils; |  | ||||||
| import org.apache.log4j.Logger; |  | ||||||
| 
 | 
 | ||||||
| import com.cloud.agent.AgentManager; | import com.cloud.agent.AgentManager; | ||||||
| import com.cloud.agent.Listener; | import com.cloud.agent.Listener; | ||||||
| @ -84,7 +95,6 @@ import com.cloud.deploy.dao.PlannerHostReservationDao; | |||||||
| import com.cloud.exception.AffinityConflictException; | import com.cloud.exception.AffinityConflictException; | ||||||
| import com.cloud.exception.ConnectionException; | import com.cloud.exception.ConnectionException; | ||||||
| import com.cloud.exception.InsufficientServerCapacityException; | import com.cloud.exception.InsufficientServerCapacityException; | ||||||
| import com.cloud.exception.StorageUnavailableException; |  | ||||||
| import com.cloud.gpu.GPU; | import com.cloud.gpu.GPU; | ||||||
| import com.cloud.host.DetailVO; | import com.cloud.host.DetailVO; | ||||||
| import com.cloud.host.Host; | import com.cloud.host.Host; | ||||||
| @ -97,7 +107,6 @@ import com.cloud.offering.ServiceOffering; | |||||||
| import com.cloud.org.Cluster; | import com.cloud.org.Cluster; | ||||||
| import com.cloud.org.Grouping; | import com.cloud.org.Grouping; | ||||||
| import com.cloud.resource.ResourceManager; | import com.cloud.resource.ResourceManager; | ||||||
| import com.cloud.resource.ResourceState; |  | ||||||
| import com.cloud.service.ServiceOfferingDetailsVO; | import com.cloud.service.ServiceOfferingDetailsVO; | ||||||
| import com.cloud.service.dao.ServiceOfferingDetailsDao; | import com.cloud.service.dao.ServiceOfferingDetailsDao; | ||||||
| import com.cloud.storage.DiskOfferingVO; | import com.cloud.storage.DiskOfferingVO; | ||||||
| @ -107,31 +116,26 @@ import com.cloud.storage.Storage; | |||||||
| import com.cloud.storage.StorageManager; | import com.cloud.storage.StorageManager; | ||||||
| import com.cloud.storage.StoragePool; | import com.cloud.storage.StoragePool; | ||||||
| import com.cloud.storage.StoragePoolHostVO; | import com.cloud.storage.StoragePoolHostVO; | ||||||
| import com.cloud.storage.VMTemplateVO; |  | ||||||
| import com.cloud.storage.Volume; | import com.cloud.storage.Volume; | ||||||
| import com.cloud.storage.VolumeVO; | import com.cloud.storage.VolumeVO; | ||||||
| import com.cloud.storage.dao.DiskOfferingDao; | import com.cloud.storage.dao.DiskOfferingDao; | ||||||
| import com.cloud.storage.dao.GuestOSCategoryDao; | import com.cloud.storage.dao.GuestOSCategoryDao; | ||||||
| import com.cloud.storage.dao.GuestOSDao; | import com.cloud.storage.dao.GuestOSDao; | ||||||
| import com.cloud.storage.dao.StoragePoolHostDao; | import com.cloud.storage.dao.StoragePoolHostDao; | ||||||
| import com.cloud.storage.dao.VMTemplateDao; |  | ||||||
| import com.cloud.storage.dao.VolumeDao; | import com.cloud.storage.dao.VolumeDao; | ||||||
| import com.cloud.user.AccountManager; | import com.cloud.user.AccountManager; | ||||||
| import com.cloud.utils.DateUtil; | import com.cloud.utils.DateUtil; | ||||||
| import com.cloud.utils.NumbersUtil; | import com.cloud.utils.NumbersUtil; | ||||||
| import com.cloud.utils.Pair; | import com.cloud.utils.Pair; | ||||||
| import com.cloud.utils.StringUtils; |  | ||||||
| import com.cloud.utils.component.Manager; | import com.cloud.utils.component.Manager; | ||||||
| import com.cloud.utils.component.ManagerBase; | import com.cloud.utils.component.ManagerBase; | ||||||
| import com.cloud.utils.db.DB; | import com.cloud.utils.db.DB; | ||||||
| import com.cloud.utils.db.Filter; |  | ||||||
| import com.cloud.utils.db.SearchCriteria; | import com.cloud.utils.db.SearchCriteria; | ||||||
| import com.cloud.utils.db.Transaction; | import com.cloud.utils.db.Transaction; | ||||||
| import com.cloud.utils.db.TransactionCallback; | import com.cloud.utils.db.TransactionCallback; | ||||||
| import com.cloud.utils.db.TransactionStatus; | import com.cloud.utils.db.TransactionStatus; | ||||||
| import com.cloud.utils.exception.CloudRuntimeException; | import com.cloud.utils.exception.CloudRuntimeException; | ||||||
| import com.cloud.utils.fsm.StateListener; | import com.cloud.utils.fsm.StateListener; | ||||||
| import com.cloud.utils.fsm.StateMachine2; |  | ||||||
| import com.cloud.vm.DiskProfile; | import com.cloud.vm.DiskProfile; | ||||||
| import com.cloud.vm.VMInstanceVO; | import com.cloud.vm.VMInstanceVO; | ||||||
| import com.cloud.vm.VirtualMachine; | import com.cloud.vm.VirtualMachine; | ||||||
| @ -144,12 +148,14 @@ import com.cloud.vm.dao.VMInstanceDao; | |||||||
| import static com.cloud.utils.NumbersUtil.toHumanReadableSize; | import static com.cloud.utils.NumbersUtil.toHumanReadableSize; | ||||||
| 
 | 
 | ||||||
| public class DeploymentPlanningManagerImpl extends ManagerBase implements DeploymentPlanningManager, Manager, Listener, | public class DeploymentPlanningManagerImpl extends ManagerBase implements DeploymentPlanningManager, Manager, Listener, | ||||||
| StateListener<State, VirtualMachine.Event, VirtualMachine> { | StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable { | ||||||
| 
 | 
 | ||||||
|     private static final Logger s_logger = Logger.getLogger(DeploymentPlanningManagerImpl.class); |     private static final Logger s_logger = Logger.getLogger(DeploymentPlanningManagerImpl.class); | ||||||
|     @Inject |     @Inject | ||||||
|     AgentManager _agentMgr; |     AgentManager _agentMgr; | ||||||
|     @Inject |     @Inject | ||||||
|  |     private AccountDao accountDao; | ||||||
|  |     @Inject | ||||||
|     protected UserVmDao _vmDao; |     protected UserVmDao _vmDao; | ||||||
|     @Inject |     @Inject | ||||||
|     protected VMInstanceDao _vmInstanceDao; |     protected VMInstanceDao _vmInstanceDao; | ||||||
| @ -177,6 +183,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|     @Inject |     @Inject | ||||||
|     private VMTemplateDao templateDao; |     private VMTemplateDao templateDao; | ||||||
| 
 | 
 | ||||||
|  |     private static final long ADMIN_ACCOUNT_ROLE_ID = 1l; | ||||||
|     private static final long INITIAL_RESERVATION_RELEASE_CHECKER_DELAY = 30L * 1000L; // thirty seconds expressed in milliseconds |     private static final long INITIAL_RESERVATION_RELEASE_CHECKER_DELAY = 30L * 1000L; // thirty seconds expressed in milliseconds | ||||||
|     protected long _nodeId = -1; |     protected long _nodeId = -1; | ||||||
| 
 | 
 | ||||||
| @ -283,6 +290,8 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|             s_logger.debug("Is ROOT volume READY (pool already allocated)?: " + (plan.getPoolId() != null ? "Yes" : "No")); |             s_logger.debug("Is ROOT volume READY (pool already allocated)?: " + (plan.getPoolId() != null ? "Yes" : "No")); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         avoidDisabledResources(vmProfile, dc, avoids); | ||||||
|  | 
 | ||||||
|         String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag); |         String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag); | ||||||
|         String uefiFlag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.UefiFlag); |         String uefiFlag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.UefiFlag); | ||||||
| 
 | 
 | ||||||
| @ -311,17 +320,8 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 Pod pod = _podDao.findById(host.getPodId()); |                 Pod pod = _podDao.findById(host.getPodId()); | ||||||
|                 // check if the cluster or the pod is disabled |  | ||||||
|                 if (pod.getAllocationState() != Grouping.AllocationState.Enabled) { |  | ||||||
|                     s_logger.warn("The Pod containing this host is in disabled state, PodId= " + pod.getId()); |  | ||||||
|                     return null; |  | ||||||
|                 } |  | ||||||
| 
 | 
 | ||||||
|                 Cluster cluster = _clusterDao.findById(host.getClusterId()); |                 Cluster cluster = _clusterDao.findById(host.getClusterId()); | ||||||
|                 if (cluster.getAllocationState() != Grouping.AllocationState.Enabled) { |  | ||||||
|                     s_logger.warn("The Cluster containing this host is in disabled state, PodId= " + cluster.getId()); |  | ||||||
|                     return null; |  | ||||||
|                 } |  | ||||||
| 
 | 
 | ||||||
|                 boolean displayStorage = getDisplayStorageFromVmProfile(vmProfile); |                 boolean displayStorage = getDisplayStorageFromVmProfile(vmProfile); | ||||||
|                 if (vm.getHypervisorType() == HypervisorType.BareMetal) { |                 if (vm.getHypervisorType() == HypervisorType.BareMetal) { | ||||||
| @ -422,8 +422,15 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|                     s_logger.debug("The last host of this VM does not have required GPU devices available"); |                     s_logger.debug("The last host of this VM does not have required GPU devices available"); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 if (host.getStatus() == Status.Up && host.getResourceState() == ResourceState.Enabled) { |                 if (host.getStatus() == Status.Up) { | ||||||
|                     if (checkVmProfileAndHost(vmProfile, host)) { |                     boolean hostTagsMatch = true; | ||||||
|  |                     if(offering.getHostTag() != null){ | ||||||
|  |                         _hostDao.loadHostTags(host); | ||||||
|  |                         if (!(host.getHostTags() != null && host.getHostTags().contains(offering.getHostTag()))) { | ||||||
|  |                             hostTagsMatch = false; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     if (hostTagsMatch) { | ||||||
|                         long cluster_id = host.getClusterId(); |                         long cluster_id = host.getClusterId(); | ||||||
|                         ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id, |                         ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id, | ||||||
|                                 "cpuOvercommitRatio"); |                                 "cpuOvercommitRatio"); | ||||||
| @ -573,6 +580,86 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|         return vmProfile == null || vmProfile.getTemplate() == null || !vmProfile.getTemplate().isDeployAsIs(); |         return vmProfile == null || vmProfile.getTemplate() == null || !vmProfile.getTemplate().isDeployAsIs(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |         /** | ||||||
|  |          * Adds disabled resources (Data centers, Pods, Clusters, and hosts) to exclude list (avoid) in case of disabled state. | ||||||
|  |          */ | ||||||
|  |         public void avoidDisabledResources(VirtualMachineProfile vmProfile, DataCenter dc, ExcludeList avoids) { | ||||||
|  |             if (vmProfile.getType().isUsedBySystem() && isRouterDeployableInDisabledResources()) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             VMInstanceVO vm = _vmInstanceDao.findById(vmProfile.getId()); | ||||||
|  |             AccountVO owner = accountDao.findById(vm.getAccountId()); | ||||||
|  |             boolean isOwnerRoleIdAdmin = false; | ||||||
|  | 
 | ||||||
|  |             if (owner != null && owner.getRoleId() != null && owner.getRoleId() == ADMIN_ACCOUNT_ROLE_ID) { | ||||||
|  |                 isOwnerRoleIdAdmin = true; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (isOwnerRoleIdAdmin && isAdminVmDeployableInDisabledResources()) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             avoidDisabledDataCenters(dc, avoids); | ||||||
|  |             avoidDisabledPods(dc, avoids); | ||||||
|  |             avoidDisabledClusters(dc, avoids); | ||||||
|  |             avoidDisabledHosts(dc, avoids); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the value of the ConfigKey 'allow.router.on.disabled.resources'. | ||||||
|  |      * @note this method allows mocking and testing with the respective ConfigKey parameter. | ||||||
|  |      */ | ||||||
|  |     protected boolean isRouterDeployableInDisabledResources() { | ||||||
|  |         return allowRouterOnDisabledResource.value(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the value of the ConfigKey 'allow.admin.vm.on.disabled.resources'. | ||||||
|  |      * @note this method allows mocking and testing with the respective ConfigKey parameter. | ||||||
|  |      */ | ||||||
|  |     protected boolean isAdminVmDeployableInDisabledResources() { | ||||||
|  |         return allowAdminVmOnDisabledResource.value(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds disabled Hosts to the ExcludeList in order to avoid them at the deployment planner. | ||||||
|  |      */ | ||||||
|  |     protected void avoidDisabledHosts(DataCenter dc, ExcludeList avoids) { | ||||||
|  |         List<HostVO> disabledHosts = _hostDao.listDisabledByDataCenterId(dc.getId()); | ||||||
|  |         for (HostVO host : disabledHosts) { | ||||||
|  |             avoids.addHost(host.getId()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds disabled Clusters to the ExcludeList in order to avoid them at the deployment planner. | ||||||
|  |      */ | ||||||
|  |     protected void avoidDisabledClusters(DataCenter dc, ExcludeList avoids) { | ||||||
|  |         List<Long> pods = _podDao.listAllPods(dc.getId()); | ||||||
|  |         for (Long podId : pods) { | ||||||
|  |             List<Long> disabledClusters = _clusterDao.listDisabledClusters(dc.getId(), podId); | ||||||
|  |             avoids.addClusterList(disabledClusters); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds disabled Pods to the ExcludeList in order to avoid them at the deployment planner. | ||||||
|  |      */ | ||||||
|  |     protected void avoidDisabledPods(DataCenter dc, ExcludeList avoids) { | ||||||
|  |         List<Long> disabledPods = _podDao.listDisabledPods(dc.getId()); | ||||||
|  |         avoids.addPodList(disabledPods); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds disabled Data Centers (Zones) to the ExcludeList in order to avoid them at the deployment planner. | ||||||
|  |      */ | ||||||
|  |     protected void avoidDisabledDataCenters(DataCenter dc, ExcludeList avoids) { | ||||||
|  |         if (dc.getAllocationState() == Grouping.AllocationState.Disabled) { | ||||||
|  |             avoids.addDataCenter(dc.getId()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public DeploymentPlanner getDeploymentPlannerByName(String plannerName) { |     public DeploymentPlanner getDeploymentPlannerByName(String plannerName) { | ||||||
|         if (plannerName != null) { |         if (plannerName != null) { | ||||||
| @ -1092,11 +1179,6 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|         for (Long clusterId : clusterList) { |         for (Long clusterId : clusterList) { | ||||||
|             ClusterVO clusterVO = _clusterDao.findById(clusterId); |             ClusterVO clusterVO = _clusterDao.findById(clusterId); | ||||||
| 
 | 
 | ||||||
|             if (clusterVO.getAllocationState() == Grouping.AllocationState.Disabled && !plan.isMigrationPlan()) { |  | ||||||
|                 s_logger.debug("Cannot deploy in disabled cluster " + clusterId + ", skipping this cluster"); |  | ||||||
|                 avoid.addCluster(clusterVO.getId()); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (clusterVO.getHypervisorType() != vmProfile.getHypervisorType()) { |             if (clusterVO.getHypervisorType() != vmProfile.getHypervisorType()) { | ||||||
|                 s_logger.debug("Cluster: " + clusterId + " has HyperVisorType that does not match the VM, skipping this cluster"); |                 s_logger.debug("Cluster: " + clusterId + " has HyperVisorType that does not match the VM, skipping this cluster"); | ||||||
|                 avoid.addCluster(clusterVO.getId()); |                 avoid.addCluster(clusterVO.getId()); | ||||||
| @ -1110,7 +1192,9 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|                     new DataCenterDeployment(plan.getDataCenterId(), clusterVO.getPodId(), clusterVO.getId(), null, plan.getPoolId(), null, plan.getReservationContext()); |                     new DataCenterDeployment(plan.getDataCenterId(), clusterVO.getPodId(), clusterVO.getId(), null, plan.getPoolId(), null, plan.getReservationContext()); | ||||||
| 
 | 
 | ||||||
|             Pod pod = _podDao.findById(clusterVO.getPodId()); |             Pod pod = _podDao.findById(clusterVO.getPodId()); | ||||||
|             if (pod.getAllocationState() == Grouping.AllocationState.Enabled ) { |             if (CollectionUtils.isNotEmpty(avoid.getPodsToAvoid()) && avoid.getPodsToAvoid().contains(pod.getId())) { | ||||||
|  |                 s_logger.debug("The cluster is in a disabled pod : " + pod.getId()); | ||||||
|  |             } else { | ||||||
|                 // find suitable hosts under this cluster, need as many hosts as we |                 // find suitable hosts under this cluster, need as many hosts as we | ||||||
|                 // get. |                 // get. | ||||||
|                 List<Host> suitableHosts = findSuitableHosts(vmProfile, potentialPlan, avoid, HostAllocator.RETURN_UPTO_ALL); |                 List<Host> suitableHosts = findSuitableHosts(vmProfile, potentialPlan, avoid, HostAllocator.RETURN_UPTO_ALL); | ||||||
| @ -1151,9 +1235,6 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|                     s_logger.debug("No suitable hosts found under this Cluster: " + clusterId); |                     s_logger.debug("No suitable hosts found under this Cluster: " + clusterId); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             else { |  | ||||||
|                 s_logger.debug("The cluster is in a disabled pod : " + pod.getId()); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             if (canAvoidCluster(clusterVO, avoid, plannerAvoidOutput, vmProfile)) { |             if (canAvoidCluster(clusterVO, avoid, plannerAvoidOutput, vmProfile)) { | ||||||
|                 avoid.addCluster(clusterVO.getId()); |                 avoid.addCluster(clusterVO.getId()); | ||||||
| @ -1739,4 +1820,14 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> { | |||||||
|       } |       } | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public ConfigKey<?>[] getConfigKeys() { | ||||||
|  |         return new ConfigKey<?>[] {allowRouterOnDisabledResource, allowAdminVmOnDisabledResource}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getConfigComponentName() { | ||||||
|  |         return DeploymentPlanningManager.class.getSimpleName(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -260,15 +260,6 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla | |||||||
|                 } |                 } | ||||||
|                 podsWithCapacity.removeAll(avoid.getPodsToAvoid()); |                 podsWithCapacity.removeAll(avoid.getPodsToAvoid()); | ||||||
|             } |             } | ||||||
|             if (!isRootAdmin(vmProfile)) { |  | ||||||
|                 List<Long> disabledPods = listDisabledPods(plan.getDataCenterId()); |  | ||||||
|                 if (!disabledPods.isEmpty()) { |  | ||||||
|                     if (s_logger.isDebugEnabled()) { |  | ||||||
|                         s_logger.debug("Removing from the podId list these pods that are disabled: " + disabledPods); |  | ||||||
|                     } |  | ||||||
|                     podsWithCapacity.removeAll(disabledPods); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } else { |         } else { | ||||||
|             if (s_logger.isDebugEnabled()) { |             if (s_logger.isDebugEnabled()) { | ||||||
|                 s_logger.debug("No pods found having a host with enough capacity, returning."); |                 s_logger.debug("No pods found having a host with enough capacity, returning."); | ||||||
| @ -402,21 +393,6 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla | |||||||
|                 prioritizedClusterIds.removeAll(avoid.getClustersToAvoid()); |                 prioritizedClusterIds.removeAll(avoid.getClustersToAvoid()); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (!isRootAdmin(vmProfile)) { |  | ||||||
|                 List<Long> disabledClusters = new ArrayList<Long>(); |  | ||||||
|                 if (isZone) { |  | ||||||
|                     disabledClusters = listDisabledClusters(plan.getDataCenterId(), null); |  | ||||||
|                 } else { |  | ||||||
|                     disabledClusters = listDisabledClusters(plan.getDataCenterId(), id); |  | ||||||
|                 } |  | ||||||
|                 if (!disabledClusters.isEmpty()) { |  | ||||||
|                     if (s_logger.isDebugEnabled()) { |  | ||||||
|                         s_logger.debug("Removing from the clusterId list these clusters that are disabled/clusters under disabled pods: " + disabledClusters); |  | ||||||
|                     } |  | ||||||
|                     prioritizedClusterIds.removeAll(disabledClusters); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             removeClustersCrossingThreshold(prioritizedClusterIds, avoid, vmProfile, plan); |             removeClustersCrossingThreshold(prioritizedClusterIds, avoid, vmProfile, plan); | ||||||
|             String hostTagOnOffering = offering.getHostTag(); |             String hostTagOnOffering = offering.getHostTag(); | ||||||
|             if (hostTagOnOffering != null) { |             if (hostTagOnOffering != null) { | ||||||
| @ -465,21 +441,6 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla | |||||||
|         return podIdsByCapacity; |         return podIdsByCapacity; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private List<Long> listDisabledClusters(long zoneId, Long podId) { |  | ||||||
|         List<Long> disabledClusters = clusterDao.listDisabledClusters(zoneId, podId); |  | ||||||
|         if (podId == null) { |  | ||||||
|             //list all disabled clusters under this zone + clusters under any disabled pod of this zone |  | ||||||
|             List<Long> clustersWithDisabledPods = clusterDao.listClustersWithDisabledPods(zoneId); |  | ||||||
|             disabledClusters.addAll(clustersWithDisabledPods); |  | ||||||
|         } |  | ||||||
|         return disabledClusters; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private List<Long> listDisabledPods(long zoneId) { |  | ||||||
|         List<Long> disabledPods = podDao.listDisabledPods(zoneId); |  | ||||||
|         return disabledPods; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     protected Pair<List<Long>, Map<Long, Double>> listClustersByCapacity(long id, int requiredCpu, long requiredRam, ExcludeList avoid, boolean isZone) { |     protected Pair<List<Long>, Map<Long, Double>> listClustersByCapacity(long id, int requiredCpu, long requiredRam, ExcludeList avoid, boolean isZone) { | ||||||
|         //look at the aggregate available cpu and ram per cluster |         //look at the aggregate available cpu and ram per cluster | ||||||
|         //although an aggregate value may be false indicator that a cluster can host a vm, it will at the least eliminate those clusters which definitely cannot |         //although an aggregate value may be false indicator that a cluster can host a vm, it will at the least eliminate those clusters which definitely cannot | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ | |||||||
| // KIND, either express or implied.  See the License for the | // KIND, either express or implied.  See the License for the | ||||||
| // specific language governing permissions and limitations | // specific language governing permissions and limitations | ||||||
| // under the License. | // under the License. | ||||||
| package com.cloud.vm; | package com.cloud.deploy; | ||||||
| 
 | 
 | ||||||
| import static org.junit.Assert.assertFalse; | import static org.junit.Assert.assertFalse; | ||||||
| import static org.junit.Assert.assertNull; | import static org.junit.Assert.assertNull; | ||||||
| @ -28,18 +28,30 @@ import java.util.List; | |||||||
| import javax.inject.Inject; | import javax.inject.Inject; | ||||||
| import javax.naming.ConfigurationException; | import javax.naming.ConfigurationException; | ||||||
| 
 | 
 | ||||||
|  | import com.cloud.dc.DataCenter; | ||||||
| import com.cloud.host.Host; | import com.cloud.host.Host; | ||||||
| import com.cloud.storage.VMTemplateVO; | import com.cloud.storage.VMTemplateVO; | ||||||
| import com.cloud.storage.dao.VMTemplateDao; | import com.cloud.storage.dao.VMTemplateDao; | ||||||
|  | import com.cloud.user.AccountVO; | ||||||
|  | import com.cloud.user.dao.AccountDao; | ||||||
|  | import com.cloud.vm.VMInstanceVO; | ||||||
|  | import com.cloud.vm.VirtualMachine; | ||||||
|  | import com.cloud.vm.VirtualMachine.Type; | ||||||
|  | import com.cloud.vm.VirtualMachineProfile; | ||||||
|  | import com.cloud.vm.VirtualMachineProfileImpl; | ||||||
| import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao; | import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao; | ||||||
|  | import org.apache.commons.collections.CollectionUtils; | ||||||
|  | import org.junit.Assert; | ||||||
| import org.junit.Before; | import org.junit.Before; | ||||||
| import org.junit.BeforeClass; | import org.junit.BeforeClass; | ||||||
| import org.junit.Test; | import org.junit.Test; | ||||||
| import org.junit.runner.RunWith; | import org.junit.runner.RunWith; | ||||||
|  | import org.mockito.InjectMocks; | ||||||
| import org.mockito.Matchers; | import org.mockito.Matchers; | ||||||
| import org.mockito.Mock; | import org.mockito.Mock; | ||||||
| import org.mockito.Mockito; | import org.mockito.Mockito; | ||||||
| import org.mockito.MockitoAnnotations; | import org.mockito.MockitoAnnotations; | ||||||
|  | import org.mockito.Spy; | ||||||
| import org.springframework.context.annotation.Bean; | import org.springframework.context.annotation.Bean; | ||||||
| import org.springframework.context.annotation.ComponentScan; | import org.springframework.context.annotation.ComponentScan; | ||||||
| import org.springframework.context.annotation.ComponentScan.Filter; | import org.springframework.context.annotation.ComponentScan.Filter; | ||||||
| @ -73,15 +85,8 @@ import com.cloud.dc.dao.ClusterDao; | |||||||
| import com.cloud.dc.dao.DataCenterDao; | import com.cloud.dc.dao.DataCenterDao; | ||||||
| import com.cloud.dc.dao.DedicatedResourceDao; | import com.cloud.dc.dao.DedicatedResourceDao; | ||||||
| import com.cloud.dc.dao.HostPodDao; | import com.cloud.dc.dao.HostPodDao; | ||||||
| import com.cloud.deploy.DataCenterDeployment; |  | ||||||
| import com.cloud.deploy.DeployDestination; |  | ||||||
| import com.cloud.deploy.DeploymentClusterPlanner; |  | ||||||
| import com.cloud.deploy.DeploymentPlanner; |  | ||||||
| import com.cloud.deploy.DeploymentPlanner.ExcludeList; | import com.cloud.deploy.DeploymentPlanner.ExcludeList; | ||||||
| import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage; | import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage; | ||||||
| import com.cloud.deploy.DeploymentPlanningManagerImpl; |  | ||||||
| import com.cloud.deploy.FirstFitPlanner; |  | ||||||
| import com.cloud.deploy.PlannerHostReservationVO; |  | ||||||
| import com.cloud.deploy.dao.PlannerHostReservationDao; | import com.cloud.deploy.dao.PlannerHostReservationDao; | ||||||
| import com.cloud.exception.AffinityConflictException; | import com.cloud.exception.AffinityConflictException; | ||||||
| import com.cloud.exception.InsufficientServerCapacityException; | import com.cloud.exception.InsufficientServerCapacityException; | ||||||
| @ -90,6 +95,7 @@ import com.cloud.host.dao.HostDao; | |||||||
| import com.cloud.host.dao.HostTagsDao; | import com.cloud.host.dao.HostTagsDao; | ||||||
| import com.cloud.hypervisor.Hypervisor.HypervisorType; | import com.cloud.hypervisor.Hypervisor.HypervisorType; | ||||||
| import com.cloud.resource.ResourceManager; | import com.cloud.resource.ResourceManager; | ||||||
|  | import com.cloud.org.Grouping.AllocationState; | ||||||
| import com.cloud.service.ServiceOfferingVO; | import com.cloud.service.ServiceOfferingVO; | ||||||
| import com.cloud.service.dao.ServiceOfferingDetailsDao; | import com.cloud.service.dao.ServiceOfferingDetailsDao; | ||||||
| import com.cloud.storage.Storage.ProvisioningType; | import com.cloud.storage.Storage.ProvisioningType; | ||||||
| @ -110,7 +116,8 @@ import com.cloud.host.dao.HostDetailsDao; | |||||||
| @ContextConfiguration(loader = AnnotationConfigContextLoader.class) | @ContextConfiguration(loader = AnnotationConfigContextLoader.class) | ||||||
| public class DeploymentPlanningManagerImplTest { | public class DeploymentPlanningManagerImplTest { | ||||||
| 
 | 
 | ||||||
|     @Inject |     @Spy | ||||||
|  |     @InjectMocks | ||||||
|     DeploymentPlanningManagerImpl _dpm; |     DeploymentPlanningManagerImpl _dpm; | ||||||
| 
 | 
 | ||||||
|     @Inject |     @Inject | ||||||
| @ -119,6 +126,12 @@ public class DeploymentPlanningManagerImplTest { | |||||||
|     @Inject |     @Inject | ||||||
|     VirtualMachineProfileImpl vmProfile; |     VirtualMachineProfileImpl vmProfile; | ||||||
| 
 | 
 | ||||||
|  |     @Inject | ||||||
|  |     private AccountDao accountDao; | ||||||
|  | 
 | ||||||
|  |     @Inject | ||||||
|  |     private VMInstanceDao vmInstanceDao; | ||||||
|  | 
 | ||||||
|     @Inject |     @Inject | ||||||
|     AffinityGroupVMMapDao _affinityGroupVMMapDao; |     AffinityGroupVMMapDao _affinityGroupVMMapDao; | ||||||
| 
 | 
 | ||||||
| @ -146,11 +159,15 @@ public class DeploymentPlanningManagerImplTest { | |||||||
|     @Inject |     @Inject | ||||||
|     VMTemplateDao templateDao; |     VMTemplateDao templateDao; | ||||||
| 
 | 
 | ||||||
|  |     @Inject | ||||||
|  |     HostPodDao hostPodDao; | ||||||
|  | 
 | ||||||
|     @Mock |     @Mock | ||||||
|     Host host; |     Host host; | ||||||
| 
 | 
 | ||||||
|     private static long dataCenterId = 1L; |     private static long dataCenterId = 1L; | ||||||
|     private static long hostId = 1l; |     private static long hostId = 1l; | ||||||
|  |     private static final long ADMIN_ACCOUNT_ROLE_ID = 1l; | ||||||
| 
 | 
 | ||||||
|     @BeforeClass |     @BeforeClass | ||||||
|     public static void setUp() throws ConfigurationException { |     public static void setUp() throws ConfigurationException { | ||||||
| @ -189,6 +206,7 @@ public class DeploymentPlanningManagerImplTest { | |||||||
|         _dpm.setPlanners(planners); |         _dpm.setPlanners(planners); | ||||||
| 
 | 
 | ||||||
|         Mockito.when(host.getId()).thenReturn(hostId); |         Mockito.when(host.getId()).thenReturn(hostId); | ||||||
|  |         Mockito.doNothing().when(_dpm).avoidDisabledResources(vmProfile, dc, avoids); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
| @ -259,6 +277,184 @@ public class DeploymentPlanningManagerImplTest { | |||||||
|         assertFalse(_dpm.checkAffinity(host, Arrays.asList(3l, 4l, 2l))); |         assertFalse(_dpm.checkAffinity(host, Arrays.asList(3l, 4l, 2l))); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Test | ||||||
|  |     public void routerInDisabledResourceAssertFalse() { | ||||||
|  |         Assert.assertFalse(DeploymentPlanningManager.allowRouterOnDisabledResource.value()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void adminVmInDisabledResourceAssertFalse() { | ||||||
|  |         Assert.assertFalse(DeploymentPlanningManager.allowAdminVmOnDisabledResource.value()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void avoidDisabledResourcesTestAdminAccount() { | ||||||
|  |         Type[] vmTypes = VirtualMachine.Type.values(); | ||||||
|  |         for (int i = 0; i < vmTypes.length - 1; ++i) { | ||||||
|  |             Mockito.when(vmProfile.getType()).thenReturn(vmTypes[i]); | ||||||
|  |             if (vmTypes[i].isUsedBySystem()) { | ||||||
|  |                 prepareAndVerifyAvoidDisabledResourcesTest(1, 0, 0, ADMIN_ACCOUNT_ROLE_ID, vmTypes[i], true, false); | ||||||
|  |             } else { | ||||||
|  |                 prepareAndVerifyAvoidDisabledResourcesTest(0, 1, 1, ADMIN_ACCOUNT_ROLE_ID, vmTypes[i], true, false); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void avoidDisabledResourcesTestUserAccounAdminCannotDeployOnDisabled() { | ||||||
|  |         Type[] vmTypes = VirtualMachine.Type.values(); | ||||||
|  |         for (int i = 0; i < vmTypes.length - 1; ++i) { | ||||||
|  |             Mockito.when(vmProfile.getType()).thenReturn(vmTypes[i]); | ||||||
|  |             long userAccountId = ADMIN_ACCOUNT_ROLE_ID + 1; | ||||||
|  |             if (vmTypes[i].isUsedBySystem()) { | ||||||
|  |                 prepareAndVerifyAvoidDisabledResourcesTest(1, 0, 0, userAccountId, vmTypes[i], true, false); | ||||||
|  |             } else { | ||||||
|  |                 prepareAndVerifyAvoidDisabledResourcesTest(0, 0, 1, userAccountId, vmTypes[i], true, false); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void avoidDisabledResourcesTestUserAccounAdminCanDeployOnDisabled() { | ||||||
|  |         Type[] vmTypes = VirtualMachine.Type.values(); | ||||||
|  |         for (int i = 0; i < vmTypes.length - 1; ++i) { | ||||||
|  |             Mockito.when(vmProfile.getType()).thenReturn(vmTypes[i]); | ||||||
|  |             long userAccountId = ADMIN_ACCOUNT_ROLE_ID + 1; | ||||||
|  |             if (vmTypes[i].isUsedBySystem()) { | ||||||
|  |                 prepareAndVerifyAvoidDisabledResourcesTest(1, 0, 0, userAccountId, vmTypes[i], true, true); | ||||||
|  |             } else { | ||||||
|  |                 prepareAndVerifyAvoidDisabledResourcesTest(0, 0, 1, userAccountId, vmTypes[i], true, true); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void prepareAndVerifyAvoidDisabledResourcesTest(int timesRouter, int timesAdminVm, int timesDisabledResource, long roleId, Type vmType, boolean isSystemDepolyable, | ||||||
|  |             boolean isAdminVmDeployable) { | ||||||
|  |         Mockito.doReturn(isSystemDepolyable).when(_dpm).isRouterDeployableInDisabledResources(); | ||||||
|  |         Mockito.doReturn(isAdminVmDeployable).when(_dpm).isAdminVmDeployableInDisabledResources(); | ||||||
|  | 
 | ||||||
|  |         VirtualMachineProfile vmProfile = Mockito.mock(VirtualMachineProfile.class); | ||||||
|  |         DataCenter dc = Mockito.mock(DataCenter.class); | ||||||
|  |         ExcludeList avoids = Mockito.mock(ExcludeList.class); | ||||||
|  | 
 | ||||||
|  |         Mockito.when(vmProfile.getType()).thenReturn(vmType); | ||||||
|  |         Mockito.when(vmProfile.getId()).thenReturn(1l); | ||||||
|  | 
 | ||||||
|  |         Mockito.doNothing().when(_dpm).avoidDisabledDataCenters(dc, avoids); | ||||||
|  |         Mockito.doNothing().when(_dpm).avoidDisabledPods(dc, avoids); | ||||||
|  |         Mockito.doNothing().when(_dpm).avoidDisabledClusters(dc, avoids); | ||||||
|  |         Mockito.doNothing().when(_dpm).avoidDisabledHosts(dc, avoids); | ||||||
|  | 
 | ||||||
|  |         VMInstanceVO vmInstanceVO = Mockito.mock(VMInstanceVO.class); | ||||||
|  |         Mockito.when(vmInstanceDao.findById(Mockito.anyLong())).thenReturn(vmInstanceVO); | ||||||
|  |         AccountVO owner = Mockito.mock(AccountVO.class); | ||||||
|  |         Mockito.when(owner.getRoleId()).thenReturn(roleId); | ||||||
|  |         Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(owner); | ||||||
|  | 
 | ||||||
|  |         _dpm.avoidDisabledResources(vmProfile, dc, avoids); | ||||||
|  | 
 | ||||||
|  |         Mockito.verify(_dpm, Mockito.times(timesRouter)).isRouterDeployableInDisabledResources(); | ||||||
|  |         Mockito.verify(_dpm, Mockito.times(timesAdminVm)).isAdminVmDeployableInDisabledResources(); | ||||||
|  |         Mockito.verify(_dpm, Mockito.times(timesDisabledResource)).avoidDisabledDataCenters(dc, avoids); | ||||||
|  |         Mockito.verify(_dpm, Mockito.times(timesDisabledResource)).avoidDisabledPods(dc, avoids); | ||||||
|  |         Mockito.verify(_dpm, Mockito.times(timesDisabledResource)).avoidDisabledClusters(dc, avoids); | ||||||
|  |         Mockito.verify(_dpm, Mockito.times(timesDisabledResource)).avoidDisabledHosts(dc, avoids); | ||||||
|  |         Mockito.reset(_dpm); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void avoidDisabledDataCentersTest() { | ||||||
|  |         DataCenter dc = Mockito.mock(DataCenter.class); | ||||||
|  |         Mockito.when(dc.getId()).thenReturn(123l); | ||||||
|  | 
 | ||||||
|  |         ExcludeList avoids = new ExcludeList(); | ||||||
|  |         AllocationState[] allocationStates = AllocationState.values(); | ||||||
|  |         for (int i = 0; i < allocationStates.length - 1; ++i) { | ||||||
|  |             Mockito.when(dc.getAllocationState()).thenReturn(allocationStates[i]); | ||||||
|  | 
 | ||||||
|  |             _dpm.avoidDisabledDataCenters(dc, avoids); | ||||||
|  | 
 | ||||||
|  |             if (allocationStates[i] == AllocationState.Disabled) { | ||||||
|  |                 assertAvoidIsEmpty(avoids, false, true, true, true); | ||||||
|  |                 Assert.assertTrue(avoids.getDataCentersToAvoid().size() == 1); | ||||||
|  |                 Assert.assertTrue(avoids.getDataCentersToAvoid().contains(dc.getId())); | ||||||
|  |             } else { | ||||||
|  |                 assertAvoidIsEmpty(avoids, true, true, true, true); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void avoidDisabledPodsTestNoDisabledPod() { | ||||||
|  |         DataCenter dc = Mockito.mock(DataCenter.class); | ||||||
|  |         List<Long> podIds = new ArrayList<>(); | ||||||
|  |         long expectedPodId = 123l; | ||||||
|  |         podIds.add(expectedPodId); | ||||||
|  |         Mockito.doReturn(new ArrayList<>()).when(hostPodDao).listDisabledPods(Mockito.anyLong()); | ||||||
|  |         ExcludeList avoids = new ExcludeList(); | ||||||
|  | 
 | ||||||
|  |         _dpm.avoidDisabledPods(dc, avoids); | ||||||
|  |         assertAvoidIsEmpty(avoids, true, true, true, true); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void avoidDisabledPodsTestHasDisabledPod() { | ||||||
|  |         DataCenter dc = Mockito.mock(DataCenter.class); | ||||||
|  |         List<Long> podIds = new ArrayList<>(); | ||||||
|  |         long expectedPodId = 123l; | ||||||
|  |         podIds.add(expectedPodId); | ||||||
|  |         Mockito.doReturn(podIds).when(hostPodDao).listDisabledPods(Mockito.anyLong()); | ||||||
|  | 
 | ||||||
|  |         ExcludeList avoids = new ExcludeList(); | ||||||
|  | 
 | ||||||
|  |         _dpm.avoidDisabledPods(dc, avoids); | ||||||
|  |         assertAvoidIsEmpty(avoids, true, false, true, true); | ||||||
|  |         Assert.assertTrue(avoids.getPodsToAvoid().size() == 1); | ||||||
|  |         Assert.assertTrue(avoids.getPodsToAvoid().contains(expectedPodId)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void avoidDisabledClustersTestNoDisabledCluster() { | ||||||
|  |         DataCenter dc = prepareAvoidDisabledTests(); | ||||||
|  |         Mockito.doReturn(new ArrayList<>()).when(_clusterDao).listDisabledClusters(Mockito.anyLong(), Mockito.anyLong()); | ||||||
|  |         ExcludeList avoids = new ExcludeList(); | ||||||
|  | 
 | ||||||
|  |         _dpm.avoidDisabledClusters(dc, avoids); | ||||||
|  |         assertAvoidIsEmpty(avoids, true, true, true, true); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void avoidDisabledClustersTestHasDisabledCluster() { | ||||||
|  |         DataCenter dc = prepareAvoidDisabledTests(); | ||||||
|  |         long expectedClusterId = 123l; | ||||||
|  |         List<Long> disabledClusters = new ArrayList<>(); | ||||||
|  |         disabledClusters.add(expectedClusterId); | ||||||
|  |         Mockito.doReturn(disabledClusters).when(_clusterDao).listDisabledClusters(Mockito.anyLong(), Mockito.anyLong()); | ||||||
|  |         ExcludeList avoids = new ExcludeList(); | ||||||
|  | 
 | ||||||
|  |         _dpm.avoidDisabledClusters(dc, avoids); | ||||||
|  | 
 | ||||||
|  |         assertAvoidIsEmpty(avoids, true, true, false, true); | ||||||
|  |         Assert.assertTrue(avoids.getClustersToAvoid().size() == 1); | ||||||
|  |         Assert.assertTrue(avoids.getClustersToAvoid().contains(expectedClusterId)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private DataCenter prepareAvoidDisabledTests() { | ||||||
|  |         DataCenter dc = Mockito.mock(DataCenter.class); | ||||||
|  |         Mockito.when(dc.getId()).thenReturn(123l); | ||||||
|  |         List<Long> podIds = new ArrayList<>(); | ||||||
|  |         podIds.add(1l); | ||||||
|  |         Mockito.doReturn(podIds).when(hostPodDao).listAllPods(Mockito.anyLong()); | ||||||
|  |         return dc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void assertAvoidIsEmpty(ExcludeList avoids, boolean isDcEmpty, boolean isPodsEmpty, boolean isClustersEmpty, boolean isHostsEmpty) { | ||||||
|  |         Assert.assertEquals(isDcEmpty, CollectionUtils.isEmpty(avoids.getDataCentersToAvoid())); | ||||||
|  |         Assert.assertEquals(isPodsEmpty, CollectionUtils.isEmpty(avoids.getPodsToAvoid())); | ||||||
|  |         Assert.assertEquals(isClustersEmpty, CollectionUtils.isEmpty(avoids.getClustersToAvoid())); | ||||||
|  |         Assert.assertEquals(isHostsEmpty, CollectionUtils.isEmpty(avoids.getHostsToAvoid())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Configuration |     @Configuration | ||||||
|     @ComponentScan(basePackageClasses = {DeploymentPlanningManagerImpl.class}, includeFilters = {@Filter(value = TestConfiguration.Library.class, |     @ComponentScan(basePackageClasses = {DeploymentPlanningManagerImpl.class}, includeFilters = {@Filter(value = TestConfiguration.Library.class, | ||||||
|                                                                                                          type = FilterType.CUSTOM)}, useDefaultFilters = false) |                                                                                                          type = FilterType.CUSTOM)}, useDefaultFilters = false) | ||||||
| @ -461,10 +657,15 @@ public class DeploymentPlanningManagerImplTest { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         @Bean |         @Bean | ||||||
|         public HostGpuGroupsDao hostGpuGroupsDap() { |         public HostGpuGroupsDao hostGpuGroupsDao() { | ||||||
|             return Mockito.mock(HostGpuGroupsDao.class); |             return Mockito.mock(HostGpuGroupsDao.class); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         @Bean | ||||||
|  |         public AccountDao accountDao() { | ||||||
|  |             return Mockito.mock(AccountDao.class); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         @Bean |         @Bean | ||||||
|         public VMTemplateDao vmTemplateDao() { |         public VMTemplateDao vmTemplateDao() { | ||||||
|             return Mockito.mock(VMTemplateDao.class); |             return Mockito.mock(VMTemplateDao.class); | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user