You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2013/08/15 03:13:13 UTC

[1/2] git commit: updated refs/heads/master to c675f82

Updated Branches:
  refs/heads/master 7dd653d24 -> c675f826e


CLOUDSTACK-2583: [Object_Store_Refactor] Failed to create snapshot from
root disk of a guest VM.


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

Branch: refs/heads/master
Commit: 8a104b95d5e06a3efc88dccbe17e1c60970c3ef9
Parents: 7dd653d
Author: Min Chen <mi...@citrix.com>
Authored: Wed Aug 14 17:58:25 2013 -0700
Committer: Min Chen <mi...@citrix.com>
Committed: Wed Aug 14 18:02:25 2013 -0700

----------------------------------------------------------------------
 .../xen/resource/XenServerStorageProcessor.java | 314 ++++++++++---------
 1 file changed, 158 insertions(+), 156 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8a104b95/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
index 634759d..60f1ef9 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
@@ -35,7 +35,6 @@ import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Storage.StoragePoolType;
 import com.cloud.storage.resource.StorageProcessor;
 import com.cloud.utils.S3Utils;
-import com.cloud.utils.StringUtils;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.storage.encoding.DecodedDataObject;
 import com.cloud.utils.storage.encoding.DecodedDataStore;
@@ -68,7 +67,6 @@ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
 import org.apache.cloudstack.storage.to.VolumeObjectTO;
-import org.apache.cloudstack.storage.to.VolumeObjectTO;
 import org.apache.log4j.Logger;
 import org.apache.xmlrpc.XmlRpcException;
 
