GaOrtiga commented on code in PR #7214:
URL: https://github.com/apache/cloudstack/pull/7214#discussion_r1409224353
##########
server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java:
##########
@@ -205,6 +206,8 @@ public List<Host> allocateTo(VirtualMachineProfile
vmProfile, DeploymentPlan pla
// add all hosts that we are not considering to the avoid list
List<HostVO> allhostsInCluster =
_hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, null);
allhostsInCluster.removeAll(clusterHosts);
+ s_logger.debug(String.format("Adding hosts [%s] to the avoid set
because these hosts does not support HA.",
Review Comment:
```suggestion
s_logger.debug(String.format("Adding hosts [%s] to the avoid set
because these hosts do not support HA.",
```
##########
server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java:
##########
@@ -808,109 +850,101 @@ public void
checkForNonDedicatedResources(VirtualMachineProfile vmProfile, DataC
//Only when the type is instance VM and not explicitly dedicated.
if (vm.getType() == VirtualMachine.Type.User && !isExplicit) {
- //add explicitly dedicated resources in avoidList
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Adding pods to avoid lists for non-explicit VM
deployment: " + allPodsInDc);
- }
- avoids.addPodList(allPodsInDc);
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Adding clusters to avoid lists for
non-explicit VM deployment: " + allClustersInDc);
- }
- avoids.addClusterList(allClustersInDc);
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Adding hosts to avoid lists for non-explicit
VM deployment: " + allHostsInDc);
- }
- avoids.addHostList(allHostsInDc);
+ findAvoidSetForNonExplicitUserVM(avoids, isExplicit, vm,
allPodsInDc, allClustersInDc, allHostsInDc);
}
//Handle the Virtual Router Case
//No need to check the isExplicit. As both the cases are handled.
if (vm.getType() == VirtualMachine.Type.DomainRouter) {
- long vmAccountId = vm.getAccountId();
- long vmDomainId = vm.getDomainId();
-
- //Lists all explicitly dedicated resources from vm account ID or
domain ID.
- List<Long> allPodsFromDedicatedID = new ArrayList<Long>();
- List<Long> allClustersFromDedicatedID = new ArrayList<Long>();
- List<Long> allHostsFromDedicatedID = new ArrayList<Long>();
+ findAvoiSetForRouterVM(avoids, vm, allPodsInDc, allClustersInDc,
allHostsInDc);
+ }
+ }
- //Whether the dedicated resources belong to Domain or not. If not,
it may belongs to Account or no dedication.
- List<AffinityGroupDomainMapVO> domainGroupMappings =
_affinityGroupDomainMapDao.listByDomain(vmDomainId);
+ private void findAvoiSetForRouterVM(ExcludeList avoids, VirtualMachine vm,
List<Long> allPodsInDc, List<Long> allClustersInDc, List<Long> allHostsInDc) {
+ long vmAccountId = vm.getAccountId();
+ long vmDomainId = vm.getDomainId();
- //For temporary storage and indexing.
- List<DedicatedResourceVO> tempStorage;
+ List<Long> allPodsFromDedicatedID = new ArrayList<Long>();
+ List<Long> allClustersFromDedicatedID = new ArrayList<Long>();
+ List<Long> allHostsFromDedicatedID = new ArrayList<Long>();
- if (domainGroupMappings == null || domainGroupMappings.isEmpty()) {
- //The dedicated resource belongs to VM Account ID.
+ List<AffinityGroupDomainMapVO> domainGroupMappings =
_affinityGroupDomainMapDao.listByDomain(vmDomainId);
- tempStorage = _dedicatedDao.searchDedicatedPods(null,
vmDomainId, vmAccountId, null, new Filter(DedicatedResourceVO.class, "id",
true, 0L, 1L)).first();
+ List<DedicatedResourceVO> tempStorage;
- for(DedicatedResourceVO vo : tempStorage) {
- allPodsFromDedicatedID.add(vo.getPodId());
- }
+ if (domainGroupMappings == null || domainGroupMappings.isEmpty()) {
+ tempStorage = _dedicatedDao.searchDedicatedPods(null, vmDomainId,
vmAccountId, null,
+ new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
- tempStorage.clear();
- tempStorage = _dedicatedDao.searchDedicatedClusters(null,
vmDomainId, vmAccountId, null, new Filter(DedicatedResourceVO.class, "id",
true, 0L, 1L)).first();
+ for (DedicatedResourceVO vo : tempStorage) {
+ allPodsFromDedicatedID.add(vo.getPodId());
+ }
- for(DedicatedResourceVO vo : tempStorage) {
- allClustersFromDedicatedID.add(vo.getClusterId());
- }
+ tempStorage.clear();
+ tempStorage = _dedicatedDao.searchDedicatedClusters(null,
vmDomainId, vmAccountId, null,
+ new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
- tempStorage.clear();
- tempStorage = _dedicatedDao.searchDedicatedHosts(null,
vmDomainId, vmAccountId, null, new Filter(DedicatedResourceVO.class, "id",
true, 0L, 1L)).first();
+ for (DedicatedResourceVO vo : tempStorage) {
+ allClustersFromDedicatedID.add(vo.getClusterId());
+ }
- for(DedicatedResourceVO vo : tempStorage) {
- allHostsFromDedicatedID.add(vo.getHostId());
- }
+ tempStorage.clear();
+ tempStorage = _dedicatedDao.searchDedicatedHosts(null, vmDomainId,
vmAccountId, null,
+ new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
- //Remove the dedicated ones from main list
- allPodsInDc.removeAll(allPodsFromDedicatedID);
- allClustersInDc.removeAll(allClustersFromDedicatedID);
- allHostsInDc.removeAll(allHostsFromDedicatedID);
+ for (DedicatedResourceVO vo : tempStorage) {
+ allHostsFromDedicatedID.add(vo.getHostId());
}
- else {
- //The dedicated resource belongs to VM Domain ID or No
dedication.
-
- tempStorage = _dedicatedDao.searchDedicatedPods(null,
vmDomainId, null, null, new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
- for(DedicatedResourceVO vo : tempStorage) {
- allPodsFromDedicatedID.add(vo.getPodId());
- }
+ allPodsInDc.removeAll(allPodsFromDedicatedID);
+ allClustersInDc.removeAll(allClustersFromDedicatedID);
+ allHostsInDc.removeAll(allHostsFromDedicatedID);
+ } else {
+ tempStorage = _dedicatedDao.searchDedicatedPods(null, vmDomainId,
null, null,
+ new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
- tempStorage.clear();
- tempStorage = _dedicatedDao.searchDedicatedClusters(null,
vmDomainId, null, null, new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
+ for (DedicatedResourceVO vo : tempStorage) {
+ allPodsFromDedicatedID.add(vo.getPodId());
+ }
- for(DedicatedResourceVO vo : tempStorage) {
- allClustersFromDedicatedID.add(vo.getClusterId());
- }
+ tempStorage.clear();
+ tempStorage = _dedicatedDao.searchDedicatedClusters(null,
vmDomainId, null, null,
+ new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
- tempStorage.clear();
- tempStorage = _dedicatedDao.searchDedicatedHosts(null,
vmDomainId, null, null, new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
+ for (DedicatedResourceVO vo : tempStorage) {
+ allClustersFromDedicatedID.add(vo.getClusterId());
+ }
- for(DedicatedResourceVO vo : tempStorage) {
- allHostsFromDedicatedID.add(vo.getHostId());
- }
+ tempStorage.clear();
+ tempStorage = _dedicatedDao.searchDedicatedHosts(null, vmDomainId,
null, null,
+ new Filter(DedicatedResourceVO.class, "id", true, 0L,
1L)).first();
- //Remove the dedicated ones from main list
- allPodsInDc.removeAll(allPodsFromDedicatedID);
- allClustersInDc.removeAll(allClustersFromDedicatedID);
- allHostsInDc.removeAll(allHostsFromDedicatedID);
+ for (DedicatedResourceVO vo : tempStorage) {
+ allHostsFromDedicatedID.add(vo.getHostId());
}
- //Add in avoid list or no addition if no dedication
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Adding pods to avoid lists: " + allPodsInDc);
- }
- avoids.addPodList(allPodsInDc);
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Adding clusters to avoid lists: " +
allClustersInDc);
- }
- avoids.addClusterList(allClustersInDc);
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Adding hosts to avoid lists: " + allHostsInDc);
- }
- avoids.addHostList(allHostsInDc);
+ allPodsInDc.removeAll(allPodsFromDedicatedID);
+ allClustersInDc.removeAll(allClustersFromDedicatedID);
+ allHostsInDc.removeAll(allHostsFromDedicatedID);
}
+
+ s_logger.debug(LogUtils.logGsonWithoutException(
+ "Adding pods [%s], clusters [%s] and hosts [%s] to the avoid
list in the deploy process of VR VM [%s], "
+ + "because this VM is not dedicated to this
components.",
+ allPodsInDc, allClustersInDc, allHostsInDc, vm.getUuid()));
+ avoids.addPodList(allPodsInDc);
+ avoids.addClusterList(allClustersInDc);
+ avoids.addHostList(allHostsInDc);
+ }
+
+ private void findAvoidSetForNonExplicitUserVM(ExcludeList avoids, boolean
isExplicit, VirtualMachine vm, List<Long> allPodsInDc, List<Long>
allClustersInDc, List<Long> allHostsInDc) {
+ s_logger.debug(LogUtils.logGsonWithoutException(
+ "Adding pods [%s], clusters [%s] and hosts [%s] to the avoid
list in the deploy process of user VM [%s], "
+ + "because this VM is not explicit dedicated to this
components.",
Review Comment:
```suggestion
+ "because this VM is not explicitly dedicated to
this components.",
```
##########
server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java:
##########
@@ -614,6 +455,200 @@ public DeployDestination
planDeployment(VirtualMachineProfile vmProfile, Deploym
return dest;
}
+ 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());
+ _hostDao.loadHostTags(host);
+ _hostDao.loadDetails(host);
+
+ if (canUseLastHost(host, avoids, plan, vm, offering,
volumesRequireEncryption)) {
+ if (host.getStatus() != Status.Up) {
+ s_logger.debug(String.format("Cannot deploy VM [%s] to the
last host [%s] because this host is not in UP state or is not enabled. Host
current status [%s] and resource status [%s].",
+ vm.getUuid(), host.getUuid(), host.getState().name(),
host.getResourceState()));
+ return null;
+ }
+ if (checkVmProfileAndHost(vmProfile, host)) {
+ long cluster_id = host.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.getId(), offering.getCpu(),
offering.getSpeed());
+
+ if (hostHasCpuCapability) {
+ // first check from reserved capacity
+ hostHasCapacity =
_capacityMgr.checkIfHostHasCapacity(host.getId(), cpuRequested, ramRequested,
true, cpuOvercommitRatio, memoryOvercommitRatio, true);
+
+ // if not reserved, check the free capacity
+ if (!hostHasCapacity)
+ hostHasCapacity =
_capacityMgr.checkIfHostHasCapacity(host.getId(), cpuRequested, ramRequested,
false, cpuOvercommitRatio, memoryOvercommitRatio, true);
+ }
+
+ boolean displayStorage =
getDisplayStorageFromVmProfile(vmProfile);
+ if (!hostHasCapacity || !hostHasCpuCapability) {
+ s_logger.debug(String.format("Cannot deploy VM [%s] to the
last host [%s] because this host does not have enough capacity to deploy this
VM.", vm.getUuid(), host.getUuid()));
+ return null;
+ }
+ s_logger.debug(String.format("Last host [%s] of VM [%s] is UP
and has enough capacity. Checking for suitable pools for this host under zone
[%s], pod [%s] and cluster [%s].",
+ host.getUuid(), vm.getUuid(), host.getDataCenterId(),
host.getPodId(), host.getClusterId()));
+
+ Pod pod = _podDao.findById(host.getPodId());
+ Cluster cluster = _clusterDao.findById(host.getClusterId());
+ if (vm.getHypervisorType() == HypervisorType.BareMetal) {
+ DeployDestination dest = new DeployDestination(dc, pod,
cluster, host, new HashMap<Volume, StoragePool>(), displayStorage);
+ s_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);
+ Pair<Map<Volume, List<StoragePool>>, List<Volume>> result =
findSuitablePoolsForVolumes(
+ vmProfile, lastPlan, avoids,
HostAllocator.RETURN_UPTO_ALL);
+ Map<Volume, List<StoragePool>> suitableVolumeStoragePools =
result.first();
+ List<Volume> readyAndReusedVolumes = result.second();
+
+ // choose the potential pool for this VM for this
+ // host
+ if (suitableVolumeStoragePools.isEmpty()) {
+ s_logger.debug(String.format("Cannot find suitable storage
pools in host [%s] to deploy VM [%s]", host.getUuid(), vm.getUuid()));
+ return null;
+ }
+ List<Host> suitableHosts = new ArrayList<Host>();
+ suitableHosts.add(host);
+ Pair<Host, Map<Volume, StoragePool>> potentialResources =
findPotentialDeploymentResources(
+ suitableHosts, suitableVolumeStoragePools, avoids,
+ getPlannerUsage(planner, vmProfile, plan, avoids),
readyAndReusedVolumes, plan.getPreferredHosts(), vm);
+ if (potentialResources != null) {
+ Map<Volume, StoragePool> storageVolMap =
potentialResources.second();
+ // remove the reused vol<->pool from
+ // destination, since we don't have to
+ // prepare
+ // this volume.
+ for (Volume vol : readyAndReusedVolumes) {
+ storageVolMap.remove(vol);
+ }
+ DeployDestination dest = new DeployDestination(dc, pod,
cluster, host, storageVolMap, displayStorage);
+ s_logger.debug("Returning Deployment Destination: " +
dest);
+ return dest;
+ }
+ }
+ }
+ s_logger.debug(String.format("Cannot choose the last host to deploy
this VM %s", vm));
+ return null;
+ }
+
+ private boolean canUseLastHost(HostVO host, ExcludeList avoids,
DeploymentPlan plan, VirtualMachine vm, ServiceOffering offering, boolean
volumesRequireEncryption) {
+ if (host == null) {
+ s_logger.warn(String.format("Could not find last host of VM [%s]
with id [%s]. Skipping this and trying other available hosts.", vm.getUuid(),
vm.getLastHostId()));
+ return false;
+ }
+
+ if (avoids.shouldAvoid(host)) {
+ s_logger.warn(String.format("The last host [%s] of VM [%s] is in
the avoid set. Skipping this and trying other available hosts.",
host.getUuid(), vm.getUuid()));
+ return false;
+ }
+
+ if (plan.getClusterId() != null && host.getClusterId() != null &&
!plan.getClusterId().equals(host.getClusterId())) {
+ s_logger.debug(String.format("The last host [%s] of VM [%s] cannot
be picked, as the plan [%s] specifies a different cluster [%s] to deploy this
VM. Skipping this and trying other available hosts.",
+
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(host, "uuid",
"clusterId"), vm.getUuid(), plan.getClass().getSimpleName(),
plan.getClusterId()));
+ return false;
+ }
+
+ if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) {
+ s_logger.debug(String.format("Cannot deploy VM [%s] in the last
host [%s] because this host already has the max number of running VMs (users
and system VMs). Skipping this and trying other available hosts.",
+ vm.getUuid(), host.getUuid()));
+ return false;
+ }
+
+ ServiceOfferingDetailsVO offeringDetails =
_serviceOfferingDetailsDao.findDetail(offering.getId(),
GPU.Keys.vgpuType.toString());
+ ServiceOfferingDetailsVO groupName =
_serviceOfferingDetailsDao.findDetail(offering.getId(),
GPU.Keys.pciDevice.toString());
+ if (offeringDetails != null &&
!_resourceMgr.isGPUDeviceAvailable(host.getId(), groupName.getValue(),
offeringDetails.getValue())) {
+ s_logger.debug(String.format("Cannot deploy VM [%s] in the last
host [%s] because this host does not have the required GPU devices available.
Skipping this and trying other available hosts.",
+ vm.getUuid(), host.getUuid()));
+ return false;
+ }
+
+ if (volumesRequireEncryption &&
!Boolean.parseBoolean(host.getDetail(Host.HOST_VOLUME_ENCRYPTION))) {
+ s_logger.warn(String.format("The last host of this VM %s does not
support volume encryption, which is required by this VM.", host));
+ return false;
+ }
+ return true;
+ }
+
+ private DeployDestination
deployInSpecifiedHostWithoutHA(VirtualMachineProfile vmProfile, DeploymentPlan
plan, ExcludeList avoids,
+ DeploymentPlanner planner, VirtualMachine vm, DataCenter dc,
String uefiFlag)
+ throws InsufficientServerCapacityException {
+ Long hostIdSpecified = plan.getHostId();
+ s_logger.debug(String.format("DeploymentPlan [%s] has specified host
[%s] without HA flag. Choosing this host to deploy VM [%s].",
plan.getClass().getSimpleName(), hostIdSpecified, vm.getUuid()));
+
+ HostVO host = _hostDao.findById(hostIdSpecified);
+ if (host != null && StringUtils.isNotBlank(uefiFlag) &&
"yes".equalsIgnoreCase(uefiFlag)) {
+ _hostDao.loadDetails(host);
+ if (MapUtils.isNotEmpty(host.getDetails()) &&
host.getDetails().containsKey(Host.HOST_UEFI_ENABLE) &&
"false".equalsIgnoreCase(host.getDetails().get(Host.HOST_UEFI_ENABLE))) {
+ s_logger.debug(String.format("Cannot deploy VM [%s] to
specified host [%s] because this host does not support UEFI VM deployment,
returning.", vm.getUuid(), host.getUuid()));
+ return null;
+
+ }
+ }
+ if (host == null) {
+ s_logger.debug(String.format("Cannot deploy VM [%s] to host [%s]
because this host cannot be found.", vm.getUuid(), hostIdSpecified));
+ return null;
+ }
+ if (avoids.shouldAvoid(host)) {
+ s_logger.debug(String.format("Cannot deploy VM [%s] to host [%s]
because this host is in the avoid set.", vm.getUuid(), host.getUuid()));
+ return null;
+ }
+
+ s_logger.debug(String.format("Trying to find suitable pools for host
[%s] under pod [%s], cluster [%s] and zone [%s], to deploy VM [%s].",
+ host.getUuid(), host.getDataCenterId(), host.getPodId(),
host.getClusterId(), vm.getUuid()));
+
+ Pod pod = _podDao.findById(host.getPodId());
+ Cluster cluster = _clusterDao.findById(host.getClusterId());
+
+ boolean displayStorage = getDisplayStorageFromVmProfile(vmProfile);
+ if (vm.getHypervisorType() == HypervisorType.BareMetal) {
+ DeployDestination dest = new DeployDestination(dc, pod, cluster,
host, new HashMap<Volume, StoragePool>(),
+ displayStorage);
+ s_logger.debug("Returning Deployment Destination: " + dest);
+ return dest;
+ }
+
+ DataCenterDeployment lastPlan = new
DataCenterDeployment(host.getDataCenterId(), host.getPodId(),
+ host.getClusterId(), hostIdSpecified, plan.getPoolId(), null,
plan.getReservationContext());
+
+ Pair<Map<Volume, List<StoragePool>>, List<Volume>> result =
findSuitablePoolsForVolumes(vmProfile, lastPlan,
+ avoids, HostAllocator.RETURN_UPTO_ALL);
+ Map<Volume, List<StoragePool>> suitableVolumeStoragePools =
result.first();
+ List<Volume> readyAndReusedVolumes = result.second();
+
+ if (!suitableVolumeStoragePools.isEmpty()) {
+ List<Host> suitableHosts = new ArrayList<Host>();
+ suitableHosts.add(host);
+ Pair<Host, Map<Volume, StoragePool>> potentialResources =
findPotentialDeploymentResources(suitableHosts,
+ suitableVolumeStoragePools, avoids,
getPlannerUsage(planner, vmProfile, plan, avoids),
+ readyAndReusedVolumes, plan.getPreferredHosts(), vm);
+ if (potentialResources != null) {
+ pod = _podDao.findById(host.getPodId());
+ cluster = _clusterDao.findById(host.getClusterId());
+ Map<Volume, StoragePool> storageVolMap =
potentialResources.second();
+ for (Volume vol : readyAndReusedVolumes) {
+ storageVolMap.remove(vol);
+ }
+ DeployDestination dest = new DeployDestination(dc, pod,
cluster, host, storageVolMap, displayStorage);
+ s_logger.debug("Returning Deployment Destination: " + dest);
+ return dest;
+ }
+ }
+ s_logger.debug(String.format("Cannot deploy VM [%s] under host [%s],
because there are no suitable pools found.", vmProfile.getUuid(),
host.getUuid()));
Review Comment:
```suggestion
s_logger.debug(String.format("Cannot deploy VM [%s] under host [%s],
because no suitable pools were found.", vmProfile.getUuid(), host.getUuid()));
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]