This is an automated email from the ASF dual-hosted git repository.

nvazquez pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.22 by this push:
     new 9e386a3128b PowerFlex/ScaleIO client initialization, authentication 
and command execution improvements (#12391)
9e386a3128b is described below

commit 9e386a3128b3130e35a7f31594eafecfb511f39d
Author: Suresh Kumar Anaparti <[email protected]>
AuthorDate: Thu Feb 26 17:53:41 2026 +0530

    PowerFlex/ScaleIO client initialization, authentication and command 
execution improvements (#12391)
    
    * PowerFlex/ScaleIO client initialization, authentication and command 
execution improvements
    
    * Migrate VM with volume not supported yet for PowerFlex/ScaleIO
    
    * review changes
---
 .../motion/StorageSystemDataMotionStrategy.java    |  3 +-
 .../cloudstack/framework/config/ConfigKey.java     |  8 ++
 .../kvm/storage/ScaleIOStorageAdaptorTest.java     |  7 +-
 .../kvm/storage/ScaleIOStoragePoolTest.java        | 13 ++--
 .../client/ScaleIOGatewayClientConnectionPool.java | 89 ++++++++++++----------
 .../datastore/client/ScaleIOGatewayClientImpl.java | 22 ++++--
 .../driver/ScaleIOPrimaryDataStoreDriver.java      | 10 +--
 .../datastore/manager/ScaleIOSDCManagerImpl.java   | 32 ++++----
 .../storage/datastore/util/ScaleIOUtil.java        | 35 ++++-----
 .../client/ScaleIOGatewayClientImplTest.java       | 21 ++---
 10 files changed, 137 insertions(+), 103 deletions(-)

diff --git 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
index 61d2caa0e06..275f41de43a 100644
--- 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
+++ 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
@@ -2565,8 +2565,7 @@ public class StorageSystemDataMotionStrategy implements 
DataMotionStrategy {
                 throw new CloudRuntimeException("Destination storage pool with 
ID " + dataStore.getId() + " was not located.");
             }
 
-            boolean isSrcAndDestPoolPowerFlexStorage = 
srcStoragePoolVO.getPoolType().equals(Storage.StoragePoolType.PowerFlex) && 
destStoragePoolVO.getPoolType().equals(Storage.StoragePoolType.PowerFlex);
-            if (srcStoragePoolVO.isManaged() && 
!isSrcAndDestPoolPowerFlexStorage && srcStoragePoolVO.getId() != 
destStoragePoolVO.getId()) {
+            if (srcStoragePoolVO.isManaged() && srcStoragePoolVO.getId() != 
destStoragePoolVO.getId()) {
                 throw new CloudRuntimeException("Migrating a volume online 
with KVM from managed storage is not currently supported.");
             }
 
diff --git 
a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java
 
b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java
index c19ec751153..ef50064050f 100644
--- 
a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java
+++ 
b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java
@@ -420,6 +420,14 @@ public class ConfigKey<T> {
         return value();
     }
 
+    /**
+     * @deprecated
+     * Still used by some external code, but use {@link 
ConfigKey#valueInScope(Scope, Long)} instead.
+     */
+    public T valueInDomain(Long domainId) {
+        return valueInScope(Scope.Domain, domainId);
+    }
+
     public T valueInScope(Scope scope, Long id) {
         if (id == null) {
             return value();
diff --git 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptorTest.java
 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptorTest.java
index eddaa8f6499..2d51637c524 100644
--- 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptorTest.java
+++ 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptorTest.java
@@ -180,7 +180,8 @@ public class ScaleIOStorageAdaptorTest {
         details.put(ScaleIOGatewayClient.STORAGE_POOL_MDMS, "1.1.1.1,2.2.2.2");
         when(Script.runSimpleBashScriptForExitValue(Mockito.eq("systemctl 
status scini"))).thenReturn(3);
         when(Script.runSimpleBashScriptForExitValue(Mockito.eq("systemctl 
is-enabled scini"))).thenReturn(0);
-        
when(Script.runSimpleBashScript(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_mdms|grep 1.1.1.1"))).thenReturn("MDM-ID 71fd458f0775010f SDC ID 
4421a91a00000000 INSTALLATION ID 204930df2cbcaf8e IPs [0]-3.3.3.3 [1]-4.4.4.4");
+        
when(Script.runSimpleBashScript(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_mdms|grep 1.1.1.1"), Mockito.eq(ScaleIOUtil.DEFAULT_TIMEOUT_MS)))
+                .thenReturn("MDM-ID 71fd458f0775010f SDC ID 4421a91a00000000 
INSTALLATION ID 204930df2cbcaf8e IPs [0]-3.3.3.3 [1]-4.4.4.4");
 
         Pair<Boolean, String> result = 
scaleIOStorageAdaptor.unprepareStorageClient(poolUuid, details);
 
@@ -196,11 +197,11 @@ public class ScaleIOStorageAdaptorTest {
         when(Script.runSimpleBashScriptForExitValue(Mockito.eq("systemctl 
is-enabled scini"))).thenReturn(0);
         when(Script.executeCommand(Mockito.eq("sed -i '/1.1.1.1\\,/d' 
/etc/emc/scaleio/drv_cfg.txt"))).thenReturn(new Pair<>(null, null));
         when(Script.runSimpleBashScriptForExitValue(Mockito.eq("systemctl 
restart scini"))).thenReturn(0);
-        
when(Script.runSimpleBashScript(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_mdms|grep 1.1.1.1"))).thenReturn("MDM-ID 71fd458f0775010f SDC ID 
4421a91a00000000 INSTALLATION ID 204930df2cbcaf8e IPs [0]-1.1.1.1 [1]-2.2.2.2");
+        
when(Script.runSimpleBashScript(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_mdms --file /etc/emc/scaleio/drv_cfg.txt|grep 1.1.1.1"), 
Mockito.eq(ScaleIOUtil.DEFAULT_TIMEOUT_MS)))
+                .thenReturn("MDM-ID 71fd458f0775010f SDC ID 4421a91a00000000 
INSTALLATION ID 204930df2cbcaf8e IPs [0]-1.1.1.1 [1]-2.2.2.2");
         
when(Script.executeCommand(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg"))).thenReturn(new
 Pair<>(null, null));
         
when(Script.executeCommand(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_vols"))).thenReturn(new Pair<>("", null));
 
-
         Pair<Boolean, String> result = 
scaleIOStorageAdaptor.unprepareStorageClient(poolUuid, details);
 
         Assert.assertFalse(result.first());
diff --git 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePoolTest.java
 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePoolTest.java
index ba6f9ce4b0a..d520a03c79c 100644
--- 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePoolTest.java
+++ 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePoolTest.java
@@ -95,9 +95,8 @@ public class ScaleIOStoragePoolTest {
         details.put(ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID, systemId);
 
         try (MockedStatic<Script> ignored = Mockito.mockStatic(Script.class)) {
-            when(Script.runSimpleBashScript(
-                    "/opt/emc/scaleio/sdc/bin/drv_cfg --query_mdms|grep 
218ce1797566a00f|awk '{print $5}'")).thenReturn(
-                    sdcId);
+            
when(Script.runSimpleBashScript(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_mdms --file /etc/emc/scaleio/drv_cfg.txt|grep 218ce1797566a00f|awk 
'{print $5}'"), Mockito.eq(ScaleIOUtil.DEFAULT_TIMEOUT_MS)))
+                    .thenReturn(sdcId);
 
             ScaleIOStoragePool pool1 = new ScaleIOStoragePool(uuid, 
"192.168.1.19", 443, "a519be2f00000000", type,
                     details, adapter);
@@ -116,10 +115,10 @@ public class ScaleIOStoragePoolTest {
         details.put(ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID, systemId);
 
         try (MockedStatic<Script> ignored = Mockito.mockStatic(Script.class)) {
-            when(Script.runSimpleBashScript(
-                    "/opt/emc/scaleio/sdc/bin/drv_cfg --query_mdms|grep 
218ce1797566a00f|awk '{print $5}'")).thenReturn(
-                    null);
-            when(Script.runSimpleBashScript("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_guid")).thenReturn(sdcGuid);
+            
when(Script.runSimpleBashScript(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_mdms --file /etc/emc/scaleio/drv_cfg.txt|grep 218ce1797566a00f|awk 
'{print $5}'"), Mockito.eq(ScaleIOUtil.DEFAULT_TIMEOUT_MS)))
+                    .thenReturn(null);
+            
when(Script.runSimpleBashScript(Mockito.eq("/opt/emc/scaleio/sdc/bin/drv_cfg 
--query_guid --file /etc/emc/scaleio/drv_cfg.txt"), 
Mockito.eq(ScaleIOUtil.DEFAULT_TIMEOUT_MS)))
+                    .thenReturn(sdcGuid);
 
             ScaleIOStoragePool pool1 = new ScaleIOStoragePool(uuid, 
"192.168.1.19", 443, "a519be2f00000000", type,
                     details, adapter);
diff --git 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientConnectionPool.java
 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientConnectionPool.java
index 39bcc205586..e98d502d681 100644
--- 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientConnectionPool.java
+++ 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientConnectionPool.java
@@ -17,12 +17,12 @@
 
 package org.apache.cloudstack.storage.datastore.client;
 
-import java.net.URISyntaxException;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 
 import com.cloud.storage.StoragePool;
+import com.cloud.utils.exception.CloudRuntimeException;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
@@ -36,9 +36,9 @@ import com.google.common.base.Preconditions;
 public class ScaleIOGatewayClientConnectionPool {
     protected Logger logger = LogManager.getLogger(getClass());
 
-    private ConcurrentHashMap<Long, ScaleIOGatewayClient> gatewayClients;
-
+    private Map<Long, ScaleIOGatewayClient> gatewayClients;
     private static final ScaleIOGatewayClientConnectionPool instance;
+    private final Object lock = new Object();
 
     static {
         instance = new ScaleIOGatewayClientConnectionPool();
@@ -49,60 +49,67 @@ public class ScaleIOGatewayClientConnectionPool {
     }
 
     private ScaleIOGatewayClientConnectionPool() {
-        gatewayClients = new ConcurrentHashMap<Long, ScaleIOGatewayClient>();
+        gatewayClients = new ConcurrentHashMap<>();
     }
 
     public ScaleIOGatewayClient getClient(StoragePool storagePool,
-                                          StoragePoolDetailsDao 
storagePoolDetailsDao)
-            throws NoSuchAlgorithmException, KeyManagementException, 
URISyntaxException {
+                                          StoragePoolDetailsDao 
storagePoolDetailsDao) {
         return getClient(storagePool.getId(), storagePool.getUuid(), 
storagePoolDetailsDao);
     }
 
 
     public ScaleIOGatewayClient getClient(DataStore dataStore,
-                                          StoragePoolDetailsDao 
storagePoolDetailsDao)
-            throws NoSuchAlgorithmException, KeyManagementException, 
URISyntaxException {
+                                          StoragePoolDetailsDao 
storagePoolDetailsDao) {
         return getClient(dataStore.getId(), dataStore.getUuid(), 
storagePoolDetailsDao);
     }
 
-
     private ScaleIOGatewayClient getClient(Long storagePoolId, String 
storagePoolUuid,
-                                           StoragePoolDetailsDao 
storagePoolDetailsDao)
-            throws NoSuchAlgorithmException, KeyManagementException, 
URISyntaxException {
+                                           StoragePoolDetailsDao 
storagePoolDetailsDao) {
 
         Preconditions.checkArgument(storagePoolId != null && storagePoolId > 0,
                 "Invalid storage pool id");
 
-        ScaleIOGatewayClient client = null;
-        synchronized (gatewayClients) {
-            client = gatewayClients.get(storagePoolId);
-            if (client == null) {
-                String url = null;
-                StoragePoolDetailVO urlDetail  = 
storagePoolDetailsDao.findDetail(storagePoolId, 
ScaleIOGatewayClient.GATEWAY_API_ENDPOINT);
-                if (urlDetail != null) {
-                    url = urlDetail.getValue();
-                }
-                String username = null;
-                StoragePoolDetailVO encryptedUsernameDetail = 
storagePoolDetailsDao.findDetail(storagePoolId, 
ScaleIOGatewayClient.GATEWAY_API_USERNAME);
-                if (encryptedUsernameDetail != null) {
-                    final String encryptedUsername = 
encryptedUsernameDetail.getValue();
-                    username = DBEncryptionUtil.decrypt(encryptedUsername);
+        logger.debug("Getting ScaleIO client for {} ({})", storagePoolId, 
storagePoolUuid);
+
+        ScaleIOGatewayClient client = gatewayClients.get(storagePoolId);
+        if (client == null) {
+            logger.debug("Before acquiring lock to create ScaleIO client for 
{} ({})", storagePoolId, storagePoolUuid);
+            synchronized (lock) {
+                logger.debug("Acquired lock to create ScaleIO client for {} 
({})", storagePoolId, storagePoolUuid);
+                client = gatewayClients.get(storagePoolId);
+                if (client == null) {
+                    logger.debug("Initializing ScaleIO client for {} ({})", 
storagePoolId, storagePoolUuid);
+
+                    String url = 
Optional.ofNullable(storagePoolDetailsDao.findDetail(storagePoolId, 
ScaleIOGatewayClient.GATEWAY_API_ENDPOINT))
+                            .map(StoragePoolDetailVO::getValue)
+                            .orElse(null);
+
+                    String username = 
Optional.ofNullable(storagePoolDetailsDao.findDetail(storagePoolId, 
ScaleIOGatewayClient.GATEWAY_API_USERNAME))
+                            .map(StoragePoolDetailVO::getValue)
+                            .map(DBEncryptionUtil::decrypt)
+                            .orElse(null);
+
+                    String password = 
Optional.ofNullable(storagePoolDetailsDao.findDetail(storagePoolId, 
ScaleIOGatewayClient.GATEWAY_API_PASSWORD))
+                            .map(StoragePoolDetailVO::getValue)
+                            .map(DBEncryptionUtil::decrypt)
+                            .orElse(null);
+
+                    int clientTimeout = 
StorageManager.STORAGE_POOL_CLIENT_TIMEOUT.valueIn(storagePoolId);
+                    int clientMaxConnections = 
StorageManager.STORAGE_POOL_CLIENT_MAX_CONNECTIONS.valueIn(storagePoolId);
+
+                    try {
+                        client = new ScaleIOGatewayClientImpl(url, username, 
password, false, clientTimeout, clientMaxConnections);
+                        logger.debug("Created ScaleIO client for the storage 
pool [id: {}, uuid: {}]", storagePoolId, storagePoolUuid);
+                        gatewayClients.put(storagePoolId, client);
+                    } catch (Exception e) {
+                        String msg = String.format("Failed to create ScaleIO 
client for the storage pool [id: %d, uuid: %s]", storagePoolId, 
storagePoolUuid);
+                        throw new CloudRuntimeException(msg, e);
+                    }
                 }
-                String password = null;
-                StoragePoolDetailVO encryptedPasswordDetail = 
storagePoolDetailsDao.findDetail(storagePoolId, 
ScaleIOGatewayClient.GATEWAY_API_PASSWORD);
-                if (encryptedPasswordDetail != null) {
-                    final String encryptedPassword = 
encryptedPasswordDetail.getValue();
-                    password = DBEncryptionUtil.decrypt(encryptedPassword);
-                }
-                final int clientTimeout = 
StorageManager.STORAGE_POOL_CLIENT_TIMEOUT.valueIn(storagePoolId);
-                final int clientMaxConnections = 
StorageManager.STORAGE_POOL_CLIENT_MAX_CONNECTIONS.valueIn(storagePoolId);
-
-                client = new ScaleIOGatewayClientImpl(url, username, password, 
false, clientTimeout, clientMaxConnections);
-                gatewayClients.put(storagePoolId, client);
-                logger.debug("Added gateway client for the storage pool [id: 
{}, uuid: {}]", storagePoolId, storagePoolUuid);
             }
         }
 
+        logger.debug("Returning ScaleIO client for {} ({})", storagePoolId, 
storagePoolUuid);
         return client;
     }
 
@@ -110,8 +117,8 @@ public class ScaleIOGatewayClientConnectionPool {
         Preconditions.checkArgument(dataStore != null && dataStore.getId() > 0,
                 "Invalid storage pool id");
 
-        ScaleIOGatewayClient client = null;
-        synchronized (gatewayClients) {
+        ScaleIOGatewayClient client;
+        synchronized (lock) {
             client = gatewayClients.remove(dataStore.getId());
         }
 
diff --git 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientImpl.java
 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientImpl.java
index 6c4cc57ce50..c6a61c35b8b 100644
--- 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientImpl.java
+++ 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientImpl.java
@@ -92,7 +92,7 @@ public class ScaleIOGatewayClientImpl implements 
ScaleIOGatewayClient {
 
     private String username;
     private String password;
-    private String sessionKey = null;
+    private String sessionKey;
 
     // The session token is valid for 8 hours from the time it was created, 
unless there has been no activity for 10 minutes
     // Reference: 
https://cpsdocs.dellemc.com/bundle/PF_REST_API_RG/page/GUID-92430F19-9F44-42B6-B898-87D5307AE59B.html
@@ -102,7 +102,7 @@ public class ScaleIOGatewayClientImpl implements 
ScaleIOGatewayClient {
     private static final long MAX_IDLE_TIME_IN_MILLISECS = 
MAX_IDLE_TIME_IN_MINS * 60 * 1000;
     private static final long BUFFER_TIME_IN_MILLISECS = 30 * 1000; // keep 30 
secs buffer before the expiration (to avoid any last-minute operations)
 
-    private boolean authenticating = false;
+    private volatile boolean authenticating = false;
     private long createTime = 0;
     private long lastUsedTime = 0;
 
@@ -142,7 +142,6 @@ public class ScaleIOGatewayClientImpl implements 
ScaleIOGatewayClient {
         this.username = username;
         this.password = password;
 
-        authenticate();
         logger.debug("API client for the PowerFlex gateway " + 
apiURI.getHost() + " is created successfully, with max connections: "
                 + maxConnections + " and timeout: " + timeout + " secs");
     }
@@ -181,7 +180,7 @@ public class ScaleIOGatewayClientImpl implements 
ScaleIOGatewayClient {
             long now = System.currentTimeMillis();
             createTime = lastUsedTime = now;
         } catch (final IOException e) {
-            logger.error("Failed to authenticate PowerFlex API Gateway " + 
apiURI.getHost() + " due to: " + e.getMessage() + getConnectionManagerStats());
+            logger.error("Failed to authenticate PowerFlex API Gateway " + 
apiURI.getHost() + " due to: " + e.getMessage() + getConnectionManagerStats(), 
e);
             throw new CloudRuntimeException("Failed to authenticate PowerFlex 
API Gateway " + apiURI.getHost() + " due to: " + e.getMessage());
         } finally {
             authenticating = false;
@@ -199,6 +198,10 @@ public class ScaleIOGatewayClientImpl implements 
ScaleIOGatewayClient {
     }
 
     private boolean isSessionExpired() {
+        if (sessionKey == null) {
+            logger.debug("Session never created for the Gateway " + 
apiURI.getHost());
+            return true;
+        }
         long now = System.currentTimeMillis() + BUFFER_TIME_IN_MILLISECS;
         if ((now - createTime) > MAX_VALID_SESSION_TIME_IN_MILLISECS) {
             logger.debug("Session expired for the Gateway " + apiURI.getHost() 
+ ", token is invalid after " + MAX_VALID_SESSION_TIME_IN_HRS
@@ -281,7 +284,11 @@ public class ScaleIOGatewayClientImpl implements 
ScaleIOGatewayClient {
         HttpResponse response = null;
         boolean responseConsumed = false;
         try {
-            while (authenticating); // wait for authentication request (if 
any) to complete (and to pick the new session key)
+            while (authenticating) { // wait for authentication request (if 
any)
+                // to complete (and to pick the new session key)
+                Thread.yield();
+            }
+
             final HttpGet request = new HttpGet(apiURI.toString() + path);
             request.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + 
Base64.getEncoder().encodeToString((this.username + ":" + 
this.sessionKey).getBytes()));
             logger.debug("Sending GET request: " + request.toString());
@@ -316,7 +323,10 @@ public class ScaleIOGatewayClientImpl implements 
ScaleIOGatewayClient {
         HttpResponse response = null;
         boolean responseConsumed = false;
         try {
-            while (authenticating); // wait for authentication request (if 
any) to complete (and to pick the new session key)
+            while (authenticating) { // wait for authentication request (if 
any)
+                // to complete (and to pick the new session key)
+                Thread.yield();
+            }
             final HttpPost request = new HttpPost(apiURI.toString() + path);
             request.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + 
Base64.getEncoder().encodeToString((this.username + ":" + 
this.sessionKey).getBytes()));
             request.setHeader("content-type", "application/json");
diff --git 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java
 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java
index 506cb54e1d8..2c6460422a4 100644
--- 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java
+++ 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java
@@ -153,15 +153,15 @@ public class ScaleIOPrimaryDataStoreDriver implements 
PrimaryDataStoreDriver {
         sdcManager = new ScaleIOSDCManagerImpl();
     }
 
-    ScaleIOGatewayClient getScaleIOClient(final StoragePool storagePool) 
throws Exception {
+    ScaleIOGatewayClient getScaleIOClient(final StoragePool storagePool) {
         return 
ScaleIOGatewayClientConnectionPool.getInstance().getClient(storagePool, 
storagePoolDetailsDao);
     }
 
-    ScaleIOGatewayClient getScaleIOClient(final DataStore dataStore) throws 
Exception {
+    ScaleIOGatewayClient getScaleIOClient(final DataStore dataStore) {
         return 
ScaleIOGatewayClientConnectionPool.getInstance().getClient(dataStore, 
storagePoolDetailsDao);
     }
 
-    private boolean setVolumeLimitsOnSDC(VolumeVO volume, Host host, DataStore 
dataStore, Long iopsLimit, Long bandwidthLimitInKbps) throws Exception {
+    private boolean setVolumeLimitsOnSDC(VolumeVO volume, Host host, DataStore 
dataStore, Long iopsLimit, Long bandwidthLimitInKbps) {
         sdcManager = ComponentContext.inject(sdcManager);
         final String sdcId = sdcManager.prepareSDC(host, dataStore);
         if (StringUtils.isBlank(sdcId)) {
@@ -173,7 +173,7 @@ public class ScaleIOPrimaryDataStoreDriver implements 
PrimaryDataStoreDriver {
         return 
client.mapVolumeToSdcWithLimits(ScaleIOUtil.getVolumePath(volume.getPath()), 
sdcId, iopsLimit, bandwidthLimitInKbps);
     }
 
-    private boolean setVolumeLimitsFromDetails(VolumeVO volume, Host host, 
DataStore dataStore) throws Exception {
+    private boolean setVolumeLimitsFromDetails(VolumeVO volume, Host host, 
DataStore dataStore) {
         Long bandwidthLimitInKbps = 0L; // Unlimited
         // Check Bandwidth Limit parameter in volume details
         final VolumeDetailVO bandwidthVolumeDetail = 
volumeDetailsDao.findDetail(volume.getId(), Volume.BANDWIDTH_LIMIT_IN_MBPS);
@@ -997,7 +997,7 @@ public class ScaleIOPrimaryDataStoreDriver implements 
PrimaryDataStoreDriver {
         return host;
     }
 
-    public void updateSnapshotsAfterCopyVolume(DataObject srcData, DataObject 
destData) throws Exception {
+    public void updateSnapshotsAfterCopyVolume(DataObject srcData, DataObject 
destData) {
         final long srcVolumeId = srcData.getId();
         DataStore srcStore = srcData.getDataStore();
         final ScaleIOGatewayClient client = getScaleIOClient(srcStore);
diff --git 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/manager/ScaleIOSDCManagerImpl.java
 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/manager/ScaleIOSDCManagerImpl.java
index c13ad61a6cd..cb111e9ccac 100644
--- 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/manager/ScaleIOSDCManagerImpl.java
+++ 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/manager/ScaleIOSDCManagerImpl.java
@@ -361,14 +361,13 @@ public class ScaleIOSDCManagerImpl implements 
ScaleIOSDCManager, Configurable {
             return false;
         }
 
-        try {
-            if (logger.isDebugEnabled()) {
-                List<StoragePoolHostVO> poolHostVOsBySdc = 
storagePoolHostDao.findByLocalPath(sdcId);
-                if (CollectionUtils.isNotEmpty(poolHostVOsBySdc) && 
poolHostVOsBySdc.size() > 1) {
-                    logger.debug(String.format("There are other connected 
pools with the same SDC of the host %s", host));
-                }
-            }
+        List<StoragePoolHostVO> poolHostVOsBySdc = 
storagePoolHostDao.findByLocalPath(sdcId);
+        if (CollectionUtils.isNotEmpty(poolHostVOsBySdc) && 
poolHostVOsBySdc.size() > 1) {
+            logger.debug(String.format("There are other connected pools with 
the same SDC of the host %s", host));
+            return false;
+        }
 
+        try {
             return !areVolumesMappedToPoolSdc(dataStore.getId(), sdcId);
         } catch (Exception e) {
             logger.warn("Unable to check whether the SDC of the pool: " + 
dataStore.getId() + " can be unprepared on the host: " + host.getId() + ", due 
to " + e.getMessage(), e);
@@ -425,20 +424,26 @@ public class ScaleIOSDCManagerImpl implements 
ScaleIOSDCManager, Configurable {
     @Override
     public boolean isHostSdcConnected(String sdcId, DataStore dataStore, int 
waitTimeInSecs) {
         long poolId = dataStore.getId();
-        logger.debug(String.format("Waiting (for %d secs) for the SDC %s of 
the pool %s to connect",
-                waitTimeInSecs, sdcId, dataStore));
+        logger.debug("Waiting (for {} secs) for the SDC {} of the pool {} to 
connect", waitTimeInSecs, sdcId, dataStore);
         int timeBetweenTries = 1000; // Try more frequently (every sec) and 
return early if connected
-        while (waitTimeInSecs > 0) {
+        for (int i = 0; i < waitTimeInSecs; i++) {
+            logger.debug("Attempt {} of {} for the SDC {} of the pool {} to 
connect", i + 1, waitTimeInSecs, sdcId, dataStore);
             if (isHostSdcConnected(sdcId, poolId)) {
+                logger.debug("Attempt {} of {} successful for the SDC {} of 
the pool {} to connect", i + 1, waitTimeInSecs, sdcId, dataStore);
                 return true;
             }
-            waitTimeInSecs--;
             try {
                 Thread.sleep(timeBetweenTries);
             } catch (Exception ignore) {
             }
         }
-        return isHostSdcConnected(sdcId, poolId);
+        boolean isConnected = isHostSdcConnected(sdcId, poolId);
+        if (isConnected) {
+            logger.debug("Final attempt to connect the SDC {} of the pool {} 
succeeded", sdcId, dataStore);
+        } else {
+            logger.debug("Final attempt to connect the SDC {} of the pool {} 
failed", sdcId, dataStore);
+        }
+        return isConnected;
     }
 
     @Override
@@ -470,6 +475,7 @@ public class ScaleIOSDCManagerImpl implements 
ScaleIOSDCManager, Configurable {
     private boolean isHostSdcConnected(String sdcId, long poolId) {
         try {
             final ScaleIOGatewayClient client = getScaleIOClient(poolId);
+            logger.debug("Checking whether SDC {} connected or not", sdcId);
             return client.isSdcConnected(sdcId);
         } catch (Exception e) {
             logger.error("Failed to check host SDC connection", e);
@@ -477,7 +483,7 @@ public class ScaleIOSDCManagerImpl implements 
ScaleIOSDCManager, Configurable {
         }
     }
 
-    private ScaleIOGatewayClient getScaleIOClient(final Long storagePoolId) 
throws Exception {
+    private ScaleIOGatewayClient getScaleIOClient(Long storagePoolId) {
         StoragePoolVO storagePool = storagePoolDao.findById(storagePoolId);
         if (storagePool == null) {
             throw new CloudRuntimeException("Unable to find the storage pool 
with id " + storagePoolId);
diff --git 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/util/ScaleIOUtil.java
 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/util/ScaleIOUtil.java
index 70ea6f429e7..c1bc9fc10cf 100644
--- 
a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/util/ScaleIOUtil.java
+++ 
b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/util/ScaleIOUtil.java
@@ -158,6 +158,11 @@ public class ScaleIOUtil {
      */
     private static final Pattern DRV_CFG_MDM_IPS_PATTERN = 
Pattern.compile("\\s*,\\s*");
 
+    /**
+     * Default command execution timeout 5 minutes.
+     */
+    public static final int DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;
+
     public static boolean addMdms(String... mdmAddresses) {
         if (mdmAddresses.length < 1) {
             return false;
@@ -226,14 +231,10 @@ public class ScaleIOUtil {
                 }
             } else {
                 String command = String.format(REMOVE_MDM_CMD_TEMPLATE, 
mdmAddress, DRV_CFG_FILE);
-                String stdErr = Script.executeCommand(command).second();
-                if(StringUtils.isEmpty(stdErr)) {
-                    // restart SDC needed only if configuration file modified 
manually (not by CLI)
-                    restartSDC = true;
-                    changesApplied = true;
-                } else {
-                    LOGGER.error(String.format("Failed to remove MDM %s from 
%s: %s", mdmAddress, DRV_CFG_FILE, stdErr));
-                }
+                Script.runSimpleBashScript(command, DEFAULT_TIMEOUT_MS);
+                // restart SDC needed only if configuration file modified 
manually (not by CLI)
+                restartSDC = true;
+                changesApplied = true;
             }
         }
         if (restartSDC) {
@@ -338,9 +339,9 @@ public class ScaleIOUtil {
      */
     public static boolean isMdmPresent(String mdmAddress) {
         //query_mdms outputs "MDM-ID <System/MDM-Id> SDC ID <SDC-Id> 
INSTALLATION ID <Installation-Id> IPs [0]-x.x.x.x [1]-x.x.x.x" for a MDM with 
ID: <MDM-Id>
-        String queryMdmsCmd = ScaleIOUtil.SDC_HOME_PATH + "/bin/" + 
ScaleIOUtil.QUERY_MDMS_CMD;
+        String queryMdmsCmd = ScaleIOUtil.SDC_HOME_PATH + "/bin/" + 
ScaleIOUtil.QUERY_MDMS_CMD + " --file " + DRV_CFG_FILE;
         queryMdmsCmd += "|grep " + mdmAddress;
-        String result = Script.runSimpleBashScript(queryMdmsCmd);
+        String result = Script.runSimpleBashScript(queryMdmsCmd, 
DEFAULT_TIMEOUT_MS);
 
         return StringUtils.isNotBlank(result) && result.contains(mdmAddress);
     }
@@ -348,7 +349,7 @@ public class ScaleIOUtil {
     public static String getSdcHomePath() {
         String sdcHomePropertyCmdFormat = "sed -n '/%s/p' '%s' 2>/dev/null  | 
sed 's/%s=//g' 2>/dev/null";
         String sdcHomeCmd = String.format(sdcHomePropertyCmdFormat, 
SDC_HOME_PARAMETER, AGENT_PROPERTIES_FILE, SDC_HOME_PARAMETER);
-        String result = Script.runSimpleBashScript(sdcHomeCmd);
+        String result = Script.runSimpleBashScript(sdcHomeCmd, 
DEFAULT_TIMEOUT_MS);
         String sdcHomePath;
         if (result == null) {
             sdcHomePath = DEFAULT_SDC_HOME_PATH;
@@ -364,7 +365,7 @@ public class ScaleIOUtil {
         // Detecting new volumes
         String rescanCmd = ScaleIOUtil.SDC_HOME_PATH + "/bin/" + 
ScaleIOUtil.RESCAN_CMD;
 
-        String result = Script.runSimpleBashScript(rescanCmd);
+        String result = Script.runSimpleBashScript(rescanCmd, 
DEFAULT_TIMEOUT_MS);
         if (result == null) {
             LOGGER.warn("Failed to rescan for new volumes");
         }
@@ -375,7 +376,7 @@ public class ScaleIOUtil {
         String queryDiskCmd = SDC_HOME_PATH + "/bin/" + 
ScaleIOUtil.QUERY_VOLUMES_CMD;
         queryDiskCmd += "|grep " + volumeId + "|awk '{print $4}'";
 
-        String result = Script.runSimpleBashScript(queryDiskCmd);
+        String result = Script.runSimpleBashScript(queryDiskCmd, 
DEFAULT_TIMEOUT_MS);
         if (result == null) {
             LOGGER.warn("Query volumes failed to get volume: " + volumeId + " 
details for system id");
             return null;
@@ -390,8 +391,8 @@ public class ScaleIOUtil {
     }
 
     public static String getSdcGuid() {
-        String queryGuidCmd = ScaleIOUtil.SDC_HOME_PATH + "/bin/" + 
ScaleIOUtil.QUERY_GUID_CMD;
-        String result = Script.runSimpleBashScript(queryGuidCmd);
+        String queryGuidCmd = ScaleIOUtil.SDC_HOME_PATH + "/bin/" + 
ScaleIOUtil.QUERY_GUID_CMD + " --file " + DRV_CFG_FILE;
+        String result = Script.runSimpleBashScript(queryGuidCmd, 
DEFAULT_TIMEOUT_MS);
         if (result == null) {
             LOGGER.warn("Failed to get SDC guid");
             return null;
@@ -412,9 +413,9 @@ public class ScaleIOUtil {
 
     public static String getSdcId(String mdmId) {
         //query_mdms outputs "MDM-ID <System/MDM-Id> SDC ID <SDC-Id> 
INSTALLATION ID <Installation-Id> IPs [0]-x.x.x.x [1]-x.x.x.x" for a MDM with 
ID: <MDM-Id>
-        String queryMdmsCmd = ScaleIOUtil.SDC_HOME_PATH + "/bin/" + 
ScaleIOUtil.QUERY_MDMS_CMD;
+        String queryMdmsCmd = ScaleIOUtil.SDC_HOME_PATH + "/bin/" + 
ScaleIOUtil.QUERY_MDMS_CMD + " --file " + DRV_CFG_FILE;
         queryMdmsCmd += "|grep " + mdmId + "|awk '{print $5}'";
-        String result = Script.runSimpleBashScript(queryMdmsCmd);
+        String result = Script.runSimpleBashScript(queryMdmsCmd, 
DEFAULT_TIMEOUT_MS);
         if (result == null) {
             LOGGER.warn("Failed to get SDC Id, for the MDM: " + mdmId);
             return null;
diff --git 
a/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientImplTest.java
 
b/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientImplTest.java
index 817a67fc650..ee8351ae765 100644
--- 
a/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientImplTest.java
+++ 
b/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/client/ScaleIOGatewayClientImplTest.java
@@ -99,8 +99,6 @@ public class ScaleIOGatewayClientImplTest {
     @Test
     public void testClientAuthSuccess() {
         Assert.assertNotNull(client);
-        wireMockRule.verify(getRequestedFor(urlEqualTo("/api/login"))
-                .withBasicAuth(new BasicCredentials(username, password)));
 
         wireMockRule.stubFor(get("/api/types/StoragePool/instances")
                 .willReturn(aResponse()
@@ -110,25 +108,28 @@ public class ScaleIOGatewayClientImplTest {
 
         client.listStoragePools();
 
+        wireMockRule.verify(getRequestedFor(urlEqualTo("/api/login"))
+                .withBasicAuth(new BasicCredentials(username, password)));
+
         
wireMockRule.verify(getRequestedFor(urlEqualTo("/api/types/StoragePool/instances"))
                 .withBasicAuth(new BasicCredentials(username, sessionKey)));
     }
 
     @Test(expected = CloudRuntimeException.class)
     public void testClientAuthFailure() throws Exception {
+        Assert.assertNotNull(client);
+
         wireMockRule.stubFor(get("/api/login")
                 .willReturn(unauthorized()
                         .withHeader("content-type", 
"application/json;charset=UTF-8")
                         .withBody("")));
 
-        new ScaleIOGatewayClientImpl("https://localhost/api";, username, 
password, false, timeout, maxConnections);
+        client.listStoragePools();
     }
 
     @Test(expected = ServerApiException.class)
     public void testRequestTimeout() {
         Assert.assertNotNull(client);
-        wireMockRule.verify(getRequestedFor(urlEqualTo("/api/login"))
-                .withBasicAuth(new BasicCredentials(username, password)));
 
         wireMockRule.stubFor(get("/api/types/StoragePool/instances")
                 .willReturn(aResponse()
@@ -143,14 +144,15 @@ public class ScaleIOGatewayClientImplTest {
     @Test
     public void testCreateSingleVolume() {
         Assert.assertNotNull(client);
-        wireMockRule.verify(getRequestedFor(urlEqualTo("/api/login"))
-                .withBasicAuth(new BasicCredentials(username, password)));
 
         final String volumeName = "testvolume";
         final String scaleIOStoragePoolId = "4daaa55e00000000";
         final int sizeInGb = 8;
         Volume scaleIOVolume = client.createVolume(volumeName, 
scaleIOStoragePoolId, sizeInGb, Storage.ProvisioningType.THIN);
 
+        wireMockRule.verify(getRequestedFor(urlEqualTo("/api/login"))
+                .withBasicAuth(new BasicCredentials(username, password)));
+
         
wireMockRule.verify(postRequestedFor(urlEqualTo("/api/types/Volume/instances"))
                 .withBasicAuth(new BasicCredentials(username, sessionKey))
                 .withRequestBody(containing("\"name\":\"" + volumeName + "\""))
@@ -169,8 +171,6 @@ public class ScaleIOGatewayClientImplTest {
     @Test
     public void testCreateMultipleVolumes() {
         Assert.assertNotNull(client);
-        wireMockRule.verify(getRequestedFor(urlEqualTo("/api/login"))
-                .withBasicAuth(new BasicCredentials(username, password)));
 
         final String volumeNamePrefix = "testvolume_";
         final String scaleIOStoragePoolId = "4daaa55e00000000";
@@ -188,6 +188,9 @@ public class ScaleIOGatewayClientImplTest {
             Assert.assertEquals(scaleIOVolume.getVolumeType(), 
Volume.VolumeType.ThinProvisioned);
         }
 
+        wireMockRule.verify(getRequestedFor(urlEqualTo("/api/login"))
+                .withBasicAuth(new BasicCredentials(username, password)));
+
         wireMockRule.verify(volumesCount, 
postRequestedFor(urlEqualTo("/api/types/Volume/instances"))
                 .withBasicAuth(new BasicCredentials(username, sessionKey))
                 .withRequestBody(containing("\"name\":\"" + volumeNamePrefix))


Reply via email to