You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mt...@apache.org on 2014/01/10 07:20:27 UTC

git commit: updated refs/heads/master to a354d96

Updated Branches:
  refs/heads/master 929838c8e -> a354d969c


Merge from 4.3: CLOUDSTACK-5823: Taking a VMware snapshot doesn't work

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

Branch: refs/heads/master
Commit: a354d969ce316d065a4abf1405fce708955bdf0a
Parents: 929838c
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Thu Jan 9 23:10:40 2014 -0700
Committer: Mike Tutkowski <mi...@solidfire.com>
Committed: Thu Jan 9 23:10:40 2014 -0700

----------------------------------------------------------------------
 .../manager/VmwareStorageManagerImpl.java       | 220 ++++++++++++-------
 .../cloud/hypervisor/vmware/mo/ClusterMO.java   |   5 +
 .../com/cloud/hypervisor/vmware/mo/HostMO.java  |   6 +
 .../vmware/mo/VmwareHypervisorHost.java         |   2 +
 4 files changed, 154 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a354d969/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
index 0f18936..a7089ce 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
@@ -1184,9 +1184,10 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         return "snapshots/" + accountId + "/" + volumeId;
     }
 
-    private long getVMSnapshotChainSize(VmwareContext context, VmwareHypervisorHost hyperHost, String fileName, String poolUuid, String exceptFileName) throws Exception {
+    private long getVMSnapshotChainSize(VmwareContext context, VmwareHypervisorHost hyperHost,
+            String fileName, ManagedObjectReference morDs, String exceptFileName)
+                    throws Exception{
         long size = 0;
-        ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid);
         DatastoreMO dsMo = new DatastoreMO(context, morDs);
         HostDatastoreBrowserMO browserMo = dsMo.getHostDatastoreBrowserMO();
         String datastorePath = "[" + dsMo.getName() + "]";
@@ -1245,15 +1246,17 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         boolean quiescevm = cmd.getTarget().getQuiescevm();
         VirtualMachineMO vmMo = null;
         VmwareContext context = hostService.getServiceContext(cmd);
-        Map<String, String> mapNewDisk = new HashMap<String, String>();
+
         try {
             VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
 
             // wait if there are already VM snapshot task running
             ManagedObjectReference taskmgr = context.getServiceContent().getTaskManager();
             List<ManagedObjectReference> tasks = (ArrayList<ManagedObjectReference>)context.getVimClient().getDynamicProperty(taskmgr, "recentTask");
+
             for (ManagedObjectReference taskMor : tasks) {
                 TaskInfo info = (TaskInfo)(context.getVimClient().getDynamicProperty(taskMor, "info"));
+
                 if (info.getEntityName().equals(cmd.getVmName()) && info.getName().equalsIgnoreCase("CreateSnapshot_Task")) {
                     s_logger.debug("There is already a VM snapshot task running, wait for it");
                     context.getVimClient().waitForTask(taskMor);
@@ -1261,12 +1264,15 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
             }
 
             vmMo = hyperHost.findVmOnHyperHost(vmName);
+
             if (vmMo == null) {
                 vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
             }
+
             if (vmMo == null) {
                 String msg = "Unable to find VM for CreateVMSnapshotCommand";
                 s_logger.debug(msg);
+
                 return new CreateVMSnapshotAnswer(cmd, false, msg);
             } else {
                 if (vmMo.getSnapshotMor(vmSnapshotName) != null) {
@@ -1274,66 +1280,145 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
                 } else if (!vmMo.createSnapshot(vmSnapshotName, vmSnapshotDesc, snapshotMemory, quiescevm)) {
                     return new CreateVMSnapshotAnswer(cmd, false, "Unable to create snapshot due to esxi internal failed");
                 }
-                // find VM disk file path after creating snapshot
-                VirtualDisk[] vdisks = vmMo.getAllDiskDevice();
-                for (int i = 0; i < vdisks.length; i++) {
-                    List<Pair<String, ManagedObjectReference>> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i], false);
-                    for (Pair<String, ManagedObjectReference> fileItem : vmdkFiles) {
-                        String vmdkName = fileItem.first().split(" ")[1];
-                        if (vmdkName.endsWith(".vmdk")) {
-                            vmdkName = vmdkName.substring(0, vmdkName.length() - (".vmdk").length());
-                        }
-                        String baseName = extractSnapshotBaseFileName(vmdkName);
-                        mapNewDisk.put(baseName, vmdkName);
-                    }
-                }
-                for (VolumeObjectTO volumeTO : volumeTOs) {
-                    String baseName = extractSnapshotBaseFileName(volumeTO.getPath());
-                    String newPath = mapNewDisk.get(baseName);
-                    // get volume's chain size for this VM snapshot, exclude current volume vdisk
-                    DataStoreTO store = volumeTO.getDataStore();
-                    long size = getVMSnapshotChainSize(context, hyperHost, baseName + "*.vmdk", store.getUuid(), newPath);
-
-                    if (volumeTO.getVolumeType() == Volume.Type.ROOT) {
-                        // add memory snapshot size
-                        size = size + getVMSnapshotChainSize(context, hyperHost, cmd.getVmName() + "*.vmsn", store.getUuid(), null);
-                    }
 
-                    volumeTO.setSize(size);
-                    volumeTO.setPath(newPath);
-                }
+                Map<String, String> mapNewDisk = getNewDiskMap(vmMo);
+
+                setVolumeToPathAndSize(volumeTOs, mapNewDisk, context, hyperHost, cmd.getVmName());
+
                 return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), volumeTOs);
             }
         } catch (Exception e) {
             String msg = e.getMessage();
             s_logger.error("failed to create snapshot for vm:" + vmName + " due to " + msg);
+
             try {
                 if (vmMo.getSnapshotMor(vmSnapshotName) != null) {
                     vmMo.removeSnapshot(vmSnapshotName, false);
                 }
             } catch (Exception e1) {
             }
+
             return new CreateVMSnapshotAnswer(cmd, false, e.getMessage());
         }
     }
 
