This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new 6f27b1f459f Improve logs when adding components to avoid set (#7214)
6f27b1f459f is described below

commit 6f27b1f459f8347ccaff1cc780980856a446705c
Author: SadiJr <[email protected]>
AuthorDate: Wed Feb 28 04:49:10 2024 -0300

    Improve logs when adding components to avoid set (#7214)
    
    Co-authored-by: SadiJr <[email protected]>
    Co-authored-by: GaOrtiga <[email protected]>
    Co-authored-by: João Jandre <[email protected]>
---
 .../java/com/cloud/deploy/DeploymentPlanner.java   |  24 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java    |  14 +-
 .../manager/allocator/impl/FirstFitAllocator.java  |  14 +-
 .../deploy/DeploymentPlanningManagerImpl.java      | 783 +++++++++++----------
 .../deploy/DeploymentPlanningManagerImplTest.java  |   4 +-
 5 files changed, 455 insertions(+), 384 deletions(-)

diff --git a/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java 
b/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java
index e9f706ac1ce..354f9cfaac5 100644
--- a/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java
+++ b/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java
@@ -21,8 +21,12 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
 
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
 import com.cloud.dc.DataCenter;
 import com.cloud.dc.Pod;
+import com.cloud.exception.CloudException;
 import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.InsufficientServerCapacityException;
 import com.cloud.exception.ResourceUnavailableException;
@@ -75,7 +79,7 @@ public interface DeploymentPlanner extends Adapter {
 
     public static class ExcludeList implements Serializable {
         private static final long serialVersionUID = -482175549460148301L;
-
+        protected static Logger LOGGER = 
LogManager.getLogger(ExcludeList.class);
         private Set<Long> _dcIds;
         private Set<Long> _podIds;
         private Set<Long> _clusterIds;
@@ -104,13 +108,26 @@ public interface DeploymentPlanner extends Adapter {
             }
         }
 
+        private void logAvoid(Class<?> scope, CloudException e) {
+            Long id = null;
+            if (e instanceof InsufficientCapacityException) {
+                id = ((InsufficientCapacityException) e).getId();
+            } else if (e instanceof ResourceUnavailableException) {
+                id = ((ResourceUnavailableException) e).getResourceId();
+            } else {
+                LOGGER.debug("Failed to log avoided component due to 
unexpected exception type [{}].", e.getMessage());
+                return;
+            }
+            LOGGER.debug("Adding {} [{}] to the avoid set due to [{}].", 
scope.getSimpleName(), id, e.getMessage());
+        }
+
         public boolean add(InsufficientCapacityException e) {
             Class<?> scope = e.getScope();
 
             if (scope == null) {
                 return false;
             }
-
+            logAvoid(scope, e);
             if (Host.class.isAssignableFrom(scope)) {
                 addHost(e.getId());
             } else if (Pod.class.isAssignableFrom(scope)) {
@@ -128,13 +145,14 @@ public interface DeploymentPlanner extends Adapter {
             return true;
         }
 
+
         public boolean add(ResourceUnavailableException e) {
             Class<?> scope = e.getScope();
 
             if (scope == null) {
                 return false;
             }
-
+            logAvoid(scope, e);
             if (Host.class.isAssignableFrom(scope)) {
                 addHost(e.getResourceId());
             } else if (Pod.class.isAssignableFrom(scope)) {
diff --git 
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
 
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
index f3ec3dd4761..87399389271 100755
--- 
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++ 
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -165,6 +165,7 @@ import com.cloud.deploy.DeploymentPlan;
 import com.cloud.deploy.DeploymentPlanner;
 import com.cloud.deploy.DeploymentPlanner.ExcludeList;
 import com.cloud.deploy.DeploymentPlanningManager;
+import com.cloud.deploy.DeploymentPlanningManagerImpl;
 import com.cloud.deployasis.dao.UserVmDeployAsIsDetailsDao;
 import com.cloud.event.EventTypes;
 import com.cloud.event.UsageEventUtils;
@@ -237,6 +238,7 @@ import com.cloud.user.User;
 import com.cloud.uservm.UserVm;
 import com.cloud.utils.DateUtil;
 import com.cloud.utils.Journal;
+import com.cloud.utils.LogUtils;
 import com.cloud.utils.Pair;
 import com.cloud.utils.Predicate;
 import com.cloud.utils.ReflectionUse;
@@ -1093,6 +1095,7 @@ public class VirtualMachineManagerImpl extends 
ManagerBase implements VirtualMac
     public void orchestrateStart(final String vmUuid, final 
Map<VirtualMachineProfile.Param, Object> params, final DeploymentPlan 
planToDeploy, final DeploymentPlanner planner)
             throws InsufficientCapacityException, 
ConcurrentOperationException, ResourceUnavailableException {
 
+        logger.debug(() -> LogUtils.logGsonWithoutException("Trying to start 
VM [%s] using plan [%s] and planner [%s].", vmUuid, planToDeploy, planner));
         final CallContext cctxt = CallContext.current();
         final Account account = cctxt.getCallingAccount();
         final User caller = cctxt.getCallingUser();
@@ -1116,10 +1119,8 @@ public class VirtualMachineManagerImpl extends 
ManagerBase implements VirtualMac
 
         DataCenterDeployment plan = new 
DataCenterDeployment(vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, 
null, null, ctx);
         if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
-            if (logger.isDebugEnabled()) {
-                logger.debug("advanceStart: DeploymentPlan is provided, using 
dcId:" + planToDeploy.getDataCenterId() + ", podId: " + planToDeploy.getPodId() 
+
-                        ", clusterId: " + planToDeploy.getClusterId() + ", 
hostId: " + planToDeploy.getHostId() + ", poolId: " + planToDeploy.getPoolId());
-            }
+            VMInstanceVO finalVm = vm;
+            logger.debug(() -> 
DeploymentPlanningManagerImpl.logDeploymentWithoutException(finalVm, 
planToDeploy, planToDeploy.getAvoids(), planner));
             plan =
                     new DataCenterDeployment(planToDeploy.getDataCenterId(), 
planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(),
                             planToDeploy.getPoolId(), 
planToDeploy.getPhysicalNetworkId(), ctx);
@@ -1140,13 +1141,12 @@ public class VirtualMachineManagerImpl extends 
ManagerBase implements VirtualMac
 
             if (planToDeploy != null) {
                 avoids = planToDeploy.getAvoids();
+                ExcludeList finalAvoids = avoids;
+                logger.debug(() -> LogUtils.logGsonWithoutException("Avoiding 
components [%s] in deployment of VM [%s].", finalAvoids, vmUuid));
             }
             if (avoids == null) {
                 avoids = new ExcludeList();
             }
-            if (logger.isDebugEnabled()) {
-                logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() 
+ ", clusters: " + avoids.getClustersToAvoid() + ", hosts: " + 
avoids.getHostsToAvoid());
-            }
 
             boolean planChangedByVolume = false;
             boolean reuseVolume = true;
diff --git 
a/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
 
b/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
index 1e92a80a280..36330d6685c 100644
--- 
a/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
+++ 
b/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
@@ -27,6 +27,7 @@ import javax.naming.ConfigurationException;
 
 import com.cloud.utils.exception.CloudRuntimeException;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import 
org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
 import org.springframework.stereotype.Component;
 
 import com.cloud.agent.manager.allocator.HostAllocator;
@@ -210,6 +211,10 @@ public class FirstFitAllocator extends AdapterBase 
implements HostAllocator {
         // 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);
+
+        logger.debug(() -> String.format("Adding hosts [%s] to the avoid set 
because these hosts do not support HA.",
+                
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(allhostsInCluster, 
"uuid", "name")));
+
         for (HostVO host : allhostsInCluster) {
             avoid.addHost(host.getId());
         }
@@ -325,10 +330,8 @@ public class FirstFitAllocator extends AdapterBase 
implements HostAllocator {
 
             //find number of guest VMs occupying capacity on this host.
             if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) {
-                if (logger.isDebugEnabled()) {
-                    logger.debug("Host name: " + host.getName() + ", hostId: " 
+ host.getId() +
-                        " already has max Running VMs(count includes system 
VMs), skipping this and trying other available hosts");
-                }
+                logger.debug(() -> String.format("Adding host [%s] to the 
avoid set because this host already has the max number of running (user and/or 
system) VMs.",
+                        
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(host, "uuid", 
"name")));
                 avoid.addHost(host.getId());
                 continue;
             }
@@ -337,7 +340,8 @@ public class FirstFitAllocator extends AdapterBase 
implements HostAllocator {
             if ((offeringDetails   = 
_serviceOfferingDetailsDao.findDetail(serviceOfferingId, 
GPU.Keys.vgpuType.toString())) != null) {
                 ServiceOfferingDetailsVO groupName = 
_serviceOfferingDetailsDao.findDetail(serviceOfferingId, 
GPU.Keys.pciDevice.toString());
                 if(!_resourceMgr.isGPUDeviceAvailable(host.getId(), 
groupName.getValue(), offeringDetails.getValue())){
-                    logger.info("Host name: " + host.getName() + ", hostId: "+ 
host.getId() +" does not have required GPU devices available");
+                    logger.debug(String.format("Adding host [%s] to avoid set, 
because this host does not have required GPU devices available.",
+                            
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(host, "uuid", 
"name")));
                     avoid.addHost(host.getId());
                     continue;
                 }
diff --git 
a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java 
b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
index 41a51bc7af5..d97fcef7453 100644
--- a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
+++ b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
@@ -46,7 +46,9 @@ import com.cloud.utils.fsm.StateMachine2;
 
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.Configurable;
+import 
org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cloudstack.affinity.AffinityGroupProcessor;
 import org.apache.cloudstack.affinity.AffinityGroupService;
@@ -128,6 +130,7 @@ import com.cloud.storage.dao.VolumeDao;
 import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.user.AccountManager;
 import com.cloud.utils.DateUtil;
+import com.cloud.utils.LogUtils;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
 import com.cloud.utils.component.Manager;
@@ -299,25 +302,30 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
     @Override
     public DeployDestination planDeployment(VirtualMachineProfile vmProfile, 
DeploymentPlan plan, ExcludeList avoids, DeploymentPlanner planner)
             throws InsufficientServerCapacityException, 
AffinityConflictException {
+        
logger.debug(logDeploymentWithoutException(vmProfile.getVirtualMachine(), plan, 
avoids, planner));
 
         ServiceOffering offering = vmProfile.getServiceOffering();
-        int cpu_requested = offering.getCpu() * offering.getSpeed();
-        long ram_requested = offering.getRamSize() * 1024L * 1024L;
+        int cpuRequested = offering.getCpu() * offering.getSpeed();
+        long ramRequested = offering.getRamSize() * 1024L * 1024L;
         VirtualMachine vm = vmProfile.getVirtualMachine();
         DataCenter dc = _dcDao.findById(vm.getDataCenterId());
         boolean volumesRequireEncryption = 
anyVolumeRequiresEncryption(_volsDao.findByInstance(vm.getId()));
 
         if (vm.getType() == VirtualMachine.Type.User || vm.getType() == 
VirtualMachine.Type.DomainRouter) {
+            logger.debug("Checking non dedicated resources to deploy VM 
[{}].", () -> ReflectionToStringBuilderUtils.reflectOnlySelectedFields(vm, 
"uuid", "type", "instanceName"));
             checkForNonDedicatedResources(vmProfile, dc, avoids);
         }
-        if (logger.isDebugEnabled()) {
-            logger.debug("DeploymentPlanner allocation algorithm: " + planner);
 
-            logger.debug("Trying to allocate a host and storage pools from 
dc:" + plan.getDataCenterId() + ", pod:" + plan.getPodId() + ",cluster:" +
-                    plan.getClusterId() + ", requested cpu: " + cpu_requested 
+ ", requested ram: " + toHumanReadableSize(ram_requested));
+        logger.debug(() -> {
+            String datacenter = 
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(dc, "uuid", "name");
+            String podVO = 
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(_podDao.findById(plan.getPodId()),
 "uuid", "name");
+            String clusterVO = 
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(_clusterDao.findById(plan.getClusterId()),
 "uuid", "name");
+            String vmDetails = 
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(vm, "uuid", "type", 
"instanceName");
+            return String.format("Trying to allocate a host and storage pools 
from datacenter [%s], pod [%s], cluster [%s], to deploy VM [%s] "
+                    + "with requested CPU [%s] and requested RAM [%s].", 
datacenter, podVO, clusterVO, vmDetails, cpuRequested, 
toHumanReadableSize(ramRequested));
+        });
 
-            logger.debug("Is ROOT volume READY (pool already allocated)?: " + 
(plan.getPoolId() != null ? "Yes" : "No"));
-        }
+        logger.debug("ROOT volume [{}] {} to deploy VM [{}].", () -> 
getRootVolumeUuid(_volsDao.findByInstance(vm.getId())), () -> plan.getPoolId() 
!= null ? "is ready" : "is not ready", vm::getUuid);
 
         avoidDisabledResources(vmProfile, dc, avoids);
 
@@ -325,81 +333,7 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
         String uefiFlag = 
(String)vmProfile.getParameter(VirtualMachineProfile.Param.UefiFlag);
 
         if (plan.getHostId() != null && haVmTag == null) {
-            Long hostIdSpecified = plan.getHostId();
-            if (logger.isDebugEnabled()) {
-                logger.debug("DeploymentPlan has host_id specified, choosing 
this host: " + hostIdSpecified);
-            }
-            HostVO host = _hostDao.findById(hostIdSpecified);
-            if (host != null && StringUtils.isNotBlank(uefiFlag) && 
"yes".equalsIgnoreCase(uefiFlag)) {
-                DetailVO uefiHostDetail = 
_hostDetailsDao.findDetail(host.getId(), Host.HOST_UEFI_ENABLE);
-                if (uefiHostDetail == null || 
"false".equalsIgnoreCase(uefiHostDetail.getValue())) {
-                    logger.debug("Cannot deploy to specified host as host does 
n't support uefi vm deployment, returning.");
-                    return null;
-
-                }
-            }
-            if (host == null) {
-                logger.debug("The specified host cannot be found");
-            } else if (avoids.shouldAvoid(host)) {
-                logger.debug("The specified host is in avoid set");
-            } else {
-                if (logger.isDebugEnabled()) {
-                    logger.debug(
-                            "Looking for suitable pools for this host under 
zone: " + host.getDataCenterId() + ", pod: " + host.getPodId() + ", cluster: " 
+ host.getClusterId());
-                }
-
-                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);
-                    logger.debug("Returning Deployment Destination: " + dest);
-                    return dest;
-                }
-
-                // search for storage under the zone, pod, cluster of the host.
-                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();
-
-                _hostDao.loadDetails(host);
-                if (volumesRequireEncryption && 
!Boolean.parseBoolean(host.getDetail(Host.HOST_VOLUME_ENCRYPTION))) {
-                    logger.warn(String.format("VM's volumes require encryption 
support, and provided host %s can't handle it", host));
-                    return null;
-                } else {
-                    logger.debug(String.format("Volume encryption requirements 
are met by provided host %s", host));
-                }
-
-                // choose the potential pool for this VM for this host
-                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();
-                        // 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);
-                        logger.debug("Returning Deployment Destination: " + 
dest);
-                        return dest;
-                    }
-                }
-            }
-            logger.debug("Cannot deploy to specified host, returning.");
-            return null;
+            return deployInSpecifiedHostWithoutHA(vmProfile, plan, avoids, 
planner, vm, dc, uefiFlag);
         }
 
         // call affinitygroup chain
@@ -410,11 +344,14 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
                 processor.process(vmProfile, plan, avoids);
             }
         }
+        logger.debug("DeploymentPlan [{}] has not specified host. Trying to 
find another destination to deploy VM [{}], avoiding pods [{}], clusters [{}] 
and hosts [{}].",
+                () -> plan.getClass().getSimpleName(), vmProfile::getUuid, () 
-> StringUtils.join(avoids.getPodsToAvoid(), ", "), () -> 
StringUtils.join(avoids.getClustersToAvoid(), ", "),
+                () -> StringUtils.join(avoids.getHostsToAvoid(), ", "));
+
+
+        logger.debug("Deploy avoids pods: {}, clusters: {}, hosts: {}.", 
avoids.getPodsToAvoid(), avoids.getClustersToAvoid(),  
avoids.getHostsToAvoid());
+        logger.debug("Deploy hosts with priorities {}, hosts have NORMAL 
priority by default", plan.getHostPriorities());
 
-        if (logger.isDebugEnabled()) {
-            logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + ", 
clusters: " + avoids.getClustersToAvoid() + ", hosts: " + 
avoids.getHostsToAvoid());
-            logger.debug("Deploy hosts with priorities " + 
plan.getHostPriorities() + " , hosts have NORMAL priority by default");
-        }
 
         // call planners
         // DataCenter dc = _dcDao.findById(vm.getDataCenterId());
@@ -448,108 +385,11 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
 
             HostVO host = _hostDao.findById(vm.getLastHostId());
             lastHost = host;
-            _hostDao.loadHostTags(host);
-            _hostDao.loadDetails(host);
-            ServiceOfferingDetailsVO offeringDetails = null;
-            if (host == null) {
-                logger.debug("The last host of this VM cannot be found");
-            } else if (avoids.shouldAvoid(host)) {
-                logger.debug("The last host of this VM is in avoid set");
-            } else if (plan.getClusterId() != null && host.getClusterId() != 
null
-                    && !plan.getClusterId().equals(host.getClusterId())) {
-                logger.debug("The last host of this VM cannot be picked as the 
plan specifies different clusterId: "
-                        + plan.getClusterId());
-            } else if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) {
-                logger.debug("The last Host, hostId: " + host.getId() +
-                        " already has max Running VMs(count includes system 
VMs), skipping this and trying other available hosts");
-            } else if ((offeringDetails  = 
_serviceOfferingDetailsDao.findDetail(offering.getId(), 
GPU.Keys.vgpuType.toString())) != null) {
-                ServiceOfferingDetailsVO groupName = 
_serviceOfferingDetailsDao.findDetail(offering.getId(), 
GPU.Keys.pciDevice.toString());
-                if(!_resourceMgr.isGPUDeviceAvailable(host.getId(), 
groupName.getValue(), offeringDetails.getValue())){
-                    logger.debug("The last host of this VM does not have 
required GPU devices available");
-                }
-            } else if (volumesRequireEncryption && 
!Boolean.parseBoolean(host.getDetail(Host.HOST_VOLUME_ENCRYPTION))) {
-                logger.warn(String.format("The last host of this VM %s does 
not support volume encryption, which is required by this VM.", host));
-            } else {
-                if (host.getStatus() == Status.Up) {
-                    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(), cpu_requested, ram_requested, 
true, cpuOvercommitRatio, memoryOvercommitRatio, true);
-
-                            // if not reserved, check the free capacity
-                            if (!hostHasCapacity)
-                                hostHasCapacity = 
_capacityMgr.checkIfHostHasCapacity(host.getId(), cpu_requested, ram_requested, 
false, cpuOvercommitRatio, memoryOvercommitRatio, true);
-                        }
-
-                        boolean displayStorage = 
getDisplayStorageFromVmProfile(vmProfile);
-                        if (hostHasCapacity
-                                && hostHasCpuCapability) {
-                            logger.debug("The last host of this VM is UP and 
has enough capacity");
-                            logger.debug("Now checking for suitable pools 
under zone: " + host.getDataCenterId()
-                                    + ", pod: " + host.getPodId() + ", 
cluster: " + 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);
-                                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()) {
-                                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);
-                                    logger.debug("Returning Deployment 
Destination: " + dest);
-                                    return dest;
-                                }
-                            }
-                        } else {
-                            logger.debug("The last host of this VM does not 
have enough capacity");
-                        }
-                    }
-                } else {
-                    logger.debug("The last host of this VM is not UP or is not 
enabled, host status is: " + host.getStatus().name() + ", host resource state 
is: " +
-                            host.getResourceState());
-                }
+            DeployDestination deployDestination = 
deployInVmLastHost(vmProfile, plan, avoids, planner, vm, dc, offering, 
cpuRequested, ramRequested, volumesRequireEncryption);
+            if (deployDestination != null) {
+                return deployDestination;
             }
-            logger.debug("Cannot choose the last host to deploy this VM ");
         }
 
         avoidOtherClustersForDeploymentIfMigrationDisabled(vm, lastHost, 
avoids);
@@ -614,6 +454,208 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
         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) {
+                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.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) {
+                    logger.debug("Cannot deploy VM [{}] to the last host [{}] 
because this host does not have enough capacity to deploy this VM.", 
vm.getUuid(), host.getUuid());
+                    return null;
+                }
+                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.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);
+                    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()) {
+                    logger.debug("Cannot find suitable storage pools in host 
[{}] to deploy VM [{}]", 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);
+                    logger.debug("Returning Deployment Destination: {}", dest);
+                    return dest;
+                }
+            }
+        }
+        logger.debug("Cannot choose the last host to deploy this VM {}.", vm);
+        return null;
+    }
+
+    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.getUuid(), 
vm.getLastHostId());
+            return false;
+        }
+
+        if (avoids.shouldAvoid(host)) {
+            logger.warn("The last host [{}] of VM [{}] 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())) {
+            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)) {
+            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.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())) {
+            logger.debug("Cannot deploy VM [{}] in the last host [{}] 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))) {
+            logger.warn("The last host of this VM {} 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();
+        logger.debug("DeploymentPlan [{}] has specified host [{}] without HA 
flag. Choosing this host to deploy VM [{}].", 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))) {
+                logger.debug("Cannot deploy VM [{}] to specified host [{}] 
because this host does not support UEFI VM deployment, returning.", 
vm.getUuid(), host.getUuid());
+                return null;
+            }
+        }
+        if (host == null) {
+            logger.debug("Cannot deploy VM [{}] to host [{}] because this host 
cannot be found.", vm.getUuid(), hostIdSpecified);
+            return null;
+        }
+        if (avoids.shouldAvoid(host)) {
+            logger.debug("Cannot deploy VM [{}] to host [{}] because this host 
is in the avoid set.", vm.getUuid(), host.getUuid());
+            return null;
+        }
+
+        logger.debug("Trying to find suitable pools for host [{}] under pod 
[{}], cluster [{}] and zone [{}], to deploy VM [{}].",
+                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);
+            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);
+                logger.debug("Returning Deployment Destination: {}", dest);
+                return dest;
+            }
+        }
+        logger.debug("Cannot deploy VM [{}] under host [{}], because no 
suitable pools were found.", vmProfile.getUuid(), host.getUuid());
+        return null;
+    }
+
+    protected String getRootVolumeUuid(List<? extends Volume> volumes) {
+        for (Volume volume : volumes) {
+            if (volume.getVolumeType() == Volume.Type.ROOT) {
+                return volume.getUuid();
+            }
+        }
+        return null;
+    }
+
     protected boolean anyVolumeRequiresEncryption(List<? extends Volume> 
volumes) {
         for (Volume volume : volumes) {
             if (volume.getPassphraseId() != null) {
@@ -636,32 +678,29 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
         return vmProfile == null || vmProfile.getTemplate() == null || 
!vmProfile.getTemplate().isDeployAsIs();
     }
 
-        /**
-         * Adds disabled resources (Data centers, Pods, Clusters, and hosts) 
to exclude list (avoid) in case of disabled state.
-         */
-        public void avoidDisabledResources(VirtualMachineProfile vmProfile, 
DataCenter dc, ExcludeList avoids) {
-            if (vmProfile.getType().isUsedBySystem() && 
isRouterDeployableInDisabledResources()) {
-                return;
-            }
-
-            VMInstanceVO vm = _vmInstanceDao.findById(vmProfile.getId());
-            AccountVO owner = accountDao.findById(vm.getAccountId());
-            boolean isOwnerRoleIdAdmin = false;
-
-            if (owner != null && owner.getRoleId() != null && 
owner.getRoleId() == ADMIN_ACCOUNT_ROLE_ID) {
-                isOwnerRoleIdAdmin = true;
-            }
+    /**
+     * Adds disabled resources (Data centers, Pods, Clusters, and hosts) to 
exclude
+     * list (avoid) in case of disabled state.
+     */
+    public void avoidDisabledResources(VirtualMachineProfile vmProfile, 
DataCenter dc, ExcludeList avoids) {
+        if (vmProfile.getType().isUsedBySystem() && 
isRouterDeployableInDisabledResources()) {
+            return;
+        }
 
-            if (isOwnerRoleIdAdmin && 
isAdminVmDeployableInDisabledResources()) {
-                return;
-            }
+        VMInstanceVO vm = _vmInstanceDao.findById(vmProfile.getId());
+        AccountVO owner = accountDao.findById(vm.getAccountId());
+        boolean isOwnerRoleIdAdmin = owner != null && owner.getRoleId() != 
null && owner.getRoleId() == ADMIN_ACCOUNT_ROLE_ID;
 
-            avoidDisabledDataCenters(dc, avoids);
-            avoidDisabledPods(dc, avoids);
-            avoidDisabledClusters(dc, avoids);
-            avoidDisabledHosts(dc, avoids);
+        if (isOwnerRoleIdAdmin && isAdminVmDeployableInDisabledResources()) {
+            return;
         }
 
+        avoidDisabledDataCenters(dc, avoids);
+        avoidDisabledPods(dc, avoids);
+        avoidDisabledClusters(dc, avoids);
+        avoidDisabledHosts(dc, avoids);
+    }
+
     /**
      * Returns the value of the ConfigKey 'allow.router.on.disabled.resources'.
      * @note this method allows mocking and testing with the respective 
ConfigKey parameter.
@@ -683,6 +722,8 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
      */
     protected void avoidDisabledHosts(DataCenter dc, ExcludeList avoids) {
         List<HostVO> disabledHosts = 
_hostDao.listDisabledByDataCenterId(dc.getId());
+        logger.debug(() -> String.format("Adding hosts [%s] of datacenter [%s] 
to the avoid set, because these hosts are in the Disabled state.",
+                
disabledHosts.stream().map(HostVO::getUuid).collect(Collectors.joining(", ")), 
dc.getUuid()));
         for (HostVO host : disabledHosts) {
             avoids.addHost(host.getId());
         }
@@ -695,6 +736,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
         List<Long> pods = _podDao.listAllPods(dc.getId());
         for (Long podId : pods) {
             List<Long> disabledClusters = 
_clusterDao.listDisabledClusters(dc.getId(), podId);
+            logger.debug(() -> String.format("Adding clusters [%s] of pod [%s] 
to the void set because these clusters are in the Disabled state.", 
StringUtils.join(disabledClusters, ", "), podId));
             avoids.addClusterList(disabledClusters);
         }
     }
@@ -704,6 +746,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
      */
     protected void avoidDisabledPods(DataCenter dc, ExcludeList avoids) {
         List<Long> disabledPods = _podDao.listDisabledPods(dc.getId());
+        logger.debug(() -> String.format("Adding pods [%s] to the avoid set 
because these pods are in the Disabled state.", StringUtils.join(disabledPods, 
", ")));
         avoids.addPodList(disabledPods);
     }
 
@@ -712,6 +755,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
      */
     protected void avoidDisabledDataCenters(DataCenter dc, ExcludeList avoids) 
{
         if (dc.getAllocationState() == Grouping.AllocationState.Disabled) {
+            logger.debug("Adding datacenter [{}] to the avoid set because this 
datacenter is in Disabled state.", dc.getUuid());
             avoids.addDataCenter(dc.getId());
         }
     }
@@ -765,6 +809,8 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
         if (dedicatedZone != null && 
!_accountMgr.isRootAdmin(vmProfile.getOwner().getId())) {
             long accountDomainId = vmProfile.getOwner().getDomainId();
             long accountId = vmProfile.getOwner().getAccountId();
+            logger.debug("Zone [{}] is dedicated. Checking if account [{}] in 
domain [{}] can use this zone to deploy VM [{}].",
+                    dedicatedZone.getUuid(), accountId, accountDomainId, 
vmProfile.getUuid());
 
             // If a zone is dedicated to an account then all hosts in this zone
             // will be explicitly dedicated to
@@ -784,7 +830,6 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, 
Configurable {
             if 
(!_affinityGroupService.isAffinityGroupAvailableInDomain(dedicatedZone.getAffinityGroupId(),
 accountDomainId)) {
                 throw new CloudRuntimeException("Failed to deploy VM, Zone " + 
dc.getName() + " not available for the user domain " + vmProfile.getOwner());
             }
-
         }
 
         // check affinity group of type Explicit dedication exists. If No put
@@ -809,109 +854,97 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
 
         //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 (logger.isDebugEnabled()) {
-                logger.debug("Adding pods to avoid lists for non-explicit VM 
deployment: " + allPodsInDc);
-            }
-            avoids.addPodList(allPodsInDc);
-            if (logger.isDebugEnabled()) {
-                logger.debug("Adding clusters to avoid lists for non-explicit 
VM deployment: " + allClustersInDc);
-            }
-            avoids.addClusterList(allClustersInDc);
-            if (logger.isDebugEnabled()) {
-                logger.debug("Adding hosts to avoid lists for non-explicit VM 
deployment: " + allHostsInDc);
-            }
-            avoids.addHostList(allHostsInDc);
+            findAvoidSetForNonExplicitUserVM(avoids, 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 (logger.isDebugEnabled()) {
-                logger.debug("Adding pods to avoid lists: " + allPodsInDc);
-            }
-            avoids.addPodList(allPodsInDc);
-            if (logger.isDebugEnabled()) {
-                logger.debug("Adding clusters to avoid lists: " + 
allClustersInDc);
-            }
-            avoids.addClusterList(allClustersInDc);
-            if (logger.isDebugEnabled()) {
-                logger.debug("Adding hosts to avoid lists: " + allHostsInDc);
-            }
-            avoids.addHostList(allHostsInDc);
+            allPodsInDc.removeAll(allPodsFromDedicatedID);
+            allClustersInDc.removeAll(allClustersFromDedicatedID);
+            allHostsInDc.removeAll(allHostsFromDedicatedID);
         }
+
+        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, 
VirtualMachine vm, List<Long> allPodsInDc, List<Long> allClustersInDc, 
List<Long> allHostsInDc) {
+        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 explicitly dedicated to 
these components.", allPodsInDc, allClustersInDc, allHostsInDc, vm.getUuid()));
+        avoids.addPodList(allPodsInDc);
+        avoids.addClusterList(allClustersInDc);
+        avoids.addHostList(allHostsInDc);
     }
 
     private void resetAvoidSet(ExcludeList avoidSet, ExcludeList removeSet) {
@@ -1246,14 +1279,15 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
             DeploymentPlanner.PlannerResourceUsage resourceUsageRequired, 
ExcludeList plannerAvoidOutput) {
 
         if (logger.isTraceEnabled()) {
-            logger.trace("ClusterId List to consider: " + clusterList);
+            logger.trace("ClusterId List to consider: {}.", clusterList);
         }
 
         for (Long clusterId : clusterList) {
             ClusterVO clusterVO = _clusterDao.findById(clusterId);
 
             if (clusterVO.getHypervisorType() != 
vmProfile.getHypervisorType()) {
-                logger.debug("Cluster: " + clusterId + " has HyperVisorType 
that does not match the VM, skipping this cluster");
+                logger.debug("Adding cluster [{}] to the avoid set because the 
cluster's hypervisor [{}] does not match the VM [{}] hypervisor: [{}]. Skipping 
this cluster.",
+                        clusterVO.getUuid(), 
clusterVO.getHypervisorType().name(), vmProfile.getUuid(), 
vmProfile.getHypervisorType().name());
                 avoid.addCluster(clusterVO.getId());
                 continue;
             }
@@ -1564,14 +1598,17 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
 
             boolean hostHasEncryption = 
Boolean.parseBoolean(potentialHostVO.getDetail(Host.HOST_VOLUME_ENCRYPTION));
             boolean hostMeetsEncryptionRequirements = 
!anyVolumeRequiresEncryption(new ArrayList<>(volumesOrderBySizeDesc)) || 
hostHasEncryption;
-            boolean plannerUsageFits = 
checkIfHostFitsPlannerUsage(potentialHost.getId(), resourceUsageRequired);
+            boolean hostFitsPlannerUsage = 
checkIfHostFitsPlannerUsage(potentialHost.getId(), resourceUsageRequired);
 
-            if (hostCanAccessPool && haveEnoughSpace && hostAffinityCheck && 
hostMeetsEncryptionRequirements && plannerUsageFits) {
+            if (hostCanAccessPool && haveEnoughSpace && hostAffinityCheck && 
hostMeetsEncryptionRequirements && hostFitsPlannerUsage) {
                 logger.debug("Found a potential host " + "id: " + 
potentialHost.getId() + " name: " + potentialHost.getName() +
                         " and associated storage pools for this VM");
                 volumeAllocationMap.clear();
                 return new Pair<Host, Map<Volume, StoragePool>>(potentialHost, 
storage);
             } else {
+                logger.debug("Adding host [{}] to the avoid set because: can 
access Pool [{}], has enough space [{}], affinity check [{}], fits planner [{}] 
usage [{}].",
+                        potentialHost.getUuid(), hostCanAccessPool, 
haveEnoughSpace, hostAffinityCheck, 
resourceUsageRequired.getClass().getSimpleName(), hostFitsPlannerUsage);
+
                 if (!hostMeetsEncryptionRequirements) {
                     logger.debug("Potential host " + potentialHost + " did not 
meet encryption requirements of all volumes");
                 }
@@ -1668,12 +1705,12 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
         // There should be at least the ROOT volume of the VM in usable state
         if (volumesTobeCreated.isEmpty()) {
             // OfflineVmwareMigration: find out what is wrong with the id of 
the vm we try to start
-            throw new CloudRuntimeException("Unable to create deployment, no 
usable volumes found for the VM: " + vmProfile.getId());
+            throw new CloudRuntimeException("Unable to create deployment, no 
usable volumes found for the VM: " + vmProfile.getUuid());
         }
 
         // don't allow to start vm that doesn't have a root volume
         if (_volsDao.findByInstanceAndType(vmProfile.getId(), 
Volume.Type.ROOT).isEmpty()) {
-            throw new CloudRuntimeException("Unable to prepare volumes for vm 
as ROOT volume is missing");
+            throw new CloudRuntimeException(String.format("Unable to deploy VM 
[%s] because the ROOT volume is missing.", vmProfile.getUuid()));
         }
 
         // for each volume find list of suitable storage pools by calling the
@@ -1685,7 +1722,7 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
         Set<Long> poolsToAvoidOutput = new HashSet<>(originalAvoidPoolSet);
 
         for (VolumeVO toBeCreated : volumesTobeCreated) {
-            logger.debug("Checking suitable pools for volume (Id, Type): (" + 
toBeCreated.getId() + "," + toBeCreated.getVolumeType().name() + ")");
+            logger.debug("Checking suitable pools for volume [{}, {}] of VM 
[{}].", toBeCreated.getUuid(), toBeCreated.getVolumeType().name(), 
vmProfile.getUuid());
 
             if (toBeCreated.getState() == Volume.State.Allocated && 
toBeCreated.getPoolId() != null) {
                 toBeCreated.setPoolId(null);
@@ -1701,72 +1738,18 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
             // volume is ready and the pool should be reused.
             // In this case, also check if rest of the volumes are ready and 
can
             // be reused.
-            if (plan.getPoolId() != null || (toBeCreated.getVolumeType() == 
Volume.Type.DATADISK && toBeCreated.getPoolId() != null && 
toBeCreated.getState() == Volume.State.Ready)) {
-                logger.debug("Volume has pool already allocated, checking if 
pool can be reused, poolId: " + toBeCreated.getPoolId());
-                List<StoragePool> suitablePools = new ArrayList<StoragePool>();
-                StoragePool pool = null;
-                if (toBeCreated.getPoolId() != null) {
-                    pool = 
(StoragePool)dataStoreMgr.getPrimaryDataStore(toBeCreated.getPoolId());
-                } else {
-                    pool = 
(StoragePool)dataStoreMgr.getPrimaryDataStore(plan.getPoolId());
-                }
-
-                if (!pool.isInMaintenance()) {
-                    if (!avoid.shouldAvoid(pool)) {
-                        long exstPoolDcId = pool.getDataCenterId();
-                        long exstPoolPodId = pool.getPodId() != null ? 
pool.getPodId() : -1;
-                        long exstPoolClusterId = pool.getClusterId() != null ? 
pool.getClusterId() : -1;
-                        boolean canReusePool = false;
-                        if (plan.getDataCenterId() == exstPoolDcId && 
plan.getPodId() == exstPoolPodId && plan.getClusterId() == exstPoolClusterId) {
-                            canReusePool = true;
-                        } else if (plan.getDataCenterId() == exstPoolDcId) {
-                            DataStore dataStore = 
dataStoreMgr.getPrimaryDataStore(pool.getId());
-                            if (dataStore != null && dataStore.getScope() != 
null && dataStore.getScope().getScopeType() == ScopeType.ZONE) {
-                                canReusePool = true;
-                            }
-                        } else {
-                            logger.debug("Pool of the volume does not fit the 
specified plan, need to reallocate a pool for this volume");
-                            canReusePool = false;
-                        }
-
-                        if (canReusePool) {
-                            logger.debug("Planner need not allocate a pool for 
this volume since its READY");
-                            suitablePools.add(pool);
-                            suitableVolumeStoragePools.put(toBeCreated, 
suitablePools);
-                            if (!(toBeCreated.getState() == 
Volume.State.Allocated || toBeCreated.getState() == Volume.State.Creating)) {
-                                readyAndReusedVolumes.add(toBeCreated);
-                            }
-                            continue;
-                        }
-                    } else {
-                        logger.debug("Pool of the volume is in avoid set, need 
to reallocate a pool for this volume");
-                    }
-                } else {
-                    logger.debug("Pool of the volume is in maintenance, need 
to reallocate a pool for this volume");
-                }
+            if ((plan.getPoolId() != null || (toBeCreated.getVolumeType() == 
Volume.Type.DATADISK && toBeCreated.getPoolId() != null && 
toBeCreated.getState() == Volume.State.Ready)) &&
+                    checkIfPoolCanBeReused(vmProfile, plan, avoid, 
suitableVolumeStoragePools, readyAndReusedVolumes, toBeCreated)) {
+                continue;
             }
 
-            if (logger.isDebugEnabled()) {
-                logger.debug("We need to allocate new storagepool for this 
volume");
-            }
-            if (!isRootAdmin(vmProfile)) {
-                if (!isEnabledForAllocation(plan.getDataCenterId(), 
plan.getPodId(), plan.getClusterId())) {
-                    if (logger.isDebugEnabled()) {
-                        logger.debug("Cannot allocate new storagepool for this 
volume in this cluster, allocation state is disabled");
-                        logger.debug("Cannot deploy to this specified plan, 
allocation state is disabled, returning.");
-                    }
-                    // Cannot find suitable storage pools under this cluster 
for
-                    // this volume since allocation_state is disabled.
-                    // - remove any suitable pools found for other volumes.
-                    // All volumes should get suitable pools under this 
cluster;
-                    // else we can't use this cluster.
-                    suitableVolumeStoragePools.clear();
-                    break;
-                }
+            if (!isRootAdmin(vmProfile) && 
!isEnabledForAllocation(plan.getDataCenterId(), plan.getPodId(), 
plan.getClusterId())) {
+                logger.debug(String.format("Cannot find new storage pool to 
deploy volume [{}] of VM [{}] in cluster [{}] because allocation state is 
disabled. Returning.",
+                        toBeCreated.getUuid(), vmProfile.getUuid(), 
plan.getClusterId()));
+                suitableVolumeStoragePools.clear();
+                break;
             }
 
-            logger.debug("Calling StoragePoolAllocators to find suitable 
pools");
-
             DiskOfferingVO diskOffering = 
_diskOfferingDao.findById(toBeCreated.getDiskOfferingId());
 
             DiskProfile diskProfile = new DiskProfile(toBeCreated, 
diskOffering, vmProfile.getHypervisorType());
@@ -1783,16 +1766,8 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
                 useLocalStorage = diskOffering.isUseLocalStorage();
             }
             diskProfile.setUseLocalStorage(useLocalStorage);
-
-            boolean foundPotentialPools = false;
-            for (StoragePoolAllocator allocator : _storagePoolAllocators) {
-                final List<StoragePool> suitablePools = 
allocator.allocateToPool(diskProfile, vmProfile, plan, avoid, returnUpTo);
-                if (suitablePools != null && !suitablePools.isEmpty()) {
-                    checkForPreferredStoragePool(suitablePools, 
vmProfile.getVirtualMachine(), suitableVolumeStoragePools, toBeCreated);
-                    foundPotentialPools = true;
-                    break;
-                }
-            }
+            logger.debug(String.format("Calling StoragePoolAllocators to find 
suitable pools to allocate volume [{}] necessary to deploy VM [{}].", 
toBeCreated.getUuid(), vmProfile.getUuid()));
+            boolean foundPotentialPools = 
tryToFindPotentialPoolsToAlocateVolume(vmProfile, plan, avoid, returnUpTo, 
suitableVolumeStoragePools, toBeCreated, diskProfile);
 
             if (avoid.getPoolsToAvoid() != null) {
                 poolsToAvoidOutput.addAll(avoid.getPoolsToAvoid());
@@ -1800,7 +1775,7 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
             }
 
             if (!foundPotentialPools) {
-                logger.debug("No suitable pools found for volume: " + 
toBeCreated + " under cluster: " + plan.getClusterId());
+                logger.debug(String.format("No suitable pools found for volume 
[{}] used by VM [{}] under cluster: [{}].", toBeCreated.getUuid(), 
vmProfile.getUuid(), plan.getClusterId()));
                 // No suitable storage pools found under this cluster for this
                 // volume. - remove any suitable pools found for other volumes.
                 // All volumes should get suitable pools under this cluster;
@@ -1829,6 +1804,75 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
         return new Pair<Map<Volume, List<StoragePool>>, 
List<Volume>>(suitableVolumeStoragePools, readyAndReusedVolumes);
     }
 
+    private boolean 
tryToFindPotentialPoolsToAlocateVolume(VirtualMachineProfile vmProfile, 
DeploymentPlan plan, ExcludeList avoid, int returnUpTo,
+            Map<Volume, List<StoragePool>> suitableVolumeStoragePools, 
VolumeVO toBeCreated, DiskProfile diskProfile) {
+        for (StoragePoolAllocator allocator : _storagePoolAllocators) {
+            logger.debug("Trying to find suitable pools to allocate volume 
[{}] necessary to deploy VM [{}], using StoragePoolAllocator: [{}].",
+                    toBeCreated.getUuid(), vmProfile.getUuid(), 
allocator.getClass().getSimpleName());
+
+            final List<StoragePool> suitablePools = 
allocator.allocateToPool(diskProfile, vmProfile, plan, avoid, returnUpTo);
+            if (suitablePools != null && !suitablePools.isEmpty()) {
+                logger.debug("StoragePoolAllocator [{}] found {} suitable 
pools to allocate volume [{}] necessary to deploy VM [{}].",
+                        allocator.getClass().getSimpleName(), 
suitablePools.size(), toBeCreated.getUuid(), vmProfile.getUuid());
+                checkForPreferredStoragePool(suitablePools, 
vmProfile.getVirtualMachine(), suitableVolumeStoragePools, toBeCreated);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkIfPoolCanBeReused(VirtualMachineProfile vmProfile, 
DeploymentPlan plan, ExcludeList avoid,
+            Map<Volume, List<StoragePool>> suitableVolumeStoragePools, 
List<Volume> readyAndReusedVolumes,
+            VolumeVO toBeCreated) {
+        logger.debug("Volume [{}] of VM [{}] has pool [{}] already specified. 
Checking if this pool can be reused.", toBeCreated.getUuid(), 
vmProfile.getUuid(), toBeCreated.getPoolId());
+        List<StoragePool> suitablePools = new ArrayList<StoragePool>();
+        StoragePool pool = null;
+        if (toBeCreated.getPoolId() != null) {
+            pool = 
(StoragePool)dataStoreMgr.getPrimaryDataStore(toBeCreated.getPoolId());
+        } else {
+            pool = 
(StoragePool)dataStoreMgr.getPrimaryDataStore(plan.getPoolId());
+        }
+
+        if (!pool.isInMaintenance()) {
+            if (!avoid.shouldAvoid(pool)) {
+                return canReusePool(vmProfile, plan, 
suitableVolumeStoragePools, readyAndReusedVolumes, toBeCreated, suitablePools, 
pool);
+            } else {
+                logger.debug("Pool [{}] of volume [{}] used by VM [{}] is in 
the avoid set. Need to reallocate a pool for this volume.",
+                        pool.getUuid(), toBeCreated.getUuid(), 
vmProfile.getUuid());
+            }
+        } else {
+            logger.debug("Pool [{}] of volume [{}] used by VM [{}] is in 
maintenance. Need to reallocate a pool for this volume.",
+                    pool.getUuid(), toBeCreated.getUuid(), 
vmProfile.getUuid());
+        }
+        return false;
+    }
+
+    private boolean canReusePool(VirtualMachineProfile vmProfile, 
DeploymentPlan plan,
+            Map<Volume, List<StoragePool>> suitableVolumeStoragePools, 
List<Volume> readyAndReusedVolumes,
+            VolumeVO toBeCreated, List<StoragePool> suitablePools, StoragePool 
pool) {
+        DataStore dataStore = dataStoreMgr.getPrimaryDataStore(pool.getId());
+
+        long exstPoolDcId = pool.getDataCenterId();
+        long exstPoolPodId = pool.getPodId() != null ? pool.getPodId() : -1;
+        long exstPoolClusterId = pool.getClusterId() != null ? 
pool.getClusterId() : -1;
+
+        if (plan.getDataCenterId() == exstPoolDcId && ((plan.getPodId() == 
exstPoolPodId && plan.getClusterId() == exstPoolClusterId) ||
+                (dataStore != null && dataStore.getScope() != null && 
dataStore.getScope().getScopeType() == ScopeType.ZONE))) {
+            logger.debug("Pool [{}] of volume [{}] used by VM [{}] fits the 
specified plan. No need to reallocate a pool for this volume.",
+                    pool.getUuid(), toBeCreated.getUuid(), 
vmProfile.getUuid());
+            suitablePools.add(pool);
+            suitableVolumeStoragePools.put(toBeCreated, suitablePools);
+            if (!(toBeCreated.getState() == Volume.State.Allocated || 
toBeCreated.getState() == Volume.State.Creating)) {
+                readyAndReusedVolumes.add(toBeCreated);
+            }
+            return true;
+        }
+
+        logger.debug("Pool [{}] of volume [{}] used by VM [{}] does not fit 
the specified plan. Need to reallocate a pool for this volume.",
+                pool.getUuid(), toBeCreated.getUuid(), vmProfile.getUuid());
+        return false;
+    }
+
     private void checkForPreferredStoragePool(List<StoragePool> suitablePools,
                                               VirtualMachine vm,
                                               Map<Volume, List<StoragePool>> 
suitableVolumeStoragePools,
@@ -1972,6 +2016,9 @@ StateListener<State, VirtualMachine.Event, 
VirtualMachine>, Configurable {
       return true;
     }
 
+    public static String logDeploymentWithoutException(VirtualMachine vm, 
DeploymentPlan plan, ExcludeList avoids, DeploymentPlanner planner) {
+        return LogUtils.logGsonWithoutException("Trying to deploy VM [%s] and 
details: Plan [%s]; avoid list [%s] and planner: [%s].", vm, plan, avoids, 
planner);
+    }
     @Override
     public ConfigKey<?>[] getConfigKeys() {
         return new ConfigKey<?>[] {allowRouterOnDisabledResource, 
allowAdminVmOnDisabledResource};
diff --git 
a/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java 
b/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java
index ea04a09cf92..3afd3dc4a95 100644
--- 
a/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java
+++ 
b/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java
@@ -252,7 +252,9 @@ public class DeploymentPlanningManagerImplTest {
         Mockito.when(template.isDeployAsIs()).thenReturn(false);
         
Mockito.when(templateDao.findById(Mockito.anyLong())).thenReturn(template);
 
-        VMInstanceVO vm = new VMInstanceVO();
+        VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+        Mockito.when(vm.getType()).thenReturn(Type.Instance);
+        Mockito.when(vm.getLastHostId()).thenReturn(null);
         Mockito.when(vmProfile.getVirtualMachine()).thenReturn(vm);
         Mockito.when(vmProfile.getId()).thenReturn(instanceId);
 

Reply via email to