Deal with Storage Manager tech debt
diff --git a/api/src/main/java/com/cloud/storage/StorageService.java b/api/src/main/java/com/cloud/storage/StorageService.java
index a29c8f6..65f0904 100644
--- a/api/src/main/java/com/cloud/storage/StorageService.java
+++ b/api/src/main/java/com/cloud/storage/StorageService.java
@@ -17,7 +17,6 @@
 
 package com.cloud.storage;
 
-import java.net.UnknownHostException;
 import java.util.Map;
 
 import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
@@ -35,10 +34,8 @@
 import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
 
 import com.cloud.exception.DiscoveryException;
-import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceInUseException;
 import com.cloud.exception.ResourceUnavailableException;
 import org.apache.cloudstack.api.command.admin.storage.heuristics.CreateSecondaryStorageSelectorCmd;
 import org.apache.cloudstack.api.command.admin.storage.heuristics.RemoveSecondaryStorageSelectorCmd;
@@ -55,12 +52,9 @@
      *            storage pool.
      * @return
      *            The StoragePool created.
-     * @throws ResourceInUseException
      * @throws IllegalArgumentException
-     * @throws UnknownHostException
-     * @throws ResourceUnavailableException
      */
-    StoragePool createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceUnavailableException;
+    StoragePool createPool(CreateStoragePoolCmd cmd) throws IllegalArgumentException;
 
     ImageStore createSecondaryStagingStore(CreateSecondaryStagingStoreCmd cmd);
 
@@ -79,10 +73,8 @@
      * @param primaryStorageId
      *            - the primaryStorageId
      * @return the primary storage pool
-     * @throws ResourceUnavailableException
-     * @throws InsufficientCapacityException
      */
-    StoragePool preparePrimaryStorageForMaintenance(Long primaryStorageId) throws ResourceUnavailableException, InsufficientCapacityException;
+    StoragePool preparePrimaryStorageForMaintenance(Long primaryStorageId);
 
     /**
      * Complete maintenance for primary storage
@@ -108,7 +100,7 @@
 
     boolean deleteSecondaryStagingStore(DeleteSecondaryStagingStoreCmd cmd);
 
-    ImageStore discoverImageStore(String name, String url, String providerName, Long zoneId, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
+    ImageStore discoverImageStore(String name, String url, String providerName, Long zoneId, Map<String, String> details) throws IllegalArgumentException, InvalidParameterValueException;
 
     /**
      * Migrate existing NFS to use object store.
@@ -134,7 +126,7 @@
 
     void removeSecondaryStorageHeuristic(RemoveSecondaryStorageSelectorCmd cmd);
 
-    ObjectStore discoverObjectStore(String name, String url, Long size, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
+    ObjectStore discoverObjectStore(String name, String url, Long size, String providerName, Map<String, String> details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
 
     boolean deleteObjectStore(DeleteObjectStoragePoolCmd cmd);
 
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java
index 585fd1b..1df2c09 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java
@@ -26,7 +26,6 @@
 import org.apache.cloudstack.api.response.ImageStoreResponse;
 import org.apache.cloudstack.api.response.ZoneResponse;
 
-import com.cloud.exception.DiscoveryException;
 import com.cloud.storage.ImageStore;
 import com.cloud.user.Account;
 import org.apache.commons.collections.MapUtils;
@@ -89,20 +88,15 @@
 
     @Override
     public void execute(){
-        try{
-            ImageStore result = _storageService.discoverImageStore(null, getUrl(), "NFS", getZoneId(), getDetails());
-            ImageStoreResponse storeResponse = null;
-            if (result != null ) {
-                    storeResponse = _responseGenerator.createImageStoreResponse(result);
-                    storeResponse.setResponseName(getCommandName());
-                    storeResponse.setObjectName("secondarystorage");
-                    setResponseObject(storeResponse);
-            } else {
-                throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage");
-            }
-        } catch (DiscoveryException ex) {
-            logger.warn("Exception: ", ex);
-            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
+        ImageStore result = _storageService.discoverImageStore(null, getUrl(), "NFS", getZoneId(), getDetails());
+        ImageStoreResponse storeResponse = null;
+        if (result != null ) {
+                storeResponse = _responseGenerator.createImageStoreResponse(result);
+                storeResponse.setResponseName(getCommandName());
+                storeResponse.setObjectName("secondarystorage");
+                setResponseObject(storeResponse);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage");
         }
     }
 }
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java
index 72e2e96..4f50b77 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java
@@ -18,7 +18,6 @@
 
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 
@@ -31,7 +30,6 @@
 import org.apache.cloudstack.api.response.ImageStoreResponse;
 import org.apache.cloudstack.api.response.ZoneResponse;
 
-import com.cloud.exception.DiscoveryException;
 import com.cloud.storage.ImageStore;
 import com.cloud.user.Account;
 
@@ -79,11 +77,10 @@
     public Map<String, String> getDetails() {
         Map<String, String> detailsMap = null;
         if (details != null && !details.isEmpty()) {
-            detailsMap = new HashMap<String, String>();
+            detailsMap = new HashMap<>();
             Collection<?> props = details.values();
-            Iterator<?> iter = props.iterator();
-            while (iter.hasNext()) {
-                HashMap<String, String> detail = (HashMap<String, String>)iter.next();
+            for (Object prop : props) {
+                HashMap<String, String> detail = (HashMap<String, String>) prop;
                 String key = detail.get("key");
                 String value = detail.get("value");
                 detailsMap.put(key, value);
@@ -123,20 +120,15 @@
 
     @Override
     public void execute(){
-        try{
-            ImageStore result = _storageService.discoverImageStore(getName(), getUrl(), getProviderName(), getZoneId(), getDetails());
-            ImageStoreResponse storeResponse = null;
-            if (result != null) {
-                storeResponse = _responseGenerator.createImageStoreResponse(result);
-                storeResponse.setResponseName(getCommandName());
-                storeResponse.setObjectName("imagestore");
-                setResponseObject(storeResponse);
-            } else {
-                throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage");
-            }
-        } catch (DiscoveryException ex) {
-            logger.warn("Exception: ", ex);
-            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
+        ImageStore result = _storageService.discoverImageStore(getName(), getUrl(), getProviderName(), getZoneId(), getDetails());
+        ImageStoreResponse storeResponse;
+        if (result != null) {
+            storeResponse = _responseGenerator.createImageStoreResponse(result);
+            storeResponse.setResponseName(getCommandName());
+            storeResponse.setObjectName("imagestore");
+            setResponseObject(storeResponse);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage");
         }
     }
 }
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreS3CMD.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreS3CMD.java
index 75fcf12..d90a14f 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreS3CMD.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreS3CMD.java
@@ -48,15 +48,14 @@
 import org.apache.cloudstack.api.response.ImageStoreResponse;
 
 import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.DiscoveryException;
 import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.NetworkRuleConflictException;
 import com.cloud.exception.ResourceAllocationException;
 import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.storage.ImageStore;
 
-@APICommand(name = "addImageStoreS3", description = "Adds S3 Image Store", responseObject = ImageStoreResponse.class, since = "4.7.0",
-        requestHasSensitiveInfo = true, responseHasSensitiveInfo = false)
+@APICommand(name = "addImageStoreS3", description = "Adds S3 Image Store", responseObject = ImageStoreResponse.class,
+        since = "4.7.0", responseHasSensitiveInfo = false)
 public final class AddImageStoreS3CMD extends BaseCmd implements ClientOptions {
 
     private static final String s_name = "addImageStoreS3Response";
@@ -73,32 +72,32 @@
     @Parameter(name = S3_BUCKET_NAME, type = STRING, required = true, description = "Name of the storage bucket")
     private String bucketName;
 
-    @Parameter(name = S3_SIGNER, type = STRING, required = false, description = "Signer Algorithm to use, either S3SignerType or AWSS3V4SignerType")
+    @Parameter(name = S3_SIGNER, type = STRING, description = "Signer Algorithm to use, either S3SignerType or AWSS3V4SignerType")
     private String signer;
 
-    @Parameter(name = S3_HTTPS_FLAG, type = BOOLEAN, required = false, description = "Use HTTPS instead of HTTP")
+    @Parameter(name = S3_HTTPS_FLAG, type = BOOLEAN, description = "Use HTTPS instead of HTTP")
     private Boolean httpsFlag;
 
-    @Parameter(name = S3_CONNECTION_TIMEOUT, type = INTEGER, required = false, description = "Connection timeout (milliseconds)")
+    @Parameter(name = S3_CONNECTION_TIMEOUT, type = INTEGER, description = "Connection timeout (milliseconds)")
     private Integer connectionTimeout;
 
-    @Parameter(name = S3_MAX_ERROR_RETRY, type = INTEGER, required = false, description = "Maximum number of times to retry on error")
+    @Parameter(name = S3_MAX_ERROR_RETRY, type = INTEGER, description = "Maximum number of times to retry on error")
     private Integer maxErrorRetry;
 
-    @Parameter(name = S3_SOCKET_TIMEOUT, type = INTEGER, required = false, description = "Socket timeout (milliseconds)")
+    @Parameter(name = S3_SOCKET_TIMEOUT, type = INTEGER, description = "Socket timeout (milliseconds)")
     private Integer socketTimeout;
 
-    @Parameter(name = S3_CONNECTION_TTL, type = INTEGER, required = false, description = "Connection TTL (milliseconds)")
+    @Parameter(name = S3_CONNECTION_TTL, type = INTEGER, description = "Connection TTL (milliseconds)")
     private Integer connectionTtl;
 
-    @Parameter(name = S3_USE_TCP_KEEPALIVE, type = BOOLEAN, required = false, description = "Whether TCP keep-alive is used")
+    @Parameter(name = S3_USE_TCP_KEEPALIVE, type = BOOLEAN, description = "Whether TCP keep-alive is used")
     private Boolean useTCPKeepAlive;
 
     @Override
     public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
         ResourceAllocationException, NetworkRuleConflictException {
 
-        Map<String, String> dm = new HashMap();
+        Map<String, String> dm = new HashMap<>();
 
         dm.put(ApiConstants.S3_ACCESS_KEY, getAccessKey());
         dm.put(ApiConstants.SECRET_KEY, getSecretKey());
@@ -127,20 +126,15 @@
             dm.put(ApiConstants.S3_USE_TCP_KEEPALIVE, getUseTCPKeepAlive().toString());
         }
 
-        try{
-            ImageStore result = _storageService.discoverImageStore(null, null, "S3", null, dm);
-            ImageStoreResponse storeResponse;
-            if (result != null) {
-                storeResponse = _responseGenerator.createImageStoreResponse(result);
-                storeResponse.setResponseName(getCommandName());
-                storeResponse.setObjectName("imagestore");
-                setResponseObject(storeResponse);
-            } else {
-                throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add S3 Image Store.");
-            }
-        } catch (DiscoveryException ex) {
-            logger.warn("Exception: ", ex);
-            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
+        ImageStore result = _storageService.discoverImageStore(null, null, "S3", null, dm);
+        ImageStoreResponse storeResponse;
+        if (result != null) {
+            storeResponse = _responseGenerator.createImageStoreResponse(result);
+            storeResponse.setResponseName(getCommandName());
+            storeResponse.setObjectName("imagestore");
+            setResponseObject(storeResponse);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add S3 Image Store.");
         }
     }
 
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java
index 2aef856..6b5bc63 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java
@@ -16,7 +16,6 @@
 // under the License.
 package org.apache.cloudstack.api.command.admin.storage;
 
-import java.net.UnknownHostException;
 import java.util.Map;
 
 
@@ -31,8 +30,6 @@
 import org.apache.cloudstack.api.response.StoragePoolResponse;
 import org.apache.cloudstack.api.response.ZoneResponse;
 
-import com.cloud.exception.ResourceInUseException;
-import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.storage.StoragePool;
 import com.cloud.user.Account;
 
@@ -46,53 +43,85 @@
     //////////////// API parameters /////////////////////
     /////////////////////////////////////////////////////
 
-    @Parameter(name = ApiConstants.CLUSTER_ID, type = CommandType.UUID, entityType = ClusterResponse.class, description = "The cluster ID for the storage pool")
+    @Parameter(name = ApiConstants.CLUSTER_ID,
+            type = CommandType.UUID,
+            entityType = ClusterResponse.class,
+            description = "The cluster ID for the storage pool")
     private Long clusterId;
 
-    @Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, description = "The details for the storage pool")
+    @Parameter(name = ApiConstants.DETAILS,
+            type = CommandType.MAP,
+            description = "The details for the storage pool")
     private Map details;
 
-    @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "The name for the storage pool")
+    @Parameter(name = ApiConstants.NAME,
+            type = CommandType.STRING,
+            required = true,
+            description = "The name for the storage pool")
     private String storagePoolName;
 
-    @Parameter(name = ApiConstants.POD_ID, type = CommandType.UUID, entityType = PodResponse.class, description = "The Pod ID for the storage pool")
+    @Parameter(name = ApiConstants.POD_ID,
+            type = CommandType.UUID,
+            entityType = PodResponse.class,
+            description = "The Pod ID for the storage pool")
     private Long podId;
 
-    @Parameter(name = ApiConstants.TAGS, type = CommandType.STRING, description = "The tags for the storage pool")
+    @Parameter(name = ApiConstants.TAGS,
+            type = CommandType.STRING,
+            description = "The tags for the storage pool")
     private String tags;
 
-    @Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS, type = CommandType.STRING,
+    @Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS,
+            type = CommandType.STRING,
             description = "comma separated list of storage access groups for connecting to hosts having those specific groups", since = "4.21.0")
     private String storageAccessGroups;
 
-    @Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "The URL of the storage pool")
+    @Parameter(name = ApiConstants.URL,
+            type = CommandType.STRING,
+            required = true,
+            description = "The URL of the storage pool")
     private String url;
 
-    @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "The Zone ID for the storage pool")
+    @Parameter(name = ApiConstants.ZONE_ID,
+            type = CommandType.UUID,
+            entityType = ZoneResponse.class,
+            required = true,
+            description = "The Zone ID for the storage pool")
     private Long zoneId;
 
-    @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, required = false, description = "The storage provider name")
+    @Parameter(name = ApiConstants.PROVIDER,
+            type = CommandType.STRING,
+            description = "The storage provider name")
     private String storageProviderName;
 
-    @Parameter(name = ApiConstants.SCOPE, type = CommandType.STRING, required = false, description = "The scope of the storage: cluster or zone")
+    @Parameter(name = ApiConstants.SCOPE,
+            type = CommandType.STRING,
+            description = "The scope of the storage: cluster or zone")
     private String scope;
 
-    @Parameter(name = ApiConstants.MANAGED, type = CommandType.BOOLEAN, required = false, description = "Whether the storage should be managed by CloudStack")
+    @Parameter(name = ApiConstants.MANAGED,
+            type = CommandType.BOOLEAN,
+            description = "Whether the storage should be managed by CloudStack")
     private Boolean managed;
 
-    @Parameter(name = ApiConstants.CAPACITY_IOPS, type = CommandType.LONG, required = false, description = "IOPS CloudStack can provision from this storage pool")
+    @Parameter(name = ApiConstants.CAPACITY_IOPS,
+            type = CommandType.LONG,
+            description = "IOPS CloudStack can provision from this storage pool")
     private Long capacityIops;
 
-    @Parameter(name = ApiConstants.CAPACITY_BYTES, type = CommandType.LONG, required = false, description = "Bytes CloudStack can provision from this storage pool")
+    @Parameter(name = ApiConstants.CAPACITY_BYTES,
+            type = CommandType.LONG,
+            description = "Bytes CloudStack can provision from this storage pool")
     private Long capacityBytes;
 
     @Parameter(name = ApiConstants.HYPERVISOR,
                type = CommandType.STRING,
-               required = false,
                description = "Hypervisor type of the hosts in zone that will be attached to this storage pool. KVM, VMware supported as of now.")
     private String hypervisor;
 
-    @Parameter(name = ApiConstants.IS_TAG_A_RULE, type = CommandType.BOOLEAN, description = ApiConstants.PARAMETER_DESCRIPTION_IS_TAG_A_RULE)
+    @Parameter(name = ApiConstants.IS_TAG_A_RULE,
+            type = CommandType.BOOLEAN,
+            description = ApiConstants.PARAMETER_DESCRIPTION_IS_TAG_A_RULE)
     private Boolean isTagARule;
 
     /////////////////////////////////////////////////////
@@ -175,15 +204,6 @@
             } else {
                 throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add storage pool");
             }
-        } catch (ResourceUnavailableException ex1) {
-            logger.warn("Exception: ", ex1);
-            throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex1.getMessage());
-        } catch (ResourceInUseException ex2) {
-            logger.warn("Exception: ", ex2);
-            throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex2.getMessage());
-        } catch (UnknownHostException ex3) {
-            logger.warn("Exception: ", ex3);
-            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex3.getMessage());
         } catch (Exception ex4) {
             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex4.getMessage());
         }
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStoragePoolCmd.java
index 4b0a6ba..f37559c 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStoragePoolCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStoragePoolCmd.java
@@ -131,7 +131,7 @@
         return ApiCommandResourceType.StoragePool;
     }
 
-    public Map<String,String> getDetails() {
+    public Map<String,Object> getDetails() {
         return details;
     }
 
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java
index cc0c773..c322db8 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java
@@ -28,7 +28,6 @@
 import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.response.ImageStoreResponse;
 
-import com.cloud.exception.DiscoveryException;
 import com.cloud.storage.ImageStore;
 import com.cloud.user.Account;
 
@@ -83,25 +82,20 @@
 
     @Override
     public void execute() {
-        Map<String, String> dm = new HashMap<String, String>();
+        Map<String, String> dm = new HashMap<>();
         dm.put(ApiConstants.ACCOUNT, getAccount());
         dm.put(ApiConstants.USERNAME, getUsername());
         dm.put(ApiConstants.KEY, getKey());
 
-        try{
-            ImageStore result = _storageService.discoverImageStore(null, getUrl(), "Swift", null, dm);
-            ImageStoreResponse storeResponse = null;
-            if (result != null) {
-                storeResponse = _responseGenerator.createImageStoreResponse(result);
-                storeResponse.setResponseName(getCommandName());
-                storeResponse.setObjectName("secondarystorage");
-                setResponseObject(storeResponse);
-            } else {
-                throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Swift secondary storage");
-            }
-        } catch (DiscoveryException ex) {
-            logger.warn("Exception: ", ex);
-            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
+        ImageStore result = _storageService.discoverImageStore(null, getUrl(), "Swift", null, dm);
+        ImageStoreResponse storeResponse;
+        if (result != null) {
+            storeResponse = _responseGenerator.createImageStoreResponse(result);
+            storeResponse.setResponseName(getCommandName());
+            storeResponse.setObjectName("secondarystorage");
+            setResponseObject(storeResponse);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Swift secondary storage");
         }
     }
 }
diff --git a/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java b/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java
index 5909d09..fd87b09 100644
--- a/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java
+++ b/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java
@@ -71,6 +71,53 @@
             "Weight for CPU (as a value between 0 and 1) applied to compute capacity for Pods, Clusters and Hosts for COMBINED capacityType for ordering. Weight for RAM will be (1 - weight of CPU)",
             true, ConfigKey.Scope.Global);
 
+    ConfigKey<Integer> ExpungeDelay = new ConfigKey<>(
+            ConfigKey.CATEGORY_ADVANCED,
+            Integer.class,
+            "expunge.delay",
+            "86400",
+            "Determines how long (in seconds) to wait before actually expunging destroyed vm. The default value = the default value of expunge.interval",
+            false,
+            ConfigKey.Scope.Global,
+            null);
+    ConfigKey<Integer> ExpungeInterval = new ConfigKey<>(
+            ConfigKey.CATEGORY_ADVANCED,
+            Integer.class,
+            "expunge.interval",
+            "86400",
+            "The interval (in seconds) to wait before running the expunge thread.",
+            false,
+            ConfigKey.Scope.Global,
+            null);
+    ConfigKey<Integer> ExpungeWorkers = new ConfigKey<>(
+            ConfigKey.CATEGORY_ADVANCED,
+            Integer.class,
+            "expunge.workers",
+            "10",
+            "Number of workers performing expunge",
+            false,
+            ConfigKey.Scope.Global,
+            null);
+
+    ConfigKey<Integer> ExtractURLCleanUpInterval = new ConfigKey<>(
+            ConfigKey.CATEGORY_ADVANCED,
+            Integer.class,
+            "extract.url.cleanup.interval",
+            "7200",
+            "The interval (in seconds) to wait before cleaning up the extract URL's ",
+            false,
+            ConfigKey.Scope.Global,
+            null);
+    ConfigKey<Integer> ExtractURLExpirationInterval = new ConfigKey<>(
+            ConfigKey.CATEGORY_ADVANCED,
+            Integer.class,
+            "extract.url.expiration.interval",
+            "14400",
+            "The life of an extract URL after which it is deleted ",
+            false,
+            ConfigKey.Scope.Global,
+            null);
+
     /**
      * Is this for a VPC
      * @param offering the offering to check
diff --git a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
index d6604cf..741f4fb 100644
--- a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
+++ b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
@@ -241,6 +241,43 @@
             "while adding a new Secondary Storage. If the copy operation fails, the system falls back to downloading the template from the source URL.",
             true, ConfigKey.Scope.Zone, null);
 
+    ConfigKey<Integer> VmDiskThrottlingIopsReadRate = new ConfigKey<>(
+            Integer.class,
+            "vm.disk.throttling.iops_read_rate",
+            "Storage",
+            "0",
+            "Default disk I/O read rate in requests per second allowed in User vm's disk.",
+            true,
+            ConfigKey.Scope.Global,
+            null);
+    ConfigKey<Integer> VmDiskThrottlingIopsWriteRate = new ConfigKey<>(
+            Integer.class,
+            "vm.disk.throttling.iops_write_rate",
+            "Storage",
+            "0",
+            "Default disk I/O writerate in requests per second allowed in User vm's disk.",
+            true,
+            ConfigKey.Scope.Global,
+            null);
+    ConfigKey<Integer> VmDiskThrottlingBytesReadRate = new ConfigKey<>(
+            Integer.class,
+            "vm.disk.throttling.bytes_read_rate",
+            "Storage",
+            "0",
+            "Default disk I/O read rate in bytes per second allowed in User vm's disk.",
+            true,
+            ConfigKey.Scope.Global,
+            null);
+    ConfigKey<Integer> VmDiskThrottlingBytesWriteRate = new ConfigKey<>(
+            Integer.class,
+            "vm.disk.throttling.bytes_write_rate",
+            "Advanced",
+            "0",
+            "Default disk I/O writerate in bytes per second allowed in User vm's disk.",
+            true,
+            ConfigKey.Scope.Global,
+            null);
+
     /**
      * should we execute in sequence not involving any storages?
      * @return true if commands should execute in sequence
@@ -250,8 +287,8 @@
     }
 
     static boolean shouldExecuteInSequenceOnVmware(Long srcStoreId, Long dstStoreId) {
-        final Boolean fullClone = getFullCloneConfiguration(srcStoreId) || getFullCloneConfiguration(dstStoreId);
-        final Boolean allowParallel = getAllowParallelExecutionConfiguration();
+        final boolean fullClone = getFullCloneConfiguration(srcStoreId) || getFullCloneConfiguration(dstStoreId);
+        final boolean allowParallel = getAllowParallelExecutionConfiguration();
         return fullClone && !allowParallel;
     }
 
@@ -293,10 +330,6 @@
 
     boolean canPoolProvideStorageStats(StoragePool pool);
 
-    boolean poolProvidesCustomStorageStats(StoragePool pool);
-
-    Map<String, String> getCustomStorageStats(StoragePool pool);
-
     /**
      * Checks if a host has running VMs that are using its local storage pool.
      * @return true if local storage is active on the host
@@ -309,8 +342,6 @@
      */
     void cleanupStorage(boolean recurring);
 