@@ -101,15 +99,15 @@ public class XenServerStorageProcessor implements StorageProcessor {
 
         String isoURL = null;
         if (store == null) {
-        	TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
-        	isoURL = iso.getName();
+            TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
+            isoURL = iso.getName();
         } else {
-        	if (!(store instanceof NfsTO)) {
-        		s_logger.debug("Can't attach a iso which is not created on nfs: ");
-        		return new AttachAnswer("Can't attach a iso which is not created on nfs: ");
-        	}
-        	NfsTO nfsStore = (NfsTO)store;
-        	isoURL = nfsStore.getUrl() + File.separator + data.getPath();
+            if (!(store instanceof NfsTO)) {
+                s_logger.debug("Can't attach a iso which is not created on nfs: ");
+                return new AttachAnswer("Can't attach a iso which is not created on nfs: ");
+            }
+            NfsTO nfsStore = (NfsTO)store;
+            isoURL = nfsStore.getUrl() + File.separator + data.getPath();
         }
 
         String vmName = cmd.getVmName();
@@ -250,15 +248,15 @@ public class XenServerStorageProcessor implements StorageProcessor {
 
         String isoURL = null;
         if (store == null) {
-        	TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
-        	isoURL = iso.getName();
+            TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
+            isoURL = iso.getName();
         } else {
-        	if (!(store instanceof NfsTO)) {
-        		s_logger.debug("Can't attach a iso which is not created on nfs: ");
-        		return new AttachAnswer("Can't attach a iso which is not created on nfs: ");
-        	}
-        	NfsTO nfsStore = (NfsTO)store;
-        	isoURL = nfsStore.getUrl() + File.separator + data.getPath();
+            if (!(store instanceof NfsTO)) {
+                s_logger.debug("Can't attach a iso which is not created on nfs: ");
+                return new AttachAnswer("Can't attach a iso which is not created on nfs: ");
+            }
+            NfsTO nfsStore = (NfsTO)store;
+            isoURL = nfsStore.getUrl() + File.separator + data.getPath();
         }
 
         try {
@@ -443,7 +441,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
 
     @Override
     public Answer deleteVolume(DeleteCommand cmd) {
-    	DataTO volume = cmd.getData();
+        DataTO volume = cmd.getData();
         Connection conn = hypervisorResource.getConnection();
         String errorMsg = null;
         try {
@@ -718,7 +716,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
                 try {
                     vdi.destroy(conn);
                 } catch (BadServerResponse e) {
-                   s_logger.debug("Failed to cleanup newly created vdi");
+                    s_logger.debug("Failed to cleanup newly created vdi");
                 } catch (XenAPIException e) {
                     s_logger.debug("Failed to cleanup newly created vdi");
                 } catch (XmlRpcException e) {
@@ -831,9 +829,9 @@ public class XenServerStorageProcessor implements StorageProcessor {
 
     @Override
     public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
-    	DataTO srcData = cmd.getSrcTO();
-    	DataTO destData = cmd.getDestTO();
-    	int wait = cmd.getWait();
+        DataTO srcData = cmd.getSrcTO();
+        DataTO destData = cmd.getDestTO();
+        int wait = cmd.getWait();
         DataStoreTO srcStore = srcData.getDataStore();
         try {
             if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) {
@@ -889,33 +887,33 @@ public class XenServerStorageProcessor implements StorageProcessor {
 
     @Override
     public Answer createVolume(CreateObjectCommand cmd) {
-    	DataTO data = cmd.getData();
-    	VolumeObjectTO volume = (VolumeObjectTO)data;
-
-    	try {
-    		Connection conn = hypervisorResource.getConnection();
-    		PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore();
-    		SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
-    		VDI.Record vdir = new VDI.Record();
-    		vdir.nameLabel = volume.getName();
-    		vdir.SR = poolSr;
-    		vdir.type = Types.VdiType.USER;
-
-    		vdir.virtualSize = volume.getSize();
-    		VDI vdi;
-
-    		vdi = VDI.create(conn, vdir);
-    		vdir = vdi.getRecord(conn);
-    		VolumeObjectTO newVol = new VolumeObjectTO();
-    		newVol.setName(vdir.nameLabel);
-    		newVol.setSize(vdir.virtualSize);
-    		newVol.setPath(vdir.uuid);
-
-    		return new CreateObjectAnswer(newVol);
-    	} catch (Exception e) {
-    		s_logger.debug("create volume failed: " + e.toString());
-    		return new CreateObjectAnswer(e.toString());
-    	}
+        DataTO data = cmd.getData();
+        VolumeObjectTO volume = (VolumeObjectTO)data;
+
+        try {
+            Connection conn = hypervisorResource.getConnection();
+            PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore();
+            SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
+            VDI.Record vdir = new VDI.Record();
+            vdir.nameLabel = volume.getName();
+            vdir.SR = poolSr;
+            vdir.type = Types.VdiType.USER;
+
+            vdir.virtualSize = volume.getSize();
+            VDI vdi;
+
+            vdi = VDI.create(conn, vdir);
+            vdir = vdi.getRecord(conn);
+            VolumeObjectTO newVol = new VolumeObjectTO();
+            newVol.setName(vdir.nameLabel);
+            newVol.setSize(vdir.virtualSize);
+            newVol.setPath(vdir.uuid);
+
+            return new CreateObjectAnswer(newVol);
+        } catch (Exception e) {
+            s_logger.debug("create volume failed: " + e.toString());
+            return new CreateObjectAnswer(e.toString());
+        }
     }
 
     @Override
@@ -1063,15 +1061,14 @@ public class XenServerStorageProcessor implements StorageProcessor {
         return lfilename;
     }
 
-    private boolean backupSnapshotToS3(final Connection connection,
-                                       final S3TO s3, final String srUuid, final String snapshotUuid,
-                                       final Boolean iSCSIFlag, final int wait) {
+    private String backupSnapshotToS3(final Connection connection, final S3TO s3, final String srUuid, final String folder, final String snapshotUuid,
+            final Boolean iSCSIFlag, final int wait) {
 
         final String filename = iSCSIFlag ? "VHD-" + snapshotUuid
                 : snapshotUuid + ".vhd";
         final String dir = (iSCSIFlag ? "/dev/VG_XenStorage-"
                 : "/var/run/sr-mount/") + srUuid;
-        final String key = String.format("/snapshots/%1$s", snapshotUuid);
+        final String key = folder + "/" + filename; // String.format("/snapshots/%1$s", snapshotUuid);
 
         try {
 
@@ -1083,14 +1080,15 @@ public class XenServerStorageProcessor implements StorageProcessor {
                     dir + "/" + filename, "iSCSIFlag",
                     iSCSIFlag.toString(), "bucket", s3.getBucketName(),
                     "key", key, "https", s3.isHttps() != null ? s3.isHttps().toString()
-                    : "null"));
+                            : "null"));
             final String result = hypervisorResource.callHostPluginAsync(connection, "s3xen",
                     "s3", wait,
                     parameters.toArray(new String[parameters.size()]));
 
             if (result != null && result.equals("true")) {
-                return true;
+                return key;
             }
+            return null;
 
         } catch (Exception e) {
             s_logger.error(String.format(
@@ -1098,7 +1096,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
                     snapshotUuid, e.toString()), e);
         }
 
-        return false;
+        return null;
 
     }
 
@@ -1265,12 +1263,14 @@ public class XenServerStorageProcessor implements StorageProcessor {
 
                     } else if (destStore instanceof S3TO) {
                         try {
-                            backupSnapshotToS3(conn, (S3TO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, isISCSI, wait);
-                            snapshotBackupUuid = snapshotBackupUuid + ".vhd";
+                            finalPath = backupSnapshotToS3(conn, (S3TO) destStore, snapshotSr.getUuid(conn), folder, snapshotBackupUuid, isISCSI, wait);
+                            if (finalPath == null) {
+                                throw new CloudRuntimeException("S3 upload of snapshots " + snapshotBackupUuid + " failed");
+                            }
                         } finally {
                             deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid);
                         }
-                        finalPath = folder + File.separator + snapshotBackupUuid;
+                        // finalPath = folder + File.separator + snapshotBackupUuid;
                     } else {
                         finalPath = folder + File.separator + snapshotBackupUuid;
                     }
@@ -1287,11 +1287,13 @@ public class XenServerStorageProcessor implements StorageProcessor {
                     snapshotBackupUuid = swiftBackupSnapshot(conn, (SwiftTO)destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait);
                     finalPath = container + File.separator + snapshotBackupUuid;
                 } else if (destStore instanceof S3TO ) {
-                    backupSnapshotToS3(conn, (S3TO)destStore, primaryStorageSRUuid, snapshotPaUuid, isISCSI, wait);
-                    finalPath = folder + File.separator + snapshotPaUuid;
+                    finalPath = backupSnapshotToS3(conn, (S3TO) destStore, primaryStorageSRUuid, folder, snapshotPaUuid, isISCSI, wait);
+                    if (finalPath == null) {
+                        throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed");
+                    }
                 } else {
                     snapshotBackupUuid = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder,
-                             secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait);
+                            secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait);
 
                     finalPath = folder + File.separator + snapshotBackupUuid;
                 }
@@ -1398,97 +1400,97 @@ public class XenServerStorageProcessor implements StorageProcessor {
     }
 
     @Override
-	public Answer createVolumeFromSnapshot(CopyCommand cmd) {
-		Connection conn = this.hypervisorResource.getConnection();
-		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();
-		String secondaryStorageUrl = nfsImageStore.getUrl();
-		int wait = cmd.getWait();
-		boolean result = false;
-		// Generic error message.
-		String details = null;
-		String volumeUUID = null;
-
-		if (secondaryStorageUrl == null) {
-			details += " because the URL passed: " + secondaryStorageUrl + " is invalid.";
-			return new CopyCmdAnswer(details);
-		}
-		try {
-			SR primaryStorageSR = this.hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel);
-			if (primaryStorageSR == null) {
-				throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: "
-						+ primaryStorageNameLabel);
-			}
-			// Get the absolute path of the snapshot on the secondary storage.
-			String snapshotInstallPath = snapshot.getPath();
-			int index = snapshotInstallPath.lastIndexOf(File.separator);
-			String snapshotName = snapshotInstallPath.substring(index + 1);
-
-			if (!snapshotName.startsWith("VHD-") && !snapshotName.endsWith(".vhd")) {
-				snapshotInstallPath = snapshotInstallPath + ".vhd";
-			}
-			URI snapshotURI = new URI(secondaryStorageUrl + File.separator + snapshotInstallPath);
-			String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath();
-			String srUuid = primaryStorageSR.getUuid(conn);
-			volumeUUID = copy_vhd_from_secondarystorage(conn, snapshotPath, srUuid, wait);
-			result = true;
-			VDI volume = VDI.getByUuid(conn, volumeUUID);
-			VDI.Record vdir = volume.getRecord(conn);
-			VolumeObjectTO newVol = new VolumeObjectTO();
-			newVol.setPath(volumeUUID);
-			newVol.setSize(vdir.virtualSize);
-			return new CopyCmdAnswer(newVol);
-		} catch (XenAPIException e) {
-			details += " due to " + e.toString();
-			s_logger.warn(details, e);
-		} catch (Exception e) {
-			details += " due to " + e.getMessage();
-			s_logger.warn(details, e);
-		}
-		if (!result) {
-			// Is this logged at a higher level?
-			s_logger.error(details);
-		}
-
-		// In all cases return something.
-		return new CopyCmdAnswer(details);
-	}
-
-	@Override
-	public Answer deleteSnapshot(DeleteCommand cmd) {
-		SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData();
-		DataStoreTO store = snapshot.getDataStore();
-		if (store.getRole() == DataStoreRole.Primary) {
-			Connection conn = this.hypervisorResource.getConnection();
-			VDI snapshotVdi = getVDIbyUuid(conn, snapshot.getPath());
-			if (snapshotVdi == null) {
-				return new Answer(null);
-			}
-			String errMsg = null;
-			try {
-				this.deleteVDI(conn, snapshotVdi);
-			} catch (BadServerResponse e) {
-				s_logger.debug("delete snapshot failed:" + e.toString());
-				errMsg = e.toString();
-			} catch (XenAPIException e) {
-				s_logger.debug("delete snapshot failed:" + e.toString());
-				errMsg = e.toString();
-			} catch (XmlRpcException e) {
-				s_logger.debug("delete snapshot failed:" + e.toString());
-				errMsg = e.toString();
-			}
-			return new Answer(cmd, false, errMsg);
-		}
-		return new Answer(cmd, false, "unsupported storage type");
-	}
+    public Answer createVolumeFromSnapshot(CopyCommand cmd) {
+        Connection conn = this.hypervisorResource.getConnection();
+        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();
+        String secondaryStorageUrl = nfsImageStore.getUrl();
+        int wait = cmd.getWait();
+        boolean result = false;
+        // Generic error message.
+        String details = null;
+        String volumeUUID = null;
+
+        if (secondaryStorageUrl == null) {
+            details += " because the URL passed: " + secondaryStorageUrl + " is invalid.";
+            return new CopyCmdAnswer(details);
+        }
+        try {
+            SR primaryStorageSR = this.hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel);
+            if (primaryStorageSR == null) {
+                throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: "
+                        + primaryStorageNameLabel);
+            }
+            // Get the absolute path of the snapshot on the secondary storage.
+            String snapshotInstallPath = snapshot.getPath();
+            int index = snapshotInstallPath.lastIndexOf(File.separator);
+            String snapshotName = snapshotInstallPath.substring(index + 1);
+
+            if (!snapshotName.startsWith("VHD-") && !snapshotName.endsWith(".vhd")) {
+                snapshotInstallPath = snapshotInstallPath + ".vhd";
+            }
+            URI snapshotURI = new URI(secondaryStorageUrl + File.separator + snapshotInstallPath);
+            String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath();
+            String srUuid = primaryStorageSR.getUuid(conn);
+            volumeUUID = copy_vhd_from_secondarystorage(conn, snapshotPath, srUuid, wait);
+            result = true;
+            VDI volume = VDI.getByUuid(conn, volumeUUID);
+            VDI.Record vdir = volume.getRecord(conn);
+            VolumeObjectTO newVol = new VolumeObjectTO();
+            newVol.setPath(volumeUUID);
+            newVol.setSize(vdir.virtualSize);
+            return new CopyCmdAnswer(newVol);
+        } catch (XenAPIException e) {
+            details += " due to " + e.toString();
+            s_logger.warn(details, e);
+        } catch (Exception e) {
+            details += " due to " + e.getMessage();
+            s_logger.warn(details, e);
+        }
+        if (!result) {
+            // Is this logged at a higher level?
+            s_logger.error(details);
+        }
+
+        // In all cases return something.
+        return new CopyCmdAnswer(details);
+    }
+
+    @Override
+    public Answer deleteSnapshot(DeleteCommand cmd) {
+        SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData();
+        DataStoreTO store = snapshot.getDataStore();
+        if (store.getRole() == DataStoreRole.Primary) {
+            Connection conn = this.hypervisorResource.getConnection();
+            VDI snapshotVdi = getVDIbyUuid(conn, snapshot.getPath());
+            if (snapshotVdi == null) {
+                return new Answer(null);
+            }
+            String errMsg = null;
+            try {
+                this.deleteVDI(conn, snapshotVdi);
+            } catch (BadServerResponse e) {
+                s_logger.debug("delete snapshot failed:" + e.toString());
+                errMsg = e.toString();
+            } catch (XenAPIException e) {
+                s_logger.debug("delete snapshot failed:" + e.toString());
+                errMsg = e.toString();
+            } catch (XmlRpcException e) {
+                s_logger.debug("delete snapshot failed:" + e.toString());
+                errMsg = e.toString();
+            }
+            return new Answer(cmd, false, errMsg);
+        }
+        return new Answer(cmd, false, "unsupported storage type");
+    }
 }


[2/2] git commit: updated refs/heads/master to c675f82

Posted by mc...@apache.org.
CLOUDSTACK-4318:[Object_Store_Refactor] Failed to delete snapshot copied
to Staging storage during snapshot creation.



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

Branch: refs/heads/master
Commit: c675f826e5851c652ffa4a4e67407cf664021997
Parents: 8a104b9
Author: Min Chen <mi...@citrix.com>
Authored: Wed Aug 14 18:12:53 2013 -0700
Committer: Min Chen <mi...@citrix.com>
Committed: Wed Aug 14 18:12:53 2013 -0700

----------------------------------------------------------------------
 .../storage/image/store/TemplateObject.java     |   4 +-
 .../consoleproxy/ConsoleProxyManagerImpl.java   |  35 ++--
 .../secondary/SecondaryStorageManagerImpl.java  | 164 ++++++++++---------
 .../resource/NfsSecondaryStorageResource.java   |  21 ++-
 4 files changed, 124 insertions(+), 100 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c675f826/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
index b04ca6c..9c9c751 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
@@ -198,7 +198,9 @@ public class TemplateObject implements TemplateInfo {
                     templateStoreRef.setDownloadPercent(100);
                     templateStoreRef.setDownloadState(Status.DOWNLOADED);
                     templateStoreRef.setSize(newTemplate.getSize());
-                    templateStoreRef.setPhysicalSize(newTemplate.getPhysicalSize());
+                    if (newTemplate.getPhysicalSize() != null) {
+                        templateStoreRef.setPhysicalSize(newTemplate.getPhysicalSize());
+                    }
                     templateStoreDao.update(templateStoreRef.getId(), templateStoreRef);
                     if (this.getDataStore().getRole() == DataStoreRole.Image) {
                         VMTemplateVO templateVO = this.imageDao.findById(this.getId());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c675f826/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
index fd28259..aa4aa52 100755
--- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
+++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
@@ -155,7 +155,7 @@ import com.cloud.vm.dao.VMInstanceDao;
 //
 @Local(value = { ConsoleProxyManager.class, ConsoleProxyService.class })
 public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxyManager,
-        VirtualMachineGuru, SystemVmLoadScanHandler<Long>, ResourceStateAdapter {
+VirtualMachineGuru, SystemVmLoadScanHandler<Long>, ResourceStateAdapter {
     private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class);
 
     private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 seconds
@@ -558,7 +558,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
 
             // For VMs that are in Stopping, Starting, Migrating state, let client to wait by returning null
             // as sooner or later, Starting/Migrating state will be transited to Running and Stopping will be transited
-// to
+            // to
             // Stopped to allow
             // Starting of it
             s_logger.warn("Console proxy is not in correct state to be started: " + proxy.getState());
@@ -661,7 +661,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
         HypervisorType availableHypervisor = _resourceMgr.getAvailableHypervisor(dataCenterId);
         template = _templateDao.findSystemVMReadyTemplate(dataCenterId, availableHypervisor);
         if (template == null) {
-             throw new CloudRuntimeException("Not able to find the System templates or not downloaded in zone " + dataCenterId);
+            throw new CloudRuntimeException("Not able to find the System templates or not downloaded in zone " + dataCenterId);
         }
 
         Map<String, Object> context = createProxyInstance(dataCenterId, template);
@@ -707,18 +707,18 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
             }
             defaultNetwork = networks.get(0);
         } else {
-        TrafficType defaultTrafficType = TrafficType.Public;
-        if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) {
-            defaultTrafficType = TrafficType.Guest;
-        }
-        List<NetworkVO> defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType);
+            TrafficType defaultTrafficType = TrafficType.Public;
+            if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) {
+                defaultTrafficType = TrafficType.Guest;
+            }
+            List<NetworkVO> defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType);
 
             // api should never allow this situation to happen
