You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2018/03/29 18:55:44 UTC

[GitHub] rafaelweingartner closed pull request #2414: [CLOUDSTACK-10241] Duplicated file SRs being created in XenServer pools

rafaelweingartner closed pull request #2414: [CLOUDSTACK-10241] Duplicated file SRs being created in XenServer pools
URL: https://github.com/apache/cloudstack/pull/2414
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
index ee146a1f88c..2cecbea162c 100644
--- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
@@ -198,7 +198,7 @@ public String toString() {
 
     private final static int BASE_TO_CONVERT_BYTES_INTO_KILOBYTES = 1024;
 
-    protected static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance();
+    private static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance();
     // static min values for guests on xenserver
     private static final long mem_128m = 134217728L;
 
@@ -243,7 +243,7 @@ private static boolean isAlienVm(final VM vm, final Connection conn) throws XenA
     protected String _guestNetworkName;
     protected int _heartbeatInterval = 60;
     protected int _heartbeatTimeout = 120;
-    protected final XsHost _host = new XsHost();
+    protected XsHost _host = new XsHost();
     protected String _instance; // instance name (default is usually "VM")
     protected boolean _isOvs = false;
     protected String _linkLocalPrivateNetworkName;
diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java
index dea1752abd7..d809560ac22 100644
--- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java
+++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java
@@ -18,6 +18,27 @@
  */
 package com.cloud.hypervisor.xenserver.resource;
 
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CopyCommand;
+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.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.apache.xmlrpc.XmlRpcException;
+
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.to.DataObjectType;
 import com.cloud.agent.api.to.DataStoreTO;
@@ -37,26 +58,9 @@
 import com.xensource.xenapi.Task;
 import com.xensource.xenapi.Types;
 import com.xensource.xenapi.Types.BadServerResponse;
+import com.xensource.xenapi.Types.StorageOperations;
 import com.xensource.xenapi.Types.XenAPIException;
 import com.xensource.xenapi.VDI;
-import org.apache.cloudstack.storage.command.CopyCmdAnswer;
-import org.apache.cloudstack.storage.command.CopyCommand;
-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.commons.lang.StringUtils;
-import org.apache.log4j.Logger;
-import org.apache.xmlrpc.XmlRpcException;
-
-import java.io.File;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
 
 public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
     private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class);
@@ -65,90 +69,181 @@ public Xenserver625StorageProcessor(final CitrixResourceBase resource) {
         super(resource);
     }
 
-    protected boolean mountNfs(final Connection conn, final String remoteDir, String localDir) {
+    private void mountNfs(Connection conn, String remoteDir, String localDir) {
         if (localDir == null) {
             localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remoteDir.getBytes());
         }
-
-        final String results = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000, "localDir", localDir, "remoteDir",
-                remoteDir);
-
-        if (results == null || results.isEmpty()) {
+        String result = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000, "localDir", localDir, "remoteDir", remoteDir);
+        if (StringUtils.isBlank(result)) {
             final String errMsg = "Could not mount secondary storage " + remoteDir + " on host " + localDir;
-
             s_logger.warn(errMsg);
-
             throw new CloudRuntimeException(errMsg);
         }
-
-        return true;
     }
 
-    protected boolean makeDirectory(final Connection conn, final String path) {
-        final String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "makeDirectory", "path", path);
+    protected boolean makeDirectory(Connection conn, String path) {
+        String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "makeDirectory", "path", path);
+        return StringUtils.isNotBlank(result);
+    }
 
