diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java index 114385bb3c2..cfe32c2bd07 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java @@ -27,6 +27,8 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import com.cloud.exception.StorageUnavailableException; +import com.cloud.storage.StoragePoolStatus; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; @@ -222,6 +224,13 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement if (pool.getPoolType() == Storage.StoragePoolType.DatastoreCluster && storageMgr.isStoragePoolDatastoreClusterParent(pool)) { return false; } + // Skip the storage pool whose parent datastore cluster is not in UP state. + if (pool.getParent() != 0L) { + StoragePoolVO datastoreCluster = storagePoolDao.findById(pool.getParent()); + if (datastoreCluster == null || (datastoreCluster != null && datastoreCluster.getStatus() != StoragePoolStatus.Up)) { + return false; + } + } try { boolean isStoragePoolStoragepolicyComplaince = storageMgr.isStoragePoolComplaintWithStoragePolicy(requestVolumes, pool); diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index 597ec58ef8f..7b00e3491c5 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -1541,6 +1541,9 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C DataStore store = _dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); if (primaryStorage.getPoolType() == StoragePoolType.DatastoreCluster) { + if (primaryStorage.getStatus() == StoragePoolStatus.PrepareForMaintenance) { + throw new CloudRuntimeException(String.format("There is already a job running for preparation for maintenance of the storage pool %s", primaryStorage.getUuid())); + } handlePrepareDatastoreCluserMaintenance(lifeCycle, primaryStorageId); } lifeCycle.maintain(store); @@ -1549,6 +1552,10 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } private void handlePrepareDatastoreCluserMaintenance(DataStoreLifeCycle lifeCycle, Long primaryStorageId) { + StoragePoolVO datastoreCluster = _storagePoolDao.findById(primaryStorageId); + datastoreCluster.setStatus(StoragePoolStatus.PrepareForMaintenance); + _storagePoolDao.update(datastoreCluster.getId(), datastoreCluster); + // Before preparing the datastorecluster to maintenance mode, the storagepools in the datastore cluster needs to put in maintenance List childDatastores = _storagePoolDao.listChildStoragePoolsInDatastoreCluster(primaryStorageId); Transaction.execute(new TransactionCallbackNoReturn() { @@ -1611,6 +1618,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); DataStore store = _dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); if (primaryStorage.getPoolType() == StoragePoolType.DatastoreCluster) { + primaryStorage.setStatus(StoragePoolStatus.Up); + _storagePoolDao.update(primaryStorage.getId(), primaryStorage); //FR41 need to handle when one of the primary stores is unable to cancel the maintenance mode List childDatastores = _storagePoolDao.listChildStoragePoolsInDatastoreCluster(primaryStorageId); for (StoragePoolVO childDatastore : childDatastores) { diff --git a/server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java b/server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java index 15a72590fc4..3e8822e67eb 100644 --- a/server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java +++ b/server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java @@ -117,7 +117,7 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { spes = primaryDataStoreDao.listBy(pool.getDataCenterId(), pool.getPodId(), pool.getClusterId(), ScopeType.CLUSTER); } for (StoragePoolVO sp : spes) { - if (sp.getParent() != pool.getParent()) { // If Datastore cluster is tried to prepare for maintenance then child storage pools are also kept in PrepareForMaintenance mode + if (sp.getParent() != pool.getParent() && sp.getId() != pool.getParent()) { // If Datastore cluster is tried to prepare for maintenance then child storage pools are also kept in PrepareForMaintenance mode if (sp.getStatus() == StoragePoolStatus.PrepareForMaintenance) { throw new CloudRuntimeException("Only one storage pool in a cluster can be in PrepareForMaintenance mode, " + sp.getId() + " is already in PrepareForMaintenance mode "); @@ -321,7 +321,7 @@ public class StoragePoolAutomationImpl implements StoragePoolAutomation { } } else { if (s_logger.isDebugEnabled()) { - s_logger.debug("ModifyStoragePool add secceeded"); + s_logger.debug("ModifyStoragePool add succeeded"); } } }