Updated Branches:
  refs/heads/master fee7a868e -> 9939d0945

CLOUDSTACK-3848: Usage events for dynamic scaling of cpu/ram operation on VM


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

Branch: refs/heads/master
Commit: 2c53ede1de1aae2f919e6235975e3342026a134a
Parents: fee7a86
Author: Harikrishna Patnala <[email protected]>
Authored: Wed Jul 31 11:05:10 2013 +0530
Committer: Kishan Kavala <[email protected]>
Committed: Wed Jul 31 15:07:17 2013 +0530

----------------------------------------------------------------------
 api/src/com/cloud/event/EventTypes.java         |   4 +-
 .../admin/systemvm/ScaleSystemVMCmd.java        |  12 +--
 .../api/command/user/vm/ScaleVMCmd.java         |  21 ++--
 .../com/cloud/server/ManagementServerImpl.java  |   4 +-
 server/src/com/cloud/vm/UserVmManagerImpl.java  | 105 ++++++++++++++++---
 usage/src/com/cloud/usage/UsageManagerImpl.java |  45 ++++++++
 6 files changed, 154 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2c53ede1/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java 
b/api/src/com/cloud/event/EventTypes.java
index 4fbab20..b3aa91a 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -70,7 +70,7 @@ public class EventTypes {
     public static final String EVENT_VM_REBOOT = "VM.REBOOT";
     public static final String EVENT_VM_UPDATE = "VM.UPDATE";
     public static final String EVENT_VM_UPGRADE = "VM.UPGRADE";
-    public static final String EVENT_VM_SCALE = "VM.SCALE";
+    public static final String EVENT_VM_DYNAMIC_SCALE = "VM.DYNAMIC.SCALE";
     public static final String EVENT_VM_RESETPASSWORD = "VM.RESETPASSWORD";
     public static final String EVENT_VM_RESETSSHKEY = "VM.RESETSSHKEY";
     public static final String EVENT_VM_MIGRATE = "VM.MIGRATE";
@@ -93,7 +93,6 @@ public class EventTypes {
     public static final String EVENT_PROXY_STOP = "PROXY.STOP";
     public static final String EVENT_PROXY_REBOOT = "PROXY.REBOOT";
     public static final String EVENT_PROXY_HA = "PROXY.HA";
-    public static final String EVENT_PROXY_SCALE = "PROXY.SCALE";
 
 
     // VNC Console Events
@@ -218,7 +217,6 @@ public class EventTypes {
     public static final String EVENT_SSVM_STOP = "SSVM.STOP";
     public static final String EVENT_SSVM_REBOOT = "SSVM.REBOOT";
     public static final String EVENT_SSVM_HA = "SSVM.HA";
-    public static final String EVENT_SSVM_SCALE = "SSVM.SCALE";
 
     // Service Offerings
     public static final String EVENT_SERVICE_OFFERING_CREATE = 
"SERVICE.OFFERING.CREATE";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2c53ede1/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 61b457f..94040df 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
@@ -111,23 +111,17 @@ public class ScaleSystemVMCmd extends BaseAsyncCmd {
             response.setResponseName(getCommandName());
             this.setResponseObject(response);
         } else {
-            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed 
to scale system vm");
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed 
to upgrade system vm");
         }
     }
 
     @Override
     public String getEventType() {
-        VirtualMachine.Type type = _mgr.findSystemVMTypeById(getId());
-        if(type == VirtualMachine.Type.ConsoleProxy){
-            return EventTypes.EVENT_PROXY_SCALE;
-        }
-        else{
-            return EventTypes.EVENT_SSVM_SCALE;
-        }
+        return EventTypes.EVENT_VM_UPGRADE;
     }
 
     @Override
     public String getEventDescription() {
-        return  "scaling system vm: " + getId() + " to service offering: " + 
getServiceOfferingId();
+        return  "Upgrading system vm: " + getId() + " to service offering: " + 
getServiceOfferingId();
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2c53ede1/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 ac04419..44f5575 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
@@ -87,8 +87,17 @@ public class ScaleVMCmd extends BaseAsyncCmd {
     }
 
     @Override
+    public String getEventType() {
+        return EventTypes.EVENT_VM_UPGRADE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "upgrading vm: " + getId() + " to service offering: " + 
getServiceOfferingId();
+    }
+
+    @Override
     public void execute(){
-        //UserContext.current().setEventDetails("Vm Id: "+getId());
         UserVm result;
         try {
             result = _userVmService.upgradeVirtualMachine(this);
@@ -114,14 +123,4 @@ public class ScaleVMCmd extends BaseAsyncCmd {
             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed 
to scale vm");
         }
     }
-
-    @Override
-    public String getEventType() {
-        return EventTypes.EVENT_VM_SCALE;
-    }
-
-    @Override
-    public String getEventDescription() {
-        return  "scaling volume: " + getId() + " to service offering: " + 
getServiceOfferingId();
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2c53ede1/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 29b35d1..dbb2f2a 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -3202,6 +3202,7 @@ public class ManagementServerImpl extends ManagerBase 
implements ManagementServe
     public Map<String, Object> listCapabilities(ListCapabilitiesCmd cmd) {
         Map<String, Object> capabilities = new HashMap<String, Object>();
 
+        Account caller = CallContext.current().getCallingAccount();
         boolean securityGroupsEnabled = false;
         boolean elasticLoadBalancerEnabled = false;
         String supportELB = "false";
@@ -3729,6 +3730,7 @@ public class ManagementServerImpl extends ManagerBase 
implements ManagementServe
     }
 
     @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VM_UPGRADE, eventDescription = 
"Upgrading system VM", async = true)
     public VirtualMachine upgradeSystemVM(ScaleSystemVMCmd cmd) throws 
ResourceUnavailableException, ManagementServerException, 
VirtualMachineMigrationException, ConcurrentOperationException {
 
         VMInstanceVO vmInstance = _vmInstanceDao.findById(cmd.getId());
@@ -3740,7 +3742,7 @@ public class ManagementServerImpl extends ManagerBase 
implements ManagementServe
             VirtualMachine vm = _vmInstanceDao.findById(cmd.getId());
             return vm;
         }else{
-            return null;
+            throw new CloudRuntimeException("Failed to upgrade System VM");
         }
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2c53ede1/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 227a785..4e09dac 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -758,14 +758,10 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
     /*
      * TODO: cleanup eventually - Refactored API call
      */
+    // This method will be deprecated as we use ScaleVMCmd for both stopped 
VMs and running VMs
     public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws 
ResourceAllocationException {
         Long vmId = cmd.getId();
         Long svcOffId = cmd.getServiceOfferingId();
-        return upgradeStoppedVirtualMachine(vmId, svcOffId);
-    }
-
-
-    private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId) 
throws ResourceAllocationException {
         Account caller = CallContext.current().getCallingAccount();
 
         // Verify input parameters
@@ -831,6 +827,70 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
                 vmInstance.getServiceOfferingId(), vmInstance.getTemplateId(), 
vmInstance.getHypervisorType().toString(), VirtualMachine.class.getName(), 
vmInstance.getUuid());
 
         return _vmDao.findById(vmInstance.getId());
+    }
+
+    private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId) 
throws ResourceAllocationException {
+        Account caller = CallContext.current().getCallingAccount();
+
+        // Verify input parameters
+        //UserVmVO vmInstance = _vmDao.findById(vmId);
+        VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
+        if (vmInstance == null) {
+            throw new InvalidParameterValueException(
+                    "unable to find a virtual machine with id " + vmId);
+        }
+
+        _accountMgr.checkAccess(caller, null, true, vmInstance);
+
+        // Check resource limits for CPU and Memory.
+        ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId);
+        ServiceOfferingVO currentServiceOffering = 
_offeringDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId());
+
+        int newCpu = newServiceOffering.getCpu();
+        int newMemory = newServiceOffering.getRamSize();
+        int currentCpu = currentServiceOffering.getCpu();
+        int currentMemory = currentServiceOffering.getRamSize();
+
+        if (newCpu > currentCpu) {
+            _resourceLimitMgr.checkResourceLimit(caller, ResourceType.cpu,
+                    newCpu - currentCpu);
+        }
+        if (newMemory > currentMemory) {
+            _resourceLimitMgr.checkResourceLimit(caller, ResourceType.memory,
+                    newMemory - currentMemory);
+        }
+
+        // Check that the specified service offering ID is valid
+        _itMgr.checkIfCanUpgrade(vmInstance, svcOffId);
+
+        // remove diskAndMemory VM snapshots
+        List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
+        for (VMSnapshotVO vmSnapshotVO : vmSnapshots) {
+            if(vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory){
+                if(!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, 
VMSnapshot.Type.DiskAndMemory)){
+                    String errMsg = "Failed to remove VM snapshot during 
upgrading, snapshot id " + vmSnapshotVO.getId();
+                    s_logger.debug(errMsg);
+                    throw new CloudRuntimeException(errMsg);
+                }
+
+            }
+        }
+
+        _itMgr.upgradeVmDb(vmId, svcOffId);
+
+        // Increment or decrement CPU and Memory count accordingly.
+        if (newCpu > currentCpu) {
+            _resourceLimitMgr.incrementResourceCount(caller.getAccountId(), 
ResourceType.cpu, new Long (newCpu - currentCpu));
+        } else if (currentCpu > newCpu) {
+            _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), 
ResourceType.cpu, new Long (currentCpu - newCpu));
+        }
+        if (newMemory > currentMemory) {
+            _resourceLimitMgr.incrementResourceCount(caller.getAccountId(), 
ResourceType.memory, new Long (newMemory - currentMemory));
+        } else if (currentMemory > newMemory) {
+            _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), 
ResourceType.memory, new Long (currentMemory - newMemory));
+        }
+
+        return _vmDao.findById(vmInstance.getId());
 
     }
 
