Skip to content

Commit 26b5765

Browse files
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
1 parent 664f76c commit 26b5765

File tree

3 files changed

+45
-41
lines changed

3 files changed

+45
-41
lines changed

server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import javax.inject.Inject;
3737
import javax.naming.ConfigurationException;
3838

39+
import com.cloud.resource.ResourceState;
3940
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
4041
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
4142
import 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;

server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ public Long migrate(final HaWorkVO work) {
833833
if (checkAndCancelWorkIfNeeded(work)) {
834834
return null;
835835
}
836-
logger.info("Migration attempt: for VM {}from host {}. Starting attempt: {}/{} times.", vm, srcHost, 1 + work.getTimesTried(), _maxRetries);
836+
logger.info("Migration attempt: for {} from {}. Starting attempt: {}/{} times.", vm, srcHost, 1 + work.getTimesTried(), _maxRetries);
837837

838838
if (VirtualMachine.State.Stopped.equals(vm.getState())) {
839839
logger.info(String.format("vm %s is Stopped, skipping migrate.", vm));
@@ -843,8 +843,6 @@ public Long migrate(final HaWorkVO work) {
843843
logger.info(String.format("VM %s is running on a different host %s, skipping migration", vm, vm.getHostId()));
844844
return null;
845845
}
846-
logger.info("Migration attempt: for VM " + vm.getUuid() + "from host id " + srcHostId +
847-
". Starting attempt: " + (1 + work.getTimesTried()) + "/" + _maxRetries + " times.");
848846

849847
try {
850848
work.setStep(Step.Migrating);

server/src/main/java/com/cloud/resource/ResourceManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ private boolean doMaintain(final long hostId) {
14171417
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.");
14181418
}
14191419
} else {
1420-
logger.info("Maintenance: scheduling migration of VM {} from host {}", vm, host);
1420+
logger.info("Maintenance: scheduling migration of {} from {}", vm, host);
14211421
_haMgr.scheduleMigration(vm, HighAvailabilityManager.ReasonType.HostMaintenance);
14221422
}
14231423
}

0 commit comments

Comments
 (0)