cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kous...@apache.org
Subject git commit: updated refs/heads/master to 68406ba
Date Fri, 29 Nov 2013 12:31:17 GMT
Updated Branches:
  refs/heads/master abd4a826e -> 68406ba29


CLOUDSTACK-5161 enable scaling of a vm using custom offering

Signed-off-by: Koushik Das <koushik@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/68406ba2
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/68406ba2
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/68406ba2

Branch: refs/heads/master
Commit: 68406ba29d7dc31dcfd9ef2cefc673ff32cfa514
Parents: abd4a82
Author: Bharat Kumar <bharat.kumar@citrix.com>
Authored: Thu Nov 28 07:53:21 2013 +0530
Committer: Koushik Das <koushik@apache.org>
Committed: Fri Nov 29 17:53:33 2013 +0530

----------------------------------------------------------------------
 .../org/apache/cloudstack/api/ApiConstants.java |   1 +
 .../admin/systemvm/ScaleSystemVMCmd.java        |  25 +++
 .../admin/systemvm/UpgradeSystemVMCmd.java      |  25 +++
 .../api/command/user/vm/ScaleVMCmd.java         |  29 ++++
 .../api/command/user/vm/UpgradeVMCmd.java       |  25 +++
 .../api/response/ServiceOfferingResponse.java   |  21 ++-
 .../src/com/cloud/vm/VirtualMachineManager.java |   4 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java |   9 +-
 .../cloud/entity/api/VMEntityManagerImpl.java   |   1 +
 .../src/com/cloud/event/UsageEventVO.java       |   4 +
 .../com/cloud/service/ServiceOfferingVO.java    |  18 +-
 .../cloud/service/dao/ServiceOfferingDao.java   |   3 +-
 .../service/dao/ServiceOfferingDaoImpl.java     |  34 ++--
 .../src/com/cloud/storage/DiskOfferingVO.java   |  16 ++
 .../src/com/cloud/usage/UsageVMInstanceVO.java  |   3 -
 .../query/dao/ServiceOfferingJoinDaoImpl.java   |   1 +
 .../api/query/vo/ServiceOfferingJoinVO.java     |  16 +-
 .../com/cloud/capacity/CapacityManagerImpl.java |   5 +-
 .../configuration/ConfigurationManagerImpl.java |   7 +
 .../com/cloud/server/ManagementServerImpl.java  |  29 +++-
 server/src/com/cloud/vm/UserVmManager.java      |  12 +-
 server/src/com/cloud/vm/UserVmManagerImpl.java  | 170 +++++++++++++++----
 server/test/com/cloud/vm/UserVmManagerTest.java |   6 +-
 usage/src/com/cloud/usage/UsageManagerImpl.java |  12 +-
 24 files changed, 388 insertions(+), 88 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 7b87264..efdff12 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -72,6 +72,7 @@ public class ApiConstants {
     public static final String DISPLAY_VM = "displayvm";
     public static final String DISPLAY_OFFERING = "displayoffering";
     public static final String DISPLAY_VOLUME = "displayvolume";
+    public static final String CUSTOM_PARAMETERS = "customparameters";
     public static final String DNS1 = "dns1";
     public static final String DNS2 = "dns2";
     public static final String IP6_DNS1 = "ip6dns1";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java
index a7c864d..247df1e 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java
@@ -39,6 +39,11 @@ import com.cloud.offering.ServiceOffering;
 import com.cloud.user.Account;
 import com.cloud.vm.VirtualMachine;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
 @APICommand(name = "scaleSystemVm",
             responseObject = SystemVmResponse.class,
             description = "Scale the service offering for a system vm (console proxy or secondary storage). " + "The system vm must be in a \"Stopped\" state for "
@@ -61,6 +66,11 @@ public class ScaleSystemVMCmd extends BaseAsyncCmd {
                description = "the service offering ID to apply to the system vm")
     private Long serviceOfferingId;
 
+    @Parameter(name=ApiConstants.CUSTOM_PARAMETERS,
+            type = CommandType.MAP,
+            description = "name value pairs of custom parameters for cpu, memory and cpunumber. example customparameters[i].name=value")
+    private Map<String, String> customParameters;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -73,6 +83,21 @@ public class ScaleSystemVMCmd extends BaseAsyncCmd {
         return serviceOfferingId;
     }
 
+    public Map<String, String> getCustomParameters() {
+        Map<String,String> customparameterMap = new HashMap<String, String>();
+        if (customParameters != null && customParameters.size() != 0) {
+            Collection parameterCollection = customParameters.values();
+            Iterator iter = parameterCollection.iterator();
+            while (iter.hasNext()) {
+                HashMap<String, String> value = (HashMap<String, String>) iter.next();
+                for (String key : value.keySet()) {
+                    customparameterMap.put(key, value.get(key));
+                }
+            }
+        }
+        return customparameterMap;
+    }
+
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java
index 1357a7d..a49828b 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java
@@ -34,6 +34,11 @@ import com.cloud.offering.ServiceOffering;
 import com.cloud.user.Account;
 import com.cloud.vm.VirtualMachine;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
 @APICommand(name = "changeServiceForSystemVm",
             responseObject = SystemVmResponse.class,
             description = "Changes the service offering for a system vm (console proxy or secondary storage). " + "The system vm must be in a \"Stopped\" state for "
@@ -56,6 +61,11 @@ public class UpgradeSystemVMCmd extends BaseCmd {
                description = "the service offering ID to apply to the system vm")
     private Long serviceOfferingId;
 
+    @Parameter(name=ApiConstants.CUSTOM_PARAMETERS,
+            type = CommandType.MAP,
+            description = "name value pairs of custom parameters for cpu, memory and cpunumber. example customparameters[i].name=value")
+    private Map<String, String> customParameters;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -68,6 +78,21 @@ public class UpgradeSystemVMCmd extends BaseCmd {
         return serviceOfferingId;
     }
 
+    public Map<String, String> getCustomParameters() {
+        Map<String,String> customparameterMap = new HashMap<String, String>();
+        if (customParameters != null && customParameters.size() !=0){
+            Collection parameterCollection = customParameters.values();
+            Iterator iter = parameterCollection.iterator();
+            while (iter.hasNext()) {
+                HashMap<String, String> value = (HashMap<String, String>) iter.next();
+                for (String key : value.keySet()) {
+                    customparameterMap.put(key, value.get(key));
+                }
+            }
+        }
+        return customparameterMap;
+    }
+
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java
index 6cb49c1..08a4a56 100644
--- a/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java
@@ -39,6 +39,12 @@ import com.cloud.exception.VirtualMachineMigrationException;
 import com.cloud.user.Account;
 import com.cloud.uservm.UserVm;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+
 @APICommand(name = "scaleVirtualMachine", description = "Scales the virtual machine to a new service offering.", responseObject = SuccessResponse.class)
 public class ScaleVMCmd extends BaseAsyncCmd {
     public static final Logger s_logger = Logger.getLogger(ScaleVMCmd.class.getName());
@@ -60,6 +66,11 @@ public class ScaleVMCmd extends BaseAsyncCmd {
                description = "the ID of the service offering for the virtual machine")
     private Long serviceOfferingId;
 
+    @Parameter(name=ApiConstants.CUSTOM_PARAMETERS,
+            type = CommandType.MAP,
+            description = "name value pairs of custom parameters for cpu, memory and cpunumber. example customparameters[i].name=value")
+    private Map<String, String> customParameters;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -72,6 +83,24 @@ public class ScaleVMCmd extends BaseAsyncCmd {
         return serviceOfferingId;
     }
 
+    //instead of reading a map directly we are using collections.
+    //it is because customParameters.values() cannot be cast to a map.
+    //it gives a exception
+    public Map<String, String> getCustomParameters() {
+        Map<String,String> customparameterMap = new HashMap<String, String>();
+        if (customParameters != null && customParameters.size() !=0){
+            Collection parameterCollection = customParameters.values();
+            Iterator iter = parameterCollection.iterator();
+            while (iter.hasNext()) {
+                HashMap<String, String> value = (HashMap<String, String>) iter.next();
+                for (String key : value.keySet()) {
+                    customparameterMap.put(key, value.get(key));
+                }
+            }
+        }
+        return customparameterMap;
+    }
+
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java
index 3dfcdf9..4349781 100644
--- a/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java
@@ -34,6 +34,11 @@ import com.cloud.offering.ServiceOffering;
 import com.cloud.user.Account;
 import com.cloud.uservm.UserVm;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
 @APICommand(name = "changeServiceForVirtualMachine", responseObject = UserVmResponse.class, description = "Changes the service offering for a virtual machine. "
     + "The virtual machine must be in a \"Stopped\" state for " + "this command to take effect.")
 public class UpgradeVMCmd extends BaseCmd {
@@ -54,6 +59,11 @@ public class UpgradeVMCmd extends BaseCmd {
                description = "the service offering ID to apply to the virtual machine")
     private Long serviceOfferingId;
 
+    @Parameter(name=ApiConstants.CUSTOM_PARAMETERS,
+            type = CommandType.MAP,
+            description = "name value pairs of custom parameters for cpu, memory and cpunumber. example customparameters[i].name=value")
+    private Map<String, String> customParameters;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -66,6 +76,21 @@ public class UpgradeVMCmd extends BaseCmd {
         return serviceOfferingId;
     }
 
+    public Map<String, String> getCustomParameters() {
+        Map<String,String> customparameterMap = new HashMap<String, String>();
+        if (customParameters != null && customParameters.size() !=0){
+            Collection parameterCollection = customParameters.values();
+            Iterator iter = parameterCollection.iterator();
+            while (iter.hasNext()) {
+                HashMap<String, String> value = (HashMap<String, String>) iter.next();
+                for (String key : value.keySet()) {
+                    customparameterMap.put(key, value.get(key));
+                }
+            }
+        }
+        return customparameterMap;
+    }
+
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
index 7ec739e..c8dee14 100644
--- a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
@@ -44,15 +44,15 @@ public class ServiceOfferingResponse extends BaseResponse {
 
     @SerializedName("cpunumber")
     @Param(description = "the number of CPU")
-    private int cpuNumber;
+    private Integer cpuNumber;
 
     @SerializedName("cpuspeed")
     @Param(description = "the clock rate CPU speed in Mhz")
-    private int cpuSpeed;
+    private Integer cpuSpeed;
 
     @SerializedName("memory")
     @Param(description = "the memory in MB")
-    private int memory;
+    private Integer memory;
 
     @SerializedName("created")
     @Param(description = "the date this service offering was created")
@@ -130,6 +130,10 @@ public class ServiceOfferingResponse extends BaseResponse {
     @Param(description = "additional key/value details tied with this service offering", since = "4.2.0")
     private Map<String, String> details;
 
+    @SerializedName("iscustomized")
+    @Param(description = "is true if the offering is customized", since = "4.3.0")
+    private Boolean isCustomized;
+
     public ServiceOfferingResponse() {
     }
 
@@ -185,7 +189,7 @@ public class ServiceOfferingResponse extends BaseResponse {
         return cpuNumber;
     }
 
-    public void setCpuNumber(int cpuNumber) {
+    public void setCpuNumber(Integer cpuNumber) {
         this.cpuNumber = cpuNumber;
     }
 
@@ -193,7 +197,7 @@ public class ServiceOfferingResponse extends BaseResponse {
         return cpuSpeed;
     }
 
-    public void setCpuSpeed(int cpuSpeed) {
+    public void setCpuSpeed(Integer cpuSpeed) {
         this.cpuSpeed = cpuSpeed;
     }
 
@@ -201,7 +205,7 @@ public class ServiceOfferingResponse extends BaseResponse {
         return memory;
     }
 
-    public void setMemory(int memory) {
+    public void setMemory(Integer memory) {
         this.memory = memory;
     }
 
@@ -309,4 +313,9 @@ public class ServiceOfferingResponse extends BaseResponse {
         this.details = details;
     }
 
+    public void setIscutomized(boolean iscutomized) {
+        this.isCustomized = iscutomized;
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/api/src/com/cloud/vm/VirtualMachineManager.java
----------------------------------------------------------------------
diff --git a/engine/api/src/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/com/cloud/vm/VirtualMachineManager.java
index c78942f..fbbed21 100644
--- a/engine/api/src/com/cloud/vm/VirtualMachineManager.java
+++ b/engine/api/src/com/cloud/vm/VirtualMachineManager.java
@@ -145,9 +145,9 @@ public interface VirtualMachineManager extends Manager {
 
     /**
      * @param vmInstance
-     * @param newServiceOfferingId
+     * @param newServiceOffering
      */
-    void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId);
+    void checkIfCanUpgrade(VirtualMachine vmInstance, ServiceOffering newServiceOffering);
 
     /**
      * @param vmId

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 3a3de70..6b551cc 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -3011,10 +3011,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     @Override
-    public void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId) {
-        ServiceOfferingVO newServiceOffering = _offeringDao.findById(vmInstance.getId(), newServiceOfferingId);
+    public void checkIfCanUpgrade(VirtualMachine vmInstance, ServiceOffering newServiceOffering) {
         if (newServiceOffering == null) {
-            throw new InvalidParameterValueException("Unable to find a service offering with id " + newServiceOfferingId);
+            throw new InvalidParameterValueException("Unable to find a service offering with id " + newServiceOffering.getId());
         }
 
         // Check that the VM is stopped / running
@@ -3025,7 +3024,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
 
         // Check if the service offering being upgraded to is what the VM is already running with
-        if (vmInstance.getServiceOfferingId() == newServiceOffering.getId()) {
+        if (!newServiceOffering.isDynamic() && vmInstance.getServiceOfferingId() == newServiceOffering.getId()) {
             if (s_logger.isInfoEnabled()) {
                 s_logger.info("Not upgrading vm " + vmInstance.toString() + " since it already has the requested " + "service offering (" + newServiceOffering.getName() +
                     ")");
@@ -3734,7 +3733,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
         long newServiceofferingId = vm.getServiceOfferingId();
-        ServiceOffering newServiceOffering = _entityMgr.findById(ServiceOffering.class, newServiceofferingId);
+        ServiceOffering newServiceOffering = _offeringDao.findById(vm.getId(), newServiceofferingId);
         HostVO hostVo = _hostDao.findById(vm.getHostId());
 
         Float memoryOvercommitRatio = CapacityManager.MemOverprovisioningFactor.valueIn(hostVo.getClusterId());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
index c02e0ad..40b0f44 100755
--- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
@@ -146,6 +146,7 @@ public class VMEntityManagerImpl implements VMEntityManager {
         //FIXME: profile should work on VirtualMachineEntity
         VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid());
         VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm);
+        vmProfile.setServiceOffering(_serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()));
         DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null);
         if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
             plan =

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/schema/src/com/cloud/event/UsageEventVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/event/UsageEventVO.java b/engine/schema/src/com/cloud/event/UsageEventVO.java
index 719a79b..2278103 100644
--- a/engine/schema/src/com/cloud/event/UsageEventVO.java
+++ b/engine/schema/src/com/cloud/event/UsageEventVO.java
@@ -30,6 +30,10 @@ import com.cloud.utils.db.GenericDao;
 @Entity
 @Table(name = "usage_event")
 public class UsageEventVO implements UsageEvent {
+    public enum DynamicParameters {
+        cpuSpeed, cpuNumber, memory
+    };
+
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Column(name = "id")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/schema/src/com/cloud/service/ServiceOfferingVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java
index d968de5..f1cc39b 100755
--- a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java
+++ b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java
@@ -34,10 +34,6 @@ import com.cloud.vm.VirtualMachine;
 @DiscriminatorValue(value = "Service")
 @PrimaryKeyJoinColumn(name = "id")
 public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering {
-    public enum DynamicParameters {
-        cpuSpeed, cpuNumber, memory
-    };
-
     @Column(name = "cpu")
     private Integer cpu;
 
@@ -167,6 +163,20 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
         this.deploymentPlanner = deploymentPlanner;
     }
 
+    public ServiceOfferingVO(ServiceOfferingVO offering) {
+        super(offering.getId(), offering.getName(), offering.getDisplayText(), false, offering.getTags(), offering.isRecreatable(), offering.getUseLocalStorage(), offering.getSystemUse(), true, offering.getDomainId());
+        this.cpu = offering.getCpu();
+        this.ramSize = offering.getRamSize();
+        this.speed = offering.getSpeed();
+        this.rateMbps = offering.getRateMbps();
+        this.multicastRateMbps = offering.getMulticastRateMbps();
+        this.offerHA = offering.getOfferHA();
+        this.limitCpuUse = offering.getLimitCpuUse();
+        this.volatileVm = offering.getVolatileVm();
+        this.hostTag = offering.getHostTag();
+        this.vm_type = offering.getSystemVmType();
+    }
+
     @Override
     public boolean getOfferHA() {
         return offerHA;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java
index 10d6616..ecab8d2 100644
--- a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java
+++ b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java
@@ -17,6 +17,7 @@
 package com.cloud.service.dao;
 
 import java.util.List;
+import java.util.Map;
 
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.utils.db.GenericDao;
@@ -47,5 +48,5 @@ public interface ServiceOfferingDao extends GenericDao<ServiceOfferingVO, Long>
 
     boolean isDynamic(long serviceOfferingId);
 
-    ServiceOfferingVO getcomputeOffering(long serviceOfferingId, Integer cpuCores, Integer cpuSpeed, Integer memory);
+    ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map<String, String> customParameters);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java
index f1f97fc..5d423e0 100644
--- a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java
+++ b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java
@@ -25,6 +25,7 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.persistence.EntityExistsException;
 
+import com.cloud.event.UsageEventVO;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
@@ -191,14 +192,12 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
     public ServiceOfferingVO findById(Long vmId, long serviceOfferingId) {
         ServiceOfferingVO offering = super.findById(serviceOfferingId);
         if (offering.isDynamic()) {
+            offering.setDynamicFlag(true);
             if (vmId == null) {
                 throw new CloudRuntimeException("missing argument vmId");
             }
             Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId);
-            offering.setCpu(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name())));
-            offering.setSpeed(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name())));
-            offering.setRamSize(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.memory.name())));
-            return offering;
+            return getcomputeOffering(offering, dynamicOffering);
         }
         return offering;
     }
@@ -207,15 +206,12 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
     public ServiceOfferingVO findByIdIncludingRemoved(Long vmId, long serviceOfferingId) {
         ServiceOfferingVO offering = super.findByIdIncludingRemoved(serviceOfferingId);
         if (offering.isDynamic()) {
+            offering.setDynamicFlag(true);
             if (vmId == null) {
                 throw new CloudRuntimeException("missing argument vmId");
             }
             Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId);
-            offering.setCpu(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name())));
-            offering.setSpeed(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name())));
-            offering.setRamSize(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.memory.name())));
-            return offering;
-
+            return  getcomputeOffering(offering, dynamicOffering);
         }
         return offering;
     }
@@ -227,11 +223,19 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
     }
 
     @Override
-    public ServiceOfferingVO getcomputeOffering(long serviceOfferingId, Integer cpuCores, Integer cpuSpeed, Integer memory) {
-        ServiceOfferingVO offering = super.findById(serviceOfferingId);
-        offering.setCpu(cpuCores);
-        offering.setSpeed(cpuSpeed);
-        offering.setRamSize(memory);
-        return offering;
+    public ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map<String, String> customParameters) {
+        ServiceOfferingVO dummyoffering = new ServiceOfferingVO(serviceOffering);
+        dummyoffering.setDynamicFlag(true);
+        if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) {
+            dummyoffering.setCpu(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuNumber.name())));
+        }
+        if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuSpeed.name())) {
+            dummyoffering.setSpeed(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuSpeed.name())));
+        }
+        if (customParameters.containsKey(UsageEventVO.DynamicParameters.memory.name())) {
+            dummyoffering.setRamSize(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.memory.name())));
+        }
+
+        return dummyoffering;
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/schema/src/com/cloud/storage/DiskOfferingVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/DiskOfferingVO.java b/engine/schema/src/com/cloud/storage/DiskOfferingVO.java
index 8a9dd3d..1ff62ab 100755
--- a/engine/schema/src/com/cloud/storage/DiskOfferingVO.java
+++ b/engine/schema/src/com/cloud/storage/DiskOfferingVO.java
@@ -206,6 +206,22 @@ public class DiskOfferingVO implements DiskOffering {
         state = State.Active;
     }
 
+    public DiskOfferingVO(long id, String name, String displayText, boolean mirrored, String tags, boolean recreatable,
+                          boolean useLocalStorage, boolean systemUse, boolean customized, Long domainId) {
+        this.id = id;
+        type = Type.Service;
+        this.name = name;
+        this.displayText = displayText;
+        this.tags = tags;
+        this.recreatable = recreatable;
+        this.useLocalStorage = useLocalStorage;
+        this.systemUse = systemUse;
+        this.customized = customized;
+        this.domainId = domainId;
+        uuid = UUID.randomUUID().toString();
+        state = State.Active;
+    }
+
     @Override
     public State getState() {
         return state;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/engine/schema/src/com/cloud/usage/UsageVMInstanceVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/usage/UsageVMInstanceVO.java b/engine/schema/src/com/cloud/usage/UsageVMInstanceVO.java
index cd746c2..8d9491f 100644
--- a/engine/schema/src/com/cloud/usage/UsageVMInstanceVO.java
+++ b/engine/schema/src/com/cloud/usage/UsageVMInstanceVO.java
@@ -27,9 +27,6 @@ import javax.persistence.TemporalType;
 @Entity
 @Table(name = "usage_vm_instance")
 public class UsageVMInstanceVO {
-    public enum DynamicParameters {
-        cpuSpeed, cpuNumber, memory
-    };
 
     @Column(name = "usage_type")
     private int usageType;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java
index 4f351eb..7e113e4 100644
--- a/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java
@@ -79,6 +79,7 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
         offeringResponse.setIopsWriteRate(offering.getIopsWriteRate());
         offeringResponse.setDetails(ApiDBUtils.getResourceDetails(offering.getId(), ResourceObjectType.ServiceOffering));
         offeringResponse.setObjectName("serviceoffering");
+        offeringResponse.setIscutomized(offering.isDynamic());
 
         return offeringResponse;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/server/src/com/cloud/api/query/vo/ServiceOfferingJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/ServiceOfferingJoinVO.java b/server/src/com/cloud/api/query/vo/ServiceOfferingJoinVO.java
index 2260e1e..cfcc9b7 100644
--- a/server/src/com/cloud/api/query/vo/ServiceOfferingJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/ServiceOfferingJoinVO.java
@@ -55,13 +55,13 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
     private boolean systemUse;
 
     @Column(name = "cpu")
-    private int cpu;
+    private Integer cpu;
 
     @Column(name = "speed")
-    private int speed;
+    private Integer speed;
 
     @Column(name = "ram_size")
-    private int ramSize;
+    private Integer ramSize;
 
     @Column(name = "nw_rate")
     private Integer rateMbps;
@@ -184,15 +184,15 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
         return sortKey;
     }
 
-    public int getCpu() {
+    public Integer getCpu() {
         return cpu;
     }
 
-    public int getSpeed() {
+    public Integer getSpeed() {
         return speed;
     }
 
-    public int getRamSize() {
+    public Integer getRamSize() {
         return ramSize;
     }
 
@@ -247,4 +247,8 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
     public Long getIopsWriteRate() {
         return iopsWriteRate;
     }
+
+    public boolean isDynamic() {
+        return cpu == null || speed == null || ramSize == null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/server/src/com/cloud/capacity/CapacityManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java
index c733c03..8ed2433 100755
--- a/server/src/com/cloud/capacity/CapacityManagerImpl.java
+++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java
@@ -27,6 +27,7 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.event.UsageEventVO;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.framework.config.ConfigDepot;
@@ -543,10 +544,10 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
             ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId());
             if (so.isDynamic()) {
                 usedMemory +=
-                    ((Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.memory.name())) * 1024L * 1024L) / ramOvercommitRatio) *
+                    ((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.memory.name())) * 1024L * 1024L) / ramOvercommitRatio) *
                         clusterRamOvercommitRatio;
                 usedCpu +=
-                    ((Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name()))) / cpuOvercommitRatio) *
+                    ((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()))) / cpuOvercommitRatio) *
                         clusterCpuOvercommitRatio;
             } else {
                 usedMemory += ((so.getRamSize() * 1024L * 1024L) / ramOvercommitRatio) * clusterRamOvercommitRatio;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 3770eb8..854c089 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -1934,6 +1934,13 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
         Integer cpuSpeed = cmd.getCpuSpeed();
         Integer memory = cmd.getMemory();
 
+        //restricting the createserviceoffering to allow setting all or none of the dynamic parameters to null
+        if (cpuNumber == null || cpuSpeed == null || memory == null) {
+            if (cpuNumber !=null || cpuSpeed !=null || memory !=null) {
+                throw new InvalidParameterValueException("For creating a custom compute offering cpu, cpu speed and memory all should be null");
+            }
+        }
+
         if ((cpuNumber != null) && ((cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647))) {
             throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the cpu number value between 1 and 2147483647");
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index d34da4f..860f165 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -42,6 +42,8 @@ import javax.crypto.spec.SecretKeySpec;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.service.ServiceOfferingVO;
+import com.cloud.service.dao.ServiceOfferingDao;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.log4j.Logger;
 
@@ -716,6 +718,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     AccountService _accountService;
     @Inject
     ConfigurationManager _configMgr;
+    @Inject
+    ServiceOfferingDao _offeringDao;
 
     @Inject
     DeploymentPlanningManager _dpMgr;
@@ -3769,8 +3773,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         if (vmInstance.getHypervisorType() == HypervisorType.XenServer && vmInstance.getState().equals(State.Running)) {
             throw new InvalidParameterValueException("Dynamic Scaling operation is not permitted for this hypervisor on system vm");
         }
-        boolean result = _userVmMgr.upgradeVirtualMachine(cmd.getId(), cmd.getServiceOfferingId());
-        if (result) {
+        boolean result = _userVmMgr.upgradeVirtualMachine(cmd.getId(), cmd.getServiceOfferingId(), cmd.getCustomParameters());
+        if(result){
             VirtualMachine vm = _vmInstanceDao.findById(cmd.getId());
             return vm;
         } else {
@@ -3782,11 +3786,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     public VirtualMachine upgradeSystemVM(UpgradeSystemVMCmd cmd) {
         Long systemVmId = cmd.getId();
         Long serviceOfferingId = cmd.getServiceOfferingId();
-        return upgradeStoppedSystemVm(systemVmId, serviceOfferingId);
+        return upgradeStoppedSystemVm(systemVmId, serviceOfferingId, cmd.getCustomParameters());
 
     }
 
-    private VirtualMachine upgradeStoppedSystemVm(Long systemVmId, Long serviceOfferingId) {
+    private VirtualMachine upgradeStoppedSystemVm(Long systemVmId, Long serviceOfferingId, Map<String, String> customparameters){
         Account caller = CallContext.current().getCallingAccount();
 
         VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(systemVmId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
@@ -3797,10 +3801,25 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         _accountMgr.checkAccess(caller, null, true, systemVm);
 
         // Check that the specified service offering ID is valid
-        _itMgr.checkIfCanUpgrade(systemVm, serviceOfferingId);
+        ServiceOfferingVO newServiceOffering = _offeringDao.findById(serviceOfferingId);
+        ServiceOfferingVO currentServiceOffering = _offeringDao.findById(systemVmId,systemVm.getServiceOfferingId());
+        if (newServiceOffering.isDynamic()){
+            newServiceOffering.setDynamicFlag(true);
+            _userVmMgr.validateCustomParameters(newServiceOffering, customparameters);
+            newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customparameters);
+        }
+        _itMgr.checkIfCanUpgrade(systemVm, newServiceOffering);
 
         boolean result = _itMgr.upgradeVmDb(systemVmId, serviceOfferingId);
 
+        if (newServiceOffering.isDynamic()) {
+            //save the custom values to the database.
+            _userVmMgr.saveCustomOfferingDetails(systemVmId, newServiceOffering);
+        }
+        if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
+            _userVmMgr.removeCustomOfferingDetails(systemVmId);
+        }
+
         if (result) {
             return _vmInstanceDao.findById(systemVmId);
         } else {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/server/src/com/cloud/vm/UserVmManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java
index 8463326..da60f33 100755
--- a/server/src/com/cloud/vm/UserVmManager.java
+++ b/server/src/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.service.ServiceOfferingVO;
 import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
 import org.apache.cloudstack.framework.config.ConfigKey;
 
@@ -108,7 +110,7 @@ public interface UserVmManager extends UserVmService {
     Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMachine(long vmId, Long hostId, Map<VirtualMachineProfile.Param, Object> additionalParams)
         throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException;
 
-    boolean upgradeVirtualMachine(Long id, Long serviceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
+    boolean upgradeVirtualMachine(Long id, Long serviceOfferingId, Map<String, String> customParameters) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
         VirtualMachineMigrationException;
 
     boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic);
@@ -117,4 +119,12 @@ public interface UserVmManager extends UserVmService {
 
     UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
                                 Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId) throws ResourceUnavailableException, InsufficientCapacityException;
+
+    //the validateCustomParameters, save and remove CustomOfferingDetils functions can be removed from the interface once we can
+    //find a common place for all the scaling and upgrading code of both user and systemvms.
+    void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<String, String> customParameters);
+
+    public void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering);
+
+    public void removeCustomOfferingDetails(long vmId);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index c0b0031..1d5a187 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -34,6 +34,7 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.event.UsageEventVO;
 import com.cloud.uuididentity.UUIDManager;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.log4j.Logger;
@@ -773,7 +774,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         _accountMgr.checkAccess(caller, null, true, vmInstance);
 
         // Check resource limits for CPU and Memory.
+        Map<String,String> customParameters = cmd.getCustomParameters();
         ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId);
+        if (newServiceOffering.isDynamic()) {
+            newServiceOffering.setDynamicFlag(true);
+            validateCustomParameters(newServiceOffering, cmd.getCustomParameters());
+            newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters);
+        }
         ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
 
         int newCpu = newServiceOffering.getCpu();
@@ -789,7 +796,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         }
 
         // Check that the specified service offering ID is valid
-        _itMgr.checkIfCanUpgrade(vmInstance, svcOffId);
+        _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
 
         // remove diskAndMemory VM snapshots
         List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
@@ -805,6 +812,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         }
 
         _itMgr.upgradeVmDb(vmId, svcOffId);
+        if (newServiceOffering.isDynamic()) {
+            //save the custom values to the database.
+            saveCustomOfferingDetails(vmId, newServiceOffering);
+        }
+        if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
+           removeCustomOfferingDetails(vmId);
+        }
 
         // Increment or decrement CPU and Memory count accordingly.
         if (newCpu > currentCpu) {
@@ -818,15 +832,46 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
             _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long(currentMemory - newMemory));
         }
 
-        // Generate usage event for VM upgrade
-        UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_UPGRADE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(),
-            vmInstance.getHostName(), vmInstance.getServiceOfferingId(), vmInstance.getTemplateId(), vmInstance.getHypervisorType().toString(),
-            VirtualMachine.class.getName(), vmInstance.getUuid());
+        generateUsageEvent(newServiceOffering, cmd.getCustomParameters(), _vmDao.findById(vmId), EventTypes.EVENT_VM_UPGRADE);
 
         return _vmDao.findById(vmInstance.getId());
     }
 
-    private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId) throws ResourceAllocationException {
+    @Override
+    public void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<String, String> customParameters) {
+        if (customParameters.size() !=0 ) {
+            if (serviceOffering.getCpu() == null) {
+                String cpuNumber = customParameters.get(UsageEventVO.DynamicParameters.cpuNumber.name());
+                if ((cpuNumber == null) || (NumbersUtil.parseInt(cpuNumber, -1) <= 0 || NumbersUtil.parseInt(cpuNumber, -1) > 2147483647)) {
+                    throw new InvalidParameterValueException("Invalid cpu cores value, specify a value between 1 and 2147483647");
+                }
+            } else if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) {
+                throw new InvalidParameterValueException("The cpu cores of this offering id:"+serviceOffering.getId()+" is not customizable. This is predefined in the template.");
+            }
+
+            if (serviceOffering.getSpeed() == null) {
+                String cpuSpeed = customParameters.get(UsageEventVO.DynamicParameters.cpuSpeed.name());
+                if ((cpuSpeed == null) || (NumbersUtil.parseInt(cpuSpeed, -1) <= 0 || NumbersUtil.parseInt(cpuSpeed, -1) > 2147483647 )) {
+                    throw new InvalidParameterValueException("Invalid cpu speed value, specify a value between 1 and 2147483647");
+                }
+            } else if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuSpeed.name())) {
+                throw new InvalidParameterValueException("The cpu speed of this offering id:"+serviceOffering.getId()+" is not customizable. This is predefined in the template.");
+            }
+
+            if (serviceOffering.getRamSize() == null) {
+                String memory = customParameters.get(UsageEventVO.DynamicParameters.memory.name());
+                if (memory == null || (NumbersUtil.parseInt(memory, -1) < 32 || NumbersUtil.parseInt(memory, -1) > 2147483647)) {
+                    throw new InvalidParameterValueException("Invalid memory value, specify a value between 32 and 2147483647 MB");
+                }
+            } else if (customParameters.containsKey(UsageEventVO.DynamicParameters.memory.name())){
+                throw new InvalidParameterValueException("The memory of this offering id:"+serviceOffering.getId()+" is not customizable. This is predefined in the template.");
+            }
+        } else {
+            throw new InvalidParameterValueException("Need to specify custom parameter values cpu, cpu speed and memory when using custom offering");
+        }
+    }
+
+    private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map<String, String> customParameters) throws ResourceAllocationException {
         Account caller = CallContext.current().getCallingAccount();
 
         // Verify input parameters
@@ -840,6 +885,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
 
         // Check resource limits for CPU and Memory.
         ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId);
+        if (newServiceOffering.isDynamic()) {
+            newServiceOffering.setDynamicFlag(true);
+            validateCustomParameters(newServiceOffering, customParameters);
+            newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters);
+        }
         ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
 
         int newCpu = newServiceOffering.getCpu();
@@ -855,7 +905,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         }
 
         // Check that the specified service offering ID is valid
-        _itMgr.checkIfCanUpgrade(vmInstance, svcOffId);
+        _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
 
         // remove diskAndMemory VM snapshots
         List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
@@ -871,6 +921,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         }
 
         _itMgr.upgradeVmDb(vmId, svcOffId);
+        if (newServiceOffering.isDynamic()) {
+            //save the custom values to the database.
+            saveCustomOfferingDetails(vmId, newServiceOffering);
+        }
+        if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
+            removeCustomOfferingDetails(vmId);
+        }
 
         // Increment or decrement CPU and Memory count accordingly.
         if (newCpu > currentCpu) {
@@ -1149,20 +1206,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         Long newServiceOfferingId = cmd.getServiceOfferingId();
         CallContext.current().setEventDetails("Vm Id: " + vmId);
 
-        boolean result = upgradeVirtualMachine(vmId, newServiceOfferingId);
-        if (result) {
+        boolean  result = upgradeVirtualMachine(vmId, newServiceOfferingId,cmd.getCustomParameters());
+        if(result){
             UserVmVO vmInstance = _vmDao.findById(vmId);
             if (vmInstance.getState().equals(State.Stopped)) {
                 // Generate usage event for VM upgrade
-                UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_UPGRADE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(),
-                    vmInstance.getHostName(), vmInstance.getServiceOfferingId(), vmInstance.getTemplateId(), vmInstance.getHypervisorType().toString(),
-                    VirtualMachine.class.getName(), vmInstance.getUuid());
+                generateUsageEvent(_serviceOfferingDao.findById(newServiceOfferingId), cmd.getCustomParameters(), vmInstance, EventTypes.EVENT_VM_UPGRADE);
             }
             if (vmInstance.getState().equals(State.Running)) {
                 // Generate usage event for Dynamic scaling of VM
-                UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_DYNAMIC_SCALE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(),
-                    vmInstance.getHostName(), vmInstance.getServiceOfferingId(), vmInstance.getTemplateId(), vmInstance.getHypervisorType().toString(),
-                    VirtualMachine.class.getName(), vmInstance.getUuid());
+                generateUsageEvent(_serviceOfferingDao.findById(newServiceOfferingId),cmd.getCustomParameters(), vmInstance, EventTypes.EVENT_VM_UPGRADE);
             }
             return vmInstance;
         } else {
@@ -1207,24 +1260,22 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
     }
 
     @Override
-    public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException,
-        ManagementServerException, VirtualMachineMigrationException {
+    public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId, Map<String, String> customParameters) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException{
 
         // Verify input parameters
         VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
 
         if (vmInstance.getState().equals(State.Stopped)) {
-            upgradeStoppedVirtualMachine(vmId, newServiceOfferingId);
+            upgradeStoppedVirtualMachine(vmId, newServiceOfferingId, customParameters);
             return true;
         }
-        if (vmInstance.getState().equals(State.Running)) {
-            return upgradeRunningVirtualMachine(vmId, newServiceOfferingId);
+        if(vmInstance.getState().equals(State.Running)){
+            return upgradeRunningVirtualMachine(vmId, newServiceOfferingId, customParameters);
         }
         return false;
     }
 
-    private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException,
-        ManagementServerException, VirtualMachineMigrationException {
+    private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingId, Map<String, String> customParameters) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException{
 
         Account caller = CallContext.current().getCallingAccount();
         VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
@@ -1234,11 +1285,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
 
         _accountMgr.checkAccess(caller, null, true, vmInstance);
 
+        //Check if its a scale "up"
+        ServiceOfferingVO newServiceOffering = (ServiceOfferingVO) _offeringDao.findById(newServiceOfferingId);
+        if (newServiceOffering.isDynamic()) {
+            newServiceOffering.setDynamicFlag(true);
+            validateCustomParameters(newServiceOffering, customParameters);
+            newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters);
+        }
+
         // Check that the specified service offering ID is valid
-        _itMgr.checkIfCanUpgrade(vmInstance, newServiceOfferingId);
+        _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
 
-        //Check if its a scale "up"
-        ServiceOffering newServiceOffering = _entityMgr.findById(ServiceOffering.class, newServiceOfferingId);
         ServiceOffering currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
         int newCpu = newServiceOffering.getCpu();
         int newMemory = newServiceOffering.getRamSize();
@@ -1304,9 +1361,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
 
                     // #3 scale the vm now
                     _itMgr.upgradeVmDb(vmId, newServiceOfferingId);
+                    if (newServiceOffering.isDynamic()) {
+                        //save the custom values to the database.
+                        saveCustomOfferingDetails(vmId, newServiceOffering);
+                    }
                     vmInstance = _vmInstanceDao.findById(vmId);
                     _itMgr.reConfigureVm(vmInstance.getUuid(), currentServiceOffering, existingHostHasCapacity);
                     success = true;
+                    if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
+                        removeCustomOfferingDetails(vmId);
+                    }
                     return success;
                 } catch (InsufficientCapacityException e) {
                     s_logger.warn("Received exception while scaling ", e);
@@ -1319,6 +1383,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                 } finally {
                     if (!success) {
                         _itMgr.upgradeVmDb(vmId, currentServiceOffering.getId()); // rollback
+                        if (newServiceOffering.isDynamic()) {
+                           removeCustomOfferingDetails(vmId);
+                        }
                         // Decrement CPU and Memory count accordingly.
                         if (newCpu > currentCpu) {
                             _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu));
@@ -1330,11 +1397,39 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                 }
             }
         }
-
         return success;
     }
 
     @Override
+    public void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering) {
+        //save the custom values to the database.
+        Map<String, String> details = _uservmDetailsDao.listDetailsKeyPairs(vmId);
+        details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
+        details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
+        details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
+        List <UserVmDetailVO> detailList = new ArrayList<UserVmDetailVO>();
+        for (String key : details.keySet()) {
+            UserVmDetailVO detailVO = new UserVmDetailVO(vmId, key, details.get(key));
+            detailList.add(detailVO);
+        }
+        _uservmDetailsDao.saveDetails(detailList);
+    }
+
+    @Override
+    public void removeCustomOfferingDetails(long vmId){
+        Map<String, String> details = _uservmDetailsDao.listDetailsKeyPairs(vmId);
+        details.remove(UsageEventVO.DynamicParameters.cpuNumber.name());
+        details.remove(UsageEventVO.DynamicParameters.cpuSpeed.name());
+        details.remove(UsageEventVO.DynamicParameters.memory.name());
+        List <UserVmDetailVO> detailList = new ArrayList<UserVmDetailVO>();
+        for (String key : details.keySet()) {
+            UserVmDetailVO detailVO = new UserVmDetailVO(vmId, key, details.get(key));
+            detailList.add(detailVO);
+        }
+        _uservmDetailsDao.saveDetails(detailList);
+    }
+
+    @Override
     public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException {
         HashMap<Long, VmStatsEntry> vmStatsById = new HashMap<Long, VmStatsEntry>();
 
@@ -2594,10 +2689,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                 }
             }
 
-            details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.cpuNumber.toString(), cpuNumber.toString()));
-            details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.cpuSpeed.toString(), cpuSpeed.toString()));
-            details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.memory.toString(), memory.toString()));
-            offering = _serviceOfferingDao.getcomputeOffering(serviceOffering.getId(), cpuNumber, cpuSpeed, memory);
+            details.add(new UserVmDetailVO(id, UsageEventVO.DynamicParameters.cpuNumber.toString(), cpuNumber.toString()));
+            details.add(new UserVmDetailVO(id, UsageEventVO.DynamicParameters.cpuSpeed.toString(), cpuSpeed.toString()));
+            details.add(new UserVmDetailVO(id, UsageEventVO.DynamicParameters.memory.toString(), memory.toString()));
+            offering.setCpu(cpuNumber);
+            offering.setRamSize(memory);
+            offering.setSpeed(cpuSpeed);
             offering.setDynamicFlag(true);
         }
         if (hostName != null) {
@@ -2814,6 +2911,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         });
     }
 
+    private void generateUsageEvent(ServiceOfferingVO serviceOffering, Map<String, String> customParameters, UserVmVO vm,  String eventType){
+        if (!serviceOffering.isDynamic()) {
+            UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(),
+                    vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(),
+                    VirtualMachine.class.getName(), vm.getUuid());
+        }
+        else {
+            UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(),
+                    vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(),
+                    VirtualMachine.class.getName(), vm.getUuid(), customParameters);
+        }
+    }
+
     private void validateUserData(String userData, HTTPMethod httpmethod) {
         byte[] decodedUserData = null;
         if (userData != null) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/server/test/com/cloud/vm/UserVmManagerTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java
index 71bbebe..83f7520 100755
--- a/server/test/com/cloud/vm/UserVmManagerTest.java
+++ b/server/test/com/cloud/vm/UserVmManagerTest.java
@@ -136,6 +136,8 @@ public class UserVmManagerTest {
     @Mock
     ServiceOfferingDao _offeringDao;
     @Mock
+    ServiceOfferingVO _offeringVo;
+    @Mock
     EntityManager _entityMgr;
     @Mock
     ResourceLimitService _resourceLimitMgr;
@@ -384,12 +386,12 @@ public class UserVmManagerTest {
 
         doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock);
 
-        doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, cmd.getServiceOfferingId());
+        doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, _offeringVo);
 
         ServiceOffering so1 = getSvcoffering(512);
         ServiceOffering so2 = getSvcoffering(256);
 
-        when(_entityMgr.findById(eq(ServiceOffering.class), anyLong())).thenReturn(so1);
+        when(_offeringDao.findById(anyLong())).thenReturn((ServiceOfferingVO)so1);
         when(_offeringDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn((ServiceOfferingVO)so1);
 
         Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, UUID.randomUUID().toString());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68406ba2/usage/src/com/cloud/usage/UsageManagerImpl.java
----------------------------------------------------------------------
diff --git a/usage/src/com/cloud/usage/UsageManagerImpl.java b/usage/src/com/cloud/usage/UsageManagerImpl.java
index 81e7892..3da7d48 100644
--- a/usage/src/com/cloud/usage/UsageManagerImpl.java
+++ b/usage/src/com/cloud/usage/UsageManagerImpl.java
@@ -1113,14 +1113,14 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
                 Map<String, String> usageDetails = _usageEventDetailsDao.findDetails(event.getId());
 
                 if (usageDetails != null && usageDetails.size() != 0) {
-                    if (usageDetails.get(UsageVMInstanceVO.DynamicParameters.cpuNumber.name()) != null) {
-                        cpuCores = Long.parseLong(usageDetails.get(UsageVMInstanceVO.DynamicParameters.cpuNumber.name()));
+                    if (usageDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name()) != null) {
+                        cpuCores = Long.parseLong(usageDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name()));
                     }
-                    if (usageDetails.get(UsageVMInstanceVO.DynamicParameters.cpuSpeed.name()) != null) {
-                        cpuSpeed = Long.parseLong(usageDetails.get(UsageVMInstanceVO.DynamicParameters.cpuSpeed.name()));
+                    if (usageDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()) != null) {
+                        cpuSpeed = Long.parseLong(usageDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()));
                     }
-                    if (usageDetails.get(UsageVMInstanceVO.DynamicParameters.memory.name()) != null) {
-                        memory = Long.parseLong(usageDetails.get(UsageVMInstanceVO.DynamicParameters.memory.name()));
+                    if (usageDetails.get(UsageEventVO.DynamicParameters.memory.name()) != null) {
+                        memory = Long.parseLong(usageDetails.get(UsageEventVO.DynamicParameters.memory.name()));
                     }
                 }
 


Mime
View raw message