This is an automated email from the ASF dual-hosted git repository.

bstoyanov pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.20 by this push:
     new 26b57655ece Deployment plan fixes for VM with last host, and last host 
in maintenance (#12062)
26b57655ece is described below

commit 26b57655ecea10d65689084a9bf7a2285b744697
Author: Suresh Kumar Anaparti <[email protected]>
AuthorDate: Thu Jan 29 13:59:41 2026 +0530

    Deployment plan fixes for VM with last host, and last host in maintenance 
(#12062)
    
    * Deployment plan fixes for VM with last host
    - Consider last host when it is not in maintenance
    - Fail deployment when user requests for last host consideration and last 
host doesn't exists or in maintenance
    
    * changes
    
    * msg update with vm/host name
    
    * address comments
    
    * Exclude last hosts with error or degraded state as well, for vm deploy
    
    * review changes
---
 .../deploy/DeploymentPlanningManagerImpl.java      | 80 ++++++++++++----------
 .../com/cloud/ha/HighAvailabilityManagerImpl.java  |  4 +-
 .../com/cloud/resource/ResourceManagerImpl.java    |  2 +-
 3 files changed, 45 insertions(+), 41 deletions(-)

diff --git 
a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java 
b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
index e7b926eb4e4..6881fbab98c 100644
--- a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
+++ b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
@@ -36,6 +36,7 @@ import java.util.stream.Collectors;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.resource.ResourceState;
 import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
 import org.apache.cloudstack.affinity.AffinityGroupProcessor;
 import org.apache.cloudstack.affinity.AffinityGroupService;
@@ -378,22 +379,12 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
             planner = getDeploymentPlannerByName(plannerName);
         }
 
-        Host lastHost = null;
-
-        String considerLastHostStr = 
(String)vmProfile.getParameter(VirtualMachineProfile.Param.ConsiderLastHost);
-        boolean considerLastHost = vm.getLastHostId() != null && haVmTag == 
null &&
-                (considerLastHostStr == null || 
Boolean.TRUE.toString().equalsIgnoreCase(considerLastHostStr));
-        if (considerLastHost) {
-            HostVO host = _hostDao.findById(vm.getLastHostId());
-            logger.debug("This VM has last host_id specified, trying to choose 
the same host: " + host);
-            lastHost = host;
-
-            DeployDestination deployDestination = 
deployInVmLastHost(vmProfile, plan, avoids, planner, vm, dc, offering, 
cpuRequested, ramRequested, volumesRequireEncryption);
-            if (deployDestination != null) {
-                return deployDestination;
-            }
+        DeployDestination deployDestinationForVmLasthost = 
deployInVmLastHost(vmProfile, plan, avoids, planner, vm, dc, offering, 
cpuRequested, ramRequested, volumesRequireEncryption);
+        if (deployDestinationForVmLasthost != null) {
+            return deployDestinationForVmLasthost;
         }
 
+        HostVO lastHost = _hostDao.findById(vm.getLastHostId());
         avoidOtherClustersForDeploymentIfMigrationDisabled(vm, lastHost, 
avoids);
 
         DeployDestination dest = null;
@@ -475,47 +466,56 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
     private DeployDestination deployInVmLastHost(VirtualMachineProfile 
vmProfile, DeploymentPlan plan, ExcludeList avoids,
             DeploymentPlanner planner, VirtualMachine vm, DataCenter dc, 
ServiceOffering offering, int cpuRequested, long ramRequested,
             boolean volumesRequireEncryption) throws 
InsufficientServerCapacityException {
-        HostVO host = _hostDao.findById(vm.getLastHostId());
-        if (canUseLastHost(host, avoids, plan, vm, offering, 
volumesRequireEncryption)) {
-            _hostDao.loadHostTags(host);
-            _hostDao.loadDetails(host);
-            if (host.getStatus() != Status.Up) {
+        String considerLastHostStr = 
(String)vmProfile.getParameter(VirtualMachineProfile.Param.ConsiderLastHost);
+        String haVmTag = 
(String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
+        boolean considerLastHost = vm.getLastHostId() != null && haVmTag == 
null &&
+                
!(Boolean.FALSE.toString().equalsIgnoreCase(considerLastHostStr));
+        if (!considerLastHost) {
+            return null;
+        }
+
+        logger.debug("This VM has last host_id: {}", vm.getLastHostId());
+        HostVO lastHost = _hostDao.findById(vm.getLastHostId());
+        if (canUseLastHost(lastHost, avoids, plan, vm, offering, 
volumesRequireEncryption)) {
+            _hostDao.loadHostTags(lastHost);
+            _hostDao.loadDetails(lastHost);
+            if (lastHost.getStatus() != Status.Up) {
                 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 [{}].",
-                        vm, host, host.getState().name(), 
host.getResourceState());
+                        vm, lastHost, lastHost.getState().name(), 
lastHost.getResourceState());
                 return null;
             }
-            if (checkVmProfileAndHost(vmProfile, host)) {
-                long cluster_id = host.getClusterId();
+            if (checkVmProfileAndHost(vmProfile, lastHost)) {
+                long cluster_id = lastHost.getClusterId();
                 ClusterDetailsVO cluster_detail_cpu = 
_clusterDetailsDao.findDetail(cluster_id, "cpuOvercommitRatio");
                 ClusterDetailsVO cluster_detail_ram = 
_clusterDetailsDao.findDetail(cluster_id, "memoryOvercommitRatio");
                 float cpuOvercommitRatio = 
Float.parseFloat(cluster_detail_cpu.getValue());
                 float memoryOvercommitRatio = 
Float.parseFloat(cluster_detail_ram.getValue());
 
                 boolean hostHasCpuCapability, hostHasCapacity = false;
-                hostHasCpuCapability = 
_capacityMgr.checkIfHostHasCpuCapability(host, offering.getCpu(), 
offering.getSpeed());
+                hostHasCpuCapability = 
_capacityMgr.checkIfHostHasCpuCapability(lastHost, offering.getCpu(), 
offering.getSpeed());
 
                 if (hostHasCpuCapability) {
                     // first check from reserved capacity
-                    hostHasCapacity = 
_capacityMgr.checkIfHostHasCapacity(host, cpuRequested, ramRequested, true, 
cpuOvercommitRatio, memoryOvercommitRatio, true);
+                    hostHasCapacity = 
_capacityMgr.checkIfHostHasCapacity(lastHost, cpuRequested, ramRequested, true, 
cpuOvercommitRatio, memoryOvercommitRatio, true);
 
                     // if not reserved, check the free capacity
                     if (!hostHasCapacity)
-                        hostHasCapacity = 
_capacityMgr.checkIfHostHasCapacity(host, cpuRequested, ramRequested, false, 
cpuOvercommitRatio, memoryOvercommitRatio, true);
+                        hostHasCapacity = 
_capacityMgr.checkIfHostHasCapacity(lastHost, cpuRequested, ramRequested, 
false, cpuOvercommitRatio, memoryOvercommitRatio, true);
                     }
 
                 boolean displayStorage = 
getDisplayStorageFromVmProfile(vmProfile);
                 if (!hostHasCapacity || !hostHasCpuCapability) {
-                    logger.debug("Cannot deploy VM [{}] to the last host [{}] 
because this host does not have enough capacity to deploy this VM.", vm, host);
+                    logger.debug("Cannot deploy VM [{}] to the last host [{}] 
because this host does not have enough capacity to deploy this VM.", vm, 
lastHost);
                     return null;
                 }
-                Pod pod = _podDao.findById(host.getPodId());
-                Cluster cluster = _clusterDao.findById(host.getClusterId());
+                Pod pod = _podDao.findById(lastHost.getPodId());
+                Cluster cluster = 
_clusterDao.findById(lastHost.getClusterId());
 
                 logger.debug("Last host [{}] of VM [{}] is UP and has enough 
capacity. Checking for suitable pools for this host under zone [{}], pod [{}] 
and cluster [{}].",
-                        host, vm, dc, pod, cluster);
+                        lastHost, vm, dc, pod, cluster);
 
                 if (vm.getHypervisorType() == HypervisorType.BareMetal) {
-                    DeployDestination dest = new DeployDestination(dc, pod, 
cluster, host, new HashMap<>(), displayStorage);
+                    DeployDestination dest = new DeployDestination(dc, pod, 
cluster, lastHost, new HashMap<>(), displayStorage);
                     logger.debug("Returning Deployment Destination: {}.", 
dest);
                     return dest;
                 }
@@ -523,8 +523,8 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
                 // search for storage under the zone, pod, cluster
                 // of
                 // the last host.
-                DataCenterDeployment lastPlan = new 
DataCenterDeployment(host.getDataCenterId(),
-                        host.getPodId(), host.getClusterId(), host.getId(), 
plan.getPoolId(), null);
+                DataCenterDeployment lastPlan = new 
DataCenterDeployment(lastHost.getDataCenterId(),
+                        lastHost.getPodId(), lastHost.getClusterId(), 
lastHost.getId(), plan.getPoolId(), null);
                 Pair<Map<Volume, List<StoragePool>>, List<Volume>> result = 
findSuitablePoolsForVolumes(
                         vmProfile, lastPlan, avoids, 
HostAllocator.RETURN_UPTO_ALL);
                 Map<Volume, List<StoragePool>> suitableVolumeStoragePools = 
result.first();
@@ -533,11 +533,11 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
                 // choose the potential pool for this VM for this
                 // host
                 if (suitableVolumeStoragePools.isEmpty()) {
-                    logger.debug("Cannot find suitable storage pools in host 
[{}] to deploy VM [{}]", host, vm);
+                    logger.debug("Cannot find suitable storage pools in host 
[{}] to deploy VM [{}]", lastHost, vm);
                     return null;
                 }
                 List<Host> suitableHosts = new ArrayList<>();
-                suitableHosts.add(host);
+                suitableHosts.add(lastHost);
                 Pair<Host, Map<Volume, StoragePool>> potentialResources = 
findPotentialDeploymentResources(
                         suitableHosts, suitableVolumeStoragePools, avoids,
                         getPlannerUsage(planner, vmProfile, plan, avoids), 
readyAndReusedVolumes, plan.getPreferredHosts(), vm);
@@ -550,7 +550,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
                     for (Volume vol : readyAndReusedVolumes) {
                         storageVolMap.remove(vol);
                     }
-                    DeployDestination dest = new DeployDestination(dc, pod, 
cluster, host, storageVolMap, displayStorage);
+                    DeployDestination dest = new DeployDestination(dc, pod, 
cluster, lastHost, storageVolMap, displayStorage);
                     logger.debug("Returning Deployment Destination: {}", dest);
                     return dest;
                 }
@@ -562,7 +562,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
 
     private boolean canUseLastHost(HostVO host, ExcludeList avoids, 
DeploymentPlan plan, VirtualMachine vm, ServiceOffering offering, boolean 
volumesRequireEncryption) {
         if (host == null) {
-            logger.warn("Could not find last host of VM [{}] with id [{}]. 
Skipping this and trying other available hosts.", vm, vm.getLastHostId());
+            logger.warn("Could not find last host of VM [{}] with id [{}]. 
Skipping it", vm, vm.getLastHostId());
             return false;
         }
 
@@ -576,6 +576,12 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
             return false;
         }
 
+        logger.debug("VM's last host is {}, trying to choose the same host if 
it is not in maintenance, error or degraded state", host);
+        if (host.isInMaintenanceStates() || Arrays.asList(ResourceState.Error, 
ResourceState.Degraded).contains(host.getResourceState())) {
+            logger.debug("Unable to deploy VM {} in the last host, last host 
{} is in {} state", vm.getName(), host.getName(), host.getResourceState());
+            return false;
+        }
+
         if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) {
             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.",
                     vm, host);
@@ -1474,7 +1480,7 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
 
     protected Pair<Host, Map<Volume, StoragePool>> 
findPotentialDeploymentResources(List<Host> suitableHosts, Map<Volume, 
List<StoragePool>> suitableVolumeStoragePools,
                                                                                
     ExcludeList avoid, PlannerResourceUsage resourceUsageRequired, 
List<Volume> readyAndReusedVolumes, List<Long> preferredHosts, VirtualMachine 
vm) {
-        logger.debug("Trying to find a potenial host and associated storage 
pools from the suitable host/pool lists for this VM");
+        logger.debug("Trying to find a potential host and associated storage 
pools from the suitable host/pool lists for this VM");
 
         boolean hostCanAccessPool = false;
         boolean haveEnoughSpace = false;
diff --git a/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java 
b/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java
index b0f3e6d8d69..e3f67420a2a 100644
--- a/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java
+++ b/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java
@@ -833,7 +833,7 @@ public class HighAvailabilityManagerImpl extends 
ManagerBase implements Configur
         if (checkAndCancelWorkIfNeeded(work)) {
             return null;
         }
-        logger.info("Migration attempt: for VM {}from host {}. Starting 
attempt: {}/{} times.", vm, srcHost, 1 + work.getTimesTried(), _maxRetries);
+        logger.info("Migration attempt: for {} from {}. Starting attempt: 
{}/{} times.", vm, srcHost, 1 + work.getTimesTried(), _maxRetries);
 
         if (VirtualMachine.State.Stopped.equals(vm.getState())) {
             logger.info(String.format("vm %s is Stopped, skipping migrate.", 
vm));
@@ -843,8 +843,6 @@ public class HighAvailabilityManagerImpl extends 
ManagerBase implements Configur
             logger.info(String.format("VM %s is running on a different host 
%s, skipping migration", vm, vm.getHostId()));
             return null;
         }
-        logger.info("Migration attempt: for VM " + vm.getUuid() + "from host 
id " + srcHostId +
-                ". Starting attempt: " + (1 + work.getTimesTried()) + "/" + 
_maxRetries + " times.");
 
         try {
             work.setStep(Step.Migrating);
diff --git a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java 
b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java
index c076ab7c893..12ceac21322 100755
--- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java
@@ -1417,7 +1417,7 @@ public class ResourceManagerImpl extends ManagerBase 
implements ResourceManager,
                         throw new CloudRuntimeException("There are active VMs 
using the host's local storage pool. Please stop all VMs on this host that use 
local storage.");
                     }
                 } else {
-                    logger.info("Maintenance: scheduling migration of VM {} 
from host {}", vm, host);
+                    logger.info("Maintenance: scheduling migration of {} from 
{}", vm, host);
                     _haMgr.scheduleMigration(vm, 
HighAvailabilityManager.ReasonType.HostMaintenance);
                 }
             }

Reply via email to