Skip to content

Commit f30b4bb

Browse files
committed
Break into smaller methods random and firfit allocators.
1 parent 10d602f commit f30b4bb

File tree

9 files changed

+205
-372
lines changed

9 files changed

+205
-372
lines changed

api/src/main/java/com/cloud/agent/manager/allocator/HostAllocator.java

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,11 @@
2222
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
2323
import com.cloud.host.Host;
2424
import com.cloud.host.Host.Type;
25-
import com.cloud.offering.ServiceOffering;
2625
import com.cloud.utils.component.Adapter;
27-
import com.cloud.vm.VirtualMachine;
2826
import com.cloud.vm.VirtualMachineProfile;
2927

3028
public interface HostAllocator extends Adapter {
3129

32-
/**
33-
* @param UserVm vm
34-
* @param ServiceOffering offering
35-
**/
36-
boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering);
37-
3830
/**
3931
* Determines which physical hosts are suitable to
4032
* allocate the guest virtual machines on
@@ -49,31 +41,6 @@ public interface HostAllocator extends Adapter {
4941

5042
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo);
5143

52-
/**
53-
* Determines which physical hosts are suitable to allocate the guest
54-
* virtual machines on
55-
*
56-
* Allocators must set any other hosts not considered for allocation in the
57-
* ExcludeList avoid. Thus the avoid set and the list of hosts suitable,
58-
* together must cover the entire host set in the cluster.
59-
*
60-
* @param VirtualMachineProfile
61-
* vmProfile
62-
* @param DeploymentPlan
63-
* plan
64-
* @param GuestType
65-
* type
66-
* @param ExcludeList
67-
* avoid
68-
* @param int returnUpTo (use -1 to return all possible hosts)
69-
* @param boolean considerReservedCapacity (default should be true, set to
70-
* false if host capacity calculation should not look at reserved
71-
* capacity)
72-
* @return List<Host> List of hosts that are suitable for VM allocation
73-
**/
74-
75-
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity);
76-
7744
/**
7845
* Determines which physical hosts are suitable to allocate the guest
7946
* virtual machines on

api/src/main/java/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public void execute() {
7878
for (Host host : result.first()) {
7979
HostForMigrationResponse hostResponse = _responseGenerator.createHostForMigrationResponse(host);
8080
Boolean suitableForMigration = false;
81-
if (hostsWithCapacity.contains(host)) {
81+
if (hostsWithCapacity != null && hostsWithCapacity.contains(host)) {
8282
suitableForMigration = true;
8383
}
8484
hostResponse.setSuitableForMigration(suitableForMigration);

api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ protected ListResponse<HostResponse> getHostResponses() {
212212
for (Host host : result.first()) {
213213
HostResponse hostResponse = _responseGenerator.createHostResponse(host, getDetails());
214214
Boolean suitableForMigration = false;
215-
if (hostsWithCapacity.contains(host)) {
215+
if (hostsWithCapacity != null && hostsWithCapacity.contains(host)) {
216216
suitableForMigration = true;
217217
}
218218
hostResponse.setSuitableForMigration(suitableForMigration);

engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,6 @@ void orchestrateStart(String vmUuid, Map<VirtualMachineProfile.Param, Object> pa
157157
void advanceReboot(String vmUuid, Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException,
158158
ConcurrentOperationException, OperationTimedoutException;
159159

160-
/**
161-
* Check to see if a virtual machine can be upgraded to the given service offering
162-
*
163-
* @param vm
164-
* @param offering
165-
* @return true if the host can handle the upgrade, false otherwise
166-
*/
167-
boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering);
168-
169160
VirtualMachine findById(long vmId);
170161

171162
void storageMigration(String vmUuid, Map<Long, Long> volumeToPool);

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3519,19 +3519,6 @@ protected void runInContext() {
35193519
}
35203520
}
35213521