-    String getPrimaryStorageNameLabel(VolumeVO volume);
-
     void createCapacityEntry(StoragePoolVO storagePool, short capacityType, long allocated);
 
     Answer sendToPool(StoragePool pool, long[] hostIdsToTryFirst, Command cmd) throws StorageUnavailableException;
@@ -323,8 +354,6 @@
 
     CapacityVO getStoragePoolUsedStats(Long zoneId, Long podId, Long clusterId, List<Long> poolIds);
 
-    List<StoragePoolVO> ListByDataCenterHypervisor(long datacenterId, HypervisorType type);
-
     List<VMInstanceVO> listByStoragePool(long storagePoolId);
 
     StoragePoolVO findLocalStorageOnHost(long hostId);
@@ -337,11 +366,9 @@
 
     boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool);
 
-    boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool);
-
     Host getHost(long hostId);
 
-    Host updateSecondaryStorage(long secStorageId, String newUrl);
+    void updateSecondaryStorage(long secStorageId, String newUrl);
 
     void removeStoragePoolFromCluster(long hostId, String iScsiName, StoragePool storagePool);
 
@@ -360,24 +387,19 @@
 
     /**
      * This comment is relevant to managed storage only.
-     *
      *  Long clusterId = only used for managed storage
-     *
      *  Some managed storage can be more efficient handling VM templates (via cloning) if it knows the capabilities of the compute cluster it is dealing with.
      *  If the compute cluster supports UUID resigning and the storage system can clone a volume from a volume, then this determines how much more space a
      *  new root volume (that makes use of a template) will take up on the storage system.
-     *
      *  For example, if a storage system can clone a volume from a volume and the compute cluster supports UUID resigning (relevant for hypervisors like
      *  XenServer and ESXi that put virtual disks in clustered file systems), then the storage system will need to determine if it already has a copy of
      *  the template or if it will need to create one first before cloning the template to a new volume to be used for the new root disk (assuming the root
-     *  disk is being deployed from a template). If the template doesn't already exists on the storage system, then you need to take into consideration space
+     *  disk is being deployed from a template). If the template doesn't already exist on the storage system, then you need to take into consideration space
      *  required for that template (stored in one volume) and space required for a new volume created from that template volume (for your new root volume).
-     *
      *  If UUID resigning is not available in the compute cluster or the storage system doesn't support cloning a volume from a volume, then for each new
      *  root disk that uses a template, CloudStack will have the template be copied down to a newly created volume on the storage system (i.e. no need
      *  to take into consideration the possible need to first create a volume on the storage system for a template that will be used for the root disk
      *  via cloning).
-     *
      *  Cloning volumes on the back-end instead of copying down a new template for each new volume helps to alleviate load on the hypervisors.
      */
     boolean storagePoolHasEnoughSpace(List<Pair<Volume, DiskProfile>> volume, StoragePool pool, Long clusterId);