@@ -1083,17 +1143,30 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
     }
 
     @Override
-    @ActionEvent(eventType = EventTypes.EVENT_VM_SCALE, eventDescription = 
"scaling Vm")
+    @ActionEvent(eventType = EventTypes.EVENT_VM_UPGRADE, eventDescription = 
"Upgrading VM", async = true)
     public UserVm
     upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, 
ConcurrentOperationException, ManagementServerException, 
VirtualMachineMigrationException{
 
         Long vmId = cmd.getId();
         Long newServiceOfferingId = cmd.getServiceOfferingId();
+        CallContext.current().setEventDetails("Vm Id: " + vmId);
+
         boolean  result = upgradeVirtualMachine(vmId, newServiceOfferingId);
         if(result){
-            return _vmDao.findById(vmId);
-        }else{
-            return null;
+            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());
+            }
+            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());
+            }
+            return vmInstance;
+        } else {
+            throw new CloudRuntimeException("Failed to scale the VM");
         }
 
     }
@@ -1135,7 +1208,6 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
 
     @Override
     public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId) 
throws ResourceUnavailableException, ConcurrentOperationException, 
ManagementServerException, VirtualMachineMigrationException{
-        Account caller = CallContext.current().getCallingAccount();
 
         // Verify input parameters
         VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
@@ -1144,7 +1216,16 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
             upgradeStoppedVirtualMachine(vmId, newServiceOfferingId);
             return true;
         }
