You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/07/30 03:59:25 UTC

[1/2] CLOUDSTACK-3107: fix attach upload volume

Updated Branches:
  refs/heads/4.2 0f765727d -> 6533e6559


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6533e655/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 6451828..112a0cb 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -86,29 +86,29 @@ import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
 import com.vmware.vim25.VirtualSCSISharing;
 
 public class VmwareStorageProcessor implements StorageProcessor {
-	private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
-	private VmwareHostService hostService;
-	private boolean _fullCloneFlag;
-	private VmwareStorageMount mountService;
-	private VmwareResource resource;
-	private Integer _timeout;
-	protected Integer _shutdown_waitMs;
-	private final Gson _gson;
-	private final StorageLayer _storage = new JavaStorageLayer();
-	public VmwareStorageProcessor(VmwareHostService hostService, boolean fullCloneFlag, VmwareStorageMount mountService,
-			Integer timeout,
-			VmwareResource resource,
-			Integer shutdownWaitMs) {
-		this.hostService = hostService;
-		this._fullCloneFlag = fullCloneFlag;
-		this.mountService = mountService;
-		this._timeout = timeout;
-		this.resource = resource;
-		this._shutdown_waitMs = shutdownWaitMs;
-		_gson = GsonHelper.getGsonLogger();
-	}
-	
-	private String getOVFFilePath(String srcOVAFileName) {
+    private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
+    private VmwareHostService hostService;
+    private boolean _fullCloneFlag;
+    private VmwareStorageMount mountService;
+    private VmwareResource resource;
+    private Integer _timeout;
+    protected Integer _shutdown_waitMs;
+    private final Gson _gson;
+    private final StorageLayer _storage = new JavaStorageLayer();
+    public VmwareStorageProcessor(VmwareHostService hostService, boolean fullCloneFlag, VmwareStorageMount mountService,
+                                  Integer timeout,
+                                  VmwareResource resource,
+                                  Integer shutdownWaitMs) {
+        this.hostService = hostService;
+        this._fullCloneFlag = fullCloneFlag;
+        this.mountService = mountService;
+        this._timeout = timeout;
+        this.resource = resource;
+        this._shutdown_waitMs = shutdownWaitMs;
+        _gson = GsonHelper.getGsonLogger();
+    }
+
+    private String getOVFFilePath(String srcOVAFileName) {
         File file = new File(srcOVAFileName);
         assert(_storage != null);
         String[] files = _storage.listFiles(file.getParent());
@@ -122,144 +122,144 @@ public class VmwareStorageProcessor implements StorageProcessor {
         }
         return null;
     }
-	 private void copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl,
-		        String templatePathAtSecondaryStorage, String templateName, String templateUuid) throws Exception {
-
-		        s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: "
-		            + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
-		            + ", templateName: " + templateName);
-
-		        String secondaryMountPoint = mountService.getMountPoint(secondaryStorageUrl);
-		        s_logger.info("Secondary storage mount point: " + secondaryMountPoint);
-
-		        String srcOVAFileName = secondaryMountPoint + "/" +  templatePathAtSecondaryStorage +
-		            templateName + "." + ImageFormat.OVA.getFileExtension();
-
-		        String srcFileName = getOVFFilePath(srcOVAFileName);
-		        if(srcFileName == null) {
-		            Script command = new Script("tar", 0, s_logger);
-		            command.add("--no-same-owner");
-		            command.add("-xf", srcOVAFileName);
-		            command.setWorkDir(secondaryMountPoint + "/" +  templatePathAtSecondaryStorage);
-		            s_logger.info("Executing command: " + command.toString());
-		            String result = command.execute();
-		            if(result != null) {
-		                String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
-		                s_logger.error(msg);
-		                throw new Exception(msg);
-		            }
-		        }
-
-		        srcFileName = getOVFFilePath(srcOVAFileName);
-		        if(srcFileName == null) {
-		            String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
-		            s_logger.error(msg);
-		            throw new Exception(msg);
-		        }
-
-		        String vmName = templateUuid;
-		        hyperHost.importVmFromOVF(srcFileName, vmName, datastoreMo, "thin");
-
-		        VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
-		        if(vmMo == null) {
-		            String msg = "Failed to import OVA template. secondaryStorage: "
-		                + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
-		                + ", templateName: " + templateName + ", templateUuid: " + templateUuid;
-		            s_logger.error(msg);
-		            throw new Exception(msg);
-		        }
-
-		        if(vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) {
-		            vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateUuid);
-		            vmMo.markAsTemplate();
-		        } else {
-		            vmMo.destroy();
-		            String msg = "Unable to create base snapshot for template, templateName: " + templateName + ", templateUuid: " + templateUuid;
-		            s_logger.error(msg);
-		            throw new Exception(msg);
-		        }
-		    }
-	
-	@Override
-	public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
-		DataTO srcData = cmd.getSrcTO();
-		TemplateObjectTO template = (TemplateObjectTO)srcData;
-		DataStoreTO srcStore = srcData.getDataStore();
-		if (!(srcStore instanceof NfsTO)) {
-			return new CopyCmdAnswer("unsupported protocol");
-		}
-		NfsTO nfsImageStore = (NfsTO)srcStore;
-		DataTO destData = cmd.getDestTO();
-		DataStoreTO destStore = destData.getDataStore();
-		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destStore;
-		String secondaryStorageUrl = nfsImageStore.getUrl();
-		assert (secondaryStorageUrl != null);
-
-		String templateUrl = secondaryStorageUrl + File.separator + srcData.getPath();
-
-		String templateName = null;
-		String mountPoint = null;
-		if (templateUrl.endsWith(".ova")) {
-			int index = templateUrl.lastIndexOf("/");
-			mountPoint = templateUrl.substring(0, index);
-			mountPoint = mountPoint.substring(secondaryStorageUrl.length() + 1);
-			if (!mountPoint.endsWith("/")) {
-				mountPoint = mountPoint + "/";
-			}
-
-			templateName = templateUrl.substring(index + 1).replace("." + ImageFormat.OVA.getFileExtension(), "");
-
-			if (templateName == null || templateName.isEmpty()) {
-				templateName = template.getName();
-			}
-		} else {
-			mountPoint = templateUrl.substring(secondaryStorageUrl.length() + 1);
-			if (!mountPoint.endsWith("/")) {
-				mountPoint = mountPoint + "/";
-			}
-			templateName = template.getName();
-		}
-
-		VmwareContext context = hostService.getServiceContext(cmd);
-		try {
-			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
-
-			String templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + primaryStore.getUuid() + "-" + hyperHost.getMor().getValue()).getBytes()).toString();
-			// truncate template name to 32 chars to ensure they work well with vSphere API's.
-			templateUuidName = templateUuidName.replace("-", "");
-
-			DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
-			VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
-
-			if (templateMo == null) {
-			    if(s_logger.isInfoEnabled())
-			        s_logger.info("Template " + templateName + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
-				ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
-				assert (morDs != null);
-				DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs);
-
-				copyTemplateFromSecondaryToPrimary(hyperHost,
-					primaryStorageDatastoreMo, secondaryStorageUrl,
-					mountPoint, templateName, templateUuidName);
-			} else {
-				s_logger.info("Template " + templateName + " has already been setup, skip the template setup process in primary storage");
-			}
-
-			TemplateObjectTO newTemplate = new TemplateObjectTO();
-			newTemplate.setPath(templateUuidName);
-			return new CopyCmdAnswer(newTemplate);
-		} catch (Throwable e) {
-			if (e instanceof RemoteException) {
-				hostService.invalidateServiceContext(context);
-			}
-
-			String msg = "Unable to execute PrimaryStorageDownloadCommand due to exception";
-			s_logger.error(msg, e);
-			return new CopyCmdAnswer(msg);
-		}
-	}
-	private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
-            String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
+    private void copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl,
+                                                    String templatePathAtSecondaryStorage, String templateName, String templateUuid) throws Exception {
+
+        s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: "
+                + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
+                + ", templateName: " + templateName);
+
+        String secondaryMountPoint = mountService.getMountPoint(secondaryStorageUrl);
+        s_logger.info("Secondary storage mount point: " + secondaryMountPoint);
+
+        String srcOVAFileName = secondaryMountPoint + "/" +  templatePathAtSecondaryStorage +
+                templateName + "." + ImageFormat.OVA.getFileExtension();
+
+        String srcFileName = getOVFFilePath(srcOVAFileName);
+        if(srcFileName == null) {
+            Script command = new Script("tar", 0, s_logger);
+            command.add("--no-same-owner");
+            command.add("-xf", srcOVAFileName);
+            command.setWorkDir(secondaryMountPoint + "/" +  templatePathAtSecondaryStorage);
+            s_logger.info("Executing command: " + command.toString());
+            String result = command.execute();
+            if(result != null) {
+                String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+        }
+
+        srcFileName = getOVFFilePath(srcOVAFileName);
+        if(srcFileName == null) {
+            String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
+            s_logger.error(msg);
+            throw new Exception(msg);
+        }
+
+        String vmName = templateUuid;
+        hyperHost.importVmFromOVF(srcFileName, vmName, datastoreMo, "thin");
+
+        VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+        if(vmMo == null) {
+            String msg = "Failed to import OVA template. secondaryStorage: "
+                    + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
+                    + ", templateName: " + templateName + ", templateUuid: " + templateUuid;
+            s_logger.error(msg);
+            throw new Exception(msg);
+        }
+
+        if(vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) {
+            vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateUuid);
+            vmMo.markAsTemplate();
+        } else {
+            vmMo.destroy();
+            String msg = "Unable to create base snapshot for template, templateName: " + templateName + ", templateUuid: " + templateUuid;
+            s_logger.error(msg);
+            throw new Exception(msg);
+        }
+    }
+
+    @Override
+    public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
+        DataTO srcData = cmd.getSrcTO();
+        TemplateObjectTO template = (TemplateObjectTO)srcData;
+        DataStoreTO srcStore = srcData.getDataStore();
+        if (!(srcStore instanceof NfsTO)) {
+            return new CopyCmdAnswer("unsupported protocol");
+        }
+        NfsTO nfsImageStore = (NfsTO)srcStore;
+        DataTO destData = cmd.getDestTO();
+        DataStoreTO destStore = destData.getDataStore();
+        PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destStore;
+        String secondaryStorageUrl = nfsImageStore.getUrl();
+        assert (secondaryStorageUrl != null);
+
+        String templateUrl = secondaryStorageUrl + File.separator + srcData.getPath();
+
+        String templateName = null;
+        String mountPoint = null;
+        if (templateUrl.endsWith(".ova")) {
+            int index = templateUrl.lastIndexOf("/");
+            mountPoint = templateUrl.substring(0, index);
+            mountPoint = mountPoint.substring(secondaryStorageUrl.length() + 1);
+            if (!mountPoint.endsWith("/")) {
+                mountPoint = mountPoint + "/";
+            }
+
+            templateName = templateUrl.substring(index + 1).replace("." + ImageFormat.OVA.getFileExtension(), "");
+
+            if (templateName == null || templateName.isEmpty()) {
+                templateName = template.getName();
+            }
+        } else {
+            mountPoint = templateUrl.substring(secondaryStorageUrl.length() + 1);
+            if (!mountPoint.endsWith("/")) {
+                mountPoint = mountPoint + "/";
+            }
+            templateName = template.getName();
+        }
+
+        VmwareContext context = hostService.getServiceContext(cmd);
+        try {
+            VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+
+            String templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + primaryStore.getUuid() + "-" + hyperHost.getMor().getValue()).getBytes()).toString();
+            // truncate template name to 32 chars to ensure they work well with vSphere API's.
+            templateUuidName = templateUuidName.replace("-", "");
+
+            DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
+            VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
+
+            if (templateMo == null) {
+                if(s_logger.isInfoEnabled())
+                    s_logger.info("Template " + templateName + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
+                ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+                assert (morDs != null);
+                DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs);
+
+                copyTemplateFromSecondaryToPrimary(hyperHost,
+                        primaryStorageDatastoreMo, secondaryStorageUrl,
+                        mountPoint, templateName, templateUuidName);
+            } else {
+                s_logger.info("Template " + templateName + " has already been setup, skip the template setup process in primary storage");
+            }
+
+            TemplateObjectTO newTemplate = new TemplateObjectTO();
+            newTemplate.setPath(templateUuidName);
+            return new CopyCmdAnswer(newTemplate);
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                hostService.invalidateServiceContext(context);
+            }
+
+            String msg = "Unable to execute PrimaryStorageDownloadCommand due to exception";
+            s_logger.error(msg, e);
+            return new CopyCmdAnswer(msg);
+        }
+    }
+    private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
+                                        String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
 
         ManagedObjectReference morBaseSnapshot = vmTemplate.getSnapshotMor("cloud.template.base");
         if (morBaseSnapshot == null) {
@@ -292,8 +292,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
         return true;
     }
 
-	private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
-            String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
+    private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
+                                      String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
 
         if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
             dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
@@ -319,109 +319,117 @@ public class VmwareStorageProcessor implements StorageProcessor {
         return true;
     }
 
-	@Override
-	public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
-		DataTO srcData = cmd.getSrcTO();
-		TemplateObjectTO template = (TemplateObjectTO)srcData;
-		DataTO destData = cmd.getDestTO();
-		VolumeObjectTO volume = (VolumeObjectTO)destData;
-		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
-		PrimaryDataStoreTO srcStore = (PrimaryDataStoreTO)template.getDataStore();
-
-		
-		try {
-			VmwareContext context = this.hostService.getServiceContext(null);
-			VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
-			DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
-			VirtualMachineMO vmMo = null;
-			ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
-			if (morDatastore == null)
-				throw new Exception("Unable to find datastore in vSphere");
-
-			DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
-
-
-			// attach volume id to make the name unique
-			String vmdkName = volume.getName() + "-" + volume.getId();
-			if (srcStore == null) {
-				// create a root volume for blank VM
-				String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
-
-				try {
-					vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
-					if (vmMo == null) {
-						throw new Exception("Unable to create a dummy VM for volume creation");
-					}
-
-					String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
-					synchronized (this) {
-						s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
-						VmwareHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
-						vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, -1);
-						vmMo.detachDisk(volumeDatastorePath, false);
-					}
-
-					VolumeObjectTO newVol = new VolumeObjectTO();
-					newVol.setPath(vmdkName);
+    @Override
+    public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
+        DataTO srcData = cmd.getSrcTO();
+        TemplateObjectTO template = (TemplateObjectTO)srcData;
+        DataTO destData = cmd.getDestTO();
+        VolumeObjectTO volume = (VolumeObjectTO)destData;
+        PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+        PrimaryDataStoreTO srcStore = (PrimaryDataStoreTO)template.getDataStore();
+
+
+        try {
+            VmwareContext context = this.hostService.getServiceContext(null);
+            VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
+            DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
+            VirtualMachineMO vmMo = null;
+            ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+            if (morDatastore == null)
+                throw new Exception("Unable to find datastore in vSphere");
+
+            DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
+
+
+            // attach volume id to make the name unique
+            String vmdkName = volume.getName() + "-" + volume.getId();
+            if (srcStore == null) {
+                // create a root volume for blank VM
+                String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
+
+                try {
+                    vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
+                    if (vmMo == null) {
+                        throw new Exception("Unable to create a dummy VM for volume creation");
+                    }
+
+                    String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
+                    synchronized (this) {
+                        s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
+                        VmwareHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
+                        vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, -1);
+                        vmMo.detachDisk(volumeDatastorePath, false);
+                    }
+
+                    VolumeObjectTO newVol = new VolumeObjectTO();
+                    newVol.setPath(vmdkName);
                     newVol.setSize(volume.getSize());
-					return new CopyCmdAnswer(newVol);
-				} finally {
-					vmMo.detachAllDisks();
-
-					s_logger.info("Destroy dummy VM after volume creation");
-					vmMo.destroy();
-				}
-			} else {
-				String templatePath = template.getPath();
-				VirtualMachineMO vmTemplate = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templatePath), true);
-				if (vmTemplate == null) {
-					s_logger.warn("Template host in vSphere is not in connected state, request template reload");
-					return new CopyCmdAnswer("Template host in vSphere is not in connected state, request template reload");
-				}
-
-				ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
-				ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
-				//createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
-				if (!_fullCloneFlag) {
-					createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
-				} else {
-					createVMFullClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
-				}
-
-				vmMo = new ClusterMO(context, morCluster).findVmOnHyperHost(vmdkName);
-				assert (vmMo != null);
-
-				s_logger.info("detach disks from volume-wrapper VM " + vmdkName);
-				vmMo.detachAllDisks();
-
-				s_logger.info("destroy volume-wrapper VM " + vmdkName);
-				vmMo.destroy();
-
-				String srcFile = String.format("[%s] %s/", dsMo.getName(), vmdkName);
-				dsMo.deleteFile(srcFile, dcMo.getMor(), true);
-				VolumeObjectTO newVol = new VolumeObjectTO();
-				newVol.setPath(vmdkName);
+                    return new CopyCmdAnswer(newVol);
+                } finally {
+                    vmMo.detachAllDisks();
+
+                    s_logger.info("Destroy dummy VM after volume creation");
+                    vmMo.destroy();
+                }
+            } else {
+                String templatePath = template.getPath();
+                VirtualMachineMO vmTemplate = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templatePath), true);
+                if (vmTemplate == null) {
+                    s_logger.warn("Template host in vSphere is not in connected state, request template reload");
+                    return new CopyCmdAnswer("Template host in vSphere is not in connected state, request template reload");
+                }
+
+                ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
+                ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
+                //createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+                if (!_fullCloneFlag) {
+                    createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+                } else {
+                    createVMFullClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+                }
+
+                vmMo = new ClusterMO(context, morCluster).findVmOnHyperHost(vmdkName);
+                assert (vmMo != null);
+
+                s_logger.info("detach disks from volume-wrapper VM " + vmdkName);
+                vmMo.detachAllDisks();
+
+                s_logger.info("destroy volume-wrapper VM " + vmdkName);
+                vmMo.destroy();
+
+                String srcFile = String.format("[%s] %s/", dsMo.getName(), vmdkName);
+                dsMo.deleteFile(srcFile, dcMo.getMor(), true);
+                VolumeObjectTO newVol = new VolumeObjectTO();
+                newVol.setPath(vmdkName);
                 newVol.setSize(volume.getSize());
-				return new CopyCmdAnswer(newVol);
-			}
-		} catch (Throwable e) {
-			if (e instanceof RemoteException) {
-				s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
-				this.hostService.invalidateServiceContext(null);
-			}
-
-			String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
-			s_logger.error(msg, e);
-			return new CopyCmdAnswer(e.toString());
-		}
-	}
+                return new CopyCmdAnswer(newVol);
+            }
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+                this.hostService.invalidateServiceContext(null);
+            }
+
+            String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+            s_logger.error(msg, e);
+            return new CopyCmdAnswer(e.toString());
+        }
+    }
 
     private Pair<String, String> copyVolumeFromSecStorage(VmwareHypervisorHost hyperHost, String srcVolumePath,
                                                           DatastoreMO dsMo, String secStorageUrl) throws Exception {
-        //srcVolumePath has volumes/dc/id/uuid
+
+        String volumeFolder = null;
+        String volumeName = null;
+        String sufix = ".ova";
         int index = srcVolumePath.lastIndexOf(File.separator);
-        String volumeFolder = srcVolumePath;
-        String volumeName = srcVolumePath.substring(index + 1);
+        if (srcVolumePath.endsWith(sufix)) {
+            volumeFolder = srcVolumePath.substring(0, index);
+            volumeName = srcVolumePath.substring(index + 1).replace(sufix, "");
+        } else {
+            volumeFolder = srcVolumePath;
+            volumeName = srcVolumePath.substring(index + 1);
+        }
 
         String newVolume    = UUID.randomUUID().toString().replaceAll("-", "");
         restoreVolumeFromSecStorage(hyperHost, dsMo, newVolume, secStorageUrl, volumeFolder, volumeName);
@@ -445,8 +453,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
         }
     }
 
-	@Override
-	public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
+    @Override
+    public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
         VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO();
         VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO();
         VmwareContext context = hostService.getServiceContext(cmd);
@@ -566,8 +574,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
         }
     }
 
-	@Override
-	public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
+    @Override
+    public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
         VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO();
         VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO();
         String vmName = srcVolume.getVmName();
@@ -596,167 +604,167 @@ public class VmwareStorageProcessor implements StorageProcessor {
             s_logger.error(msg, e);
             return new CopyCmdAnswer("CopyVolumeCommand failed due to exception: " + e.toString());
         }
