Skip to content
Merged
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
16 changes: 16 additions & 0 deletions engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ public interface VirtualMachineManager extends Manager {
ConfigKey<Boolean> AllowExposeHypervisorHostname = new ConfigKey<Boolean>("Advanced", Boolean.class, "global.allow.expose.host.hostname",
"false", "If set to true, it allows the hypervisor host name on which the VM is spawned on to be exposed to the VM", true, ConfigKey.Scope.Global);

static final ConfigKey<Integer> VmServiceOfferingMaxCPUCores = new ConfigKey<Integer>("Advanced",
Integer.class,
"vm.serviceoffering.cpu.cores.max",
"0",
"Maximum CPU cores for vm service offering. If 0 - no limitation",
true
);

static final ConfigKey<Integer> VmServiceOfferingMaxRAMSize = new ConfigKey<Integer>("Advanced",
Integer.class,
"vm.serviceoffering.ram.size.max",
"0",
"Maximum RAM size in MB for vm service offering. If 0 - no limitation",
true
);

interface Topics {
String VM_POWER_STATE = "vm.powerstate";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4499,7 +4499,8 @@ public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {ClusterDeltaSyncInterval, StartRetry, VmDestroyForcestop, VmOpCancelInterval, VmOpCleanupInterval, VmOpCleanupWait,
VmOpLockStateRetry,
VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval, VmConfigDriveLabel, VmConfigDriveOnPrimaryPool, HaVmRestartHostUp,
ResoureCountRunningVMsonly, AllowExposeHypervisorHostname, AllowExposeHypervisorHostnameAccountLevel };
ResoureCountRunningVMsonly, AllowExposeHypervisorHostname, AllowExposeHypervisorHostnameAccountLevel,
VmServiceOfferingMaxCPUCores, VmServiceOfferingMaxRAMSize };
}

public List<StoragePoolAllocator> getStoragePoolAllocators() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.NicIpAlias;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicIpAliasDao;
import com.cloud.vm.dao.NicIpAliasVO;
Expand Down Expand Up @@ -2340,14 +2341,16 @@ public ServiceOffering createServiceOffering(final CreateServiceOfferingCmd cmd)
details.put(ApiConstants.MAX_CPU_NUMBER, maxCPU.toString());
}
} else {
if (cpuNumber != null && (cpuNumber.intValue() <= 0 || cpuNumber.longValue() > Integer.MAX_VALUE)) {
throw new InvalidParameterValueException("Failed to create service offering " + offeringName + ": specify the cpu number value between 1 and " + Integer.MAX_VALUE);
Integer maxCPUCores = VirtualMachineManager.VmServiceOfferingMaxCPUCores.value() == 0 ? Integer.MAX_VALUE: VirtualMachineManager.VmServiceOfferingMaxCPUCores.value();
Integer maxRAMSize = VirtualMachineManager.VmServiceOfferingMaxRAMSize.value() == 0 ? Integer.MAX_VALUE: VirtualMachineManager.VmServiceOfferingMaxRAMSize.value();
if (cpuNumber != null && (cpuNumber.intValue() <= 0 || cpuNumber.longValue() > maxCPUCores)) {
throw new InvalidParameterValueException("Failed to create service offering " + offeringName + ": specify the cpu number value between 1 and " + maxCPUCores);
}
if (cpuSpeed != null && (cpuSpeed.intValue() < 0 || cpuSpeed.longValue() > Integer.MAX_VALUE)) {
throw new InvalidParameterValueException("Failed to create service offering " + offeringName + ": specify the cpu speed value between 0 and " + Integer.MAX_VALUE);
}
if (memory != null && (memory.intValue() < 32 || memory.longValue() > Integer.MAX_VALUE)) {
throw new InvalidParameterValueException("Failed to create service offering " + offeringName + ": specify the memory value between 32 and " + Integer.MAX_VALUE + " MB");
if (memory != null && (memory.intValue() < 32 || memory.longValue() > maxRAMSize)) {
throw new InvalidParameterValueException("Failed to create service offering " + offeringName + ": specify the memory value between 32 and " + maxRAMSize + " MB");
}
}

Expand Down
28 changes: 24 additions & 4 deletions server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,10 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE
newServiceOffering.setDynamicFlag(true);
validateCustomParameters(newServiceOffering, cmd.getDetails());
newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customParameters);
} else {
validateOfferingMaxResource(newServiceOffering);
}

ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());

int newCpu = newServiceOffering.getCpu();
Expand Down Expand Up @@ -1075,6 +1078,17 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE
return userVm;
}

