Skip to content

Commit 939ee9e

Browse files
authored
server,engine-orchestration: allocate vm without transaction (#7695)
When deploying a VM is failed during the allocation process it may leave the resources that have been already allocated before the failure. They will get removed from the database as the whole code block is wrapped inside a transaction twice but the server would not inform the network or storage plugins to clean up the allocated resources. This PR removes Transactions during VM allocation which results in the allocated VM and its resource records being persisted in DB even during failures. When failure is encountered VM is moved to Error state. This helps VM and its resources to be properly deallocated when it is expunged either by a server task such as ExpungeTask or during manual expunge. Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent c733a23 commit 939ee9e

File tree

2 files changed

+185
-184
lines changed

2 files changed

+185
-184
lines changed

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 59 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -458,72 +458,79 @@ public void allocate(final String vmInstanceName, final VirtualMachineTemplate t
458458
throws InsufficientCapacityException {
459459

460460
s_logger.info(String.format("allocating virtual machine from template:%s with hostname:%s and %d networks", template.getUuid(), vmInstanceName, auxiliaryNetworks.size()));
461+
VMInstanceVO persistedVm = null;
462+
try {
463+
final VMInstanceVO vm = _vmDao.findVMByInstanceName(vmInstanceName);
464+
final Account owner = _entityMgr.findById(Account.class, vm.getAccountId());
461465

462-
final VMInstanceVO vm = _vmDao.findVMByInstanceName(vmInstanceName);
463-
final Account owner = _entityMgr.findById(Account.class, vm.getAccountId());
464-
465-
if (s_logger.isDebugEnabled()) {
466-
s_logger.debug("Allocating entries for VM: " + vm);
467-
}
466+
if (s_logger.isDebugEnabled()) {
467+
s_logger.debug("Allocating entries for VM: " + vm);
468+
}
468469

469-
vm.setDataCenterId(plan.getDataCenterId());
470-
if (plan.getPodId() != null) {
471-
vm.setPodIdToDeployIn(plan.getPodId());
472-
}
473-
assert plan.getClusterId() == null && plan.getPoolId() == null : "We currently don't support cluster and pool preset yet";
474-
final VMInstanceVO vmFinal = _vmDao.persist(vm);
470+
vm.setDataCenterId(plan.getDataCenterId());
471+
if (plan.getPodId() != null) {
472+
vm.setPodIdToDeployIn(plan.getPodId());
473+
}
474+
assert plan.getClusterId() == null && plan.getPoolId() == null : "We currently don't support cluster and pool preset yet";
475+
persistedVm = _vmDao.persist(vm);
475476

476-
final VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmFinal, template, serviceOffering, null, null);
477+
final VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(persistedVm, template, serviceOffering, null, null);
477478

478-
Long rootDiskSize = rootDiskOfferingInfo.getSize();
479-
if (vm.getType().isUsedBySystem() && SystemVmRootDiskSize.value() != null && SystemVmRootDiskSize.value() > 0L) {
480-
rootDiskSize = SystemVmRootDiskSize.value();
481-
}
482-
final Long rootDiskSizeFinal = rootDiskSize;
479+
Long rootDiskSize = rootDiskOfferingInfo.getSize();
480+
if (vm.getType().isUsedBySystem() && SystemVmRootDiskSize.value() != null && SystemVmRootDiskSize.value() > 0L) {
481+
rootDiskSize = SystemVmRootDiskSize.value();
482+
}
483+
final Long rootDiskSizeFinal = rootDiskSize;
483484

484-
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<InsufficientCapacityException>() {
485-
@Override
486-
public void doInTransactionWithoutResult(final TransactionStatus status) throws InsufficientCapacityException {
487-
if (s_logger.isDebugEnabled()) {
488-
s_logger.debug("Allocating nics for " + vmFinal);
489-
}
485+
if (s_logger.isDebugEnabled()) {
486+
s_logger.debug("Allocating nics for " + persistedVm);
487+
}
490488

491-
try {
492-
if (!vmProfile.getBootArgs().contains("ExternalLoadBalancerVm")) {
493-
_networkMgr.allocate(vmProfile, auxiliaryNetworks, extraDhcpOptions);
494-
}
495-
} catch (final ConcurrentOperationException e) {
496-
throw new CloudRuntimeException("Concurrent operation while trying to allocate resources for the VM", e);
489+
try {
490+
if (!vmProfile.getBootArgs().contains("ExternalLoadBalancerVm")) {
491+
_networkMgr.allocate(vmProfile, auxiliaryNetworks, extraDhcpOptions);
497492
}
493+
} catch (final ConcurrentOperationException e) {
494+
throw new CloudRuntimeException("Concurrent operation while trying to allocate resources for the VM", e);
495+
}
498496

499-
if (s_logger.isDebugEnabled()) {
500-
s_logger.debug("Allocating disks for " + vmFinal);
501-
}
497+
if (s_logger.isDebugEnabled()) {
498+
s_logger.debug("Allocating disks for " + persistedVm);
499+
}
502500

503-
allocateRootVolume(vmFinal, template, rootDiskOfferingInfo, owner, rootDiskSizeFinal);
501+
allocateRootVolume(persistedVm, template, rootDiskOfferingInfo, owner, rootDiskSizeFinal);
504502

505-
if (dataDiskOfferings != null) {
506-
for (final DiskOfferingInfo dataDiskOfferingInfo : dataDiskOfferings) {
507-
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vmFinal.getId(), dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(),
508-
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), vmFinal, template, owner, null);
509-
}
503+
if (dataDiskOfferings != null) {
504+
for (final DiskOfferingInfo dataDiskOfferingInfo : dataDiskOfferings) {
505+
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId(), dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(),
506+
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, null);
510507
}
511-
if (datadiskTemplateToDiskOfferingMap != null && !datadiskTemplateToDiskOfferingMap.isEmpty()) {
512-
int diskNumber = 1;
513-
for (Entry<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap : datadiskTemplateToDiskOfferingMap.entrySet()) {
514-
DiskOffering diskOffering = dataDiskTemplateToDiskOfferingMap.getValue();
515-
long diskOfferingSize = diskOffering.getDiskSize() / (1024 * 1024 * 1024);
516-
VMTemplateVO dataDiskTemplate = _templateDao.findById(dataDiskTemplateToDiskOfferingMap.getKey());
517-
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vmFinal.getId() + "-" + String.valueOf(diskNumber), diskOffering, diskOfferingSize, null, null,
518-
vmFinal, dataDiskTemplate, owner, Long.valueOf(diskNumber));
519-
diskNumber++;
520-
}
508+
}
509+
if (datadiskTemplateToDiskOfferingMap != null && !datadiskTemplateToDiskOfferingMap.isEmpty()) {
510+
int diskNumber = 1;
511+
for (Entry<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap : datadiskTemplateToDiskOfferingMap.entrySet()) {
512+
DiskOffering diskOffering = dataDiskTemplateToDiskOfferingMap.getValue();
513+
long diskOfferingSize = diskOffering.getDiskSize() / (1024 * 1024 * 1024);
514+
VMTemplateVO dataDiskTemplate = _templateDao.findById(dataDiskTemplateToDiskOfferingMap.getKey());
515+
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId() + "-" + String.valueOf(diskNumber), diskOffering, diskOfferingSize, null, null,
516+
persistedVm, dataDiskTemplate, owner, Long.valueOf(diskNumber));
517+
diskNumber++;
521518
}
522519
}
523-
});
524520

525-
if (s_logger.isDebugEnabled()) {
526-
s_logger.debug("Allocation completed for VM: " + vmFinal);
521+
if (s_logger.isDebugEnabled()) {
522+
s_logger.debug("Allocation completed for VM: " + persistedVm);
523+
}
524+
} catch (InsufficientCapacityException | CloudRuntimeException e) {
525+
// Failed VM will be in Stopped. Transition it to Error, so it can be expunged by ExpungeTask or similar
526+
try {
527+
if (persistedVm != null) {
528+
stateTransitTo(persistedVm, VirtualMachine.Event.OperationFailedToError, null);
529+
}
530+
} catch (NoTransitionException nte) {
531+
s_logger.error(String.format("Failed to transition %s in %s state to Error state", persistedVm, persistedVm.getState().toString()));
532+
}
533+
throw e;
527534
}
528535
}
529536

0 commit comments

Comments
 (0)