Skip to content

Guest OS rules #10098

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,11 @@
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.offering.ServiceOffering;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;

public interface HostAllocator extends Adapter {

/**
* @param UserVm vm
* @param ServiceOffering offering
**/
boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering);

/**
* Determines which physical hosts are suitable to
* allocate the guest virtual machines on
Expand All @@ -49,31 +41,6 @@ public interface HostAllocator extends Adapter {

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

/**
* Determines which physical hosts are suitable to allocate the guest
* virtual machines on
*
* Allocators must set any other hosts not considered for allocation in the
* ExcludeList avoid. Thus the avoid set and the list of hosts suitable,
* together must cover the entire host set in the cluster.
*
* @param VirtualMachineProfile
* vmProfile
* @param DeploymentPlan
* plan
* @param GuestType
* 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 vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity);

/**
* Determines which physical hosts are suitable to allocate the guest
* virtual machines on
Expand Down
2 changes: 1 addition & 1 deletion api/src/main/java/com/cloud/deploy/DeploymentPlanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public interface DeploymentPlanner extends Adapter {
boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid);

public enum AllocationAlgorithm {
random, firstfit, userdispersing, userconcentratedpod_random, userconcentratedpod_firstfit;
random, firstfit, userdispersing, userconcentratedpod_random, userconcentratedpod_firstfit, firstfitleastconsumed
}

public enum PlannerResourceUsage {
Expand Down
2 changes: 2 additions & 0 deletions api/src/main/java/com/cloud/host/Host.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public static String[] toStrings(Host.Type... types) {
public static final String HOST_UEFI_ENABLE = "host.uefi.enable";
public static final String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
public static final String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
String GUEST_OS_CATEGORY_ID = "guest.os.category.id";
String GUEST_OS_RULE = "guest.os.rule";

/**
* @return name of the machine.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ public class ApiConstants {
public static final String OS_NAME_FOR_HYPERVISOR = "osnameforhypervisor";
public static final String GUEST_OS_LIST = "guestoslist";
public static final String GUEST_OS_COUNT = "guestoscount";
public static final String GUEST_OS_RULE = "guestosrule";
public static final String OS_MAPPING_CHECK_ENABLED = "osmappingcheckenabled";
public static final String OUTOFBANDMANAGEMENT_POWERSTATE = "outofbandmanagementpowerstate";
public static final String OUTOFBANDMANAGEMENT_ENABLED = "outofbandmanagementenabled";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void execute() {
for (Host host : result.first()) {
HostForMigrationResponse hostResponse = _responseGenerator.createHostForMigrationResponse(host);
Boolean suitableForMigration = false;
if (hostsWithCapacity.contains(host)) {
if (hostsWithCapacity != null && hostsWithCapacity.contains(host)) {
suitableForMigration = true;
}
hostResponse.setSuitableForMigration(suitableForMigration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ protected ListResponse<HostResponse> getHostResponses() {
for (Host host : result.first()) {
HostResponse hostResponse = _responseGenerator.createHostResponse(host, getDetails());
Boolean suitableForMigration = false;
if (hostsWithCapacity.contains(host)) {
if (hostsWithCapacity != null && hostsWithCapacity.contains(host)) {
suitableForMigration = true;
}
hostResponse.setSuitableForMigration(suitableForMigration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,14 @@ public class UpdateHostCmd extends BaseCmd {
@Parameter(name = ApiConstants.OS_CATEGORY_ID,
type = CommandType.UUID,
entityType = GuestOSCategoryResponse.class,
description = "the id of Os category to update the host with")
description = "the ID of OS category used to prioritize VMs with matching OS category during the allocation process." +
" It cannot be used alongside the `guestosrule` parameter.")
private Long osCategoryId;

@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." +
"It cannot be used alongside the `oscategoryid` parameter.")
private String guestOsRule;

@Parameter(name = ApiConstants.ALLOCATION_STATE,
type = CommandType.STRING,
description = "Change resource state of host, valid values are [Enable, Disable]. Operation may failed if host in states not allowing Enable/Disable")
Expand Down Expand Up @@ -83,6 +88,10 @@ public Long getOsCategoryId() {
return osCategoryId;
}

public String getGuestOsRule() {
return guestOsRule;
}

public String getAllocationState() {
return allocationState;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ public class HostResponse extends BaseResponseWithAnnotations {
@Param(description = "the OS category name of the host")
private String osCategoryName;

@SerializedName(ApiConstants.GUEST_OS_RULE)
@Param(description = "the guest OS rule")
private String guestOsRule;

@SerializedName(ApiConstants.IP_ADDRESS)
@Param(description = "the IP address of the host")
private String ipAddress;
Expand Down Expand Up @@ -870,4 +874,12 @@ public Boolean getEncryptionSupported() {
public Boolean getInstanceConversionSupported() {
return instanceConversionSupported;
}

public String getGuestOsRule() {
return guestOsRule;
}

public void setGuestOsRule(String guestOsRule) {
this.guestOsRule = guestOsRule;
}
}
5 changes: 0 additions & 5 deletions client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,6 @@
<artifactId>cloud-plugin-explicit-dedication</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-host-allocator-random</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-outofbandmanagement-driver-ipmitool</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,6 @@ void orchestrateStart(String vmUuid, Map<VirtualMachineProfile.Param, Object> pa
void advanceReboot(String vmUuid, Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException,
ConcurrentOperationException, OperationTimedoutException;

/**
* Check to see if a virtual machine can be upgraded to the given service offering
*
* @param vm
* @param offering
* @return true if the host can handle the upgrade, false otherwise
*/
boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering);

