diff --git a/api/src/com/cloud/api/commands/ListHostsCmd.java b/api/src/com/cloud/api/commands/ListHostsCmd.java index c84aecd13e2..c52df4cafc0 100644 --- a/api/src/com/cloud/api/commands/ListHostsCmd.java +++ b/api/src/com/cloud/api/commands/ListHostsCmd.java @@ -127,16 +127,16 @@ public class ListHostsCmd extends BaseListCmd { @Override public void execute(){ List result = new ArrayList(); - List hostIdsWithCapacity = new ArrayList(); + List hostsWithCapacity = new ArrayList(); if(getVirtualMachineId() != null){ UserVm userVm = _userVmService.getUserVm(getVirtualMachineId()); if (userVm == null) { throw new InvalidParameterValueException("Unable to find the VM by id=" + getVirtualMachineId()); } - Pair, List> hostsForMigration = _mgr.listHostsForMigrationOfVM(userVm, this.getStartIndex(), this.getPageSizeVal()); + Pair, List> hostsForMigration = _mgr.listHostsForMigrationOfVM(userVm, this.getStartIndex(), this.getPageSizeVal()); result = hostsForMigration.first(); - hostIdsWithCapacity = hostsForMigration.second(); + hostsWithCapacity = hostsForMigration.second(); }else{ result = _mgr.searchForServers(this); } @@ -145,11 +145,11 @@ public class ListHostsCmd extends BaseListCmd { List hostResponses = new ArrayList(); for (Host host : result) { HostResponse hostResponse = _responseGenerator.createHostResponse(host); - Boolean hasEnoughCapacity = false; - if(hostIdsWithCapacity.contains(host.getId())){ - hasEnoughCapacity = true; + Boolean suitableForMigration = false; + if(hostsWithCapacity.contains(host)){ + suitableForMigration = true; } - hostResponse.setHasEnoughCapacity(hasEnoughCapacity); + hostResponse.setSuitableForMigration(suitableForMigration); hostResponse.setObjectName("host"); hostResponses.add(hostResponse); } diff --git a/api/src/com/cloud/api/response/HostResponse.java b/api/src/com/cloud/api/response/HostResponse.java index 5d6b06a350d..c7526a11824 100755 --- a/api/src/com/cloud/api/response/HostResponse.java +++ b/api/src/com/cloud/api/response/HostResponse.java @@ -150,6 +150,9 @@ public class HostResponse extends BaseResponse { @SerializedName("hasEnoughCapacity") @Param(description="true if this host has enough CPU and RAM capacity to migrate a VM to it, false otherwise") private Boolean hasEnoughCapacity; + @SerializedName("suitableForMigration") @Param(description="true if this host is suitable(has enough capacity and satisfies all conditions like hosttags, max guests vm limit etc) to migrate a VM to it , false otherwise") + private Boolean suitableForMigration; + @SerializedName("allocationstate") @Param(description="the allocation state of the host") private String allocationState; @@ -485,6 +488,14 @@ public class HostResponse extends BaseResponse { public void setHasEnoughCapacity(Boolean hasEnoughCapacity) { this.hasEnoughCapacity = hasEnoughCapacity; } + + public Boolean isSuitableForMigration() { + return suitableForMigration; + } + + public void setSuitableForMigration(Boolean suitableForMigration) { + this.suitableForMigration = suitableForMigration; + } public String getAllocationState() { return allocationState; diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java index 123f56597a2..e81a6e437d4 100755 --- a/api/src/com/cloud/server/ManagementService.java +++ b/api/src/com/cloud/server/ManagementService.java @@ -501,13 +501,13 @@ public interface ManagementService { /** * List hosts for migrating the given VM. The API returns list of all hosts in the VM's cluster minus the current host and - * also a list of hostIds that seem to have enough CPU and RAM capacity to host this VM. + * also a list of hosts that seem to have enough CPU and RAM capacity to host this VM. * * @param UserVm * vm The VM to migrate - * @return Pair, List> List of all Hosts in VM's cluster and list of HostIds with enough capacity + * @return Pair, List> List of all Hosts in VM's cluster and list of Hosts with enough capacity */ - Pair, List> listHostsForMigrationOfVM(UserVm vm, Long startIndex, Long pageSize); + Pair, List> listHostsForMigrationOfVM(UserVm vm, Long startIndex, Long pageSize); String[] listEventTypes(); diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 2e4e93296d3..712b5e32ba3 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -4879,6 +4879,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe details.put("product_version", hr.softwareVersion.get("product_version")); if( hr.softwareVersion.get("product_version_text_short") != null ) { details.put("product_version_text_short", hr.softwareVersion.get("product_version_text_short")); + cmd.setHypervisorVersion(hr.softwareVersion.get("product_version_text_short")); + }else{ + cmd.setHypervisorVersion(hr.softwareVersion.get("product_version")); } if (_privateNetworkName != null) { details.put("private.network.device", _privateNetworkName); diff --git a/server/src/com/cloud/agent/manager/allocator/HostAllocator.java b/server/src/com/cloud/agent/manager/allocator/HostAllocator.java index 77828c0a1ad..1ee8a7dc765 100755 --- a/server/src/com/cloud/agent/manager/allocator/HostAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/HostAllocator.java @@ -18,6 +18,7 @@ package com.cloud.agent.manager.allocator; import java.util.List; + import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.host.Host; @@ -51,5 +52,23 @@ public interface HostAllocator extends Adapter { **/ public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo); + + /** + * Determines which physical hosts are suitable to + * allocate the guest virtual machines on + * + * @param VirtualMachineProfile vmProfile + * @param DeploymentPlan plan + * @param Type type + * @param ExcludeList avoid + * @param int returnUpTo (use -1 to return all possible hosts) + * @param boolean considerReservedCapacity (default should be true, set to false if host capacity calculation should not look at reserved capacity) + * @return List List of hosts that are suitable for VM allocation + **/ + + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity); + + + public static int RETURN_UPTO_ALL = -1; } diff --git a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java index 201a8fc4b90..b591dcb8ff3 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java @@ -82,11 +82,17 @@ public class FirstFitAllocator implements HostAllocator { protected String _allocationAlgorithm = "random"; @Inject CapacityManager _capacityMgr; + @Override public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) { - - long dcId = plan.getDataCenterId(); + return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true); + } + + @Override + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) { + + long dcId = plan.getDataCenterId(); Long podId = plan.getPodId(); Long clusterId = plan.getClusterId(); ServiceOffering offering = vmProfile.getServiceOffering(); @@ -150,10 +156,10 @@ public class FirstFitAllocator implements HostAllocator { } - return allocateTo(offering, template, avoid, clusterHosts, returnUpTo); + return allocateTo(offering, template, avoid, clusterHosts, returnUpTo, considerReservedCapacity); } - protected List allocateTo(ServiceOffering offering, VMTemplateVO template, ExcludeList avoid, List hosts, int returnUpTo) { + protected List allocateTo(ServiceOffering offering, VMTemplateVO template, ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity) { if (_allocationAlgorithm.equals("random")) { // Shuffle this so that we don't check the hosts in the same order. Collections.shuffle(hosts); @@ -208,7 +214,7 @@ public class FirstFitAllocator implements HostAllocator { boolean numCpusGood = host.getCpus().intValue() >= offering.getCpu(); int cpu_requested = offering.getCpu() * offering.getSpeed(); long ram_requested = offering.getRamSize() * 1024L * 1024L; - boolean hostHasCapacity = _capacityMgr.checkIfHostHasCapacity(host.getId(), cpu_requested, ram_requested, false, _factor); + boolean hostHasCapacity = _capacityMgr.checkIfHostHasCapacity(host.getId(), cpu_requested, ram_requested, false, _factor, considerReservedCapacity); if (numCpusGood && hostHasCapacity) { if (s_logger.isDebugEnabled()) { @@ -382,5 +388,4 @@ public class FirstFitAllocator implements HostAllocator { return true; } - } diff --git a/server/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java index f6a70d4bce8..72f889ec3de 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java @@ -21,22 +21,19 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Set; import javax.ejb.Local; import org.apache.log4j.Logger; -import com.cloud.host.HostVO; -import com.cloud.host.Host.Type; + import com.cloud.agent.manager.allocator.HostAllocator; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.HostPodVO; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.offering.ServiceOffering; -import com.cloud.storage.VMTemplateVO; import com.cloud.uservm.UserVm; import com.cloud.utils.component.ComponentLocator; import com.cloud.vm.VirtualMachine; @@ -50,7 +47,13 @@ public class RandomAllocator implements HostAllocator { @Override public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, - ExcludeList avoid, int returnUpTo) { + ExcludeList avoid, int returnUpTo) { + return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true); + } + + @Override + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) { long dcId = plan.getDataCenterId(); Long podId = plan.getPodId(); diff --git a/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java index 4b0f8e22287..02220ffd72e 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java @@ -49,7 +49,13 @@ public class TestingAllocator implements HostAllocator { @Override public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, - ExcludeList avoid, int returnUpTo) { + ExcludeList avoid, int returnUpTo) { + return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true); + } + + @Override + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) { List availableHosts = new ArrayList(); Host host = null; if (type == Host.Type.Routing && _routingHost != null) { diff --git a/server/src/com/cloud/capacity/CapacityManager.java b/server/src/com/cloud/capacity/CapacityManager.java index 0149599e19e..5edbd77d25b 100755 --- a/server/src/com/cloud/capacity/CapacityManager.java +++ b/server/src/com/cloud/capacity/CapacityManager.java @@ -32,7 +32,15 @@ public interface CapacityManager extends Manager { void allocateVmCapacity(VirtualMachine vm, boolean fromLastHost); - boolean checkIfHostHasCapacity(long hostId, Integer cpu, long ram, boolean checkFromReservedCapacity, float cpuOverprovisioningFactor); - + /** + * @param hostId Id of the host to check capacity + * @param cpu required CPU + * @param ram required RAM + * @param checkFromReservedCapacity set to true if ONLY reserved capacity of the host should be looked at + * @param cpuOverprovisioningFactor factor to apply to the actual host cpu + * @param considerReservedCapacity (default should be true, set to false if host capacity calculation should not look at reserved capacity at all) + */ + boolean checkIfHostHasCapacity(long hostId, Integer cpu, long ram, boolean checkFromReservedCapacity, float cpuOverprovisioningFactor, boolean considerReservedCapacity); + void updateCapacityForHost(HostVO host); } diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index c4e2bd767c9..31ec150d6c4 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -293,7 +293,7 @@ public class CapacityManagerImpl implements CapacityManager, StateListener _hostAllocators; - private static int RETURN_UPTO_ALL = -1; @Override public DeployDestination plan(VirtualMachineProfile vmProfile, @@ -144,7 +143,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { //search for storage under the zone, pod, cluster of the host. DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), hostIdSpecified, plan.getPoolId()); - Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, RETURN_UPTO_ALL); + Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL); Map> suitableVolumeStoragePools = result.first(); List readyAndReusedVolumes = result.second(); @@ -179,12 +178,12 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { s_logger.debug("The last host of this VM cannot be found"); }else{ if (host.getStatus() == Status.Up && host.getHostAllocationState() == Host.HostAllocationState.Enabled) { - if(_capacityMgr.checkIfHostHasCapacity(host.getId(), cpu_requested, ram_requested, true, cpuOverprovisioningFactor)){ + if(_capacityMgr.checkIfHostHasCapacity(host.getId(), cpu_requested, ram_requested, true, cpuOverprovisioningFactor, true)){ s_logger.debug("The last host of this VM is UP and has enough capacity"); s_logger.debug("Now checking for suitable pools under zone: "+host.getDataCenterId() +", pod: "+ host.getPodId()+", cluster: "+ host.getClusterId()); //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()); - Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, RETURN_UPTO_ALL); + Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL); Map> suitableVolumeStoragePools = result.first(); List readyAndReusedVolumes = result.second(); //choose the potential pool for this VM for this host @@ -362,7 +361,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { DataCenterDeployment potentialPlan = new DataCenterDeployment(plan.getDataCenterId(), clusterVO.getPodId(), clusterVO.getId(), null, plan.getPoolId()); //find suitable hosts under this cluster, need as many hosts as we get. - List suitableHosts = findSuitableHosts(vmProfile, potentialPlan, avoid, RETURN_UPTO_ALL); + List suitableHosts = findSuitableHosts(vmProfile, potentialPlan, avoid, HostAllocator.RETURN_UPTO_ALL); //if found suitable hosts in this cluster, find suitable storage pools for each volume of the VM if(suitableHosts != null && !suitableHosts.isEmpty()){ if (vmProfile.getHypervisorType() == HypervisorType.BareMetal) { @@ -374,7 +373,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { if (_allocationAlgorithm != null && _allocationAlgorithm.equalsIgnoreCase("random")) { Collections.shuffle(suitableHosts); } - Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, potentialPlan, avoid, RETURN_UPTO_ALL); + Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, potentialPlan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL); Map> suitableVolumeStoragePools = result.first(); List readyAndReusedVolumes = result.second(); diff --git a/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDaoImpl.java b/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDaoImpl.java index a277547c137..79d76fcf4e1 100644 --- a/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDaoImpl.java +++ b/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDaoImpl.java @@ -22,6 +22,9 @@ public class HypervisorCapabilitiesDaoImpl extends GenericDaoBase HypervisorTypeAndVersionSearch; protected final GenericSearchBuilder MaxGuestLimitByHypervisorSearch; + //we insert a record for each hypervisor type with version 'default' to ensure we dont face errors in case hypervisor version is missing or does not match. + private static final String DEFAULT_VERSION = "default"; + protected HypervisorCapabilitiesDaoImpl() { HypervisorTypeSearch = createSearchBuilder(); HypervisorTypeSearch.and("hypervisorType", HypervisorTypeSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ); @@ -58,15 +61,27 @@ public class HypervisorCapabilitiesDaoImpl extends GenericDaoBase sc = MaxGuestLimitByHypervisorSearch.create(); sc.setParameters("hypervisorType", hypervisorType); sc.setParameters("hypervisorVersion", hypervisorVersion); - result = customSearch(sc, null).get(0); + List limitList = customSearch(sc, null); + if(!limitList.isEmpty()){ + result = limitList.get(0); + }else{ + useDefault = true; + } }else{ - List capabilities = listAllByHypervisorType(hypervisorType); - if(!capabilities.isEmpty()){ - result = capabilities.get(0).getMaxGuestsLimit(); + useDefault = true; + } + if(useDefault){ + SearchCriteria sc = MaxGuestLimitByHypervisorSearch.create(); + sc.setParameters("hypervisorType", hypervisorType); + sc.setParameters("hypervisorVersion", DEFAULT_VERSION); + List limitList = customSearch(sc, null); + if(!limitList.isEmpty()){ + result = limitList.get(0); } } if(result == null){ diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 561469ef596..0ebae8c614a 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -59,6 +59,7 @@ import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeCommand; +import com.cloud.agent.manager.allocator.HostAllocator; import com.cloud.alert.Alert; import com.cloud.alert.AlertVO; import com.cloud.alert.dao.AlertDao; @@ -151,6 +152,8 @@ import com.cloud.dc.dao.DataCenterIpAddressDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.PodVlanMapDao; import com.cloud.dc.dao.VlanDao; +import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; @@ -266,6 +269,8 @@ import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VirtualMachineProfileImpl; import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.InstanceGroupDao; @@ -335,6 +340,7 @@ public class ManagementServerImpl implements ManagementServer { private final SSHKeyPairDao _sshKeyPairDao; private final LoadBalancerDao _loadbalancerDao; private final HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; + private final Adapters _hostAllocators; private final KeystoreManager _ksMgr; @@ -410,6 +416,11 @@ public class ManagementServerImpl implements ManagementServer { s_logger.error("Unable to find an user authenticator."); } + _hostAllocators = locator.getAdapters(HostAllocator.class); + if (_hostAllocators == null || !_hostAllocators.isSet()) { + s_logger.error("Unable to find HostAllocators"); + } + _templateMgr = locator.getManager(TemplateManager.class); String value = _configs.get("account.cleanup.interval"); @@ -1250,7 +1261,7 @@ public class ManagementServerImpl implements ManagementServer { } @Override - public Pair, List> listHostsForMigrationOfVM(UserVm vm, Long startIndex, Long pageSize) { + public Pair, List> listHostsForMigrationOfVM(UserVm vm, Long startIndex, Long pageSize) { // access check - only root admin can migrate VM Account caller = UserContext.current().getCaller(); if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { @@ -1302,25 +1313,36 @@ public class ManagementServerImpl implements ManagementServer { s_logger.debug("Other Hosts in this cluster: " + allHostsInCluster); } - int requiredCpu = svcOffering.getCpu() * svcOffering.getSpeed(); - long requiredRam = svcOffering.getRamSize() * 1024L * 1024L; - if (s_logger.isDebugEnabled()) { - s_logger.debug("Searching for hosts in cluster: " + cluster + " having required CPU: " + requiredCpu + " and RAM:" + requiredRam); + s_logger.debug("Calling HostAllocators to search for hosts in cluster: " + cluster + " having enough capacity and suitable for migration"); } - String opFactor = _configDao.getValue(Config.CPUOverprovisioningFactor.key()); - float cpuOverprovisioningFactor = NumbersUtil.parseFloat(opFactor, 1); - if (s_logger.isDebugEnabled()) { - s_logger.debug("CPUOverprovisioningFactor considered: " + cpuOverprovisioningFactor); - } - List hostsWithCapacity = _capacityDao.listHostsWithEnoughCapacity(requiredCpu, requiredRam, cluster, hostType.name(), cpuOverprovisioningFactor); + + List suitableHosts = new ArrayList(); + Enumeration enHost = _hostAllocators.enumeration(); + UserVmVO vmVO = (UserVmVO)vm; + VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vmVO); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Hosts having capacity: " + hostsWithCapacity); + DataCenterDeployment plan = new DataCenterDeployment(srcHost.getDataCenterId(), srcHost.getPodId(), srcHost.getClusterId(), null, null); + ExcludeList excludes = new ExcludeList(); + excludes.addHost(srcHostId); + while (enHost.hasMoreElements()) { + final HostAllocator allocator = enHost.nextElement(); + suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, HostAllocator.RETURN_UPTO_ALL, false); + if (suitableHosts != null && !suitableHosts.isEmpty()) { + break; + } } - return new Pair, List>(allHostsInCluster, hostsWithCapacity); + if(suitableHosts.isEmpty()){ + s_logger.debug("No suitable hosts found"); + }else{ + if (s_logger.isDebugEnabled()) { + s_logger.debug("Hosts having capacity and suitable for migration: " + suitableHosts); + } + } + + return new Pair, List>(allHostsInCluster, suitableHosts); } private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword, diff --git a/server/src/com/cloud/storage/allocator/StoragePoolAllocator.java b/server/src/com/cloud/storage/allocator/StoragePoolAllocator.java index 5b6f61db6cd..8d611cdf343 100644 --- a/server/src/com/cloud/storage/allocator/StoragePoolAllocator.java +++ b/server/src/com/cloud/storage/allocator/StoragePoolAllocator.java @@ -19,6 +19,7 @@ package com.cloud.storage.allocator; import java.util.List; import java.util.Set; + import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.host.Host; @@ -27,7 +28,6 @@ import com.cloud.template.VirtualMachineTemplate; import com.cloud.utils.component.Adapter; import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachineProfile; /** * Allocator for a disk. This determines which StoragePool should @@ -51,4 +51,6 @@ public interface StoragePoolAllocator extends Adapter { * @return List List of storage pools that are suitable for the VM **/ List allocateToPool(DiskProfile dskCh, VirtualMachineTemplate VMtemplate, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); + + public static int RETURN_UPTO_ALL = -1; } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 552fc246b4c..f5d8d3a19c9 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -218,7 +218,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene protected Adapters _planners; @Inject(adapter = HostAllocator.class) - protected Adapters _hostAllocators; + protected Adapters _hostAllocators; Map> _vmGurus = new HashMap>(); protected StateMachine2 _stateMachine; @@ -1122,7 +1122,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene if (s_logger.isDebugEnabled()) { s_logger.debug("VM is not Running, unable to migrate the vm " + vm); } - throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm); + throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString()); } short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;