mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
server: Submitting multiple dynamic VM Scaling API commands for the same instance can result in two usage events in the same second causing a compound key violation in usage service (#3991)
Root cause: Even though dynamic scaling job is handled in vmworkjob queue which ensures serilizing multiple jobs but the database updating and generating usage events are out of the job queue. Solution: Moved all updations into the job queue Firstly I have tested all the scenarios to check if nothing is broken: Scaling on a running VM with normal compute offering Scaling on a stopped VM with normal compute offering Scaling on a running VM with custom compute offering Scaling on stopped VM with custom compute offering Scaling on stopped/running VM between custom compute offering and normal compute offering and combinations among these. Checked if the custom parameters have been populated or deleted accordingly based on the offering to which the VM is scaled Since this is a corner scenario I could not test the exact point where two usage events are recorded at the same time for two different API calls on same VM.
This commit is contained in:
parent
6a683dcf77
commit
5054766d9f
@ -152,7 +152,7 @@ public interface VirtualMachineManager extends Manager {
|
|||||||
* @param serviceOfferingId
|
* @param serviceOfferingId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean upgradeVmDb(long vmId, long serviceOfferingId);
|
boolean upgradeVmDb(long vmId, ServiceOffering newServiceOffering, ServiceOffering currentServiceOffering);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param vm
|
* @param vm
|
||||||
@ -201,7 +201,7 @@ public interface VirtualMachineManager extends Manager {
|
|||||||
boolean replugNic(Network network, NicTO nic, VirtualMachineTO vm, ReservationContext context, DeployDestination dest) throws ConcurrentOperationException,
|
boolean replugNic(Network network, NicTO nic, VirtualMachineTO vm, ReservationContext context, DeployDestination dest) throws ConcurrentOperationException,
|
||||||
ResourceUnavailableException, InsufficientCapacityException;
|
ResourceUnavailableException, InsufficientCapacityException;
|
||||||
|
|
||||||
VirtualMachine reConfigureVm(String vmUuid, ServiceOffering newServiceOffering, boolean sameHost) throws ResourceUnavailableException, ConcurrentOperationException,
|
VirtualMachine reConfigureVm(String vmUuid, ServiceOffering oldServiceOffering, ServiceOffering newServiceOffering, Map<String, String> customParameters, boolean sameHost) throws ResourceUnavailableException, ConcurrentOperationException,
|
||||||
InsufficientServerCapacityException;
|
InsufficientServerCapacityException;
|
||||||
|
|
||||||
void findHostAndMigrate(String vmUuid, Long newSvcOfferingId, DeploymentPlanner.ExcludeList excludeHostList) throws InsufficientCapacityException,
|
void findHostAndMigrate(String vmUuid, Long newSvcOfferingId, DeploymentPlanner.ExcludeList excludeHostList) throws InsufficientCapacityException,
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import javax.naming.ConfigurationException;
|
|||||||
|
|
||||||
import com.cloud.agent.api.PrepareForMigrationAnswer;
|
import com.cloud.agent.api.PrepareForMigrationAnswer;
|
||||||
import com.cloud.agent.api.to.DpdkTO;
|
import com.cloud.agent.api.to.DpdkTO;
|
||||||
|
import com.cloud.event.UsageEventVO;
|
||||||
import com.cloud.offering.NetworkOffering;
|
import com.cloud.offering.NetworkOffering;
|
||||||
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
|
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
|
||||||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||||
@ -232,6 +233,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
|
|
||||||
private static final String VM_SYNC_ALERT_SUBJECT = "VM state sync alert";
|
private static final String VM_SYNC_ALERT_SUBJECT = "VM state sync alert";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private UserVmManager _userVmMgr;
|
||||||
@Inject
|
@Inject
|
||||||
private DataStoreManager dataStoreMgr;
|
private DataStoreManager dataStoreMgr;
|
||||||
@Inject
|
@Inject
|
||||||
@ -3406,13 +3409,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean upgradeVmDb(final long vmId, final long serviceOfferingId) {
|
public boolean upgradeVmDb(final long vmId, final ServiceOffering newServiceOffering, ServiceOffering currentServiceOffering) {
|
||||||
final VMInstanceVO vmForUpdate = _vmDao.createForUpdate();
|
|
||||||
vmForUpdate.setServiceOfferingId(serviceOfferingId);
|
final VMInstanceVO vmForUpdate = _vmDao.findById(vmId);
|
||||||
final ServiceOffering newSvcOff = _entityMgr.findById(ServiceOffering.class, serviceOfferingId);
|
vmForUpdate.setServiceOfferingId(newServiceOffering.getId());
|
||||||
|
final ServiceOffering newSvcOff = _entityMgr.findById(ServiceOffering.class, newServiceOffering.getId());
|
||||||
vmForUpdate.setHaEnabled(newSvcOff.isOfferHA());
|
vmForUpdate.setHaEnabled(newSvcOff.isOfferHA());
|
||||||
vmForUpdate.setLimitCpuUse(newSvcOff.getLimitCpuUse());
|
vmForUpdate.setLimitCpuUse(newSvcOff.getLimitCpuUse());
|
||||||
vmForUpdate.setServiceOfferingId(newSvcOff.getId());
|
vmForUpdate.setServiceOfferingId(newSvcOff.getId());
|
||||||
|
if (newServiceOffering.isDynamic()) {
|
||||||
|
saveCustomOfferingDetails(vmId, newServiceOffering);
|
||||||
|
}
|
||||||
|
if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
|
||||||
|
removeCustomOfferingDetails(vmId);
|
||||||
|
}
|
||||||
return _vmDao.update(vmId, vmForUpdate);
|
return _vmDao.update(vmId, vmForUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4087,8 +4097,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VMInstanceVO reConfigureVm(final String vmUuid, final ServiceOffering oldServiceOffering,
|
public VMInstanceVO reConfigureVm(final String vmUuid, final ServiceOffering oldServiceOffering, final ServiceOffering newServiceOffering,
|
||||||
final boolean reconfiguringOnExistingHost)
|
Map<String, String> customParameters, final boolean reconfiguringOnExistingHost)
|
||||||
throws ResourceUnavailableException, InsufficientServerCapacityException, ConcurrentOperationException {
|
throws ResourceUnavailableException, InsufficientServerCapacityException, ConcurrentOperationException {
|
||||||
|
|
||||||
final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
|
final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
|
||||||
@ -4098,14 +4108,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
final VirtualMachine vm = _vmDao.findByUuid(vmUuid);
|
final VirtualMachine vm = _vmDao.findByUuid(vmUuid);
|
||||||
placeHolder = createPlaceHolderWork(vm.getId());
|
placeHolder = createPlaceHolderWork(vm.getId());
|
||||||
try {
|
try {
|
||||||
return orchestrateReConfigureVm(vmUuid, oldServiceOffering, reconfiguringOnExistingHost);
|
return orchestrateReConfigureVm(vmUuid, oldServiceOffering, newServiceOffering, reconfiguringOnExistingHost);
|
||||||
} finally {
|
} finally {
|
||||||
if (placeHolder != null) {
|
if (placeHolder != null) {
|
||||||
_workJobDao.expunge(placeHolder.getId());
|
_workJobDao.expunge(placeHolder.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final Outcome<VirtualMachine> outcome = reconfigureVmThroughJobQueue(vmUuid, oldServiceOffering, reconfiguringOnExistingHost);
|
final Outcome<VirtualMachine> outcome = reconfigureVmThroughJobQueue(vmUuid, oldServiceOffering, newServiceOffering, customParameters, reconfiguringOnExistingHost);
|
||||||
|
|
||||||
VirtualMachine vm = null;
|
VirtualMachine vm = null;
|
||||||
try {
|
try {
|
||||||
@ -4134,14 +4144,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private VMInstanceVO orchestrateReConfigureVm(final String vmUuid, final ServiceOffering oldServiceOffering, final boolean reconfiguringOnExistingHost) throws ResourceUnavailableException,
|
private VMInstanceVO orchestrateReConfigureVm(final String vmUuid, final ServiceOffering oldServiceOffering, final ServiceOffering newServiceOffering,
|
||||||
ConcurrentOperationException {
|
final boolean reconfiguringOnExistingHost) throws ResourceUnavailableException, ConcurrentOperationException {
|
||||||
final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
|
final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
|
||||||
|
upgradeVmDb(vm.getId(), newServiceOffering, oldServiceOffering);
|
||||||
|
|
||||||
final long newServiceofferingId = vm.getServiceOfferingId();
|
|
||||||
final ServiceOffering newServiceOffering = _offeringDao.findById(vm.getId(), newServiceofferingId);
|
|
||||||
final HostVO hostVo = _hostDao.findById(vm.getHostId());
|
final HostVO hostVo = _hostDao.findById(vm.getHostId());
|
||||||
|
|
||||||
final Float memoryOvercommitRatio = CapacityManager.MemOverprovisioningFactor.valueIn(hostVo.getClusterId());
|
final Float memoryOvercommitRatio = CapacityManager.MemOverprovisioningFactor.valueIn(hostVo.getClusterId());
|
||||||
final Float cpuOvercommitRatio = CapacityManager.CpuOverprovisioningFactor.valueIn(hostVo.getClusterId());
|
final Float cpuOvercommitRatio = CapacityManager.CpuOverprovisioningFactor.valueIn(hostVo.getClusterId());
|
||||||
final long minMemory = (long)(newServiceOffering.getRamSize() / memoryOvercommitRatio);
|
final long minMemory = (long)(newServiceOffering.getRamSize() / memoryOvercommitRatio);
|
||||||
@ -4168,7 +4176,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
if (reconfiguringOnExistingHost) {
|
if (reconfiguringOnExistingHost) {
|
||||||
vm.setServiceOfferingId(oldServiceOffering.getId());
|
vm.setServiceOfferingId(oldServiceOffering.getId());
|
||||||
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); //release the old capacity
|
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); //release the old capacity
|
||||||
vm.setServiceOfferingId(newServiceofferingId);
|
vm.setServiceOfferingId(newServiceOffering.getId());
|
||||||
_capacityMgr.allocateVmCapacity(vm, false); // lock the new capacity
|
_capacityMgr.allocateVmCapacity(vm, false); // lock the new capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4177,7 +4185,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
s_logger.error("Unable to scale vm due to " + (reconfigureAnswer == null ? "" : reconfigureAnswer.getDetails()));
|
s_logger.error("Unable to scale vm due to " + (reconfigureAnswer == null ? "" : reconfigureAnswer.getDetails()));
|
||||||
throw new CloudRuntimeException("Unable to scale vm due to " + (reconfigureAnswer == null ? "" : reconfigureAnswer.getDetails()));
|
throw new CloudRuntimeException("Unable to scale vm due to " + (reconfigureAnswer == null ? "" : reconfigureAnswer.getDetails()));
|
||||||
}
|
}
|
||||||
|
if (vm.getType().equals(VirtualMachine.Type.User)) {
|
||||||
|
_userVmMgr.generateUsageEvent(vm, vm.isDisplayVm(), EventTypes.EVENT_VM_DYNAMIC_SCALE);
|
||||||
|
}
|
||||||
success = true;
|
success = true;
|
||||||
} catch (final OperationTimedoutException e) {
|
} catch (final OperationTimedoutException e) {
|
||||||
throw new AgentUnavailableException("Operation timed out on reconfiguring " + vm, dstHostId);
|
throw new AgentUnavailableException("Operation timed out on reconfiguring " + vm, dstHostId);
|
||||||
@ -4186,7 +4196,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
} finally {
|
} finally {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); // release the new capacity
|
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); // release the new capacity
|
||||||
vm.setServiceOfferingId(oldServiceOffering.getId());
|
upgradeVmDb(vm.getId(), oldServiceOffering, newServiceOffering); // rollback
|
||||||
_capacityMgr.allocateVmCapacity(vm, false); // allocate the old capacity
|
_capacityMgr.allocateVmCapacity(vm, false); // allocate the old capacity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4195,6 +4205,33 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private 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(Map.Entry<String, String> entry: details.entrySet()) {
|
||||||
|
UserVmDetailVO detailVO = new UserVmDetailVO(vmId, entry.getKey(), entry.getValue(), true);
|
||||||
|
detailList.add(detailVO);
|
||||||
|
}
|
||||||
|
userVmDetailsDao.saveDetails(detailList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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 (Map.Entry<String, String> entry: details.entrySet()) {
|
||||||
|
UserVmDetailVO detailVO = new UserVmDetailVO(vmId, entry.getKey(), entry.getValue(), true);
|
||||||
|
detailList.add(detailVO);
|
||||||
|
}
|
||||||
|
userVmDetailsDao.saveDetails(detailList);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigComponentName() {
|
public String getConfigComponentName() {
|
||||||
return VirtualMachineManager.class.getSimpleName();
|
return VirtualMachineManager.class.getSimpleName();
|
||||||
@ -5090,7 +5127,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Outcome<VirtualMachine> reconfigureVmThroughJobQueue(
|
public Outcome<VirtualMachine> reconfigureVmThroughJobQueue(
|
||||||
final String vmUuid, final ServiceOffering newServiceOffering, final boolean reconfiguringOnExistingHost) {
|
final String vmUuid, final ServiceOffering oldServiceOffering, final ServiceOffering newServiceOffering, Map<String, String> customParameters, final boolean reconfiguringOnExistingHost) {
|
||||||
|
|
||||||
final CallContext context = CallContext.current();
|
final CallContext context = CallContext.current();
|
||||||
final User user = context.getCallingUser();
|
final User user = context.getCallingUser();
|
||||||
@ -5121,7 +5158,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
|
|
||||||
// save work context info (there are some duplications)
|
// save work context info (there are some duplications)
|
||||||
final VmWorkReconfigure workInfo = new VmWorkReconfigure(user.getId(), account.getId(), vm.getId(),
|
final VmWorkReconfigure workInfo = new VmWorkReconfigure(user.getId(), account.getId(), vm.getId(),
|
||||||
VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, newServiceOffering.getId(), reconfiguringOnExistingHost);
|
VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, oldServiceOffering.getId(), newServiceOffering.getId(), customParameters, reconfiguringOnExistingHost);
|
||||||
workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
|
workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
|
||||||
|
|
||||||
_jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
|
_jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
|
||||||
@ -5280,10 +5317,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
s_logger.info("Unable to find vm " + work.getVmId());
|
s_logger.info("Unable to find vm " + work.getVmId());
|
||||||
}
|
}
|
||||||
assert vm != null;
|
assert vm != null;
|
||||||
|
ServiceOfferingVO oldServiceOffering = _offeringDao.findById(work.getOldServiceOfferingId());
|
||||||
|
ServiceOfferingVO newServiceOffering = _offeringDao.findById(work.getNewServiceOfferingId());
|
||||||
|
if (newServiceOffering.isDynamic()) {
|
||||||
|
// update the service offering object with the custom parameters like cpu, memory
|
||||||
|
newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, work.getCustomParameters());
|
||||||
|
}
|
||||||
|
|
||||||
final ServiceOffering newServiceOffering = _offeringDao.findById(vm.getId(), work.getNewServiceOfferingId());
|
reConfigureVm(vm.getUuid(), oldServiceOffering, newServiceOffering, work.getCustomParameters(),
|
||||||
|
|
||||||
reConfigureVm(vm.getUuid(), newServiceOffering,
|
|
||||||
work.isSameHost());
|
work.isSameHost());
|
||||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
|
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,25 +17,40 @@
|
|||||||
package com.cloud.vm;
|
package com.cloud.vm;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class VmWorkReconfigure extends VmWork {
|
public class VmWorkReconfigure extends VmWork {
|
||||||
private static final long serialVersionUID = -4517030323758086615L;
|
private static final long serialVersionUID = -4517030323758086615L;
|
||||||
|
|
||||||
|
Long oldServiceOfferingId;
|
||||||
Long newServiceOfferingId;
|
Long newServiceOfferingId;
|
||||||
|
|
||||||
|
Map<String, String> customParameters;
|
||||||
boolean sameHost;
|
boolean sameHost;
|
||||||
|
|
||||||
public VmWorkReconfigure(long userId, long accountId, long vmId, String handlerName,
|
public VmWorkReconfigure(long userId, long accountId, long vmId, String handlerName, Long oldServiceOfferingId,
|
||||||
Long newServiceOfferingId, boolean sameHost) {
|
Long newServiceOfferingId, Map<String, String> customParameters, boolean sameHost) {
|
||||||
|
|
||||||
super(userId, accountId, vmId, handlerName);
|
super(userId, accountId, vmId, handlerName);
|
||||||
|
|
||||||
|
this.oldServiceOfferingId = oldServiceOfferingId;
|
||||||
this.newServiceOfferingId = newServiceOfferingId;
|
this.newServiceOfferingId = newServiceOfferingId;
|
||||||
|
this.customParameters = customParameters;
|
||||||
this.sameHost = sameHost;
|
this.sameHost = sameHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getOldServiceOfferingId() {
|
||||||
|
return oldServiceOfferingId;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getNewServiceOfferingId() {
|
public Long getNewServiceOfferingId() {
|
||||||
return newServiceOfferingId;
|
return newServiceOfferingId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getCustomParameters() {
|
||||||
|
return customParameters;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSameHost() {
|
public boolean isSameHost() {
|
||||||
return sameHost;
|
return sameHost;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4086,15 +4086,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||||||
}
|
}
|
||||||
_itMgr.checkIfCanUpgrade(systemVm, newServiceOffering);
|
_itMgr.checkIfCanUpgrade(systemVm, newServiceOffering);
|
||||||
|
|
||||||
final boolean result = _itMgr.upgradeVmDb(systemVmId, serviceOfferingId);
|
final boolean result = _itMgr.upgradeVmDb(systemVmId, newServiceOffering, currentServiceOffering);
|
||||||
|
|
||||||
if (newServiceOffering.isDynamic()) {
|
|
||||||
//save the custom values to the database.
|
|
||||||
_userVmMgr.saveCustomOfferingDetails(systemVmId, newServiceOffering);
|
|
||||||
}
|
|
||||||
if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
|
|
||||||
_userVmMgr.removeCustomOfferingDetails(systemVmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
return _vmInstanceDao.findById(systemVmId);
|
return _vmInstanceDao.findById(systemVmId);
|
||||||
|
|||||||
@ -32,7 +32,6 @@ import com.cloud.exception.InsufficientCapacityException;
|
|||||||
import com.cloud.exception.ManagementServerException;
|
import com.cloud.exception.ManagementServerException;
|
||||||
import com.cloud.exception.ResourceUnavailableException;
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.exception.VirtualMachineMigrationException;
|
import com.cloud.exception.VirtualMachineMigrationException;
|
||||||
import com.cloud.offering.ServiceOffering;
|
|
||||||
import com.cloud.service.ServiceOfferingVO;
|
import com.cloud.service.ServiceOfferingVO;
|
||||||
import com.cloud.storage.Storage.StoragePoolType;
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
import com.cloud.user.Account;
|
import com.cloud.user.Account;
|
||||||
@ -117,10 +116,6 @@ public interface UserVmManager extends UserVmService {
|
|||||||
//find a common place for all the scaling and upgrading code of both user and systemvms.
|
//find a common place for all the scaling and upgrading code of both user and systemvms.
|
||||||
void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<String, String> customParameters);
|
void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<String, String> customParameters);
|
||||||
|
|
||||||
public void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering);
|
|
||||||
|
|
||||||
public void removeCustomOfferingDetails(long vmId);
|
|
||||||
|
|
||||||
void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType);
|
void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType);
|
||||||
|
|
||||||
void persistDeviceBusInfo(UserVmVO paramUserVmVO, String paramString);
|
void persistDeviceBusInfo(UserVmVO paramUserVmVO, String paramString);
|
||||||
|
|||||||
@ -1007,14 +1007,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
// Check that the specified service offering ID is valid
|
// Check that the specified service offering ID is valid
|
||||||
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
|
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
|
||||||
|
|
||||||
_itMgr.upgradeVmDb(vmId, svcOffId);
|
_itMgr.upgradeVmDb(vmId, newServiceOffering, currentServiceOffering);
|
||||||
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.
|
// Increment or decrement CPU and Memory count accordingly.
|
||||||
if (newCpu > currentCpu) {
|
if (newCpu > currentCpu) {
|
||||||
@ -1132,14 +1125,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
ServiceOffering newSvcOffering = _offeringDao.findById(svcOffId);
|
ServiceOffering newSvcOffering = _offeringDao.findById(svcOffId);
|
||||||
_accountMgr.checkAccess(owner, newSvcOffering, _dcDao.findById(vmInstance.getDataCenterId()));
|
_accountMgr.checkAccess(owner, newSvcOffering, _dcDao.findById(vmInstance.getDataCenterId()));
|
||||||
|
|
||||||
_itMgr.upgradeVmDb(vmId, svcOffId);
|
_itMgr.upgradeVmDb(vmId, newServiceOffering, currentServiceOffering);
|
||||||
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.
|
// Increment or decrement CPU and Memory count accordingly.
|
||||||
if (newCpu > currentCpu) {
|
if (newCpu > currentCpu) {
|
||||||
@ -1659,10 +1645,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
// Generate usage event for VM upgrade
|
// Generate usage event for VM upgrade
|
||||||
generateUsageEvent(vmInstance, vmInstance.isDisplayVm(), EventTypes.EVENT_VM_UPGRADE);
|
generateUsageEvent(vmInstance, vmInstance.isDisplayVm(), EventTypes.EVENT_VM_UPGRADE);
|
||||||
}
|
}
|
||||||
if (vmInstance.getState().equals(State.Running)) {
|
|
||||||
// Generate usage event for Dynamic scaling of VM
|
|
||||||
generateUsageEvent( vmInstance, vmInstance.isDisplayVm(), EventTypes.EVENT_VM_DYNAMIC_SCALE);
|
|
||||||
}
|
|
||||||
return vmInstance;
|
return vmInstance;
|
||||||
} else {
|
} else {
|
||||||
throw new CloudRuntimeException("Failed to scale the VM");
|
throw new CloudRuntimeException("Failed to scale the VM");
|
||||||
@ -1835,17 +1817,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #3 scale the vm now
|
// #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);
|
vmInstance = _vmInstanceDao.findById(vmId);
|
||||||
_itMgr.reConfigureVm(vmInstance.getUuid(), currentServiceOffering, existingHostHasCapacity);
|
_itMgr.reConfigureVm(vmInstance.getUuid(), currentServiceOffering, newServiceOffering, customParameters, existingHostHasCapacity);
|
||||||
success = true;
|
success = true;
|
||||||
if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
|
|
||||||
removeCustomOfferingDetails(vmId);
|
|
||||||
}
|
|
||||||
return success;
|
return success;
|
||||||
} catch (InsufficientCapacityException e) {
|
} catch (InsufficientCapacityException e) {
|
||||||
s_logger.warn("Received exception while scaling ", e);
|
s_logger.warn("Received exception while scaling ", e);
|
||||||
@ -1857,16 +1831,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
s_logger.warn("Received exception while scaling ", e);
|
s_logger.warn("Received exception while scaling ", e);
|
||||||
} finally {
|
} finally {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
_itMgr.upgradeVmDb(vmId, currentServiceOffering.getId()); // rollback
|
|
||||||
|
|
||||||
// Decrement CPU and Memory count accordingly.
|
// Decrement CPU and Memory count accordingly.
|
||||||
if (newCpu > currentCpu) {
|
if (newCpu > currentCpu) {
|
||||||
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu));
|
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu));
|
||||||
}
|
}
|
||||||
//restoring old service offering will take care of removing new SO.
|
|
||||||
if(currentServiceOffering.isDynamic()){
|
|
||||||
saveCustomOfferingDetails(vmId, currentServiceOffering);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memoryDiff > 0) {
|
if (memoryDiff > 0) {
|
||||||
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long(memoryDiff));
|
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long(memoryDiff));
|
||||||
@ -1878,35 +1846,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
return success;
|
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 (Map.Entry<String, String> entry: details.entrySet()) {
|
|
||||||
UserVmDetailVO detailVO = new UserVmDetailVO(vmId, entry.getKey(), entry.getValue(), true);
|
|
||||||
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(Map.Entry<String, String> entry: details.entrySet()) {
|
|
||||||
UserVmDetailVO detailVO = new UserVmDetailVO(vmId, entry.getKey(), entry.getValue(), true);
|
|
||||||
detailList.add(detailVO);
|
|
||||||
}
|
|
||||||
userVmDetailsDao.saveDetails(detailList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException {
|
public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException {
|
||||||
HashMap<Long, VmStatsEntry> vmStatsById = new HashMap<Long, VmStatsEntry>();
|
HashMap<Long, VmStatsEntry> vmStatsById = new HashMap<Long, VmStatsEntry>();
|
||||||
|
|||||||
@ -572,7 +572,7 @@ public class UserVmManagerTest {
|
|||||||
doReturn(VirtualMachine.State.Stopped).when(_vmInstance).getState();
|
doReturn(VirtualMachine.State.Stopped).when(_vmInstance).getState();
|
||||||
when(_vmDao.findById(anyLong())).thenReturn(null);
|
when(_vmDao.findById(anyLong())).thenReturn(null);
|
||||||
|
|
||||||
doReturn(true).when(_itMgr).upgradeVmDb(anyLong(), anyLong());
|
doReturn(true).when(_itMgr).upgradeVmDb(anyLong(), so1, so2);
|
||||||
|
|
||||||
//when(_vmDao.findById(anyLong())).thenReturn(_vmMock);
|
//when(_vmDao.findById(anyLong())).thenReturn(_vmMock);
|
||||||
|
|
||||||
@ -619,9 +619,9 @@ public class UserVmManagerTest {
|
|||||||
|
|
||||||
//when(ApiDBUtils.getCpuOverprovisioningFactor()).thenReturn(3f);
|
//when(ApiDBUtils.getCpuOverprovisioningFactor()).thenReturn(3f);
|
||||||
when(_capacityMgr.checkIfHostHasCapacity(anyLong(), anyInt(), anyLong(), anyBoolean(), anyFloat(), anyFloat(), anyBoolean())).thenReturn(false);
|
when(_capacityMgr.checkIfHostHasCapacity(anyLong(), anyInt(), anyLong(), anyBoolean(), anyFloat(), anyFloat(), anyBoolean())).thenReturn(false);
|
||||||
when(_itMgr.reConfigureVm(_vmInstance.getUuid(), so1, false)).thenReturn(_vmInstance);
|
when(_itMgr.reConfigureVm(_vmInstance.getUuid(), so2, so1, new HashMap<String, String>(), false)).thenReturn(_vmInstance);
|
||||||
|
|
||||||
doReturn(true).when(_itMgr).upgradeVmDb(anyLong(), anyLong());
|
doReturn(true).when(_itMgr).upgradeVmDb(anyLong(), so1, so2);
|
||||||
|
|
||||||
when(_vmDao.findById(anyLong())).thenReturn(_vmMock);
|
when(_vmDao.findById(anyLong())).thenReturn(_vmMock);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user