Skip to content

Commit fc78948

Browse files
committed
Guest OS rules
1 parent cbc1ae7 commit fc78948

27 files changed

Lines changed: 325 additions & 94 deletions

File tree

api/src/main/java/com/cloud/host/Host.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public static String[] toStrings(Host.Type... types) {
6363
String HOST_OVFTOOL_VERSION = "host.ovftool.version";
6464
String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
6565
String HOST_SSH_PORT = "host.ssh.port";
66+
String GUEST_OS_CATEGORY_ID = "guest.os.category.id";
67+
String GUEST_OS_RULE = "guest.os.rule";
6668

6769
int DEFAULT_SSH_PORT = 22;
6870

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ public class ApiConstants {
442442
public static final String MAX_VGPU_PER_PHYSICAL_GPU = "maxvgpuperphysicalgpu";
443443
public static final String GUEST_OS_LIST = "guestoslist";
444444
public static final String GUEST_OS_COUNT = "guestoscount";
445+
public static final String GUEST_OS_RULE = "guestosrule";
445446
public static final String OS_MAPPING_CHECK_ENABLED = "osmappingcheckenabled";
446447
public static final String OUTOFBANDMANAGEMENT_POWERSTATE = "outofbandmanagementpowerstate";
447448
public static final String OUTOFBANDMANAGEMENT_ENABLED = "outofbandmanagementenabled";

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,14 @@ public class UpdateHostCmd extends BaseCmd {
4949
@Parameter(name = ApiConstants.OS_CATEGORY_ID,
5050
type = CommandType.UUID,
5151
entityType = GuestOSCategoryResponse.class,
52-
description = "The ID of OS category to update the host with")
52+
description = "the ID of OS category used to prioritize VMs with mathing OS category during the allocation process. " +
53+
"It cannot be used alongside the 'guestosrule' parameter.")
5354
private Long osCategoryId;
5455

56+
@Parameter(name = ApiConstants.GUEST_OS_RULE, type = CommandType.STRING, description = "the guest OS rule written in JavaScript to match with the OS of the VM." +
57+
"It cannot be used alongside the 'oscategoryid' parameter.")
58+
private String guestOsRule;
59+
5560
@Parameter(name = ApiConstants.ALLOCATION_STATE,
5661
type = CommandType.STRING,
5762
description = "Change resource state of host, valid values are [Enable, Disable]. Operation may failed if host in states not allowing Enable/Disable")
@@ -96,6 +101,10 @@ public Long getOsCategoryId() {
96101
return osCategoryId;
97102
}
98103

104+
public String getGuestOsRule() {
105+
return guestOsRule;
106+
}
107+
99108
public String getAllocationState() {
100109
return allocationState;
101110
}

api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ public class HostResponse extends BaseResponseWithAnnotations {
6363
@Param(description = "The OS category name of the host")
6464
private String osCategoryName;
6565

66+
@SerializedName(ApiConstants.GUEST_OS_RULE)
67+
@Param(description = "the guest OS rule")
68+
private String guestOsRule;
69+
6670
@SerializedName(ApiConstants.IP_ADDRESS)
6771
@Param(description = "The IP address of the host")
6872
private String ipAddress;
@@ -999,4 +1003,12 @@ public void setExtensionName(String extensionName) {
9991003
public String getExtensionName() {
10001004
return extensionName;
10011005
}
1006+
1007+
public String getGuestOsRule() {
1008+
return guestOsRule;
1009+
}
1010+
1011+
public void setGuestOsRule(String guestOsRule) {
1012+
this.guestOsRule = guestOsRule;
1013+
}
10021014
}

engine/schema/src/main/java/com/cloud/host/HostVO.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import com.cloud.cpu.CPU;
4646
import org.apache.cloudstack.util.CPUArchConverter;
4747
import org.apache.cloudstack.util.HypervisorTypeConverter;
48-
import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
48+
import org.apache.cloudstack.utils.jsinterpreter.GenericRuleHelper;
4949
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
5050
import org.apache.commons.collections.CollectionUtils;
5151
import org.apache.commons.lang.BooleanUtils;
@@ -856,7 +856,7 @@ public boolean checkHostServiceOfferingTags(ServiceOffering serviceOffering) {
856856
}
857857

858858
if (BooleanUtils.isTrue(this.getIsTagARule())) {
859-
return TagAsRuleHelper.interpretTagAsRule(this.getHostTags().get(0), serviceOffering.getHostTag(), HostTagsDao.hostTagRuleExecutionTimeout.value());
859+
return GenericRuleHelper.interpretTagAsRule(this.getHostTags().get(0), serviceOffering.getHostTag(), HostTagsDao.hostTagRuleExecutionTimeout.value());
860860
}
861861

862862
if (StringUtils.isEmpty(serviceOffering.getHostTag())) {

engine/schema/src/main/java/com/cloud/host/dao/HostDao.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,17 @@
3232
import com.cloud.utils.db.GenericDao;
3333
import com.cloud.utils.fsm.StateDao;
3434
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
35+
import org.apache.cloudstack.framework.config.ConfigKey;
3536

3637
/**
3738
* Data Access Object for server
3839
*
3940
*/
4041
public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Status.Event, Host> {
42+
43+
ConfigKey<Long> guestOsRuleExecutionTimeout = new ConfigKey<>("Advanced", Long.class, "guest.os.rule.execution.timeout", "3000", "The maximum runtime, in milliseconds, " +
44+
"to execute a guest OS rule; if it is reached, a timeout will happen.", true);
45+
4146
long countBy(long clusterId, ResourceState... states);
4247

4348
Integer countAllByType(final Host.Type type);
@@ -220,6 +225,8 @@ int countHostsByMsResourceStateTypeAndHypervisorType(long msId, List<ResourceSta
220225

221226
List<HostVO> findHostsWithTagRuleThatMatchComputeOfferingTags(String computeOfferingTags);
222227

228+
List<HostVO> findHostsWithGuestOsRulesThatDidNotMatchOsOfGuestVm(String templateGuestOSName);
229+
223230
List<Long> findClustersThatMatchHostTagRule(String computeOfferingTags);
224231

225232
List<Long> listSsvmHostsWithPendingMigrateJobsOrderedByJobCount();

engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@
3737

3838
import com.cloud.vm.VirtualMachine;
3939
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
40-
import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
40+
import org.apache.cloudstack.framework.config.ConfigKey;
41+
import org.apache.cloudstack.framework.config.Configurable;
42+
import org.apache.cloudstack.utils.jsinterpreter.GenericRuleHelper;
4143
import org.apache.commons.collections.CollectionUtils;
4244

4345
import com.cloud.agent.api.VgpuTypesInfo;
@@ -84,7 +86,7 @@
8486

8587
@DB
8688
@TableGenerator(name = "host_req_sq", table = "op_host", pkColumnName = "id", valueColumnName = "sequence", allocationSize = 1)
87-
public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao { //FIXME: , ExternalIdDao {
89+
public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao, Configurable {
8890

8991
private static final String LIST_HOST_IDS_BY_HOST_TAGS = "SELECT filtered.host_id, COUNT(filtered.tag) AS tag_count "
9092
+ "FROM (SELECT host_id, tag, is_tag_a_rule FROM host_tags GROUP BY host_id,tag,is_tag_a_rule) AS filtered "
@@ -1520,18 +1522,37 @@ private List<Long> findHostIdsByHostTags(String hostTags){
15201522
}
15211523
}
15221524

1525+
@Override
15231526
public List<HostVO> findHostsWithTagRuleThatMatchComputeOfferingTags(String computeOfferingTags) {
15241527
List<HostTagVO> hostTagVOList = _hostTagsDao.findHostRuleTags();
15251528
List<HostVO> result = new ArrayList<>();
15261529
for (HostTagVO rule: hostTagVOList) {
1527-
if (TagAsRuleHelper.interpretTagAsRule(rule.getTag(), computeOfferingTags, HostTagsDao.hostTagRuleExecutionTimeout.value())) {
1530+
if (GenericRuleHelper.interpretTagAsRule(rule.getTag(), computeOfferingTags, HostTagsDao.hostTagRuleExecutionTimeout.value(),
1531+
HostTagsDao.hostTagRuleExecutionTimeout.key())) {
15281532
result.add(findById(rule.getHostId()));
15291533
}
15301534
}
15311535

15321536
return result;
15331537
}
15341538

1539+
@Override
1540+
public List<HostVO> findHostsWithGuestOsRulesThatDidNotMatchOsOfGuestVm(String templateGuestOSName) {
1541+
List<DetailVO> hostIdsWithGuestOsRule = _detailsDao.findByName(Host.GUEST_OS_RULE);
1542+
List<HostVO> hostsWithIncompatibleRules = new ArrayList<>();
1543+
for (DetailVO guestOsRule : hostIdsWithGuestOsRule) {
1544+
if (!GenericRuleHelper.interpretGuestOsRule(guestOsRule.getValue(), templateGuestOSName, HostDao.guestOsRuleExecutionTimeout.value(),
1545+
HostDao.guestOsRuleExecutionTimeout.key())) {
1546+
logger.trace("The guest OS rule [{}] of the host with ID [{}] is incompatible with the OS of the VM.",
1547+
guestOsRule.getHostId(), guestOsRule.getValue());
1548+
hostsWithIncompatibleRules.add(findById(guestOsRule.getHostId()));
1549+
}
1550+
}
1551+
logger.trace("The hosts with the following IDs [{}] are incompatible with the VM considering their guest OS rule.",
1552+
hostsWithIncompatibleRules);
1553+
return hostsWithIncompatibleRules;
1554+
}
1555+
15351556
public List<Long> findClustersThatMatchHostTagRule(String computeOfferingTags) {
15361557
Set<Long> result = new HashSet<>();
15371558
List<HostVO> hosts = findHostsWithTagRuleThatMatchComputeOfferingTags(computeOfferingTags);
@@ -1984,4 +2005,14 @@ public List<String> listDistinctStorageAccessGroups(String name, String keyword)
19842005

19852006
return customSearch(sc, null);
19862007
}
2008+
2009+
@Override
2010+
public ConfigKey<?>[] getConfigKeys() {
2011+
return new ConfigKey<?>[] {guestOsRuleExecutionTimeout};
2012+
}
2013+
2014+
@Override
2015+
public String getConfigComponentName() {
2016+
return HostDaoImpl.class.getSimpleName();
2017+
}
19872018
}

engine/schema/src/main/resources/META-INF/db/views/cloud.host_view.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ SELECT
6464
guest_os_category.id guest_os_category_id,
6565
guest_os_category.uuid guest_os_category_uuid,
6666
guest_os_category.name guest_os_category_name,
67+
(SELECT `value` FROM `cloud`.`host_details` `hd` WHERE `hd`.`host_id` = `cloud`.`host`.`id` AND `hd`.`name` = 'guest.os.rule') AS `guest_os_rule`,
6768
mem_caps.used_capacity memory_used_capacity,
6869
mem_caps.reserved_capacity memory_reserved_capacity,
6970
cpu_caps.used_capacity cpu_used_capacity,

framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ protected List<QuotaUsageVO> createQuotaUsagesAccordingToQuotaTariffs(AccountVO
312312

313313
List<Pair<UsageVO, QuotaUsageVO>> pairsUsageAndQuotaUsage = new ArrayList<>();
314314

315-
try (JsInterpreter jsInterpreter = new JsInterpreter(QuotaConfig.QuotaActivationRuleTimeout.value())) {
315+
try (JsInterpreter jsInterpreter = new JsInterpreter(QuotaConfig.QuotaActivationRuleTimeout.value(), QuotaConfig.QuotaActivationRuleTimeout.key())) {
316316
for (UsageVO usageRecord : usageRecords) {
317317
int usageType = usageRecord.getUsageType();
318318

plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,7 @@ public QuotaValidateActivationRuleResponse validateActivationRule(QuotaValidateA
12441244
addAllPresetVariables(PresetVariables.class, quotaType, usageTypeVariablesAndDescriptions, null);
12451245
List<String> usageTypeVariables = usageTypeVariablesAndDescriptions.stream().map(Pair::first).collect(Collectors.toList());
12461246

1247-
try (JsInterpreter jsInterpreter = new JsInterpreter(QuotaConfig.QuotaActivationRuleTimeout.value())) {
1247+
try (JsInterpreter jsInterpreter = new JsInterpreter(QuotaConfig.QuotaActivationRuleTimeout.value(), QuotaConfig.QuotaActivationRuleTimeout.key())) {
12481248
Map<String, String> newVariables = injectUsageTypeVariables(jsInterpreter, usageTypeVariables);
12491249
String scriptToExecute = jsInterpreterHelper.replaceScriptVariables(activationRule, newVariables);
12501250
jsInterpreter.executeScript(String.format("new Function(\"%s\")", scriptToExecute.replaceAll("\n", "")));

0 commit comments

Comments
 (0)