mirror of https://github.com/apache/cloudstack.git
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:
parent
6419e1c825
commit
9e386a3128
|
|
@ -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.");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Reference in New Issue