Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
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;
Expand Down Expand Up @@ -378,22 +379,12 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym
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;
Expand Down Expand Up @@ -475,56 +466,65 @@ private void avoidDifferentArchResources(VirtualMachineProfile vmProfile, DataCe
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;
}

// 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();
Expand All @@ -533,11 +533,11 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De
// 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);
Expand All @@ -550,7 +550,7 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De
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;
}
Expand All @@ -562,7 +562,7 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De

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

Expand All @@ -576,6 +576,12 @@ private boolean canUseLastHost(HostVO host, ExcludeList avoids, DeploymentPlan p
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);
Expand Down Expand Up @@ -1474,7 +1480,7 @@ private Pair<Boolean, Boolean> findVMStorageRequirements(VirtualMachineProfile v

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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,7 @@ public Long migrate(final HaWorkVO work) {
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));
Expand All @@ -843,8 +843,6 @@ public Long migrate(final HaWorkVO work) {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1417,7 +1417,7 @@ private boolean doMaintain(final long hostId) {
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);
}
}
Expand Down
Loading