CLOUDSTACK-658 - Adding capacity related changes

This commit is contained in:
Nitin Mehta 2013-03-18 20:09:23 +05:30
parent 6bf8ff623d
commit bffc09c61a
5 changed files with 81 additions and 75 deletions

View File

@ -40,14 +40,14 @@ public class ScaleVmCommand extends Command {
}
public ScaleVmCommand(String vmName, int cpus,
Integer speed, long minRam, long maxRam) {
Integer speed, long minRam, long maxRam, boolean limitCpuUse) {
super();
this.vmName = vmName;
this.cpus = cpus;
//this.speed = speed;
this.speed = speed;
this.minRam = minRam;
this.maxRam = maxRam;
this.vm = new VirtualMachineTO(1L, vmName, null, cpus, null, minRam, maxRam, null, null, false, false, null);
this.vm = new VirtualMachineTO(1L, vmName, null, cpus, speed, minRam, maxRam, null, null, false, false, null);
/*vm.setName(vmName);
vm.setCpus(cpus);
vm.setRam(minRam, maxRam);*/

View File

@ -41,7 +41,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I
Destroyed(false, "VM is marked for destroy."),
Expunging(true, "VM is being expunged."),
Migrating(true, "VM is being migrated. host id holds to from host"),
Reconfiguring(true, "VM is being reconfigured to a new service offering"),
Error(false, "VM is in error"),
Unknown(false, "VM state is unknown."),
Shutdowned(false, "VM is shutdowned from inside");
@ -96,9 +95,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I
s_fsm.addTransition(State.Running, VirtualMachine.Event.StopRequested, State.Stopping);
s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportShutdowned, State.Stopped);
s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportMigrated, State.Running);
s_fsm.addTransition(State.Running, VirtualMachine.Event.ReconfiguringRequested, State.Reconfiguring);
s_fsm.addTransition(State.Reconfiguring, VirtualMachine.Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Reconfiguring, VirtualMachine.Event.OperationFailed, State.Running);
s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationRequested, State.Migrating);
s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationFailed, State.Running);
@ -181,7 +177,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I
AgentReportMigrated,
RevertRequested,
SnapshotRequested,
ReconfiguringRequested
};
public enum Type {

View File

@ -339,7 +339,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Inject
protected SecurityGroupDao _securityGroupDao;
@Inject
protected CapacityManager _capacityMgr;;
protected CapacityManager _capacityMgr;
@Inject
protected VMInstanceDao _vmInstanceDao;
@Inject
@ -1043,7 +1043,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
public UserVm
upgradeVirtualMachine(ScaleVMCmd cmd) throws InvalidParameterValueException {
Long vmId = cmd.getId();
Long newSvcOffId = cmd.getServiceOfferingId();
Long newServiceOfferingId = cmd.getServiceOfferingId();
Account caller = UserContext.current().getCaller();
// Verify input parameters
@ -1055,14 +1055,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
_accountMgr.checkAccess(caller, null, true, vmInstance);
// Check that the specified service offering ID is valid
_itMgr.checkIfCanUpgrade(vmInstance, newSvcOffId);
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOfferingId);
//Check if its a scale "up"
ServiceOffering newServiceOffering = _configMgr.getServiceOffering(newSvcOffId);
ServiceOffering newServiceOffering = _configMgr.getServiceOffering(newServiceOfferingId);
ServiceOffering oldServiceOffering = _configMgr.getServiceOffering(vmInstance.getServiceOfferingId());
if(newServiceOffering.getSpeed() <= oldServiceOffering.getSpeed()
&& newServiceOffering.getRamSize() <= oldServiceOffering.getRamSize()){
throw new InvalidParameterValueException("Only scaling up the vm is supported");
throw new InvalidParameterValueException("Only scaling up the vm is supported, new service offering should have both cpu and memory greater than the old values");
}
// Dynamically upgrade the running vms
@ -1073,38 +1073,41 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
try{
// #1 Check existing host has capacity
boolean existingHostHasCapacity = _capacityMgr.checkIfHostHasCapacity(vmInstance.getHostId(), newServiceOffering.getSpeed() - oldServiceOffering.getSpeed(),
(newServiceOffering.getRamSize() - oldServiceOffering.getRamSize()) * 1024L * 1024L, false, ApiDBUtils.getCpuOverprovisioningFactor(), 1f, false);
(newServiceOffering.getRamSize() - oldServiceOffering.getRamSize()) * 1024L * 1024L, false, ApiDBUtils.getCpuOverprovisioningFactor(), 1f, false); // TO DO fill it with mem.
// #2 migrate the vm if host doesn't have capacity
if (!existingHostHasCapacity){
vmInstance = _itMgr.scale(vmInstance.getType(), vmInstance, newSvcOffId);
}else{
vmInstance.setSameHost(existingHostHasCapacity);
vmInstance = _itMgr.findHostAndMigrate(vmInstance.getType(), vmInstance, newServiceOfferingId);
}
// #3 scale the vm now
vmInstance = _itMgr.reConfigureVm(vmInstance, newServiceOffering, existingHostHasCapacity);
_itMgr.upgradeVmDb(vmId, newServiceOfferingId);
vmInstance = _vmInstanceDao.findById(vmId);
vmInstance = _itMgr.reConfigureVm(vmInstance, oldServiceOffering, existingHostHasCapacity);
success = true;
return _vmDao.findById(vmInstance.getId());
}catch(InsufficientCapacityException e ){
s_logger.warn("Recieved exception while scaling ",e);
s_logger.warn("Received exception while scaling ",e);
} catch (ResourceUnavailableException e) {
s_logger.warn("Recieved exception while scaling ",e);
s_logger.warn("Received exception while scaling ",e);
} catch (ConcurrentOperationException e) {
s_logger.warn("Recieved exception while scaling ",e);
s_logger.warn("Received exception while scaling ",e);
} catch (VirtualMachineMigrationException e) {
s_logger.warn("Recieved exception while scaling ",e);
s_logger.warn("Received exception while scaling ",e);
} catch (ManagementServerException e) {
s_logger.warn("Recieved exception while scaling ",e);
s_logger.warn("Received exception while scaling ",e);
}finally{
if(!success){
_itMgr.upgradeVmDb(vmId, oldServiceOffering.getId()); // rollback
}
}
}
if (!success)
return null;
}
//Update the DB.
_itMgr.upgradeVmDb(vmId, newSvcOffId);
return _vmDao.findById(vmInstance.getId());
}
@Override

