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);
}
}