mirror of https://github.com/apache/cloudstack.git
Bug 11200 - maximum number of guests per host
Changes: To make sure migration does not attempt to pick a host that has running VMs more than the max guest VM's limit: - Changed manual migration to call host allocators to return a list of hosts suitable for migration. Host allocators check for the max guest VM limit. - Earlier we returned hosts with enough capacity but now Host Allocators make other checks along with capacity. So the list of hosts returned are hosts that have enough capacity AND satisfy all other conditions like host tags, max guests limit etc. Or in other words Allocators dont return the hosts that dont satisfy all conditions even if they have capacity. -Therefore, now we mark the list of hosts returned for manual migration as 'suitable' hosts instead of 'hasenoughCapacity' in the HostResponse. - HA migration already calls allocators, so no change is needed there.
This commit is contained in:
parent
980c1cafd8
commit
4ad9ac5e71
|
|
@ -127,16 +127,16 @@ public class ListHostsCmd extends BaseListCmd {
|
|||
@Override
|
||||
public void execute(){
|
||||
List<? extends Host> result = new ArrayList<Host>();
|
||||
List<Long> hostIdsWithCapacity = new ArrayList<Long>();
|
||||
List<? extends Host> hostsWithCapacity = new ArrayList<Host>();
|
||||
|
||||
if(getVirtualMachineId() != null){
|
||||
UserVm userVm = _userVmService.getUserVm(getVirtualMachineId());
|
||||
if (userVm == null) {
|
||||
throw new InvalidParameterValueException("Unable to find the VM by id=" + getVirtualMachineId());
|
||||
}
|
||||
Pair<List<? extends Host>, List<Long>> hostsForMigration = _mgr.listHostsForMigrationOfVM(userVm, this.getStartIndex(), this.getPageSizeVal());
|
||||
Pair<List<? extends Host>, List<? extends Host>> 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<HostResponse> hostResponses = new ArrayList<HostResponse>();
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<? extends Host>, List<Long>> List of all Hosts in VM's cluster and list of HostIds with enough capacity
|
||||
* @return Pair<List<? extends Host>, List<? extends Host>> List of all Hosts in VM's cluster and list of Hosts with enough capacity
|
||||
*/
|
||||
Pair<List<? extends Host>, List<Long>> listHostsForMigrationOfVM(UserVm vm, Long startIndex, Long pageSize);
|
||||
Pair<List<? extends Host>, List<? extends Host>> listHostsForMigrationOfVM(UserVm vm, Long startIndex, Long pageSize);
|
||||
|
||||
String[] listEventTypes();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<Host> allocateTo(VirtualMachineProfile<?extends VirtualMachine> 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<Host> List of hosts that are suitable for VM allocation
|
||||
**/
|
||||
|
||||
public List<Host> allocateTo(VirtualMachineProfile<?extends VirtualMachine> vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity);
|
||||
|
||||
|
||||
public static int RETURN_UPTO_ALL = -1;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,11 +82,17 @@ public class FirstFitAllocator implements HostAllocator {
|
|||
protected String _allocationAlgorithm = "random";
|
||||
@Inject CapacityManager _capacityMgr;
|
||||
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, Type type,
|
||||
ExcludeList avoid, int returnUpTo) {
|
||||
|
||||
long dcId = plan.getDataCenterId();
|
||||
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile<? extends VirtualMachine> 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<Host> allocateTo(ServiceOffering offering, VMTemplateVO template, ExcludeList avoid, List<HostVO> hosts, int returnUpTo) {
|
||||
protected List<Host> allocateTo(ServiceOffering offering, VMTemplateVO template, ExcludeList avoid, List<HostVO> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Host> allocateTo(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, Type type,
|
||||
ExcludeList avoid, int returnUpTo) {
|
||||
ExcludeList avoid, int returnUpTo) {
|
||||
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, Type type,
|
||||
ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) {
|
||||
|
||||
long dcId = plan.getDataCenterId();
|
||||
Long podId = plan.getPodId();
|
||||
|
|
|
|||
|
|
@ -49,7 +49,13 @@ public class TestingAllocator implements HostAllocator {
|
|||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, Type type,
|
||||
ExcludeList avoid, int returnUpTo) {
|
||||
ExcludeList avoid, int returnUpTo) {
|
||||
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, Type type,
|
||||
ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) {
|
||||
List<Host> availableHosts = new ArrayList<Host>();
|
||||
Host host = null;
|
||||
if (type == Host.Type.Routing && _routingHost != null) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ public class CapacityManagerImpl implements CapacityManager, StateListener<State
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean checkIfHostHasCapacity(long hostId, Integer cpu, long ram, boolean checkFromReservedCapacity, float cpuOverprovisioningFactor) {
|
||||
public boolean checkIfHostHasCapacity(long hostId, Integer cpu, long ram, boolean checkFromReservedCapacity, float cpuOverprovisioningFactor, boolean considerReservedCapacity) {
|
||||
boolean hasCapacity = false;
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
|
|
@ -352,16 +352,27 @@ public class CapacityManagerImpl implements CapacityManager, StateListener<State
|
|||
failureReason = "Host does not have enough reserved CPU available";
|
||||
}
|
||||
} else {
|
||||
long freeCpu = totalCpu - (reservedCpu + usedCpu);
|
||||
long freeMem = totalMem - (reservedMem + usedMem);
|
||||
|
||||
long reservedCpuValueToUse = reservedCpu;
|
||||
long reservedMemValueToUse = reservedMem;
|
||||
|
||||
if(!considerReservedCapacity){
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("considerReservedCapacity is" + considerReservedCapacity + " , not considering reserved capacity for calculating free capacity");
|
||||
}
|
||||
reservedCpuValueToUse = 0;
|
||||
reservedMemValueToUse = 0;
|
||||
}
|
||||
long freeCpu = totalCpu - (reservedCpuValueToUse + usedCpu);
|
||||
long freeMem = totalMem - (reservedMemValueToUse + usedMem);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Free CPU: " + freeCpu + " , Requested CPU: " + cpu);
|
||||
s_logger.debug("Free RAM: " + freeMem + " , Requested RAM: " + ram);
|
||||
}
|
||||
/* alloc from free resource */
|
||||
if ((reservedCpu + usedCpu + cpu <= totalCpu)) {
|
||||
if ((reservedMem + usedMem + ram <= totalMem)) {
|
||||
if ((reservedCpuValueToUse + usedCpu + cpu <= totalCpu)) {
|
||||
if ((reservedMemValueToUse + usedMem + ram <= totalMem)) {
|
||||
hasCapacity = true;
|
||||
} else {
|
||||
failureReason = "Host does not have enough RAM available";
|
||||
|
|
@ -378,10 +389,10 @@ public class CapacityManagerImpl implements CapacityManager, StateListener<State
|
|||
|
||||
s_logger.debug("STATS: Can alloc CPU from host: " + hostId + ", used: " + usedCpu + ", reserved: " + reservedCpu + ", actual total: "
|
||||
+ actualTotalCpu + ", total with overprovisioning: " + totalCpu + "; requested cpu:" + cpu + ",alloc_from_last_host?:"
|
||||
+ checkFromReservedCapacity);
|
||||
+ checkFromReservedCapacity + " ,considerReservedCapacity?: "+considerReservedCapacity);
|
||||
|
||||
s_logger.debug("STATS: Can alloc MEM from host: " + hostId + ", used: " + usedMem + ", reserved: " + reservedMem + ", total: " + totalMem
|
||||
+ "; requested mem: " + ram + ",alloc_from_last_host?:" + checkFromReservedCapacity);
|
||||
+ "; requested mem: " + ram + ",alloc_from_last_host?:" + checkFromReservedCapacity+ " ,considerReservedCapacity?: "+considerReservedCapacity);
|
||||
} else {
|
||||
|
||||
if (checkFromReservedCapacity) {
|
||||
|
|
@ -390,7 +401,7 @@ public class CapacityManagerImpl implements CapacityManager, StateListener<State
|
|||
} else {
|
||||
s_logger.debug("STATS: Failed to alloc resource from host: " + hostId + " reservedCpu: " + reservedCpu + ", used cpu: " + usedCpu
|
||||
+ ", requested cpu: " + cpu + ", actual total cpu: " + actualTotalCpu + ", total cpu with overprovisioning: " + totalCpu
|
||||
+ ", reservedMem: " + reservedMem + ", used Mem: " + usedMem + ", requested mem: " + ram + ", total Mem:" + totalMem);
|
||||
+ ", reservedMem: " + reservedMem + ", used Mem: " + usedMem + ", requested mem: " + ram + ", total Mem:" + totalMem+ " ,considerReservedCapacity?: "+considerReservedCapacity);
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import com.cloud.dc.dao.ClusterDao;
|
|||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.exception.InsufficientServerCapacityException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
|
|
@ -48,7 +47,6 @@ import com.cloud.utils.component.Inject;
|
|||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.VirtualMachineProfileImpl;
|
||||
|
||||
@Local(value=DeploymentPlanner.class)
|
||||
public class BareMetalPlanner implements DeploymentPlanner {
|
||||
|
|
@ -118,7 +116,7 @@ public class BareMetalPlanner implements DeploymentPlanner {
|
|||
|
||||
for (HostVO h : hosts) {
|
||||
if (h.getStatus() == Status.Up) {
|
||||
if(_capacityMgr.checkIfHostHasCapacity(h.getId(), cpu_requested, ram_requested, false, cpuOverprovisioningFactor)){
|
||||
if(_capacityMgr.checkIfHostHasCapacity(h.getId(), cpu_requested, ram_requested, false, cpuOverprovisioningFactor, true)){
|
||||
s_logger.debug("Find host " + h.getId() + " has enough capacity");
|
||||
DataCenter dc = _dcDao.findById(h.getDataCenterId());
|
||||
Pod pod = _podDao.findById(h.getPodId());
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
|||
@Inject(adapter=HostAllocator.class)
|
||||
protected Adapters<HostAllocator> _hostAllocators;
|
||||
|
||||
private static int RETURN_UPTO_ALL = -1;
|
||||
|
||||
@Override
|
||||
public DeployDestination plan(VirtualMachineProfile<? extends VirtualMachine> 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<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, RETURN_UPTO_ALL);
|
||||
Pair<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL);
|
||||
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = result.first();
|
||||
List<Volume> 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<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, RETURN_UPTO_ALL);
|
||||
Pair<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, 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
|
||||
|
|
@ -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<Host> suitableHosts = findSuitableHosts(vmProfile, potentialPlan, avoid, RETURN_UPTO_ALL);
|
||||
List<Host> 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<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile, potentialPlan, avoid, RETURN_UPTO_ALL);
|
||||
Pair<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile, potentialPlan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL);
|
||||
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = result.first();
|
||||
List<Volume> readyAndReusedVolumes = result.second();
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ public class HypervisorCapabilitiesDaoImpl extends GenericDaoBase<HypervisorCapa
|
|||
protected final SearchBuilder<HypervisorCapabilitiesVO> HypervisorTypeAndVersionSearch;
|
||||
protected final GenericSearchBuilder<HypervisorCapabilitiesVO, Long> 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<HypervisorCapa
|
|||
public Long getMaxGuestsLimit(HypervisorType hypervisorType, String hypervisorVersion){
|
||||
Long defaultLimit = new Long(50);
|
||||
Long result = null;
|
||||
boolean useDefault = false;
|
||||
if(hypervisorVersion != null){
|
||||
SearchCriteria<Long> sc = MaxGuestLimitByHypervisorSearch.create();
|
||||
sc.setParameters("hypervisorType", hypervisorType);
|
||||
sc.setParameters("hypervisorVersion", hypervisorVersion);
|
||||
result = customSearch(sc, null).get(0);
|
||||
List<Long> limitList = customSearch(sc, null);
|
||||
if(!limitList.isEmpty()){
|
||||
result = limitList.get(0);
|
||||
}else{
|
||||
useDefault = true;
|
||||
}
|
||||
}else{
|
||||
List<HypervisorCapabilitiesVO> capabilities = listAllByHypervisorType(hypervisorType);
|
||||
if(!capabilities.isEmpty()){
|
||||
result = capabilities.get(0).getMaxGuestsLimit();
|
||||
useDefault = true;
|
||||
}
|
||||
if(useDefault){
|
||||
SearchCriteria<Long> sc = MaxGuestLimitByHypervisorSearch.create();
|
||||
sc.setParameters("hypervisorType", hypervisorType);
|
||||
sc.setParameters("hypervisorVersion", DEFAULT_VERSION);
|
||||
List<Long> limitList = customSearch(sc, null);
|
||||
if(!limitList.isEmpty()){
|
||||
result = limitList.get(0);
|
||||
}
|
||||
}
|
||||
if(result == null){
|
||||
|
|
|
|||
|
|
@ -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<HostAllocator> _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<? extends Host>, List<Long>> listHostsForMigrationOfVM(UserVm vm, Long startIndex, Long pageSize) {
|
||||
public Pair<List<? extends Host>, List<? extends Host>> 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<Long> hostsWithCapacity = _capacityDao.listHostsWithEnoughCapacity(requiredCpu, requiredRam, cluster, hostType.name(), cpuOverprovisioningFactor);
|
||||
|
||||
List<Host> suitableHosts = new ArrayList<Host>();
|
||||
Enumeration<HostAllocator> enHost = _hostAllocators.enumeration();
|
||||
UserVmVO vmVO = (UserVmVO)vm;
|
||||
VirtualMachineProfile<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(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<? extends Host>, List<Long>>(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<? extends Host>, List<? extends Host>>(allHostsInCluster, suitableHosts);
|
||||
}
|
||||
|
||||
private List<HostVO> searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword,
|
||||
|
|
|
|||
|
|
@ -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<StoragePool> List of storage pools that are suitable for the VM
|
||||
**/
|
||||
List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineTemplate VMtemplate, DeploymentPlan plan, ExcludeList avoid, int returnUpTo);
|
||||
|
||||
public static int RETURN_UPTO_ALL = -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
|
|||
protected Adapters<DeploymentPlanner> _planners;
|
||||
|
||||
@Inject(adapter = HostAllocator.class)
|
||||
protected Adapters<HostAllocator> _hostAllocators;
|
||||
protected Adapters<HostAllocator> _hostAllocators;
|
||||
|
||||
Map<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>> _vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>>();
|
||||
protected StateMachine2<State, VirtualMachine.Event, VirtualMachine> _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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue