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;