+    private Map<String, String> getNewDiskMap(VirtualMachineMO vmMo) throws Exception {
+        Map<String, String> mapNewDisk = new HashMap<String, String>();
+
+        // find VM disk file path after creating snapshot
+        VirtualDisk[] vdisks = vmMo.getAllDiskDevice();
+
+        for (int i = 0; i < vdisks.length; i++) {
+            List<Pair<String, ManagedObjectReference>> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i], false);
+
+            for (Pair<String, ManagedObjectReference> fileItem : vmdkFiles) {
+                String fullPath = fileItem.first();
+                String baseName = null;
+                String vmdkName = null;
+
+                // if this is managed storage
+                if (fullPath.startsWith("[-iqn.")) { // ex. [-iqn.2010-01.com.company:3y8w.vol-10.64-0] -iqn.2010-01.com.company:3y8w.vol-10.64-0-000001.vmdk
+                    baseName = fullPath.split(" ")[0]; // ex. [-iqn.2010-01.com.company:3y8w.vol-10.64-0]
+
+                    // remove '[' and ']'
+                    baseName = baseName.substring(1, baseName.length() - 1);
+
+                    vmdkName = fullPath; // for managed storage, vmdkName == fullPath
+                }
+                else {
+                    vmdkName = fullPath.split(" ")[1];
+
+                    if (vmdkName.endsWith(".vmdk")) {
+                        vmdkName = vmdkName.substring(0, vmdkName.length() - (".vmdk").length());
+                    }
+
+                    String token = "/";
+
+                    if (vmdkName.contains(token)) {
+                        vmdkName = vmdkName.substring(vmdkName.indexOf(token) + token.length());
+                    }
+
+                    baseName = extractSnapshotBaseFileName(vmdkName);
+                }
+
+                mapNewDisk.put(baseName, vmdkName);
+            }
+        }
+
+        return mapNewDisk;
+    }
+
+    private void setVolumeToPathAndSize(List<VolumeObjectTO> volumeTOs, Map<String, String> mapNewDisk, VmwareContext context,
+            VmwareHypervisorHost hyperHost, String vmName) throws Exception {
+        for (VolumeObjectTO volumeTO : volumeTOs) {
+            String oldPath = volumeTO.getPath();
+
+            final String baseName;
+
+            // if this is managed storage
+            if (oldPath.startsWith("[-iqn.")) { // ex. [-iqn.2010-01.com.company:3y8w.vol-10.64-0] -iqn.2010-01.com.company:3y8w.vol-10.64-0-000001.vmdk
+                oldPath = oldPath.split(" ")[0]; // ex. [-iqn.2010-01.com.company:3y8w.vol-10.64-0]
+
+                // remove '[' and ']'
+                baseName = oldPath.substring(1, oldPath.length() - 1);
+            }
+            else {
+                baseName = extractSnapshotBaseFileName(volumeTO.getPath());
+            }
+
+            String newPath = mapNewDisk.get(baseName);
+
+            // get volume's chain size for this VM snapshot; exclude current volume vdisk
+            DataStoreTO store = volumeTO.getDataStore();
+            ManagedObjectReference morDs = getDatastoreAsManagedObjectReference(baseName, hyperHost, store);
+            long size = getVMSnapshotChainSize(context, hyperHost, baseName + "*.vmdk", morDs, newPath);
+
+            if (volumeTO.getVolumeType()== Volume.Type.ROOT) {
+                // add memory snapshot size
+                size += getVMSnapshotChainSize(context, hyperHost, vmName + "*.vmsn", morDs, null);
+            }
+
+            volumeTO.setSize(size);
+            volumeTO.setPath(newPath);
+        }
+    }
+
+    private ManagedObjectReference getDatastoreAsManagedObjectReference(String baseName, VmwareHypervisorHost hyperHost, DataStoreTO store)  throws Exception {
+        try {
+            // if baseName equates to a datastore name, this should be managed storage
+            ManagedObjectReference morDs = hyperHost.findDatastoreByName(baseName);
+
+            if (morDs != null) {
+                return morDs;
+            }
+        }
+        catch (Exception ex) {
+        }
+
+        // not managed storage, so use the standard way of getting a ManagedObjectReference for a datastore
+        return HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
+    }
+
     @Override
     public DeleteVMSnapshotAnswer execute(VmwareHostService hostService, DeleteVMSnapshotCommand cmd) {
         List<VolumeObjectTO> listVolumeTo = cmd.getVolumeTOs();
         VirtualMachineMO vmMo = null;
         VmwareContext context = hostService.getServiceContext(cmd);
-        Map<String, String> mapNewDisk = new HashMap<String, String>();
         String vmName = cmd.getVmName();
         String vmSnapshotName = cmd.getTarget().getSnapshotName();
+
         try {
             VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
             vmMo = hyperHost.findVmOnHyperHost(vmName);
+
             if (vmMo == null) {
                 vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
             }
+
             if (vmMo == null) {
                 String msg = "Unable to find VM for RevertToVMSnapshotCommand";
                 s_logger.debug(msg);
+
                 return new DeleteVMSnapshotAnswer(cmd, false, msg);
             } else {
                 if (vmMo.getSnapshotMor(vmSnapshotName) == null) {
@@ -1342,41 +1427,25 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
                     if (!vmMo.removeSnapshot(vmSnapshotName, false)) {
                         String msg = "delete vm snapshot " + vmSnapshotName + " due to error occured in vmware";
                         s_logger.error(msg);
+
                         return new DeleteVMSnapshotAnswer(cmd, false, msg);
                     }
                 }
+
                 s_logger.debug("snapshot: " + vmSnapshotName + " is removed");
+
                 // after removed snapshot, the volumes' paths have been changed for the VM, needs to report new paths to manager
-                VirtualDisk[] vdisks = vmMo.getAllDiskDevice();
-                for (int i = 0; i < vdisks.length; i++) {
-                    @SuppressWarnings("deprecation")
-                    List<Pair<String, ManagedObjectReference>> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i], false);
-                    for (Pair<String, ManagedObjectReference> fileItem : vmdkFiles) {
-                        String vmdkName = fileItem.first().split(" ")[1];
-                        if (vmdkName.endsWith(".vmdk")) {
-                            vmdkName = vmdkName.substring(0, vmdkName.length() - (".vmdk").length());
-                        }
-                        String baseName = extractSnapshotBaseFileName(vmdkName);
-                        mapNewDisk.put(baseName, vmdkName);
-                    }
-                }
-                for (VolumeObjectTO volumeTo : listVolumeTo) {
-                    String baseName = extractSnapshotBaseFileName(volumeTo.getPath());
-                    String newPath = mapNewDisk.get(baseName);
-                    DataStoreTO store = volumeTo.getDataStore();
-                    long size = getVMSnapshotChainSize(context, hyperHost, baseName + "*.vmdk", store.getUuid(), newPath);
-                    if (volumeTo.getVolumeType() == Volume.Type.ROOT) {
-                        // add memory snapshot size
-                        size = size + getVMSnapshotChainSize(context, hyperHost, cmd.getVmName() + "*.vmsn", store.getUuid(), null);
-                    }
-                    volumeTo.setSize(size);
-                    volumeTo.setPath(newPath);
-                }
+
+                Map<String, String> mapNewDisk = getNewDiskMap(vmMo);
+
+                setVolumeToPathAndSize(listVolumeTo, mapNewDisk, context, hyperHost, cmd.getVmName());
+
                 return new DeleteVMSnapshotAnswer(cmd, listVolumeTo);
             }
         } catch (Exception e) {
             String msg = e.getMessage();
             s_logger.error("failed to delete vm snapshot " + vmSnapshotName + " of vm " + vmName + " due to " + msg);
+
             return new DeleteVMSnapshotAnswer(cmd, false, msg);
         }
     }