-        if (defaultNetworks.size() != 1) {
+            if (defaultNetworks.size() != 1) {
                 throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type "
-                      + defaultTrafficType + " when expect to find 1");
+                        + defaultTrafficType + " when expect to find 1");
             }
-             defaultNetwork = defaultNetworks.get(0);
+            defaultNetwork = defaultNetworks.get(0);
         }
 
         List<? extends NetworkOffering> offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork, NetworkOffering.SystemManagementNetwork);
@@ -951,7 +951,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
         ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
         if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) {
             VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any);
-            TemplateDataStoreVO templateHostRef = _vmTemplateStoreDao.findByTemplateZoneDownloadStatus(template.getId(), dataCenterId,
+            if (template == null) {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("System vm template is not ready at data center " + dataCenterId + ", wait until it is ready to launch console proxy vm");
+                }
+                return false;
+            }
+            TemplateDataStoreVO templateHostRef = this._vmTemplateStoreDao.findByTemplateZoneDownloadStatus(template.getId(), dataCenterId,
                     Status.DOWNLOADED);
 
             if (templateHostRef != null) {
@@ -1282,8 +1288,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
         String cpvmSrvcOffIdStr = configs.get(Config.ConsoleProxyServiceOffering.key());
         if (cpvmSrvcOffIdStr != null) {
             DiskOffering diskOffering = _diskOfferingDao.findByUuid(cpvmSrvcOffIdStr);
-            if (diskOffering == null)
+            if (diskOffering == null) {
                 diskOffering = _diskOfferingDao.findById(Long.parseLong(cpvmSrvcOffIdStr));
+            }
             if (diskOffering != null) {
                 _serviceOffering = _offeringDao.findById(diskOffering.getId());
             } else {
@@ -1517,7 +1524,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
     @Override
     public void onScanStart() {
         // to reduce possible number of DB queries for capacity scan, we run following aggregated queries in preparation
-// stage
+        // stage
         _zoneHostInfoMap = getZoneHostInfo();
 
         _zoneProxyCountMap = new HashMap<Long, ConsoleProxyLoadInfo>();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c675f826/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
index fef41d8..99aad9c 100755
--- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
+++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
@@ -252,7 +252,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
     private final GlobalLock _allocLock = GlobalLock.getInternLock(getAllocLockName());
 
     public SecondaryStorageManagerImpl() {
-    	_ssvmMgr = this;
+        _ssvmMgr = this;
     }
 
     @Override
@@ -296,16 +296,18 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
             }
 
             List<DataStore> ssStores = _dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId));
-             for( DataStore ssStore : ssStores ) {
-                 if (!(ssStore.getTO() instanceof NfsTO ))
-                     continue; // only do this for Nfs
+            for( DataStore ssStore : ssStores ) {
+                if (!(ssStore.getTO() instanceof NfsTO ))
+                {
+                    continue; // only do this for Nfs
+                }
                 String secUrl = ssStore.getUri();
                 SecStorageSetupCommand setupCmd = null;
                 if (!_useSSlCopy) {
-                	setupCmd = new SecStorageSetupCommand(ssStore.getTO(), secUrl, null);
+                    setupCmd = new SecStorageSetupCommand(ssStore.getTO(), secUrl, null);
                 } else {
-                	Certificates certs = _keystoreMgr.getCertificates(ConsoleProxyManager.CERTIFICATE_NAME);
-                	setupCmd = new SecStorageSetupCommand(ssStore.getTO(), secUrl, certs);
+                    Certificates certs = _keystoreMgr.getCertificates(ConsoleProxyManager.CERTIFICATE_NAME);
+                    setupCmd = new SecStorageSetupCommand(ssStore.getTO(), secUrl, certs);
                 }
 
                 Answer answer = _agentMgr.easySend(ssHostId, setupCmd);
@@ -348,7 +350,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
                 }
             }
         }