+        if(vmInstance.getState().equals(State.Running)){
+            return upgradeRunningVirtualMachine(vmId, newServiceOfferingId);
+        }
+        return false;
+    }
 
+    private boolean upgradeRunningVirtualMachine(Long vmId, Long 
newServiceOfferingId) throws ResourceUnavailableException, 
ConcurrentOperationException, ManagementServerException, 
VirtualMachineMigrationException{
+
+        Account caller = CallContext.current().getCallingAccount();
+        VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
         if(vmInstance.getHypervisorType() != HypervisorType.XenServer && 
vmInstance.getHypervisorType() != HypervisorType.VMware){
             throw new InvalidParameterValueException("This operation not 
permitted for this hypervisor of the vm");
         }
@@ -1237,13 +1318,11 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
                         // Decrement CPU and Memory count accordingly.
                         if (newCpu > currentCpu) {
                             
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), 
ResourceType.cpu, new Long (newCpu - currentCpu));
-                    }
+                        }
                         if (newMemory > currentMemory) {
                             
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), 
ResourceType.memory, new Long (newMemory - currentMemory));
                         }
                     }
-
-
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2c53ede1/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 aa9def5..8dc62c3 100644
--- a/usage/src/com/cloud/usage/UsageManagerImpl.java
+++ b/usage/src/com/cloud/usage/UsageManagerImpl.java
@@ -1080,6 +1080,51 @@ public class UsageManagerImpl extends ManagerBase 
implements UsageManager, Runna
             UsageVMInstanceVO usageInstanceNew = new 