private void validateOfferingMaxResource(ServiceOfferingVO offering) {
Integer maxCPUCores = VirtualMachineManager.VmServiceOfferingMaxCPUCores.value() == 0 ? Integer.MAX_VALUE: VirtualMachineManager.VmServiceOfferingMaxCPUCores.value();
if (offering.getCpu() > maxCPUCores) {
throw new InvalidParameterValueException("Invalid cpu cores value, please choose another service offering with cpu cores between 1 and " + maxCPUCores);
}
Integer maxRAMSize = VirtualMachineManager.VmServiceOfferingMaxRAMSize.value() == 0 ? Integer.MAX_VALUE: VirtualMachineManager.VmServiceOfferingMaxRAMSize.value();
if (offering.getRamSize() > maxRAMSize) {
throw new InvalidParameterValueException("Invalid memory value, please choose another service offering with memory between 32 and " + maxRAMSize + " MB");
}
}

@Override
public void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<String, String> customParameters) {
//TODO need to validate custom cpu, and memory against min/max CPU/Memory ranges from service_offering_details table
Expand All @@ -1084,8 +1098,9 @@ public void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<Stri
int minCPU = NumbersUtil.parseInt(offeringDetails.get(ApiConstants.MIN_CPU_NUMBER), 1);
int maxCPU = NumbersUtil.parseInt(offeringDetails.get(ApiConstants.MAX_CPU_NUMBER), Integer.MAX_VALUE);
int cpuNumber = NumbersUtil.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuNumber.name()), -1);
if (cpuNumber < minCPU || cpuNumber > maxCPU) {
throw new InvalidParameterValueException(String.format("Invalid cpu cores value, specify a value between %d and %d", minCPU, maxCPU));
Integer maxCPUCores = VirtualMachineManager.VmServiceOfferingMaxCPUCores.value() == 0 ? Integer.MAX_VALUE: VirtualMachineManager.VmServiceOfferingMaxCPUCores.value();
if (cpuNumber < minCPU || cpuNumber > maxCPU || cpuNumber > maxCPUCores) {
throw new InvalidParameterValueException(String.format("Invalid cpu cores value, specify a value between %d and %d", minCPU, Math.min(maxCPUCores, maxCPU)));
}
} else if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) {
throw new InvalidParameterValueException("The cpu cores of this offering id:" + serviceOffering.getUuid()
Expand All @@ -1106,8 +1121,9 @@ public void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<Stri
int minMemory = NumbersUtil.parseInt(offeringDetails.get(ApiConstants.MIN_MEMORY), 32);
int maxMemory = NumbersUtil.parseInt(offeringDetails.get(ApiConstants.MAX_MEMORY), Integer.MAX_VALUE);
int memory = NumbersUtil.parseInt(customParameters.get(UsageEventVO.DynamicParameters.memory.name()), -1);
if (memory < minMemory || memory > maxMemory) {
throw new InvalidParameterValueException(String.format("Invalid memory value, specify a value between %d and %d", minMemory, maxMemory));
Integer maxRAMSize = VirtualMachineManager.VmServiceOfferingMaxRAMSize.value() == 0 ? Integer.MAX_VALUE: VirtualMachineManager.VmServiceOfferingMaxRAMSize.value();
if (memory < minMemory || memory > maxMemory || memory > maxRAMSize) {
throw new InvalidParameterValueException(String.format("Invalid memory value, specify a value between %d and %d", minMemory, Math.min(maxRAMSize, maxMemory)));
}
} else if (customParameters.containsKey(UsageEventVO.DynamicParameters.memory.name())) {
throw new InvalidParameterValueException("The memory of this offering id:" + serviceOffering.getUuid() + " is not customizable. This is predefined in the template.");
Expand Down Expand Up @@ -1135,6 +1151,8 @@ private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map<String
newServiceOffering.setDynamicFlag(true);
validateCustomParameters(newServiceOffering, customParameters);
newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customParameters);
} else {
validateOfferingMaxResource(newServiceOffering);
}
ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());

Expand Down Expand Up @@ -3461,6 +3479,8 @@ private UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffe
offering.setDynamicFlag(true);
validateCustomParameters(offering, customParameters);
offering = _offeringDao.getComputeOffering(offering, customParameters);
} else {
validateOfferingMaxResource(offering);
}
// check if account/domain is with in resource limits to create a new vm
boolean isIso = Storage.ImageFormat.ISO == template.getFormat();
Expand Down