CLOUDSTACK-4519: reimplementdestroy-volume to take consideration of on-disk snapshot

This commit is contained in:
Kelven Yang 2013-08-28 17:50:44 -07:00
parent a4762b0904
commit ea13e089b8
4 changed files with 106 additions and 34 deletions

View File

@ -416,14 +416,6 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
return tokens[0] + "@" + vCenterIp;
}
@Override
public List<Command> finalizeExpunge(VirtualMachine vm) {
UnregisterVMCommand unregisterVMCommand = new UnregisterVMCommand(vm.getInstanceName());
List<Command> commands = new ArrayList<Command>();
commands.add(unregisterVMCommand);
return commands;
}
@Override
public List<Command> finalizeExpungeNics(VirtualMachine vm, List<NicProfile> nics) {
List<Command> commands = new ArrayList<Command>();

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.storage.resource;
import java.util.List;
import org.apache.log4j.Logger;
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
@ -166,6 +168,40 @@ public class VmwareStorageLayoutHelper {
s_logger.info("Fixup folder-synchronization. move " + fileDsFullPath + " -> " + targetPath);
ds.moveDatastoreFile(fileDsFullPath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true);
}
public static void moveVolumeToRootFolder(DatacenterMO dcMo, List<String> detachedDisks) throws Exception {
if(detachedDisks.size() > 0) {
for(String fileFullDsPath : detachedDisks) {
DatastoreFile file = new DatastoreFile(fileFullDsPath);
s_logger.info("Check if we need to move " + fileFullDsPath + " to its root location");
DatastoreMO dsMo = new DatastoreMO(dcMo.getContext(), dcMo.findDatastore(file.getDatastoreName()));
if(dsMo.getMor() != null) {
DatastoreFile targetFile = new DatastoreFile(file.getDatastoreName(), file.getFileName());
if(!targetFile.getPath().equalsIgnoreCase(file.getPath())) {
s_logger.info("Move " + file.getPath() + " -> " + targetFile.getPath());
dsMo.moveDatastoreFile(file.getPath(), dcMo.getMor(), dsMo.getMor(), targetFile.getPath(), dcMo.getMor(), true);
String pairSrcFilePath = file.getCompanionPath(file.getFileBaseName() + "-flat.vmdk");
String pairTargetFilePath = targetFile.getCompanionPath(file.getFileBaseName() + "-flat.vmdk");
if(dsMo.fileExists(pairSrcFilePath)) {
s_logger.info("Move " + pairSrcFilePath + " -> " + pairTargetFilePath);
dsMo.moveDatastoreFile(pairSrcFilePath, dcMo.getMor(), dsMo.getMor(), pairTargetFilePath, dcMo.getMor(), true);
}
pairSrcFilePath = file.getCompanionPath(file.getFileBaseName() + "-delta.vmdk");
pairTargetFilePath = targetFile.getCompanionPath(file.getFileBaseName() + "-delta.vmdk");
if(dsMo.fileExists(pairSrcFilePath)) {
s_logger.info("Move " + pairSrcFilePath + " -> " + pairTargetFilePath);
dsMo.moveDatastoreFile(pairSrcFilePath, dcMo.getMor(), dsMo.getMor(), pairTargetFilePath, dcMo.getMor(), true);
}
}
} else {
s_logger.warn("Datastore for " + fileFullDsPath + " no longer exists, we have to skip");
}
}
}
}
public static String getTemplateOnSecStorageFilePath(String secStorageMountPoint, String templateRelativeFolderPath,
String templateName, String fileExtension) {
@ -227,7 +263,7 @@ public class VmwareStorageLayoutHelper {
if(!dsMo.fileExists(fileFullPath))
fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
if(fileFullPath != null) {
dsMo.deleteFile(fileFullPath, dcMo.getMor(), false);
dsMo.deleteFile(fileFullPath, dcMo.getMor(), true);
} else {
s_logger.warn("Unable to locate VMDK file: " + fileName);
}
@ -237,7 +273,7 @@ public class VmwareStorageLayoutHelper {
if(!dsMo.fileExists(fileFullPath))
fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
if(fileFullPath != null) {
dsMo.deleteFile(fileFullPath, dcMo.getMor(), false);
dsMo.deleteFile(fileFullPath, dcMo.getMor(), true);
} else {
s_logger.warn("Unable to locate VMDK file: " + fileName);
}
@ -247,7 +283,7 @@ public class VmwareStorageLayoutHelper {
if(!dsMo.fileExists(fileFullPath))
fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
if(fileFullPath != null) {
dsMo.deleteFile(fileFullPath, dcMo.getMor(), false);
dsMo.deleteFile(fileFullPath, dcMo.getMor(), true);
} else {
s_logger.warn("Unable to locate VMDK file: " + fileName);
}

View File

@ -71,6 +71,7 @@ import com.cloud.hypervisor.vmware.mo.DatastoreMO;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
import com.cloud.hypervisor.vmware.mo.NetworkDetails;
import com.cloud.hypervisor.vmware.mo.VirtualMachineDiskInfo;
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
import com.cloud.hypervisor.vmware.resource.VmwareResource;
@ -1308,7 +1309,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
} else {
try{
vmMo.unmountToolsInstaller();
}catch(Throwable e){
} catch(Throwable e){
vmMo.detachIso(null);
}
}
@ -1447,18 +1448,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
}
/*
* DestroyCommand content example
*
* {"volume": {"id":5,"name":"Volume1", "mountPoint":"/export/home/kelven/vmware-test/primary",
* "path":"6bb8762f-c34c-453c-8e03-26cc246ceec4", "size":0,"type":"DATADISK","resourceType":
* "STORAGE_POOL","storagePoolType":"NetworkFilesystem", "poolId":0,"deviceId":0 } }
*
* {"volume": {"id":1, "name":"i-2-1-KY-ROOT", "mountPoint":"/export/home/kelven/vmware-test/primary",
* "path":"i-2-1-KY-ROOT","size":0,"type":"ROOT", "resourceType":"STORAGE_POOL", "storagePoolType":"NetworkFilesystem",
* "poolId":0,"deviceId":0 } }
*/
try {
VmwareContext context = hostService.getServiceContext(null);
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
@ -1479,6 +1468,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
ClusterMO clusterMo = new ClusterMO(context, morCluster);
if (vol.getVolumeType() == Volume.Type.ROOT) {
String vmName = vol.getVmName();
if (vmName != null) {
VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vmName);
@ -1487,6 +1477,14 @@ public class VmwareStorageProcessor implements StorageProcessor {
s_logger.info("Destroy root volume and VM itself. vmName " + vmName);
}
// Remove all snapshots to consolidate disks for removal
vmMo.removeAllSnapshots();
VirtualMachineDiskInfo diskInfo = null;
if(vol.getChainInfo() != null)
diskInfo = _gson.fromJson(vol.getChainInfo(), VirtualMachineDiskInfo.class);
HostMO hostMo = vmMo.getRunningHost();
List<NetworkDetails> networks = vmMo.getNetworksWithDetails();
@ -1494,7 +1492,12 @@ public class VmwareStorageProcessor implements StorageProcessor {
if (this.resource.getVmState(vmMo) != State.Stopped) {
vmMo.safePowerOff(_shutdown_waitMs);
}
vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
List<String> detachedDisks = vmMo.detachAllDisksExcept(vol.getPath(), diskInfo != null ? diskInfo.getDiskDeviceBusName() : null);
VmwareStorageLayoutHelper.moveVolumeToRootFolder(new DatacenterMO(context, morDc), detachedDisks);
// let vmMo.destroy to delete volume for us
// vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
vmMo.destroy();
for (NetworkDetails netDetails : networks) {
@ -1506,10 +1509,13 @@ public class VmwareStorageProcessor implements StorageProcessor {
}
}
if (s_logger.isInfoEnabled())
/*
if (s_logger.isInfoEnabled()) {
s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc));
}
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc));
*/
return new Answer(cmd, true, "Success");
}

View File

@ -991,13 +991,11 @@ public class VirtualMachineMO extends BaseMO {
VirtualDevice newDisk = VmwareHelper.prepareDiskDevice(this, getScsiDeviceControllerKey(),
vmdkDatastorePathChain, morDs, -1, 1);
VirtualMachineConfigSpec reConfigSpec = new VirtualMachineConfigSpec();
//VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
deviceConfigSpec.setDevice(newDisk);
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
//deviceConfigSpecArray[0] = deviceConfigSpec;
reConfigSpec.getDeviceChange().add(deviceConfigSpec);
ManagedObjectReference morTask = _context.getService().reconfigVMTask(_mor, reConfigSpec);
@ -1024,13 +1022,11 @@ public class VirtualMachineMO extends BaseMO {
VirtualDevice newDisk = VmwareHelper.prepareDiskDevice(this, controllerKey,
vmdkDatastorePathChain, -1, 1);
VirtualMachineConfigSpec reConfigSpec = new VirtualMachineConfigSpec();
//VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
deviceConfigSpec.setDevice(newDisk);
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
//deviceConfigSpecArray[0] = deviceConfigSpec;
reConfigSpec.getDeviceChange().add(deviceConfigSpec);
ManagedObjectReference morTask = _context.getService().reconfigVMTask(_mor, reConfigSpec);
@ -1067,7 +1063,6 @@ public class VirtualMachineMO extends BaseMO {
List<Pair<String, ManagedObjectReference>> chain = getDiskDatastorePathChain(deviceInfo.first(), true);
VirtualMachineConfigSpec reConfigSpec = new VirtualMachineConfigSpec();
//VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
deviceConfigSpec.setDevice(deviceInfo.first());
@ -1076,7 +1071,6 @@ public class VirtualMachineMO extends BaseMO {
}
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE);
//deviceConfigSpecArray[0] = deviceConfigSpec;
reConfigSpec.getDeviceChange().add(deviceConfigSpec);
ManagedObjectReference morTask = _context.getService().reconfigVMTask(_mor, reConfigSpec);
@ -1964,6 +1958,50 @@ public class VirtualMachineMO extends BaseMO {
throw new Exception("Unable to find device controller");
}
public List<String> detachAllDisksExcept(String vmdkBaseName, String deviceBusName) throws Exception {
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
VirtualMachineConfigSpec reConfigSpec = new VirtualMachineConfigSpec();
List<String> detachedDiskFiles = new ArrayList<String>();
for(VirtualDevice device : devices) {
if(device instanceof VirtualDisk) {
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
VirtualDiskFlatVer2BackingInfo diskBackingInfo = (VirtualDiskFlatVer2BackingInfo)device.getBacking();
DatastoreFile dsBackingFile = new DatastoreFile(diskBackingInfo.getFileName());
String backingBaseName = dsBackingFile.getFileBaseName();
String deviceNumbering = getDeviceBusName(devices, device);
if(backingBaseName.equalsIgnoreCase(vmdkBaseName) || (deviceBusName != null && deviceBusName.equals(deviceNumbering))) {
continue;
} else {
s_logger.info("Detach " + diskBackingInfo.getFileName() + " from " + getName());
detachedDiskFiles.add(diskBackingInfo.getFileName());
deviceConfigSpec.setDevice(device);
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE);
reConfigSpec.getDeviceChange().add(deviceConfigSpec);
}
}
}
if(detachedDiskFiles.size() > 0) {
ManagedObjectReference morTask = _context.getService().reconfigVMTask(_mor, reConfigSpec);
boolean result = _context.getVimClient().waitForTask(morTask);
if(result) {
_context.waitForTaskProgressDone(morTask);
} else {
s_logger.warn("Unable to reconfigure the VM to detach disks");
throw new Exception("Unable to reconfigure the VM to detach disks");
}
}
return detachedDiskFiles;
}
public VirtualDisk[] getAllDiskDevice() throws Exception {
List<VirtualDisk> deviceList = new ArrayList<VirtualDisk>();
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");