-	}
-	
-	private void postCreatePrivateTemplate(String installFullPath, long templateId,
-	        String templateName, long size, long virtualSize) throws Exception {
-
-	        // TODO a bit ugly here
-	        BufferedWriter out = null;
-	        try {
-	            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/template.properties")));
-	            out.write("filename=" + templateName + ".ova");
-	            out.newLine();
-	            out.write("description=");
-	            out.newLine();
-	            out.write("checksum=");
-	            out.newLine();
-	            out.write("hvm=false");
-	            out.newLine();
-	            out.write("size=" + size);
-	            out.newLine();
-	            out.write("ova=true");
-	            out.newLine();
-	            out.write("id=" + templateId);
-	            out.newLine();
-	            out.write("public=false");
-	            out.newLine();
-	            out.write("ova.filename=" + templateName + ".ova");
-	            out.newLine();
-	            out.write("uniquename=" + templateName);
-	            out.newLine();
-	            out.write("ova.virtualsize=" + virtualSize);
-	            out.newLine();
-	            out.write("virtualsize=" + virtualSize);
-	            out.newLine();
-	            out.write("ova.size=" + size);
-	            out.newLine();
-	        } finally {
-	            if(out != null)
-	                out.close();
-	        }
-	    }
-
-	private Ternary<String, Long, Long> createTemplateFromVolume(VirtualMachineMO vmMo, String installPath, long templateId, String templateUniqueName,
-	        String secStorageUrl, String volumePath, String workerVmName) throws Exception {
-
-	        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
-	        String installFullPath = secondaryMountPoint + "/" + installPath;
-	        synchronized(installPath.intern()) {
-	            Script command = new Script(false, "mkdir", _timeout, s_logger);
-	            command.add("-p");
-	            command.add(installFullPath);
-
-	            String result = command.execute();
-	            if(result != null) {
-	                String msg = "unable to prepare template directory: "
-	                    + installPath + ", storage: " + secStorageUrl + ", error msg: " + result;
-	                s_logger.error(msg);
-	                throw new Exception(msg);
-	            }
-	        }
-
-	        VirtualMachineMO clonedVm = null;
-	        try {
-	            Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
-	            if(volumeDeviceInfo == null) {
-	                String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
-	                s_logger.error(msg);
-	                throw new Exception(msg);
-	            }
-
-	            if(!vmMo.createSnapshot(templateUniqueName, "Temporary snapshot for template creation", false, false)) {
-	                String msg = "Unable to take snapshot for creating template from volume. volume path: " + volumePath;
-	                s_logger.error(msg);
-	                throw new Exception(msg);
-	            }
-
-	            // 4 MB is the minimum requirement for VM memory in VMware
-	            vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
-	                VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
-	            clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
-	            if(clonedVm == null) {
-	                String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
-	                s_logger.error(msg);
-	                throw new Exception(msg);
-	            }
-
-	            clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, true, false);
-
-	            long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
-	            VmdkProcessor processor = new VmdkProcessor();
-	            Map<String, Object> params = new HashMap<String, Object>();
-	            params.put(StorageLayer.InstanceConfigKey, _storage);
-	            processor.configure("VMDK Processor", params);
-	            long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
-
-	            postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
-	            return new Ternary<String, Long, Long>(installPath + "/" + templateUniqueName + ".ova", physicalSize, virtualSize);
-
-	        } finally {
-	            if(clonedVm != null) {
-	                clonedVm.detachAllDisks();
-	                clonedVm.destroy();
-	            }
-
-	            vmMo.removeSnapshot(templateUniqueName, false);
-	        }
-	    }
-
-	@Override
-	public Answer createTemplateFromVolume(CopyCommand cmd) {
-		VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
-		TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
-		DataStoreTO imageStore = template.getDataStore();
-		
-		if (!(imageStore instanceof NfsTO)) {
-			return new CopyCmdAnswer("unsupported protocol");
-		}
-		NfsTO nfsImageStore = (NfsTO)imageStore;
-		String secondaryStoragePoolURL = nfsImageStore.getUrl();
-		String volumePath = volume.getPath();
-
-		String details = null;
-
-		VmwareContext context = hostService.getServiceContext(cmd);
-		try {
-			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
-
-			VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(volume.getVmName());
-			if (vmMo == null) {
-				if(s_logger.isDebugEnabled())
-					s_logger.debug("Unable to find the owner VM for CreatePrivateTemplateFromVolumeCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
-				vmMo = hyperHost.findVmOnPeerHyperHost(volume.getVmName());
-
-				if(vmMo == null) {
-					String msg = "Unable to find the owner VM for volume operation. vm: " + volume.getVmName();
-					s_logger.error(msg);
-					throw new Exception(msg);
-				}
-			}
-
-			Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo,
-					template.getPath(), template.getId(), template.getName(),
-					secondaryStoragePoolURL, volumePath,
-					hostService.getWorkerName(context, cmd, 0));
-
-			TemplateObjectTO newTemplate = new TemplateObjectTO();
-			newTemplate.setPath(result.first());
-			newTemplate.setFormat(ImageFormat.OVA);
-			newTemplate.setSize(result.third());
-			return new CopyCmdAnswer(newTemplate);
-
-		} catch (Throwable e) {
-			if (e instanceof RemoteException) {
-				hostService.invalidateServiceContext(context);
-			}
-
-			s_logger.error("Unexpecpted exception ", e);
-
-			details = "CreatePrivateTemplateFromVolumeCommand exception: " + e.toString();
-			return new CopyCmdAnswer(details);
-		}
-	}
+    }
+
+    private void postCreatePrivateTemplate(String installFullPath, long templateId,
+                                           String templateName, long size, long virtualSize) throws Exception {
+
+        // TODO a bit ugly here
+        BufferedWriter out = null;
+        try {
+            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/template.properties")));
+            out.write("filename=" + templateName + ".ova");
+            out.newLine();
+            out.write("description=");
+            out.newLine();
+            out.write("checksum=");
+            out.newLine();
+            out.write("hvm=false");
+            out.newLine();
+            out.write("size=" + size);
+            out.newLine();
+            out.write("ova=true");
+            out.newLine();
+            out.write("id=" + templateId);
+            out.newLine();
+            out.write("public=false");
+            out.newLine();
+            out.write("ova.filename=" + templateName + ".ova");
+            out.newLine();
+            out.write("uniquename=" + templateName);
+            out.newLine();
+            out.write("ova.virtualsize=" + virtualSize);
+            out.newLine();
+            out.write("virtualsize=" + virtualSize);
+            out.newLine();
+            out.write("ova.size=" + size);
+            out.newLine();
+        } finally {
+            if(out != null)
+                out.close();
+        }
+    }
+
+    private Ternary<String, Long, Long> createTemplateFromVolume(VirtualMachineMO vmMo, String installPath, long templateId, String templateUniqueName,
+                                                                 String secStorageUrl, String volumePath, String workerVmName) throws Exception {
+
+        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
+        String installFullPath = secondaryMountPoint + "/" + installPath;
+        synchronized(installPath.intern()) {
+            Script command = new Script(false, "mkdir", _timeout, s_logger);
+            command.add("-p");
+            command.add(installFullPath);
+
+            String result = command.execute();
+            if(result != null) {
+                String msg = "unable to prepare template directory: "
+                        + installPath + ", storage: " + secStorageUrl + ", error msg: " + result;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+        }
+
+        VirtualMachineMO clonedVm = null;
+        try {
+            Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
+            if(volumeDeviceInfo == null) {
+                String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+
+            if(!vmMo.createSnapshot(templateUniqueName, "Temporary snapshot for template creation", false, false)) {
+                String msg = "Unable to take snapshot for creating template from volume. volume path: " + volumePath;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+
+            // 4 MB is the minimum requirement for VM memory in VMware
+            vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
+                    VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
+            clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
+            if(clonedVm == null) {
+                String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+
+            clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, true, false);
+
+            long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
+            VmdkProcessor processor = new VmdkProcessor();
+            Map<String, Object> params = new HashMap<String, Object>();
+            params.put(StorageLayer.InstanceConfigKey, _storage);
+            processor.configure("VMDK Processor", params);
+            long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
+
+            postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
+            return new Ternary<String, Long, Long>(installPath + "/" + templateUniqueName + ".ova", physicalSize, virtualSize);
+
+        } finally {
+            if(clonedVm != null) {
+                clonedVm.detachAllDisks();
+                clonedVm.destroy();
+            }
+
+            vmMo.removeSnapshot(templateUniqueName, false);
+        }
+    }
+
+    @Override
+    public Answer createTemplateFromVolume(CopyCommand cmd) {
+        VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
+        TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
+        DataStoreTO imageStore = template.getDataStore();
+
+        if (!(imageStore instanceof NfsTO)) {
+            return new CopyCmdAnswer("unsupported protocol");
+        }
+        NfsTO nfsImageStore = (NfsTO)imageStore;
+        String secondaryStoragePoolURL = nfsImageStore.getUrl();
+        String volumePath = volume.getPath();
+
+        String details = null;
+
+        VmwareContext context = hostService.getServiceContext(cmd);
+        try {
+            VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+
+            VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(volume.getVmName());
+            if (vmMo == null) {
+                if(s_logger.isDebugEnabled())
+                    s_logger.debug("Unable to find the owner VM for CreatePrivateTemplateFromVolumeCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
+                vmMo = hyperHost.findVmOnPeerHyperHost(volume.getVmName());
+
+                if(vmMo == null) {
+                    String msg = "Unable to find the owner VM for volume operation. vm: " + volume.getVmName();
+                    s_logger.error(msg);
+                    throw new Exception(msg);
+                }
+            }
+
+            Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo,
+                    template.getPath(), template.getId(), template.getName(),
+                    secondaryStoragePoolURL, volumePath,
+                    hostService.getWorkerName(context, cmd, 0));
+
+            TemplateObjectTO newTemplate = new TemplateObjectTO();
+            newTemplate.setPath(result.first());
+            newTemplate.setFormat(ImageFormat.OVA);
+            newTemplate.setSize(result.third());
+            return new CopyCmdAnswer(newTemplate);
+
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                hostService.invalidateServiceContext(context);
+            }
+
+            s_logger.error("Unexpecpted exception ", e);
+
+            details = "CreatePrivateTemplateFromVolumeCommand exception: " + e.toString();
+            return new CopyCmdAnswer(details);
+        }
+    }
 
     private void writeMetaOvaForTemplate(String installFullPath, String ovfFilename, String vmdkFilename,
                                          String templateName, long diskSize) throws Exception {
@@ -927,7 +935,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
                     uniqeName,
                     nfsSvr.getUrl(), snapshot.getPath(),
                     template.getId()
-                    );
+            );
 
             TemplateObjectTO newTemplate = new TemplateObjectTO();
             newTemplate.setPath(result.first());
@@ -947,134 +955,134 @@ public class VmwareStorageProcessor implements StorageProcessor {
     }
 
     private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath,
-	        String secStorageUrl, String secStorageDir, String exportName,
-	        String workerVmName) throws Exception {
-
-	        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
-	        String exportPath =  secondaryMountPoint + "/" + secStorageDir + "/" + exportName;
-	        
-	        synchronized(exportPath.intern()) {
-	            if(!new File(exportPath).exists()) {
-	                Script command = new Script(false, "mkdir", _timeout, s_logger);
-	                command.add("-p");
-	                command.add(exportPath);
-	                if(command.execute() != null)
-	                    throw new Exception("unable to prepare snapshot backup directory");
-	            }
-	        }
-
-	        VirtualMachineMO clonedVm = null;
-	        try {
-
-	            Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
-	            if(volumeDeviceInfo == null) {
-	                String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
-	                s_logger.error(msg);
-	                throw new Exception(msg);
-	            }
-
-	            // 4 MB is the minimum requirement for VM memory in VMware
-	            vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
-	                VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
-	            clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
-	            if(clonedVm == null) {
-	                String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
-	                s_logger.error(msg);
-	                throw new Exception(msg);
-	            }
-
-	            clonedVm.exportVm(exportPath, exportName, false, false);
-	        } finally {
-	            if(clonedVm != null) {
-	                clonedVm.detachAllDisks();
-	                clonedVm.destroy();
-	            }
-	        }
-	    }
-
-	
-	private String backupSnapshotToSecondaryStorage(VirtualMachineMO vmMo, String installPath,
-	        String volumePath, String snapshotUuid, String secStorageUrl,
-	        String prevSnapshotUuid, String prevBackupUuid, String workerVmName) throws Exception {
-
-	        String backupUuid = UUID.randomUUID().toString();
-	        exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl,
-	        		installPath, backupUuid, workerVmName);
-	        return backupUuid + "/" + backupUuid;
-	    }
-	@Override
-	public Answer backupSnapshot(CopyCommand cmd) {
-		SnapshotObjectTO srcSnapshot = (SnapshotObjectTO)cmd.getSrcTO();
-		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcSnapshot.getDataStore();
-		SnapshotObjectTO destSnapshot = (SnapshotObjectTO)cmd.getDestTO();
-		DataStoreTO destStore = destSnapshot.getDataStore();
-		if (!(destStore instanceof NfsTO)) {
-			return new CopyCmdAnswer("unsupported protocol");
-		}
-
-		NfsTO destNfsStore = (NfsTO)destStore;
-
-
-		String secondaryStorageUrl = destNfsStore.getUrl();
-		String snapshotUuid = srcSnapshot.getPath();
-		String prevSnapshotUuid = srcSnapshot.getParentSnapshotPath();
-		String prevBackupUuid = destSnapshot.getParentSnapshotPath();
-		VirtualMachineMO workerVm=null;
-		String workerVMName = null;
-		String volumePath = srcSnapshot.getVolume().getPath();
-		ManagedObjectReference morDs = null;
-		DatastoreMO dsMo=null;
-
-		// By default assume failure
-		String details = null;
-		boolean success = false;
-		String snapshotBackupUuid = null;
-
-		VmwareContext context = hostService.getServiceContext(cmd);
-		VirtualMachineMO vmMo = null;
-		String vmName = srcSnapshot.getVmName();
-		try {
-			VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
-			morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
-
-			try {
-				vmMo = hyperHost.findVmOnHyperHost(vmName);
-				if (vmMo == null) {
-					if(s_logger.isDebugEnabled())
-						s_logger.debug("Unable to find owner VM for BackupSnapshotCommand on host " + hyperHost.getHyperHostName() + ", will try within datacenter");
-
-					vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
-					if(vmMo == null) {
-						dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
-
-						workerVMName = hostService.getWorkerName(context, cmd, 0);
-
-						// attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
-						if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier.OTHER_GUEST.value(), morDs, false)) {
-							String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
-							s_logger.error(msg);
-							throw new Exception(msg);
-						}
-						vmMo = hyperHost.findVmOnHyperHost(workerVMName);
-						if (vmMo == null) {
-							throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
-						}
-						workerVm = vmMo;
-
-						// attach volume to worker VM
-						String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
-						vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
-					}
-				}
-
-				if (!vmMo.createSnapshot(snapshotUuid, "Snapshot taken for " + srcSnapshot.getName(), false, false)) {
-					throw new Exception("Failed to take snapshot " + srcSnapshot.getName() + " on vm: " + vmName);
-				}
-
-				snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, destSnapshot.getPath(), srcSnapshot.getVolume().getPath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid,
-						hostService.getWorkerName(context, cmd, 1));
-
-				success = (snapshotBackupUuid != null);
+                                                String secStorageUrl, String secStorageDir, String exportName,
+                                                String workerVmName) throws Exception {
+
+        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
+        String exportPath =  secondaryMountPoint + "/" + secStorageDir + "/" + exportName;
+
+        synchronized(exportPath.intern()) {
+            if(!new File(exportPath).exists()) {
+                Script command = new Script(false, "mkdir", _timeout, s_logger);
+                command.add("-p");
+                command.add(exportPath);
+                if(command.execute() != null)
+                    throw new Exception("unable to prepare snapshot backup directory");
+            }
+        }
+
+        VirtualMachineMO clonedVm = null;
+        try {
+
+            Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
+            if(volumeDeviceInfo == null) {
+                String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+
+            // 4 MB is the minimum requirement for VM memory in VMware
+            vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
+                    VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
+            clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
+            if(clonedVm == null) {
+                String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+
+            clonedVm.exportVm(exportPath, exportName, false, false);
+        } finally {
+            if(clonedVm != null) {
+                clonedVm.detachAllDisks();
+                clonedVm.destroy();
+            }
+        }
+    }
+
+
+    private String backupSnapshotToSecondaryStorage(VirtualMachineMO vmMo, String installPath,
+                                                    String volumePath, String snapshotUuid, String secStorageUrl,
+                                                    String prevSnapshotUuid, String prevBackupUuid, String workerVmName) throws Exception {
+
+        String backupUuid = UUID.randomUUID().toString();
+        exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl,
+                installPath, backupUuid, workerVmName);
+        return backupUuid + "/" + backupUuid;
+    }
+    @Override
+    public Answer backupSnapshot(CopyCommand cmd) {
+        SnapshotObjectTO srcSnapshot = (SnapshotObjectTO)cmd.getSrcTO();
+        PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcSnapshot.getDataStore();
+        SnapshotObjectTO destSnapshot = (SnapshotObjectTO)cmd.getDestTO();
+        DataStoreTO destStore = destSnapshot.getDataStore();
+        if (!(destStore instanceof NfsTO)) {
+            return new CopyCmdAnswer("unsupported protocol");
+        }
+
+        NfsTO destNfsStore = (NfsTO)destStore;
+
+
+        String secondaryStorageUrl = destNfsStore.getUrl();
+        String snapshotUuid = srcSnapshot.getPath();
+        String prevSnapshotUuid = srcSnapshot.getParentSnapshotPath();
+        String prevBackupUuid = destSnapshot.getParentSnapshotPath();
+        VirtualMachineMO workerVm=null;
+        String workerVMName = null;
+        String volumePath = srcSnapshot.getVolume().getPath();
+        ManagedObjectReference morDs = null;
+        DatastoreMO dsMo=null;
+
+        // By default assume failure
+        String details = null;
+        boolean success = false;
+        String snapshotBackupUuid = null;
+
+        VmwareContext context = hostService.getServiceContext(cmd);
+        VirtualMachineMO vmMo = null;
+        String vmName = srcSnapshot.getVmName();
+        try {
+            VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+            morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+
+            try {
+                vmMo = hyperHost.findVmOnHyperHost(vmName);
+                if (vmMo == null) {
+                    if(s_logger.isDebugEnabled())
+                        s_logger.debug("Unable to find owner VM for BackupSnapshotCommand on host " + hyperHost.getHyperHostName() + ", will try within datacenter");
+
+                    vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
+                    if(vmMo == null) {
+                        dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
+
+                        workerVMName = hostService.getWorkerName(context, cmd, 0);
+
+                        // attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
+                        if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier.OTHER_GUEST.value(), morDs, false)) {
+                            String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
+                            s_logger.error(msg);
+                            throw new Exception(msg);
+                        }
+                        vmMo = hyperHost.findVmOnHyperHost(workerVMName);
+                        if (vmMo == null) {
+                            throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
+                        }
+                        workerVm = vmMo;
+
+                        // attach volume to worker VM
+                        String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
+                        vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
+                    }
+                }
+
+                if (!vmMo.createSnapshot(snapshotUuid, "Snapshot taken for " + srcSnapshot.getName(), false, false)) {
+                    throw new Exception("Failed to take snapshot " + srcSnapshot.getName() + " on vm: " + vmName);
+                }
+
+                snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, destSnapshot.getPath(), srcSnapshot.getVolume().getPath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid,
+                        hostService.getWorkerName(context, cmd, 1));
+
+                success = (snapshotBackupUuid != null);
 
                 if (!success) {
                     details = "Failed to backUp the snapshot with uuid: " + snapshotUuid + " to secondary storage.";
@@ -1085,40 +1093,40 @@ public class VmwareStorageProcessor implements StorageProcessor {
                     newSnapshot.setPath(destSnapshot.getPath() + "/" + snapshotBackupUuid);
                     return new CopyCmdAnswer(newSnapshot);
                 }
-			} finally {
-				if(vmMo != null){
-					ManagedObjectReference snapshotMor = vmMo.getSnapshotMor(snapshotUuid);
-					if (snapshotMor != null){
-						vmMo.removeSnapshot(snapshotUuid, false);
-					}
-				}
-
-				try {
-					if (workerVm != null) {
-						// detach volume and destroy worker vm
-						workerVm.detachAllDisks();
-						workerVm.destroy();
-					}
-				} catch (Throwable e) {
-					s_logger.warn("Failed to destroy worker VM: " + workerVMName);
-				}
-			}
-		} catch (Throwable e) {
-			if (e instanceof RemoteException) {
-				hostService.invalidateServiceContext(context);
-			}
-
-			s_logger.error("Unexpecpted exception ", e);
-
-			details = "BackupSnapshotCommand exception: " + e.toString();
-			return new CopyCmdAnswer(details);
-		}
-	}
-
-	@Override
-	public Answer attachIso(AttachCommand cmd) {
-		return this.attachIso(cmd.getDisk(), true, cmd.getVmName());
-	}
+            } finally {
+                if(vmMo != null){
+                    ManagedObjectReference snapshotMor = vmMo.getSnapshotMor(snapshotUuid);
+                    if (snapshotMor != null){
+                        vmMo.removeSnapshot(snapshotUuid, false);
+                    }
+                }
+
+                try {
+                    if (workerVm != null) {
+                        // detach volume and destroy worker vm
+                        workerVm.detachAllDisks();
+                        workerVm.destroy();
+                    }
+                } catch (Throwable e) {
+                    s_logger.warn("Failed to destroy worker VM: " + workerVMName);
+                }
+            }
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                hostService.invalidateServiceContext(context);
+            }
+
+            s_logger.error("Unexpecpted exception ", e);
+
+            details = "BackupSnapshotCommand exception: " + e.toString();
+            return new CopyCmdAnswer(details);
+        }
+    }
+
+    @Override
+    public Answer attachIso(AttachCommand cmd) {
+        return this.attachIso(cmd.getDisk(), true, cmd.getVmName());
+    }
 
     @Override
     public Answer attachVolume(AttachCommand cmd) {
@@ -1131,26 +1139,26 @@ public class VmwareStorageProcessor implements StorageProcessor {
         return attachVolume(cmd, disk, isAttach, isManaged, vmName, iScsiName, storageHost, storagePort, null, null, null, null);
     }
 
-	private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean isManaged, String vmName,
-	        String iScsiName, String storageHost, int storagePort, String initiatorUsername, String initiatorPassword,
-	        String targetUsername, String targetPassword) {
-
-		VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData();
-		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
-		try {
-			VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
-			VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
-			if (vmMo == null) {
-				String msg = "Unable to find the VM to execute AttachVolumeCommand, vmName: " + vmName;
-				s_logger.error(msg);
-				throw new Exception(msg);
-			}
+    private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean isManaged, String vmName,
+                                String iScsiName, String storageHost, int storagePort, String initiatorUsername, String initiatorPassword,
+                                String targetUsername, String targetPassword) {
+
+        VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData();
+        PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+        try {
+            VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
+            VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+            if (vmMo == null) {
+                String msg = "Unable to find the VM to execute AttachVolumeCommand, vmName: " + vmName;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
 
             ManagedObjectReference morDs = null;
 
             if (isAttach && isManaged) {
                 morDs = this.hostService.handleDatastoreAndVmdkAttach(cmd, iScsiName, storageHost, storagePort,
-                            initiatorUsername, initiatorPassword, targetUsername, targetPassword);
+                        initiatorUsername, initiatorPassword, targetUsername, targetPassword);
             }
             else {
                 morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(iScsiName) : primaryStore.getUuid());
@@ -1162,41 +1170,41 @@ public class VmwareStorageProcessor implements StorageProcessor {
                 throw new Exception(msg);
             }
 
-			DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs);
-			String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), isManaged ? dsMo.getName() : volumeTO.getPath());
+            DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs);
+            String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), isManaged ? dsMo.getName() : volumeTO.getPath());
 
             disk.setVdiUuid(datastoreVolumePath);
 