-        */
+         */
         return true;
     }
 
@@ -423,9 +425,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
         sc.addAnd(sc.getEntity().getStatus(), Op.IN, com.cloud.host.Status.Up, com.cloud.host.Status.Connecting);
         List<HostVO> ssvms = sc.list();
         for (HostVO ssvm : ssvms) {
-        	if (ssvm.getId() == ssAHostId) {
-        		continue;
-        	}
+            if (ssvm.getId() == ssAHostId) {
+                continue;
+            }
             Answer answer = _agentMgr.easySend(ssvm.getId(), thiscpc);
             if (answer != null && answer.getResult()) {
                 if (s_logger.isDebugEnabled()) {
@@ -441,10 +443,10 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
 
         SecStorageFirewallCfgCommand allSSVMIpList = new SecStorageFirewallCfgCommand(false);
         for (HostVO ssvm : ssvms) {
-        	if (ssvm.getId() == ssAHostId) {
-        		continue;
-        	}
-        	allSSVMIpList.addPortConfig(ssvm.getPublicIpAddress(), copyPort, true, TemplateConstants.DEFAULT_TMPLT_COPY_INTF);
+            if (ssvm.getId() == ssAHostId) {
+                continue;
+            }
+            allSSVMIpList.addPortConfig(ssvm.getPublicIpAddress(), copyPort, true, TemplateConstants.DEFAULT_TMPLT_COPY_INTF);
         }
 
         Answer answer = _agentMgr.easySend(ssAHostId, allSSVMIpList);
@@ -537,16 +539,16 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
             }
             defaultNetwork = networks.get(0);
         } else {
-        TrafficType defaultTrafficType = TrafficType.Public;
+            TrafficType defaultTrafficType = TrafficType.Public;
 
-        if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) {
-        	defaultTrafficType = TrafficType.Guest;
-        }
-        List<NetworkVO> defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType);
+            if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) {
+                defaultTrafficType = TrafficType.Guest;
+            }
+            List<NetworkVO> defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType);
             // api should never allow this situation to happen
