Skip to content

Commit d3a560a

Browse files
sureshanapartidhslove
authored andcommitted
Deployment plan fixes for VM with last host, and last host in maintenance (apache#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 e9eee30 commit d3a560a

3 files changed

Lines changed: 46 additions & 42 deletions

File tree

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

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import javax.naming.ConfigurationException;
3838

3939
import com.cloud.gpu.dao.VgpuProfileDao;
40+
import com.cloud.resource.ResourceState;
4041
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
4142
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
4243
import org.apache.cloudstack.affinity.AffinityGroupService;
@@ -383,22 +384,12 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym
383384
planner = getDeploymentPlannerByName(plannerName);
384385
}
385386

386-
Host lastHost = null;
387-
388-
String considerLastHostStr = (String)vmProfile.getParameter(VirtualMachineProfile.Param.ConsiderLastHost);
389-
boolean considerLastHost = vm.getLastHostId() != null && haVmTag == null &&
390-
(considerLastHostStr == null || Boolean.TRUE.toString().equalsIgnoreCase(considerLastHostStr));
391-
if (considerLastHost) {
392-
HostVO host = _hostDao.findById(vm.getLastHostId());
393-
logger.debug("This VM has last host_id specified, trying to choose the same host: " + host);
394-
lastHost = host;
395-
396-
DeployDestination deployDestination = deployInVmLastHost(vmProfile, plan, avoids, planner, vm, dc, offering, cpuRequested, ramRequested, volumesRequireEncryption);
397-
if (deployDestination != null) {
398-
return deployDestination;
399-
}
387+
DeployDestination deployDestinationForVmLasthost = deployInVmLastHost(vmProfile, plan, avoids, planner, vm, dc, offering, cpuRequested, ramRequested, volumesRequireEncryption);
388+
if (deployDestinationForVmLasthost != null) {
389+
return deployDestinationForVmLasthost;
400390
}
401391

392+
HostVO lastHost = _hostDao.findById(vm.getLastHostId());
402393
avoidOtherClustersForDeploymentIfMigrationDisabled(vm, lastHost, avoids);
403394

404395
DeployDestination dest = null;
@@ -480,56 +471,65 @@ private void avoidDifferentArchResources(VirtualMachineProfile vmProfile, DataCe
480471
private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids,
481472
DeploymentPlanner planner, VirtualMachine vm, DataCenter dc, ServiceOffering offering, int cpuRequested, long ramRequested,
482473
boolean volumesRequireEncryption) throws InsufficientServerCapacityException {
483-
HostVO host = _hostDao.findById(vm.getLastHostId());
484-
if (canUseLastHost(host, avoids, plan, vm, offering, volumesRequireEncryption)) {
485-
_hostDao.loadHostTags(host);
486-
_hostDao.loadDetails(host);
487-
if (host.getStatus() != Status.Up) {
474+
String considerLastHostStr = (String)vmProfile.getParameter(VirtualMachineProfile.Param.ConsiderLastHost);
475+
String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
476+
boolean considerLastHost = vm.getLastHostId() != null && haVmTag == null &&
477+
!(Boolean.FALSE.toString().equalsIgnoreCase(considerLastHostStr));
478+
if (!considerLastHost) {
479+
return null;
480+
}
481+
482+
logger.debug("This VM has last host_id: {}", vm.getLastHostId());
483+
HostVO lastHost = _hostDao.findById(vm.getLastHostId());
484+
if (canUseLastHost(lastHost, avoids, plan, vm, offering, volumesRequireEncryption)) {
485+
_hostDao.loadHostTags(lastHost);
486+
_hostDao.loadDetails(lastHost);
487+
if (lastHost.getStatus() != Status.Up) {
488488
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 [{}].",
489-
vm, host, host.getState().name(), host.getResourceState());
489+
vm, lastHost, lastHost.getState().name(), lastHost.getResourceState());
490490
return null;
491491
}
492-
if (checkVmProfileAndHost(vmProfile, host)) {
493-
long cluster_id = host.getClusterId();
492+
if (checkVmProfileAndHost(vmProfile, lastHost)) {
493+
long cluster_id = lastHost.getClusterId();
494494
ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id, "cpuOvercommitRatio");
495495
ClusterDetailsVO cluster_detail_ram = _clusterDetailsDao.findDetail(cluster_id, "memoryOvercommitRatio");
496496
float cpuOvercommitRatio = Float.parseFloat(cluster_detail_cpu.getValue());
497497
float memoryOvercommitRatio = Float.parseFloat(cluster_detail_ram.getValue());
498498

499499
boolean hostHasCpuCapability, hostHasCapacity = false;
500-
hostHasCpuCapability = _capacityMgr.checkIfHostHasCpuCapability(host, offering.getCpu(), offering.getSpeed());
500+
hostHasCpuCapability = _capacityMgr.checkIfHostHasCpuCapability(lastHost, offering.getCpu(), offering.getSpeed());
501501

502502
if (hostHasCpuCapability) {
503503
// first check from reserved capacity
504-
hostHasCapacity = _capacityMgr.checkIfHostHasCapacity(host, cpuRequested, ramRequested, true, cpuOvercommitRatio, memoryOvercommitRatio, true);
504+
hostHasCapacity = _capacityMgr.checkIfHostHasCapacity(lastHost, cpuRequested, ramRequested, true, cpuOvercommitRatio, memoryOvercommitRatio, true);
505505

506506
// if not reserved, check the free capacity
507507
if (!hostHasCapacity)
508-
hostHasCapacity = _capacityMgr.checkIfHostHasCapacity(host, cpuRequested, ramRequested, false, cpuOvercommitRatio, memoryOvercommitRatio, true);
508+
hostHasCapacity = _capacityMgr.checkIfHostHasCapacity(lastHost, cpuRequested, ramRequested, false, cpuOvercommitRatio, memoryOvercommitRatio, true);
509509
}
510510

511511
boolean displayStorage = getDisplayStorageFromVmProfile(vmProfile);
512512
if (!hostHasCapacity || !hostHasCpuCapability) {
513-
logger.debug("Cannot deploy VM [{}] to the last host [{}] because this host does not have enough capacity to deploy this VM.", vm, host);
513+
logger.debug("Cannot deploy VM [{}] to the last host [{}] because this host does not have enough capacity to deploy this VM.", vm, lastHost);
514514
return null;
515515
}
516-
Pod pod = _podDao.findById(host.getPodId());
517-
Cluster cluster = _clusterDao.findById(host.getClusterId());
516+
Pod pod = _podDao.findById(lastHost.getPodId());
517+
Cluster cluster = _clusterDao.findById(lastHost.getClusterId());
518518

519519
logger.debug("Last host [{}] of VM [{}] is UP and has enough capacity. Checking for suitable pools for this host under zone [{}], pod [{}] and cluster [{}].",
520-
host, vm, dc, pod, cluster);
520+
lastHost, vm, dc, pod, cluster);
521521

522-
if (DEPLOYMENT_PLANNING_SKIP_HYPERVISORS.contains(vm.getHypervisorType())) {
523-
DeployDestination dest = new DeployDestination(dc, pod, cluster, host, new HashMap<>(), displayStorage);
522+
if (vm.getHypervisorType() == HypervisorType.BareMetal) {
523+
DeployDestination dest = new DeployDestination(dc, pod, cluster, lastHost, new HashMap<>(), displayStorage);
524524
logger.debug("Returning Deployment Destination: {}.", dest);
525525
return dest;
526526
}
527527

528528
// search for storage under the zone, pod, cluster
529529
// of
530530
// the last host.
531-
DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(),
532-
host.getPodId(), host.getClusterId(), host.getId(), plan.getPoolId(), null);
531+
DataCenterDeployment lastPlan = new DataCenterDeployment(lastHost.getDataCenterId(),
532+
lastHost.getPodId(), lastHost.getClusterId(), lastHost.getId(), plan.getPoolId(), null);
533533
Pair<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(
534534
vmProfile, lastPlan, avoids, HostAllocator.RETURN_UPTO_ALL);
535535
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = result.first();
@@ -538,11 +538,11 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De
538538
// choose the potential pool for this VM for this
539539
// host
540540
if (suitableVolumeStoragePools.isEmpty()) {
541-
logger.debug("Cannot find suitable storage pools in host [{}] to deploy VM [{}]", host, vm);
541+
logger.debug("Cannot find suitable storage pools in host [{}] to deploy VM [{}]", lastHost, vm);
542542
return null;
543543
}
544544
List<Host> suitableHosts = new ArrayList<>();
545-
suitableHosts.add(host);
545+
suitableHosts.add(lastHost);
546546
Pair<Host, Map<Volume, StoragePool>> potentialResources = findPotentialDeploymentResources(
547547
suitableHosts, suitableVolumeStoragePools, avoids,
548548
getPlannerUsage(planner, vmProfile, plan, avoids), readyAndReusedVolumes, plan.getPreferredHosts(), vm);
@@ -555,7 +555,7 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De
555555
for (Volume vol : readyAndReusedVolumes) {
556556
storageVolMap.remove(vol);
557557
}
558-
DeployDestination dest = new DeployDestination(dc, pod, cluster, host, storageVolMap, displayStorage);
558+
DeployDestination dest = new DeployDestination(dc, pod, cluster, lastHost, storageVolMap, displayStorage);
559559
logger.debug("Returning Deployment Destination: {}", dest);
560560
return dest;
561561
}
@@ -567,7 +567,7 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De
567567

568568
private boolean canUseLastHost(HostVO host, ExcludeList avoids, DeploymentPlan plan, VirtualMachine vm, ServiceOffering offering, boolean volumesRequireEncryption) {
569569
if (host == null) {
570-
logger.warn("Could not find last host of VM [{}] with id [{}]. Skipping this and trying other available hosts.", vm, vm.getLastHostId());
570+
logger.warn("Could not find last host of VM [{}] with id [{}]. Skipping it", vm, vm.getLastHostId());
571571
return false;
572572
}
573573

@@ -581,6 +581,12 @@ private boolean canUseLastHost(HostVO host, ExcludeList avoids, DeploymentPlan p
581581
return false;
582582
}
583583

584+
logger.debug("VM's last host is {}, trying to choose the same host if it is not in maintenance, error or degraded state", host);
585+
if (host.isInMaintenanceStates() || Arrays.asList(ResourceState.Error, ResourceState.Degraded).contains(host.getResourceState())) {
586+
logger.debug("Unable to deploy VM {} in the last host, last host {} is in {} state", vm.getName(), host.getName(), host.getResourceState());
587+
return false;
588+
}
589+
584590
if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) {
585591
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.",
586592
vm, host);
@@ -1477,7 +1483,7 @@ private Pair<Boolean, Boolean> findVMStorageRequirements(VirtualMachineProfile v
14771483

14781484
protected Pair<Host, Map<Volume, StoragePool>> findPotentialDeploymentResources(List<Host> suitableHosts, Map<Volume, List<StoragePool>> suitableVolumeStoragePools,
14791485
ExcludeList avoid, PlannerResourceUsage resourceUsageRequired, List<Volume> readyAndReusedVolumes, List<Long> preferredHosts, VirtualMachine vm) {
1480-
logger.debug("Trying to find a potenial host and associated storage pools from the suitable host/pool lists for this VM");
1486+
logger.debug("Trying to find a potential host and associated storage pools from the suitable host/pool lists for this VM");
14811487

14821488
boolean hostCanAccessPool = false;
14831489
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
@@ -837,7 +837,7 @@ public Long migrate(final HaWorkVO work) {
837837
if (checkAndCancelWorkIfNeeded(work)) {
838838
return null;
839839
}
840-
logger.info("Migration attempt: for VM {}from host {}. Starting attempt: {}/{} times.", vm, srcHost, 1 + work.getTimesTried(), _maxRetries);
840+
logger.info("Migration attempt: for {} from {}. Starting attempt: {}/{} times.", vm, srcHost, 1 + work.getTimesTried(), _maxRetries);
841841

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

853851
try {
854852
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
@@ -1565,7 +1565,7 @@ private boolean doMaintain(final long hostId) {
15651565
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.");
15661566
}
15671567
} else {
1568-
logger.info("Maintenance: scheduling migration of VM {} from host {}", vm, host);
1568+
logger.info("Maintenance: scheduling migration of {} from {}", vm, host);
15691569
_haMgr.scheduleMigration(vm, HighAvailabilityManager.ReasonType.HostMaintenance);
15701570
}
15711571
}

0 commit comments

Comments
 (0)