This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new 083646b  server: VM dynamic scaling option granularity (#4643)
083646b is described below

commit 083646b3c3f05f4100c5de0c28b231109ebc98c3
Author: Harikrishna <[email protected]>
AuthorDate: Tue Jun 8 17:10:00 2021 +0530

    server: VM dynamic scaling option granularity (#4643)
    
    This PR introduces new granularity levels to configure VM dynamic 
scalability. Previously VM is configured to be dynamically scalable based on 
the template and global setting. Now we bringing this option to configure at 
service offering and VM level also.
    
    VM can dynamically scale only when all flags are ON at VM level, template, 
service offering and global setting. If any of the flags is set to false then 
VM cannot be scalable. This result will be persisted in DB for each VM and will 
be honoured for that VM till it is updated.
    
    We are introducing 'dynamicscalingallowed' parameter with permitted values 
of true or false for deployVM API and createServiceOffering API.
    
    Following are the API parameter changes:
    createServiceOffering API:
              dynamicscalingenabled: an optional parameter of type Boolean with 
default value “true”.
    deployVirtualMachine API:
              dynamicscalingenabled: an optional parameter of type Boolean with 
default value “true”.
    
    Following are the UI changes:
    Service offering creation has ON/OFF switch for dynamic scaling enabled 
with default value true
---
 .../java/com/cloud/offering/ServiceOffering.java   |   2 +
 api/src/main/java/com/cloud/vm/UserVmService.java  |   6 +-
 api/src/main/java/com/cloud/vm/VirtualMachine.java |   2 +
 .../org/apache/cloudstack/api/ApiConstants.java    |   1 +
 .../admin/offering/CreateServiceOfferingCmd.java   |   8 +
 .../api/command/user/vm/DeployVMCmd.java           |   8 +
 .../api/command/user/vm/UpdateVMCmd.java           |   2 +-
 .../api/response/ServiceOfferingResponse.java      |  13 +-
 .../cloudstack/api/response/SystemVmResponse.java  |  12 ++
 .../com/cloud/vm/VirtualMachineManagerImpl.java    |   3 +
 .../java/com/cloud/service/ServiceOfferingVO.java  |  67 ++----
 .../src/main/java/com/cloud/vm/VMInstanceVO.java   |   2 +-
 .../engine/cloud/entity/api/db/VMEntityVO.java     |   8 +
 .../resources/META-INF/db/schema-41510to41600.sql  |  93 ++++++++-
 .../cloudstack/quota/vo/ServiceOfferingVO.java     |   8 +
 ...ernetesClusterResourceModifierActionWorker.java |   2 +-
 .../KubernetesClusterStartWorker.java              |   4 +-
 .../main/java/com/cloud/api/ApiResponseHelper.java |   1 +
 .../java/com/cloud/api/query/QueryManagerImpl.java |   3 +-
 .../api/query/dao/ServiceOfferingJoinDaoImpl.java  |   1 +
 .../cloud/api/query/vo/ServiceOfferingJoinVO.java  |  11 +
 .../configuration/ConfigurationManagerImpl.java    |   6 +-
 .../com/cloud/hypervisor/HypervisorGuruBase.java   |   5 +-
 .../com/cloud/network/as/AutoScaleManagerImpl.java |   6 +-
 .../src/main/java/com/cloud/vm/UserVmManager.java  |   5 +
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  |  91 ++++++---
 .../deploy/DeploymentPlanningManagerImplTest.java  |   6 +-
 test/integration/smoke/test_scale_vm.py            | 226 ++++++++++++++++++++-
 tools/marvin/marvin/lib/base.py                    |   8 +-
 ui/public/locales/de_DE.json                       |   1 +
 ui/public/locales/en.json                          |   2 +
 ui/public/locales/es.json                          |   1 +
 ui/public/locales/hu.json                          |   1 +
 ui/public/locales/nl_NL.json                       |   1 +
 ui/src/components/view/ActionButton.vue            |   4 +-
 ui/src/config/section/compute.js                   |   1 +
 ui/src/config/section/infra/systemVms.js           |   2 +-
 ui/src/config/section/offering.js                  |   4 +-
 ui/src/views/compute/DeployVM.vue                  |  43 +++-
 ui/src/views/compute/EditVM.vue                    |  44 +++-
 ui/src/views/offering/AddComputeOffering.vue       |  15 +-
 41 files changed, 616 insertions(+), 113 deletions(-)

diff --git a/api/src/main/java/com/cloud/offering/ServiceOffering.java 
b/api/src/main/java/com/cloud/offering/ServiceOffering.java
index 2a80ba5..7bad77f 100644
--- a/api/src/main/java/com/cloud/offering/ServiceOffering.java
+++ b/api/src/main/java/com/cloud/offering/ServiceOffering.java
@@ -116,4 +116,6 @@ public interface ServiceOffering extends DiskOffering, 
InfrastructureEntity, Int
     String getDeploymentPlanner();
 
     boolean isDynamic();
+
+    boolean isDynamicScalingEnabled();
 }
diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java 
b/api/src/main/java/com/cloud/vm/UserVmService.java
index eab9c73..0b48a48 100644
--- a/api/src/main/java/com/cloud/vm/UserVmService.java
+++ b/api/src/main/java/com/cloud/vm/UserVmService.java
@@ -218,7 +218,7 @@ public interface UserVmService {
         String userData, String sshKeyPair, Map<Long, IpAddresses> 
requestedIps, IpAddresses defaultIp, Boolean displayVm, String keyboard,
         List<Long> affinityGroupIdList, Map<String, String> customParameter, 
String customId, Map<String, Map<Integer, String>> dhcpOptionMap,
         Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap,
-        Map<String, String> userVmOVFProperties) throws 
InsufficientCapacityException,
+        Map<String, String> userVmOVFProperties, boolean 
dynamicScalingEnabled) throws InsufficientCapacityException,
         ConcurrentOperationException, ResourceUnavailableException, 