-        if (defaultNetworks.size() != 1) {
+            if (defaultNetworks.size() != 1) {
                 throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type "
-                                + defaultTrafficType + " when expect to find 1");
+                        + defaultTrafficType + " when expect to find 1");
             }
             defaultNetwork = defaultNetworks.get(0);
         }
@@ -557,7 +559,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
         defaultNic.setDefaultNic(true);
         defaultNic.setDeviceId(2);
         try {
-        	networks.add(new Pair<NetworkVO, NicProfile>(_networkMgr.setupNetwork(systemAcct, _networkOfferingDao.findById(defaultNetwork.getNetworkOfferingId()), plan, null, null, false).get(0), defaultNic));
+            networks.add(new Pair<NetworkVO, NicProfile>(_networkMgr.setupNetwork(systemAcct, _networkOfferingDao.findById(defaultNetwork.getNetworkOfferingId()), plan, null, null, false).get(0), defaultNic));
             for (NetworkOffering offering : offerings) {
                 networks.add(new Pair<NetworkVO, NicProfile>(_networkMgr.setupNetwork(systemAcct, offering, plan, null, null, false).get(0), null));
             }
@@ -593,8 +595,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
     private SecondaryStorageVmAllocator getCurrentAllocator() {
 
         // for now, only one adapter is supported
-    	if(_ssVmAllocators.size() > 0)
-    		return _ssVmAllocators.get(0);
+        if(_ssVmAllocators.size() > 0) {
+            return _ssVmAllocators.get(0);
+        }
 
         return null;
     }
@@ -663,8 +666,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
             if (_allocLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                 try {
                     secStorageVm = startNew(dataCenterId, role);
-                    for (UploadVO upload :_uploadDao.listAll())
+                    for (UploadVO upload :_uploadDao.listAll()) {
                         _uploadDao.expunge(upload.getId());
+                    }
                 } finally {
                     _allocLock.unlock();
                 }
@@ -722,7 +726,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
         if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) {
             VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any);
             if (template == null) {
-                s_logger.debug("No hypervisor host added  in zone " + dataCenterId + ", wait until it is ready to launch secondary storage vm");
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("System vm template is not ready at data center " + dataCenterId + ", wait until it is ready to launch secondary storage vm");
+                }
                 return false;
             }
 