-			AttachAnswer answer = new AttachAnswer(disk);
-			if (isAttach) {
-				vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
-			} else {
-				vmMo.removeAllSnapshots();
-				vmMo.detachDisk(datastoreVolumePath, false);
+            AttachAnswer answer = new AttachAnswer(disk);
+            if (isAttach) {
+                vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
+            } else {
+                vmMo.removeAllSnapshots();
+                vmMo.detachDisk(datastoreVolumePath, false);
 
                 if (isManaged) {
                     this.hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort);
                 }
-			}
-
-			return answer;
-		} catch (Throwable e) {
-			if (e instanceof RemoteException) {
-				s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
-				this.hostService.invalidateServiceContext(null);
-			}
-
-			String msg = "AttachVolumeCommand failed due to " + VmwareHelper.getExceptionMessage(e);
-			s_logger.error(msg, e);
-			return new AttachAnswer(msg);
-		}
-	}
-	
-	  private static String getSecondaryDatastoreUUID(String storeUrl) {
-	        return UUID.nameUUIDFromBytes(storeUrl.getBytes()).toString();
-	    }
-
-	public synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception {
+            }
+
+            return answer;
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+                this.hostService.invalidateServiceContext(null);
+            }
+
+            String msg = "AttachVolumeCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+            s_logger.error(msg, e);
+            return new AttachAnswer(msg);
+        }
+    }
+
+    private static String getSecondaryDatastoreUUID(String storeUrl) {
+        return UUID.nameUUIDFromBytes(storeUrl.getBytes()).toString();
+    }
+
+    public synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception {
         String storeName = getSecondaryDatastoreUUID(storeUrl);
         URI uri = new URI(storeUrl);
 
@@ -1208,96 +1216,96 @@ public class VmwareStorageProcessor implements StorageProcessor {
 
         return morDatastore;
     }
-	private Answer attachIso(DiskTO disk, boolean isAttach, String vmName) {
-		
-
-	        try {
-	            VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
-	            VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
-	            if (vmMo == null) {
-	                String msg = "Unable to find VM in vSphere to execute AttachIsoCommand, vmName: " + vmName;
-	                s_logger.error(msg);
-	                throw new Exception(msg);
-	            }
-	            TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
-	            NfsTO nfsImageStore = (NfsTO)iso.getDataStore();
-	            String storeUrl = null;
-	            if (nfsImageStore != null)
-	                storeUrl = nfsImageStore.getUrl();
-	            if (storeUrl == null) {
-	                if (!iso.getName().equalsIgnoreCase("vmware-tools.iso")) {
-	                    String msg = "ISO store root url is not found in AttachIsoCommand";
-	                    s_logger.error(msg);
-	                    throw new Exception(msg);
-	                } else {
-	                    if (isAttach) {
-	                        vmMo.mountToolsInstaller();
-	                    } else {
-	                        try{
-	                            vmMo.unmountToolsInstaller();
-	                        }catch(Throwable e){
-	                            vmMo.detachIso(null);
-	                        }
-	                    }
-
-	                    return new AttachAnswer(disk);
-	                }
-	            }
-
-	            ManagedObjectReference morSecondaryDs = prepareSecondaryDatastoreOnHost(storeUrl);
-	            String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
-	            if (!isoPath.startsWith(storeUrl)) {
-	                assert (false);
-	                String msg = "ISO path does not start with the secondary storage root";
-	                s_logger.error(msg);
-	                throw new Exception(msg);
-	            }
-
-	            int isoNameStartPos = isoPath.lastIndexOf('/');
-	            String isoFileName = isoPath.substring(isoNameStartPos + 1);
-	            String isoStorePathFromRoot = isoPath.substring(storeUrl.length(), isoNameStartPos);
-
-	            // TODO, check if iso is already attached, or if there is a previous
-	            // attachment
-	            DatastoreMO secondaryDsMo = new DatastoreMO(this.hostService.getServiceContext(null), morSecondaryDs);
-	            String storeName = secondaryDsMo.getName();
-	            String isoDatastorePath = String.format("[%s] %s%s", storeName, isoStorePathFromRoot, isoFileName);
-
-	            if (isAttach) {
-	                vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false);
-	            } else {
-	                vmMo.detachIso(isoDatastorePath);
-	            }
-
-	            return new AttachAnswer(disk);
-	        } catch (Throwable e) {
-	            if (e instanceof RemoteException) {
-	                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
-	                this.hostService.invalidateServiceContext(null);
-	            }
-
-	            if(isAttach) {
-	                String msg = "AttachIsoCommand(attach) failed due to " + VmwareHelper.getExceptionMessage(e);
-	                s_logger.error(msg, e);
-	                return new AttachAnswer(msg);
-	            } else {
-	                String msg = "AttachIsoCommand(detach) failed due to " + VmwareHelper.getExceptionMessage(e);
-	                s_logger.warn(msg, e);
-	                return new AttachAnswer(msg);
-	            }
-	        }
-	}
-	@Override
-	public Answer dettachIso(DettachCommand cmd) {
-		return this.attachIso(cmd.getDisk(), false, cmd.getVmName());
-	}
-
-	@Override
-	public Answer dettachVolume(DettachCommand cmd) {
-		return this.attachVolume(cmd, cmd.getDisk(), false, cmd.isManaged(), cmd.getVmName(), cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort());
-	}
-
-	protected VirtualMachineMO prepareVolumeHostDummyVm(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception {
+    private Answer attachIso(DiskTO disk, boolean isAttach, String vmName) {
+
+
+        try {
+            VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
+            VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+            if (vmMo == null) {
+                String msg = "Unable to find VM in vSphere to execute AttachIsoCommand, vmName: " + vmName;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+            TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
+            NfsTO nfsImageStore = (NfsTO)iso.getDataStore();
+            String storeUrl = null;
+            if (nfsImageStore != null)
+                storeUrl = nfsImageStore.getUrl();
+            if (storeUrl == null) {
+                if (!iso.getName().equalsIgnoreCase("vmware-tools.iso")) {
+                    String msg = "ISO store root url is not found in AttachIsoCommand";
+                    s_logger.error(msg);
+                    throw new Exception(msg);
+                } else {
+                    if (isAttach) {
+                        vmMo.mountToolsInstaller();
+                    } else {
+                        try{
+                            vmMo.unmountToolsInstaller();
+                        }catch(Throwable e){
+                            vmMo.detachIso(null);
+                        }
+                    }
+
+                    return new AttachAnswer(disk);
+                }
+            }
+
+            ManagedObjectReference morSecondaryDs = prepareSecondaryDatastoreOnHost(storeUrl);
+            String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
+            if (!isoPath.startsWith(storeUrl)) {
+                assert (false);
+                String msg = "ISO path does not start with the secondary storage root";
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+
+            int isoNameStartPos = isoPath.lastIndexOf('/');
+            String isoFileName = isoPath.substring(isoNameStartPos + 1);
+            String isoStorePathFromRoot = isoPath.substring(storeUrl.length(), isoNameStartPos);
+
+            // TODO, check if iso is already attached, or if there is a previous
+            // attachment
+            DatastoreMO secondaryDsMo = new DatastoreMO(this.hostService.getServiceContext(null), morSecondaryDs);
+            String storeName = secondaryDsMo.getName();
+            String isoDatastorePath = String.format("[%s] %s%s", storeName, isoStorePathFromRoot, isoFileName);
+
+            if (isAttach) {
+                vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false);
+            } else {
+                vmMo.detachIso(isoDatastorePath);
+            }
+
+            return new AttachAnswer(disk);
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+                this.hostService.invalidateServiceContext(null);
+            }
+
+            if(isAttach) {
+                String msg = "AttachIsoCommand(attach) failed due to " + VmwareHelper.getExceptionMessage(e);
+                s_logger.error(msg, e);
+                return new AttachAnswer(msg);
+            } else {
+                String msg = "AttachIsoCommand(detach) failed due to " + VmwareHelper.getExceptionMessage(e);
+                s_logger.warn(msg, e);
+                return new AttachAnswer(msg);
+            }
+        }
+    }
+    @Override
+    public Answer dettachIso(DettachCommand cmd) {
+        return this.attachIso(cmd.getDisk(), false, cmd.getVmName());
+    }
+
+    @Override
+    public Answer dettachVolume(DettachCommand cmd) {
+        return this.attachVolume(cmd, cmd.getDisk(), false, cmd.isManaged(), cmd.getVmName(), cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort());
+    }
+
+    protected VirtualMachineMO prepareVolumeHostDummyVm(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception {
         assert (hyperHost != null);
 
         VirtualMachineMO vmMo = null;
@@ -1324,78 +1332,78 @@ public class VmwareStorageProcessor implements StorageProcessor {
         vmMo = hyperHost.findVmOnHyperHost(vmName);
         return vmMo;
     }
-	@Override
-	public Answer createVolume(CreateObjectCommand cmd) {
-
-		VolumeObjectTO volume = (VolumeObjectTO)cmd.getData();
-		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
-       
-		try {
-			VmwareContext context = this.hostService.getServiceContext(null);
-			VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
-			DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
-
-			ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
-			if (morDatastore == null)
-				throw new Exception("Unable to find datastore in vSphere");
-
-			DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
-			// create data volume
-			VirtualMachineMO vmMo = null;
-			String volumeUuid = UUID.randomUUID().toString().replace("-", "");
-			String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
-			String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
-			try {
-				vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
-				if (vmMo == null) {
-					throw new Exception("Unable to create a dummy VM for volume creation");
-				}
-
-				synchronized (this) {
-					// s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
-					VmwareHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
-
-					vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, vmMo.getScsiDeviceControllerKey());
-					vmMo.detachDisk(volumeDatastorePath, false);
-				}
-
-				VolumeObjectTO newVol = new VolumeObjectTO();
-				newVol.setPath(volumeUuid);
-				newVol.setSize(volume.getSize() / (1024L * 1024L));
-				return new CreateObjectAnswer(newVol);
-			} finally {
-				s_logger.info("Destroy dummy VM after volume creation");
-				vmMo.detachAllDisks();
-				vmMo.destroy();
-			}
-
-		} catch (Throwable e) {
-			if (e instanceof RemoteException) {
-				s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
-				this.hostService.invalidateServiceContext(null);
-			}
-
-			String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
-			s_logger.error(msg, e);
-			return new CreateObjectAnswer(e.toString());
-		}
-	}
-
-	@Override
-	public Answer createSnapshot(CreateObjectCommand cmd) {
-		// snapshot operation (create or destroy) is handled inside BackupSnapshotCommand(), we just fake
-		// a success return here
-		String snapshotUUID = UUID.randomUUID().toString();
-		SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
-		newSnapshot.setPath(snapshotUUID);
-		return new CreateObjectAnswer(newSnapshot);
-	}
-
-	@Override
-	public Answer deleteVolume(DeleteCommand cmd) {
-		if (s_logger.isInfoEnabled()) {
-			s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
-		}
+    @Override
+    public Answer createVolume(CreateObjectCommand cmd) {
+
+        VolumeObjectTO volume = (VolumeObjectTO)cmd.getData();
+        PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+
+        try {
+            VmwareContext context = this.hostService.getServiceContext(null);
+            VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
+            DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
+
+            ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+            if (morDatastore == null)
+                throw new Exception("Unable to find datastore in vSphere");
+
+            DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
+            // create data volume
+            VirtualMachineMO vmMo = null;
+            String volumeUuid = UUID.randomUUID().toString().replace("-", "");
+            String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
+            String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
+            try {
+                vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
+                if (vmMo == null) {
+                    throw new Exception("Unable to create a dummy VM for volume creation");
+                }
+
+                synchronized (this) {
+                    // s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
+                    VmwareHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
+
+                    vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, vmMo.getScsiDeviceControllerKey());
+                    vmMo.detachDisk(volumeDatastorePath, false);
+                }
+
+                VolumeObjectTO newVol = new VolumeObjectTO();
+                newVol.setPath(volumeUuid);
+                newVol.setSize(volume.getSize() / (1024L * 1024L));
+                return new CreateObjectAnswer(newVol);
+            } finally {
+                s_logger.info("Destroy dummy VM after volume creation");
+                vmMo.detachAllDisks();
+                vmMo.destroy();
+            }
+
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+                this.hostService.invalidateServiceContext(null);
+            }
+
+            String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+            s_logger.error(msg, e);
+            return new CreateObjectAnswer(e.toString());
+        }
+    }
+
+    @Override
+    public Answer createSnapshot(CreateObjectCommand cmd) {
+        // snapshot operation (create or destroy) is handled inside BackupSnapshotCommand(), we just fake
+        // a success return here
+        String snapshotUUID = UUID.randomUUID().toString();
+        SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+        newSnapshot.setPath(snapshotUUID);
+        return new CreateObjectAnswer(newSnapshot);
+    }
+
+    @Override
+    public Answer deleteVolume(DeleteCommand cmd) {
+        if (s_logger.isInfoEnabled()) {
+            s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
+        }
 
 		/*
 		 * DestroyCommand content example
@@ -1409,258 +1417,262 @@ public class VmwareStorageProcessor implements StorageProcessor {
 		 * "poolId":0,"deviceId":0 } }
 		 */
 
-		try {
-			VmwareContext context = this.hostService.getServiceContext(null);
-			VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
-			VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
-			PrimaryDataStoreTO store = (PrimaryDataStoreTO)vol.getDataStore();
-
-			ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
-			if (morDs == null) {
-				String msg = "Unable to find datastore based on volume mount point " + store.getPath();
-				s_logger.error(msg);
-				throw new Exception(msg);
-			}
-
-			DatastoreMO dsMo = new DatastoreMO(context, morDs);
-
-			ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
-			ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
-			ClusterMO clusterMo = new ClusterMO(context, morCluster);
-
-			if (vol.getVolumeType() == Volume.Type.ROOT) {
-				String vmName = vol.getVmName();
-				if (vmName != null) {
-					VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vmName);
-					if (vmMo != null) {
-						if (s_logger.isInfoEnabled()) {
-							s_logger.info("Destroy root volume and VM itself. vmName " + vmName);
-						}
-
-						HostMO hostMo = vmMo.getRunningHost();
-						List<NetworkDetails> networks = vmMo.getNetworksWithDetails();
-
-						// tear down all devices first before we destroy the VM to avoid accidently delete disk backing files
-						if (this.resource.getVmState(vmMo) != State.Stopped)
-							vmMo.safePowerOff(_shutdown_waitMs);
-						vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
-						vmMo.destroy();
-
-						for (NetworkDetails netDetails : networks) {
-							if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) {
-								if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) {
-									this.resource.cleanupNetwork(hostMo, netDetails);
-								}
-							}
-						}
-					}
-
-					if (s_logger.isInfoEnabled())
-						s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
-					dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
-
-					// root volume may be created via linked-clone, delete the delta disk as well
-					if (_fullCloneFlag) {
-						if (s_logger.isInfoEnabled()) {
-							s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
-						}
-						dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
-					} else {
-						if (s_logger.isInfoEnabled()) {
-							s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk");
-						}
-						dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true);
-					}
-					return new Answer(cmd, true, "Success");
-				}
-
-				if (s_logger.isInfoEnabled()) {
-					s_logger.info("Destroy root volume directly from datastore");
-				}
-			} else {
-				// evitTemplate will be converted into DestroyCommand, test if we are running in this case
-				VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vol.getPath());
-				if (vmMo != null) {
-					if (s_logger.isInfoEnabled())
-						s_logger.info("Destroy template volume " + vol.getPath());
-
-					vmMo.destroy();
-					return new Answer(cmd, true, "Success");
-				}
-			}
-
-			String chainInfo = vol.getChainInfo();
-			if (chainInfo != null && !chainInfo.isEmpty()) {
-				s_logger.info("Destroy volume by chain info: " + chainInfo);
-				String[] diskChain = _gson.fromJson(chainInfo, String[].class);
-
-				if (diskChain != null && diskChain.length > 0) {
-					for (String backingName : diskChain) {
-						if (s_logger.isInfoEnabled()) {
-							s_logger.info("Delete volume backing file: " + backingName);
-						}
-						dsMo.deleteFile(backingName, morDc, true);
-					}
-				} else {
-					if (s_logger.isInfoEnabled()) {
-						s_logger.info("Empty disk chain info, fall back to try to delete by original backing file name");
-					}
-					dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
-
-					if (s_logger.isInfoEnabled()) {
-						s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
-					}
-					dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
-				}
-			} else {
-				if (s_logger.isInfoEnabled()) {
-					s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
-				}
-				dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
-
-				if (s_logger.isInfoEnabled()) {
-					s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
-				}
-				dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
-			}
-
-			return new Answer(cmd, true, "Success");
-		} catch (Throwable e) {
-			if (e instanceof RemoteException) {
-				s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
-				this.hostService.invalidateServiceContext(null);
-			}
-
-			String msg = "DestroyCommand failed due to " + VmwareHelper.getExceptionMessage(e);
-			s_logger.error(msg, e);
-			return new Answer(cmd, false, msg);
-		}
-	}
-	
-	 private Long restoreVolumeFromSecStorage(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
-		        String secStorageUrl, String secStorageDir, String backupName) throws Exception {
-
-		        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
-		        String srcOVAFileName = secondaryMountPoint + "/" +  secStorageDir + "/"
-		            + backupName + "." + ImageFormat.OVA.getFileExtension();
-		        String snapshotDir = "";
-		        if (backupName.contains("/")){
-		            snapshotDir = backupName.split("/")[0];
-		        }
-
-		        File ovafile = new File(srcOVAFileName);
-		        String srcOVFFileName = secondaryMountPoint + "/" +  secStorageDir + "/"
-		                + backupName + ".ovf";
-		        File ovfFile = new File(srcOVFFileName);
-		        // String srcFileName = getOVFFilePath(srcOVAFileName);
-		        if (!ovfFile.exists()) {
-		            srcOVFFileName = getOVFFilePath(srcOVAFileName);
-		            if(srcOVFFileName == null && ovafile.exists() ) {  // volss: ova file exists; o/w can't do tar
-		                Script command = new Script("tar", 0, s_logger);
-		                command.add("--no-same-owner");
-		                command.add("-xf", srcOVAFileName);
-		                command.setWorkDir(secondaryMountPoint + "/" +  secStorageDir + "/" + snapshotDir);
-		                s_logger.info("Executing command: " + command.toString());
-		                String result = command.execute();
-		                if(result != null) {
-		                        String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
-		                        s_logger.error(msg);
-		                        throw new Exception(msg);
-		                }
-		            } else {
-		               String msg = "Unable to find snapshot OVA file at: " + srcOVAFileName;
-		               s_logger.error(msg);
-		               throw new Exception(msg);
-		           }
-
-		           srcOVFFileName = getOVFFilePath(srcOVAFileName);
-		        }
-		        if(srcOVFFileName == null) {
-		            String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
-		            s_logger.error(msg);
-		            throw new Exception(msg);
-		        }
-
-		        VirtualMachineMO clonedVm = null;
-		        try {
-		            hyperHost.importVmFromOVF(srcOVFFileName, newVolumeName, primaryDsMo, "thin");
-		            clonedVm = hyperHost.findVmOnHyperHost(newVolumeName);
-		            if(clonedVm == null)
-		                throw new Exception("Unable to create container VM for volume creation");
-
-		            clonedVm.moveAllVmDiskFiles(primaryDsMo, "", false);
-		            clonedVm.detachAllDisks();
-		            return _storage.getSize(srcOVFFileName);
-		        } finally {
-		            if(clonedVm != null) {
-		                clonedVm.detachAllDisks();
-		                clonedVm.destroy();
-		            }
-		        }
-		    }
-
-	@Override
-	public Answer createVolumeFromSnapshot(CopyCommand cmd) {
-		DataTO srcData = cmd.getSrcTO();
-		SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData;
-		DataTO destData = cmd.getDestTO();
-		PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();
-		DataStoreTO imageStore = srcData.getDataStore();
-
-
-		if (!(imageStore instanceof NfsTO)) {
-			return new CopyCmdAnswer("unsupported protocol");
-		}
-
-		NfsTO nfsImageStore = (NfsTO)imageStore;
-		String primaryStorageNameLabel = pool.getUuid();
-	
+        try {
+            VmwareContext context = this.hostService.getServiceContext(null);
+            VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
+            VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
+            PrimaryDataStoreTO store = (PrimaryDataStoreTO)vol.getDataStore();
+
+            ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
+            if (morDs == null) {
+                String msg = "Unable to find datastore based on volume mount point " + store.getPath();
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+
+            DatastoreMO dsMo = new DatastoreMO(context, morDs);
+
+            ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
+            ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
+            ClusterMO clusterMo = new ClusterMO(context, morCluster);
+
+            if (vol.getVolumeType() == Vol

<TRUNCATED>

[2/2] git commit: updated refs/heads/4.2 to 6533e65

Posted by ed...@apache.org.
CLOUDSTACK-3107: fix attach upload volume


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

Branch: refs/heads/4.2
Commit: 6533e6559b1221e08cbf3a385a2414d7d619e1e8
Parents: 0f76572
Author: Edison Su <su...@gmail.com>
Authored: Mon Jul 29 18:58:42 2013 -0700
Committer: Edison Su <su...@gmail.com>
Committed: Mon Jul 29 18:59:10 2013 -0700

----------------------------------------------------------------------
 .../com/cloud/hypervisor/guru/VMwareGuru.java   |   11 +-
 .../resource/VmwareStorageProcessor.java        | 2104 +++++++++---------
 2 files changed, 1067 insertions(+), 1048 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6533e655/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 d1392c4..e9495dc 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -307,10 +307,17 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
             DataTO destData = cpyCommand.getDestTO();
             DataStoreTO destStoreTO = destData.getDataStore();
 
-            if (!(HypervisorType.VMware == srcData.getHypervisorType() ||
+            if ((HypervisorType.VMware == srcData.getHypervisorType() ||
                     HypervisorType.VMware == destData.getHypervisorType()
             )) {
-                return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
+                needDelegation = true;
+            }
+
+            if (srcData.getObjectType() == DataObjectType.VOLUME) {
+                VolumeObjectTO volumeObjectTO = (VolumeObjectTO)srcData;
+                if (Storage.ImageFormat.OVA == volumeObjectTO.getFormat()) {
+                    needDelegation = true;
+                }
             }
 
             if (destData.getObjectType() == DataObjectType.VOLUME && destStoreTO.getRole() == DataStoreRole.Primary &&