Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 86BFD103CA for ; Fri, 10 Jan 2014 06:20:35 +0000 (UTC) Received: (qmail 88974 invoked by uid 500); 10 Jan 2014 06:20:31 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 88943 invoked by uid 500); 10 Jan 2014 06:20:30 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 88936 invoked by uid 99); 10 Jan 2014 06:20:28 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Jan 2014 06:20:28 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id CAFB88B4FAA; Fri, 10 Jan 2014 06:20:27 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: mtutkowski@apache.org To: commits@cloudstack.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: git commit: updated refs/heads/master to a354d96 Date: Fri, 10 Jan 2014 06:20:27 +0000 (UTC) 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 Authored: Thu Jan 9 23:10:40 2014 -0700 Committer: Mike Tutkowski 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 mapNewDisk = new HashMap(); + try { VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd); // wait if there are already VM snapshot task running ManagedObjectReference taskmgr = context.getServiceContent().getTaskManager(); List tasks = (ArrayList)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> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i], false); - for (Pair 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 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 getNewDiskMap(VirtualMachineMO vmMo) throws Exception { + Map mapNewDisk = new HashMap(); + + // find VM disk file path after creating snapshot + VirtualDisk[] vdisks = vmMo.getAllDiskDevice(); + + for (int i = 0; i < vdisks.length; i++) { + List> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i], false); + + for (Pair 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 volumeTOs, Map 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 listVolumeTo = cmd.getVolumeTOs(); VirtualMachineMO vmMo = null; VmwareContext context = hostService.getServiceContext(cmd); - Map mapNewDisk = new HashMap(); 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> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i], false); - for (Pair 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 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 mapNewDisk = new HashMap(); + try { VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd); // wait if there are already VM revert task running ManagedObjectReference taskmgr = context.getServiceContent().getTaskManager(); List tasks = (ArrayList)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 - for (int i = 0; i < vdisks.length; i++) { - @SuppressWarnings("deprecation") - List> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i], false); - for (Pair 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 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;