diff --git a/engine/storage/cache/src/main/java/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java b/engine/storage/cache/src/main/java/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java
index 21ef851..7b99b23 100644
--- a/engine/storage/cache/src/main/java/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java
+++ b/engine/storage/cache/src/main/java/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java
@@ -32,6 +32,7 @@
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.configuration.ConfigurationManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.LogManager;
 
@@ -161,7 +162,7 @@
     public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
         cacheReplacementEnabled = Boolean.parseBoolean(configDao.getValue(Config.StorageCacheReplacementEnabled.key()));
         cacheReplaceMentInterval = NumbersUtil.parseInt(configDao.getValue(Config.StorageCacheReplacementInterval.key()), 86400);
-        workers = NumbersUtil.parseInt(configDao.getValue(Config.ExpungeWorkers.key()), 10);
+        workers = ConfigurationManager.ExpungeWorkers.value();
         executors = Executors.newScheduledThreadPool(workers, new NamedThreadFactory("StorageCacheManager-cache-replacement"));
         return true;
     }
diff --git a/plugins/storage/image/s3/src/main/java/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java b/plugins/storage/image/s3/src/main/java/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java
index 6318c19..686ef8c 100644
--- a/plugins/storage/image/s3/src/main/java/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java
+++ b/plugins/storage/image/s3/src/main/java/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java
@@ -25,6 +25,7 @@
 import javax.inject.Inject;
 
 
+import com.cloud.configuration.ConfigurationManager;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@@ -37,7 +38,6 @@
 import com.cloud.agent.api.to.S3TO;
 import com.cloud.configuration.Config;
 import com.cloud.storage.Storage.ImageFormat;
-import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.storage.S3.S3Utils;
 
 public class S3ImageStoreDriverImpl extends BaseImageStoreDriverImpl {
@@ -86,22 +86,18 @@
          */
         S3TO s3 = (S3TO)getStoreTO(store);
 
-        if(logger.isDebugEnabled()) {
-            logger.debug("Generating pre-signed s3 entity extraction URL for object: " + key);
-        }
+        logger.debug("Generating pre-signed s3 entity extraction URL for object: {}", key);
         Date expiration = new Date();
         long milliSeconds = expiration.getTime();
 
         // Get extract url expiration interval set in global configuration (in seconds)
-        String urlExpirationInterval = _configDao.getValue(Config.ExtractURLExpirationInterval.toString());
-
         // Expired after configured interval (in milliseconds), default 14400 seconds
-        milliSeconds += 1000 * NumbersUtil.parseInt(urlExpirationInterval, 14400);
+        milliSeconds += 1000L * ConfigurationManager.ExtractURLExpirationInterval.value();
         expiration.setTime(milliSeconds);
 
         URL s3url = S3Utils.generatePresignedUrl(s3, s3.getBucketName(), key, expiration);
 
-        logger.info("Pre-Signed URL = " + s3url.toString());
+        logger.info("Pre-Signed URL = {}", s3url.toString());
 
         return s3url.toString();
     }
diff --git a/plugins/storage/image/swift/src/main/java/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java b/plugins/storage/image/swift/src/main/java/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java
index 61ff57f..6670de1 100644
--- a/plugins/storage/image/swift/src/main/java/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java
+++ b/plugins/storage/image/swift/src/main/java/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java
@@ -24,6 +24,7 @@
 
 import javax.inject.Inject;
 
+import com.cloud.configuration.ConfigurationManager;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
@@ -33,7 +34,6 @@
 import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
 import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.cloudstack.storage.command.DownloadCommand;
 import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
 import org.apache.cloudstack.storage.image.BaseImageStoreDriverImpl;
@@ -44,7 +44,6 @@
 import com.cloud.agent.api.to.DataObjectType;
 import com.cloud.agent.api.to.DataStoreTO;
 import com.cloud.agent.api.to.SwiftTO;
-import com.cloud.configuration.Config;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.utils.SwiftUtil;
 import com.cloud.utils.exception.CloudRuntimeException;
@@ -57,8 +56,6 @@
     EndPointSelector _epSelector;
     @Inject
     StorageCacheManager cacheManager;
-    @Inject
-    ConfigurationDao _configDao;
 
     @Override
     public DataStoreTO getStoreTO(DataStore store) {
@@ -83,15 +80,11 @@
         String containerName = SwiftUtil.getContainerName(dataObject.getType().toString(), dataObject.getId());
         String objectName = installPath.split("\\/")[1];
         // Get extract url expiration interval set in global configuration (in seconds)
-        int urlExpirationInterval = Integer.parseInt(_configDao.getValue(Config.ExtractURLExpirationInterval.toString()));
+        int urlExpirationInterval = ConfigurationManager.ExtractURLExpirationInterval.value();
 
         URL swiftUrl = SwiftUtil.generateTempUrl(swiftTO, containerName, objectName, tempKey, urlExpirationInterval);
-        if (swiftUrl != null) {
-            logger.debug("Swift temp-url: " + swiftUrl.toString());
-            return swiftUrl.toString();
-        }
-
-        throw new CloudRuntimeException("Unable to create extraction URL");
+        logger.debug("Swift temp-url: {}", swiftUrl);
+        return swiftUrl.toString();
     }
 
     @Override
@@ -115,7 +108,7 @@
             throw new CloudRuntimeException(errMsg);
         }
 
-        CreateContext<CreateCmdResult> context = new CreateContext<CreateCmdResult>(callback, data);
+        CreateContext<CreateCmdResult> context = new CreateContext<>(callback, data);
         AsyncCallbackDispatcher<SwiftImageStoreDriverImpl, DownloadAnswer> caller = AsyncCallbackDispatcher.create(this);
         caller.setContext(context);
 
@@ -125,7 +118,5 @@
             caller.setCallback(caller.getTarget().createVolumeAsyncCallback(null, null));
         }
         ep.sendMessageAsync(dcmd, caller);
-
     }
-
 }
diff --git a/server/src/main/java/com/cloud/configuration/Config.java b/server/src/main/java/com/cloud/configuration/Config.java
index 2f4f7fa..03fc54e 100644
--- a/server/src/main/java/com/cloud/configuration/Config.java
+++ b/server/src/main/java/com/cloud/configuration/Config.java
@@ -415,31 +415,6 @@
             "The interval (in seconds) between cleanup for removed accounts",
             null),
     InstanceName("Advanced", AgentManager.class, String.class, "instance.name", "VM", "Name of the deployment instance.", "instanceName"),
-    ExpungeDelay(
-            "Advanced",
-            UserVmManager.class,
-            Integer.class,
-            "expunge.delay",
-            "86400",
-            "Determines how long (in seconds) to wait before actually expunging destroyed vm. The default value = the default value of expunge.interval",
-            null),
-    ExpungeInterval(
-            "Advanced",
-            UserVmManager.class,
-            Integer.class,
-            "expunge.interval",
-            "86400",
-            "The interval (in seconds) to wait before running the expunge thread.",
-            null),
-    ExpungeWorkers("Advanced", UserVmManager.class, Integer.class, "expunge.workers", "1", "Number of workers performing expunge ", null),
-    ExtractURLCleanUpInterval(
-            "Advanced",
-            ManagementServer.class,
-            Integer.class,
-            "extract.url.cleanup.interval",
-            "7200",
-            "The interval (in seconds) to wait before cleaning up the extract URL's ",
-            null),
     DisableExtraction(
             "Advanced",
             ManagementServer.class,
@@ -448,14 +423,6 @@
             "false",
             "Flag for disabling extraction of Templates, ISOs, Snapshots and volumes",
             null),
-    ExtractURLExpirationInterval(
-            "Advanced",
-            ManagementServer.class,
-            Integer.class,
-            "extract.url.expiration.interval",
-            "14400",
-            "The life of an extract URL after which it is deleted ",
-            null),
     HostStatsInterval(
             "Advanced",
             ManagementServer.class,
@@ -734,38 +701,6 @@
             "3600",
             "Time (in seconds) to wait before taking over a VM in transition state",
             null),
-    VmDiskThrottlingIopsReadRate(
-            "Advanced",
-            ManagementServer.class,
-            Integer.class,
-            "vm.disk.throttling.iops_read_rate",
-            "0",
-            "Default disk I/O read rate in requests per second allowed in User vm's disk.",
-            null),
-    VmDiskThrottlingIopsWriteRate(
-            "Advanced",
-            ManagementServer.class,
-            Integer.class,
-            "vm.disk.throttling.iops_write_rate",
-            "0",
-            "Default disk I/O writerate in requests per second allowed in User vm's disk.",
-            null),
-    VmDiskThrottlingBytesReadRate(
-            "Advanced",
-            ManagementServer.class,
-            Integer.class,
-            "vm.disk.throttling.bytes_read_rate",
-            "0",
-            "Default disk I/O read rate in bytes per second allowed in User vm's disk.",
-            null),
-    VmDiskThrottlingBytesWriteRate(
-            "Advanced",
-            ManagementServer.class,
-            Integer.class,
-            "vm.disk.throttling.bytes_write_rate",
-            "0",
-            "Default disk I/O writerate in bytes per second allowed in User vm's disk.",
-            null),
     ControlCidr(
             "Advanced",
             ManagementServer.class,
diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
index daefdbb..92d2601 100644
--- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -9440,7 +9440,8 @@
                 BYTES_MAX_READ_LENGTH, BYTES_MAX_WRITE_LENGTH, ADD_HOST_ON_SERVICE_RESTART_KVM, SET_HOST_DOWN_TO_MAINTENANCE,
                 VM_SERVICE_OFFERING_MAX_CPU_CORES, VM_SERVICE_OFFERING_MAX_RAM_SIZE, MIGRATE_VM_ACROSS_CLUSTERS,
                 ENABLE_ACCOUNT_SETTINGS_FOR_DOMAIN, ENABLE_DOMAIN_SETTINGS_FOR_CHILD_DOMAIN,
-                ALLOW_DOMAIN_ADMINS_TO_CREATE_TAGGED_OFFERINGS, EXPOSE_ERRORS_TO_USER, DELETE_QUERY_BATCH_SIZE, AllowNonRFC1918CompliantIPs, HostCapacityTypeCpuMemoryWeight
+                ALLOW_DOMAIN_ADMINS_TO_CREATE_TAGGED_OFFERINGS, EXPOSE_ERRORS_TO_USER, DELETE_QUERY_BATCH_SIZE, AllowNonRFC1918CompliantIPs, HostCapacityTypeCpuMemoryWeight,
+                ExpungeDelay, ExpungeInterval, ExpungeWorkers, ExtractURLCleanUpInterval, ExtractURLExpirationInterval
         };
     }
 
diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
index 9cb5155..066f75d 100644
--- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
@@ -19,16 +19,12 @@
 import static com.cloud.configuration.ConfigurationManagerImpl.SystemVMUseLocalStorage;
 import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
 
-import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLDecoder;
-import java.net.UnknownHostException;
 import java.nio.file.Files;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -36,7 +32,6 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -146,8 +141,8 @@
 import org.apache.cloudstack.storage.object.ObjectStore;
 import org.apache.cloudstack.storage.object.ObjectStoreEntity;
 import org.apache.cloudstack.storage.to.VolumeObjectTO;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.MapUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang.time.DateUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.BooleanUtils;
@@ -181,7 +176,6 @@
 import com.cloud.capacity.CapacityVO;
 import com.cloud.capacity.dao.CapacityDao;
 import com.cloud.cluster.ClusterManagerListener;
-import com.cloud.configuration.Config;
 import com.cloud.configuration.ConfigurationManager;
 import com.cloud.configuration.Resource.ResourceType;
 import com.cloud.cpu.CPU;
@@ -198,11 +192,9 @@
 import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.ConnectionException;
 import com.cloud.exception.DiscoveryException;
-import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.OperationTimedoutException;
 import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceInUseException;
 import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.exception.StorageConflictException;
 import com.cloud.exception.StorageUnavailableException;
@@ -220,11 +212,9 @@
 import com.cloud.org.Grouping.AllocationState;
 import com.cloud.resource.ResourceManager;
 import com.cloud.resource.ResourceState;
-import com.cloud.server.ConfigurationServer;
 import com.cloud.server.ManagementServer;
 import com.cloud.server.ManagementService;
 import com.cloud.server.StatsCollector;
-import com.cloud.service.dao.ServiceOfferingDetailsDao;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Storage.StoragePoolType;
 import com.cloud.storage.Volume.Type;
@@ -275,7 +265,6 @@
 import com.cloud.vm.DiskProfile;
 import com.cloud.vm.UserVmManager;
 import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.State;
 import com.cloud.vm.dao.VMInstanceDao;
 import com.google.common.collect.Sets;
@@ -358,8 +347,6 @@
     @Inject
     SnapshotDataFactory snapshotFactory;
     @Inject
-    ConfigurationServer _configServer;
-    @Inject
     DataStoreManager _dataStoreMgr;
     @Inject
     DataStoreProviderManager _dataStoreProviderMgr;