VirtualMachine findById(long vmId);

void storageMigration(String vmUuid, Map<Long, Long> volumeToPool);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3536,19 +3536,6 @@ protected void runInContext() {
}
}

@Override
public boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering) {
boolean isMachineUpgradable = true;
for (final HostAllocator allocator : hostAllocators) {
isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
if (!isMachineUpgradable) {
break;
}
}

return isMachineUpgradable;
}

@Override
public void reboot(final String vmUuid, final Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException {
try {
Expand Down Expand Up @@ -3929,11 +3916,6 @@ public void checkIfCanUpgrade(final VirtualMachine vmInstance, final ServiceOffe
throw new InvalidParameterValueException("isSystem property is different for current service offering and new service offering");
}

if (!isVirtualMachineUpgradable(vmInstance, newServiceOffering)) {
throw new InvalidParameterValueException("Unable to upgrade virtual machine, not enough resources available " + "for an offering of " +
newServiceOffering.getCpu() + " cpu(s) at " + newServiceOffering.getSpeed() + " Mhz, and " + newServiceOffering.getRamSize() + " MB of memory");
}

final List<String> currentTags = StringUtils.csvTagsToList(currentDiskOffering.getTags());
final List<String> newTags = StringUtils.csvTagsToList(newDiskOffering.getTags());
if (VolumeApiServiceImpl.MatchStoragePoolTagsWithDiskOffering.valueIn(vmInstance.getDataCenterId())) {
Expand Down
5 changes: 3 additions & 2 deletions engine/schema/src/main/java/com/cloud/host/HostVO.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
import com.cloud.cpu.CPU;
import org.apache.cloudstack.util.CPUArchConverter;
import org.apache.cloudstack.util.HypervisorTypeConverter;
import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
import org.apache.cloudstack.utils.jsinterpreter.GenericRuleHelper;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.BooleanUtils;
Expand Down Expand Up @@ -832,7 +832,8 @@ public boolean checkHostServiceOfferingTags(ServiceOffering serviceOffering) {
}

if (BooleanUtils.isTrue(this.getIsTagARule())) {
return TagAsRuleHelper.interpretTagAsRule(this.getHostTags().get(0), serviceOffering.getHostTag(), HostTagsDao.hostTagRuleExecutionTimeout.value());
return GenericRuleHelper.interpretTagAsRule(this.getHostTags().get(0), serviceOffering.getHostTag(), HostTagsDao.hostTagRuleExecutionTimeout.value(),
HostTagsDao.hostTagRuleExecutionTimeout.key());
}

if (StringUtils.isEmpty(serviceOffering.getHostTag())) {
Expand Down
9 changes: 8 additions & 1 deletion engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,17 @@
import com.cloud.resource.ResourceState;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.fsm.StateDao;
import org.apache.cloudstack.framework.config.ConfigKey;

/**
* Data Access Object for server
*
*/
public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Status.Event, Host> {

ConfigKey<Long> guestOsRuleExecutionTimeout = new ConfigKey<>("Advanced", Long.class, "guest.os.rule.execution.timeout", "3000", "The maximum runtime, in milliseconds, " +
"to execute a guest OS rule; if it is reached, a timeout will happen.", true);

long countBy(long clusterId, ResourceState... states);

Integer countAllByType(final Host.Type type);
Expand Down Expand Up @@ -166,9 +171,11 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
*/
List<String> listOrderedHostsHypervisorVersionsInDatacenter(long datacenterId, HypervisorType hypervisorType);

List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String computeOfferingTags);
List<HostVO> findHostsWithTagRuleThatMatchComputeOfferingTags(String computeOfferingTags);

List<Long> findClustersThatMatchHostTagRule(String computeOfferingTags);

List<Long> listSsvmHostsWithPendingMigrateJobsOrderedByJobCount();

List<HostVO> findHostsWithGuestOsRulesThatDidNotMatchOsOfGuestVm(String templateGuestOSName);
}
40 changes: 35 additions & 5 deletions engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
import javax.inject.Inject;
import javax.persistence.TableGenerator;

import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.utils.jsinterpreter.GenericRuleHelper;
import org.apache.commons.collections.CollectionUtils;

import com.cloud.agent.api.VgpuTypesInfo;
Expand Down Expand Up @@ -78,7 +80,7 @@

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

private static final String LIST_HOST_IDS_BY_COMPUTETAGS = "SELECT filtered.host_id, COUNT(filtered.tag) AS tag_count "
+ "FROM (SELECT host_id, tag, is_tag_a_rule FROM host_tags GROUP BY host_id,tag) AS filtered "
Expand Down Expand Up @@ -1350,21 +1352,39 @@ private List<Long> findHostByComputeOfferings(String computeOfferingTags){
}
}

public List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String computeOfferingTags) {
@Override
public List<HostVO> findHostsWithTagRuleThatMatchComputeOfferingTags(String computeOfferingTags) {
List<HostTagVO> hostTagVOList = _hostTagsDao.findHostRuleTags();
List<HostVO> result = new ArrayList<>();
for (HostTagVO rule: hostTagVOList) {
if (TagAsRuleHelper.interpretTagAsRule(rule.getTag(), computeOfferingTags, HostTagsDao.hostTagRuleExecutionTimeout.value())) {
if (GenericRuleHelper.interpretTagAsRule(rule.getTag(), computeOfferingTags, HostTagsDao.hostTagRuleExecutionTimeout.value(),
HostTagsDao.hostTagRuleExecutionTimeout.key())) {
result.add(findById(rule.getHostId()));
}
}

return result;
}

@Override
public List<HostVO> findHostsWithGuestOsRulesThatDidNotMatchOsOfGuestVm(String templateGuestOSName) {
List<DetailVO> hostIdsWithGuestOsRule = _detailsDao.findByName(Host.GUEST_OS_RULE);
List<HostVO> hostsWithIncompatibleRules = new ArrayList<>();
for (DetailVO guestOsRule : hostIdsWithGuestOsRule) {
if (!GenericRuleHelper.interpretGuestOsRule(guestOsRule.getValue(), templateGuestOSName, HostDao.guestOsRuleExecutionTimeout.value(),
HostDao.guestOsRuleExecutionTimeout.key())) {
logger.trace("The guest OS rule [{}] of the host with ID [{}] is incompatible with the OS of the VM.", guestOsRule.getHostId(), guestOsRule.getValue());
hostsWithIncompatibleRules.add(findById(guestOsRule.getHostId()));
}
}
logger.trace("The hosts with the following IDs [{}] are incompatible with the VM considering their guest OS rule.", hostsWithIncompatibleRules);
return hostsWithIncompatibleRules;
}

@Override
public List<Long> findClustersThatMatchHostTagRule(String computeOfferingTags) {
Set<Long> result = new HashSet<>();
List<HostVO> hosts = findHostsWithTagRuleThatMatchComputeOferringTags(computeOfferingTags);
List<HostVO> hosts = findHostsWithTagRuleThatMatchComputeOfferingTags(computeOfferingTags);
for (HostVO host: hosts) {
result.add(host.getClusterId());
}
Expand Down Expand Up @@ -1602,4 +1622,14 @@ private String createSqlFindHostToExecuteCommand(boolean useDisabledHosts) {
}
return String.format(sqlFindHostInZoneToExecuteCommand, hostResourceStatus);
}

@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {guestOsRuleExecutionTimeout};
}

@Override
public String getConfigComponentName() {
return HostDaoImpl.class.getSimpleName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ SELECT
guest_os_category.id guest_os_category_id,
guest_os_category.uuid guest_os_category_uuid,
guest_os_category.name guest_os_category_name,
(SELECT `value` FROM `cloud`.`host_details` `hd` WHERE `hd`.`host_id` = `cloud`.`host`.`id` AND `hd`.`name` = 'guest.os.rule') AS `guest_os_rule`,
mem_caps.used_capacity memory_used_capacity,
mem_caps.reserved_capacity memory_reserved_capacity,
cpu_caps.used_capacity cpu_used_capacity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ protected List<QuotaUsageVO> createQuotaUsagesAccordingToQuotaTariffs(AccountVO

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

try (JsInterpreter jsInterpreter = new JsInterpreter(QuotaConfig.QuotaActivationRuleTimeout.value())) {
try (JsInterpreter jsInterpreter = new JsInterpreter(QuotaConfig.QuotaActivationRuleTimeout.value(), QuotaConfig.QuotaActivationRuleTimeout.key())) {
for (UsageVO usageRecord : usageRecords) {
int usageType = usageRecord.getUsageType();

Expand Down
30 changes: 0 additions & 30 deletions plugins/host-allocators/random/pom.xml

This file was deleted.

Loading
Loading