Skip to content

Commit b065389

Browse files
Don't remove MDM IPs from SDC when any volumes mapped to SDC
1 parent 86f5f0c commit b065389

File tree

10 files changed

+107
-8
lines changed

10 files changed

+107
-8
lines changed

engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ default boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool) {
137137
return false;
138138
}
139139

140+
/**
141+
* intended for managed storage
142+
* returns true if the host can be disconnected from storage pool
143+
*/
144+
default boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool) {
145+
return true;
146+
}
147+
140148
/**
141149
* Used by storage pools which want to keep VMs' information
142150
* @return true if additional VM info is needed (intended for storage pools).

engine/components-api/src/main/java/com/cloud/storage/StorageManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ static Boolean getFullCloneConfiguration(Long storeId) {
308308

309309
boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool);
310310

311+
boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool);
312+
311313
Host getHost(long hostId);
312314

313315
Host updateSecondaryStorage(long secStorageId, String newUrl);

plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,31 @@ public boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool) {
14691469
return sdcManager.areSDCConnectionsWithinLimit(pool.getId());
14701470
}
14711471

1472+
@Override
1473+
public boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool) {
1474+
if (host == null || pool == null) {
1475+
return false;
1476+
}
1477+
1478+
StoragePoolHostVO poolHostVO = storagePoolHostDao.findByPoolHost(pool.getId(), host.getId());
1479+
if (poolHostVO == null) {
1480+
return false;
1481+
}
1482+
1483+
final String sdcId = poolHostVO.getLocalPath();
1484+
if (StringUtils.isBlank(sdcId)) {
1485+
return false;
1486+
}
1487+
1488+
try {
1489+
final ScaleIOGatewayClient client = getScaleIOClient(pool.getId());
1490+
return client.listVolumesMappedToSdc(sdcId).isEmpty();
1491+
} catch (Exception e) {
1492+
logger.warn("Unable to check whether the host: " + host.getId() + " can be disconnected from storage pool: " + pool.getId() + ", due to " + e.getMessage(), e);
1493+
return false;
1494+
}
1495+
}
1496+
14721497
private void alertHostSdcDisconnection(Host host) {
14731498
if (host == null) {
14741499
return;

plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/ScaleIOPrimaryDataStoreLifeCycle.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,8 @@ public boolean maintain(DataStore store) {
336336
StoragePoolDetailVO mdmsDetail = storagePoolDetailsDao.findDetail(store.getId(), ScaleIOGatewayClient.STORAGE_POOL_MDMS);
337337
if (mdmsDetail != null) {
338338
details.put(ScaleIOGatewayClient.STORAGE_POOL_MDMS, mdmsDetail.getValue());
339+
details.put(ScaleIOSDCManager.ConnectOnDemand.key(), "false");
339340
}
340-
details.put(ScaleIOSDCManager.ConnectOnDemand.key(), "false");
341341
}
342342

343343
storagePoolAutomation.maintain(store, details);

plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/manager/ScaleIOSDCManager.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ public interface ScaleIOSDCManager {
2727
Boolean.class,
2828
"powerflex.connect.on.demand",
2929
Boolean.FALSE.toString(),
30-
"Connect PowerFlex client on Host when first Volume is mapped to SDC and disconnect when last Volume is unmapped from SDC," +
31-
" otherwise no action (that is connection remains in the same state whichever it is, connected or disconnected).",
30+
"When true, connects PowerFlex client on Host when first Volume is mapped to SDC & client connections configured 'storage.pool.connected.clients.limit' are within the limit and disconnects when last Volume is unmapped from SDC; " +
31+
"and When false, connects PowerFlex client on Host when host connects to storage pool & client connections configured 'storage.pool.connected.clients.limit' are within the limit and disconnects when host disconnects from storage pool & no volumes mapped to SDC.",
3232
Boolean.TRUE,
3333
ConfigKey.Scope.Zone);
3434

@@ -63,6 +63,14 @@ public interface ScaleIOSDCManager {
6363
*/
6464
boolean unprepareSDC(Host host, DataStore dataStore);
6565

