CLOUDSTACK-4519: reimplementdestroy-volume to take consideration of on-disk 
snapshot
(cherry picked from commit a316ffa27f84c261cace31982aaaa9c3aaf52e6a)

Signed-off-by: animesh <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/2b12088e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2b12088e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2b12088e

Branch: refs/heads/4.2
Commit: 2b12088eabb683a6de9b411dce93a3d909923b38
Parents: 42e66aa
Author: Kelven Yang <[email protected]>
Authored: Wed Aug 28 17:50:44 2013 -0700
Committer: animesh <[email protected]>
Committed: Tue Sep 3 15:59:04 2013 -0700

----------------------------------------------------------------------
 .../com/cloud/hypervisor/guru/VMwareGuru.java   |  8 ----
 .../resource/VmwareStorageLayoutHelper.java     | 42 ++++++++++++++--
 .../resource/VmwareStorageProcessor.java        | 33 +++++++------
 .../hypervisor/vmware/mo/VirtualMachineMO.java  | 50 +++++++++++++++++---
 4 files changed, 102 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b12088e/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java 
b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
index 7c70c6a..c8e82ab 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -426,14 +426,6 @@ public class VMwareGuru extends HypervisorGuruBase 
implements HypervisorGuru {
     }
 
     @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>();
         List<NicVO> nicVOs = _nicDao.listByVmId(vm.getId());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b12088e/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java
 
b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java
index d60abad..20544df 100644
--- 
a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java
+++ 
b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java
@@ -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);
                }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b12088e/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
 
b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
index 4a0b192..20c26fb 100644
--- 
a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ 
b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -63,6 +63,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;
@@ -1323,7 +1324,7 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
                     } else {
                         try{
                             vmMo.unmountToolsInstaller();
-                        }catch(Throwable e){
+                        } catch(Throwable e){
                             vmMo.detachIso(null);
                         }
                     }
@@ -1462,18 +1463,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);
@@ -1494,6 +1483,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);
@@ -1502,6 +1492,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();
 
@@ -1509,7 +1507,12 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
                         if (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) {
@@ -1521,11 +1524,13 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
                         }
                     }
 
+/*                    
                     if (s_logger.isInfoEnabled()) {
                         s_logger.info("Destroy volume by original name: " + 
vol.getPath() + ".vmdk");
                     }
 
                     VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, 
vol.getPath(), new DatacenterMO(context, morDc));
+*/
                     return new Answer(cmd, true, "Success");
                 }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b12088e/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
----------------------------------------------------------------------
diff --git 
a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java 
b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
index 71ab609..7dd947c 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -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");

Reply via email to