View File

@ -190,7 +190,7 @@ public interface VirtualMachineManager extends Manager {
VMInstanceVO reConfigureVm(VMInstanceVO vm, ServiceOffering newServiceOffering, boolean sameHost)
throws ResourceUnavailableException, ConcurrentOperationException;
VMInstanceVO scale(VirtualMachine.Type vmType, VMInstanceVO vm, Long newSvcOfferingId) throws InsufficientCapacityException,
VMInstanceVO findHostAndMigrate(VirtualMachine.Type vmType, VMInstanceVO vm, Long newSvcOfferingId) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException,
VirtualMachineMigrationException, ManagementServerException;

View File

@ -36,6 +36,7 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.capacity.CapacityManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
@ -175,6 +176,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Inject
protected UserVmDao _userVmDao;
@Inject
protected CapacityManager _capacityMgr;
@Inject
protected NicDao _nicsDao;
@Inject
protected AccountManager _accountMgr;
@ -2659,7 +2662,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
@Override
public VMInstanceVO scale(VirtualMachine.Type vmType, VMInstanceVO vm, Long newSvcOfferingId)
public VMInstanceVO findHostAndMigrate(VirtualMachine.Type vmType, VMInstanceVO vm, Long newSvcOfferingId)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, VirtualMachineMigrationException, ManagementServerException {
VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
@ -2729,53 +2732,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
}
@Override
public VMInstanceVO reConfigureVm(VMInstanceVO vm , ServiceOffering newServiceOffering, boolean sameHost) throws ResourceUnavailableException, ConcurrentOperationException {
ScaleVmCommand reconfigureCmd = new ScaleVmCommand(vm.getInstanceName(), newServiceOffering.getCpu(),
newServiceOffering.getSpeed(), newServiceOffering.getRamSize(), newServiceOffering.getRamSize());
Long dstHostId = vm.getHostId();
ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Reconfiguring, vm.getType(), vm.getId());
work.setStep(Step.Prepare);
work.setResourceType(ItWorkVO.ResourceType.Host);
work.setResourceId(vm.getHostId());
work = _workDao.persist(work);
boolean success = false;
try {
vm.setNewSvcOfferingId(newServiceOffering.getId()); // Capacity update should be delta (new - old) offering
changeState(vm, Event.ReconfiguringRequested, dstHostId, work, Step.Reconfiguring);
Answer reconfigureAnswer = _agentMgr.send(vm.getHostId(), reconfigureCmd);
if (!reconfigureAnswer.getResult()) {
s_logger.error("Unable to reconfigure due to " + reconfigureAnswer.getDetails());
return null;
}
changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Done);
success = true;
} catch (OperationTimedoutException e) {
throw new AgentUnavailableException("Operation timed out on reconfiguring " + vm, dstHostId);
} catch (AgentUnavailableException e) {
throw e;
} catch (NoTransitionException e) {
s_logger.info("Unable to change the state : " + e.getMessage());
throw new ConcurrentOperationException("Unable to change the state : " + e.getMessage());
}finally{
work.setStep(Step.Done);
_workDao.update(work.getId(), work);
if(!success){
try {
stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
} catch (NoTransitionException e) {
s_logger.warn(e.getMessage());
}
}
}
return vm;
}
@Override
public <T extends VMInstanceVO> T migrateForScale(T vm, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
VirtualMachineMigrationException {
@ -2881,10 +2837,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
try {
long newServiceOfferingId = vm.getServiceOfferingId();
vm.setServiceOfferingId(oldSvcOfferingId); // release capacity for the old service offering only
if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
throw new ConcurrentOperationException("Unable to change the state for " + vm);
}
vm.setServiceOfferingId(newServiceOfferingId);
} catch (NoTransitionException e1) {
throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
}
@ -2928,6 +2886,56 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
_workDao.update(work.getId(), work);
}
}
@Override
public VMInstanceVO reConfigureVm(VMInstanceVO vm , ServiceOffering oldServiceOffering, boolean reconfiguringOnExistingHost) throws ResourceUnavailableException, ConcurrentOperationException {
long newServiceofferingId = vm.getServiceOfferingId();
ServiceOffering newServiceOffering = _configMgr.getServiceOffering(newServiceofferingId);
ScaleVmCommand reconfigureCmd = new ScaleVmCommand(vm.getInstanceName(), newServiceOffering.getCpu(),
newServiceOffering.getSpeed(), newServiceOffering.getRamSize(), newServiceOffering.getRamSize(), newServiceOffering.getLimitCpuUse());
Long dstHostId = vm.getHostId();
ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Running, vm.getType(), vm.getId());
work.setStep(Step.Prepare);
work.setResourceType(ItWorkVO.ResourceType.Host);
work.setResourceId(vm.getHostId());
work = _workDao.persist(work);
boolean success = false;
try {
if(reconfiguringOnExistingHost){
vm.setServiceOfferingId(oldServiceOffering.getId());
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); //release the old capacity
vm.setServiceOfferingId(newServiceofferingId);
_capacityMgr.allocateVmCapacity(vm, false); // lock the new capacity
}
//vm.setNewSvcOfferingId(newServiceOffering.getId()); // Capacity update should be delta (new - old) offering
//changeState(vm, Event.ReconfiguringRequested, dstHostId, work, Step.Reconfiguring);
Answer reconfigureAnswer = _agentMgr.send(vm.getHostId(), reconfigureCmd);
if (!reconfigureAnswer.getResult()) {
s_logger.error("Unable to reconfigure due to " + reconfigureAnswer.getDetails());
return null;
}
//changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Done);
success = true;
} catch (OperationTimedoutException e) {
throw new AgentUnavailableException("Operation timed out on reconfiguring " + vm, dstHostId);
} catch (AgentUnavailableException e) {
throw e;
} finally{
work.setStep(Step.Done);
_workDao.update(work.getId(), work);
if(!success){
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); // release the new capacity
vm.setServiceOfferingId(oldServiceOffering.getId());
_capacityMgr.allocateVmCapacity(vm, false); // allocate the old capacity
}
}
return vm;
}
}