List<VolumeTO> volumeTOs = cmd.getVolumeTOs();
String vmName = cmd.getVmName();
String vmSnapshotName = cmd.getTarget().getSnapshotName();
String vmSnapshotDesc = cmd.getTarget().getDescription();
boolean snapshotMemory = cmd.getTarget().getType() == VMSnapshot.Type.DiskAndMemory;
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);
}
}
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){
s_logger.debug("VM snapshot " + vmSnapshotName + " already exists");
}else if (!vmMo.createSnapshot(vmSnapshotName, vmSnapshotDesc, snapshotMemory, true)) {
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());
}
if(vmdkName.contains("/")) {
vmdkName = vmdkName.substring(vmdkName.indexOf ("/") + 1,vmdkName.length());
}
String baseName = extractSnapshotBaseFileName(vmdkName);
mapNewDisk.put(baseName, vmdkName);
}
}
for (VolumeTO 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
long size = getVMSnapshotChainSize(context,hyperHost,baseName + "*.vmdk",
volumeTO.getPoolUuid(), newPath);
if(volumeTO.getType()== Volume.Type.ROOT){
// add memory snapshot size
size = size + getVMSnapshotChainSize(context,hyperHost,cmd.getVmName()+"*.vmsn",volumeTO.getPoolUuid(),null);
}
volumeTO.setChainSize(size);
volumeTO.setPath(newPath);
}
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());
}