Skip to content

Commit 42d16d9

Browse files
committed
Add BaseAllocator abstract class for duplicate code
1 parent 3284039 commit 42d16d9

File tree

7 files changed

+311
-343
lines changed

7 files changed

+311
-343
lines changed

api/src/main/java/com/cloud/deploy/DeploymentPlanner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public interface DeploymentPlanner extends Adapter {
7070
boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid);
7171

7272
public enum AllocationAlgorithm {
73-
random, firstfit, userdispersing, userconcentratedpod_random, userconcentratedpod_firstfit;
73+
random, firstfit, userdispersing, userconcentratedpod_random, userconcentratedpod_firstfit, firstfitleastconsumed
7474
}
7575

7676
public enum PlannerResourceUsage {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.cloud.agent.manager.allocator.impl;
2+
3+
import com.cloud.agent.manager.allocator.HostAllocator;
4+
import com.cloud.capacity.CapacityManager;
5+
import com.cloud.host.Host;
6+
import com.cloud.host.HostVO;
7+
import com.cloud.host.dao.HostDao;
8+
import com.cloud.offering.ServiceOffering;
9+
import com.cloud.utils.Pair;
10+
import com.cloud.utils.component.AdapterBase;
11+
import org.apache.commons.collections.CollectionUtils;
12+
13+
import javax.inject.Inject;
14+
import java.util.List;
15+
16+
public abstract class BaseAllocator extends AdapterBase implements HostAllocator {
17+
18+
@Inject
19+
protected HostDao hostDao;
20+
21+
@Inject
22+
protected CapacityManager capacityManager;
23+
24+
protected void retainHostsMatchingServiceOfferingAndTemplateTags(List<HostVO> availableHosts, Host.Type type, long dcId, Long podId, Long clusterId, String offeringHostTag, String templateTag) {
25+
logger.debug("Hosts {} will be checked for template and host tags compatibility.", availableHosts);
26+
27+
if (offeringHostTag != null) {
28+
logger.debug("Looking for hosts having the tag [{}] specified in the Service Offering.", offeringHostTag);
29+
List<HostVO> hostsWithHostTag = hostDao.listByHostTag(type, clusterId, podId, dcId, offeringHostTag);
30+
logger.debug("Retaining hosts {} because they match the offering host tag {}.", hostsWithHostTag, offeringHostTag);
31+
availableHosts.retainAll(hostsWithHostTag);
32+
}
33+
34+
if (templateTag != null) {
35+
logger.debug("Looking for hosts having the tag [{}] specified in the Template.", templateTag);
36+
List<HostVO> hostsWithTemplateTag = hostDao.listByHostTag(type, clusterId, podId, dcId, templateTag);
37+
logger.debug("Retaining hosts {} because they match the template tag {}.", hostsWithTemplateTag, templateTag);
38+
availableHosts.retainAll(hostsWithTemplateTag);
39+
}
40+
41+
logger.debug("Remaining hosts after template tag and host tags validations are {}.", availableHosts);
42+
}
43+
44+
protected void addHostsBasedOnTagRules(String hostTagOnOffering, List<HostVO> clusterHosts) {
45+
List<HostVO> hostsWithTagRules = hostDao.findHostsWithTagRuleThatMatchComputeOfferingTags(hostTagOnOffering);
46+
47+
if (CollectionUtils.isEmpty(hostsWithTagRules)) {
48+
logger.info("No hosts found with tag rules matching the compute offering tag [{}].", hostTagOnOffering);
49+
return;
50+
}
51+
52+
logger.info("Found hosts %s with tag rules matching the compute offering tag [{}].", hostsWithTagRules, hostTagOnOffering);
53+
clusterHosts.addAll(hostsWithTagRules);
54+
}
55+
56+
/**
57+
* Adds hosts with enough CPU capability and enough CPU capacity to the suitable hosts list.
58+
*/
59+
protected boolean hostHasCpuCapabilityAndCapacity(boolean considerReservedCapacity, ServiceOffering offering, Host host) {
60+
logger.debug("Looking for CPU frequency {} MHz and RAM {} MB.", () -> offering.getCpu() * offering.getSpeed(), offering::getRamSize);
61+
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = capacityManager.checkIfHostHasCpuCapabilityAndCapacity(host, offering, considerReservedCapacity);
62+
Boolean hasCpuCapability = cpuCapabilityAndCapacity.first();
63+
Boolean hasCpuCapacity = cpuCapabilityAndCapacity.second();
64+
65+
if (hasCpuCapability && hasCpuCapacity) {
66+
logger.debug("Host {} is a suitable host as it has enough CPU capability and CPU capacity.", () -> host);
67+
return true;
68+
}
69+
70+
logger.debug("Cannot use host {}. Does the host have CPU capability? {}. Does the host have CPU capacity? {}..", () -> host, () -> hasCpuCapability, () -> hasCpuCapacity);
71+
return false;
72+
}
73+
74+
}

server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java

Lines changed: 22 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@
2525
import javax.inject.Inject;
2626
import javax.naming.ConfigurationException;
2727

28+
import com.cloud.deploy.DeploymentPlanner.AllocationAlgorithm;
2829
import org.apache.cloudstack.api.ApiConstants;
2930
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
3031
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
3132
import org.apache.commons.collections.CollectionUtils;
33+
import org.apache.commons.lang3.EnumUtils;
3234
import org.apache.commons.lang3.ObjectUtils;
3335
import org.apache.commons.lang3.StringUtils;
3436
import org.springframework.stereotype.Component;
3537

36-
import com.cloud.agent.manager.allocator.HostAllocator;
37-
import com.cloud.capacity.CapacityManager;
3838
import com.cloud.capacity.CapacityVO;
3939
import com.cloud.capacity.dao.CapacityDao;
4040
import com.cloud.configuration.Config;
@@ -45,7 +45,6 @@
4545
import com.cloud.host.Host;
4646
import com.cloud.host.Host.Type;
4747
import com.cloud.host.HostVO;
48-
import com.cloud.host.dao.HostDao;
4948
import com.cloud.host.dao.HostDetailsDao;
5049
import com.cloud.offering.ServiceOffering;
5150
import com.cloud.resource.ResourceManager;
@@ -57,8 +56,6 @@
5756
import com.cloud.storage.dao.GuestOSCategoryDao;
5857
import com.cloud.storage.dao.GuestOSDao;
5958
import com.cloud.user.Account;
60-
import com.cloud.utils.Pair;
61-
import com.cloud.utils.component.AdapterBase;
6259
import com.cloud.vm.UserVmDetailVO;
6360
import com.cloud.vm.VirtualMachineProfile;
6461
import com.cloud.vm.dao.UserVmDetailsDao;
@@ -69,9 +66,7 @@
6966
* An allocator that tries to find a fit on a computing host. This allocator does not care whether or not the host supports routing.
7067
*/
7168
@Component
72-
public class FirstFitAllocator extends AdapterBase implements HostAllocator {
73-
@Inject
74-
protected HostDao _hostDao = null;
69+
public class FirstFitAllocator extends BaseAllocator {
7570
@Inject
7671
HostDetailsDao _hostDetailsDao = null;
7772
@Inject
@@ -87,14 +82,13 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
8782
@Inject
8883
ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
8984
@Inject
90-
CapacityManager _capacityMgr;
91-
@Inject
9285
CapacityDao _capacityDao;
9386
@Inject
9487
UserVmDetailsDao _userVmDetailsDao;
9588

9689
boolean _checkHvm = true;
97-
protected String _allocationAlgorithm = "random";
90+
91+
protected AllocationAlgorithm allocationAlgorithm = AllocationAlgorithm.random;
9892

9993

10094
@Override
@@ -146,11 +140,11 @@ protected List<HostVO> retrieveHosts(VirtualMachineProfile vmProfile, Type type,
146140
}
147141

148142
if (haVmTag != null) {
149-
clusterHosts.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, haVmTag));
143+
clusterHosts.retainAll(hostDao.listByHostTag(type, clusterId, podId, dcId, haVmTag));
150144
} else if (ObjectUtils.allNull(hostTagOnOffering, hostTagOnTemplate)) {
151145
clusterHosts.retainAll(_resourceMgr.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId));
152146
} else {
153-
retainHostsMatchingServiceOfferingAndTemplateTags(clusterHosts, hostTagOnTemplate, hostTagOnOffering, type, clusterId, podId, dcId);
147+
retainHostsMatchingServiceOfferingAndTemplateTags(clusterHosts, type, clusterId, podId, dcId, hostTagOnTemplate, hostTagOnOffering);
154148
}
155149

