diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java index dc54f543c32..49b13e1e698 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java @@ -70,6 +70,22 @@ public interface VirtualMachineManager extends Manager { ConfigKey AllowExposeHypervisorHostname = new ConfigKey("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 VmServiceOfferingMaxCPUCores = new ConfigKey("Advanced", + Integer.class, + "vm.serviceoffering.cpu.cores.max", + "0", + "Maximum CPU cores for vm service offering. If 0 - no limitation", + true + ); + + static final ConfigKey VmServiceOfferingMaxRAMSize = new ConfigKey("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"; } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index b8342b4a60e..14b3078cb4c 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -4499,7 +4499,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac 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 getStoragePoolAllocators() { diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 784fbb4ef0f..412fa7fee7d 100755 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -240,6 +240,7 @@ import com.cloud.utils.exception.CloudRuntimeException; 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; @@ -2340,14 +2341,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati 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"); } } diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index f99a0663e29..ef7617699ce 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -1031,7 +1031,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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(); @@ -1075,6 +1078,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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 customParameters) { //TODO need to validate custom cpu, and memory against min/max CPU/Memory ranges from service_offering_details table @@ -1084,8 +1098,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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() @@ -1106,8 +1121,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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."); @@ -1135,6 +1151,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir newServiceOffering.setDynamicFlag(true); validateCustomParameters(newServiceOffering, customParameters); newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customParameters); + } else { + validateOfferingMaxResource(newServiceOffering); } ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); @@ -3461,6 +3479,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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();