diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java index 253881e0959..638319f02a0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java @@ -223,8 +223,7 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.STORAGE_POLICY, type = CommandType.UUID, entityType = VsphereStoragePoliciesResponse.class,required = false, description = "Name of the storage policy defined at vCenter, this is applicable only for VMware", since = "4.15") private Long storagePolicy; - @Parameter(name = ApiConstants.DYNAMIC_SCALING_ENABLED, - type = CommandType.BOOLEAN, + @Parameter(name = ApiConstants.DYNAMIC_SCALING_ENABLED, type = CommandType.BOOLEAN, since = "4.16", description = "true if virtual machine needs to be dynamically scalable of cpu or memory") protected Boolean isDynamicScalingEnabled; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index 346d49ca6c5..789365fae58 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -235,8 +235,7 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG @LogLevel(LogLevel.Log4jLevel.Off) private Map vAppNetworks; - @Parameter(name = ApiConstants.DYNAMIC_SCALING_ENABLED, - type = CommandType.BOOLEAN, + @Parameter(name = ApiConstants.DYNAMIC_SCALING_ENABLED, type = CommandType.BOOLEAN, since = "4.16", description = "true if virtual machine needs to be dynamically scalable") protected Boolean dynamicScalingEnabled; 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 cc938a9974c..41a7c8d627c 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -3916,7 +3916,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) { removeCustomOfferingDetails(vmId); } - Boolean dynamicScalingEnabled = vmForUpdate.isDynamicallyScalable() && newServiceOffering.isDynamicScalingEnabled() && UserVmManager.EnableDynamicallyScaleVm.valueIn(vmForUpdate.getDataCenterId()); + VMTemplateVO template = _templateDao.findById(vmForUpdate.getTemplateId()); + Boolean dynamicScalingEnabled = vmForUpdate.isDynamicallyScalable() && _userVmMgr.checkIfDynamicScalingCanBeEnabled(newServiceOffering, template, vmForUpdate.getDataCenterId()); vmForUpdate.setDynamicallyScalable(dynamicScalingEnabled); return _vmDao.update(vmId, vmForUpdate); } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java index 6021427bd32..307b4f13f2b 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java @@ -72,7 +72,6 @@ import com.cloud.vm.Nic; import com.cloud.vm.ReservationContext; import com.cloud.vm.ReservationContextImpl; import com.cloud.vm.VirtualMachine; -import com.cloud.vm.UserVmManager; import com.google.common.base.Strings; public class KubernetesClusterStartWorker extends KubernetesClusterResourceModifierActionWorker { @@ -209,11 +208,10 @@ public class KubernetesClusterStartWorker extends KubernetesClusterResourceModif logAndThrow(Level.ERROR, "Failed to read Kubernetes master configuration file", e); } String base64UserData = Base64.encodeBase64String(k8sMasterConfig.getBytes(StringUtils.getPreferredCharset())); - Boolean dynamicScalingEnabled = serviceOffering.isDynamicScalingEnabled() && clusterTemplate.isDynamicallyScalable() && UserVmManager.EnableDynamicallyScaleVm.valueIn(zone.getId()); masterVm = userVmService.createAdvancedVirtualMachine(zone, serviceOffering, clusterTemplate, networkIds, owner, hostName, hostName, null, null, null, Hypervisor.HypervisorType.None, BaseCmd.HTTPMethod.POST, base64UserData, kubernetesCluster.getKeyPair(), - requestedIps, addrs, null, null, null, customParameterMap, null, null, null, null, dynamicScalingEnabled); + requestedIps, addrs, null, null, null, customParameterMap, null, null, null, null, true); if (LOGGER.isInfoEnabled()) { LOGGER.info(String.format("Created master VM ID: %s, %s in the Kubernetes cluster : %s", masterVm.getUuid(), hostName, kubernetesCluster.getName())); } @@ -264,11 +262,10 @@ public class KubernetesClusterStartWorker extends KubernetesClusterResourceModif logAndThrow(Level.ERROR, "Failed to read Kubernetes master configuration file", e); } String base64UserData = Base64.encodeBase64String(k8sMasterConfig.getBytes(StringUtils.getPreferredCharset())); - Boolean dynamicScalingEnabled = serviceOffering.isDynamicScalingEnabled() && clusterTemplate.isDynamicallyScalable() && UserVmManager.EnableDynamicallyScaleVm.valueIn(zone.getId()); additionalMasterVm = userVmService.createAdvancedVirtualMachine(zone, serviceOffering, clusterTemplate, networkIds, owner, hostName, hostName, null, null, null, Hypervisor.HypervisorType.None, BaseCmd.HTTPMethod.POST, base64UserData, kubernetesCluster.getKeyPair(), - null, addrs, null, null, null, customParameterMap, null, null, null, null, dynamicScalingEnabled); + null, addrs, null, null, null, customParameterMap, null, null, null, null, true); if (LOGGER.isInfoEnabled()) { LOGGER.info(String.format("Created master VM ID : %s, %s in the Kubernetes cluster : %s", additionalMasterVm.getUuid(), hostName, kubernetesCluster.getName())); } diff --git a/server/src/main/java/com/cloud/vm/UserVmManager.java b/server/src/main/java/com/cloud/vm/UserVmManager.java index e4206efe5d8..ba720aebc3d 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManager.java +++ b/server/src/main/java/com/cloud/vm/UserVmManager.java @@ -20,6 +20,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.cloud.offering.ServiceOffering; +import com.cloud.template.VirtualMachineTemplate; import org.apache.cloudstack.api.BaseCmd.HTTPMethod; import org.apache.cloudstack.framework.config.ConfigKey; @@ -124,4 +126,7 @@ public interface UserVmManager extends UserVmService { void persistDeviceBusInfo(UserVmVO paramUserVmVO, String paramString); HashMap> getVmNetworkStatistics(long hostId, String hostName, List vmIds); + + Boolean checkIfDynamicScalingCanBeEnabled(ServiceOffering offering, VirtualMachineTemplate template, Long zoneId); + } diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index b37252fda36..9fc2e56cbed 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -3939,7 +3939,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } - dynamicScalingEnabled = checkIfDynamicScalingCanBeEnabled(dynamicScalingEnabled, offering, template, zone.getId()); + dynamicScalingEnabled = dynamicScalingEnabled && checkIfDynamicScalingCanBeEnabled(offering, template, zone.getId()); UserVmVO vm = commitUserVm(zone, template, hostName, displayName, owner, diskOfferingId, diskSize, userData, caller, isDisplayVm, keyboard, accountId, userId, offering, isIso, sshPublicKey, networkNicMap, id, instanceName, uuidName, hypervisorType, customParameters, dhcpOptionMap, @@ -3967,13 +3967,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return vm; } - private Boolean checkIfDynamicScalingCanBeEnabled(Boolean dynamicScalingEnabled, ServiceOfferingVO offering, VMTemplateVO template, Long zoneId) { - if (dynamicScalingEnabled) { - if (!(offering.isDynamicScalingEnabled() && template.isDynamicallyScalable() && UserVmManager.EnableDynamicallyScaleVm.valueIn(zoneId))) { - s_logger.info("VM cannot be configured to be dynamically scalable if any of the service offering's dynamic scaling property, template's dynamic scaling property or global setting is false"); - } + @Override + public Boolean checkIfDynamicScalingCanBeEnabled(ServiceOffering offering, VirtualMachineTemplate template, Long zoneId) { + Boolean canEnableDynamicScaling = offering.isDynamicScalingEnabled() && template.isDynamicallyScalable() && UserVmManager.EnableDynamicallyScaleVm.valueIn(zoneId); + if (!canEnableDynamicScaling) { + s_logger.info("VM cannot be configured to be dynamically scalable if any of the service offering's dynamic scaling property, template's dynamic scaling property or global setting is false"); } - return dynamicScalingEnabled && offering.isDynamicScalingEnabled() && template.isDynamicallyScalable() && UserVmManager.EnableDynamicallyScaleVm.valueIn(zoneId); + + return canEnableDynamicScaling; } /** @@ -7095,13 +7096,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir vm.setIsoId(newTemplateId); vm.setGuestOSId(template.getGuestOSId()); vm.setTemplateId(newTemplateId); - _vmDao.update(vmId, vm); } else { newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); vm.setGuestOSId(template.getGuestOSId()); vm.setTemplateId(newTemplateId); - _vmDao.update(vmId, vm); } + // check if VM can be dynamically scalable with the new template + ServiceOfferingVO serviceOffering = _offeringDao.findById(vm.getServiceOfferingId()); + VMTemplateVO newTemplate = _templateDao.findById(newTemplateId); + Boolean dynamicScalingEnabled = vm.isDynamicallyScalable() && checkIfDynamicScalingCanBeEnabled(serviceOffering, newTemplate, vm.getDataCenterId()); + vm.setDynamicallyScalable(dynamicScalingEnabled); + _vmDao.update(vmId, vm); + } else { newVol = volumeMgr.allocateDuplicateVolume(root, null); } @@ -7506,7 +7512,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir final String uuidName = _uuidMgr.generateUuid(UserVm.class, null); final Host lastHost = powerState != VirtualMachine.PowerState.PowerOn ? host : null; - final Boolean dynamicScalingEnabled = serviceOffering.isDynamicScalingEnabled() && template.isDynamicallyScalable() && UserVmManager.EnableDynamicallyScaleVm.valueIn(zone.getId()); + final Boolean dynamicScalingEnabled = checkIfDynamicScalingCanBeEnabled(serviceOffering, template, zone.getId()); return commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner, null, null, userData, caller, isDisplayVm, keyboard, accountId, userId, serviceOffering, template.getFormat().equals(ImageFormat.ISO), sshPublicKey, null,