3131import javax .naming .ConfigurationException ;
3232
3333import org .apache .cloudstack .affinity .AffinityGroupDomainMapVO ;
34+ import com .cloud .storage .VMTemplateVO ;
35+ import com .cloud .storage .dao .VMTemplateDao ;
36+ import com .cloud .user .AccountVO ;
37+ import com .cloud .user .dao .AccountDao ;
38+ import com .cloud .utils .StringUtils ;
39+ import com .cloud .exception .StorageUnavailableException ;
40+ import com .cloud .utils .db .Filter ;
41+ import com .cloud .utils .fsm .StateMachine2 ;
42+
43+ import org .apache .cloudstack .framework .config .ConfigKey ;
44+ import org .apache .cloudstack .framework .config .Configurable ;
45+ import org .apache .commons .collections .CollectionUtils ;
46+ import org .apache .commons .collections .MapUtils ;
47+ import org .apache .log4j .Logger ;
3448import org .apache .cloudstack .affinity .AffinityGroupProcessor ;
3549import org .apache .cloudstack .affinity .AffinityGroupService ;
3650import org .apache .cloudstack .affinity .AffinityGroupVMMapVO ;
5064import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
5165import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
5266import org .apache .cloudstack .utils .identity .ManagementServerNode ;
53- import org .apache .commons .collections .CollectionUtils ;
54- import org .apache .commons .collections .MapUtils ;
55- import org .apache .log4j .Logger ;
5667
5768import com .cloud .agent .AgentManager ;
5869import com .cloud .agent .Listener ;
8495import com .cloud .exception .AffinityConflictException ;
8596import com .cloud .exception .ConnectionException ;
8697import com .cloud .exception .InsufficientServerCapacityException ;
87- import com .cloud .exception .StorageUnavailableException ;
8898import com .cloud .gpu .GPU ;
8999import com .cloud .host .DetailVO ;
90100import com .cloud .host .Host ;
97107import com .cloud .org .Cluster ;
98108import com .cloud .org .Grouping ;
99109import com .cloud .resource .ResourceManager ;
100- import com .cloud .resource .ResourceState ;
101110import com .cloud .service .ServiceOfferingDetailsVO ;
102111import com .cloud .service .dao .ServiceOfferingDetailsDao ;
103112import com .cloud .storage .DiskOfferingVO ;
107116import com .cloud .storage .StorageManager ;
108117import com .cloud .storage .StoragePool ;
109118import com .cloud .storage .StoragePoolHostVO ;
110- import com .cloud .storage .VMTemplateVO ;
111119import com .cloud .storage .Volume ;
112120import com .cloud .storage .VolumeVO ;
113121import com .cloud .storage .dao .DiskOfferingDao ;
114122import com .cloud .storage .dao .GuestOSCategoryDao ;
115123import com .cloud .storage .dao .GuestOSDao ;
116124import com .cloud .storage .dao .StoragePoolHostDao ;
117- import com .cloud .storage .dao .VMTemplateDao ;
118125import com .cloud .storage .dao .VolumeDao ;
119126import com .cloud .user .AccountManager ;
120127import com .cloud .utils .DateUtil ;
121128import com .cloud .utils .NumbersUtil ;
122129import com .cloud .utils .Pair ;
123- import com .cloud .utils .StringUtils ;
124130import com .cloud .utils .component .Manager ;
125131import com .cloud .utils .component .ManagerBase ;
126132import com .cloud .utils .db .DB ;
127- import com .cloud .utils .db .Filter ;
128133import com .cloud .utils .db .SearchCriteria ;
129134import com .cloud .utils .db .Transaction ;
130135import com .cloud .utils .db .TransactionCallback ;
131136import com .cloud .utils .db .TransactionStatus ;
132137import com .cloud .utils .exception .CloudRuntimeException ;
133138import com .cloud .utils .fsm .StateListener ;
134- import com .cloud .utils .fsm .StateMachine2 ;
135139import com .cloud .vm .DiskProfile ;
136140import com .cloud .vm .VMInstanceVO ;
137141import com .cloud .vm .VirtualMachine ;
144148import static com .cloud .utils .NumbersUtil .toHumanReadableSize ;
145149
146150public class DeploymentPlanningManagerImpl extends ManagerBase implements DeploymentPlanningManager , Manager , Listener ,
147- StateListener <State , VirtualMachine .Event , VirtualMachine > {
151+ StateListener <State , VirtualMachine .Event , VirtualMachine >, Configurable {
148152
149153 private static final Logger s_logger = Logger .getLogger (DeploymentPlanningManagerImpl .class );
150154 @ Inject
151155 AgentManager _agentMgr ;
152156 @ Inject
157+ private AccountDao accountDao ;
158+ @ Inject
153159 protected UserVmDao _vmDao ;
154160 @ Inject
155161 protected VMInstanceDao _vmInstanceDao ;
@@ -177,6 +183,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
177183 @ Inject
178184 private VMTemplateDao templateDao ;
179185
186+ private static final long ADMIN_ACCOUNT_ROLE_ID = 1l ;
180187 private static final long INITIAL_RESERVATION_RELEASE_CHECKER_DELAY = 30L * 1000L ; // thirty seconds expressed in milliseconds
181188 protected long _nodeId = -1 ;
182189
@@ -283,6 +290,8 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym
283290 s_logger .debug ("Is ROOT volume READY (pool already allocated)?: " + (plan .getPoolId () != null ? "Yes" : "No" ));
284291 }
285292
293+ avoidDisabledResources (vmProfile , dc , avoids );
294+
286295 String haVmTag = (String )vmProfile .getParameter (VirtualMachineProfile .Param .HaTag );
287296 String uefiFlag = (String )vmProfile .getParameter (VirtualMachineProfile .Param .UefiFlag );
288297
@@ -311,17 +320,8 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym
311320 }
312321
313322 Pod pod = _podDao .findById (host .getPodId ());
314- // check if the cluster or the pod is disabled
315- if (pod .getAllocationState () != Grouping .AllocationState .Enabled ) {
316- s_logger .warn ("The Pod containing this host is in disabled state, PodId= " + pod .getId ());
317- return null ;
318- }
319323
320324 Cluster cluster = _clusterDao .findById (host .getClusterId ());
321- if (cluster .getAllocationState () != Grouping .AllocationState .Enabled ) {
322- s_logger .warn ("The Cluster containing this host is in disabled state, PodId= " + cluster .getId ());
323- return null ;
324- }
325325
326326 boolean displayStorage = getDisplayStorageFromVmProfile (vmProfile );
327327 if (vm .getHypervisorType () == HypervisorType .BareMetal ) {
@@ -422,8 +422,15 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym
422422 s_logger .debug ("The last host of this VM does not have required GPU devices available" );
423423 }
424424 } else {
425- if (host .getStatus () == Status .Up && host .getResourceState () == ResourceState .Enabled ) {
426- if (checkVmProfileAndHost (vmProfile , host )) {
425+ if (host .getStatus () == Status .Up ) {
426+ boolean hostTagsMatch = true ;
427+ if (offering .getHostTag () != null ){
428+ _hostDao .loadHostTags (host );
429+ if (!(host .getHostTags () != null && host .getHostTags ().contains (offering .getHostTag ()))) {
430+ hostTagsMatch = false ;
431+ }
432+ }
433+ if (hostTagsMatch ) {
427434 long cluster_id = host .getClusterId ();
428435 ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao .findDetail (cluster_id ,
429436 "cpuOvercommitRatio" );
@@ -573,6 +580,86 @@ private boolean getDisplayStorageFromVmProfile(VirtualMachineProfile vmProfile)
573580 return vmProfile == null || vmProfile .getTemplate () == null || !vmProfile .getTemplate ().isDeployAsIs ();
574581 }
575582
583+ /**
584+ * Adds disabled resources (Data centers, Pods, Clusters, and hosts) to exclude list (avoid) in case of disabled state.
585+ */
586+ public void avoidDisabledResources (VirtualMachineProfile vmProfile , DataCenter dc , ExcludeList avoids ) {
587+ if (vmProfile .getType ().isUsedBySystem () && isRouterDeployableInDisabledResources ()) {
588+ return ;
589+ }
590+
591+ VMInstanceVO vm = _vmInstanceDao .findById (vmProfile .getId ());
592+ AccountVO owner = accountDao .findById (vm .getAccountId ());
593+ boolean isOwnerRoleIdAdmin = false ;
594+
595+ if (owner != null && owner .getRoleId () != null && owner .getRoleId () == ADMIN_ACCOUNT_ROLE_ID ) {
596+ isOwnerRoleIdAdmin = true ;
597+ }
598+
599+ if (isOwnerRoleIdAdmin && isAdminVmDeployableInDisabledResources ()) {
600+ return ;
601+ }
602+
603+ avoidDisabledDataCenters (dc , avoids );
604+ avoidDisabledPods (dc , avoids );
605+ avoidDisabledClusters (dc , avoids );
606+ avoidDisabledHosts (dc , avoids );
607+ }
608+
609+ /**
610+ * Returns the value of the ConfigKey 'allow.router.on.disabled.resources'.
611+ * @note this method allows mocking and testing with the respective ConfigKey parameter.
612+ */
613+ protected boolean isRouterDeployableInDisabledResources () {
614+ return allowRouterOnDisabledResource .value ();
615+ }
616+
617+ /**
618+ * Returns the value of the ConfigKey 'allow.admin.vm.on.disabled.resources'.
619+ * @note this method allows mocking and testing with the respective ConfigKey parameter.
620+ */
621+ protected boolean isAdminVmDeployableInDisabledResources () {
622+ return allowAdminVmOnDisabledResource .value ();
623+ }
624+
625+ /**
626+ * Adds disabled Hosts to the ExcludeList in order to avoid them at the deployment planner.
627+ */
628+ protected void avoidDisabledHosts (DataCenter dc , ExcludeList avoids ) {
629+ List <HostVO > disabledHosts = _hostDao .listDisabledByDataCenterId (dc .getId ());
630+ for (HostVO host : disabledHosts ) {
631+ avoids .addHost (host .getId ());
632+ }
633+ }
634+
635+ /**
636+ * Adds disabled Clusters to the ExcludeList in order to avoid them at the deployment planner.
637+ */
638+ protected void avoidDisabledClusters (DataCenter dc , ExcludeList avoids ) {
639+ List <Long > pods = _podDao .listAllPods (dc .getId ());
640+ for (Long podId : pods ) {
641+ List <Long > disabledClusters = _clusterDao .listDisabledClusters (dc .getId (), podId );
642+ avoids .addClusterList (disabledClusters );
643+ }
644+ }
645+
646+ /**
647+ * Adds disabled Pods to the ExcludeList in order to avoid them at the deployment planner.
648+ */
649+ protected void avoidDisabledPods (DataCenter dc , ExcludeList avoids ) {
650+ List <Long > disabledPods = _podDao .listDisabledPods (dc .getId ());
651+ avoids .addPodList (disabledPods );
652+ }
653+
654+ /**
655+ * Adds disabled Data Centers (Zones) to the ExcludeList in order to avoid them at the deployment planner.
656+ */
657+ protected void avoidDisabledDataCenters (DataCenter dc , ExcludeList avoids ) {
658+ if (dc .getAllocationState () == Grouping .AllocationState .Disabled ) {
659+ avoids .addDataCenter (dc .getId ());
660+ }
661+ }
662+
576663 @ Override
577664 public DeploymentPlanner getDeploymentPlannerByName (String plannerName ) {
578665 if (plannerName != null ) {
@@ -1092,11 +1179,6 @@ private DeployDestination checkClustersforDestination(List<Long> clusterList, Vi
10921179 for (Long clusterId : clusterList ) {
10931180 ClusterVO clusterVO = _clusterDao .findById (clusterId );
10941181
1095- if (clusterVO .getAllocationState () == Grouping .AllocationState .Disabled && !plan .isMigrationPlan ()) {
1096- s_logger .debug ("Cannot deploy in disabled cluster " + clusterId + ", skipping this cluster" );
1097- avoid .addCluster (clusterVO .getId ());
1098- }
1099-
11001182 if (clusterVO .getHypervisorType () != vmProfile .getHypervisorType ()) {
11011183 s_logger .debug ("Cluster: " + clusterId + " has HyperVisorType that does not match the VM, skipping this cluster" );
11021184 avoid .addCluster (clusterVO .getId ());
@@ -1110,7 +1192,9 @@ private DeployDestination checkClustersforDestination(List<Long> clusterList, Vi
11101192 new DataCenterDeployment (plan .getDataCenterId (), clusterVO .getPodId (), clusterVO .getId (), null , plan .getPoolId (), null , plan .getReservationContext ());
11111193
11121194 Pod pod = _podDao .findById (clusterVO .getPodId ());
1113- if (pod .getAllocationState () == Grouping .AllocationState .Enabled ) {
1195+ if (CollectionUtils .isNotEmpty (avoid .getPodsToAvoid ()) && avoid .getPodsToAvoid ().contains (pod .getId ())) {
1196+ s_logger .debug ("The cluster is in a disabled pod : " + pod .getId ());
1197+ } else {
11141198 // find suitable hosts under this cluster, need as many hosts as we
11151199 // get.
11161200 List <Host > suitableHosts = findSuitableHosts (vmProfile , potentialPlan , avoid , HostAllocator .RETURN_UPTO_ALL );
@@ -1151,9 +1235,6 @@ private DeployDestination checkClustersforDestination(List<Long> clusterList, Vi
11511235 s_logger .debug ("No suitable hosts found under this Cluster: " + clusterId );
11521236 }
11531237 }
1154- else {
1155- s_logger .debug ("The cluster is in a disabled pod : " + pod .getId ());
1156- }
11571238
11581239 if (canAvoidCluster (clusterVO , avoid , plannerAvoidOutput , vmProfile )) {
11591240 avoid .addCluster (clusterVO .getId ());
@@ -1739,4 +1820,14 @@ public boolean postStateTransitionEvent(StateMachine2.Transition<State, Event> t
17391820 }
17401821 return true ;
17411822 }
1823+
1824+ @ Override
1825+ public ConfigKey <?>[] getConfigKeys () {
1826+ return new ConfigKey <?>[] {allowRouterOnDisabledResource , allowAdminVmOnDisabledResource };
1827+ }
1828+
1829+ @ Override
1830+ public String getConfigComponentName () {
1831+ return DeploymentPlanningManager .class .getSimpleName ();
1832+ }
17421833}
0 commit comments