156150
filterHostsWithUefiEnabled(type, vmProfile, clusterId, podId, dcId, clusterHosts);
@@ -161,41 +155,11 @@ protected List<HostVO> retrieveHosts(VirtualMachineProfile vmProfile, Type type,
161155

162156
}
163157

164-
protected void addHostsBasedOnTagRules(String hostTagOnOffering, List<HostVO> clusterHosts) {
165-
List<HostVO> hostsWithTagRules = _hostDao.findHostsWithTagRuleThatMatchComputeOfferingTags(hostTagOnOffering);
166-
167-
if (CollectionUtils.isEmpty(hostsWithTagRules)) {
168-
logger.info("No hosts found with tag rules matching the compute offering tag [{}].", hostTagOnOffering);
169-
return;
170-
}
171-
172-
logger.info("Found hosts %s with tag rules matching the compute offering tag [{}].", hostsWithTagRules, hostTagOnOffering);
173-
clusterHosts.addAll(hostsWithTagRules);
174-
}
175-
176-
protected void retainHostsMatchingServiceOfferingAndTemplateTags(List<HostVO> clusterHosts, String hostTagOnTemplate, String hostTagOnOffering, Type type, Long clusterId,
177-
Long podId, long dcId) {
178-
boolean hasSvcOfferingTag = hostTagOnOffering != null;
179-
boolean hasTemplateTag = hostTagOnTemplate != null;
180-
181-
if (hasSvcOfferingTag) {
182-
logger.debug("Looking for hosts having the tag [{}] specified in the Service Offering.", hostTagOnOffering);
183-
clusterHosts.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnOffering));
184-
logger.debug("Hosts with Service Offering tag [{}] are {}.", hostTagOnOffering, clusterHosts);
185-
}
186-
187-
if (hasTemplateTag) {
188-
logger.debug("Looking for hosts having the tag [{}] specified in the Template.", hostTagOnTemplate);
189-
clusterHosts.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate));
190-
logger.debug("Hosts with Template tag [{}] are {}.", hostTagOnTemplate, clusterHosts);
191-
}
192-
}
193-
194158
/**
195159
* Add all hosts to the avoid set that were not considered during the allocation
196160
*/
197161
protected void addHostsToAvoidSet(Type type, ExcludeList avoid, Long clusterId, Long podId, long dcId, List<HostVO> suitableHosts) {
198-
List<HostVO> allHostsInCluster = _hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, null);
162+
List<HostVO> allHostsInCluster = hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, null);
199163

