mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
bug 12787: improve worker VM cleanup in snapshot operation
This commit is contained in:
parent
9b706697fb
commit
bde008ed7e
@ -13,5 +13,5 @@ public interface VmwareHostService {
|
|||||||
void invalidateServiceContext(VmwareContext context);
|
void invalidateServiceContext(VmwareContext context);
|
||||||
VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd);
|
VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd);
|
||||||
|
|
||||||
String getWorkerName(VmwareContext context, Command cmd);
|
String getWorkerName(VmwareContext context, Command cmd, int workerSequence);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -174,7 +174,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
if(vmMo == null) {
|
if(vmMo == null) {
|
||||||
dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||||
|
|
||||||
workerVMName = hostService.getWorkerName(context, cmd);
|
workerVMName = hostService.getWorkerName(context, cmd, 0);
|
||||||
|
|
||||||
// attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
|
// attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
|
||||||
if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier._otherGuest.toString(), morDs, false)) {
|
if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier._otherGuest.toString(), morDs, false)) {
|
||||||
@ -203,7 +203,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, accountId, volumeId, cmd.getVolumePath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid,
|
snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, accountId, volumeId, cmd.getVolumePath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid,
|
||||||
UUID.randomUUID().toString().replace("-", ""));
|
hostService.getWorkerName(context, cmd, 1));
|
||||||
|
|
||||||
success = (snapshotBackupUuid != null);
|
success = (snapshotBackupUuid != null);
|
||||||
if (success) {
|
if (success) {
|
||||||
@ -238,8 +238,6 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
return new BackupSnapshotAnswer(cmd, success, details, snapshotBackupUuid, true);
|
return new BackupSnapshotAnswer(cmd, success, details, snapshotBackupUuid, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd) {
|
public Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd) {
|
||||||
String secondaryStoragePoolURL = cmd.getSecondaryStorageUrl();
|
String secondaryStoragePoolURL = cmd.getSecondaryStorageUrl();
|
||||||
@ -268,7 +266,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo,
|
Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo,
|
||||||
accountId, templateId, cmd.getTemplateName(),
|
accountId, templateId, cmd.getTemplateName(),
|
||||||
secondaryStoragePoolURL, volumePath,
|
secondaryStoragePoolURL, volumePath,
|
||||||
hostService.getWorkerName(context, cmd));
|
hostService.getWorkerName(context, cmd, 0));
|
||||||
|
|
||||||
return new CreatePrivateTemplateAnswer(cmd, true, null,
|
return new CreatePrivateTemplateAnswer(cmd, true, null,
|
||||||
result.first(), result.third(), result.second(),
|
result.first(), result.third(), result.second(),
|
||||||
@ -331,10 +329,10 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
|
|
||||||
Pair<String, String> result;
|
Pair<String, String> result;
|
||||||
if (cmd.toSecondaryStorage()) {
|
if (cmd.toSecondaryStorage()) {
|
||||||
result = copyVolumeToSecStorage(
|
result = copyVolumeToSecStorage(hostService,
|
||||||
hyperHost, vmName, volumeId, cmd.getPool().getUuid(), volumePath,
|
hyperHost, cmd, vmName, volumeId, cmd.getPool().getUuid(), volumePath,
|
||||||
secondaryStorageURL,
|
secondaryStorageURL,
|
||||||
hostService.getWorkerName(context, cmd));
|
hostService.getWorkerName(context, cmd, 0));
|
||||||
} else {
|
} else {
|
||||||
StorageFilerTO poolTO = cmd.getPool();
|
StorageFilerTO poolTO = cmd.getPool();
|
||||||
|
|
||||||
@ -393,8 +391,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
|
|
||||||
DatastoreMO primaryDsMo = new DatastoreMO(hyperHost.getContext(), morPrimaryDs);
|
DatastoreMO primaryDsMo = new DatastoreMO(hyperHost.getContext(), morPrimaryDs);
|
||||||
details = createVolumeFromSnapshot(hyperHost, primaryDsMo,
|
details = createVolumeFromSnapshot(hyperHost, primaryDsMo,
|
||||||
newVolumeName, accountId, volumeId,
|
newVolumeName, accountId, volumeId, secondaryStorageUrl, backedUpSnapshotUuid);
|
||||||
secondaryStorageUrl, backedUpSnapshotUuid);
|
|
||||||
if (details == null) {
|
if (details == null) {
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
@ -738,8 +735,10 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
return "Failed to delete snapshot backup file, backupUuid: " + backupUuid;
|
return "Failed to delete snapshot backup file, backupUuid: " + backupUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<String, String> copyVolumeToSecStorage(VmwareHypervisorHost hyperHost, String vmName, long volumeId, String poolId, String volumePath,
|
private Pair<String, String> copyVolumeToSecStorage(VmwareHostService hostService, VmwareHypervisorHost hyperHost, CopyVolumeCommand cmd,
|
||||||
String secStorageUrl, String workerVmName) throws Exception {
|
String vmName, long volumeId, String poolId, String volumePath,
|
||||||
|
String secStorageUrl, String workerVmName) throws Exception {
|
||||||
|
|
||||||
String volumeFolder = String.valueOf(volumeId) + "/";
|
String volumeFolder = String.valueOf(volumeId) + "/";
|
||||||
VirtualMachineMO workerVm=null;
|
VirtualMachineMO workerVm=null;
|
||||||
VirtualMachineMO vmMo=null;
|
VirtualMachineMO vmMo=null;
|
||||||
@ -756,12 +755,11 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
|
|
||||||
vmMo = hyperHost.findVmOnHyperHost(vmName);
|
vmMo = hyperHost.findVmOnHyperHost(vmName);
|
||||||
if (vmMo == null) {
|
if (vmMo == null) {
|
||||||
//create a dummy worker vm for attaching the volume
|
// create a dummy worker vm for attaching the volume
|
||||||
DatastoreMO dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
DatastoreMO dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||||
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
|
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
|
||||||
String workerVMName = UUID.randomUUID().toString().replaceAll("-", "");
|
|
||||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||||
vmConfig.setName(workerVMName);
|
vmConfig.setName(workerVmName);
|
||||||
vmConfig.setMemoryMB((long) 4);
|
vmConfig.setMemoryMB((long) 4);
|
||||||
vmConfig.setNumCPUs(1);
|
vmConfig.setNumCPUs(1);
|
||||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier._otherGuest.toString());
|
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier._otherGuest.toString());
|
||||||
@ -780,7 +778,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
vmConfig.setDeviceChange(new VirtualDeviceConfigSpec[] { scsiControllerSpec });
|
vmConfig.setDeviceChange(new VirtualDeviceConfigSpec[] { scsiControllerSpec });
|
||||||
|
|
||||||
hyperHost.createVm(vmConfig);
|
hyperHost.createVm(vmConfig);
|
||||||
workerVm = hyperHost.findVmOnHyperHost(workerVMName);
|
workerVm = hyperHost.findVmOnHyperHost(workerVmName);
|
||||||
if (workerVm == null) {
|
if (workerVm == null) {
|
||||||
String msg = "Unable to create worker VM to execute CopyVolumeCommand";
|
String msg = "Unable to create worker VM to execute CopyVolumeCommand";
|
||||||
s_logger.error(msg);
|
s_logger.error(msg);
|
||||||
@ -795,7 +793,8 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
|
|
||||||
vmMo.createSnapshot(exportName, "Temporary snapshot for copy-volume command", false, false);
|
vmMo.createSnapshot(exportName, "Temporary snapshot for copy-volume command", false, false);
|
||||||
|
|
||||||
exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, "volumes/" + volumeFolder, exportName, workerVmName);
|
exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, "volumes/" + volumeFolder, exportName,
|
||||||
|
hostService.getWorkerName(hyperHost.getContext(), cmd, 1));
|
||||||
return new Pair<String, String>(volumeFolder, exportName);
|
return new Pair<String, String>(volumeFolder, exportName);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -2885,7 +2885,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
if (cmd.getDiskCharacteristics().getType() == Volume.Type.ROOT) {
|
if (cmd.getDiskCharacteristics().getType() == Volume.Type.ROOT) {
|
||||||
if (cmd.getTemplateUrl() == null) {
|
if (cmd.getTemplateUrl() == null) {
|
||||||
// create a root volume for blank VM
|
// create a root volume for blank VM
|
||||||
String dummyVmName = getWorkerName(context, cmd);
|
String dummyVmName = getWorkerName(context, cmd, 0);
|
||||||
VirtualMachineMO vmMo = null;
|
VirtualMachineMO vmMo = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -2969,7 +2969,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
VirtualMachineMO vmMo = null;
|
VirtualMachineMO vmMo = null;
|
||||||
String volumeUuid = UUID.randomUUID().toString().replace("-", "");
|
String volumeUuid = UUID.randomUUID().toString().replace("-", "");
|
||||||
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
|
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
|
||||||
String dummyVmName = getWorkerName(context, cmd);
|
String dummyVmName = getWorkerName(context, cmd, 0);
|
||||||
try {
|
try {
|
||||||
vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
|
vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
|
||||||
if (vmMo == null) {
|
if (vmMo == null) {
|
||||||
@ -3968,7 +3968,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@DB
|
@DB
|
||||||
public String getWorkerName(VmwareContext context, Command cmd) {
|
public String getWorkerName(VmwareContext context, Command cmd, int workerSequence) {
|
||||||
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
|
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
|
||||||
String vmName = mgr.composeWorkerName();
|
String vmName = mgr.composeWorkerName();
|
||||||
|
|
||||||
|
|||||||
@ -66,12 +66,18 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
|
|||||||
answer = _resource.defaultAction(cmd);
|
answer = _resource.defaultAction(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special handling to pass-back context info for cleanups
|
||||||
if(cmd.getContextParam("execid") != null) {
|
if(cmd.getContextParam("execid") != null) {
|
||||||
answer.setContextParam("execid", cmd.getContextParam("execid"));
|
answer.setContextParam("execid", cmd.getContextParam("execid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cmd.getContextParam("checkpoint") != null) {
|
if(cmd.getContextParam("checkpoint") != null) {
|
||||||
answer.setContextParam("checkpoint", cmd.getContextParam("checkpoint"));
|
answer.setContextParam("checkpoint", cmd.getContextParam("checkpoint"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(cmd.getContextParam("checkpoint2") != null) {
|
||||||
|
answer.setContextParam("checkpoint2", cmd.getContextParam("checkpoint2"));
|
||||||
|
}
|
||||||
|
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
@ -219,9 +225,13 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getWorkerName(VmwareContext context, Command cmd) {
|
public String getWorkerName(VmwareContext context, Command cmd, int workerSequence) {
|
||||||
assert(cmd.getContextParam("worker") != null);
|
assert(cmd.getContextParam("worker") != null);
|
||||||
return cmd.getContextParam("worker");
|
assert(workerSequence < 2);
|
||||||
|
|
||||||
|
if(workerSequence == 0)
|
||||||
|
return cmd.getContextParam("worker");
|
||||||
|
return cmd.getContextParam("worker2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -266,6 +266,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
|
|||||||
long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName));
|
long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName));
|
||||||
cmd.setContextParam("worker", workerName);
|
cmd.setContextParam("worker", workerName);
|
||||||
cmd.setContextParam("checkpoint", String.valueOf(checkPointId));
|
cmd.setContextParam("checkpoint", String.valueOf(checkPointId));
|
||||||
|
|
||||||
|
// some commands use 2 workers
|
||||||
|
String workerName2 = _vmwareMgr.composeWorkerName();
|
||||||
|
long checkPointId2 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2));
|
||||||
|
cmd.setContextParam("worker2", workerName2);
|
||||||
|
cmd.setContextParam("checkpoint2", String.valueOf(checkPointId2));
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmdTarget.first().getId();
|
return cmdTarget.first().getId();
|
||||||
|
|||||||
@ -749,6 +749,11 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis
|
|||||||
if(checkPointIdStr != null) {
|
if(checkPointIdStr != null) {
|
||||||
_checkPointMgr.popCheckPoint(Long.parseLong(checkPointIdStr));
|
_checkPointMgr.popCheckPoint(Long.parseLong(checkPointIdStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkPointIdStr = answer.getContextParam("checkpoint2");
|
||||||
|
if(checkPointIdStr != null) {
|
||||||
|
_checkPointMgr.popCheckPoint(Long.parseLong(checkPointIdStr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1411,19 +1411,32 @@ public class VirtualMachineMO extends BaseMO {
|
|||||||
HostMO hostMo = getRunningHost();
|
HostMO hostMo = getRunningHost();
|
||||||
VirtualMachineConfigInfo vmConfigInfo = getConfigInfo();
|
VirtualMachineConfigInfo vmConfigInfo = getConfigInfo();
|
||||||
|
|
||||||
hostMo.createBlankVm(clonedVmName, 1, cpuSpeedMHz, 0, false, memoryMb, 0, vmConfigInfo.getGuestId(), morDs, false);
|
if(!hostMo.createBlankVm(clonedVmName, 1, cpuSpeedMHz, 0, false, memoryMb, 0, vmConfigInfo.getGuestId(), morDs, false))
|
||||||
VirtualMachineMO clonedVmMo = hostMo.findVmOnHyperHost(clonedVmName);
|
throw new Exception("Unable to create a blank VM");
|
||||||
|
|
||||||
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
|
VirtualMachineMO clonedVmMo = hostMo.findVmOnHyperHost(clonedVmName);
|
||||||
VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
|
if(clonedVmMo == null)
|
||||||
deviceConfigSpecArray[0] = new VirtualDeviceConfigSpec();
|
throw new Exception("Unable to find just-created blank VM");
|
||||||
|
|
||||||
VirtualDevice device = VmwareHelper.prepareDiskDevice(clonedVmMo, -1, disks, morDs, -1, 1);
|
boolean bSuccess = false;
|
||||||
|
try {
|
||||||
deviceConfigSpecArray[0].setDevice(device);
|
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
|
||||||
deviceConfigSpecArray[0].setOperation(VirtualDeviceConfigSpecOperation.add);
|
VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
|
||||||
vmConfigSpec.setDeviceChange(deviceConfigSpecArray);
|
deviceConfigSpecArray[0] = new VirtualDeviceConfigSpec();
|
||||||
clonedVmMo.configureVm(vmConfigSpec);
|
|
||||||
|
VirtualDevice device = VmwareHelper.prepareDiskDevice(clonedVmMo, -1, disks, morDs, -1, 1);
|
||||||
|
|
||||||
|
deviceConfigSpecArray[0].setDevice(device);
|
||||||
|
deviceConfigSpecArray[0].setOperation(VirtualDeviceConfigSpecOperation.add);
|
||||||
|
vmConfigSpec.setDeviceChange(deviceConfigSpecArray);
|
||||||
|
clonedVmMo.configureVm(vmConfigSpec);
|
||||||
|
bSuccess = true;
|
||||||
|
} finally {
|
||||||
|
if(!bSuccess) {
|
||||||
|
clonedVmMo.detachAllDisks();
|
||||||
|
clonedVmMo.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void plugDevice(VirtualDevice device) throws Exception {
|
public void plugDevice(VirtualDevice device) throws Exception {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user