3522-
@Override
3523-
public boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering) {
3524-
boolean isMachineUpgradable = true;
3525-
for (final HostAllocator allocator : hostAllocators) {
3526-
isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
3527-
if (!isMachineUpgradable) {
3528-
break;
3529-
}
3530-
}
3531-
3532-
return isMachineUpgradable;
3533-
}
3534-
35353522
@Override
35363523
public void reboot(final String vmUuid, final Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException {
35373524
try {
@@ -3912,11 +3899,6 @@ public void checkIfCanUpgrade(final VirtualMachine vmInstance, final ServiceOffe
39123899
throw new InvalidParameterValueException("isSystem property is different for current service offering and new service offering");
39133900
}
39143901

3915-
if (!isVirtualMachineUpgradable(vmInstance, newServiceOffering)) {
3916-
throw new InvalidParameterValueException("Unable to upgrade virtual machine, not enough resources available " + "for an offering of " +
3917-
newServiceOffering.getCpu() + " cpu(s) at " + newServiceOffering.getSpeed() + " Mhz, and " + newServiceOffering.getRamSize() + " MB of memory");
3918-
}
3919-
39203902
final List<String> currentTags = StringUtils.csvTagsToList(currentDiskOffering.getTags());
39213903
final List<String> newTags = StringUtils.csvTagsToList(newDiskOffering.getTags());
39223904
if (VolumeApiServiceImpl.MatchStoragePoolTagsWithDiskOffering.valueIn(vmInstance.getDataCenterId())) {

plugins/host-allocators/random/src/main/java/com/cloud/agent/manager/allocator/impl/RandomAllocator.java

Lines changed: 91 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,10 @@
2525
import org.apache.commons.collections.CollectionUtils;
2626
import org.apache.commons.collections.ListUtils;
2727
import org.apache.commons.lang3.ObjectUtils;
28-
import org.apache.commons.lang3.StringUtils;
2928
import org.springframework.stereotype.Component;
3029

3130
import com.cloud.agent.manager.allocator.HostAllocator;
3231
import com.cloud.capacity.CapacityManager;
33-
import com.cloud.dc.ClusterDetailsDao;
34-
import com.cloud.dc.dao.ClusterDao;
3532
import com.cloud.deploy.DeploymentPlan;
3633
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
3734
import com.cloud.host.Host;
@@ -43,7 +40,6 @@
4340
import com.cloud.storage.VMTemplateVO;
4441
import com.cloud.utils.Pair;
4542
import com.cloud.utils.component.AdapterBase;
46-
import com.cloud.vm.VirtualMachine;
4743
import com.cloud.vm.VirtualMachineProfile;
4844

4945
@Component
@@ -53,142 +49,133 @@ public class RandomAllocator extends AdapterBase implements HostAllocator {
5349
@Inject
5450
private ResourceManager _resourceMgr;
5551
@Inject
56-
private ClusterDao clusterDao;
57-
@Inject
58-
private ClusterDetailsDao clusterDetailsDao;
59-
@Inject
6052
private CapacityManager capacityManager;
6153

62-
protected List<HostVO> listHostsByTags(Host.Type type, long dcId, Long podId, Long clusterId, String offeringHostTag, String templateTag) {
63-
List<HostVO> taggedHosts = new ArrayList<>();
64-
if (offeringHostTag != null) {
65-
taggedHosts.addAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, offeringHostTag));
66-
}
67-
if (templateTag != null) {
68-
List<HostVO> templateTaggedHosts = _hostDao.listByHostTag(type, clusterId, podId, dcId, templateTag);
69-
if (taggedHosts.isEmpty()) {
70-
taggedHosts = templateTaggedHosts;
71-
} else {
72-
taggedHosts.retainAll(templateTaggedHosts);
73-
}
74-
}
75-
if (logger.isDebugEnabled()) {
76-
logger.debug(String.format("Found %d hosts %s with type: %s, zone ID: %d, pod ID: %d, cluster ID: %s, offering host tag(s): %s, template tag: %s",
77-
taggedHosts.size(),
78-
(taggedHosts.isEmpty() ? "" : String.format("(%s)", StringUtils.join(taggedHosts.stream().map(HostVO::getId).toArray(), ","))),
79-
type.name(), dcId, podId, clusterId, offeringHostTag, templateTag));
80-
}
81-
return taggedHosts;
82-
}
83-
private List<Host> findSuitableHosts(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type,
84-
ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
54+
protected List<Host> findSuitableHosts(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
8555
boolean considerReservedCapacity) {
56+
if (type == Host.Type.Storage) {
57+
return null;
58+
}
59+
8660
long dcId = plan.getDataCenterId();
8761
Long podId = plan.getPodId();
8862
Long clusterId = plan.getClusterId();
8963
ServiceOffering offering = vmProfile.getServiceOffering();
90-
List<? extends Host> hostsCopy = null;
91-
List<Host> suitableHosts = new ArrayList<>();
9264

93-
if (type == Host.Type.Storage) {
94-
return suitableHosts;
95-
}
9665
String offeringHostTag = offering.getHostTag();
97-
VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate();
98-
String templateTag = template.getTemplateTag();
99-
String hostTag = null;
100-
if (ObjectUtils.anyNull(offeringHostTag, templateTag)) {
101-
hostTag = offeringHostTag;
102-
hostTag = hostTag == null ? templateTag : String.format("%s, %s", hostTag, templateTag);
103-
logger.debug(String.format("Looking for hosts in dc [%s], pod [%s], cluster [%s] and complying with host tag(s): [%s]", dcId, podId, clusterId, hostTag));
104-
} else {
105-
logger.debug("Looking for hosts in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId);
106-
}
107-
if (hosts != null) {
108-
// retain all computing hosts, regardless of whether they support routing...it's random after all
109-
hostsCopy = new ArrayList<>(hosts);
110-
if (ObjectUtils.anyNotNull(offeringHostTag, templateTag)) {
111-
hostsCopy.retainAll(listHostsByTags(type, dcId, podId, clusterId, offeringHostTag, templateTag));
112-
} else {
113-
hostsCopy.retainAll(_hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId));
114-
}
115-
} else {
116-
// list all computing hosts, regardless of whether they support routing...it's random after all
117-
if (offeringHostTag != null) {
118-
hostsCopy = listHostsByTags(type, dcId, podId, clusterId, offeringHostTag, templateTag);
119-
} else {
120-
hostsCopy = _hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId);
121-
}
122-
}
123-
hostsCopy = ListUtils.union(hostsCopy, _hostDao.findHostsWithTagRuleThatMatchComputeOfferingTags(hostTag));
66+
VMTemplateVO template = (VMTemplateVO) vmProfile.getTemplate();
67+
logger.debug("Looking for hosts in zone [{}], pod [{}], cluster [{}].", dcId, podId, clusterId);
68+
69+
List<? extends Host> availableHosts = retrieveHosts(type, (List<HostVO>) hosts, template, offeringHostTag, clusterId, podId, dcId);
12470

125-
if (hostsCopy.isEmpty()) {
126-
logger.info("No suitable host found for VM [{}] in {}.", vmProfile, hostTag);
71+
if (availableHosts.isEmpty()) {
72+
logger.info("No suitable host found for VM [{}] in zone [{}], pod [{}], cluster [{}].", vmProfile, dcId, podId, clusterId);
12773
return null;
12874
}
12975

130-
logger.debug("Random Allocator found {} hosts", hostsCopy.size());
131-
if (hostsCopy.isEmpty()) {
132-
return suitableHosts;
133-
}
76+
return filterAvailableHosts(avoid, returnUpTo, considerReservedCapacity, availableHosts, offering);
77+
}
13478

135-
Collections.shuffle(hostsCopy);
136-
for (Host host : hostsCopy) {
79+
protected List<Host> filterAvailableHosts(ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity, List<? extends Host> availableHosts, ServiceOffering offering) {
80+
logger.debug("Random Allocator found [{}] available hosts. They will be checked if they are in the avoid set and for CPU capability and capacity.", availableHosts::size);
81+
List<Host> suitableHosts = new ArrayList<>();
82+
83+
Collections.shuffle(availableHosts);
84+
for (Host host : availableHosts) {
13785
if (suitableHosts.size() == returnUpTo) {
13886
break;
13987
}
88+
14089
if (avoid.shouldAvoid(host)) {
141-
if (logger.isDebugEnabled()) {
142-
logger.debug("Host name: " + host.getName() + ", hostId: " + host.getId() + " is in avoid set, skipping this and trying other available hosts");
143-
}
90+
logger.debug("Host [{}] is in the avoid set, skipping it and trying other available hosts.", () -> host);
14491
continue;
14592
}
146-
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = capacityManager.checkIfHostHasCpuCapabilityAndCapacity(host, offering, considerReservedCapacity);
147-
if (!cpuCapabilityAndCapacity.first() || !cpuCapabilityAndCapacity.second()) {
148-
if (logger.isDebugEnabled()) {
149-
logger.debug("Not using host " + host.getId() + "; host has cpu capability? " + cpuCapabilityAndCapacity.first() + ", host has capacity?" + cpuCapabilityAndCapacity.second());
150-
}
93+
94+
if (!hostHasCpuCapabilityAndCapacity(considerReservedCapacity, offering, host)) {
15195
continue;
15296
}
153-
if (logger.isDebugEnabled()) {
154-
logger.debug("Found a suitable host, adding to list: " + host.getId());
155-
}
97+
98+
logger.debug("Found the suitable host [{}], adding to list.", () -> host);
15699
suitableHosts.add(host);
157100
}
158-
if (logger.isDebugEnabled()) {
159-
logger.debug("Random Host Allocator returning " + suitableHosts.size() + " suitable hosts");
160-
}
101+
102+
logger.debug("Random Host Allocator returning {} suitable hosts.", suitableHosts::size);
161103
return suitableHosts;
162104
}
163105

106+
107+
protected boolean hostHasCpuCapabilityAndCapacity(boolean considerReservedCapacity, ServiceOffering offering, Host host) {
108+
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = capacityManager.checkIfHostHasCpuCapabilityAndCapacity(host, offering, considerReservedCapacity);
109+
Boolean hasCpuCapability = cpuCapabilityAndCapacity.first();
110+
Boolean hasCpuCapacity = cpuCapabilityAndCapacity.second();
111+
112+
if (hasCpuCapability && hasCpuCapacity) {
113+
logger.debug("Host {} has enough CPU capability and CPU capacity.", host);
114+
return true;
115+
}
116+
117+
logger.debug("Not using host [{}]. Does the host have cpu capability? {}. Does the host have capacity? {}.", () -> host, () -> hasCpuCapability, () -> hasCpuCapacity);
118+
return false;
119+
}
120+
121+
/**
122+
* @return all computing hosts, regardless of whether they support routing.
123+
*/
124+
protected List<HostVO> retrieveHosts(Type type, List<HostVO> hosts, VMTemplateVO template, String offeringHostTag, Long clusterId, Long podId, long dcId) {
125+
List<HostVO> availableHosts;
126+
String templateTag = template.getTemplateTag();
127+
128+
if (CollectionUtils.isNotEmpty(hosts)) {
129+
availableHosts = new ArrayList<>(hosts);
130+
} else {
131+
availableHosts = _resourceMgr.listAllUpAndEnabledHosts(type, clusterId, podId, dcId);
132+
}
133+
134+
if (ObjectUtils.anyNotNull(offeringHostTag, templateTag)) {
135+
retainHostsWithMatchingTags(availableHosts, type, clusterId, podId, dcId, offeringHostTag, templateTag);
136+
} else {
137+
List<HostVO> hostsWithNoRuleTag = _hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId);
138+
logger.debug("Retaining hosts {} because they do not have rule tags.", hostsWithNoRuleTag);
139+
availableHosts.retainAll(hostsWithNoRuleTag);
140+
}
141+
142+
List<HostVO> hostsWithTagRuleThatMatchComputeOfferingTags = _hostDao.findHostsWithTagRuleThatMatchComputeOfferingTags(offeringHostTag);
143+
logger.debug("Adding hosts {} to the available pool hosts because they match the compute offering's tag.", hostsWithTagRuleThatMatchComputeOfferingTags, offeringHostTag);
144+
availableHosts = ListUtils.union(availableHosts, hostsWithTagRuleThatMatchComputeOfferingTags);
145+
146+
return availableHosts;
147+
}
148+
149+
protected void retainHostsWithMatchingTags(List<HostVO> availableHosts, Type type, long dcId, Long podId, Long clusterId, String offeringHostTag, String templateTag) {
150+
logger.debug("Hosts {} will be checked for template and host tags compatibility.", availableHosts);
151+
152+
if (offeringHostTag != null) {
153+
List<HostVO> hostsWithHostTag = _hostDao.listByHostTag(type, clusterId, podId, dcId, offeringHostTag);
154+
logger.debug("Retaining hosts {} because they match the offering host tag {}.", hostsWithHostTag, offeringHostTag);
155+
availableHosts.retainAll(hostsWithHostTag);
156+
}
157+
158+
if (templateTag != null) {
159+
List<HostVO> hostsWithTemplateTag = _hostDao.listByHostTag(type, clusterId, podId, dcId, templateTag);
160+
logger.debug("Retaining hosts {} because they match the template tag {}.", hostsWithTemplateTag, offeringHostTag);
161+
availableHosts.retainAll(hostsWithTemplateTag);
162+
}
163+
164+
logger.debug("Remaining hosts after template tag and host tags validations are {}.", availableHosts);
165+
}
166+
164167
@Override
165168
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) {
166-
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true);
169+
return allocateTo(vmProfile, plan, type, avoid, null, returnUpTo, true);
167170
}
168171

169172
@Override
170-
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type,
171-
ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
173+
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
172174
boolean considerReservedCapacity) {
173175
if (CollectionUtils.isEmpty(hosts)) {
174-
if (logger.isDebugEnabled()) {
175-
logger.debug("Random Allocator found 0 hosts as given host list is empty");
176-
}
176+
logger.debug("Random Allocator found 0 hosts as given host list is empty");
177177
return new ArrayList<>();
178178
}
179179
return findSuitableHosts(vmProfile, plan, type, avoid, hosts, returnUpTo, considerReservedCapacity);
180180
}
181-
182-
@Override
183-
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan,
184-
Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) {
185-
return findSuitableHosts(vmProfile, plan, type, avoid, null, returnUpTo, considerReservedCapacity);
186-
}
187-
188-
@Override
189-
public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
190-
// currently we do no special checks to rule out a VM being upgradable to an offering, so
191-
// return true
192-
return true;
193-
}
194181
}

0 commit comments

Comments
 (0)