@@ -841,8 +847,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
                 throw new ConfigurationException(msg);
             }
         } else {
-        	int ramSize = NumbersUtil.parseInt(_configDao.getValue("ssvm.ram.size"), DEFAULT_SS_VM_RAMSIZE);
-        	int cpuFreq = NumbersUtil.parseInt(_configDao.getValue("ssvm.cpu.mhz"), DEFAULT_SS_VM_CPUMHZ);
+            int ramSize = NumbersUtil.parseInt(_configDao.getValue("ssvm.ram.size"), DEFAULT_SS_VM_RAMSIZE);
+            int cpuFreq = NumbersUtil.parseInt(_configDao.getValue("ssvm.cpu.mhz"), DEFAULT_SS_VM_CPUMHZ);
             _useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key()));
             _serviceOffering = new ServiceOfferingVO("System Offering For Secondary Storage VM", 1, ramSize, cpuFreq, null, null, false, null, _useLocalStorage, true, null, true, VirtualMachine.Type.SecondaryStorageVm, true);
             _serviceOffering.setUniqueName(ServiceOffering.ssvmDefaultOffUniqueName);
@@ -863,27 +869,27 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
 
         _httpProxy = configs.get(Config.SecStorageProxy.key());
         if (_httpProxy != null) {
-        	boolean valid = true;
-        	String errMsg = null;
-        	try {
-				URI uri = new URI(_httpProxy);
-				if (!"http".equalsIgnoreCase(uri.getScheme())) {
-					errMsg = "Only support http proxy";
-					valid = false;
-				} else if (uri.getHost() == null) {
-					errMsg = "host can not be null";
-					valid = false;
-				} else if (uri.getPort() == -1) {
-					_httpProxy = _httpProxy + ":3128";
-				}
-			} catch (URISyntaxException e) {
-				errMsg = e.toString();
-			} finally {
-				if (!valid) {
-					s_logger.debug("ssvm http proxy " + _httpProxy + " is invalid: " + errMsg);
-					throw new ConfigurationException("ssvm http proxy " + _httpProxy +  "is invalid: " + errMsg);
-				}
-			}
+            boolean valid = true;
+            String errMsg = null;
+            try {
+                URI uri = new URI(_httpProxy);
+                if (!"http".equalsIgnoreCase(uri.getScheme())) {
+                    errMsg = "Only support http proxy";
+                    valid = false;
+                } else if (uri.getHost() == null) {
+                    errMsg = "host can not be null";
+                    valid = false;
+                } else if (uri.getPort() == -1) {
+                    _httpProxy = _httpProxy + ":3128";
+                }
+            } catch (URISyntaxException e) {
+                errMsg = e.toString();
+            } finally {
+                if (!valid) {
+                    s_logger.debug("ssvm http proxy " + _httpProxy + " is invalid: " + errMsg);
+                    throw new ConfigurationException("ssvm http proxy " + _httpProxy +  "is invalid: " + errMsg);
+                }
+            }
         }
         if (s_logger.isInfoEnabled()) {
             s_logger.info("Secondary storage vm Manager is configured.");
@@ -1040,7 +1046,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
         }
 
         if (Boolean.valueOf(_configDao.getValue("system.vm.random.password"))) {
-        	buf.append(" vmpassword=").append(_configDao.getValue("system.vm.password"));
+            buf.append(" vmpassword=").append(_configDao.getValue("system.vm.password"));
         }
 
         for (NicProfile nic : profile.getNics()) {
@@ -1066,9 +1072,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
             } else if (nic.getTrafficType() == TrafficType.Public) {
                 buf.append(" public.network.device=").append("eth").append(deviceId);
             } else if (nic.getTrafficType() == TrafficType.Storage) {
-            	buf.append(" storageip=").append(nic.getIp4Address());
-            	buf.append(" storagenetmask=").append(nic.getNetmask());
-            	buf.append(" storagegateway=").append(nic.getGateway());
+                buf.append(" storageip=").append(nic.getIp4Address());
+                buf.append(" storagenetmask=").append(nic.getNetmask());
+                buf.append(" storagegateway=").append(nic.getGateway());
             }
         }
 
