Skip to content

Commit 6cd49ec

Browse files
Don't remove MDM IPs from SDC when any volumes mapped to SDC
1 parent 7e94fb0 commit 6cd49ec

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
@@ -145,6 +145,14 @@ default boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool) {
145145
return false;
146146
}
147147

148+
/**
149+
* intended for managed storage
150+
* returns true if the host can be disconnected from storage pool
151+
*/
152+
default boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool) {
153+
return true;
154+
}
155+
148156
/**
149157
* Used by storage pools which want to keep VMs' information
150158
* @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
@@ -1481,6 +1481,31 @@ public boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool) {
14811481
return sdcManager.areSDCConnectionsWithinLimit(pool.getId());
14821482
}
14831483

1484+
@Override
1485+
public boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool) {
1486+
if (host == null || pool == null) {
1487+
return false;
1488+
}
1489+
1490+
StoragePoolHostVO poolHostVO = storagePoolHostDao.findByPoolHost(pool.getId(), host.getId());
1491+
if (poolHostVO == null) {
1492+
return false;
1493+
}
1494+
1495+
final String sdcId = poolHostVO.getLocalPath();
1496+
if (StringUtils.isBlank(sdcId)) {
1497+
return false;
1498+
}
1499+
1500+
try {
1501+
final ScaleIOGatewayClient client = getScaleIOClient(pool.getId());
1502+
return client.listVolumesMappedToSdc(sdcId).isEmpty();
1503+
} catch (Exception e) {
1504+
logger.warn("Unable to check whether the host: " + host.getId() + " can be disconnected from storage pool: " + pool.getId() + ", due to " + e.getMessage(), e);
1505+
return false;
1506+
}
1507+
}
1508+
14841509
private void alertHostSdcDisconnection(Host host) {
14851510
if (host == null) {
14861511
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
@@ -296,6 +296,11 @@ public boolean unprepareSDC(Host host, DataStore dataStore) {
296296
return true;
297297
}
298298

299+
if (!canUnprepareSDC(host, dataStore)) {
300+
logger.debug("Cannot unprepare SDC, there might be some volumes mapped to the SDC that belongs to the storage pools of PowerFlex storage cluster");
301+
return false;
302+
}
303+
299304
String mdms = getMdms(dataStore.getId());;
300305
boolean unprepareSDCStatus = unprepareSDCOnHost(host, dataStore, mdms);
301306
if (unprepareSDCStatus) {
@@ -337,6 +342,31 @@ private boolean unprepareSDCOnHost(Host host, DataStore dataStore, String mdms)
337342
return true;
338343
}
339344

345+
@Override
346+
public boolean canUnprepareSDC(Host host, DataStore dataStore) {
347+
if (host == null || dataStore == null) {
348+
return false;
349+
}
350+
351+
StoragePoolHostVO poolHostVO = storagePoolHostDao.findByPoolHost(dataStore.getId(), host.getId());
352+
if (poolHostVO == null) {
353+
return false;
354+
}
355+
356+
final String sdcId = poolHostVO.getLocalPath();
357+
if (StringUtils.isBlank(sdcId)) {
358+
return false;
359+
}
360+
361+
try {
362+
final ScaleIOGatewayClient client = getScaleIOClient(dataStore.getId());
363+
return client.listVolumesMappedToSdc(sdcId).isEmpty();
364+
} catch (Exception e) {
365+
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);
366+
return false;
367+
}
368+
}
369+
340370
@Override
341371
public String getHostSdcId(String sdcGuid, DataStore dataStore) {
342372
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
@@ -206,10 +206,12 @@ public boolean hostDisconnected(long hostId, long poolId) {
206206
}
207207
Map<String,String> details = new HashMap<>();
208208
details.put(ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID, systemId);
209-
details.put(ScaleIOSDCManager.ConnectOnDemand.key(), String.valueOf(ScaleIOSDCManager.ConnectOnDemand.valueIn(host.getDataCenterId())));
210209
_sdcManager = ComponentContext.inject(_sdcManager);
211-
String mdms = _sdcManager.getMdms(poolId);
212-
details.put(ScaleIOGatewayClient.STORAGE_POOL_MDMS, mdms);
210+
if (_sdcManager.canUnprepareSDC(host, dataStore)) {
211+
details.put(ScaleIOSDCManager.ConnectOnDemand.key(), String.valueOf(ScaleIOSDCManager.ConnectOnDemand.valueIn(host.getDataCenterId())));
212+
String mdms = _sdcManager.getMdms(poolId);
213+
details.put(ScaleIOGatewayClient.STORAGE_POOL_MDMS, mdms);
214+
}
213215

214216
ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(false, storagePool, storagePool.getPath(), details);
215217
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
@@ -2833,6 +2833,17 @@ public boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool) {
28332833
return storeDriver instanceof PrimaryDataStoreDriver && ((PrimaryDataStoreDriver)storeDriver).canHostPrepareStoragePoolAccess(host, pool);
28342834
}
28352835

2836+
@Override
2837+
public boolean canDisconnectHostFromStoragePool(Host host, StoragePool pool) {
2838+
if (pool == null || !pool.isManaged()) {
2839+
return true;
2840+
}
2841+
2842+
DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
2843+
DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
2844+
return storeDriver instanceof PrimaryDataStoreDriver && ((PrimaryDataStoreDriver)storeDriver).canDisconnectHostFromStoragePool(host, pool);
2845+
}
2846+
28362847
@Override
28372848
@DB
28382849
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
@@ -167,7 +167,7 @@ public boolean maintain(DataStore store, Map<String,String> details) {
167167
// remove heartbeat
168168
for (HostVO host : hosts) {
169169
ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(false, storagePool);
170-
if (MapUtils.isNotEmpty(details)) {
170+
if (MapUtils.isNotEmpty(details) && storageManager.canDisconnectHostFromStoragePool(host, storagePool)) {
171171
cmd.setDetails(details);
172172
}
173173
final Answer answer = agentMgr.easySend(host.getId(), cmd);

0 commit comments

Comments
 (0)