200164
allHostsInCluster.removeAll(suitableHosts);
201165

@@ -220,24 +184,24 @@ protected void filterHostsWithUefiEnabled(Type type, VirtualMachineProfile vmPro
220184

221185
logger.info("Guest VM is requested with Custom[UEFI] Boot Type enabled.");
222186

223-
List<HostVO> hostsMatchingUefiTag = _hostDao.listByHostCapability(type, clusterId, podId, dcId, Host.HOST_UEFI_ENABLE);
187+
List<HostVO> hostsMatchingUefiTag = hostDao.listByHostCapability(type, clusterId, podId, dcId, Host.HOST_UEFI_ENABLE);
224188

225189
logger.debug("Hosts with UEFI enabled are {}.", hostsMatchingUefiTag);
226190
clusterHosts.retainAll(hostsMatchingUefiTag);
227191
}
228192

229193
protected List<Host> allocateTo(DeploymentPlan plan, ServiceOffering offering, VMTemplateVO template, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
230194
boolean considerReservedCapacity, Account account) {
231-
switch (_allocationAlgorithm) {
232-
case "random":
233-
case "userconcentratedpod_random":
234-
// Shuffle this so that we don't check the hosts in the same order.
195+
196+
switch (allocationAlgorithm) {
197+
case random:
198+
case userconcentratedpod_random:
235199
Collections.shuffle(hosts);
236200
break;
237-
case "userdispersing":
201+
case userdispersing:
238202
hosts = reorderHostsByNumberOfVms(plan, hosts, account);
239203
break;
240-
case "firstfitleastconsumed":
204+
case firstfitleastconsumed:
241205
hosts = reorderHostsByCapacity(plan, hosts);
242206
break;
243207
}
@@ -252,7 +216,6 @@ protected List<Host> allocateTo(DeploymentPlan plan, ServiceOffering offering, V
252216
return suitableHosts;
253217
}
254218

255-
256219
protected List<Host> checkHostsCompatibilities(ServiceOffering offering, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo, boolean considerReservedCapacity) {
257220
List<Host> suitableHosts = new ArrayList<>();
258221
logger.debug("Checking compatibility for the following hosts {}.", suitableHosts);
@@ -268,7 +231,7 @@ protected List<Host> checkHostsCompatibilities(ServiceOffering offering, Exclude
268231
continue;
269232
}
270233

271-
if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) {
234+
if (capacityManager.checkIfHostReachMaxGuestLimit(host)) {
272235
logger.debug("Adding host [{}] to the avoid set because this host already has the max number of running (user and/or system) VMs.",
273236
() -> ReflectionToStringBuilderUtils.reflectOnlySelectedFields(host, "uuid", "name"));
274237
avoid.addHost(host.getId());
@@ -279,29 +242,13 @@ protected List<Host> checkHostsCompatibilities(ServiceOffering offering, Exclude
279242
continue;
280243
}
281244

282-
addHostToSuitableHostIfHasCpuCapacityAndCpuCapability(offering, avoid, considerReservedCapacity, host, suitableHosts);
283-
}
284-
return suitableHosts;
285-
}
286-
287-
288-
/**
289-
* Adds hosts with CPU capability and CPU capacity to the suitable hosts list. Otherwise, the host is added to the avoid list.
290-
*/
291-
protected void addHostToSuitableHostIfHasCpuCapacityAndCpuCapability(ServiceOffering offering, ExcludeList avoid, boolean considerReservedCapacity, Host host, List<Host> suitableHosts) {
292-
logger.debug("Looking for CPU frequency {} MHz and RAM {} MB.", () -> offering.getCpu() * offering.getSpeed(), () -> offering.getRamSize());
293-
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = _capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(host, offering, considerReservedCapacity);
294-
Boolean hasCpuCapability = cpuCapabilityAndCapacity.first();
295-
Boolean hasCpuCapacity = cpuCapabilityAndCapacity.second();
296-
297-
if (hasCpuCapability && hasCpuCapacity) {
298-
logger.debug("Found a suitable host, adding to list host [{}].", () -> ReflectionToStringBuilderUtils.reflectOnlySelectedFields(host, "uuid", "name"));
299-
suitableHosts.add(host);
300-
} else {
301-
logger.debug("Not using host {}; host has cpu capability? {}, host has capacity? {}.", () -> ReflectionToStringBuilderUtils.reflectOnlySelectedFields(host, "uuid",
302-
"name"), () -> hasCpuCapability, () -> hasCpuCapacity);
245+
if (hostHasCpuCapabilityAndCapacity(considerReservedCapacity,offering, host)) {
246+
suitableHosts.add(host);
247+
continue;
248+
}
303249
avoid.addHost(host.getId());
304250
}
251+
return suitableHosts;
305252
}
306253

307254
protected boolean offeringRequestedVGpuAndHostDoesNotHaveIt(ServiceOffering offering, ExcludeList avoid, Host host) {
@@ -557,7 +504,7 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
557504

558505
String allocationAlgorithm = configs.get("vm.allocation.algorithm");
559506
if (allocationAlgorithm != null) {
560-
_allocationAlgorithm = allocationAlgorithm;
507+
this.allocationAlgorithm = EnumUtils.getEnum(AllocationAlgorithm.class, allocationAlgorithm);
561508
}
562509
String value = configs.get("xenserver.check.hvm");
563510
_checkHvm = value == null || Boolean.parseBoolean(value);

0 commit comments

Comments
 (0)