@@ -1272,24 +1278,24 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
     public void onScanEnd() {
     }
 
-	@Override
+    @Override
     public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
-		/* Called when Secondary Storage VM connected */
-		StartupCommand firstCmd = cmd[0];
-	    if (!(firstCmd instanceof StartupSecondaryStorageCommand)) {
-	    	return null;
-	    }
-
-		host.setType( com.cloud.host.Host.Type.SecondaryStorageVM);
-		return host;
+        /* Called when Secondary Storage VM connected */
+        StartupCommand firstCmd = cmd[0];
+        if (!(firstCmd instanceof StartupSecondaryStorageCommand)) {
+            return null;
+        }
+
+        host.setType( com.cloud.host.Host.Type.SecondaryStorageVM);
+        return host;
     }
 
-	@Override
+    @Override
     public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
             List<String> hostTags) {
-		// Used to be Called when add secondary storage on UI through DummySecondaryStorageResource to update that host entry for Secondary Storage.
-	    // Now since we move secondary storage from host table, this code is not needed to be invoked anymore.
-	    /*
+        // Used to be Called when add secondary storage on UI through DummySecondaryStorageResource to update that host entry for Secondary Storage.
+        // Now since we move secondary storage from host table, this code is not needed to be invoked anymore.
+        /*
 		StartupCommand firstCmd = startup[0];
 		if (!(firstCmd instanceof StartupStorageCommand)) {
 			return null;
@@ -1329,30 +1335,30 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
 				host.setStorageUrl(ssCmd.getNfsShare());
 			}
 		}
-        */
-		return null; // no need to handle this event anymore since secondary storage is not in host table anymore.
+         */
+        return null; // no need to handle this event anymore since secondary storage is not in host table anymore.
     }
 
-	@Override
+    @Override
     public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
-	    // Since secondary storage is moved out of host table, this class should not handle delete secondary storage anymore.
+        // Since secondary storage is moved out of host table, this class should not handle delete secondary storage anymore.
         return null;
     }
 
 
 
-	@Override
+    @Override
     public List<HostVO> listUpAndConnectingSecondaryStorageVmHost(Long dcId) {
-		SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
+        SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
         if (dcId != null) {
             sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId);
         }
         sc.addAnd(sc.getEntity().getState(), Op.IN, com.cloud.host.Status.Up, com.cloud.host.Status.Connecting);
-		sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorageVM);
-	    return sc.list();
+        sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorageVM);
+        return sc.list();
     }
 
-	@Override
+    @Override
     public HostVO pickSsvmHost(HostVO ssHost) {
         if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) {
             return  ssHost;
@@ -1368,8 +1374,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
         return null;
     }
 
-	@Override
-	public void prepareStop(VirtualMachineProfile profile) {
+    @Override
+    public void prepareStop(VirtualMachineProfile profile) {
 
-	}
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c675f826/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
----------------------------------------------------------------------
diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
index f2b40f2..30d0ff7 100755
--- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
+++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
@@ -1239,20 +1239,29 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
         DataStoreTO dstore = obj.getDataStore();
         if (dstore instanceof NfsTO) {
             NfsTO nfs = (NfsTO) dstore;
+            String parent = getRootDir(nfs.getUrl());
+            if (!parent.endsWith(File.separator)) {
+                parent += File.separator;
+            }
             String snapshotPath = obj.getPath();
             if (snapshotPath.startsWith(File.separator)) {
                 snapshotPath = snapshotPath.substring(1);
             }
+            // check if the passed snapshot path is a directory or not. For ImageCache, path is stored as a directory instead of
+            // snapshot file name. If so, since backupSnapshot process has already deleted snapshot in cache, so we just do nothing
+            // and return true.
+            String fullSnapPath = parent + snapshotPath;
+            File snapDir = new File(fullSnapPath);
+            if (snapDir.exists() && snapDir.isDirectory()) {
+                s_logger.debug("snapshot path " + snapshotPath + " is a directory, already deleted during backup snapshot, so no need to delete");
+                return new Answer(cmd, true, null);
+            }
+            // passed snapshot path is a snapshot file path, then get snapshot directory first
             int index = snapshotPath.lastIndexOf("/");
             String snapshotName = snapshotPath.substring(index + 1);
             snapshotPath = snapshotPath.substring(0, index);
-
-            String parent = getRootDir(nfs.getUrl());
-            if (!parent.endsWith(File.separator)) {
-                parent += File.separator;
-            }
             String absoluteSnapshotPath = parent + snapshotPath;
-            // check if directory exists
+            // check if snapshot directory exists
             File snapshotDir = new File(absoluteSnapshotPath);
             String details = null;
             if (!snapshotDir.exists()) {