@@ -1390,15 +1459,17 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         VirtualMachine.State vmState = VirtualMachine.State.Running;
         VirtualMachineMO vmMo = null;
         VmwareContext context = hostService.getServiceContext(cmd);
-        Map<String, String> mapNewDisk = new HashMap<String, String>();
+
         try {
             VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
 
             // wait if there are already VM revert task running
             ManagedObjectReference taskmgr = context.getServiceContent().getTaskManager();
             List<ManagedObjectReference> tasks = (ArrayList<ManagedObjectReference>)context.getVimClient().getDynamicProperty(taskmgr, "recentTask");
+
             for (ManagedObjectReference taskMor : tasks) {
                 TaskInfo info = (TaskInfo)(context.getVimClient().getDynamicProperty(taskMor, "info"));
+
                 if (info.getEntityName().equals(cmd.getVmName()) && info.getName().equalsIgnoreCase("RevertToSnapshot_Task")) {
                     s_logger.debug("There is already a VM snapshot task running, wait for it");
                     context.getVimClient().waitForTask(taskMor);
@@ -1407,58 +1478,49 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
 
             HostMO hostMo = (HostMO)hyperHost;
             vmMo = hyperHost.findVmOnHyperHost(vmName);
+
             if (vmMo == null) {
                 vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
             }
+
             if (vmMo == null) {
                 String msg = "Unable to find VM for RevertToVMSnapshotCommand";
                 s_logger.debug(msg);
+
                 return new RevertToVMSnapshotAnswer(cmd, false, msg);
             } else {
                 if (cmd.isReloadVm()) {
                     vmMo.reload();
                 }
+
                 boolean result = false;
+
                 if (snapshotName != null) {
                     ManagedObjectReference morSnapshot = vmMo.getSnapshotMor(snapshotName);
+
                     result = hostMo.revertToSnapshot(morSnapshot);
                 } else {
                     return new RevertToVMSnapshotAnswer(cmd, false, "Unable to find the snapshot by name " + snapshotName);
                 }
 
                 if (result) {
-                    VirtualDisk[] vdisks = vmMo.getAllDiskDevice();
-                    // build a map<volumeName, vmdk>
-                    for (int i = 0; i < vdisks.length; i++) {
-                        @SuppressWarnings("deprecation")
-                        List<Pair<String, ManagedObjectReference>> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i], false);
-                        for (Pair<String, ManagedObjectReference> fileItem : vmdkFiles) {
-                            String vmdkName = fileItem.first().split(" ")[1];
-                            if (vmdkName.endsWith(".vmdk")) {
-                                vmdkName = vmdkName.substring(0, vmdkName.length() - (".vmdk").length());
-                            }
-                            String[] s = vmdkName.split("-");
-                            mapNewDisk.put(s[0], vmdkName);
-                        }
-                    }
-                    String key = null;
-                    for (VolumeObjectTO volumeTo : listVolumeTo) {
-                        String parentUUID = volumeTo.getPath();
-                        String[] s = parentUUID.split("-");
-                        key = s[0];
-                        volumeTo.setPath(mapNewDisk.get(key));
-                    }
+                    Map<String, String> mapNewDisk = getNewDiskMap(vmMo);
+
+                    setVolumeToPathAndSize(listVolumeTo, mapNewDisk, context, hyperHost, cmd.getVmName());
+
                     if (!snapshotMemory) {
                         vmState = VirtualMachine.State.Stopped;
                     }
+
                     return new RevertToVMSnapshotAnswer(cmd, listVolumeTo, vmState);
                 } else {
-                    return new RevertToVMSnapshotAnswer(cmd, false, "Error while reverting to snapshot due to execute in esxi");
+                    return new RevertToVMSnapshotAnswer(cmd, false, "Error while reverting to snapshot due to execute in ESXi");
                 }
             }
         } catch (Exception e) {
             String msg = "revert vm " + vmName + " to snapshot " + snapshotName + " failed due to " + e.getMessage();
             s_logger.error(msg);
+
             return new RevertToVMSnapshotAnswer(cmd, false, msg);
         }
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a354d969/vmware-base/src/com/cloud/hypervisor/vmware/mo/ClusterMO.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/ClusterMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/ClusterMO.java
index b9fdd01..e416cb5 100755
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/ClusterMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/ClusterMO.java
@@ -383,6 +383,11 @@ public class ClusterMO extends BaseMO implements VmwareHypervisorHost {
     }
 
     @Override
+    public ManagedObjectReference findDatastoreByName(String datastoreName) throws Exception {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public ManagedObjectReference findDatastoreByExportPath(String exportPath) throws Exception {
         if (s_logger.isTraceEnabled())
             s_logger.trace("vCenter API trace - findDatastoreByExportPath(). target MOR: " + _mor.getValue() + ", exportPath: " + exportPath);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a354d969/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
index b306b0c..f511ce2 100755
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
@@ -869,6 +869,12 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
     }
 
     @Override
+    public ManagedObjectReference findDatastoreByName(String datastoreName) throws Exception {
+        HostDatastoreSystemMO hostDsMo = getHostDatastoreSystemMO();
+        return hostDsMo.findDatastoreByName(datastoreName);
+    }
+
+    @Override
     public ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) throws Exception {
         return _mor;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a354d969/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
index 5588a6a..9727e17 100755
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
@@ -67,6 +67,8 @@ public interface VmwareHypervisorHost {
 
     ManagedObjectReference findDatastore(String poolUuid) throws Exception;
 
+    ManagedObjectReference findDatastoreByName(String datastoreName) throws Exception;
+
     @Deprecated
     ManagedObjectReference findDatastoreByExportPath(String exportPath) throws Exception;