66+
/**
67+
* Checks if the SDC can be unprepared on the host (don't remove MDM IPs from SDC if any volumes mapped to SDC).
68+
* @param host the host
69+
* @param dataStore the datastore
70+
* @return true if SDC can be unprepared on the host
71+
*/
72+
boolean canUnprepareSDC(Host host, DataStore dataStore);
73+
6674
/**
6775
* Returns the SDC Id of the host for the pool.
6876
* @param sdcGuid the SDC GUID

plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/manager/ScaleIOSDCManagerImpl.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ public boolean unprepareSDC(Host host, DataStore dataStore) {
284284
return true;
285285
}
286286

287+
if (!canUnprepareSDC(host, dataStore)) {
288+
logger.debug("Cannot unprepare SDC, there might be some volumes mapped to the SDC that belongs to the storage pools of PowerFlex storage cluster");
289+
return false;
290+
}
291+
287292
String mdms = getMdms(dataStore.getId());;
288293
boolean unprepareSDCStatus = unprepareSDCOnHost(host, dataStore, mdms);
289294
if (unprepareSDCStatus) {
@@ -327,6 +332,31 @@ private boolean unprepareSDCOnHost(Host host, DataStore dataStore, String mdms)
327332
return true;
328333
}
329334

335+
@Override
336+
public boolean canUnprepareSDC(Host host, DataStore dataStore) {
337+
if (host == null || dataStore == null) {
338+
return false;
339+
}
340+
341+
StoragePoolHostVO poolHostVO = storagePoolHostDao.findByPoolHost(dataStore.getId(), host.getId());
342+
if (poolHostVO == null) {
343+
return false;
344+
}
345+
346+
final String sdcId = poolHostVO.getLocalPath();
347+
if (StringUtils.isBlank(sdcId)) {
348+
return false;
349+
}
350+
351+
try {
352+
final ScaleIOGatewayClient client = getScaleIOClient(dataStore.getId());
353+
return client.listVolumesMappedToSdc(sdcId).isEmpty();
354+
} catch (Exception e) {
355+
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);
356+
return false;
357+
}
358+
}
359+
330360
@Override
331361
public String getHostSdcId(String sdcGuid, long poolId) {
332362
try {

plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/provider/ScaleIOHostListener.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,12 @@ public boolean hostDisconnected(long hostId, long poolId) {
202202
}
203203
Map<String,String> details = new HashMap<>();
204204
details.put(ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID, systemId);
205-
details.put(ScaleIOSDCManager.ConnectOnDemand.key(), String.valueOf(ScaleIOSDCManager.ConnectOnDemand.valueIn(host.getDataCenterId())));
206205
_sdcManager = ComponentContext.inject(_sdcManager);
207-
String mdms = _sdcManager.getMdms(poolId);
208-
details.put(ScaleIOGatewayClient.STORAGE_POOL_MDMS, mdms);
206+
if (_sdcManager.canUnprepareSDC(host, dataStore)) {
207+
details.put(ScaleIOSDCManager.ConnectOnDemand.key(), String.valueOf(ScaleIOSDCManager.ConnectOnDemand.valueIn(host.getDataCenterId())));
208+
String mdms = _sdcManager.getMdms(poolId);
209+
details.put(ScaleIOGatewayClient.STORAGE_POOL_MDMS, mdms);
210+
}
209211

210212
ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(false, storagePool, storagePool.getPath(), details);
211213
ModifyStoragePoolAnswer answer = sendModifyStoragePoolCommand(cmd, storagePool, hostId);

plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/util/ScaleIOUtil.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.List;
2121

22+
import org.apache.commons.collections.CollectionUtils;
2223
import org.apache.logging.log4j.Logger;
2324
import org.apache.logging.log4j.LogManager;
2425

@@ -91,6 +92,9 @@ public class ScaleIOUtil {
9192
private static final String DRV_CFG_FILE = "/etc/emc/scaleio/drv_cfg.txt";
9293

9394
public static void addMdms(List<String> mdmAddresses) {
95+
if (CollectionUtils.isEmpty(mdmAddresses)) {
96+
return;
97+
}
9498
// Sample Cmd - /opt/emc/scaleio/sdc/bin/drv_cfg --add_mdm --ip x.x.x.x,x.x.x.x --file /etc/emc/scaleio/drv_cfg.txt
9599
String addMdmsCmd = ScaleIOUtil.SDC_HOME_PATH + "/bin/" + ScaleIOUtil.ADD_MDMS_CMD;
96100
addMdmsCmd += " --ip " + String.join(",", mdmAddresses);
@@ -102,14 +106,23 @@ public static void addMdms(List<String> mdmAddresses) {
102106
}
103107

104108
public static void removeMdms(List<String> mdmAddresses) {
109+
if (CollectionUtils.isEmpty(mdmAddresses)) {
110+
return;
111+
}
105112
// (i) Remove MDMs from config file (ii) Restart scini
106113
// Sample Cmd - sed -i '/x.x.x.x\,/d' /etc/emc/scaleio/drv_cfg.txt
114+
boolean restartSDC = false;
107115
String removeMdmsCmdFormat = "sed -i '/%s\\,/d' %s";
108116
for (String mdmAddress : mdmAddresses) {
117+
if (mdmAdded(mdmAddress)) {
118+
restartSDC = true;
119+
}
109120
String removeMdmsCmd = String.format(removeMdmsCmdFormat, mdmAddress, DRV_CFG_FILE);
110121
Script.runSimpleBashScript(removeMdmsCmd);
111122
}
112-
restartSDCService();
123+
if (restartSDC) {
124+
restartSDCService();
125+
}
113126
}
114127

115128
public static boolean mdmAdded(String mdmAddress) {

server/src/main/java/com/cloud/storage/StorageManagerImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2826,6 +2826,17 @@ public boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool) {
28262826
return storeDriver instanceof PrimaryDataStoreDriver && ((PrimaryDataStoreDriver)storeDriver).canHostPrepareStoragePoolAccess(host, pool);
28272827
}
28282828

2829+
@Override
2830+
public boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool) {
2831+
if (pool == null || !pool.isManaged()) {
2832+
return true;
2833+
}
2834+
2835+
DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
2836+
DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
2837+
return storeDriver instanceof PrimaryDataStoreDriver && ((PrimaryDataStoreDriver)storeDriver).canDisconnectHostFromStoragePool(host, pool);
2838+
}
2839+
28292840
@Override
28302841
@DB
28312842
public Host getHost(long hostId) {

server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public boolean maintain(DataStore store, Map<String,String> details) {
168168
// remove heartbeat
169169
for (HostVO host : hosts) {
170170
ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(false, storagePool);
171-
if (MapUtils.isNotEmpty(details)) {
171+
if (MapUtils.isNotEmpty(details) && storageManager.canDisconnectHostFromStoragePool(host, storagePool)) {
172172
cmd.setDetails(details);
173173
}
174174
final Answer answer = agentMgr.easySend(host.getId(), cmd);

0 commit comments

Comments
 (0)