UsageVMInstanceVO(UsageTypes.ALLOCATED_VM, zoneId, event.getAccountId(), vmId, 
vmName,
                     soId, templateId, hypervisorType, event.getCreateDate(), 
null);
             m_usageInstanceDao.persist(usageInstanceNew);
+        } else if (EventTypes.EVENT_VM_DYNAMIC_SCALE.equals(event.getType())) {
+            // Ending the running vm event
+            SearchCriteria<UsageVMInstanceVO> sc = 
m_usageInstanceDao.createSearchCriteria();
+            sc.addAnd("vmInstanceId", SearchCriteria.Op.EQ, 
Long.valueOf(vmId));
+            sc.addAnd("endDate", SearchCriteria.Op.NULL);
+            sc.addAnd("usageType", SearchCriteria.Op.EQ, 
UsageTypes.RUNNING_VM);
+            List<UsageVMInstanceVO> usageInstances = 
m_usageInstanceDao.search(sc, null);
+            if (usageInstances != null) {
+                if (usageInstances.size() > 1) {
+                    s_logger.warn("found multiple entries for a vm running 
with id: " + vmId + ", ending them all...");
+                }
+                for (UsageVMInstanceVO usageInstance : usageInstances) {
+                    usageInstance.setEndDate(event.getCreateDate());
+                    m_usageInstanceDao.update(usageInstance);
+                }
+            }
+
+            sc = m_usageInstanceDao.createSearchCriteria();
+            sc.addAnd("vmInstanceId", SearchCriteria.Op.EQ, 
Long.valueOf(vmId));
+            sc.addAnd("endDate", SearchCriteria.Op.NULL);
+            sc.addAnd("usageType", SearchCriteria.Op.EQ, 
UsageTypes.ALLOCATED_VM);
+            usageInstances = m_usageInstanceDao.search(sc, null);
+            if (usageInstances == null || (usageInstances.size() == 0)) {
+                s_logger.error("Cannot find allocated vm entry for a vm 
running with id: " + vmId);
+            } else if (usageInstances.size() == 1) {
+                UsageVMInstanceVO usageInstance = usageInstances.get(0);
+                if(usageInstance.getSerivceOfferingId() != soId){
+                    //Service Offering changed after Vm creation
+                    //End current Allocated usage and create new Allocated Vm 
entry with new soId
+                    usageInstance.setEndDate(event.getCreateDate());
+                    m_usageInstanceDao.update(usageInstance);
+                    usageInstance.setServiceOfferingId(soId);
+                    usageInstance.setStartDate(event.getCreateDate());
+                    usageInstance.setEndDate(null);
+                    m_usageInstanceDao.persist(usageInstance);
+                }
+            }
+
+            Long templateId = event.getTemplateId();
+            String hypervisorType = event.getResourceType();
+
+            // add this VM to the usage helper table with new service offering 
Id
+            UsageVMInstanceVO usageInstanceNew = new 
UsageVMInstanceVO(UsageTypes.RUNNING_VM, zoneId, event.getAccountId(), vmId, 
vmName,
+                    soId, templateId, hypervisorType, event.getCreateDate(), 
null);
+            m_usageInstanceDao.persist(usageInstanceNew);
         }
     }
 

Reply via email to