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
This commit is contained in:
Suresh Kumar Anaparti 2026-02-26 17:53:41 +05:30 committed by GitHub
parent 6419e1c825
commit 9e386a3128
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 137 additions and 103 deletions

View File

@ -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.");
}

View File

@ -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();

View File

@ -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());

View File

@ -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);

View File

@ -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);
}
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);
logger.debug("Getting ScaleIO client for {} ({})", storagePoolId, storagePoolUuid);
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);
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);
}
}
}
}
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());
}

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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))