3636import javax .inject .Inject ;
3737import javax .naming .ConfigurationException ;
3838
39+ import com .cloud .resource .ResourceState ;
3940import org .apache .cloudstack .affinity .AffinityGroupDomainMapVO ;
4041import org .apache .cloudstack .affinity .AffinityGroupProcessor ;
4142import org .apache .cloudstack .affinity .AffinityGroupService ;
@@ -378,22 +379,12 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym
378379 planner = getDeploymentPlannerByName (plannerName );
379380 }
380381
381- Host lastHost = null ;
382-
383- String considerLastHostStr = (String )vmProfile .getParameter (VirtualMachineProfile .Param .ConsiderLastHost );
384- boolean considerLastHost = vm .getLastHostId () != null && haVmTag == null &&
385- (considerLastHostStr == null || Boolean .TRUE .toString ().equalsIgnoreCase (considerLastHostStr ));
386- if (considerLastHost ) {
387- HostVO host = _hostDao .findById (vm .getLastHostId ());
388- logger .debug ("This VM has last host_id specified, trying to choose the same host: " + host );
389- lastHost = host ;
390-
391- DeployDestination deployDestination = deployInVmLastHost (vmProfile , plan , avoids , planner , vm , dc , offering , cpuRequested , ramRequested , volumesRequireEncryption );
392- if (deployDestination != null ) {
393- return deployDestination ;
394- }
382+ DeployDestination deployDestinationForVmLasthost = deployInVmLastHost (vmProfile , plan , avoids , planner , vm , dc , offering , cpuRequested , ramRequested , volumesRequireEncryption );
383+ if (deployDestinationForVmLasthost != null ) {
384+ return deployDestinationForVmLasthost ;
395385 }
396386
387+ HostVO lastHost = _hostDao .findById (vm .getLastHostId ());
397388 avoidOtherClustersForDeploymentIfMigrationDisabled (vm , lastHost , avoids );
398389
399390 DeployDestination dest = null ;
@@ -475,56 +466,65 @@ private void avoidDifferentArchResources(VirtualMachineProfile vmProfile, DataCe
475466 private DeployDestination deployInVmLastHost (VirtualMachineProfile vmProfile , DeploymentPlan plan , ExcludeList avoids ,
476467 DeploymentPlanner planner , VirtualMachine vm , DataCenter dc , ServiceOffering offering , int cpuRequested , long ramRequested ,
477468 boolean volumesRequireEncryption ) throws InsufficientServerCapacityException {
478- HostVO host = _hostDao .findById (vm .getLastHostId ());
479- if (canUseLastHost (host , avoids , plan , vm , offering , volumesRequireEncryption )) {
480- _hostDao .loadHostTags (host );
481- _hostDao .loadDetails (host );
482- if (host .getStatus () != Status .Up ) {
469+ String considerLastHostStr = (String )vmProfile .getParameter (VirtualMachineProfile .Param .ConsiderLastHost );
470+ String haVmTag = (String )vmProfile .getParameter (VirtualMachineProfile .Param .HaTag );
471+ boolean considerLastHost = vm .getLastHostId () != null && haVmTag == null &&
472+ !(Boolean .FALSE .toString ().equalsIgnoreCase (considerLastHostStr ));
473+ if (!considerLastHost ) {
474+ return null ;
475+ }
476+
477+ logger .debug ("This VM has last host_id: {}" , vm .getLastHostId ());
478+ HostVO lastHost = _hostDao .findById (vm .getLastHostId ());
479+ if (canUseLastHost (lastHost , avoids , plan , vm , offering , volumesRequireEncryption )) {
480+ _hostDao .loadHostTags (lastHost );
481+ _hostDao .loadDetails (lastHost );
482+ if (lastHost .getStatus () != Status .Up ) {
483483 logger .debug ("Cannot deploy VM [{}] to the last host [{}] because this host is not in UP state or is not enabled. Host current status [{}] and resource status [{}]." ,
484- vm , host , host .getState ().name (), host .getResourceState ());
484+ vm , lastHost , lastHost .getState ().name (), lastHost .getResourceState ());
485485 return null ;
486486 }
487- if (checkVmProfileAndHost (vmProfile , host )) {
488- long cluster_id = host .getClusterId ();
487+ if (checkVmProfileAndHost (vmProfile , lastHost )) {
488+ long cluster_id = lastHost .getClusterId ();
489489 ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao .findDetail (cluster_id , "cpuOvercommitRatio" );
490490 ClusterDetailsVO cluster_detail_ram = _clusterDetailsDao .findDetail (cluster_id , "memoryOvercommitRatio" );
491491 float cpuOvercommitRatio = Float .parseFloat (cluster_detail_cpu .getValue ());
492492 float memoryOvercommitRatio = Float .parseFloat (cluster_detail_ram .getValue ());
493493
494494 boolean hostHasCpuCapability , hostHasCapacity = false ;
495- hostHasCpuCapability = _capacityMgr .checkIfHostHasCpuCapability (host , offering .getCpu (), offering .getSpeed ());
495+ hostHasCpuCapability = _capacityMgr .checkIfHostHasCpuCapability (lastHost , offering .getCpu (), offering .getSpeed ());
496496
497497 if (hostHasCpuCapability ) {
498498 // first check from reserved capacity
499- hostHasCapacity = _capacityMgr .checkIfHostHasCapacity (host , cpuRequested , ramRequested , true , cpuOvercommitRatio , memoryOvercommitRatio , true );
499+ hostHasCapacity = _capacityMgr .checkIfHostHasCapacity (lastHost , cpuRequested , ramRequested , true , cpuOvercommitRatio , memoryOvercommitRatio , true );
500500
501501 // if not reserved, check the free capacity
502502 if (!hostHasCapacity )
503- hostHasCapacity = _capacityMgr .checkIfHostHasCapacity (host , cpuRequested , ramRequested , false , cpuOvercommitRatio , memoryOvercommitRatio , true );
503+ hostHasCapacity = _capacityMgr .checkIfHostHasCapacity (lastHost , cpuRequested , ramRequested , false , cpuOvercommitRatio , memoryOvercommitRatio , true );
504504 }
505505
506506 boolean displayStorage = getDisplayStorageFromVmProfile (vmProfile );
507507 if (!hostHasCapacity || !hostHasCpuCapability ) {
508- logger .debug ("Cannot deploy VM [{}] to the last host [{}] because this host does not have enough capacity to deploy this VM." , vm , host );
508+ logger .debug ("Cannot deploy VM [{}] to the last host [{}] because this host does not have enough capacity to deploy this VM." , vm , lastHost );
509509 return null ;
510510 }
511- Pod pod = _podDao .findById (host .getPodId ());
512- Cluster cluster = _clusterDao .findById (host .getClusterId ());
511+ Pod pod = _podDao .findById (lastHost .getPodId ());
512+ Cluster cluster = _clusterDao .findById (lastHost .getClusterId ());
513513
514514 logger .debug ("Last host [{}] of VM [{}] is UP and has enough capacity. Checking for suitable pools for this host under zone [{}], pod [{}] and cluster [{}]." ,
515- host , vm , dc , pod , cluster );
515+ lastHost , vm , dc , pod , cluster );
516516
517517 if (vm .getHypervisorType () == HypervisorType .BareMetal ) {
518- DeployDestination dest = new DeployDestination (dc , pod , cluster , host , new HashMap <>(), displayStorage );
518+ DeployDestination dest = new DeployDestination (dc , pod , cluster , lastHost , new HashMap <>(), displayStorage );
519519 logger .debug ("Returning Deployment Destination: {}." , dest );
520520 return dest ;
521521 }
522522
523523 // search for storage under the zone, pod, cluster
524524 // of
525525 // the last host.
526- DataCenterDeployment lastPlan = new DataCenterDeployment (host .getDataCenterId (),
527- host .getPodId (), host .getClusterId (), host .getId (), plan .getPoolId (), null );
526+ DataCenterDeployment lastPlan = new DataCenterDeployment (lastHost .getDataCenterId (),
527+ lastHost .getPodId (), lastHost .getClusterId (), lastHost .getId (), plan .getPoolId (), null );
528528 Pair <Map <Volume , List <StoragePool >>, List <Volume >> result = findSuitablePoolsForVolumes (
529529 vmProfile , lastPlan , avoids , HostAllocator .RETURN_UPTO_ALL );
530530 Map <Volume , List <StoragePool >> suitableVolumeStoragePools = result .first ();
@@ -533,11 +533,11 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De
533533 // choose the potential pool for this VM for this
534534 // host
535535 if (suitableVolumeStoragePools .isEmpty ()) {
536- logger .debug ("Cannot find suitable storage pools in host [{}] to deploy VM [{}]" , host , vm );
536+ logger .debug ("Cannot find suitable storage pools in host [{}] to deploy VM [{}]" , lastHost , vm );
537537 return null ;
538538 }
539539 List <Host > suitableHosts = new ArrayList <>();
540- suitableHosts .add (host );
540+ suitableHosts .add (lastHost );
541541 Pair <Host , Map <Volume , StoragePool >> potentialResources = findPotentialDeploymentResources (
542542 suitableHosts , suitableVolumeStoragePools , avoids ,
543543 getPlannerUsage (planner , vmProfile , plan , avoids ), readyAndReusedVolumes , plan .getPreferredHosts (), vm );
@@ -550,7 +550,7 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De
550550 for (Volume vol : readyAndReusedVolumes ) {
551551 storageVolMap .remove (vol );
552552 }
553- DeployDestination dest = new DeployDestination (dc , pod , cluster , host , storageVolMap , displayStorage );
553+ DeployDestination dest = new DeployDestination (dc , pod , cluster , lastHost , storageVolMap , displayStorage );
554554 logger .debug ("Returning Deployment Destination: {}" , dest );
555555 return dest ;
556556 }
@@ -562,7 +562,7 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De
562562
563563 private boolean canUseLastHost (HostVO host , ExcludeList avoids , DeploymentPlan plan , VirtualMachine vm , ServiceOffering offering , boolean volumesRequireEncryption ) {
564564 if (host == null ) {
565- logger .warn ("Could not find last host of VM [{}] with id [{}]. Skipping this and trying other available hosts. " , vm , vm .getLastHostId ());
565+ logger .warn ("Could not find last host of VM [{}] with id [{}]. Skipping it " , vm , vm .getLastHostId ());
566566 return false ;
567567 }
568568
@@ -576,6 +576,12 @@ private boolean canUseLastHost(HostVO host, ExcludeList avoids, DeploymentPlan p
576576 return false ;
577577 }
578578
579+ logger .debug ("VM's last host is {}, trying to choose the same host if it is not in maintenance, error or degraded state" , host );
580+ if (host .isInMaintenanceStates () || Arrays .asList (ResourceState .Error , ResourceState .Degraded ).contains (host .getResourceState ())) {
581+ logger .debug ("Unable to deploy VM {} in the last host, last host {} is in {} state" , vm .getName (), host .getName (), host .getResourceState ());
582+ return false ;
583+ }
584+
579585 if (_capacityMgr .checkIfHostReachMaxGuestLimit (host )) {
580586 logger .debug ("Cannot deploy VM [{}] in the last host [{}] because this host already has the max number of running VMs (users and system VMs). Skipping this and trying other available hosts." ,
581587 vm , host );
@@ -1474,7 +1480,7 @@ private Pair<Boolean, Boolean> findVMStorageRequirements(VirtualMachineProfile v
14741480
14751481 protected Pair <Host , Map <Volume , StoragePool >> findPotentialDeploymentResources (List <Host > suitableHosts , Map <Volume , List <StoragePool >> suitableVolumeStoragePools ,
14761482 ExcludeList avoid , PlannerResourceUsage resourceUsageRequired , List <Volume > readyAndReusedVolumes , List <Long > preferredHosts , VirtualMachine vm ) {
1477- logger .debug ("Trying to find a potenial host and associated storage pools from the suitable host/pool lists for this VM" );
1483+ logger .debug ("Trying to find a potential host and associated storage pools from the suitable host/pool lists for this VM" );
14781484
14791485 boolean hostCanAccessPool = false ;
14801486 boolean haveEnoughSpace = false ;
0 commit comments