-        if (result == null || result.isEmpty()) {
-            return false;
+    /**
+     *  Creates the file SR for the given path. If there already exist a file SR for the path, we return the existing one.
+     *  This method uses a synchronized block to guarantee that only a single file SR is created per path.
+     *  If it is not possible to retrieve one file SR or to create one, a runtime exception will be thrown.
+     */
+    protected SR createFileSR(Connection conn, String path) {
+        String srPath = StringUtils.trim(path);
+        synchronized (srPath) {
+            SR sr = retrieveAlreadyConfiguredSrWithoutException(conn, srPath);
+            if (sr == null) {
+                sr = createNewFileSr(conn, srPath);
+            }
+            if (sr == null) {
+                String hostUuid = this.hypervisorResource._host.getUuid();
+                throw new CloudRuntimeException(String.format("Could not retrieve an already used file SR for path [%s] or create a new file SR on host [%s]", srPath, hostUuid));
+            }
+            return sr;
         }
-
-        return true;
     }
 
-    protected SR createFileSR(final Connection conn, final String path) {
+    /**
+     * Creates a new file SR for the given path. If any of XenServer's checked exception occurs, we use method {@link #removeSrAndPbdIfPossible(Connection, SR, PBD)} to clean the created PBD and SR entries.
+     * To avoid race conditions between management servers, we are using a deterministic srUuid for the file SR to be created (we are leaving XenServer with the burden of managing race conditions). The UUID is based on the SR file path, and is generated using {@link UUID#nameUUIDFromBytes(byte[])}.
+     * If there is an SR with the generated UUID, this means that some other management server has just created it. An exception will occur and this exception will be an {@link InternalError}. The exception will contain {@link InternalError#message} a message saying 'Db_exn.Uniqueness_constraint_violation'.
+     * For cases where the previous described error happens, we catch the exception and use the method {@link #retrieveAlreadyConfiguredSrWithoutException(Connection, String)}.
+     */
+    protected SR createNewFileSr(Connection conn, String srPath) {
+        String hostUuid = hypervisorResource.getHost().getUuid();
+        s_logger.debug(String.format("Creating file SR for path [%s] on host [%s]", srPath, this.hypervisorResource._host.getUuid()));
         SR sr = null;
         PBD pbd = null;
-
         try {
-            final String srname = path.trim();
-            synchronized (srname.intern()) {
-                final Set<SR> srs = SR.getByNameLabel(conn, srname);
-                if (srs != null && !srs.isEmpty()) {
-                    return srs.iterator().next();
-                }
-                final Map<String, String> smConfig = new HashMap<String, String>();
-                final Host host = Host.getByUuid(conn, hypervisorResource.getHost().getUuid());
-                final String uuid = UUID.randomUUID().toString();
-                sr = SR.introduce(conn, uuid, srname, srname, "file", "file", false, smConfig);
-                final PBD.Record record = new PBD.Record();
-                record.host = host;
-                record.SR = sr;
-                smConfig.put("location", path);
-                record.deviceConfig = smConfig;
-                pbd = PBD.create(conn, record);
-                pbd.plug(conn);
-                sr.scan(conn);
-            }
+            Host host = Host.getByUuid(conn, hostUuid);
+            String srUuid = UUID.nameUUIDFromBytes(srPath.getBytes()).toString();
+
+            Map<String, String> smConfig = new HashMap<String, String>();
+            sr = SR.introduce(conn, srUuid, srPath, srPath, "file", "file", false, smConfig);
+
+            PBD.Record record = new PBD.Record();
+            record.host = host;
+            record.SR = sr;
+            smConfig.put("location", srPath);
+            record.deviceConfig = smConfig;
+            pbd = PBD.create(conn, record);
+            pbd.plug(conn);
+            sr.scan(conn);
             return sr;
-        } catch (final Exception ex) {
-            try {
-                if (pbd != null) {
-                    pbd.destroy(conn);
+        } catch (XenAPIException | XmlRpcException e) {
+            if (e instanceof Types.InternalError) {
+                String expectedDuplicatedFileSrErrorMessage = "Db_exn.Uniqueness_constraint_violation";
+
+                Types.InternalError internalErrorException = (Types.InternalError)e;
+                if (StringUtils.contains(internalErrorException.message, expectedDuplicatedFileSrErrorMessage)) {
+                    s_logger.debug(String.format(
+                            "It seems that we have hit a race condition case here while creating file SR for [%s]. Instead of creating one, we will reuse the one that already exist in the XenServer pool.",
+                            srPath));
+                    return retrieveAlreadyConfiguredSrWithoutException(conn, srPath);
                 }
-            } catch (final Exception e1) {
-                s_logger.debug("Failed to destroy PBD", ex);
             }
+            removeSrAndPbdIfPossible(conn, sr, pbd);
+            s_logger.debug(String.format("Could not create file SR [%s] on host [%s].", srPath, hostUuid), e);
+            return null;
+        }
+    }
 
-            try {
-                if (sr != null) {
-                    sr.forget(conn);
-                }
-            } catch (final Exception e2) {
-                s_logger.error("Failed to forget SR", ex);
-            }
+    /**
+     * Calls {@link #unplugPbd(Connection, PBD)} and {@link #forgetSr(Connection, SR)}, if respective objects are not null.
+     */
+    protected void removeSrAndPbdIfPossible(Connection conn, SR sr, PBD pbd) {
+        if (pbd != null) {
+            unplugPbd(conn, pbd);
+        }
+        if (sr != null) {
+            forgetSr(conn, sr);
+        }
+    }
+
+    /**
+     * This is a simple facade for {@link #retrieveAlreadyConfiguredSr(Connection, String)} method.
+     * If we catch any of the checked exception of {@link #retrieveAlreadyConfiguredSr(Connection, String)}, we re-throw as a {@link CloudRuntimeException}.
+     */
+    protected SR retrieveAlreadyConfiguredSrWithoutException(Connection conn, String srPath) {
+        try {
+            return retrieveAlreadyConfiguredSr(conn, srPath);
+        } catch (XenAPIException | XmlRpcException e) {
+            throw new CloudRuntimeException("Unexpected exception while trying to retrieve an already configured file SR for path: " + srPath);
+        }
+    }
 
-            final String msg = "createFileSR failed! due to the following: " + ex.toString();
+    /**
+     *  This method will check if there is an already configured file SR for the given path. If by any chance we find more than one SR with the same name (mount point path) we throw a runtime exception because this situation should never happen.
+     *  If we find an SR, we check if the SR is working properly (performing an {@link SR#scan(Connection)}). If everything is ok with the SR, we return it.
+     *  Otherwise, we remove the SR using {@link #forgetSr(Connection, SR)} method;
+     */
+    protected SR retrieveAlreadyConfiguredSr(Connection conn, String path) throws XenAPIException, XmlRpcException {
+        Set<SR> srs = SR.getByNameLabel(conn, path);
+        if (CollectionUtils.isEmpty(srs)) {
+            s_logger.debug("No file SR found for path: " + path);
+            return null;
+        }
+        if (srs.size() > 1) {
+            throw new CloudRuntimeException("There should be only one SR with name-label: " + path);
+        }
+        SR sr = srs.iterator().next();
+        String srUuid = sr.getUuid(conn);
+        s_logger.debug(String.format("SR [%s] was already introduced in XenServer. Checking if we can reuse it.", srUuid));
+        Map<String, StorageOperations> currentOperations = sr.getCurrentOperations(conn);
+        if (MapUtils.isEmpty(currentOperations)) {
+            s_logger.debug(String.format("There are no current operation in SR [%s]. It looks like an unusual condition. We will check if it is usable before returning it.", srUuid));
+        }
+        try {
+            sr.scan(conn);
+        } catch (XenAPIException | XmlRpcException e) {
+            s_logger.debug(String.format("Problems while checking if cached temporary SR [%s] is working properly (we executed sr-scan). We will not reuse it.", srUuid));
+            forgetSr(conn, sr);
+            return null;
+        }
+        s_logger.debug(String.format("Cached temporary SR [%s] is working properly. We will reuse it.", srUuid));
+        return sr;
+    }
 
-            s_logger.warn(msg, ex);
+    /**
+     *  Forgets the given SR. Before executing the command {@link SR#forget(Connection)}, we will unplug all of its PBDs using {@link PBD#unplug(Connection)}.
+     *  Checked exceptions are captured and re-thrown as {@link CloudRuntimeException}.
+     */
+    protected void forgetSr(Connection conn, SR sr) {
+        String srUuid = StringUtils.EMPTY;
+        try {
+            srUuid = sr.getUuid(conn);
+            Set<PBD> pbDs = sr.getPBDs(conn);
+            for (PBD pbd : pbDs) {
+                s_logger.debug(String.format("Unpluging PBD [%s] of SR [%s] as it is not working properly.", pbd.getUuid(conn), srUuid));
+                unplugPbd(conn, pbd);
+            }
+            s_logger.debug(String.format("Forgetting SR [%s] as it is not working properly.", srUuid));
+            sr.forget(conn);
+        } catch (XenAPIException | XmlRpcException e) {
+            throw new CloudRuntimeException("Exception while forgeting SR: " + srUuid, e);
+        }
+    }
 
-            throw new CloudRuntimeException(msg, ex);
+    /**
+     * Unplugs the given {@link PBD}. If checked exception happens, we re-throw as {@link CloudRuntimeException}
+     */
+    protected void unplugPbd(Connection conn, PBD pbd) {
+        String pbdUuid = StringUtils.EMPTY;
+        try {
+            pbdUuid = pbd.getUuid(conn);
+            pbd.unplug(conn);
+        } catch (XenAPIException | XmlRpcException e) {
+            throw new CloudRuntimeException(String.format("Exception while unpluging PBD [%s].", pbdUuid));
         }
     }
 
-    protected SR createFileSr(final Connection conn, final String remotePath, final String dir) {
-        final String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remotePath.getBytes());
+    protected SR createFileSr(Connection conn, String remotePath, String dir) {
+        String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remotePath.getBytes());
         mountNfs(conn, remotePath, localDir);
-        final SR sr = createFileSR(conn, localDir + "/" + dir);
-        return sr;
+        return createFileSR(conn, localDir + "/" + dir);
     }
 
     @Override
@@ -165,8 +260,8 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
 
         try {
             if (srcStore instanceof NfsTO && srcData.getObjectType() == DataObjectType.TEMPLATE) {
-                final NfsTO srcImageStore = (NfsTO) srcStore;
-                final TemplateObjectTO srcTemplate = (TemplateObjectTO) srcData;
+                final NfsTO srcImageStore = (NfsTO)srcStore;
+                final TemplateObjectTO srcTemplate = (TemplateObjectTO)srcData;
                 final String storeUrl = srcImageStore.getUrl();
                 final URI uri = new URI(storeUrl);
                 String volumePath = srcData.getPath();
@@ -188,8 +283,7 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
                 final Set<VDI> setVdis = srcSr.getVDIs(conn);
 
                 if (setVdis.size() != 1) {
-                    return new CopyCmdAnswer("Expected 1 VDI template, but found " + setVdis.size() + " VDI templates on: " +
-                            uri.getHost() + ":" + uri.getPath() + "/" + volumeDirectory);
+                    return new CopyCmdAnswer("Expected 1 VDI template, but found " + setVdis.size() + " VDI templates on: " + uri.getHost() + ":" + uri.getPath() + "/" + volumeDirectory);
                 }
 
                 final VDI srcVdi = setVdis.iterator().next();
@@ -202,7 +296,7 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
                 String chapInitiatorUsername = null;
                 String chapInitiatorSecret = null;
 
-                final PrimaryDataStoreTO destStore = (PrimaryDataStoreTO) destData.getDataStore();
+                final PrimaryDataStoreTO destStore = (PrimaryDataStoreTO)destData.getDataStore();
 
                 Map<String, String> details = destStore.getDetails();
 
@@ -317,8 +411,8 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
         return new CopyCmdAnswer("not implemented yet");
     }
 
-    protected String backupSnapshot(final Connection conn, final String primaryStorageSRUuid, final String localMountPoint, final String path,
-            final String secondaryStorageMountPath, final String snapshotUuid, String prevBackupUuid, final String prevSnapshotUuid, final Boolean isISCSI, int wait) {
+    protected String backupSnapshot(final Connection conn, final String primaryStorageSRUuid, final String localMountPoint, final String path, final String secondaryStorageMountPath,
+            final String snapshotUuid, String prevBackupUuid, final String prevSnapshotUuid, final Boolean isISCSI, int wait) {
         boolean filesrcreated = false;
         // boolean copied = false;
 
@@ -378,8 +472,8 @@ protected String backupSnapshot(final Connection conn, final String primaryStora
 
     @Override
     protected String getVhdParent(final Connection conn, final String primaryStorageSRUuid, final String snapshotUuid, final Boolean isISCSI) {
-        final String parentUuid = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid",
-                snapshotUuid, "isISCSI", isISCSI.toString());
+        final String parentUuid = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI",
+                isISCSI.toString());
 
         if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) {
             s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid);
@@ -396,23 +490,23 @@ public Answer backupSnapshot(final CopyCommand cmd) {
         final DataTO cacheData = cmd.getCacheTO();
         final DataTO destData = cmd.getDestTO();
         final int wait = cmd.getWait();
-        final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) srcData.getDataStore();
+        final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcData.getDataStore();
         final String primaryStorageNameLabel = primaryStore.getUuid();
         String secondaryStorageUrl = null;
         NfsTO cacheStore = null;
         String destPath = null;
         if (cacheData != null) {
-            cacheStore = (NfsTO) cacheData.getDataStore();
+            cacheStore = (NfsTO)cacheData.getDataStore();
             secondaryStorageUrl = cacheStore.getUrl();
             destPath = cacheData.getPath();
         } else {
-            cacheStore = (NfsTO) destData.getDataStore();
+            cacheStore = (NfsTO)destData.getDataStore();
             secondaryStorageUrl = cacheStore.getUrl();
             destPath = destData.getPath();
         }
 
-        final SnapshotObjectTO snapshotTO = (SnapshotObjectTO) srcData;
-        final SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO) destData;
+        final SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData;
+        final SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData;
         String snapshotUuid = snapshotTO.getPath();
 
         final String prevBackupUuid = snapshotOnImage.getParentSnapshotPath();
@@ -437,8 +531,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
                 final String chapInitiatorSecret = srcDetails.get(DiskTO.CHAP_INITIATOR_SECRET);
                 final String srType = CitrixResourceBase.SRType.LVMOISCSI.toString();
 
-                primaryStorageSR = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName,
-                        chapInitiatorUsername, chapInitiatorSecret, false, srType, true);
+                primaryStorageSR = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, false, srType, true);
 
                 final VDI srcVdi = primaryStorageSR.getVDIs(conn).iterator().next();
                 if (srcVdi == null) {
@@ -474,7 +567,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
                     mountNfs(conn, secondaryStorageMountPath, localDir);
                     final boolean result = makeDirectory(conn, localDir + "/" + folder);
                     if (!result) {
-                        details = " Filed to create folder " + folder + " in secondary storage";
+                        details = " Failed to create folder " + folder + " in secondary storage";
                         s_logger.warn(details);
                         return new CopyCmdAnswer(details);
                     }
@@ -493,7 +586,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
                     if (destStore instanceof SwiftTO) {
                         try {
                             final String container = "S-" + snapshotTO.getVolume().getVolumeId().toString();
-                            final String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO) destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait);
+                            final String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait);
                             final String swiftPath = container + File.separator + destSnapshotName;
                             finalPath = swiftPath;
                         } finally {
@@ -506,7 +599,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
 
                     } else if (destStore instanceof S3TO) {
                         try {
-                            finalPath = backupSnapshotToS3(conn, (S3TO) destStore, snapshotSr.getUuid(conn), folder, snapshotBackupUuid, isISCSI, wait);
+                            finalPath = backupSnapshotToS3(conn, (S3TO)destStore, snapshotSr.getUuid(conn), folder, snapshotBackupUuid, isISCSI, wait);
                             if (finalPath == null) {
                                 throw new CloudRuntimeException("S3 upload of snapshots " + snapshotBackupUuid + " failed");
                             }
@@ -543,17 +636,15 @@ public Answer backupSnapshot(final CopyCommand cmd) {
                 final String primaryStorageSRUuid = primaryStorageSR.getUuid(conn);
                 if (destStore instanceof SwiftTO) {
                     final String container = "S-" + snapshotTO.getVolume().getVolumeId().toString();
-                    snapshotBackupUuid = swiftBackupSnapshot(conn, (SwiftTO) destStore, primaryStorageSRUuid, snapshotPaUuid, "S-"
-                            + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait);
+                    snapshotBackupUuid = swiftBackupSnapshot(conn, (SwiftTO)destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait);
                     finalPath = container + File.separator + snapshotBackupUuid;
                 } else if (destStore instanceof S3TO) {
-                    finalPath = backupSnapshotToS3(conn, (S3TO) destStore, primaryStorageSRUuid, folder, snapshotPaUuid, isISCSI, wait);
+                    finalPath = backupSnapshotToS3(conn, (S3TO)destStore, primaryStorageSRUuid, folder, snapshotPaUuid, isISCSI, wait);
                     if (finalPath == null) {
                         throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed");
                     }
                 } else {
-                    final String result = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, secondaryStorageMountPath, snapshotUuid, prevBackupUuid,
-                            prevSnapshotUuid, isISCSI, wait);
+                    final String result = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, secondaryStorageMountPath, snapshotUuid, prevBackupUuid, prevSnapshotUuid, isISCSI, wait);
                     final String[] tmp = result.split("#");
                     snapshotBackupUuid = tmp[0];
                     physicalSize = Long.parseLong(tmp[1]);
@@ -574,7 +665,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
                 newSnapshot.setParentSnapshotPath(prevBackupUuid);
             }
             s_logger.info("New snapshot details: " + newSnapshot.toString());
-            s_logger.info("New snapshot physical utilization: "+physicalSize);
+            s_logger.info("New snapshot physical utilization: " + physicalSize);
 
             return new CopyCmdAnswer(newSnapshot);
         } catch (final Exception e) {
@@ -592,9 +683,9 @@ public Answer backupSnapshot(final CopyCommand cmd) {
     @Override
     public Answer createTemplateFromVolume(final CopyCommand cmd) {
         final Connection conn = hypervisorResource.getConnection();
-        final VolumeObjectTO volume = (VolumeObjectTO) cmd.getSrcTO();
-        final TemplateObjectTO template = (TemplateObjectTO) cmd.getDestTO();
-        final NfsTO destStore = (NfsTO) cmd.getDestTO().getDataStore();
+        final VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
+        final TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
+        final NfsTO destStore = (NfsTO)cmd.getDestTO().getDataStore();
         final int wait = cmd.getWait();
 
         final String secondaryStoragePoolURL = destStore.getUrl();
@@ -640,8 +731,7 @@ public Answer createTemplateFromVolume(final CopyCommand cmd) {
             final long physicalSize = tmpltVDI.getPhysicalUtilisation(conn);
             // create the template.properties file
             final String templatePath = secondaryStorageMountPath + "/" + installPath;
-            result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize,
-                    template.getId());
+            result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId());
             if (!result) {
                 throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir");
             }
@@ -691,10 +781,10 @@ protected String getSnapshotUuid(final String snapshotPath) {
     public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
         final Connection conn = hypervisorResource.getConnection();
         final DataTO srcData = cmd.getSrcTO();
-        final SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData;
+        final SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData;
         final DataTO destData = cmd.getDestTO();
-        final PrimaryDataStoreTO pool = (PrimaryDataStoreTO) destData.getDataStore();
-        final VolumeObjectTO volume = (VolumeObjectTO) destData;
+        final PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();
+        final VolumeObjectTO volume = (VolumeObjectTO)destData;
         final DataStoreTO imageStore = srcData.getDataStore();
 
         if (srcData.getDataStore() instanceof PrimaryDataStoreTO && destData.getDataStore() instanceof PrimaryDataStoreTO) {
@@ -705,7 +795,7 @@ public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
             return new CopyCmdAnswer("unsupported protocol");
         }
 
-        final NfsTO nfsImageStore = (NfsTO) imageStore;
+        final NfsTO nfsImageStore = (NfsTO)imageStore;
         final String primaryStorageNameLabel = pool.getUuid();
         final String secondaryStorageUrl = nfsImageStore.getUrl();
         final int wait = cmd.getWait();
@@ -725,7 +815,7 @@ public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
 
         try {
             if (pool.isManaged()) {
-                Map<String,String> destDetails = cmd.getOptions2();
+                Map<String, String> destDetails = cmd.getOptions2();
 
                 final String iScsiName = destDetails.get(DiskTO.IQN);
                 final String storageHost = destDetails.get(DiskTO.STORAGE_HOST);
@@ -733,16 +823,14 @@ public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
                 final String chapInitiatorSecret = destDetails.get(DiskTO.CHAP_INITIATOR_SECRET);
                 final String srType = CitrixResourceBase.SRType.LVMOISCSI.toString();
 
-                primaryStorageSR = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName,
-                        chapInitiatorUsername, chapInitiatorSecret, false, srType, true);
+                primaryStorageSR = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, false, srType, true);
 
             } else {
                 primaryStorageSR = 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);
+                throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel);
             }
 
             final String nameLabel = "cloud-" + UUID.randomUUID().toString();
@@ -821,8 +909,8 @@ public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
     @Override
     public Answer copyVolumeFromPrimaryToSecondary(final CopyCommand cmd) {
         final Connection conn = hypervisorResource.getConnection();
-        final VolumeObjectTO srcVolume = (VolumeObjectTO) cmd.getSrcTO();
-        final VolumeObjectTO destVolume = (VolumeObjectTO) cmd.getDestTO();
+        final VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO();
+        final VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO();
         final int wait = cmd.getWait();
         final DataStoreTO destStore = destVolume.getDataStore();
 
@@ -830,7 +918,7 @@ public Answer copyVolumeFromPrimaryToSecondary(final CopyCommand cmd) {
             SR secondaryStorage = null;
             Task task = null;
             try {
-                final NfsTO nfsStore = (NfsTO) destStore;
+                final NfsTO nfsStore = (NfsTO)destStore;
                 final URI uri = new URI(nfsStore.getUrl());
                 // Create the volume folder
                 if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) {
@@ -876,13 +964,13 @@ public Answer copyVolumeFromImageCacheToPrimary(final CopyCommand cmd) {
         final DataTO srcData = cmd.getSrcTO();
         final DataTO destData = cmd.getDestTO();
         final int wait = cmd.getWait();
-        final VolumeObjectTO srcVolume = (VolumeObjectTO) srcData;
-        final VolumeObjectTO destVolume = (VolumeObjectTO) destData;
-        final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) destVolume.getDataStore();
+        final VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
+        final VolumeObjectTO destVolume = (VolumeObjectTO)destData;
+        final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore();
         final DataStoreTO srcStore = srcVolume.getDataStore();
 
         if (srcStore instanceof NfsTO) {
-            final NfsTO nfsStore = (NfsTO) srcStore;
+            final NfsTO nfsStore = (NfsTO)srcStore;
             final String volumePath = srcVolume.getPath();
             int index = volumePath.lastIndexOf("/");
             final String volumeDirectory = volumePath.substring(0, index);
@@ -948,11 +1036,11 @@ public Answer createTemplateFromSnapshot(final CopyCommand cmd) {
 
         final int wait = cmd.getWait();
 
-        final SnapshotObjectTO srcObj = (SnapshotObjectTO) srcData;
-        final TemplateObjectTO destObj = (TemplateObjectTO) destData;
+        final SnapshotObjectTO srcObj = (SnapshotObjectTO)srcData;
+        final TemplateObjectTO destObj = (TemplateObjectTO)destData;
 
-        final NfsTO srcStore = (NfsTO) srcObj.getDataStore();
-        final NfsTO destStore = (NfsTO) destObj.getDataStore();
+        final NfsTO srcStore = (NfsTO)srcObj.getDataStore();
+        final NfsTO destStore = (NfsTO)destObj.getDataStore();
 
         URI srcUri = null;
         URI destUri = null;
@@ -1083,8 +1171,8 @@ public Answer createTemplateFromSnapshot(final CopyCommand cmd) {
     private Answer createTemplateFromSnapshot2(final CopyCommand cmd) {
         final Connection conn = hypervisorResource.getConnection();
 
-        final SnapshotObjectTO snapshotObjTO = (SnapshotObjectTO) cmd.getSrcTO();
-        final TemplateObjectTO templateObjTO = (TemplateObjectTO) cmd.getDestTO();
+        final SnapshotObjectTO snapshotObjTO = (SnapshotObjectTO)cmd.getSrcTO();
+        final TemplateObjectTO templateObjTO = (TemplateObjectTO)cmd.getDestTO();
 
         if (!(snapshotObjTO.getDataStore() instanceof PrimaryDataStoreTO) || !(templateObjTO.getDataStore() instanceof NfsTO)) {
             return null;
@@ -1153,8 +1241,7 @@ private Answer createTemplateFromSnapshot2(final CopyCommand cmd) {
 
             templatePath = templatePath.replaceAll("//", "/");
 
-            result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, physicalSize, virtualSize,
-                    templateObjTO.getId());
+            result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, physicalSize, virtualSize, templateObjTO.getId());
 
             if (!result) {
                 throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir");
diff --git a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/XenServer625ResourceTest.java b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/XenServer625ResourceTest.java
index 317562c9089..fc14d9fd140 100644
--- a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/XenServer625ResourceTest.java
+++ b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/XenServer625ResourceTest.java
@@ -19,6 +19,7 @@
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.xensource.xenapi.Types.XenAPIException;
@@ -28,7 +29,7 @@
     @Before
     @Override
     public void beforeTest() throws XenAPIException, XmlRpcException {
-        super.citrixResourceBase = new Xenserver625Resource();
+        super.citrixResourceBase = Mockito.spy(new Xenserver625Resource());
         super.beforeTest();
     }
 
diff --git a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessorTest.java b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessorTest.java
new file mode 100644
index 00000000000..0cf99b6a600
--- /dev/null
+++ b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessorTest.java
@@ -0,0 +1,459 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.hypervisor.xenserver.resource;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.xmlrpc.XmlRpcException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.xensource.xenapi.Connection;
+import com.xensource.xenapi.Host;
+import com.xensource.xenapi.PBD;
+import com.xensource.xenapi.PBD.Record;
+import com.xensource.xenapi.SR;
+import com.xensource.xenapi.Types.InternalError;
+import com.xensource.xenapi.Types.XenAPIException;
+
+@RunWith(PowerMockRunner.class)
+public class Xenserver625StorageProcessorTest {
+
+    @InjectMocks
+    private Xenserver625StorageProcessor xenserver625StorageProcessor;
+
+    @Mock
+    private CitrixResourceBase citrixResourceBase;
+
+    @Mock
+    private Connection connectionMock;
+
+    private String pathMock = "pathMock";
+
+    @Before
+    public void before() {
+        xenserver625StorageProcessor = Mockito.spy(new Xenserver625StorageProcessor(citrixResourceBase));
+        citrixResourceBase._host = Mockito.mock(XsHost.class);
+        Mockito.when(citrixResourceBase.getHost()).thenReturn(citrixResourceBase._host);
+    }
+
+    @Test
+    public void makeDirectoryTestCallHostPlugingReturningEmpty() {
+        boolean makeDirectoryReturn = configureAndExecuteMakeDirectoryMethodForTest(pathMock, StringUtils.EMPTY);
+
+        assertFalse(makeDirectoryReturn);
+    }
+
+    @Test
+    public void makeDirectoryTestCallHostPlugingReturningNull() {
+        boolean makeDirectoryReturn = configureAndExecuteMakeDirectoryMethodForTest(pathMock, null);
+
+        assertFalse(makeDirectoryReturn);
+    }
+
+    @Test
+    public void makeDirectoryTestCallHostPlugingReturningSomething() {
+        boolean makeDirectoryReturn = configureAndExecuteMakeDirectoryMethodForTest(pathMock, "/fictitious/path/to/use/in/unit/test");
+
+        assertTrue(makeDirectoryReturn);
+    }
+
+    private boolean configureAndExecuteMakeDirectoryMethodForTest(String path, String returnMakeDirectory) {
+        Mockito.when(citrixResourceBase.callHostPlugin(connectionMock, "cloud-plugin-storage", "makeDirectory", "path", path)).thenReturn(returnMakeDirectory);
+        return xenserver625StorageProcessor.makeDirectory(connectionMock, path);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void createFileSRTestNoSrRetrieveNoSrCreated() {
+        Mockito.doReturn(null).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+        Mockito.doReturn(null).when(xenserver625StorageProcessor).createNewFileSr(connectionMock, pathMock);
+
+        xenserver625StorageProcessor.createFileSR(connectionMock, pathMock);
+    }
+
+    @Test
+    public void createFileSRTestSrAlreadyConfigured() {
+        SR srMockRetrievedMethod = Mockito.mock(SR.class);
+        SR srMockCreateMethod = Mockito.mock(SR.class);
+
+        Mockito.doReturn(srMockRetrievedMethod).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+        Mockito.doReturn(srMockCreateMethod).when(xenserver625StorageProcessor).createNewFileSr(connectionMock, pathMock);
+
+        SR methodCreateFileSrResult = xenserver625StorageProcessor.createFileSR(connectionMock, pathMock);
+
+        InOrder inOrder = Mockito.inOrder(xenserver625StorageProcessor);
+        inOrder.verify(xenserver625StorageProcessor, times(1)).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+        inOrder.verify(xenserver625StorageProcessor, times(0)).createNewFileSr(connectionMock, pathMock);
+
+        Assert.assertEquals(srMockRetrievedMethod, methodCreateFileSrResult);
+    }
+
+    @Test
+    public void createFileSRTestSrNotConfiguredAlreadyCreatingSr() {
+        SR srMockCreateMethod = Mockito.mock(SR.class);
+
+        Mockito.doReturn(null).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+        Mockito.doReturn(srMockCreateMethod).when(xenserver625StorageProcessor).createNewFileSr(connectionMock, pathMock);
+
+        SR methodCreateFileSrResult = xenserver625StorageProcessor.createFileSR(connectionMock, pathMock);
+
+        InOrder inOrder = Mockito.inOrder(xenserver625StorageProcessor);
+        inOrder.verify(xenserver625StorageProcessor, times(1)).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+        inOrder.verify(xenserver625StorageProcessor, times(1)).createNewFileSr(connectionMock, pathMock);
+
+        Assert.assertEquals(srMockCreateMethod, methodCreateFileSrResult);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void retrieveAlreadyConfiguredSrWithoutExceptionThrowingXenAPIException() throws XenAPIException, XmlRpcException {
+        Mockito.doThrow(XenAPIException.class).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+
+        xenserver625StorageProcessor.retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void retrieveAlreadyConfiguredSrWithoutExceptionThrowingXmlRpcException() throws XenAPIException, XmlRpcException {
+        Mockito.doThrow(XmlRpcException.class).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+
+        xenserver625StorageProcessor.retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void retrieveAlreadyConfiguredSrWithoutExceptionThrowingOtherException() throws XenAPIException, XmlRpcException {
+        Mockito.doThrow(RuntimeException.class).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+
+        xenserver625StorageProcessor.retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+    }
+
+    @Test
+    public void retrieveAlreadyConfiguredSrWithoutExceptionMethodWorking() throws XenAPIException, XmlRpcException {
+        SR srMock = Mockito.mock(SR.class);
+        Mockito.doReturn(srMock).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+
+        SR sr = xenserver625StorageProcessor.retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+
+        Mockito.verify(xenserver625StorageProcessor).retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+        Assert.assertEquals(srMock, sr);
+    }
+
+    @Test
+    @PrepareForTest(SR.class)
+    public void retrieveAlreadyConfiguredSrTestNoSrFound() throws XenAPIException, XmlRpcException {
+        prepareToReturnSrs(null);
+
+        SR sr = xenserver625StorageProcessor.retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+
+        PowerMockito.verifyStatic();
+        SR.getByNameLabel(connectionMock, pathMock);
+        Assert.assertNull(sr);
+    }
+
+    private void prepareToReturnSrs(Set<SR> srs) throws XenAPIException, XmlRpcException {
+        PowerMockito.mockStatic(SR.class);
+        PowerMockito.when(SR.getByNameLabel(connectionMock, pathMock)).thenReturn(srs);
+    }
+
+    @PrepareForTest(SR.class)
+    @Test(expected = CloudRuntimeException.class)
+    public void retrieveAlreadyConfiguredSrTestMultipleSrsFound() throws XenAPIException, XmlRpcException {
+        HashSet<SR> srs = new HashSet<>();
+        srs.add(Mockito.mock(SR.class));
+        srs.add(Mockito.mock(SR.class));
+
+        prepareToReturnSrs(srs);
+
+        xenserver625StorageProcessor.retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+    }
+
+    @Test
+    @PrepareForTest(SR.class)
+    public void retrieveAlreadyConfiguredSrTestSrFailsSanityCheckWithXenAPIException() throws XenAPIException, XmlRpcException {
+        configureAndExecuteMethodRetrieveAlreadyConfiguredSrTestSrFailsSanityCheckForException(XenAPIException.class);
+    }
+
+    @Test
+    @PrepareForTest(SR.class)
+    public void retrieveAlreadyConfiguredSrTestSrFailsSanityCheckWithXmlRpcException() throws XenAPIException, XmlRpcException {
+        configureAndExecuteMethodRetrieveAlreadyConfiguredSrTestSrFailsSanityCheckForException(XmlRpcException.class);
+    }
+
+    @PrepareForTest(SR.class)
+    @Test(expected = RuntimeException.class)
+    public void retrieveAlreadyConfiguredSrTestSrFailsSanityCheckWithRuntimeException() throws XenAPIException, XmlRpcException {
+        configureAndExecuteMethodRetrieveAlreadyConfiguredSrTestSrFailsSanityCheckForException(RuntimeException.class);
+    }
+
+    private void configureAndExecuteMethodRetrieveAlreadyConfiguredSrTestSrFailsSanityCheckForException(Class<? extends Throwable> exceptionClass) throws XenAPIException, XmlRpcException {
+        SR srMock = Mockito.mock(SR.class);
+        Mockito.doThrow(exceptionClass).when(srMock).scan(connectionMock);
+
+        HashSet<SR> srs = new HashSet<>();
+        srs.add(srMock);
+
+        prepareToReturnSrs(srs);
+        Mockito.doNothing().when(xenserver625StorageProcessor).forgetSr(connectionMock, srMock);
+
+        SR sr = xenserver625StorageProcessor.retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+
+        Assert.assertNull(sr);
+        Mockito.verify(xenserver625StorageProcessor).forgetSr(connectionMock, srMock);
+    }
+
+    @Test
+    @PrepareForTest(SR.class)
+    public void methodRetrieveAlreadyConfiguredSrTestSrScanSucceeds() throws XenAPIException, XmlRpcException {
+        SR srMock = Mockito.mock(SR.class);
+        Mockito.doNothing().when(srMock).scan(connectionMock);
+
+        HashSet<SR> srs = new HashSet<>();
+        srs.add(srMock);
+
+        prepareToReturnSrs(srs);
+        Mockito.doNothing().when(xenserver625StorageProcessor).forgetSr(connectionMock, srMock);
+
+        SR sr = xenserver625StorageProcessor.retrieveAlreadyConfiguredSr(connectionMock, pathMock);
+
+        Assert.assertEquals(srMock, sr);
+        Mockito.verify(xenserver625StorageProcessor, times(0)).forgetSr(connectionMock, srMock);
+    }
+
+    @Test
+    public void forgetSrTest() throws XenAPIException, XmlRpcException {
+        PBD pbdMock = Mockito.mock(PBD.class);
+        Set<PBD> pbds = new HashSet<>();
+        pbds.add(pbdMock);
+
+        SR srMock = Mockito.mock(SR.class);
+        Mockito.when(srMock.getPBDs(connectionMock)).thenReturn(pbds);
+
+        Mockito.doNothing().when(xenserver625StorageProcessor).unplugPbd(connectionMock, pbdMock);
+
+        xenserver625StorageProcessor.forgetSr(connectionMock, srMock);
+        Mockito.verify(srMock).getPBDs(connectionMock);
+        Mockito.verify(xenserver625StorageProcessor, times(1)).unplugPbd(connectionMock, pbdMock);
+        Mockito.verify(srMock).forget(connectionMock);
+    }
+
+    @Test
+    public void unplugPbdTest() throws XenAPIException, XmlRpcException {
+        PBD pbdMock = Mockito.mock(PBD.class);
+
+        xenserver625StorageProcessor.unplugPbd(connectionMock, pbdMock);
+
+        Mockito.verify(pbdMock).getUuid(connectionMock);
+        Mockito.verify(pbdMock).unplug(connectionMock);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void unplugPbdTestThrowXenAPIException() throws XenAPIException, XmlRpcException {
+        prepareAndExecuteUnplugMethodForException(XenAPIException.class);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void unplugPbdTestThrowXmlRpcException() throws XenAPIException, XmlRpcException {
+        prepareAndExecuteUnplugMethodForException(XmlRpcException.class);
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void unplugPbdTestThrowRuntimeException() throws XenAPIException, XmlRpcException {
+        prepareAndExecuteUnplugMethodForException(RuntimeException.class);
+    }
+
+    private void prepareAndExecuteUnplugMethodForException(Class<? extends Throwable> exceptionClass) throws XenAPIException, XmlRpcException {
+        PBD pbdMock = Mockito.mock(PBD.class);
+        Mockito.doThrow(exceptionClass).when(pbdMock).unplug(connectionMock);
+        xenserver625StorageProcessor.unplugPbd(connectionMock, pbdMock);
+    }
+
+    @Test
+    @PrepareForTest({Host.class, SR.class})
+    public void createNewFileSrTestThrowingXenAPIException() throws XenAPIException, XmlRpcException {
+        prepareAndExecuteTestcreateNewFileSrTestThrowingException(XenAPIException.class);
+    }
+
+    @Test
+    @PrepareForTest({Host.class, SR.class})
+    public void createNewFileSrTestThrowingXmlRpcException() throws XenAPIException, XmlRpcException {
+        prepareAndExecuteTestcreateNewFileSrTestThrowingException(XmlRpcException.class);
+    }
+
+    @Test(expected = RuntimeException.class)
+    @PrepareForTest({Host.class, SR.class})
+    public void createNewFileSrTestThrowingRuntimeException() throws XenAPIException, XmlRpcException {
+        prepareAndExecuteTestcreateNewFileSrTestThrowingException(RuntimeException.class);
+    }
+
+    private void prepareAndExecuteTestcreateNewFileSrTestThrowingException(Class<? extends Throwable> exceptionClass) throws XenAPIException, XmlRpcException {
+        String uuid = "hostUuid";
+        Mockito.when(citrixResourceBase._host.getUuid()).thenReturn(uuid);
+
+        String srUuid = UUID.nameUUIDFromBytes(pathMock.getBytes()).toString();
+
+        Host hostMock = Mockito.mock(Host.class);
+
+        PowerMockito.mockStatic(Host.class);
+        PowerMockito.when(Host.getByUuid(connectionMock, uuid)).thenReturn(hostMock);
+
+        PowerMockito.mockStatic(SR.class);
+        PowerMockito.when(SR.introduce(Mockito.eq(connectionMock), Mockito.eq(srUuid), Mockito.eq(pathMock), Mockito.eq(pathMock), Mockito.eq("file"), Mockito.eq("file"), Mockito.eq(false),
+                Mockito.anyMapOf(String.class, String.class))).thenThrow(Mockito.mock(exceptionClass));
+
+        Mockito.doNothing().when(xenserver625StorageProcessor).removeSrAndPbdIfPossible(Mockito.eq(connectionMock), Mockito.any(SR.class), Mockito.any(PBD.class));
+
+        SR sr = xenserver625StorageProcessor.createNewFileSr(connectionMock, pathMock);
+
+        assertNull(sr);
+        Mockito.verify(xenserver625StorageProcessor).removeSrAndPbdIfPossible(Mockito.eq(connectionMock), Mockito.any(SR.class), Mockito.any(PBD.class));
+    }
+
+    @Test
+    @PrepareForTest({Host.class, SR.class})
+    public void createNewFileSrTestThrowingDbUniqueException() throws XenAPIException, XmlRpcException {
+        String uuid = "hostUuid";
+        Mockito.when(citrixResourceBase._host.getUuid()).thenReturn(uuid);
+
+        SR srMock = Mockito.mock(SR.class);
+        Mockito.doReturn(srMock).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+        String srUuid = UUID.nameUUIDFromBytes(pathMock.getBytes()).toString();
+
+        Host hostMock = Mockito.mock(Host.class);
+
+        PowerMockito.mockStatic(Host.class);
+        PowerMockito.when(Host.getByUuid(connectionMock, uuid)).thenReturn(hostMock);
+
+        PowerMockito.mockStatic(SR.class);
+        InternalError dbUniquenessException = new InternalError("message: Db_exn.Uniqueness_constraint_violation(\"SR\", \"uuid\", \"fd3edbcf-f142-83d1-3fcb-029ca2446b68\")");
+
+        PowerMockito.when(SR.introduce(Mockito.eq(connectionMock), Mockito.eq(srUuid), Mockito.eq(pathMock), Mockito.eq(pathMock), Mockito.eq("file"), Mockito.eq("file"), Mockito.eq(false),
+                Mockito.anyMapOf(String.class, String.class))).thenThrow(dbUniquenessException);
+
+        Mockito.doNothing().when(xenserver625StorageProcessor).removeSrAndPbdIfPossible(Mockito.eq(connectionMock), Mockito.any(SR.class), Mockito.any(PBD.class));
+
+        SR sr = xenserver625StorageProcessor.createNewFileSr(connectionMock, pathMock);
+
+        Assert.assertEquals(srMock, sr);
+        Mockito.verify(xenserver625StorageProcessor, times(0)).removeSrAndPbdIfPossible(Mockito.eq(connectionMock), Mockito.any(SR.class), Mockito.any(PBD.class));
+        Mockito.verify(xenserver625StorageProcessor).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+    }
+
+    @Test
+    @PrepareForTest({Host.class, SR.class, PBD.class})
+    public void createNewFileSrTest() throws XenAPIException, XmlRpcException {
+        String uuid = "hostUuid";
+        Mockito.when(citrixResourceBase._host.getUuid()).thenReturn(uuid);
+
+        SR srMock = Mockito.mock(SR.class);
+        Mockito.doReturn(srMock).when(xenserver625StorageProcessor).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+        String srUuid = UUID.nameUUIDFromBytes(pathMock.getBytes()).toString();
+
+        Host hostMock = Mockito.mock(Host.class);
+
+        PowerMockito.mockStatic(Host.class);
+        PowerMockito.when(Host.getByUuid(connectionMock, uuid)).thenReturn(hostMock);
+
+        PowerMockito.mockStatic(SR.class);
+        PowerMockito.when(SR.introduce(Mockito.eq(connectionMock), Mockito.eq(srUuid), Mockito.eq(pathMock), Mockito.eq(pathMock), Mockito.eq("file"), Mockito.eq("file"), Mockito.eq(false),
+                Mockito.anyMapOf(String.class, String.class))).thenReturn(srMock);
+
+        PowerMockito.mockStatic(PBD.class);
+        PBD pbdMock = Mockito.mock(PBD.class);
+        PowerMockito.when(PBD.create(Mockito.eq(connectionMock), Mockito.any(Record.class))).thenReturn(pbdMock);
+
+        Mockito.doNothing().when(xenserver625StorageProcessor).removeSrAndPbdIfPossible(Mockito.eq(connectionMock), Mockito.any(SR.class), Mockito.any(PBD.class));
+        SR sr = xenserver625StorageProcessor.createNewFileSr(connectionMock, pathMock);
+
+        Assert.assertEquals(srMock, sr);
+        Mockito.verify(xenserver625StorageProcessor, times(0)).removeSrAndPbdIfPossible(Mockito.eq(connectionMock), Mockito.any(SR.class), Mockito.any(PBD.class));
+        Mockito.verify(xenserver625StorageProcessor, times(0)).retrieveAlreadyConfiguredSrWithoutException(connectionMock, pathMock);
+
+        Mockito.verify(srMock).scan(connectionMock);
+        Mockito.verify(pbdMock).plug(connectionMock);
+
+        PowerMockito.verifyStatic();
+        SR.introduce(Mockito.eq(connectionMock), Mockito.eq(srUuid), Mockito.eq(pathMock), Mockito.eq(pathMock), Mockito.eq("file"), Mockito.eq("file"), Mockito.eq(false),
+                Mockito.anyMapOf(String.class, String.class));
+        PBD.create(Mockito.eq(connectionMock), Mockito.any(Record.class));
+    }
+
+    @Test
+    public void removeSrAndPbdIfPossibleBothPbdAndSrNotNull() {
+        SR srMock = Mockito.mock(SR.class);
+        Mockito.doNothing().when(xenserver625StorageProcessor).forgetSr(connectionMock, srMock);
+
+        PBD pbdMock = Mockito.mock(PBD.class);
+        Mockito.doNothing().when(xenserver625StorageProcessor).unplugPbd(connectionMock, pbdMock);
+
+        xenserver625StorageProcessor.removeSrAndPbdIfPossible(connectionMock, srMock, pbdMock);
+
+        Mockito.verify(xenserver625StorageProcessor).forgetSr(connectionMock, srMock);
+        Mockito.verify(xenserver625StorageProcessor).unplugPbd(connectionMock, pbdMock);
+
+    }
+
+    @Test
+    public void removeSrAndPbdIfPossiblePbdNullAndSrNotNull() {
+        SR srMock = Mockito.mock(SR.class);
+        Mockito.doNothing().when(xenserver625StorageProcessor).forgetSr(connectionMock, srMock);
+
+        xenserver625StorageProcessor.removeSrAndPbdIfPossible(connectionMock, srMock, null);
+
+        Mockito.verify(xenserver625StorageProcessor).forgetSr(connectionMock, srMock);
+        Mockito.verify(xenserver625StorageProcessor, times(0)).unplugPbd(Mockito.eq(connectionMock), Mockito.any(PBD.class));
+
+    }
+
+    @Test
+    public void removeSrAndPbdIfPossiblePbdNotNullButSrNull() {
+        PBD pbdMock = Mockito.mock(PBD.class);
+        Mockito.doNothing().when(xenserver625StorageProcessor).unplugPbd(connectionMock, pbdMock);
+
+        xenserver625StorageProcessor.removeSrAndPbdIfPossible(connectionMock, null, pbdMock);
+
+        Mockito.verify(xenserver625StorageProcessor, times(0)).forgetSr(Mockito.eq(connectionMock), Mockito.any(SR.class));
+        Mockito.verify(xenserver625StorageProcessor).unplugPbd(connectionMock, pbdMock);
+
+    }
+
+    @Test
+    public void removeSrAndPbdIfPossibleBothPbdAndSrNull() {
+        xenserver625StorageProcessor.removeSrAndPbdIfPossible(connectionMock, null, null);
+
+        Mockito.verify(xenserver625StorageProcessor, times(0)).forgetSr(Mockito.eq(connectionMock), Mockito.any(SR.class));
+        Mockito.verify(xenserver625StorageProcessor, times(0)).unplugPbd(Mockito.eq(connectionMock), Mockito.any(PBD.class));
+
+    }
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services