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

This commit is contained in:
Harikrishna Patnala 2013-07-31 11:05:10 +05:30 committed by Kishan Kavala
parent fee7a868e1
commit 2c53ede1de
6 changed files with 154 additions and 37 deletions

View File

@ -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";

View File

@ -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();
}
}

View File

@ -86,9 +86,18 @@ public class ScaleVMCmd extends BaseAsyncCmd {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@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();
}
}

View File

@ -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");
}
}

View File

@ -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));
}
}
}
}
}

View File

@ -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);
}
}