@@ -376,8 +363,6 @@
     @Inject
     SnapshotService _snapshotService;
     @Inject
-    public StorageService storageService;
-    @Inject
     StoragePoolTagsDao _storagePoolTagsDao;
     @Inject
     StoragePoolAndAccessGroupMapDao _storagePoolAccessGroupMapDao;
@@ -386,8 +371,6 @@
     @Inject
     DiskOfferingDetailsDao _diskOfferingDetailsDao;
     @Inject
-    ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
-    @Inject
     VsphereStoragePolicyDao _vsphereStoragePolicyDao;
     @Inject
     private AnnotationDao annotationDao;
@@ -416,22 +399,10 @@
     @Inject
     ResourceManager _resourceMgr;
     @Inject
-    StorageManager storageManager;
-    @Inject
     ManagementService managementService;
     @Inject
     JsInterpreterHelper jsInterpreterHelper;
 
-    protected List<StoragePoolDiscoverer> _discoverers;
-
-    public List<StoragePoolDiscoverer> getDiscoverers() {
-        return _discoverers;
-    }
-
-    public void setDiscoverers(List<StoragePoolDiscoverer> discoverers) {
-        _discoverers = discoverers;
-    }
-
     protected GenericSearchBuilder<StoragePoolHostVO, Long> UpHostsInPoolSearch;
     protected SearchBuilder<VMInstanceVO> StoragePoolSearch;
     protected SearchBuilder<StoragePoolVO> LocalStorageSearch;
@@ -449,44 +420,6 @@
 
     private static final String NFS_MOUNT_OPTIONS_INCORRECT = "An incorrect mount option was specified";
 
-    public boolean share(VMInstanceVO vm, List<VolumeVO> vols, HostVO host, boolean cancelPreviousShare) throws StorageUnavailableException {
-
-        // if pool is in maintenance and it is the ONLY pool available; reject
-        List<VolumeVO> rootVolForGivenVm = volumeDao.findByInstanceAndType(vm.getId(), Type.ROOT);
-        if (rootVolForGivenVm != null && rootVolForGivenVm.size() > 0) {
-            boolean isPoolAvailable = isPoolAvailable(rootVolForGivenVm.get(0).getPoolId());
-            if (!isPoolAvailable) {
-                throw new StorageUnavailableException("Can not share " + vm, rootVolForGivenVm.get(0).getPoolId());
-            }
-        }
-
-        // this check is done for maintenance mode for primary storage
-        // if any one of the volume is unusable, we return false
-        // if we return false, the allocator will try to switch to another PS if
-        // available
-        for (VolumeVO vol : vols) {
-            if (vol.getRemoved() != null) {
-                logger.warn("Volume: {} is removed, cannot share on this instance: {}", vol, vm);
-                // not ok to share
-                return false;
-            }
-        }
-        // ok to share
-        return true;
-    }
-
-    private boolean isPoolAvailable(Long poolId) {
-        // get list of all pools
-        List<StoragePoolVO> pools = _storagePoolDao.listAll();
-
-        // if no pools or 1 pool which is in maintenance
-        if (pools == null || pools.size() == 0 || (pools.size() == 1 && pools.get(0).getStatus().equals(StoragePoolStatus.Maintenance))) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
     protected void enableDefaultDatastoreDownloadRedirectionForExistingInstallations() {
         if (!configDepot.isNewConfig(DataStoreDownloadFollowRedirects)) {
             logger.trace("{} is not a new configuration, skipping updating its value",
@@ -496,36 +429,13 @@
         List<DataCenterVO> zones =
                 _dcDao.listAll(new Filter(1));
         if (CollectionUtils.isNotEmpty(zones)) {
-            logger.debug(String.format("Updating value for configuration: %s to true",
-                DataStoreDownloadFollowRedirects.key()));
+            logger.debug("Updating value for configuration: {} to true",
+                DataStoreDownloadFollowRedirects.key());
             configurationDao.update(DataStoreDownloadFollowRedirects.key(), "true");
         }
     }
 
     @Override
-    public List<StoragePoolVO> ListByDataCenterHypervisor(long datacenterId, HypervisorType type) {
-        List<StoragePoolVO> pools = _storagePoolDao.listByDataCenterId(datacenterId);
-        List<StoragePoolVO> retPools = new ArrayList<>();
-        for (StoragePoolVO pool : pools) {
-            if (pool.getStatus() != StoragePoolStatus.Up) {
-                continue;
-            }
-            if (pool.getScope() == ScopeType.ZONE) {
-                if (pool.getHypervisor() != null && pool.getHypervisor() == type) {
-                    retPools.add(pool);
-                }
-            } else {
-                ClusterVO cluster = _clusterDao.findById(pool.getClusterId());
-                if (type == cluster.getHypervisorType()) {
-                    retPools.add(pool);
-                }
-            }
-        }
-        Collections.shuffle(retPools);
-        return retPools;
-    }
-
-    @Override
     public boolean isLocalStorageActiveOnHost(Long hostId) {
         List<StoragePoolHostVO> storagePoolHostRefs = _storagePoolHostDao.listByHostId(hostId);
         for (StoragePoolHostVO storagePoolHostRef : storagePoolHostRefs) {
@@ -546,7 +456,7 @@
                 volumeSC.setJoinParameters("activeVmSB", "state", State.Starting, State.Running, State.Stopping, State.Migrating);
 
                 List<VolumeVO> volumes = volumeDao.search(volumeSC, null);
-                if (volumes.size() > 0) {
+                if (!volumes.isEmpty()) {
                     return true;
                 }
             }
@@ -616,31 +526,6 @@
     }
 
     @Override
-    public boolean poolProvidesCustomStorageStats(StoragePool pool) {
-        DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
-        DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
-        return storeDriver instanceof PrimaryDataStoreDriver && ((PrimaryDataStoreDriver)storeDriver).poolProvidesCustomStorageStats();
-    }
-
-    @Override
-    public Map<String, String> getCustomStorageStats(StoragePool pool) {
-        if (pool == null) {
-            return null;
-        }
-
-        if (!pool.isManaged()) {
-            return null;
-        }
-
-        DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
-        DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
-        if (storeDriver instanceof PrimaryDataStoreDriver) {
-            return ((PrimaryDataStoreDriver)storeDriver).getCustomStorageStats(pool);
-        }
-        return null;
-    }
-
-    @Override
     public Answer getVolumeStats(StoragePool pool, Command cmd) {
         DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
         DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
@@ -661,56 +546,27 @@
         return new GetVolumeStatsAnswer(getVolumeStatsCommand, "", statEntry);
     }
 
-    public Long chooseHostForStoragePool(StoragePoolVO poolVO, List<Long> avoidHosts, boolean sendToVmResidesOn, Long vmId) {
-        if (sendToVmResidesOn) {
-            if (vmId != null) {
-                VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
-                if (vmInstance != null) {
-                    Long hostId = vmInstance.getHostId();
-                    if (hostId != null && !avoidHosts.contains(vmInstance.getHostId())) {
-                        return hostId;
-                    }
-                }
-            }
-            /*
-             * Can't find the vm where host resides on(vm is destroyed? or
-             * volume is detached from vm), randomly choose a host to send the
-             * cmd
-             */
-        }
-        List<StoragePoolHostVO> poolHosts = _storagePoolHostDao.listByHostStatus(poolVO.getId(), Status.Up);
-        Collections.shuffle(poolHosts);
-        if (poolHosts != null && poolHosts.size() > 0) {
-            for (StoragePoolHostVO sphvo : poolHosts) {
-                if (!avoidHosts.contains(sphvo.getHostId())) {
-                    return sphvo.getHostId();
-                }
-            }
-        }
-        return null;
-    }
-
     @Override
     public boolean configure(String name, Map<String, Object> params) {
         Map<String, String> configs = _configDao.getConfiguration("management-server", params);
 
         _storagePoolAcquisitionWaitSeconds = NumbersUtil.parseInt(configs.get("pool.acquisition.wait.seconds"), 1800);
-        logger.info("pool.acquisition.wait.seconds is configured as " + _storagePoolAcquisitionWaitSeconds + " seconds");
+        logger.info("pool.acquisition.wait.seconds is configured as {} seconds", _storagePoolAcquisitionWaitSeconds);
 
         _agentMgr.registerForHostEvents(new StoragePoolMonitor(this, _storagePoolDao, _storagePoolHostDao, _dataStoreProviderMgr), true, false, true);
 
-        logger.info("Storage cleanup enabled: " + StorageCleanupEnabled.value() + ", interval: " + StorageCleanupInterval.value() + ", delay: " + StorageCleanupDelay.value()
-        + ", template cleanup enabled: " + TemplateCleanupEnabled.value());
+        logger.info("Storage cleanup enabled: {}, interval: {}, delay: {}, template cleanup enabled: {}",
+                StorageCleanupEnabled.value(),
+                StorageCleanupInterval.value(),
+                StorageCleanupDelay.value(),
+                TemplateCleanupEnabled.value());
 
-        String cleanupInterval = configs.get("extract.url.cleanup.interval");
-        _downloadUrlCleanupInterval = NumbersUtil.parseInt(cleanupInterval, 7200);
+        _downloadUrlCleanupInterval = ConfigurationManager.ExtractURLCleanUpInterval.value();
 
-        String urlExpirationInterval = configs.get("extract.url.expiration.interval");
-        _downloadUrlExpirationInterval = NumbersUtil.parseInt(urlExpirationInterval, 14400);
+        _downloadUrlExpirationInterval = ConfigurationManager.ExtractURLExpirationInterval.value();
 
-        String workers = configs.get("expunge.workers");
-        int wrks = NumbersUtil.parseInt(workers, 10);
-        _executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("StorageManager-Scavenger"));
+        int workers = ConfigurationManager.ExpungeWorkers.value();
+        _executor = Executors.newScheduledThreadPool(workers, new NamedThreadFactory("StorageManager-Scavenger"));
 
         _agentMgr.registerForHostEvents(ComponentContext.inject(LocalStoragePoolListener.class), true, false, false);
 
@@ -853,7 +709,7 @@
                 // not able to distinguish multiple local datastores that may be
                 // available on the host, to support smooth migration, we
                 // need to perform runtime upgrade here
-                if (pInfo.getHostPath().length() > 0) {
+                if (!pInfo.getHostPath().isEmpty()) {
                     pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), hostAddress, "", pInfo.getUuid());
                 }
             }
@@ -861,7 +717,9 @@
                 //the path can be different, but if they have the same uuid, assume they are the same storage
                 pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), hostAddress, null, pInfo.getUuid());
                 if (pool != null) {
-                    logger.debug("Found a storage pool: " + pInfo.getUuid() + ", but with different hostpath " + pInfo.getHostPath() + ", still treat it as the same pool");
+                    logger.debug("Found a storage pool: {}, but with different hostpath {}, still treat it as the same pool",
+                            pInfo.getUuid(),
+                            pInfo.getHostPath());
                 }
             }
 
@@ -964,7 +822,7 @@
     }
 
     @Override
-    public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceUnavailableException {
+    public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws  IllegalArgumentException {
         jsInterpreterHelper.ensureInterpreterEnabledIfParameterProvided(ApiConstants.IS_TAG_A_RULE, Boolean.TRUE.equals(cmd.isTagARule()));
 
         String providerName = cmd.getStorageProviderName();
@@ -1002,7 +860,7 @@
             throw new InvalidParameterValueException("zone id can't be null, if scope is zone");
         }
 
-        HypervisorType hypervisorType = HypervisorType.KVM;
+        HypervisorType hypervisorType; // defaults to HypervisorType.KVM
         if (scopeType == ScopeType.ZONE) {
             // ignore passed clusterId and podId
             clusterId = null;
@@ -1079,7 +937,7 @@
                 lifeCycle.attachZone(store, zoneScope, hypervisorType);
             }
         } catch (Exception e) {
-            logger.debug("Failed to add data store: " + e.getMessage(), e);
+            logger.debug("Failed to add data store: {}", e.getMessage(), e);
             try {
                 // clean up the db, just absorb the exception thrown in deletion with error logged, so that user can get error for adding data store
                 // not deleting data store.
@@ -1087,7 +945,7 @@
                     lifeCycle.deleteDataStore(store);
                 }
             } catch (Exception ex) {
-                logger.debug("Failed to clean up storage pool: " + ex.getMessage());
+                logger.debug("Failed to clean up storage pool: {}", ex.getMessage());
             }
             throw new CloudRuntimeException("Failed to add data store: " + e.getMessage(), e);
         }
@@ -1101,9 +959,7 @@
         try {
             uriInfo = UriUtils.getUriInfo(url);
         } catch (CloudRuntimeException cre) {
-            if (logger.isDebugEnabled()) {
-                logger.debug(String.format("URI validation for url: %s failed, returning empty uri params", url));
-            }
+            logger.debug("URI validation for url: {} failed, returning empty uri params", url);
             return uriParams;
         }
 
@@ -1111,9 +967,7 @@
         String storageHost = uriInfo.getStorageHost();
         String storagePath = uriInfo.getStoragePath();
         if (scheme == null) {
-            if (logger.isDebugEnabled()) {
-                logger.debug(String.format("Scheme for url: %s is not found, returning empty uri params", url));
-            }
+            logger.debug("Scheme for url: {} is not found, returning empty uri params", url);
             return uriParams;
         }
         boolean isHostOrPathBlank = StringUtils.isAnyBlank(storagePath, storageHost);