StorageUnavailableException, ResourceAllocationException;
 
     /**
@@ -300,7 +300,7 @@ public interface UserVmService {
         HTTPMethod httpmethod, String userData, String sshKeyPair, Map<Long, 
IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String 
keyboard,
         List<Long> affinityGroupIdList, Map<String, String> customParameters, 
String customId, Map<String, Map<Integer, String>> dhcpOptionMap,
         Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap,
-        Map<String, String> userVmOVFProperties) throws 
InsufficientCapacityException,
+        Map<String, String> userVmOVFProperties, boolean 
dynamicScalingEnabled) throws InsufficientCapacityException,
         ConcurrentOperationException, ResourceUnavailableException, 
StorageUnavailableException, ResourceAllocationException;
 
     /**
@@ -379,7 +379,7 @@ public interface UserVmService {
         String hostName, String displayName, Long diskOfferingId, Long 
diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, 
String userData,
         String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses 
defaultIps, Boolean displayVm, String keyboard, List<Long> affinityGroupIdList,
         Map<String, String> customParameters, String customId, Map<String, 
Map<Integer, String>> dhcpOptionMap, Map<Long, DiskOffering> 
dataDiskTemplateToDiskOfferingMap,
-        Map<String, String> templateOvfPropertiesMap)
+        Map<String, String> templateOvfPropertiesMap, boolean 
dynamicScalingEnabled)
 
         throws InsufficientCapacityException, ConcurrentOperationException, 
ResourceUnavailableException, StorageUnavailableException, 
ResourceAllocationException;
 
diff --git a/api/src/main/java/com/cloud/vm/VirtualMachine.java 
b/api/src/main/java/com/cloud/vm/VirtualMachine.java
index 829e743..79154cb 100644
--- a/api/src/main/java/com/cloud/vm/VirtualMachine.java
+++ b/api/src/main/java/com/cloud/vm/VirtualMachine.java
@@ -342,4 +342,6 @@ public interface VirtualMachine extends RunningOn, 
ControlledEntity, Partition,
     @Override
     boolean isDisplay();
 
+    boolean isDynamicallyScalable();
+
 }
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java 
b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 7009584..28e4ba3 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -838,6 +838,7 @@ public class ApiConstants {
     public static final String CROSS_ZONES = "crossZones";
     public static final String TEMPLATETYPE = "templatetype";
     public static final String SOURCETEMPLATEID = "sourcetemplateid";
+    public static final String DYNAMIC_SCALING_ENABLED = 
"dynamicscalingenabled";
 
     public static final String POOL_TYPE ="pooltype";
 
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 d2d6f38..b301560 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,6 +223,10 @@ 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, since = "4.16",
+            description = "true if virtual machine needs to be dynamically 
scalable of cpu or memory")
+    protected Boolean isDynamicScalingEnabled;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -441,6 +445,10 @@ public class CreateServiceOfferingCmd extends BaseCmd {
         return storagePolicy;
     }
 
+    public boolean getDynamicScalingEnabled() {
+        return isDynamicScalingEnabled == null ? true : 
isDynamicScalingEnabled;
+    }
+
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
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 6d7cc9c..733bddb 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,6 +235,10 @@ public class DeployVMCmd extends 
BaseAsyncCreateCustomIdCmd implements SecurityG
     @LogLevel(LogLevel.Log4jLevel.Off)
     private Map vAppNetworks;
 
+    @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;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -623,6 +627,10 @@ public class DeployVMCmd extends 
BaseAsyncCreateCustomIdCmd implements SecurityG
         return bootIntoSetup;
     }
 
+    public boolean isDynamicScalingEnabled() {
+        return dynamicScalingEnabled == null ? true : dynamicScalingEnabled;
+    }
+
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
diff --git 
a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java 
b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java
index 3afee8a..38d1a5d 100644
--- 
a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java
+++ 
b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java
@@ -89,7 +89,7 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements 
SecurityGroupAction,
 
     @Parameter(name = ApiConstants.IS_DYNAMICALLY_SCALABLE,
                type = CommandType.BOOLEAN,
-               description = "true if VM contains XS/VMWare tools inorder to 
support dynamic scaling of VM cpu/memory")
+               description = "true if VM contains XS/VMWare tools inorder to 
support dynamic scaling of VM cpu/memory. This can be updated only when dynamic 
scaling is enabled on template, service offering and the corresponding global 
setting")
     protected Boolean isDynamicallyScalable;
 
     @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, 
description = "new host name of the vm. The VM has to be stopped/started for 
this update to take affect", since = "4.4")
diff --git 
a/api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
 
b/api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
index 05fcfbd..59bd72c 100644
--- 
a/api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
+++ 
b/api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
@@ -204,6 +204,10 @@ public class ServiceOfferingResponse extends BaseResponse {
     @Param(description = "Root disk size in GB", since = "4.15")
     private Long rootDiskSize;
 
+    @SerializedName(ApiConstants.DYNAMIC_SCALING_ENABLED)
+    @Param(description = "true if virtual machine needs to be dynamically 
scalable of cpu or memory", since = "4.16")
+    private Boolean dynamicScalingEnabled;
+
     public ServiceOfferingResponse() {
     }
 
@@ -457,7 +461,6 @@ public class ServiceOfferingResponse extends BaseResponse {
 
     public void setIscutomized(boolean iscutomized) {
         this.isCustomized = iscutomized;
-
     }
 
     public void setCacheMode(String cacheMode) {
@@ -475,4 +478,12 @@ public class ServiceOfferingResponse extends BaseResponse {
     public void setRootDiskSize(Long rootDiskSize) {
         this.rootDiskSize = rootDiskSize;
     }
+
+    public Boolean getDynamicScalingEnabled() {
+        return dynamicScalingEnabled;
+    }
+
+    public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) {
+        this.dynamicScalingEnabled = dynamicScalingEnabled;
+    }
 }
diff --git 
a/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java 
b/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java
index 934e84f..bfc9f9a 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java
@@ -170,6 +170,10 @@ public class SystemVmResponse extends BaseResponse {
     @Param(description = "the systemvm agent version", since = "4.13.1")
     private String version;
 
+    @SerializedName(ApiConstants.IS_DYNAMICALLY_SCALABLE)
+    @Param(description = "true if vm contains XS/VMWare tools inorder to 
support dynamic scaling of VM cpu/memory.")
+    private Boolean isDynamicallyScalable;
+
     @Override
     public String getObjectId() {
         return this.getId();
@@ -442,4 +446,12 @@ public class SystemVmResponse extends BaseResponse {
     public void setVersion(String version) {
         this.version = version;
     }
+
+    public Boolean getDynamicallyScalable() {
+        return isDynamicallyScalable;
+    }
+
+    public void setDynamicallyScalable(Boolean dynamicallyScalable) {
+        isDynamicallyScalable = dynamicallyScalable;
+    }
 }
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 4e3879f..e378842 100755
--- 
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++ 
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -3917,6 +3917,9 @@ public class VirtualMachineManagerImpl extends 
ManagerBase implements VirtualMac
         if (currentServiceOffering.isDynamic() && 
!newServiceOffering.isDynamic()) {
             removeCustomOfferingDetails(vmId);
         }
+        VMTemplateVO template = 
_templateDao.findById(vmForUpdate.getTemplateId());
+        boolean dynamicScalingEnabled = 
_userVmMgr.checkIfDynamicScalingCanBeEnabled(vmForUpdate, newServiceOffering, 
template, vmForUpdate.getDataCenterId());
+        vmForUpdate.setDynamicallyScalable(dynamicScalingEnabled);
         return _vmDao.update(vmId, vmForUpdate);
     }
 
diff --git 
a/engine/schema/src/main/java/com/cloud/service/ServiceOfferingVO.java 
b/engine/schema/src/main/java/com/cloud/service/ServiceOfferingVO.java
index 3a5f318..44f39a1 100644
--- a/engine/schema/src/main/java/com/cloud/service/ServiceOfferingVO.java
+++ b/engine/schema/src/main/java/com/cloud/service/ServiceOfferingVO.java
@@ -75,6 +75,9 @@ public class ServiceOfferingVO extends DiskOfferingVO 
implements ServiceOffering
     @Column(name = "deployment_planner")
     private String deploymentPlanner = null;
 
+    @Column(name = "dynamic_scaling_enabled")
+    private boolean dynamicScalingEnabled = true;
+
     // This is a delayed load value.  If the value is null,
     // then this field has not been loaded yet.
     // Call service offering dao to load it.
@@ -91,7 +94,7 @@ public class ServiceOfferingVO extends DiskOfferingVO 
implements ServiceOffering
     }
 
     public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, 
Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, 
String displayText,
-            ProvisioningType provisioningType, boolean useLocalStorage, 
boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type 
vmType, boolean defaultUse) {
+                             ProvisioningType provisioningType, boolean 
useLocalStorage, boolean recreatable, String tags, boolean systemUse, 
VirtualMachine.Type vmType, boolean defaultUse) {
         super(name, displayText, provisioningType, false, tags, recreatable, 
useLocalStorage, systemUse, true);
         this.cpu = cpu;
         this.ramSize = ramSize;
@@ -105,8 +108,9 @@ public class ServiceOfferingVO extends DiskOfferingVO 
implements ServiceOffering
         this.vmType = vmType == null ? null : vmType.toString().toLowerCase();
     }
 
-    public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, 
Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, 
boolean limitCpuUse,
-                             boolean volatileVm, String displayText, 
ProvisioningType provisioningType, boolean useLocalStorage, boolean 
recreatable, String tags, boolean systemUse, VirtualMachine.Type vmType) {
+    public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, 
Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA,
+                             boolean limitResourceUse, boolean volatileVm, 
String displayText, ProvisioningType provisioningType, boolean useLocalStorage, 
boolean recreatable, String tags, boolean systemUse,
+                             VirtualMachine.Type vmType, String hostTag, 
String deploymentPlanner, boolean dynamicScalingEnabled) {
         super(name, displayText, provisioningType, false, tags, recreatable, 
useLocalStorage, systemUse, true);
         this.cpu = cpu;
         this.ramSize = ramSize;
@@ -114,55 +118,12 @@ public class ServiceOfferingVO extends DiskOfferingVO 
implements ServiceOffering
         this.rateMbps = rateMbps;
         this.multicastRateMbps = multicastRateMbps;
         this.offerHA = offerHA;
-        this.limitCpuUse = limitCpuUse;
+        this.limitCpuUse = limitResourceUse;
         this.volatileVm = volatileVm;
         this.vmType = vmType == null ? null : vmType.toString().toLowerCase();
-    }
-
-    public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, 
Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA,
-                             boolean limitResourceUse, boolean volatileVm, 
String displayText, ProvisioningType provisioningType, boolean useLocalStorage, 
boolean recreatable, String tags, boolean systemUse,
-                             VirtualMachine.Type vmType, String hostTag) {
-        this(name,
-            cpu,
-            ramSize,
-            speed,
-            rateMbps,
-            multicastRateMbps,
-            offerHA,
-            limitResourceUse,
-            volatileVm,
-            displayText,
-            provisioningType,
-            useLocalStorage,
-            recreatable,
-            tags,
-            systemUse,
-            vmType
-        );
         this.hostTag = hostTag;
-    }
-
-    public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, 
Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA,
-                             boolean limitResourceUse, boolean volatileVm, 
String displayText, ProvisioningType provisioningType, boolean useLocalStorage, 
boolean recreatable, String tags, boolean systemUse,
-                             VirtualMachine.Type vmType, String hostTag, 
String deploymentPlanner) {
-        this(name,
-            cpu,
-            ramSize,
-            speed,
-            rateMbps,
-            multicastRateMbps,
-            offerHA,
-            limitResourceUse,
-            volatileVm,
-            displayText,
-            provisioningType,
-            useLocalStorage,
-            recreatable,
-            tags,
-            systemUse,
-            vmType,
-                hostTag);
         this.deploymentPlanner = deploymentPlanner;
+        this.dynamicScalingEnabled = dynamicScalingEnabled;
     }
 
     public ServiceOfferingVO(ServiceOfferingVO offering) {
@@ -189,6 +150,7 @@ public class ServiceOfferingVO extends DiskOfferingVO 
implements ServiceOffering
         volatileVm = offering.isVolatileVm();
         hostTag = offering.getHostTag();
         vmType = offering.getSystemVmType();
+        dynamicScalingEnabled = offering.isDynamicScalingEnabled();
     }
 
     @Override
@@ -334,4 +296,13 @@ public class ServiceOfferingVO extends DiskOfferingVO 
implements ServiceOffering
     public boolean isCustomCpuSpeedSupported() {
         return isCustomized() && getDetail("minCPU") != null;
     }
+
+    @Override
+    public boolean isDynamicScalingEnabled() {
+        return dynamicScalingEnabled;
+    }
+
+    public void setDynamicScalingEnabled(boolean dynamicScalingEnabled) {
+        this.dynamicScalingEnabled = dynamicScalingEnabled;
+    }
 }
diff --git a/engine/schema/src/main/java/com/cloud/vm/VMInstanceVO.java 
b/engine/schema/src/main/java/com/cloud/vm/VMInstanceVO.java
index 0e8dd4e..aa2e736 100644
--- a/engine/schema/src/main/java/com/cloud/vm/VMInstanceVO.java
+++ b/engine/schema/src/main/java/com/cloud/vm/VMInstanceVO.java
@@ -544,7 +544,7 @@ public class VMInstanceVO implements VirtualMachine, 
FiniteStateObject<State, Vi
         this.dynamicallyScalable = dynamicallyScalable;
     }
 
-    public Boolean isDynamicallyScalable() {
+    public boolean isDynamicallyScalable() {
         return dynamicallyScalable;
     }
 
diff --git 
a/engine/schema/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java
 
b/engine/schema/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java
index 4ab5f42..67af516 100644
--- 
a/engine/schema/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java
+++ 
b/engine/schema/src/main/java/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java
@@ -189,6 +189,9 @@ public class VMEntityVO implements VirtualMachine, 
FiniteStateObject<State, Virt
     @Column(name = "backup_volumes")
     private String backupVolumes;
 
+    @Column(name = "dynamically_scalable")
+    protected boolean dynamicallyScalable;
+
     @Transient
     private VMReservationVO vmReservation;
 
@@ -561,6 +564,11 @@ public class VMEntityVO implements VirtualMachine, 
FiniteStateObject<State, Virt
         return display;
     }
 
+    @Override
+    public boolean isDynamicallyScalable() {
+        return dynamicallyScalable;
+    }
+
     public void setDisplay(boolean display) {
         this.display = display;
     }
diff --git 
a/engine/schema/src/main/resources/META-INF/db/schema-41510to41600.sql 
b/engine/schema/src/main/resources/META-INF/db/schema-41510to41600.sql
index d5058c1..f7a7c4a 100644
--- a/engine/schema/src/main/resources/META-INF/db/schema-41510to41600.sql
+++ b/engine/schema/src/main/resources/META-INF/db/schema-41510to41600.sql
@@ -19,6 +19,97 @@
 -- Schema upgrade from 4.15.1.0 to 4.16.0.0
 --;
 
+-- Adding dynamic scalable flag for service offering table
+ALTER TABLE `cloud`.`service_offering` ADD COLUMN `dynamic_scaling_enabled` 
tinyint(1) unsigned NOT NULL DEFAULT 1  COMMENT 'true(1) if VM needs to be 
dynamically scalable of cpu or memory';
+DROP VIEW IF EXISTS `cloud`.`service_offering_view`;
+CREATE VIEW `cloud`.`service_offering_view` AS
+    SELECT
+        `service_offering`.`id` AS `id`,
+        `disk_offering`.`uuid` AS `uuid`,
+        `disk_offering`.`name` AS `name`,
+        `disk_offering`.`display_text` AS `display_text`,
+        `disk_offering`.`provisioning_type` AS `provisioning_type`,
+        `disk_offering`.`created` AS `created`,
+        `disk_offering`.`tags` AS `tags`,
+        `disk_offering`.`removed` AS `removed`,
+        `disk_offering`.`use_local_storage` AS `use_local_storage`,
+        `disk_offering`.`system_use` AS `system_use`,
+        `disk_offering`.`customized_iops` AS `customized_iops`,
+        `disk_offering`.`min_iops` AS `min_iops`,
+        `disk_offering`.`max_iops` AS `max_iops`,
+        `disk_offering`.`hv_ss_reserve` AS `hv_ss_reserve`,
+        `disk_offering`.`bytes_read_rate` AS `bytes_read_rate`,
+        `disk_offering`.`bytes_read_rate_max` AS `bytes_read_rate_max`,
+        `disk_offering`.`bytes_read_rate_max_length` AS 
`bytes_read_rate_max_length`,
+        `disk_offering`.`bytes_write_rate` AS `bytes_write_rate`,
+        `disk_offering`.`bytes_write_rate_max` AS `bytes_write_rate_max`,
+        `disk_offering`.`bytes_write_rate_max_length` AS 
`bytes_write_rate_max_length`,
+        `disk_offering`.`iops_read_rate` AS `iops_read_rate`,
+        `disk_offering`.`iops_read_rate_max` AS `iops_read_rate_max`,
+        `disk_offering`.`iops_read_rate_max_length` AS 
`iops_read_rate_max_length`,
+        `disk_offering`.`iops_write_rate` AS `iops_write_rate`,
+        `disk_offering`.`iops_write_rate_max` AS `iops_write_rate_max`,
+        `disk_offering`.`iops_write_rate_max_length` AS 
`iops_write_rate_max_length`,
+        `disk_offering`.`cache_mode` AS `cache_mode`,
+        `disk_offering`.`disk_size` AS `root_disk_size`,
+        `service_offering`.`cpu` AS `cpu`,
+        `service_offering`.`speed` AS `speed`,
+        `service_offering`.`ram_size` AS `ram_size`,
+        `service_offering`.`nw_rate` AS `nw_rate`,
+        `service_offering`.`mc_rate` AS `mc_rate`,
+        `service_offering`.`ha_enabled` AS `ha_enabled`,
+        `service_offering`.`limit_cpu_use` AS `limit_cpu_use`,
+        `service_offering`.`host_tag` AS `host_tag`,
+        `service_offering`.`default_use` AS `default_use`,
+        `service_offering`.`vm_type` AS `vm_type`,
+        `service_offering`.`sort_key` AS `sort_key`,
+        `service_offering`.`is_volatile` AS `is_volatile`,
+        `service_offering`.`deployment_planner` AS `deployment_planner`,
+        `service_offering`.`dynamic_scaling_enabled` AS 
`dynamic_scaling_enabled`,
+        `vsphere_storage_policy`.`value` AS `vsphere_storage_policy`,
+        GROUP_CONCAT(DISTINCT(domain.id)) AS domain_id,
+        GROUP_CONCAT(DISTINCT(domain.uuid)) AS domain_uuid,
+        GROUP_CONCAT(DISTINCT(domain.name)) AS domain_name,
+        GROUP_CONCAT(DISTINCT(domain.path)) AS domain_path,
+        GROUP_CONCAT(DISTINCT(zone.id)) AS zone_id,
+        GROUP_CONCAT(DISTINCT(zone.uuid)) AS zone_uuid,
+        GROUP_CONCAT(DISTINCT(zone.name)) AS zone_name,
+        IFNULL(`min_compute_details`.`value`, `cpu`) AS min_cpu,
+        IFNULL(`max_compute_details`.`value`, `cpu`) AS max_cpu,
+        IFNULL(`min_memory_details`.`value`, `ram_size`) AS min_memory,
+        IFNULL(`max_memory_details`.`value`, `ram_size`) AS max_memory
+    FROM
+        `cloud`.`service_offering`
+            INNER JOIN
+        `cloud`.`disk_offering_view` AS `disk_offering` ON service_offering.id 
= disk_offering.id
+            LEFT JOIN
+        `cloud`.`service_offering_details` AS `domain_details` ON 
`domain_details`.`service_offering_id` = `disk_offering`.`id` AND 
`domain_details`.`name`='domainid'
+            LEFT JOIN
+        `cloud`.`domain` AS `domain` ON FIND_IN_SET(`domain`.`id`, 
`domain_details`.`value`)
+            LEFT JOIN
+        `cloud`.`service_offering_details` AS `zone_details` ON 
`zone_details`.`service_offering_id` = `disk_offering`.`id` AND 
`zone_details`.`name`='zoneid'
+            LEFT JOIN
+        `cloud`.`data_center` AS `zone` ON FIND_IN_SET(`zone`.`id`, 
`zone_details`.`value`)
+                       LEFT JOIN
+               `cloud`.`service_offering_details` AS `min_compute_details` ON 
`min_compute_details`.`service_offering_id` = `disk_offering`.`id`
+                               AND `min_compute_details`.`name` = 
'mincpunumber'
+                       LEFT JOIN
+               `cloud`.`service_offering_details` AS `max_compute_details` ON 
`max_compute_details`.`service_offering_id` = `disk_offering`.`id`
+                               AND `max_compute_details`.`name` = 
'maxcpunumber'
+                       LEFT JOIN
+               `cloud`.`service_offering_details` AS `min_memory_details` ON 
`min_memory_details`.`service_offering_id` = `disk_offering`.`id`
+                               AND `min_memory_details`.`name` = 'minmemory'
+                       LEFT JOIN
+               `cloud`.`service_offering_details` AS `max_memory_details` ON 
`max_memory_details`.`service_offering_id` = `disk_offering`.`id`
+                               AND `max_memory_details`.`name` = 'maxmemory'
+                       LEFT JOIN
+               `cloud`.`service_offering_details` AS `vsphere_storage_policy` 
ON `vsphere_storage_policy`.`service_offering_id` = `disk_offering`.`id`
+                               AND `vsphere_storage_policy`.`name` = 
'storagepolicy'
+    WHERE
+        `disk_offering`.`state`='Active'
+    GROUP BY
+        `service_offering`.`id`;
+
 --;
 -- Stored procedure to do idempotent column add;
 -- This is copied from schema-41000to41100.sql
@@ -300,7 +391,7 @@ from
         left join
     `cloud`.`resource_count` secondary_storage_count ON domain.id = 
secondary_storage_count.domain_id
         and secondary_storage_count.type = 'secondary_storage';
-        
+
 -- Update name for global configuration user.vm.readonly.ui.details
 Update configuration set name='user.vm.readonly.details' where 
name='user.vm.readonly.ui.details';
 
diff --git 
a/framework/quota/src/main/java/org/apache/cloudstack/quota/vo/ServiceOfferingVO.java
 
b/framework/quota/src/main/java/org/apache/cloudstack/quota/vo/ServiceOfferingVO.java
index 5ac401e..ab6b931 100644
--- 
a/framework/quota/src/main/java/org/apache/cloudstack/quota/vo/ServiceOfferingVO.java
+++ 
b/framework/quota/src/main/java/org/apache/cloudstack/quota/vo/ServiceOfferingVO.java
@@ -75,6 +75,9 @@ public class ServiceOfferingVO extends DiskOfferingVO 
implements ServiceOffering
     @Column(name = "deployment_planner")
     private String deploymentPlanner = null;
 
+    @Column(name = "dynamic_scaling_enabled")
+    private boolean dynamicScalingEnabled;
+
     @Transient
     Map<String, String> details = new HashMap<String, String>();
 
@@ -284,4 +287,9 @@ public class ServiceOfferingVO extends DiskOfferingVO 
implements ServiceOffering
     public void setDynamicFlag(boolean isdynamic) {
         isDynamic = isdynamic;
     }
+
+    @Override
+    public boolean isDynamicScalingEnabled() {
+        return dynamicScalingEnabled;
+    }
 }
diff --git 
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java
 
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java
index 17def80..28f9259 100644
--- 
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java
+++ 
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java
@@ -374,7 +374,7 @@ public class KubernetesClusterResourceModifierActionWorker 
extends KubernetesClu
         nodeVm = 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);
+                null, addrs, null, null, null, customParameterMap, null, null, 
null, null, true);
         if (LOGGER.isInfoEnabled()) {
             LOGGER.info(String.format("Created node VM : %s, %s in the 
Kubernetes cluster : %s", hostName, nodeVm.getUuid(), 
kubernetesCluster.getName()));
         }
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 54c3a62..c6f939c 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
@@ -211,7 +211,7 @@ public class KubernetesClusterStartWorker extends 
KubernetesClusterResourceModif
         controlVm = 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);
+                requestedIps, addrs, null, null, null, customParameterMap, 
null, null, null, null, true);
         if (LOGGER.isInfoEnabled()) {
             LOGGER.info(String.format("Created control VM ID: %s, %s in the 
Kubernetes cluster : %s", controlVm.getUuid(), hostName, 
kubernetesCluster.getName()));
         }
@@ -265,7 +265,7 @@ public class KubernetesClusterStartWorker extends 
KubernetesClusterResourceModif
         additionalControlVm = 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);
+                null, addrs, null, null, null, customParameterMap, null, null, 
null, null, true);
         if (LOGGER.isInfoEnabled()) {
             LOGGER.info(String.format("Created control VM ID : %s, %s in the 
Kubernetes cluster : %s", additionalControlVm.getUuid(), hostName, 
kubernetesCluster.getName()));
         }
diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java 
b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
index a7968cc..b84e10d 100644
--- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
@@ -1470,6 +1470,7 @@ public class ApiResponseHelper implements 
ResponseGenerator {
                 vmResponse.setState(vm.getState().toString());
             }
 
+            vmResponse.setDynamicallyScalable(vm.isDynamicallyScalable());
             // for console proxies, add the active sessions
             if (vm.getType() == Type.ConsoleProxy) {
                 ConsoleProxyVO proxy = ApiDBUtils.findConsoleProxy(vm.getId());
diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java 
b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
index ae82120..e388a75 100644
--- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
@@ -2971,11 +2971,12 @@ public class QueryManagerImpl extends 
MutualExclusiveIdsManagerBase implements Q
             // 1. Only return offerings with the same storage type than the 
storage pool where the VM's root volume is allocated
             sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, 
isRootVolumeUsingLocalStorage);
 
-            // 2.In case vm is running return only offerings greater than 
equal to current offering compute.
+            // 2.In case vm is running return only offerings greater than 
equal to current offering compute and offering's dynamic scalability should 
match
             if (vmInstance.getState() == VirtualMachine.State.Running) {
                 sc.addAnd("cpu", Op.GTEQ, currentVmOffering.getCpu());
                 sc.addAnd("speed", Op.GTEQ, currentVmOffering.getSpeed());
                 sc.addAnd("ramSize", Op.GTEQ, currentVmOffering.getRamSize());
+                sc.addAnd("dynamicScalingEnabled", Op.EQ, 
currentVmOffering.isDynamicScalingEnabled());
             }
         }
 
diff --git 
a/server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java 
b/server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java
index 87b0374..55faa39 100644
--- 
a/server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java
+++ 
b/server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java
@@ -113,6 +113,7 @@ public class ServiceOfferingJoinDaoImpl extends 
GenericDaoBase<ServiceOfferingJo
         offeringResponse.setObjectName("serviceoffering");
         offeringResponse.setIscutomized(offering.isDynamic());
         offeringResponse.setCacheMode(offering.getCacheMode());
+        
offeringResponse.setDynamicScalingEnabled(offering.isDynamicScalingEnabled());
 
         if (offeringDetails != null && !offeringDetails.isEmpty()) {
             String vsphereStoragePolicyId = 
offeringDetails.get(ApiConstants.STORAGE_POLICY);
diff --git 
a/server/src/main/java/com/cloud/api/query/vo/ServiceOfferingJoinVO.java 
b/server/src/main/java/com/cloud/api/query/vo/ServiceOfferingJoinVO.java
index 4d9b2cd..e9b2f2d 100644
--- a/server/src/main/java/com/cloud/api/query/vo/ServiceOfferingJoinVO.java
+++ b/server/src/main/java/com/cloud/api/query/vo/ServiceOfferingJoinVO.java
@@ -193,6 +193,9 @@ public class ServiceOfferingJoinVO extends BaseViewVO 
implements InternalIdentit
     @Column(name = "root_disk_size")
     private Long rootDiskSize;
 
+    @Column(name = "dynamic_scaling_enabled")
+    private boolean dynamicScalingEnabled;
+
     public ServiceOfferingJoinVO() {
     }
 
@@ -397,4 +400,12 @@ public class ServiceOfferingJoinVO extends BaseViewVO 
implements InternalIdentit
     public Long getRootDiskSize() {
         return rootDiskSize ;
     }
+
+    public boolean isDynamicScalingEnabled() {
+        return dynamicScalingEnabled;
+    }
+
+    public void setDynamicScalingEnabled(boolean dynamicScalingEnabled) {
+        this.dynamicScalingEnabled = dynamicScalingEnabled;
+    }
 }
diff --git 
a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java 
b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
index 6e21386..cb7e4b5 100755
--- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -2481,7 +2481,7 @@ public class ConfigurationManagerImpl extends ManagerBase 
implements Configurati
                 cmd.getBytesWriteRate(), cmd.getBytesWriteRateMax(), 
cmd.getBytesWriteRateMaxLength(),
                 cmd.getIopsReadRate(), cmd.getIopsReadRateMax(), 
cmd.getIopsReadRateMaxLength(),
                 cmd.getIopsWriteRate(), cmd.getIopsWriteRateMax(), 
cmd.getIopsWriteRateMaxLength(),
-                cmd.getHypervisorSnapshotReserve(), cmd.getCacheMode(), 
storagePolicyId);
+                cmd.getHypervisorSnapshotReserve(), cmd.getCacheMode(), 
storagePolicyId, cmd.getDynamicScalingEnabled());
     }
 
     protected ServiceOfferingVO createServiceOffering(final long userId, final 
boolean isSystem, final VirtualMachine.Type vmType,
@@ -2492,7 +2492,7 @@ public class ConfigurationManagerImpl extends ManagerBase 
implements Configurati
             Long bytesWriteRate, Long bytesWriteRateMax, Long 
bytesWriteRateMaxLength,
             Long iopsReadRate, Long iopsReadRateMax, Long 
iopsReadRateMaxLength,
             Long iopsWriteRate, Long iopsWriteRateMax, Long 
iopsWriteRateMaxLength,
-            final Integer hypervisorSnapshotReserve, String cacheMode, final 
Long storagePolicyID) {
+            final Integer hypervisorSnapshotReserve, String cacheMode, final 
Long storagePolicyID, final boolean dynamicScalingEnabled) {
         // Filter child domains when both parent and child domains are present
         List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
 
@@ -2524,7 +2524,7 @@ public class ConfigurationManagerImpl extends ManagerBase 
implements Configurati
 
         ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, 
speed, networkRate, null, offerHA,
                 limitResourceUse, volatileVm, displayText, 
typedProvisioningType, localStorageRequired, false, tags, isSystem, vmType,
-                hostTag, deploymentPlanner);
+                hostTag, deploymentPlanner, dynamicScalingEnabled);
 
         if (Boolean.TRUE.equals(isCustomizedIops) || isCustomizedIops == null) 
{
                 minIops = null;
diff --git a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java 
b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
index 7d6c888..2a8b13e 100644
--- a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -54,7 +54,6 @@ import com.cloud.utils.Pair;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.NicVO;
-import com.cloud.vm.UserVmManager;
 import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachineProfile;
@@ -257,9 +256,7 @@ public abstract class HypervisorGuruBase extends 
AdapterBase implements Hypervis
 
         // Workaround to make sure the TO has the UUID we need for Niciri 
integration
         VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId());
-        // check if XStools/VMWare tools are present in the VM and dynamic 
scaling feature is enabled (per zone/global)
-        Boolean isDynamicallyScalable = vmInstance.isDynamicallyScalable() && 
UserVmManager.EnableDynamicallyScaleVm.valueIn(vm.getDataCenterId());
-        to.setEnableDynamicallyScaleVm(isDynamicallyScalable);
+        to.setEnableDynamicallyScaleVm(vmInstance.isDynamicallyScalable());
         to.setUuid(vmInstance.getUuid());
 
         to.setVmData(vmProfile.getVmData());
diff --git 
a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java 
b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java
index c710549..5e7f0a9 100644
--- a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java
@@ -1325,18 +1325,18 @@ public class AutoScaleManagerImpl<Type> extends 
ManagerBase implements AutoScale
                 vm = 
_userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, 
template, null, owner, "autoScaleVm-" + asGroup.getId() + "-" +
                     getCurrentTimeStampString(),
                     "autoScaleVm-" + asGroup.getId() + "-" + 
getCurrentTimeStampString(), null, null, null, HypervisorType.XenServer, 
HTTPMethod.GET, null, null, null,
-                    null, true, null, null, null, null, null, null, null);
+                    null, true, null, null, null, null, null, null, null, 
true);
             } else {
                 if (zone.isSecurityGroupEnabled()) {
                     vm = 
_userVmService.createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, 
template, null, null,
                         owner, "autoScaleVm-" + asGroup.getId() + "-" + 
getCurrentTimeStampString(),
                         "autoScaleVm-" + asGroup.getId() + "-" + 
getCurrentTimeStampString(), null, null, null, HypervisorType.XenServer, 
HTTPMethod.GET, null, null,
-                        null, null, true, null, null, null, null, null, null, 
null);
+                        null, null, true, null, null, null, null, null, null, 
null, true);
 
                 } else {
                     vm = _userVmService.createAdvancedVirtualMachine(zone, 
serviceOffering, template, null, owner, "autoScaleVm-" + asGroup.getId() + "-" +
                         getCurrentTimeStampString(), "autoScaleVm-" + 
asGroup.getId() + "-" + getCurrentTimeStampString(),
-                        null, null, null, HypervisorType.XenServer, 
HTTPMethod.GET, null, null, null, addrs, true, null, null, null, null, null, 
null, null);
+                        null, null, null, HypervisorType.XenServer, 
HTTPMethod.GET, null, null, null, addrs, true, null, null, null, null, null, 
null, null, true);
 
                 }
             }
diff --git a/server/src/main/java/com/cloud/vm/UserVmManager.java 
b/server/src/main/java/com/cloud/vm/UserVmManager.java
index e4206ef..98b7cb2 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<Long, List<VmNetworkStatsEntry>> getVmNetworkStatistics(long 
hostId, String hostName, List<Long> vmIds);
+
+    boolean checkIfDynamicScalingCanBeEnabled(VirtualMachine vm, 
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 d9dc32d..14cdae6 100644
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@ -1888,6 +1888,10 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
         _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
 
         ServiceOfferingVO currentServiceOffering = 
_offeringDao.findByIdIncludingRemoved(vmInstance.getId(), 
vmInstance.getServiceOfferingId());
+        if (newServiceOffering.isDynamicScalingEnabled() != 
currentServiceOffering.isDynamicScalingEnabled()) {
+            throw new InvalidParameterValueException("Unable to Scale VM: 
since dynamic scaling enabled flag is not same for new service offering and old 
service offering");
+        }
+
         int newCpu = newServiceOffering.getCpu();
         int newMemory = newServiceOffering.getRamSize();
         int newSpeed = newServiceOffering.getSpeed();
@@ -1939,7 +1943,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
             // Check vm flag
             if (!vmInstance.isDynamicallyScalable()) {
-                throw new CloudRuntimeException("Unable to Scale the vm: " + 
vmInstance.getUuid() + " as vm does not have tools to support dynamic scaling");
+                throw new CloudRuntimeException("Unable to Scale the VM: " + 
vmInstance.getUuid() + " as VM is not configured to be dynamically scalable");
             }
 
             // Check disable threshold for cluster is not crossed
@@ -2777,10 +2781,6 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
             userData = vm.getUserData();
         }
 
-        if (isDynamicallyScalable == null) {
-            isDynamicallyScalable = vm.isDynamicallyScalable();
-        }
-
         if (osTypeId == null) {
             osTypeId = vm.getGuestOSId();
         }
@@ -2791,6 +2791,20 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
         if (isDynamicallyScalable == null) {
             isDynamicallyScalable = vm.isDynamicallyScalable();
+        } else {
+            if (isDynamicallyScalable == true) {
+                VMTemplateVO template = 
_templateDao.findByIdIncludingRemoved(vm.getTemplateId());
+                if (!template.isDynamicallyScalable()) {
+                    throw new InvalidParameterValueException("Dynamic Scaling 
cannot be enabled for the VM since its template does not have dynamic scaling 
enabled");
+                }
+                if (!offering.isDynamicScalingEnabled()) {
+                    throw new InvalidParameterValueException("Dynamic Scaling 
cannot be enabled for the VM since its service offering does not have dynamic 
scaling enabled");
+                }
+                if 
(!UserVmManager.EnableDynamicallyScaleVm.valueIn(vm.getDataCenterId())) {
+                    s_logger.debug(String.format("Dynamic Scaling cannot be 
enabled for the VM %s since the global setting enable.dynamic.scale.vm is set 
to false", vm.getUuid()));
+                    throw new InvalidParameterValueException("Dynamic Scaling 
cannot be enabled for the VM since corresponding global setting is set to 
false");
+                }
+            }
         }
 
         boolean isVMware = (vm.getHypervisorType() == HypervisorType.VMware);
@@ -3239,7 +3253,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
             Account owner, String hostName, String displayName, Long 
diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, 
HTTPMethod httpmethod,
             String userData, String sshKeyPair, Map<Long, IpAddresses> 
requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, 
List<Long> affinityGroupIdList,
             Map<String, String> customParametes, String customId, Map<String, 
Map<Integer, String>> dhcpOptionMap,
-            Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, 
Map<String, String> userVmOVFProperties) throws InsufficientCapacityException, 
ConcurrentOperationException, ResourceUnavailableException,
+            Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, 
Map<String, String> userVmOVFProperties, boolean dynamicScalingEnabled) throws 
InsufficientCapacityException, ConcurrentOperationException, 
ResourceUnavailableException,
     StorageUnavailableException, ResourceAllocationException {
 
         Account caller = CallContext.current().getCallingAccount();
@@ -3288,7 +3302,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
         return createVirtualMachine(zone, serviceOffering, template, hostName, 
displayName, owner, diskOfferingId, diskSize, networkList, securityGroupIdList, 
group, httpmethod,
                 userData, sshKeyPair, hypervisor, caller, requestedIps, 
defaultIps, displayVm, keyboard, affinityGroupIdList, customParametes, 
customId, dhcpOptionMap,
-                dataDiskTemplateToDiskOfferingMap, userVmOVFProperties);
+                dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, 
dynamicScalingEnabled);
 
     }
 
@@ -3298,7 +3312,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
             List<Long> securityGroupIdList, Account owner, String hostName, 
String displayName, Long diskOfferingId, Long diskSize, String group, 
HypervisorType hypervisor,
             HTTPMethod httpmethod, String userData, String sshKeyPair, 
Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, 
String keyboard,
             List<Long> affinityGroupIdList, Map<String, String> 
customParameters, String customId, Map<String, Map<Integer, String>> 
dhcpOptionMap,
-            Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, 
Map<String, String> userVmOVFProperties) throws InsufficientCapacityException, 
ConcurrentOperationException,
+            Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, 
Map<String, String> userVmOVFProperties, boolean dynamicScalingEnabled) throws 
InsufficientCapacityException, ConcurrentOperationException,
     ResourceUnavailableException, StorageUnavailableException, 
ResourceAllocationException {
 
         Account caller = CallContext.current().getCallingAccount();
@@ -3399,7 +3413,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
         return createVirtualMachine(zone, serviceOffering, template, hostName, 
displayName, owner, diskOfferingId, diskSize, networkList, securityGroupIdList, 
group, httpmethod,
                 userData, sshKeyPair, hypervisor, caller, requestedIps, 
defaultIps, displayVm, keyboard, affinityGroupIdList, customParameters, 
customId, dhcpOptionMap, dataDiskTemplateToDiskOfferingMap,
-                userVmOVFProperties);
+                userVmOVFProperties, dynamicScalingEnabled);
     }
 
     @Override
@@ -3408,7 +3422,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
             String hostName, String displayName, Long diskOfferingId, Long 
diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, 
String userData,
             String sshKeyPair, Map<Long, IpAddresses> requestedIps, 
IpAddresses defaultIps, Boolean displayvm, String keyboard, List<Long> 
affinityGroupIdList,
             Map<String, String> customParametrs, String customId, Map<String, 
Map<Integer, String>> dhcpOptionsMap, Map<Long, DiskOffering> 
dataDiskTemplateToDiskOfferingMap,
-            Map<String, String> userVmOVFPropertiesMap) throws 
InsufficientCapacityException, ConcurrentOperationException, 
ResourceUnavailableException,
+            Map<String, String> userVmOVFPropertiesMap, boolean 
dynamicScalingEnabled) throws InsufficientCapacityException, 
ConcurrentOperationException, ResourceUnavailableException,
     StorageUnavailableException, ResourceAllocationException {
 
         Account caller = CallContext.current().getCallingAccount();
@@ -3460,7 +3474,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
         return createVirtualMachine(zone, serviceOffering, template, hostName, 
displayName, owner, diskOfferingId, diskSize, networkList, null, group, 
httpmethod, userData,
                 sshKeyPair, hypervisor, caller, requestedIps, defaultIps, 
displayvm, keyboard, affinityGroupIdList, customParametrs, customId, 
dhcpOptionsMap,
-                dataDiskTemplateToDiskOfferingMap, userVmOVFPropertiesMap);
+                dataDiskTemplateToDiskOfferingMap, userVmOVFPropertiesMap, 
dynamicScalingEnabled);
     }
 
     private NetworkVO getNetworkToAddToNetworkList(VirtualMachineTemplate 
template, Account owner, HypervisorType hypervisor,
@@ -3575,11 +3589,11 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
     @DB
     private UserVm createVirtualMachine(DataCenter zone, ServiceOffering 
serviceOffering, VirtualMachineTemplate tmplt, String hostName, String 
displayName, Account owner,
-            Long diskOfferingId, Long diskSize, List<NetworkVO> networkList, 
List<Long> securityGroupIdList, String group, HTTPMethod httpmethod, String 
userData,
-            String sshKeyPair, HypervisorType hypervisor, Account caller, 
Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean 
isDisplayVm, String keyboard,
-            List<Long> affinityGroupIdList, Map<String, String> 
customParameters, String customId, Map<String, Map<Integer, String>> 
dhcpOptionMap,
-            Map<Long, DiskOffering> datadiskTemplateToDiskOfferringMap,
-            Map<String, String> userVmOVFPropertiesMap) throws 
InsufficientCapacityException, ResourceUnavailableException,
+                                        Long diskOfferingId, Long diskSize, 
List<NetworkVO> networkList, List<Long> securityGroupIdList, String group, 
HTTPMethod httpmethod, String userData,
+                                        String sshKeyPair, HypervisorType 
hypervisor, Account caller, Map<Long, IpAddresses> requestedIps, IpAddresses 
defaultIps, Boolean isDisplayVm, String keyboard,
+                                        List<Long> affinityGroupIdList, 
Map<String, String> customParameters, String customId, Map<String, Map<Integer, 
String>> dhcpOptionMap,
+                                        Map<Long, DiskOffering> 
datadiskTemplateToDiskOfferringMap,
+                                        Map<String, String> 
userVmOVFPropertiesMap, boolean dynamicScalingEnabled) throws 
InsufficientCapacityException, ResourceUnavailableException,
     ConcurrentOperationException, StorageUnavailableException, 
ResourceAllocationException {
 
         _accountMgr.checkAccess(caller, null, true, owner);
@@ -3939,9 +3953,11 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
             }
         }
 
+        dynamicScalingEnabled = dynamicScalingEnabled && 
checkIfDynamicScalingCanBeEnabled(null, 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,
-                datadiskTemplateToDiskOfferringMap, userVmOVFPropertiesMap);
+                datadiskTemplateToDiskOfferringMap, userVmOVFPropertiesMap, 
dynamicScalingEnabled);
 
         // Assign instance to the group
         try {
@@ -3965,6 +3981,16 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
         return vm;
     }
 
+    @Override
+    public boolean checkIfDynamicScalingCanBeEnabled(VirtualMachine vm, 
ServiceOffering offering, VirtualMachineTemplate template, Long zoneId) {
+        boolean canEnableDynamicScaling = (vm != null ? 
vm.isDynamicallyScalable() : true) && 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 canEnableDynamicScaling;
+    }
+
     /**
      * Configures the Root disk size via User`s custom parameters.
      * If the Service Offering has the Root Disk size field configured then 
the User`s root disk custom parameter is overwritten by the service offering.
@@ -4043,14 +4069,14 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
                                   final long accountId, final long userId, 
final ServiceOffering offering, final boolean isIso, final String sshPublicKey, 
final LinkedHashMap<String, List<NicProfile>> networkNicMap,
                                   final long id, final String instanceName, 
final String uuidName, final HypervisorType hypervisorType, final Map<String, 
String> customParameters,
                                   final Map<String, Map<Integer, String>> 
extraDhcpOptionMap, final Map<Long, DiskOffering> 
dataDiskTemplateToDiskOfferingMap,
-                                  final Map<String, String> 
userVmOVFPropertiesMap, final VirtualMachine.PowerState powerState) throws 
InsufficientCapacityException {
+                                  final Map<String, String> 
userVmOVFPropertiesMap, final VirtualMachine.PowerState powerState, final 
boolean dynamicScalingEnabled) throws InsufficientCapacityException {
         return Transaction.execute(new 
TransactionCallbackWithException<UserVmVO, InsufficientCapacityException>() {
             @Override
             public UserVmVO doInTransaction(TransactionStatus status) throws 
InsufficientCapacityException {
                 UserVmVO vm = new UserVmVO(id, instanceName, displayName, 
template.getId(), hypervisorType, template.getGuestOSId(), offering.isOfferHA(),
                         offering.getLimitCpuUse(), owner.getDomainId(), 
owner.getId(), userId, offering.getId(), userData, hostName, diskOfferingId);
                 vm.setUuid(uuidName);
-                vm.setDynamicallyScalable(template.isDynamicallyScalable());
+                vm.setDynamicallyScalable(dynamicScalingEnabled);
 
                 Map<String, String> details = template.getDetails();
                 if (details != null && !details.isEmpty()) {
@@ -4235,13 +4261,13 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
             final long accountId, final long userId, final ServiceOfferingVO 
offering, final boolean isIso, final String sshPublicKey, final 
LinkedHashMap<String, List<NicProfile>> networkNicMap,
             final long id, final String instanceName, final String uuidName, 
final HypervisorType hypervisorType, final Map<String, String> 
customParameters, final Map<String,
             Map<Integer, String>> extraDhcpOptionMap, final Map<Long, 
DiskOffering> dataDiskTemplateToDiskOfferingMap,
-            Map<String, String> userVmOVFPropertiesMap) throws 
InsufficientCapacityException {
+            Map<String, String> userVmOVFPropertiesMap, final boolean 
dynamicScalingEnabled) throws InsufficientCapacityException {
         return commitUserVm(false, zone, null, null, template, hostName, 
displayName, owner,
                 diskOfferingId, diskSize, userData, caller, isDisplayVm, 
keyboard,
                 accountId, userId, offering, isIso, sshPublicKey, 
networkNicMap,
                 id, instanceName, uuidName, hypervisorType, customParameters,
                 extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap,
-                userVmOVFPropertiesMap, null);
+                userVmOVFPropertiesMap, null, dynamicScalingEnabled);
     }
 
     public void validateRootDiskResize(final HypervisorType hypervisorType, 
Long rootDiskSize, VMTemplateVO templateVO, UserVmVO vm, final Map<String, 
String> customParameters) throws InvalidParameterValueException
@@ -5326,6 +5352,8 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
         Long templateId = cmd.getTemplateId();
 
+        boolean dynamicScalingEnabled = cmd.isDynamicScalingEnabled();
+
         VirtualMachineTemplate template = 
_entityMgr.findById(VirtualMachineTemplate.class, templateId);
         // Make sure a valid template ID was specified
         if (template == null) {
@@ -5403,14 +5431,14 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
                 vm = createBasicSecurityGroupVirtualMachine(zone, 
serviceOffering, template, getSecurityGroupIdList(cmd), owner, name, 
displayName, diskOfferingId,
                         size , group , cmd.getHypervisor(), 
cmd.getHttpMethod(), userData , sshKeyPairName , cmd.getIpToNetworkMap(), 
addrs, displayVm , keyboard , cmd.getAffinityGroupIdList(),
                         cmd.getDetails(), cmd.getCustomId(), 
cmd.getDhcpOptionsMap(),
-                        dataDiskTemplateToDiskOfferingMap, 
userVmOVFProperties);
+                        dataDiskTemplateToDiskOfferingMap, 
userVmOVFProperties, dynamicScalingEnabled);
             }
         } else {
             if (zone.isSecurityGroupEnabled())  {
                 vm = createAdvancedSecurityGroupVirtualMachine(zone, 
serviceOffering, template, networkIds, getSecurityGroupIdList(cmd), owner, name,
                         displayName, diskOfferingId, size, group, 
cmd.getHypervisor(), cmd.getHttpMethod(), userData, sshKeyPairName, 
cmd.getIpToNetworkMap(), addrs, displayVm, keyboard,
                         cmd.getAffinityGroupIdList(), cmd.getDetails(), 
cmd.getCustomId(), cmd.getDhcpOptionsMap(),
-                        dataDiskTemplateToDiskOfferingMap, 
userVmOVFProperties);
+                        dataDiskTemplateToDiskOfferingMap, 
userVmOVFProperties, dynamicScalingEnabled);
 
             } else {
                 if (cmd.getSecurityGroupIdList() != null && 
!cmd.getSecurityGroupIdList().isEmpty()) {
@@ -5418,7 +5446,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
                 }
                 vm = createAdvancedVirtualMachine(zone, serviceOffering, 
template, networkIds, owner, name, displayName, diskOfferingId, size, group,
                         cmd.getHypervisor(), cmd.getHttpMethod(), userData, 
sshKeyPairName, cmd.getIpToNetworkMap(), addrs, displayVm, keyboard, 
cmd.getAffinityGroupIdList(), cmd.getDetails(),
-                        cmd.getCustomId(), cmd.getDhcpOptionsMap(), 
dataDiskTemplateToDiskOfferingMap, userVmOVFProperties);
+                        cmd.getCustomId(), cmd.getDhcpOptionsMap(), 
dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, dynamicScalingEnabled);
             }
         }
         // check if this templateId has a child ISO
@@ -7083,13 +7111,13 @@ 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 and update VM if it can be dynamically scalable 
with the new template
+                    updateVMDynamicallyScalabilityUsingTemplate(vm, 
newTemplateId);
                 } else {
                     newVol = volumeMgr.allocateDuplicateVolume(root, null);
                 }
@@ -7177,6 +7205,14 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
     }
 
+    private void updateVMDynamicallyScalabilityUsingTemplate(UserVmVO vm, Long 
newTemplateId) {
+        ServiceOfferingVO serviceOffering = 
_offeringDao.findById(vm.getServiceOfferingId());
+        VMTemplateVO newTemplate = _templateDao.findById(newTemplateId);
+        boolean dynamicScalingEnabled = checkIfDynamicScalingCanBeEnabled(vm, 
serviceOffering, newTemplate, vm.getDataCenterId());
+        vm.setDynamicallyScalable(dynamicScalingEnabled);
+        _vmDao.update(vm.getId(), vm);
+    }
+
     /**
      * Perform basic checkings to make sure restore is possible. If not, 
#InvalidParameterValueException is thrown.
      *
@@ -7494,11 +7530,12 @@ 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 = 
checkIfDynamicScalingCanBeEnabled(null, 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,
                 id, instanceName, uuidName, hypervisorType, customParameters,
-                null, null, null, powerState);
+                null, null, null, powerState, dynamicScalingEnabled);
     }
 
     @Override
diff --git 
a/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java 
b/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java
index ab73e63..97e15de 100644
--- 
a/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java
+++ 
b/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java
@@ -214,7 +214,7 @@ public class DeploymentPlanningManagerImplTest {
         ServiceOfferingVO svcOffering =
             new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, 
false, false, "test dpm",
                     ProvisioningType.THIN, false, false, null, false, 
VirtualMachine.Type.User,
-                    null, "FirstFitPlanner");
+                    null, "FirstFitPlanner", true);
         Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
 
         DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
@@ -229,7 +229,7 @@ public class DeploymentPlanningManagerImplTest {
         ServiceOfferingVO svcOffering =
             new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, 
false, false, "test dpm",
                     ProvisioningType.THIN, false, false, null, false, 
VirtualMachine.Type.User,
-                    null, "UserDispersingPlanner");
+                    null, "UserDispersingPlanner", true);
         Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
 
         DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
@@ -245,7 +245,7 @@ public class DeploymentPlanningManagerImplTest {
         ServiceOfferingVO svcOffering =
             new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, 
false, false, "test dpm",
                 ProvisioningType.THIN, false, false, null, false, 
VirtualMachine.Type.User,
-                    null, "FirstFitPlanner");
+                    null, "FirstFitPlanner", true);
         Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
 
         DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
diff --git a/test/integration/smoke/test_scale_vm.py 
b/test/integration/smoke/test_scale_vm.py
index 64ab380..c9b1bf8 100644
--- a/test/integration/smoke/test_scale_vm.py
+++ b/test/integration/smoke/test_scale_vm.py
@@ -67,6 +67,11 @@ class TestScaleVm(cloudstackTestCase):
             if cls.template == FAILED:
                 assert False, "get_template() failed to return template\
                         with description %s" % cls.services["ostype"]
+            cls.template = Template.update(
+                cls.template,
+                cls.apiclient,
+                isdynamicallyscalable='true'
+            )
         else:
             cls.template = Template.register(
                        cls.apiclient,
@@ -107,6 +112,18 @@ class TestScaleVm(cloudstackTestCase):
                     value="true"
                 )
 
+        cls.small_offering_dynamic_scaling_disabled = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["service_offerings"]["small"],
+            dynamicscalingenabled=False
+        )
+
+        cls.big_offering_dynamic_scaling_disabled = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["service_offerings"]["small"],
+            dynamicscalingenabled=False
+        )
+
         # create a virtual machine
         cls.virtual_machine = VirtualMachine.create(
             cls.apiclient,
@@ -117,8 +134,42 @@ class TestScaleVm(cloudstackTestCase):
             mode=cls.services["mode"]
         )
 
+        # create a virtual machine which cannot be dynamically scalable
+        cls.virtual_machine_with_service_offering_dynamic_scaling_disabled = 
VirtualMachine.create(
+            cls.apiclient,
+            cls.services["small"],
+            accountid=cls.account.name,
+            domainid=cls.account.domainid,
+            serviceofferingid=cls.small_offering_dynamic_scaling_disabled.id,
+            mode=cls.services["mode"]
+        )
+
+        # create a virtual machine which cannot be dynamically scalable
+        cls.virtual_machine_not_dynamically_scalable = VirtualMachine.create(
+            cls.apiclient,
+            cls.services["small"],
+            accountid=cls.account.name,
+            domainid=cls.account.domainid,
+            serviceofferingid=cls.small_offering.id,
+            mode=cls.services["mode"],
+            dynamicscalingenabled=False
+        )
+
+        cls._cleanup = [
+            cls.small_offering,
+            cls.big_offering,
+            cls.small_offering_dynamic_scaling_disabled,
+            cls.big_offering_dynamic_scaling_disabled,
+            cls.account
+        ]
+
     @classmethod
     def tearDownClass(cls):
+        Configurations.update(
+            cls.apiclient,
+            name="enable.dynamic.scale.vm",
+            value="false"
+        )
         super(TestScaleVm,cls).tearDownClass()
         return
 
@@ -132,11 +183,6 @@ class TestScaleVm(cloudstackTestCase):
                     %s" % self.hypervisor)
 
     def tearDown(self):
-        Configurations.update(
-            self.apiclient,
-            name="enable.dynamic.scale.vm",
-            value="false"
-        )
         # Clean up, terminate the created ISOs
         super(TestScaleVm,self).tearDown()
         return
@@ -265,3 +311,173 @@ class TestScaleVm(cloudstackTestCase):
             "Check the state of VM"
         )
         return
+
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_02_scale_vm(self):
+        """Test scale virtual machine which is created from a service offering 
for which dynamicscalingenabled is false. Scaling operation should fail.
+        """
+
+        #        VirtualMachine should be updated to tell cloudstack
+        #        it has PV tools
+        #        available and successfully scaled. We will only mock
+        #        that behaviour
+        #        here but it is not expected in production since the VM
+        #        scaling is not
+        #        guaranteed until tools are installed, vm rebooted
+
+        # If hypervisor is Vmware, then check if
+        # the vmware tools are installed and the process is running
+        # Vmware tools are necessary for scale VM operation
+        if self.hypervisor.lower() == "vmware":
+            sshClient = 
self.virtual_machine_with_service_offering_dynamic_scaling_disabled.get_ssh_client()
+            result = str(
+                sshClient.execute("service vmware-tools status")).lower()
+            self.debug("and result is: %s" % result)
+            if not "running" in result:
+                self.skipTest("Skipping scale VM operation because\
+                    VMware tools are not installed on the VM")
+
+        list_vm_response = VirtualMachine.list(
+            self.apiclient,
+            
id=self.virtual_machine_with_service_offering_dynamic_scaling_disabled.id
+        )
+        self.assertEqual(
+            isinstance(list_vm_response, list),
+            True,
+            "Check list response returns a valid list"
+        )
+        self.assertNotEqual(
+            list_vm_response,
+            None,
+            "Check virtual machine is in listVirtualMachines"
+        )
+
+        vm_response = list_vm_response[0]
+        self.assertEqual(
+            vm_response.id,
+            
self.virtual_machine_with_service_offering_dynamic_scaling_disabled.id,
+            "Check virtual machine ID of scaled VM"
+        )
+
+        self.assertEqual(
+            vm_response.isdynamicallyscalable,
+            False,
+            "Check if VM is not dynamically scalable"
+        )
+
+        self.debug("Scaling VM-ID: %s to service offering: %s for which 
dynamic scaling is disabled and VM state %s" % (
+            
self.virtual_machine_with_service_offering_dynamic_scaling_disabled.id,
+            self.big_offering_dynamic_scaling_disabled.id,
+            self.virtual_machine.state
+        ))
+
+        cmd = scaleVirtualMachine.scaleVirtualMachineCmd()
+        cmd.serviceofferingid = self.big_offering_dynamic_scaling_disabled.id
+        cmd.id = 
self.virtual_machine_with_service_offering_dynamic_scaling_disabled.id
+
+        try:
+            self.apiclient.scaleVirtualMachine(cmd)
+        except Exception as e:
+            if "LicenceRestriction" in str(e):
+                self.skipTest("Your XenServer License does not allow scaling")
+            else:
+                pass
+        else:
+            self.fail("Expected an exception to be thrown, failing")
+
+        self.debug("Scaling VM-ID: %s to service offering: %s for which 
dynamic scaling is enabled and VM state %s" % (
+            
self.virtual_machine_with_service_offering_dynamic_scaling_disabled.id,
+            self.big_offering.id,
+            self.virtual_machine.state
+        ))
+
+        cmd = scaleVirtualMachine.scaleVirtualMachineCmd()
+        cmd.serviceofferingid = self.big_offering.id
+        cmd.id = 
self.virtual_machine_with_service_offering_dynamic_scaling_disabled.id
+
+        try:
+            self.apiclient.scaleVirtualMachine(cmd)
+        except Exception as e:
+            if "LicenceRestriction" in str(e):
+                self.skipTest("Your XenServer License does not allow scaling")
+            else:
+                pass
+        else:
+            self.fail("Expected an exception to be thrown, failing")
+
+        return
+
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_03_scale_vm(self):
+        """Test scale virtual machine which is not dynamically scalable to a 
service offering. Scaling operation should fail.
+        """
+        # Validate the following
+        # Scale up the vm which is not dynamically scalable and see if scaling 
operation fails
+
+        #        VirtualMachine should be updated to tell cloudstack
+        #        it has PV tools
+        #        available and successfully scaled. We will only mock
+        #        that behaviour
+        #        here but it is not expected in production since the VM
+        #        scaling is not
+        #        guaranteed until tools are installed, vm rebooted
+
+        # If hypervisor is Vmware, then check if
+        # the vmware tools are installed and the process is running
+        # Vmware tools are necessary for scale VM operation
+        if self.hypervisor.lower() == "vmware":
+            sshClient = 
self.virtual_machine_not_dynamically_scalable.get_ssh_client()
+            result = str(
+                sshClient.execute("service vmware-tools status")).lower()
+            self.debug("and result is: %s" % result)
+            if not "running" in result:
+                self.skipTest("Skipping scale VM operation because\
+                    VMware tools are not installed on the VM")
+
+        list_vm_response = VirtualMachine.list(
+            self.apiclient,
+            id=self.virtual_machine_not_dynamically_scalable.id
+        )
+        self.assertEqual(
+            isinstance(list_vm_response, list),
+            True,
+            "Check list response returns a valid list"
+        )
+        self.assertNotEqual(
+            list_vm_response,
+            None,
+            "Check virtual machine is in listVirtualMachines"
+        )
+        vm_response = list_vm_response[0]
+        self.assertEqual(
+            vm_response.id,
+            self.virtual_machine_not_dynamically_scalable.id,
+            "Check virtual machine ID of scaled VM"
+        )
+        self.assertEqual(
+            vm_response.isdynamicallyscalable,
+            False,
+            "Check if VM is not dynamically scalable"
+        )
+
+        self.debug("Scaling VM-ID: %s to service offering: %s for which 
dynamic scaling is enabled and VM state %s" % (
+            self.virtual_machine_not_dynamically_scalable.id,
+            self.big_offering.id,
+            self.virtual_machine.state
+        ))
+
+        cmd = scaleVirtualMachine.scaleVirtualMachineCmd()
+        cmd.serviceofferingid = self.big_offering.id
+        cmd.id = self.virtual_machine_not_dynamically_scalable.id
+
+        try:
+            self.apiclient.scaleVirtualMachine(cmd)
+        except Exception as e:
+            if "LicenceRestriction" in str(e):
+                self.skipTest("Your XenServer License does not allow scaling")
+            else:
+                pass
+        else:
+            self.fail("Expected an exception to be thrown, failing")
+
+        return
\ No newline at end of file
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 5a8db63..916af64 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -522,7 +522,7 @@ class VirtualMachine:
                method='GET', hypervisor=None, customcpunumber=None,
                customcpuspeed=None, custommemory=None, rootdisksize=None,
                rootdiskcontroller=None, vpcid=None, macaddress=None, 
datadisktemplate_diskoffering_list={},
-               properties=None, nicnetworklist=None, bootmode=None, 
boottype=None):
+               properties=None, nicnetworklist=None, bootmode=None, 
boottype=None, dynamicscalingenabled=None):
         """Create the instance"""
 
         cmd = deployVirtualMachine.deployVirtualMachineCmd()
@@ -615,6 +615,9 @@ class VirtualMachine:
         if "dhcpoptionsnetworklist" in services:
             cmd.dhcpoptionsnetworklist = services["dhcpoptionsnetworklist"]
 
+        if dynamicscalingenabled is not None:
+            cmd.dynamicscalingenabled = dynamicscalingenabled
+
         cmd.details = [{}]
 
         if customcpunumber:
@@ -2293,6 +2296,9 @@ class ServiceOffering:
         if "offerha" in services:
             cmd.offerha = services["offerha"]
 
+        if "dynamicscalingenabled" in services:
+            cmd.dynamicscalingenabled = services["dynamicscalingenabled"]
+
         # Service Offering private to that domain
         if domainid:
             cmd.domainid = domainid
diff --git a/ui/public/locales/de_DE.json b/ui/public/locales/de_DE.json
index c5e346e..f30e9ab 100644
--- a/ui/public/locales/de_DE.json
+++ b/ui/public/locales/de_DE.json
@@ -783,6 +783,7 @@
 "label.drag.new.position": "Ziehe zu neuer Position",
 "label.driver": "Treiber",
 "label.duration.in.sec": "Dauer (in Sekunden)",
+"label.dynamicscalingenabled": "Dynamische Skalierung aktiviert",
 "label.edit": "Bearbeiten",
 "label.edit.acl.list": "Edit ACL List",
 "label.edit.acl.rule": "ACL-Regel bearbeiten",
diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json
index 3778d85..33e8f32 100644
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@ -810,6 +810,8 @@
 "label.drag.new.position": "Drag to new position",
 "label.driver": "Driver",
 "label.duration.in.sec": "Duration (in sec)",
+"label.dynamicscalingenabled": "Dynamic Scaling Enabled",
+"label.dynamicscalingenabled.tooltip": "VM can dynamically scale only when 
dynamic scaling is enabled on template, service offering and global setting",
 "label.edit": "Edit",
 "label.edit.acl.list": "Edit ACL List",
 "label.edit.acl.rule": "Edit ACL rule",
diff --git a/ui/public/locales/es.json b/ui/public/locales/es.json
index 30ec8f4..7e8bac3 100644
--- a/ui/public/locales/es.json
+++ b/ui/public/locales/es.json
@@ -670,6 +670,7 @@
 "label.drag.new.position": "Arrastrar a una nueva ubicaci\u00f3n",
 "label.driver": "Controlador",
 "label.duration.in.sec": "Duraci\u00f3n (en seg)",
+"label.dynamicscalingenabled": "Escalado din\u00e1mico habilitado",
 "label.edit": "Editar",
 "label.edit.acl.list": "Edit ACL List",
 "label.edit.acl.rule": "Editar regla ACL",
diff --git a/ui/public/locales/hu.json b/ui/public/locales/hu.json
index 2dc08a9..359d877 100644
--- a/ui/public/locales/hu.json
+++ b/ui/public/locales/hu.json
@@ -658,6 +658,7 @@
 "label.drag.new.position": "\u00daj helyre h\u00faz\u00e1s",
 "label.driver": "Driver",
 "label.duration.in.sec": "Id\u0151tartam (mp)",
+"label.dynamicscalingenabled": "dinamikus méretezés engedélyezve",
 "label.edit": "Szerkeszt\u00e9s",
 "label.edit.acl.list": "Edit ACL List",
 "label.edit.acl.rule": "ACL szab\u00e1ly szerkeszt\u00e9se",
diff --git a/ui/public/locales/nl_NL.json b/ui/public/locales/nl_NL.json
index e227766..b40c91a 100644
--- a/ui/public/locales/nl_NL.json
+++ b/ui/public/locales/nl_NL.json
@@ -658,6 +658,7 @@
 "label.dpd": "Dead Peer detectie",
 "label.drag.new.position": "Sleep naar nieuwe positie",
 "label.driver": "Driver",
+"label.dynamicscalingenabled": "Dynamisch schalen ingeschakeld\n",
 "label.duration.in.sec": "duur (in sec)",
 "label.edit": "Wijzig",
 "label.edit.acl.list": "Verander een ACL lijst",
diff --git a/ui/src/components/view/ActionButton.vue 
b/ui/src/components/view/ActionButton.vue
index bf9f63b..5202cc6 100644
--- a/ui/src/components/view/ActionButton.vue
+++ b/ui/src/components/view/ActionButton.vue
@@ -39,7 +39,8 @@
           action.showBadge && (
             (!dataView && ((action.listView && ('show' in action ? 
action.show(resource, $store.getters) : true)) || (action.groupAction && 
selectedRowKeys.length > 0 && ('groupShow' in action ? action.show(resource, 
$store.getters) : true)))) ||
             (dataView && action.dataView && ('show' in action ? 
action.show(resource, $store.getters) : true))
-          )" >
+          )"
+        :disabled="'disabled' in action ? action.disabled(resource, 
$store.getters) : false" >
         <a-button
           :type="action.icon === 'delete' ? 'danger' : (action.icon === 'plus' 
? 'primary' : 'default')"
           :shape="!dataView && action.icon === 'plus' ? 'round' : 'circle'"
@@ -59,6 +60,7 @@
             (!dataView && ((action.listView && ('show' in action ? 
action.show(resource, $store.getters) : true)) || (action.groupAction && 
selectedRowKeys.length > 0 && ('groupShow' in action ? action.show(resource, 
$store.getters) : true)))) ||
             (dataView && action.dataView && ('show' in action ? 
action.show(resource, $store.getters) : true))
           )"
+        :disabled="'disabled' in action ? action.disabled(resource, 
$store.getters) : false"
         :type="action.icon === 'delete' ? 'danger' : (action.icon === 'plus' ? 
'primary' : 'default')"
         :shape="!dataView && ['plus', 'user-add'].includes(action.icon) ? 
'round' : 'circle'"
         style="margin-left: 5px"
diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js
index cc2104c..f16f89e 100644
--- a/ui/src/config/section/compute.js
+++ b/ui/src/config/section/compute.js
@@ -285,6 +285,7 @@ export default {
           docHelp: 
'adminguide/virtual_machines.html#how-to-dynamically-scale-cpu-and-ram',
           dataView: true,
           show: (record) => { return ['Stopped'].includes(record.state) || 
(['Running'].includes(record.state) && record.hypervisor !== 'KVM' && 
record.hypervisor !== 'LXC') },
+          disabled: (record) => { return !record.isdynamicallyscalable },
           popup: true,
           component: () => import('@/views/compute/ScaleVM.vue')
         },
diff --git a/ui/src/config/section/infra/systemVms.js 
b/ui/src/config/section/infra/systemVms.js
index 181b8e8..cdde068 100644
--- a/ui/src/config/section/infra/systemVms.js
+++ b/ui/src/config/section/infra/systemVms.js
@@ -22,7 +22,7 @@ export default {
   docHelp: 'adminguide/systemvm.html',
   permission: ['listSystemVms'],
   columns: ['name', 'state', 'agentstate', 'systemvmtype', 'publicip', 
'privateip', 'linklocalip', 'hostname', 'zonename'],
-  details: ['name', 'id', 'agentstate', 'systemvmtype', 'publicip', 
'privateip', 'linklocalip', 'gateway', 'hostname', 'zonename', 'created', 
'activeviewersessions'],
+  details: ['name', 'id', 'agentstate', 'systemvmtype', 'publicip', 
'privateip', 'linklocalip', 'gateway', 'hostname', 'zonename', 'created', 
'activeviewersessions', 'isdynamicallyscalable'],
   actions: [
     {
       api: 'startSystemVm',
diff --git a/ui/src/config/section/offering.js 
b/ui/src/config/section/offering.js
index b8b2bef..f495841 100644
--- a/ui/src/config/section/offering.js
+++ b/ui/src/config/section/offering.js
@@ -31,7 +31,7 @@ export default {
       params: { isrecursive: 'true' },
       columns: ['name', 'displaytext', 'cpunumber', 'cpuspeed', 'memory', 
'domain', 'zone', 'order'],
       details: () => {
-        var fields = ['name', 'id', 'displaytext', 'offerha', 
'provisioningtype', 'storagetype', 'iscustomized', 'limitcpuuse', 'cpunumber', 
'cpuspeed', 'memory', 'hosttags', 'tags', 'domain', 'zone', 'created']
+        var fields = ['name', 'id', 'displaytext', 'offerha', 
'provisioningtype', 'storagetype', 'iscustomized', 'limitcpuuse', 'cpunumber', 
'cpuspeed', 'memory', 'hosttags', 'tags', 'domain', 'zone', 'created', 
'dynamicscalingenabled']
         if (store.getters.apis.createServiceOffering &&
           store.getters.apis.createServiceOffering.params.filter(x => x.name 
=== 'storagepolicy').length > 0) {
           fields.splice(6, 0, 'vspherestoragepolicy')
@@ -87,7 +87,7 @@ export default {
       permission: ['listServiceOfferings', 'listInfrastructure'],
       params: { issystem: 'true', isrecursive: 'true' },
       columns: ['name', 'systemvmtype', 'cpunumber', 'cpuspeed', 'memory', 
'storagetype', 'order'],
-      details: ['name', 'id', 'displaytext', 'systemvmtype', 
'provisioningtype', 'storagetype', 'iscustomized', 'limitcpuuse', 'cpunumber', 
'cpuspeed', 'memory', 'hosttags', 'tags', 'domain', 'zone', 'created'],
+      details: ['name', 'id', 'displaytext', 'systemvmtype', 
'provisioningtype', 'storagetype', 'iscustomized', 'limitcpuuse', 'cpunumber', 
'cpuspeed', 'memory', 'hosttags', 'tags', 'domain', 'zone', 'created', 
'dynamicscalingenabled'],
       actions: [{
         api: 'createServiceOffering',
         icon: 'plus',
diff --git a/ui/src/views/compute/DeployVM.vue 
b/ui/src/views/compute/DeployVM.vue
index c0965bf..bccd928 100644
--- a/ui/src/views/compute/DeployVM.vue
+++ b/ui/src/views/compute/DeployVM.vue
@@ -509,6 +509,21 @@
                         v-decorator="['bootintosetup']">
                       </a-switch>
                     </a-form-item>
+                    <a-form-item>
+                      <span slot="label">
+                        {{ $t('label.dynamicscalingenabled') }}
+                        <a-tooltip 
:title="$t('label.dynamicscalingenabled.tooltip')">
+                          <a-icon type="info-circle" style="color: 
rgba(0,0,0,.45)" />
+                        </a-tooltip>
+                      </span>
+                      <a-form-item>
+                        <a-switch
+                          v-decorator="['dynamicscalingenabled']"
+                          :checked="isDynamicallyScalable() && 
dynamicscalingenabled"
+                          :disabled="!isDynamicallyScalable()"
+                          @change="val => { dynamicscalingenabled = val }"/>
+                      </a-form-item>
+                    </a-form-item>
                     <a-form-item :label="$t('label.userdata')">
                       <a-textarea
                         v-decorator="['userdata']">
@@ -675,6 +690,7 @@ export default {
       clusterId: null,
       zoneSelected: false,
       startvm: true,
+      dynamicscalingenabled: true,
       vm: {
         name: null,
         zoneid: null,
@@ -710,7 +726,8 @@ export default {
         groups: [],
         keyboards: [],
         bootTypes: [],
-        bootModes: []
+        bootModes: [],
+        dynamicScalingVmConfig: false
       },
       rowCount: {},
       loading: {
@@ -892,6 +909,13 @@ export default {
             type: 'Routing'
           },
           field: 'hostid'
+        },
+        dynamicScalingVmConfig: {
+          list: 'listConfigurations',
+          options: {
+            zoneid: _.get(this.zone, 'id'),
+            name: 'enable.dynamic.scale.vm'
+          }
         }
       }
     },
@@ -970,6 +994,9 @@ export default {
     },
     showSecurityGroupSection () {
       return (this.networks.length > 0 && this.zone.securitygroupsenabled) || 
(this.zone && this.zone.networktype === 'Basic')
+    },
+    dynamicScalingVmConfigValue () {
+      return this.options.dynamicScalingVmConfig?.[0]?.value === 'true'
     }
   },
   watch: {
@@ -1086,6 +1113,16 @@ export default {
       }
     }
   },
+  serviceOffering (oldValue, newValue) {
+    if (oldValue && newValue && oldValue.id !== newValue.id) {
+      this.dynamicscalingenabled = this.isDynamicallyScalable()
+    }
+  },
+  template (oldValue, newValue) {
+    if (oldValue && newValue && oldValue.id !== newValue.id) {
+      this.dynamicscalingenabled = this.isDynamicallyScalable()
+    }
+  },
   created () {
     this.form = this.$form.createForm(this, {
       onValuesChange: (props, fields) => {
@@ -1179,6 +1216,9 @@ export default {
         this.instanceConfig = this.form.getFieldsValue() // ToDo: maybe 
initialize with some other defaults
       })
     },
+    isDynamicallyScalable () {
+      return this.serviceOffering && 
this.serviceOffering.dynamicscalingenabled && this.template && 
this.template.isdynamicallyscalable && this.dynamicScalingVmConfigValue
+    },
     async fetchDataByZone (zoneId) {
       this.fillValue('zoneid')
       this.options.zones = await this.fetchZones()
@@ -1416,6 +1456,7 @@ export default {
         deployVmData.keyboard = values.keyboard
         deployVmData.boottype = values.boottype
         deployVmData.bootmode = values.bootmode
+        deployVmData.dynamicscalingenabled = values.dynamicscalingenabled
         if (values.userdata && values.userdata.length > 0) {
           deployVmData.userdata = 
encodeURIComponent(btoa(this.sanitizeReverse(values.userdata)))
         }
diff --git a/ui/src/views/compute/EditVM.vue b/ui/src/views/compute/EditVM.vue
index c9f342b..1aa654b 100644
--- a/ui/src/views/compute/EditVM.vue
+++ b/ui/src/views/compute/EditVM.vue
@@ -72,7 +72,8 @@
         </span>
         <a-switch
           :default-checked="resource.isdynamicallyscalable"
-          v-decorator="['isdynamicallyscalable']" />
+          v-decorator="['isdynamicallyscalable']"
+          :disabled="!canDynamicScalingEnabled()" />
       </a-form-item>
       <a-form-item>
         <span slot="label">
@@ -125,6 +126,9 @@ export default {
   },
   data () {
     return {
+      serviceOffering: {},
+      template: {},
+      dynamicScalingVmConfig: false,
       loading: false,
       osTypes: {
         loading: false,
@@ -151,6 +155,44 @@ export default {
     fetchData () {
       this.fetchOsTypes()
       this.fetchInstaceGroups()
+      this.fetchServiceOfferingData()
+      this.fetchTemplateData()
+      this.fetchDynamicScalingVmConfig()
+    },
+    fetchServiceOfferingData () {
+      const params = {}
+      params.id = this.resource.serviceofferingid
+      params.isrecursive = true
+      var apiName = 'listServiceOfferings'
+      api(apiName, params).then(json => {
+        const offerings = json.listserviceofferingsresponse.serviceoffering
+        this.serviceOffering = offerings[0]
+      })
+    },
+    fetchTemplateData () {
+      const params = {}
+      console.log('templateid ' + this.resource.templateid)
+      params.id = this.resource.templateid
+      params.isrecursive = true
+      params.templatefilter = 'all'
+      var apiName = 'listTemplates'
+      api(apiName, params).then(json => {
+        const templateResponses = json.listtemplatesresponse.template
+        this.template = templateResponses[0]
+      })
+    },
+    fetchDynamicScalingVmConfig () {
+      const params = {}
+      params.name = 'enable.dynamic.scale.vm'
+      params.zoneid = this.resource.zoneid
+      var apiName = 'listConfigurations'
+      api(apiName, params).then(json => {
+        const configResponse = json.listconfigurationsresponse.configuration
+        this.dynamicScalingVmConfig = configResponse[0]?.value === 'true'
+      })
+    },
+    canDynamicScalingEnabled () {
+      return this.template.isdynamicallyscalable && 
this.serviceOffering.dynamicscalingenabled && this.dynamicScalingVmConfig
     },
     fetchOsTypes () {
       this.osTypes.loading = true
diff --git a/ui/src/views/offering/AddComputeOffering.vue 
b/ui/src/views/offering/AddComputeOffering.vue
index 1c13dc3..c61d2d1 100644
--- a/ui/src/views/offering/AddComputeOffering.vue
+++ b/ui/src/views/offering/AddComputeOffering.vue
@@ -532,6 +532,15 @@
           </span>
           <a-switch v-decorator="['offerha', {initialValue: false}]" />
         </a-form-item>
+        <a-form-item>
+          <span slot="label">
+            {{ $t('label.dynamicscalingenabled') }}
+            <a-tooltip :title="apiParams.dynamicscalingenabled.description">
+              <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
+            </a-tooltip>
+          </span>
+          <a-switch v-decorator="['dynamicscalingenabled', {initialValue: 
dynamicscalingenabled}]" :checked="dynamicscalingenabled" @change="val => { 
dynamicscalingenabled = val }"/>
+        </a-form-item>
         <a-form-item v-if="this.isAdmin()">
           <span slot="label">
             {{ $t('label.hosttags') }}
@@ -797,7 +806,8 @@ export default {
       ],
       vGpuVisible: false,
       vGpuTypes: [],
-      loading: false
+      loading: false,
+      dynamicscalingenabled: true
     }
   },
   beforeCreate () {
@@ -959,7 +969,8 @@ export default {
           cachemode: values.cachemode,
           customized: values.offeringtype !== 'fixed',
           offerha: values.offerha === true,
-          limitcpuuse: values.limitcpuuse === true
+          limitcpuuse: values.limitcpuuse === true,
+          dynamicscalingenabled: values.dynamicscalingenabled
         }
 
         // custom fields (begin)

Reply via email to