@@ -1150,12 +1004,7 @@
             }
         }
 
-        String hostPath = null;
-        try {
-            hostPath = URLDecoder.decode(storagePath, "UTF-8");
-        } catch (UnsupportedEncodingException e) {
-            logger.error("[ignored] we are on a platform not supporting \"UTF-8\"!?!", e);
-        }
+        String hostPath = URLDecoder.decode(storagePath, StringUtils.getPreferredCharset());
         if (hostPath == null) { // if decoding fails, use getPath() anyway
             hostPath = storagePath;
         }
@@ -1170,17 +1019,15 @@
         return uriParams;
     }
 
-    private Map<String, String> extractApiParamAsMap(Map ds) {
+    private Map<String, String> extractApiParamAsMap(Map<String, Object> ds) {
         Map<String, String> details = new HashMap<>();
         if (ds != null) {
-            Collection detailsCollection = ds.values();
-            Iterator it = detailsCollection.iterator();
-            while (it.hasNext()) {
-                HashMap d = (HashMap)it.next();
-                Iterator it2 = d.entrySet().iterator();
-                while (it2.hasNext()) {
-                    Map.Entry entry = (Map.Entry)it2.next();
-                    details.put((String)entry.getKey(), (String)entry.getValue());
+            Collection<Object> detailsCollection = ds.values();
+            for (Object o : detailsCollection) {
+                HashMap d = (HashMap) o;
+                for (Object object : d.entrySet()) {
+                    Map.Entry entry = (Map.Entry) object;
+                    details.put((String) entry.getKey(), (String) entry.getValue());
                 }
             }
         }
@@ -1242,17 +1089,14 @@
 
         String name = cmd.getName();
         if(StringUtils.isNotBlank(name)) {
-            logger.debug("Updating Storage Pool name to: " + name);
+            logger.debug("Updating Storage Pool name to: {}", name);
             pool.setName(name);
             _storagePoolDao.update(pool.getId(), pool);
         }
 
-
         final List<String> storagePoolTags = cmd.getTags();
         if (storagePoolTags != null) {
-            if (logger.isDebugEnabled()) {
-                logger.debug("Updating Storage Pool Tags to :" + storagePoolTags);
-            }
+            logger.debug("Updating Storage Pool Tags to : {}", storagePoolTags);
             if (pool.getPoolType() == StoragePoolType.DatastoreCluster) {
                 List<StoragePoolVO> childStoragePools = _storagePoolDao.listChildStoragePoolsInDatastoreCluster(pool.getId());
                 for (StoragePoolVO childPool : childStoragePools) {
@@ -1283,9 +1127,8 @@
         }
 
         // retrieve current details and merge/overlay input to capture changes
-        Map<String, String> details = null;
-        details = _storagePoolDetailsDao.listDetailsKeyPairs(id);
-        if (inputDetails != null) {
+        Map<String, String> details = _storagePoolDetailsDao.listDetailsKeyPairs(id);
+        if (!inputDetails.isEmpty()) {
             details.putAll(inputDetails);
             changes = true;
         }
@@ -1297,11 +1140,11 @@
 
             if (dataStoreLifeCycle instanceof PrimaryDataStoreLifeCycle) {
                 if (updatedCapacityBytes != null) {
-                    details.put(PrimaryDataStoreLifeCycle.CAPACITY_BYTES, updatedCapacityBytes != null ? String.valueOf(updatedCapacityBytes) : null);
+                    details.put(PrimaryDataStoreLifeCycle.CAPACITY_BYTES, String.valueOf(updatedCapacityBytes));
                     _storagePoolDao.updateCapacityBytes(id, updatedCapacityBytes);
                 }
                 if (updatedCapacityIops != null) {
-                    details.put(PrimaryDataStoreLifeCycle.CAPACITY_IOPS, updatedCapacityIops != null ? String.valueOf(updatedCapacityIops) : null);
+                    details.put(PrimaryDataStoreLifeCycle.CAPACITY_IOPS, String.valueOf(updatedCapacityIops));
                     _storagePoolDao.updateCapacityIops(id, updatedCapacityIops);
                 }
                 if (cmd.getUrl() != null) {
@@ -1348,9 +1191,7 @@
             throw new PermissionDeniedException("Cannot perform this operation, Cluster is currently disabled: " + clusterId);
         }
 
-        List<VirtualMachine.State> states = Arrays.asList(State.Starting, State.Running, State.Stopping, State.Migrating, State.Restoring);
-
-        Long id = primaryStorage.getId();
+        long id = primaryStorage.getId();
         Pair<List<VMInstanceVO>, Integer> vmsNotInClusterUsingPool = _vmInstanceDao.listByVmsNotInClusterUsingPool(clusterId, id);
         if (vmsNotInClusterUsingPool.second() != 0) {
             throw new CloudRuntimeException(String.format("Cannot change scope of the storage pool [%s] to cluster [%s] " +
@@ -1537,9 +1378,7 @@
                 throw new CloudRuntimeException("Storage Access Groups are not suitable for local storage");
             }
 
-            if (logger.isDebugEnabled()) {
-                logger.debug("Updating Storage Pool Access Group Maps to :" + storageAccessGroups);
-            }
+            logger.debug("Updating Storage Pool Access Group Maps to : {}", storageAccessGroups);
 
             if (storagePool.getPoolType() == StoragePoolType.DatastoreCluster) {
                 List<StoragePoolVO> childStoragePools = _storagePoolDao.listChildStoragePoolsInDatastoreCluster(storagePool.getId());
@@ -1562,9 +1401,8 @@
 
         String storageAccessGroupsOnZone = zoneVO.getStorageAccessGroups();
         List<String> zoneTagsList = parseTags(storageAccessGroupsOnZone);
-        List<String> newTags = storageAccessGroups;
 
-        List<String> existingTagsOnZone = (List<String>) CollectionUtils.intersection(newTags, zoneTagsList);
+        List<String> existingTagsOnZone = new ArrayList<>(CollectionUtils.intersection(storageAccessGroups, zoneTagsList));
 
         if (CollectionUtils.isNotEmpty(existingTagsOnZone)) {
             throw new CloudRuntimeException(String.format("access groups already exist on the zone: %s", existingTagsOnZone));
@@ -1580,10 +1418,9 @@
 
         List<String> podTagsList = parseTags(storageAccessGroupsOnPod);
         List<String> zoneTagsList = parseTags(storageAccessGroupsOnZone);
-        List<String> newTags = storageAccessGroups;
 
-        List<String> existingTagsOnPod = (List<String>) CollectionUtils.intersection(newTags, podTagsList);
-        List<String> existingTagsOnZone = (List<String>) CollectionUtils.intersection(newTags, zoneTagsList);
+        List<String> existingTagsOnPod = new ArrayList<>(CollectionUtils.intersection(storageAccessGroups, podTagsList));
+        List<String> existingTagsOnZone = new ArrayList<>(CollectionUtils.intersection(storageAccessGroups, zoneTagsList));
 
         if (CollectionUtils.isNotEmpty(existingTagsOnPod) || CollectionUtils.isNotEmpty(existingTagsOnZone)) {
             String message = "access groups already exist ";
@@ -1614,11 +1451,10 @@
         List<String> podTagsList = parseTags(storageAccessGroupsOnPod);
         List<String> zoneTagsList = parseTags(storageAccessGroupsOnZone);
         List<String> clusterTagsList = parseTags(storageAccessGroupsOnCluster);
-        List<String> newTags = storageAccessGroups;
 
-        List<String> existingTagsOnCluster = (List<String>) CollectionUtils.intersection(newTags, clusterTagsList);
-        List<String> existingTagsOnPod = (List<String>) CollectionUtils.intersection(newTags, podTagsList);
-        List<String> existingTagsOnZone = (List<String>) CollectionUtils.intersection(newTags, zoneTagsList);
+        List<String> existingTagsOnCluster = new ArrayList<>(CollectionUtils.intersection(storageAccessGroups, clusterTagsList));
+        List<String> existingTagsOnPod = new ArrayList<>(CollectionUtils.intersection(storageAccessGroups, podTagsList));
+        List<String> existingTagsOnZone = new ArrayList<>(CollectionUtils.intersection(storageAccessGroups, zoneTagsList));
 
         if (CollectionUtils.isNotEmpty(existingTagsOnCluster) || CollectionUtils.isNotEmpty(existingTagsOnPod) || CollectionUtils.isNotEmpty(existingTagsOnZone)) {
             String message = "access groups already exist ";
@@ -1683,7 +1519,7 @@
 
         StoragePoolVO sPool = _storagePoolDao.findById(id);
         if (sPool == null) {
-            logger.warn("Unable to find pool:" + id);
+            logger.warn("Unable to find pool: {}", id);
             throw new InvalidParameterValueException("Unable to find pool by id " + id);
         }
         if (sPool.getStatus() != StoragePoolStatus.Maintenance) {
@@ -1692,7 +1528,7 @@
         }
 
         if (sPool.getPoolType() == StoragePoolType.DatastoreCluster) {
-            // FR41 yet to handle on failure of deletion of any of the child storage pool
+            // FR41 yet to handle on failure of deletion any child storage pool
             if (checkIfDataStoreClusterCanbeDeleted(sPool, forced)) {
                 Transaction.execute(new TransactionCallbackNoReturn() {
                     @Override
@@ -1714,17 +1550,15 @@
     @Override
     public Pair<Map<String, String>, Boolean> getStoragePoolNFSMountOpts(StoragePool pool, Map<String, String> details) {
         boolean details_added = false;
-        if (!pool.getPoolType().equals(Storage.StoragePoolType.NetworkFilesystem)) {
-            return new Pair<>(details, details_added);
-        }
-
-        StoragePoolDetailVO nfsMountOpts = _storagePoolDetailsDao.findDetail(pool.getId(), ApiConstants.NFS_MOUNT_OPTIONS);
-        if (nfsMountOpts != null) {
-            if (details == null) {
-                details = new HashMap<>();
+        if (pool.getPoolType().equals(Storage.StoragePoolType.NetworkFilesystem)) {
+            StoragePoolDetailVO nfsMountOpts = _storagePoolDetailsDao.findDetail(pool.getId(), ApiConstants.NFS_MOUNT_OPTIONS);
+            if (nfsMountOpts != null) {
+                if (details == null) {
+                    details = new HashMap<>();
+                }
+                details.put(ApiConstants.NFS_MOUNT_OPTIONS, nfsMountOpts.getValue());
+                details_added = true;
             }
-            details.put(ApiConstants.NFS_MOUNT_OPTIONS, nfsMountOpts.getValue());
-            details_added = true;
         }
         return new Pair<>(details, details_added);
     }
@@ -1948,7 +1782,7 @@
                         }
                     }
                     catch (Exception ex) {
-                        logger.error("hostEnabled(long) failed for storage provider " + provider.getName(), ex);
+                        logger.error("hostEnabled(long) failed for storage provider {}", provider.getName(), ex);
                     }
                 }
             }
@@ -1957,7 +1791,7 @@
 
     @Override
     public BigDecimal getStorageOverProvisioningFactor(Long poolId) {
-        return new BigDecimal(CapacityManager.StorageOverprovisioningFactor.valueIn(poolId));
+        return BigDecimal.valueOf(CapacityManager.StorageOverprovisioningFactor.valueIn(poolId));
     }
 
     @Override
@@ -2009,7 +1843,7 @@
             }
         }
 
-        if (capacities.size() == 0) {
+        if (capacities.isEmpty()) {
             CapacityVO capacity = new CapacityVO(storagePool.getId(), storagePool.getDataCenterId(), storagePool.getPodId(), storagePool.getClusterId(), allocated, totalOverProvCapacity,
                     capacityType);
             capacity.setCapacityState(capacityState);
@@ -2051,7 +1885,7 @@
         if (hostIdsToAvoid != null) {
             hostIds.removeAll(hostIdsToAvoid);
         }
-        if (hostIds == null || hostIds.isEmpty()) {
+        if (hostIds.isEmpty()) {
             throw new StorageUnavailableException(String.format("Unable to send command to the pool %s due to there is no enabled hosts up in this cluster", pool), pool.getId());
         }
         for (Long hostId : hostIds) {
@@ -2062,7 +1896,7 @@
                     long targetHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(hostId, cmd);
                     answers.add(_agentMgr.send(targetHostId, cmd));
                 }
-                return new Pair<>(hostId, answers.toArray(new Answer[answers.size()]));
+                return new Pair<>(hostId, answers.toArray(new Answer[0]));
             } catch (AgentUnavailableException | OperationTimedoutException e) {
                 logger.debug("Unable to send storage pool command to {} via {}", pool::toString, () -> _hostDao.findById(hostId), () -> e);
             }
@@ -2121,8 +1955,8 @@
                                     _tmpltMgr.evictTemplateFromStoragePool(templatePoolVO);
                                 }
                             } catch (Exception e) {
-                                logger.error(String.format("Failed to clean up primary storage pool [%s] due to: [%s].", pool, e.getMessage()));
-                                logger.debug(String.format("Failed to clean up primary storage pool [%s].", pool), e);
+                                logger.error("Failed to clean up primary storage pool [{}] due to: [{}].", pool, e.getMessage());
+                                logger.debug("Failed to clean up primary storage pool [{}].", pool, e);
                             }
                         }
                     }
@@ -2141,7 +1975,7 @@
                              }
                         }
                         if (isVolumeSuspectedDestroyDuplicateOfVmVolume(vol)) {
-                            logger.warn(String.format("Skipping cleaning up %s as it could be a duplicate for another volume on same pool", vol));
+                            logger.warn("Skipping cleaning up {} as it could be a duplicate for another volume on same pool", vol);
                             continue;
                         }
                         try {
@@ -2174,7 +2008,7 @@
                     for (VolumeDataStoreVO volumeDataStore : volumeDataStores) {
                         VolumeVO volume = volumeDao.findById(volumeDataStore.getVolumeId());
                         if (volume == null) {
-                            logger.warn(String.format("Uploaded volume [%s] not found, so cannot be destroyed.", volumeDataStore.getVolumeId()));
+                            logger.warn("Uploaded volume [{}] not found, so cannot be destroyed.", volumeDataStore.getVolumeId());
                             continue;
                         }
                         try {
@@ -2186,7 +2020,7 @@
                             }
                             Host host = _hostDao.findById(ep.getId());
                             if (host != null && host.getManagementServerId() != null) {
-                                if (_serverId == host.getManagementServerId().longValue()) {
+                                if (_serverId == host.getManagementServerId()) {
                                     volService.destroyVolume(volume.getId());
                                     // decrement volume resource count
                                     _resourceLimitMgr.decrementVolumeResourceCount(volume.getAccountId(), volume.isDisplayVolume(),
@@ -2214,7 +2048,7 @@
                     for (TemplateDataStoreVO templateDataStore : templateDataStores) {
                         VMTemplateVO template = _templateDao.findById(templateDataStore.getTemplateId());
                         if (template == null) {
-                            logger.warn(String.format("Uploaded template [%s] not found, so cannot be destroyed.", templateDataStore.getTemplateId()));
+                            logger.warn("Uploaded template [{}] not found, so cannot be destroyed.", templateDataStore.getTemplateId());
                             continue;
                         }
                         try {
@@ -2226,7 +2060,7 @@
                             }
                             Host host = _hostDao.findById(ep.getId());
                             if (host != null && host.getManagementServerId() != null) {
-                                if (_serverId == host.getManagementServerId().longValue()) {
+                                if (_serverId == host.getManagementServerId()) {
                                     AsyncCallFuture<TemplateApiResult> future = _imageSrv.deleteTemplateAsync(tmplFactory.getTemplate(template.getId(), dataStore));
                                     TemplateApiResult result = future.get();
                                     if (!result.isSuccess()) {
@@ -2244,7 +2078,7 @@
                                     _templateStoreDao.removeByTemplateStore(template.getId(), dataStore.getId());
                                     // find all eligible image stores for this template
                                     List<DataStore> imageStores = _tmpltMgr.getImageStoreByTemplate(template.getId(), null);
-                                    if (imageStores == null || imageStores.size() == 0) {
+                                    if (imageStores == null || imageStores.isEmpty()) {
                                         template.setState(VirtualMachineTemplate.State.Inactive);
                                         _templateDao.update(template.getId(), template);
 
@@ -2336,7 +2170,7 @@
         List<VolumeVO> vmUsableVolumes = volumeDao.findUsableVolumesForInstance(vmId);
         for (VolumeVO vol : vmUsableVolumes) {
             if (gcVolume.getPoolId().equals(vol.getPoolId()) && gcVolume.getPath().equals(vol.getPath())) {
-                logger.debug(String.format("%s meant for garbage collection could a possible duplicate for %s", gcVolume, vol));
+                logger.debug("{} meant for garbage collection could a possible duplicate for {}", gcVolume, vol);
                 return true;
             }
         }
@@ -2345,10 +2179,8 @@
 
     /**
      * This method only applies for managed storage.
-     *
      * For XenServer and vSphere, see if we need to remove an SR or a datastore, then remove the underlying volume
      * from any applicable access control list (before other code attempts to delete the volume that supports it).
-     *
      * For KVM, just tell the underlying storage plug-in to remove the volume from any applicable access control list
      * (before other code attempts to delete the volume that supports it).
      */
@@ -2399,52 +2231,10 @@
         }
     }
 
-    @DB
-    List<Long> findAllVolumeIdInSnapshotTable(Long storeId) {
-        String sql = "SELECT volume_id from snapshots, snapshot_store_ref WHERE snapshots.id = snapshot_store_ref.snapshot_id and store_id=? GROUP BY volume_id";
-        List<Long> list = new ArrayList<>();
-        try {
-            TransactionLegacy txn = TransactionLegacy.currentTxn();
-            ResultSet rs = null;
-            PreparedStatement pstmt = null;
-            pstmt = txn.prepareAutoCloseStatement(sql);
-            pstmt.setLong(1, storeId);
-            rs = pstmt.executeQuery();
-            while (rs.next()) {
-                list.add(rs.getLong(1));
-            }
-            return list;
-        } catch (Exception e) {
-            logger.debug("failed to get all volumes who has snapshots in secondary storage " + storeId + " due to " + e.getMessage());
-            return null;
-        }
-
-    }
-
-    List<String> findAllSnapshotForVolume(Long volumeId) {
-        String sql = "SELECT backup_snap_id FROM snapshots WHERE volume_id=? and backup_snap_id is not NULL";
-        try {
-            TransactionLegacy txn = TransactionLegacy.currentTxn();
-            ResultSet rs = null;
-            PreparedStatement pstmt = null;
-            pstmt = txn.prepareAutoCloseStatement(sql);
-            pstmt.setLong(1, volumeId);
-            rs = pstmt.executeQuery();
-            List<String> list = new ArrayList<>();
-            while (rs.next()) {
-                list.add(rs.getString(1));
-            }
-            return list;
-        } catch (Exception e) {
-            logger.debug("failed to get all snapshots for a volume " + volumeId + " due to " + e.getMessage());
-            return null;
-        }
-    }
-
     @Override
     @DB
     public void cleanupSecondaryStorage(boolean recurring) {
-        // NOTE that object_store refactor will immediately delete the object from secondary storage when deleteTemplate etc api is issued.
+        // NOTE that object_store refactor will immediately delete the object from secondary storage when deleteTemplate etc. api is issued.
         // so here we don't need to issue DeleteCommand to resource anymore, only need to remove db entry.
         try {
             // Cleanup templates in template_store_ref
@@ -2456,7 +2246,7 @@
                     logger.debug("Secondary storage garbage collector found {} Templates to cleanup on template_store_ref for store: {}", destroyedTemplateStoreVOs.size(), store);
                     for (TemplateDataStoreVO destroyedTemplateStoreVO : destroyedTemplateStoreVOs) {
                         if (logger.isDebugEnabled()) {
-                            logger.debug("Deleting template store DB entry: " + destroyedTemplateStoreVO);
+                            logger.debug("Deleting template store DB entry: {}", destroyedTemplateStoreVO);
                         }
                         _templateStoreDao.remove(destroyedTemplateStoreVO.getId());
                     }
@@ -2474,13 +2264,11 @@
                         // check if this snapshot has child
                         SnapshotInfo snap = snapshotFactory.getSnapshot(destroyedSnapshotStoreVO.getSnapshotId(), store);
                         if (snap.getChild() != null) {
-                            logger.debug("Skip snapshot on store: " + destroyedSnapshotStoreVO + " , because it has child");
+                            logger.debug("Skip snapshot on store: {} , because it has child", destroyedSnapshotStoreVO);
                             continue;
                         }
 
-                        if (logger.isDebugEnabled()) {
-                            logger.debug("Deleting snapshot store DB entry: " + destroyedSnapshotStoreVO);
-                        }
+                        logger.debug("Deleting snapshot store DB entry: {}", destroyedSnapshotStoreVO);
 
                         List<SnapshotDataStoreVO> imageStoreRefs = _snapshotStoreDao.listBySnapshotAndDataStoreRole(destroyedSnapshotStoreVO.getSnapshotId(), DataStoreRole.Image);
                         if (imageStoreRefs.size() <= 1) {
@@ -2488,9 +2276,7 @@
                         }
                         SnapshotDataStoreVO snapshotOnPrimary = _snapshotStoreDao.findDestroyedReferenceBySnapshot(destroyedSnapshotStoreVO.getSnapshotId(), DataStoreRole.Primary);
                         if (snapshotOnPrimary != null) {
-                            if (logger.isDebugEnabled()) {
-                                logger.debug("Deleting snapshot on primary store reference DB entry: " + snapshotOnPrimary);
-                            }
+                            logger.debug("Deleting snapshot on primary store reference DB entry: {}", snapshotOnPrimary);
                             _snapshotStoreDao.remove(snapshotOnPrimary.getId());
                         }
                         _snapshotStoreDao.remove(destroyedSnapshotStoreVO.getId());
@@ -2509,9 +2295,7 @@
                     destroyedStoreVOs.addAll(_volumeDataStoreDao.listByVolumeState(Volume.State.Expunged));
                     logger.debug("Secondary storage garbage collector found {} volumes to cleanup on volume_store_ref for store: {}", destroyedStoreVOs.size(), store);
                     for (VolumeDataStoreVO destroyedStoreVO : destroyedStoreVOs) {
-                        if (logger.isDebugEnabled()) {
-                            logger.debug("Deleting volume store DB entry: " + destroyedStoreVO);
-                        }
+                        logger.debug("Deleting volume store DB entry: {}", destroyedStoreVO);
                         _volumeStoreDao.remove(destroyedStoreVO.getId());
                     }
 
@@ -2525,23 +2309,11 @@
     }
 
     @Override
-    public String getPrimaryStorageNameLabel(VolumeVO volume) {
-        Long poolId = volume.getPoolId();
-
-        // poolId is null only if volume is destroyed, which has been checked
-        // before.
-        assert poolId != null;
-        StoragePoolVO primaryDataStoreVO = _storagePoolDao.findById(poolId);
-        assert primaryDataStoreVO != null;
-        return primaryDataStoreVO.getUuid();
-    }
-
-    @Override
     @DB
     @ActionEvent(eventType = EventTypes.EVENT_MAINTENANCE_PREPARE_PRIMARY_STORAGE,
             eventDescription = "preparing storage pool for maintenance", async = true)
-    public PrimaryDataStoreInfo preparePrimaryStorageForMaintenance(Long primaryStorageId) throws ResourceUnavailableException, InsufficientCapacityException {
-        StoragePoolVO primaryStorage = null;
+    public PrimaryDataStoreInfo preparePrimaryStorageForMaintenance(Long primaryStorageId) {
+        StoragePoolVO primaryStorage;
         primaryStorage = _storagePoolDao.findById(primaryStorageId);
 
         if (primaryStorage == null) {
@@ -2586,14 +2358,12 @@
                 }
             }
         });
-        for (Iterator<StoragePoolVO> iteratorChildDatastore = childDatastores.listIterator(); iteratorChildDatastore.hasNext(); ) {
-            DataStore childStore = _dataStoreMgr.getDataStore(iteratorChildDatastore.next().getId(), DataStoreRole.Primary);
+        for (StoragePoolVO datastore : childDatastores) {
+            DataStore childStore = _dataStoreMgr.getDataStore(datastore.getId(), DataStoreRole.Primary);
             try {
                 lifeCycle.maintain(childStore);
             } catch (Exception e) {
-                if (logger.isDebugEnabled()) {
-                    logger.debug("Exception on maintenance preparation of one of the child datastores in datastore cluster {} with error {}", datastoreCluster, e);
-                }
+                logger.debug("Exception on maintenance preparation of one of the child datastores in datastore cluster {}", datastoreCluster, e);
                 // Set to ErrorInMaintenance state of all child storage pools and datastore cluster
                 for (StoragePoolVO childDatastore : childDatastores) {
                     childDatastore.setStatus(StoragePoolStatus.ErrorInMaintenance);
@@ -2612,7 +2382,7 @@
             eventDescription = "canceling maintenance for primary storage pool", async = true)
     public PrimaryDataStoreInfo cancelPrimaryStorageForMaintenance(CancelPrimaryStorageMaintenanceCmd cmd) throws ResourceUnavailableException {
         Long primaryStorageId = cmd.getId();
-        StoragePoolVO primaryStorage = null;
+        StoragePoolVO primaryStorage;
 
         primaryStorage = _storagePoolDao.findById(primaryStorageId);
 
@@ -2669,7 +2439,7 @@
         List<Long> poolIds = new ArrayList<>();
         poolIds.add(poolId);
         List<Long> hosts = _storagePoolHostDao.findHostsConnectedToPools(poolIds);
-        if (hosts.size() > 0) {
+        if (!hosts.isEmpty()) {
             Long hostId = hosts.get(0);
             ModifyStoragePoolCommand modifyStoragePoolCommand = new ModifyStoragePoolCommand(true, pool);
             final Answer answer = _agentMgr.easySend(hostId, modifyStoragePoolCommand);
@@ -2787,9 +2557,9 @@
             }
             if (dataStoreVO != null) {
                 if (dataStoreVO.getParent() != datastoreClusterPoolId) {
-                    logger.debug(String.format("Storage pool %s with uuid %s is found to be under datastore cluster %s at vCenter, " +
+                    logger.debug("Storage pool {} with uuid {} is found to be under datastore cluster {} at vCenter, " +
                                     "so moving the storage pool to be a child storage pool under the datastore cluster in CloudStack management server",
-                            childStoragePoolInfo.getName(), childStoragePoolInfo.getUuid(), datastoreClusterPool.getName()));
+                            childStoragePoolInfo.getName(), childStoragePoolInfo.getUuid(), datastoreClusterPool.getName());
                     dataStoreVO.setParent(datastoreClusterPoolId);
                     _storagePoolDao.update(dataStoreVO.getId(), dataStoreVO);
                     if (CollectionUtils.isNotEmpty(storageTags)) {
@@ -2801,9 +2571,7 @@
                         Set<StoragePoolTagVO> set = new LinkedHashSet<>(storageTags);
                         storageTags.clear();
                         storageTags.addAll(set);
-                        if (logger.isDebugEnabled()) {
-                            logger.debug("Updating Storage Pool Tags to :" + storageTags);
-                        }
+                        logger.debug("Updating Storage Pool Tags to : {}", storageTags);
                         _storagePoolTagsDao.persist(storageTags);
                     }
                 } else {
@@ -2908,11 +2676,11 @@
         }
 
         if (ArrayUtils.isNotEmpty(hostStorageAccessGroups)) {
-            logger.debug(String.format("Storage access groups on the host %s are %s", host, hostStorageAccessGroups));
+            logger.debug("Storage access groups on the host {} are {}", host, hostStorageAccessGroups);
         }
 
         if (CollectionUtils.isNotEmpty(storagePoolAccessGroups)) {
-            logger.debug(String.format("Storage access groups on the storage pool %s are %s", host, storagePoolAccessGroups));
+            logger.debug("Storage access groups on the storage pool {} are {}", host, storagePoolAccessGroups);
         }
 
         List<String> hostTagList = Arrays.asList(hostStorageAccessGroups);
@@ -2935,8 +2703,8 @@
                 List<String> destStorageAccessGroups = _storagePoolAccessGroupMapDao.getStorageAccessGroups(destPool.getId());
 
                 if (CollectionUtils.isNotEmpty(srcStorageAccessGroups) && CollectionUtils.isNotEmpty(destStorageAccessGroups)) {
-                    logger.debug(String.format("Storage access groups on source storage %s are %s and destination storage %s are %s",
-                            srcPool, srcStorageAccessGroups, destPool, destStorageAccessGroups));
+                    logger.debug("Storage access groups on source storage {} are {} and destination storage {} are {}",
+                            srcPool, srcStorageAccessGroups, destPool, destStorageAccessGroups);
                     List<String> intersection = new ArrayList<>(srcStorageAccessGroups);
                     intersection.retainAll(destStorageAccessGroups);
                     if (CollectionUtils.isNotEmpty(intersection)) {
@@ -2962,16 +2730,14 @@
                     List<String> srcStorageAccessGroups = _storagePoolAccessGroupMapDao.getStorageAccessGroups(srcPoolId);
                     List<String> destStorageAccessGroups = _storagePoolAccessGroupMapDao.getStorageAccessGroups(destPool.getId());
 
-                    logger.debug(String.format("Storage access groups on source storage %s are %s and destination storage %s are %s",
-                            srcPool, srcStorageAccessGroups, destPool, destStorageAccessGroups));
+                    logger.debug("Storage access groups on source storage {} are {} and destination storage {} are {}",
+                            srcPool, srcStorageAccessGroups, destPool, destStorageAccessGroups);
 
                     if (CollectionUtils.isEmpty(srcStorageAccessGroups) && CollectionUtils.isEmpty(destStorageAccessGroups)) {
                         return new Pair<>(true, "Success");
                     }
 
                     if (CollectionUtils.isNotEmpty(srcStorageAccessGroups) && CollectionUtils.isNotEmpty(destStorageAccessGroups)) {
-                        List<String> intersection = new ArrayList<>(srcStorageAccessGroups);
-                        intersection.retainAll(destStorageAccessGroups);
 
                         if (ArrayUtils.isNotEmpty(hostStorageAccessGroups)) {
                             boolean hasSrcCommon = srcStorageAccessGroups.stream()
@@ -3150,7 +2916,7 @@
             if (vo.getMsid() == _serverId) {
                 logger.info("Cleaning up storage maintenance jobs associated with Management server: {}", vo);
                 List<Long> poolIds = _storagePoolWorkDao.searchForPoolIdsForPendingWorkJobs(vo.getMsid());
-                if (poolIds.size() > 0) {
+                if (!poolIds.isEmpty()) {
                     for (Long poolId : poolIds) {
                         StoragePoolVO pool = _storagePoolDao.findById(poolId);
                         // check if pool is in an inconsistent state
@@ -3348,24 +3114,13 @@
     }
 
     @Override
-    public boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool) {
-        if (pool == null || !pool.isManaged()) {
-            return true;
-        }
-
-        DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
-        DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
-        return storeDriver instanceof PrimaryDataStoreDriver && ((PrimaryDataStoreDriver)storeDriver).canDisconnectHostFromStoragePool(host, pool);
-    }
-
-    @Override
     @DB
     public Host getHost(long hostId) {
         return _hostDao.findById(hostId);
     }
 
     @Override
-    public Host updateSecondaryStorage(long secStorageId, String newUrl) {
+    public void updateSecondaryStorage(long secStorageId, String newUrl) {
         HostVO secHost = _hostDao.findById(secStorageId);
         if (secHost == null) {
             throw new InvalidParameterValueException("Can not find out the secondary storage id: " + secStorageId);
@@ -3405,14 +3160,13 @@
                 throw new InvalidParameterValueException("can not change old scheme:" + oldUri.getScheme() + " to " + uri.getScheme());
             }
         } catch (URISyntaxException e) {
-            logger.debug("Failed to get uri from " + oldUrl);
+            logger.debug("Failed to get uri from {}", oldUrl);
         }
 
         secHost.setStorageUrl(newUrl);
         secHost.setGuid(newUrl);
         secHost.setName(newUrl);
         _hostDao.update(secHost.getId(), secHost);
-        return secHost;
     }
 
     @Override
@@ -3498,14 +3252,15 @@
         long futureIops = currentIops + requestedIops;
         boolean hasEnoughIops = futureIops <= pool.getCapacityIops();
         String hasCapacity = hasEnoughIops ? "has" : "does not have";
-        logger.debug(String.format("Pool [%s] %s enough IOPS to allocate volumes [%s].", pool, hasCapacity, requestedVolumes));
+        logger.debug("Pool [{}] {} enough IOPS to allocate volumes [{}].", pool, hasCapacity, requestedVolumes);
         return hasEnoughIops;
     }
 
     @Override
     public boolean storagePoolHasEnoughIops(List<Pair<Volume, DiskProfile>> requestedVolumes, StoragePool pool) {
         if (requestedVolumes == null || requestedVolumes.isEmpty() || pool == null) {
-            logger.debug(String.format("Cannot check if storage [%s] has enough IOPS to allocate volumes [%s].", pool, requestedVolumes));
+            logger.debug("Cannot check if storage [{}] has enough IOPS to allocate volumes [{}].",
+                    pool, requestedVolumes);
             return false;
         }
         if (checkIfPoolIopsCapacityNull(pool)) {
@@ -3556,12 +3311,12 @@
     @Override
     public boolean storagePoolHasEnoughSpace(List<Pair<Volume, DiskProfile>> volumeDiskProfilesList, StoragePool pool, Long clusterId) {
         if (CollectionUtils.isEmpty(volumeDiskProfilesList)) {
-            logger.debug(String.format("Cannot check if pool [%s] has enough space to allocate volumes because the volumes list is empty.", pool));
+            logger.debug("Cannot check if pool [{}] has enough space to allocate volumes because the volumes list is empty.", pool);
             return false;
         }
 
         if (!checkUsagedSpace(pool)) {
-            logger.debug(String.format("Cannot allocate pool [%s] because there is not enough space in this pool.", pool));
+            logger.debug("Cannot allocate pool [{}] because there is not enough space in this pool.", pool);
             return false;
         }
 
@@ -3590,7 +3345,7 @@
                 volumeVO = volumeDao.findById(volume.getId());
             }
 
-            // this if statement should resolve to true at most once per execution of the for loop its contained within (for a root disk that is
+            // this if statement should resolve to true at most once per execution of the for loop it's contained within (for a root disk that is
             // to leverage a template)
             if (volume.getTemplateId() != null) {
                 VMTemplateVO tmpl = _templateDao.findByIdIncludingRemoved(volume.getTemplateId());
@@ -3652,10 +3407,10 @@
             long targetHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(hostIds.get(0), cmd);
             return _agentMgr.send(targetHostId, cmd);
         } catch (AgentUnavailableException e) {
-            logger.debug("Unable to send storage pool command to " + pool + " via " + hostIds.get(0), e);
+            logger.debug("Unable to send storage pool command to {} via {}", pool, hostIds.get(0), e);
             throw new StorageUnavailableException("Unable to send command to the pool ", pool.getId());
         } catch (OperationTimedoutException e) {
-            logger.debug("Failed to process storage pool command to " + pool + " via " + hostIds.get(0), e);
+            logger.debug("Failed to process storage pool command to {} via {}", pool, hostIds.get(0), e);
             throw new StorageUnavailableException("Failed to process storage command to the pool ", pool.getId());
         }
     }
@@ -3739,14 +3494,14 @@
                 return false;
             }
             if (!AllowVolumeReSizeBeyondAllocation.valueIn(pool.getId())) {
-                logger.debug(String.format("Skipping the pool %s as %s is false", pool, AllowVolumeReSizeBeyondAllocation.key()));
+                logger.debug("Skipping the pool {} as {} is false", pool, AllowVolumeReSizeBeyondAllocation.key());
                 return false;
             }
 
             double storageAllocatedThresholdForResize = CapacityManager.StorageAllocatedCapacityDisableThresholdForVolumeSize.valueIn(pool.getId());
             if (usedPercentage > storageAllocatedThresholdForResize) {
-                logger.debug(String.format("Skipping the pool %s since its allocated percentage: %s has crossed the allocated %s: %s",
-                        pool, usedPercentage, CapacityManager.StorageAllocatedCapacityDisableThresholdForVolumeSize.key(), storageAllocatedThresholdForResize));
+                logger.debug("Skipping the pool {} since its allocated percentage: {} has crossed the allocated {}: {}",
+                        pool, usedPercentage, CapacityManager.StorageAllocatedCapacityDisableThresholdForVolumeSize.key(), storageAllocatedThresholdForResize);
                 return false;
             }
         }
@@ -3768,7 +3523,6 @@
     /**
      * Storage plug-ins for managed storage can be designed in such a way as to store a template on the primary storage once and
      * make use of it via storage-side cloning.
-     *
      * This method determines how many more bytes it will need for the template (if the template is already stored on the primary storage,
      * then the answer is 0).
      */
@@ -3850,34 +3604,37 @@
     @Override
     public boolean storagePoolCompatibleWithVolumePool(StoragePool pool, Volume volume) {
         if (pool == null || volume == null) {
-            logger.debug(String.format("Cannot check if storage pool [%s] is compatible with volume [%s].", pool, volume));
+            logger.debug("Cannot check if storage pool [{}] is compatible with volume [{}].", pool, volume);
             return false;
         }
 
         if (volume.getPoolId() == null) {
-            logger.debug(String.format("Volume [%s] is not allocated to any pool. Cannot check compatibility with pool [%s].", volume, pool));
+            logger.debug("Volume [{}] is not allocated to any pool. Cannot check compatibility with pool [{}].",
+                    volume, pool);
             return true;
         }
 
         StoragePool volumePool = _storagePoolDao.findById(volume.getPoolId());
         if (volumePool == null) {
-            logger.debug(String.format("Pool [%s] used by volume [%s] does not exist. Cannot check compatibility.", pool, volume));
+            logger.debug("Pool [{}] used by volume [{}] does not exist. Cannot check compatibility.", pool, volume);
             return true;
         }
 
         if (volume.getState() == Volume.State.Ready) {
             if (volumePool.getPoolType() == Storage.StoragePoolType.PowerFlex && pool.getPoolType() != Storage.StoragePoolType.PowerFlex) {
-                logger.debug(String.format("Pool [%s] with type [%s] does not match volume [%s] pool type [%s].", pool, pool.getPoolType(), volume, volumePool.getPoolType()));
+                logger.debug("Pool [{}] with type [{}] does not match volume [{}] pool type [{}].",
+                        pool, pool.getPoolType(), volume, volumePool.getPoolType());
                 return false;
             } else if (volumePool.getPoolType() != Storage.StoragePoolType.PowerFlex && pool.getPoolType() == Storage.StoragePoolType.PowerFlex) {
-                logger.debug(String.format("Pool [%s] with type [%s] does not match volume [%s] pool type [%s].", pool, pool.getPoolType(), volume, volumePool.getPoolType()));
+                logger.debug("Pool [{}] with type [{}] does not match volume [{}] pool type [{}].",
+                        pool, pool.getPoolType(), volume, volumePool.getPoolType());
                 return false;
             }
         } else {
-            logger.debug(String.format("Cannot check compatibility of pool [%s] because volume [%s] is not in [%s] state.", pool, volume, Volume.State.Ready));
+            logger.debug("Cannot check compatibility of pool [{}] because volume [{}] is not in [{}] state.", pool, volume, Volume.State.Ready);
             return false;
         }
-        logger.debug(String.format("Pool [%s] is compatible with volume [%s].", pool, volume));
+        logger.debug("Pool [{}] is compatible with volume [{}].", pool, volume);
         return true;
     }
 
@@ -3924,7 +3681,7 @@
         return templateName;
     }
     @Override
-    public ImageStore discoverImageStore(String name, String url, String providerName, Long zoneId, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException {
+    public ImageStore discoverImageStore(String name, String url, String providerName, Long zoneId, Map<String, String> details) throws IllegalArgumentException, InvalidParameterValueException {
         DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName);
 
         if (storeProvider == null) {
@@ -3995,7 +3752,7 @@
             store = lifeCycle.initialize(params);
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
-                logger.debug("Failed to add data store: " + e.getMessage(), e);
+                logger.debug("Failed to add data store: {}", e.getMessage(), e);
             }
             throw new CloudRuntimeException("Failed to add data store: " + e.getMessage(), e);
         }
@@ -4103,7 +3860,7 @@
         // check if current cloud is ready to migrate, we only support cloud with only NFS secondary storages
         List<ImageStoreVO> imgStores = _imageStoreDao.listImageStores();
         List<ImageStoreVO> nfsStores = new ArrayList<>();
-        if (imgStores != null && imgStores.size() > 0) {
+        if (CollectionUtils.isNotEmpty(imgStores)) {
             for (ImageStoreVO store : imgStores) {
                 if (!store.getProviderName().equals(DataStoreProvider.NFS_IMAGE)) {
                     throw new InvalidParameterValueException("We only support migrate NFS secondary storage to use object store!");
@@ -4113,7 +3870,7 @@
             }
         }
         // convert all NFS secondary storage to staging store
-        if (nfsStores != null && nfsStores.size() > 0) {
+        if (CollectionUtils.isNotEmpty(nfsStores)) {
             for (ImageStoreVO store : nfsStores) {
                 long storeId = store.getId();
 
@@ -4211,11 +3968,17 @@
         List<Long> poolIds = new ArrayList<>();
         poolIds.add(pool.getId());
         List<Long> hosts = _storagePoolHostDao.findHostsConnectedToPools(poolIds);
-        if (hosts.size() > 0) {
+        if (!hosts.isEmpty()) {
             GetStoragePoolCapabilitiesCommand cmd = new GetStoragePoolCapabilitiesCommand();
             cmd.setPool(new StorageFilerTO(pool));
             GetStoragePoolCapabilitiesAnswer answer = (GetStoragePoolCapabilitiesAnswer) _agentMgr.easySend(hosts.get(0), cmd);
-            if (answer.getPoolDetails() != null && answer.getPoolDetails().containsKey(Storage.Capability.HARDWARE_ACCELERATION.toString())) {
+            if (answer == null) {
+                String msg = "Unable to get storage capabilities from storage pool: " + pool.getName();
+                logger.error(msg);
+                if (failOnChecks) {
+                    throw new CloudRuntimeException(msg);
+                }
+            } else if (answer.getPoolDetails() != null && answer.getPoolDetails().containsKey(Storage.Capability.HARDWARE_ACCELERATION.toString())) {
                 StoragePoolDetailVO hardwareAccelerationSupported = _storagePoolDetailsDao.findDetail(pool.getId(), Storage.Capability.HARDWARE_ACCELERATION.toString());
                 if (hardwareAccelerationSupported == null) {
                     StoragePoolDetailVO storagePoolDetailVO = new StoragePoolDetailVO(pool.getId(), Storage.Capability.HARDWARE_ACCELERATION.toString(), answer.getPoolDetails().get(Storage.Capability.HARDWARE_ACCELERATION.toString()), false);
@@ -4224,12 +3987,10 @@
                     hardwareAccelerationSupported.setValue(answer.getPoolDetails().get(Storage.Capability.HARDWARE_ACCELERATION.toString()));
                     _storagePoolDetailsDao.update(hardwareAccelerationSupported.getId(), hardwareAccelerationSupported);
                 }
-            } else {
-                if (answer != null && !answer.getResult()) {
-                    logger.error("Failed to update storage pool capabilities: " + answer.getDetails());
-                    if (failOnChecks) {
-                        throw new CloudRuntimeException(answer.getDetails());
-                    }
+            } else if (!answer.getResult()) {
+                logger.error("Failed to update storage pool capabilities: {}", answer.getDetails());
+                if (failOnChecks) {
+                    throw new CloudRuntimeException(answer.getDetails());
                 }
             }
         }
@@ -4283,17 +4044,17 @@
         // Verify that there are no live snapshot, template, volume on the image
         // store to be deleted
         List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listByStoreId(storeId, DataStoreRole.Image);
-        if (snapshots != null && snapshots.size() > 0) {
+        if (CollectionUtils.isNotEmpty(snapshots)) {
             throw new InvalidParameterValueException("Cannot delete image store with active snapshots backup!");
         }
         List<VolumeDataStoreVO> volumes = _volumeStoreDao.listByStoreId(storeId);
-        if (volumes != null && volumes.size() > 0) {
+        if (CollectionUtils.isNotEmpty(volumes)) {
             throw new InvalidParameterValueException("Cannot delete image store with active volumes backup!");
         }
 
         // search if there are user templates stored on this image store, excluding system, builtin templates
         List<TemplateJoinVO> templates = _templateViewDao.listActiveTemplates(storeId);
-        if (templates != null && templates.size() > 0) {
+        if (CollectionUtils.isNotEmpty(templates)) {
             throw new InvalidParameterValueException("Cannot delete image store with active Templates backup!");
         }
 
@@ -4372,11 +4133,11 @@
         params.put("role", DataStoreRole.ImageCache);
 
         DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle();
-        DataStore store = null;
+        DataStore store;
         try {
             store = lifeCycle.initialize(params);
         } catch (Exception e) {
-            logger.debug("Failed to add data store: " + e.getMessage(), e);
+            logger.debug("Failed to add data store: {}", e.getMessage(), e);
             throw new CloudRuntimeException("Failed to add data store: " + e.getMessage(), e);
         }
 
@@ -4396,16 +4157,16 @@
         // Verify that there are no live snapshot, template, volume on the cache
         // store that is currently referenced
         List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listActiveOnCache(storeId);
-        if (snapshots != null && snapshots.size() > 0) {
+        if (CollectionUtils.isNotEmpty(snapshots)) {
             throw new InvalidParameterValueException("Cannot delete cache store with staging snapshots currently in use!");
         }
         List<VolumeDataStoreVO> volumes = _volumeStoreDao.listActiveOnCache(storeId);
-        if (volumes != null && volumes.size() > 0) {
+        if (CollectionUtils.isNotEmpty(volumes)) {
             throw new InvalidParameterValueException("Cannot delete cache store with staging Volumes currently in use!");
         }
 
         List<TemplateDataStoreVO> templates = _templateStoreDao.listActiveOnCache(storeId);
-        if (templates != null && templates.size() > 0) {
+        if (CollectionUtils.isNotEmpty(templates)) {
             throw new InvalidParameterValueException("Cannot delete cache store with staging Templates currently in use!");
         }
 
@@ -4542,7 +4303,7 @@
         } else if ((diskOffering != null) && (diskOffering.getBytesReadRate() != null) && (diskOffering.getBytesReadRate() > 0)) {
             return diskOffering.getBytesReadRate();
         } else {
-            Long bytesReadRate = Long.parseLong(_configDao.getValue(Config.VmDiskThrottlingBytesReadRate.key()));
+            long bytesReadRate = VmDiskThrottlingBytesReadRate.value();
             if ((bytesReadRate > 0) && ((offering == null) || (!offering.isSystemUse()))) {
                 return bytesReadRate;
             }
@@ -4556,7 +4317,7 @@
         if ((diskOffering != null) && (diskOffering.getBytesWriteRate() != null) && (diskOffering.getBytesWriteRate() > 0)) {
             return diskOffering.getBytesWriteRate();
         } else {
-            Long bytesWriteRate = Long.parseLong(_configDao.getValue(Config.VmDiskThrottlingBytesWriteRate.key()));
+            long bytesWriteRate = VmDiskThrottlingBytesWriteRate.value();
             if ((bytesWriteRate > 0) && ((offering == null) || (!offering.isSystemUse()))) {
                 return bytesWriteRate;
             }
@@ -4570,7 +4331,7 @@
         if ((diskOffering != null) && (diskOffering.getIopsReadRate() != null) && (diskOffering.getIopsReadRate() > 0)) {
             return diskOffering.getIopsReadRate();
         } else {
-            Long iopsReadRate = Long.parseLong(_configDao.getValue(Config.VmDiskThrottlingIopsReadRate.key()));
+            long iopsReadRate = VmDiskThrottlingIopsReadRate.value();
             if ((iopsReadRate > 0) && ((offering == null) || (!offering.isSystemUse()))) {
                 return iopsReadRate;
             }
@@ -4584,7 +4345,7 @@
         if ((diskOffering != null) && (diskOffering.getIopsWriteRate() != null) && (diskOffering.getIopsWriteRate() > 0)) {
             return diskOffering.getIopsWriteRate();
         } else {
-            Long iopsWriteRate = Long.parseLong(_configDao.getValue(Config.VmDiskThrottlingIopsWriteRate.key()));
+            long iopsWriteRate = VmDiskThrottlingIopsWriteRate.value();
             if ((iopsWriteRate > 0) && ((offering == null) || (!offering.isSystemUse()))) {
                 return iopsWriteRate;
             }
@@ -4626,8 +4387,7 @@
                 DataStoreDownloadFollowRedirects,
                 AllowVolumeReSizeBeyondAllocation,
                 StoragePoolHostConnectWorkers,
-                ObjectStorageCapacityThreshold,
-                COPY_TEMPLATES_FROM_OTHER_SECONDARY_STORAGES
+                ObjectStorageCapacityThreshold
         };
     }
 
@@ -4641,8 +4401,8 @@
 
     @Override
     public DiskTO getDiskWithThrottling(final DataTO volTO, final Volume.Type volumeType, final long deviceId, final String path, final long offeringId, final long diskOfferingId) {
-        DiskTO disk = null;
-        if (volTO != null && volTO instanceof VolumeObjectTO) {
+        DiskTO disk;
+        if (volTO instanceof VolumeObjectTO) {
             VolumeObjectTO volumeTO = (VolumeObjectTO)volTO;
             ServiceOffering offering = _entityMgr.findById(ServiceOffering.class, offeringId);
             DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, diskOfferingId);
@@ -4661,10 +4421,7 @@
     @Override
     public boolean isStoragePoolDatastoreClusterParent(StoragePool pool) {
         List<StoragePoolVO> childStoragePools = _storagePoolDao.listChildStoragePoolsInDatastoreCluster(pool.getId());
-        if (childStoragePools != null && !childStoragePools.isEmpty()) {
-            return true;
-        }
-        return false;
+        return CollectionUtils.isNotEmpty(childStoragePools);
     }
 
     private void setVolumeObjectTOThrottling(VolumeObjectTO volumeTO, final ServiceOffering offering, final DiskOffering diskOffering) {
@@ -4676,7 +4433,7 @@
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_OBJECT_STORE_CREATE, eventDescription = "creating object storage")
-    public ObjectStore discoverObjectStore(String name, String url, Long size, String providerName, Map details)
+    public ObjectStore discoverObjectStore(String name, String url, Long size, String providerName, Map<String, String> details)
             throws IllegalArgumentException, InvalidParameterValueException {
         DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName);
 
@@ -4706,11 +4463,7 @@
         Map<String, Object> params = new HashMap<>();
         params.put("url", url);
         params.put("name", name);
-        if (size == null) {
-            params.put("size", 0L);
-        } else {
-            params.put("size", size);
-        }
+        params.put("size", size == null ? 0L : size);
         params.put("providerName", storeProvider.getName());
         params.put("role", DataStoreRole.Object);
         params.put("details", details);
@@ -4722,9 +4475,9 @@
             store = lifeCycle.initialize(params);
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
-                logger.debug("Failed to add object store: " + e.getMessage(), e);
+                logger.debug("Failed to add object store: {}", e.getMessage(), e);
             }
-            throw new CloudRuntimeException("Failed to add object store: " + e.getMessage(), e);
+            throw new CloudRuntimeException("Failed to add object store: {}" + e.getMessage(), e);
         }
 
         return (ObjectStore)_dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Object);
@@ -4742,7 +4495,7 @@
 
         // Verify that there are no buckets in the store
         List<BucketVO> buckets = _bucketDao.listByObjectStoreId(storeId);
-        if(buckets != null && buckets.size() > 0) {
+        if(CollectionUtils.isNotEmpty(buckets)) {
             throw new InvalidParameterValueException("Cannot delete object store with buckets");
         }
 
@@ -4815,7 +4568,6 @@
                 total += objectStore.getTotalSize();
             }
         }
-        CapacityVO capacity = new CapacityVO(null, zoneId, null, null, allocated, total, Capacity.CAPACITY_TYPE_OBJECT_STORAGE);
-        return capacity;
+        return new CapacityVO(null, zoneId, null, null, allocated, total, Capacity.CAPACITY_TYPE_OBJECT_STORAGE);
     }
 }