This is an automated email from the ASF dual-hosted git repository.
nvazquez pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.22 by this push:
new cc2f74f5c5d Ensure compliance with storage access groups when mounting
disabled storage pools (#13990)
cc2f74f5c5d is described below
commit cc2f74f5c5d567ebbc096ad6ba389da4cf78dfca
Author: Suresh Kumar Anaparti <[email protected]>
AuthorDate: Wed Oct 7 00:47:07 2026 +0530
Ensure compliance with storage access groups when mounting disabled storage
pools (#13990)
- connect to only storage pools with empty tags when access group is empty
Co-authored-by: Sachin R Doddaguni <[email protected]>
---
.../java/com/cloud/storage/StorageManager.java | 4 +
.../storage/datastore/db/PrimaryDataStoreDao.java | 30 +++++-
.../datastore/db/PrimaryDataStoreDaoImpl.java | 59 ++++++++++-
.../com/cloud/resource/ResourceManagerImpl.java | 8 +-
.../cloud/storage/listener/StoragePoolMonitor.java | 23 ++--
.../storage/listener/StoragePoolMonitorTest.java | 116 +++++++++++++++++----
6 files changed, 205 insertions(+), 35 deletions(-)
diff --git
a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
index 5c7348cbe6c..7a29ce81002 100644
--- a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
+++ b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
@@ -432,4 +432,8 @@ public interface StorageManager extends StorageService {
String[] getStorageAccessGroups(Long zoneId, Long podId, Long clusterId,
Long hostId);
CapacityVO getObjectStorageUsedStats(Long zoneId);
+
+ static ConfigKey<Boolean> getMountDisabledStoragePool() {
+ return MountDisabledStoragePool;
+ }
}
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
index 57b5f6461c6..fd85dba1efc 100644
---
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
+++
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
@@ -90,6 +90,22 @@ public interface PrimaryDataStoreDao extends
GenericDao<StoragePoolVO, Long> {
List<StoragePoolVO> findDisabledPoolsByScope(long dcId, Long podId, Long
clusterId, ScopeType scope);
+ /**
+ * Finds disabled storage pools within the specified scope that are
associated with the given storage access groups.
+ * This method is used to locate storage pools with 'Disabled' status that
match specific storage access group
+ * filters.
+ *
+ * @param dcId the data center ID.
+ * @param podId the pod ID.
+ * @param clusterId the cluster ID.
+ * @param scope ZONE, CLUSTER OR HOST type scope
+ * @param storageAccessGroups array of storage access group names to match
against.
+ * Only pools associated with these access
groups will be returned.
+ * If null or empty, returns an empty list.
+ * @return a list of {@link StoragePoolVO} objects.
+ */
+ List<StoragePoolVO> findDisabledPoolsByScopeAndAccessGroups(long dcId,
Long podId, Long clusterId, ScopeType scope, String[] storageAccessGroups);
+
/**
* Find pool by UUID.
*
@@ -167,7 +183,19 @@ public interface PrimaryDataStoreDao extends
GenericDao<StoragePoolVO, Long> {
List<StoragePoolVO> listByIds(List<Long> ids);
- List<StoragePoolVO> findStoragePoolsByEmptyStorageAccessGroups(Long dcId,
Long podId, Long clusterId, ScopeType scope, HypervisorType hypervisorType);
+ /**
+ * Finds storage pools that have no storage access groups associated with
them within the specified criteria.
+ * This method identifies storage pools without access group restrictions.
+ *
+ * @param dcId the data center ID. Can be null to include all data centers.
+ * @param podId the pod ID. Can be null to include all pods.
+ * @param clusterId the cluster ID. Can be null to include all clusters.
+ * @param scope ZONE, CLUSTER or HOST type scope
+ * @param hypervisorType the hypervisor type filter. Can be null to
include all hypervisor types.
+ * @param status the storage pool status to filter by.
+ * @return a list of {@link StoragePoolVO} objects that have no storage
access groups associated.
+ */
+ List<StoragePoolVO> findStoragePoolsByEmptyStorageAccessGroups(Long dcId,
Long podId, Long clusterId, ScopeType scope, HypervisorType hypervisorType,
StoragePoolStatus status);
List<StoragePoolVO> findPoolsByStorageTypeAndZone(Storage.StoragePoolType
storageType, Long zoneId);
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
index b5d6415e3a1..4d0e581826f 100644
---
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
+++
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
@@ -54,6 +54,7 @@ import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.commons.lang3.ArrayUtils;
@DB()
public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO,
Long> implements PrimaryDataStoreDao {
@@ -86,6 +87,37 @@ public class PrimaryDataStoreDaoImpl extends
GenericDaoBase<StoragePoolVO, Long>
private final String
ZoneWideStorageAccessGroupsWithHypervisorTypeSqlPrefix = "SELECT storage_pool.*
from storage_pool LEFT JOIN storage_pool_and_access_group_map ON
storage_pool.id = storage_pool_and_access_group_map.pool_id WHERE
storage_pool.removed is null and storage_pool.status = 'Up' and
storage_pool.hypervisor = ? and storage_pool.data_center_id = ? and
storage_pool.scope = ? and (";
private final String
ZoneWideStorageAccessGroupsWithHypervisorTypeSqlSuffix = ") GROUP BY
storage_pool_and_access_group_map.pool_id";
+ /**
+ * SQL query prefix to find zone-wide disabled storage pools that are
associated with specific storage access groups.
+ */
+ private final String ZoneWideDisabledStorageAccessGroupsSqlPrefix =
+ "SELECT storage_pool.* FROM storage_pool " +
+ "LEFT JOIN storage_pool_and_access_group_map ON
storage_pool.id = storage_pool_and_access_group_map.pool_id " +
+ "WHERE storage_pool.removed IS NULL " +
+ " AND storage_pool.status = 'Disabled' " +
+ " AND storage_pool.data_center_id = ? " +
+ " AND storage_pool.scope = ? " +
+ " AND (";
+
+ /**
+ * SQL query prefix to find disabled storage pools with specific storage
access groups. The query is used at the HOST scope.
+ */
+ private final String DisabledStorageAccessGroupsForHostConnectionSqlPrefix
=
+ "SELECT storage_pool.* FROM storage_pool " +
+ "LEFT JOIN storage_pool_and_access_group_map ON
storage_pool.id = storage_pool_and_access_group_map.pool_id " +
+ "WHERE storage_pool.removed IS NULL " +
+ " AND storage_pool.status = 'Disabled' " +
+ " AND storage_pool.data_center_id = ? " +
+ " AND (storage_pool.pod_id = ? OR storage_pool.pod_id IS
NULL) " +
+ " AND storage_pool.scope = ? " +
+ " AND (";
+
+ /**
+ * SQL query suffix for disabled storage access groups queries. This
suffix completes the query by grouping
+ * results by pool_id.
+ */
+ private final String DisabledStorageAccessGroupsSqlSuffix = ") GROUP BY
storage_pool_and_access_group_map.pool_id";
+
// Storage tags are now separate from storage_pool_details, leaving only
details on that table
protected final String TagsSqlPrefix = "SELECT storage_pool.* from
storage_pool LEFT JOIN storage_pool_tags ON storage_pool.id =
storage_pool_tags.pool_id WHERE storage_pool.removed is null and
storage_pool.status = 'Up' AND storage_pool_tags.is_tag_a_rule = 0 and
storage_pool.data_center_id = ? and (storage_pool.pod_id = ? or
storage_pool.pod_id is null) and storage_pool.scope = ? and (";
protected final String TagsSqlSuffix = ") GROUP BY
storage_pool_tags.pool_id HAVING COUNT(storage_pool_tags.tag) >= ?";
@@ -568,6 +600,26 @@ public class PrimaryDataStoreDaoImpl extends
GenericDaoBase<StoragePoolVO, Long>
return storagePools;
}
+ @Override
+ public List<StoragePoolVO> findDisabledPoolsByScopeAndAccessGroups(long
dcId, Long podId, Long clusterId, ScopeType scope, String[]
storageAccessGroups) {
+ if (ArrayUtils.isEmpty(storageAccessGroups)) {
+ return List.of();
+ }
+
+ List<StoragePoolVO> storagePools = null;
+ String sqlValues =
getSqlValuesFromStorageAccessGroups(storageAccessGroups);
+
+ if (scope == ScopeType.ZONE) {
+ String sql =
getSqlPreparedStatement(ZoneWideDisabledStorageAccessGroupsSqlPrefix,
DisabledStorageAccessGroupsSqlSuffix, sqlValues, null);
+ storagePools = searchStoragePoolsPreparedStatement(sql, dcId,
null, null, scope, null);
+ } else if ((scope == ScopeType.CLUSTER || scope == ScopeType.HOST) &&
podId != null && clusterId != null) {
+ String sql =
getSqlPreparedStatement(DisabledStorageAccessGroupsForHostConnectionSqlPrefix,
DisabledStorageAccessGroupsSqlSuffix, sqlValues, clusterId);
+ storagePools = searchStoragePoolsPreparedStatement(sql, dcId,
podId, clusterId, scope, null);
+ }
+
+ return storagePools;
+ }
+
@Override
public List<StoragePoolVO> findLocalStoragePoolsByTags(long dcId, long
podId, Long clusterId, String[] tags, boolean validateTagRule) {
return findLocalStoragePoolsByTags(dcId, podId, clusterId, tags,
validateTagRule, null);
@@ -691,7 +743,7 @@ public class PrimaryDataStoreDaoImpl extends
GenericDaoBase<StoragePoolVO, Long>
}
@Override
- public List<StoragePoolVO> findStoragePoolsByEmptyStorageAccessGroups(Long
dcId, Long podId, Long clusterId, ScopeType scope, HypervisorType
hypervisorType) {
+ public List<StoragePoolVO> findStoragePoolsByEmptyStorageAccessGroups(Long
dcId, Long podId, Long clusterId, ScopeType scope, HypervisorType
hypervisorType, StoragePoolStatus status) {
SearchBuilder<StoragePoolVO> poolSearch = createSearchBuilder();
SearchBuilder<StoragePoolAndAccessGroupMapVO>
storageAccessGroupsPoolSearch =
_storagePoolAccessGroupMapDao.createSearchBuilder();
// Set criteria for pools
@@ -709,7 +761,6 @@ public class PrimaryDataStoreDaoImpl extends
GenericDaoBase<StoragePoolVO, Long>
SearchCriteria<StoragePoolVO> sc = poolSearch.create();
sc.setParameters("scope", scope.toString());
- sc.setParameters("status", Status.Up.toString());
if (dcId != null) {
sc.setParameters("datacenterid", dcId);
@@ -727,6 +778,10 @@ public class PrimaryDataStoreDaoImpl extends
GenericDaoBase<StoragePoolVO, Long>
sc.setParameters("hypervisortype", hypervisorType);
}
+ if (status != null) {
+ sc.setParameters("status", status.toString());
+ }
+
return listBy(sc);
}
diff --git a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java
b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java
index 02cd4de1e86..f9c06b5409c 100755
--- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java
@@ -2763,8 +2763,8 @@ public class ResourceManagerImpl extends ManagerBase
implements ResourceManager,
allPoolsByTags.addAll(_storagePoolDao.findPoolsByAccessGroupsForHostConnection(dcId,
podId, clusterId, ScopeType.CLUSTER, storageAccessGroups));
allPoolsByTags.addAll(_storagePoolDao.findZoneWideStoragePoolsByAccessGroupsForHostConnection(dcId,
storageAccessGroups));
if (includeEmptyTags) {
-
allPoolsByTags.addAll(_storagePoolDao.findStoragePoolsByEmptyStorageAccessGroups(dcId,
podId, clusterId, ScopeType.CLUSTER, null));
-
allPoolsByTags.addAll(_storagePoolDao.findStoragePoolsByEmptyStorageAccessGroups(dcId,
null, null, ScopeType.ZONE, null));
+
allPoolsByTags.addAll(_storagePoolDao.findStoragePoolsByEmptyStorageAccessGroups(dcId,
podId, clusterId, ScopeType.CLUSTER, null, StoragePoolStatus.Up));
+
allPoolsByTags.addAll(_storagePoolDao.findStoragePoolsByEmptyStorageAccessGroups(dcId,
null, null, ScopeType.ZONE, null, StoragePoolStatus.Up));
}
return allPoolsByTags;
@@ -2772,8 +2772,8 @@ public class ResourceManagerImpl extends ManagerBase
implements ResourceManager,
private List<StoragePoolVO> getStoragePoolsByEmptyStorageAccessGroups(Long
dcId, Long podId, Long clusterId) {
List<StoragePoolVO> allPoolsByTags = new ArrayList<>();
-
allPoolsByTags.addAll(_storagePoolDao.findStoragePoolsByEmptyStorageAccessGroups(dcId,
podId, clusterId, ScopeType.CLUSTER, null));
-
allPoolsByTags.addAll(_storagePoolDao.findStoragePoolsByEmptyStorageAccessGroups(dcId,
null, null, ScopeType.ZONE, null));
+
allPoolsByTags.addAll(_storagePoolDao.findStoragePoolsByEmptyStorageAccessGroups(dcId,
podId, clusterId, ScopeType.CLUSTER, null, StoragePoolStatus.Up));
+
allPoolsByTags.addAll(_storagePoolDao.findStoragePoolsByEmptyStorageAccessGroups(dcId,
null, null, ScopeType.ZONE, null, StoragePoolStatus.Up));
return allPoolsByTags;
}
diff --git
a/server/src/main/java/com/cloud/storage/listener/StoragePoolMonitor.java
b/server/src/main/java/com/cloud/storage/listener/StoragePoolMonitor.java
index 2f9750edee2..d7f20c03671 100644
--- a/server/src/main/java/com/cloud/storage/listener/StoragePoolMonitor.java
+++ b/server/src/main/java/com/cloud/storage/listener/StoragePoolMonitor.java
@@ -25,6 +25,7 @@ import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.exception.StorageConflictException;
import com.cloud.storage.StorageManager;
+import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.Profiler;
@@ -123,21 +124,21 @@ public class StoragePoolMonitor implements Listener {
List<StoragePoolVO> pools = new ArrayList<>();
// SAG -> Storage Access Group
if (ArrayUtils.isEmpty(sags)) {
- List<StoragePoolVO> clusterStoragePoolsByEmptySAGs =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
host.getPodId(), host.getClusterId(), ScopeType.CLUSTER, null);
- List<StoragePoolVO> storagePoolsByEmptySAGs =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, null);
- List<StoragePoolVO> zoneStoragePoolsByHypervisor =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, scCmd.getHypervisorType());
+ List<StoragePoolVO> clusterStoragePoolsByEmptySAGs =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
host.getPodId(), host.getClusterId(), ScopeType.CLUSTER, null,
StoragePoolStatus.Up);
+ List<StoragePoolVO> storagePoolsByEmptySAGs =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, null, StoragePoolStatus.Up);
+ List<StoragePoolVO> zoneStoragePoolsByHypervisor =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, scCmd.getHypervisorType(), StoragePoolStatus.Up);
storagePoolsByEmptySAGs.retainAll(zoneStoragePoolsByHypervisor);
pools.addAll(storagePoolsByEmptySAGs);
pools.addAll(clusterStoragePoolsByEmptySAGs);
- List<StoragePoolVO> zoneStoragePoolsByAnyHypervisor =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, HypervisorType.Any);
+ List<StoragePoolVO> zoneStoragePoolsByAnyHypervisor =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, HypervisorType.Any, StoragePoolStatus.Up);
pools.addAll(zoneStoragePoolsByAnyHypervisor);
} else {
List<StoragePoolVO> storagePoolsBySAGs = new ArrayList<>();
List<StoragePoolVO> clusterStoragePoolsBySAGs =
_poolDao.findPoolsByAccessGroupsForHostConnection(host.getDataCenterId(),
host.getPodId(), host.getClusterId(), ScopeType.CLUSTER, sags);
- List<StoragePoolVO> clusterStoragePoolsByEmptySAGs =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
host.getPodId(), host.getClusterId(), ScopeType.CLUSTER, null);
+ List<StoragePoolVO> clusterStoragePoolsByEmptySAGs =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
host.getPodId(), host.getClusterId(), ScopeType.CLUSTER, null,
StoragePoolStatus.Up);
List<StoragePoolVO> zoneStoragePoolsBySAGs =
_poolDao.findZoneWideStoragePoolsByAccessGroupsAndHypervisorTypeForHostConnection(host.getDataCenterId(),
sags, scCmd.getHypervisorType());
List<StoragePoolVO> zoneStoragePoolsByHypervisorTypeAny =
_poolDao.findZoneWideStoragePoolsByAccessGroupsAndHypervisorTypeForHostConnection(host.getDataCenterId(),
sags, HypervisorType.Any);
- List<StoragePoolVO> zoneStoragePoolsByEmptySAGs =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, null);
+ List<StoragePoolVO> zoneStoragePoolsByEmptySAGs =
_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, null, StoragePoolStatus.Up);
storagePoolsBySAGs.addAll(zoneStoragePoolsBySAGs);
storagePoolsBySAGs.addAll(zoneStoragePoolsByEmptySAGs);
@@ -148,13 +149,15 @@ public class StoragePoolMonitor implements Listener {
}
// get the zone wide disabled pools list if global setting is true.
- if (StorageManager.MountDisabledStoragePool.value()) {
-
pools.addAll(_poolDao.findDisabledPoolsByScope(host.getDataCenterId(), null,
null, ScopeType.ZONE));
+ if (StorageManager.getMountDisabledStoragePool().value()) {
+
pools.addAll(_poolDao.findDisabledPoolsByScopeAndAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, sags));
+
pools.addAll(_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
null, null, ScopeType.ZONE, null, StoragePoolStatus.Disabled));
}
// get the cluster wide disabled pool list
- if
(StorageManager.MountDisabledStoragePool.valueIn(host.getClusterId())) {
-
pools.addAll(_poolDao.findDisabledPoolsByScope(host.getDataCenterId(),
host.getPodId(), host.getClusterId(), ScopeType.CLUSTER));
+ if
(StorageManager.getMountDisabledStoragePool().valueIn(host.getClusterId())) {
+
pools.addAll(_poolDao.findDisabledPoolsByScopeAndAccessGroups(host.getDataCenterId(),
host.getPodId(), host.getClusterId(), ScopeType.CLUSTER, sags));
+
pools.addAll(_poolDao.findStoragePoolsByEmptyStorageAccessGroups(host.getDataCenterId(),
host.getPodId(), host.getClusterId(), ScopeType.CLUSTER, null,
StoragePoolStatus.Disabled));
}
List<StoragePoolHostVO> previouslyConnectedPools = new
ArrayList<>();
diff --git
a/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java
b/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java
index 7421eb7ae2d..0c729b364d1 100644
---
a/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java
+++
b/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java
@@ -22,17 +22,27 @@ import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
+import com.cloud.storage.StorageManager;
import com.cloud.storage.StorageManagerImpl;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.dao.StoragePoolHostDao;
+import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockedStatic;
import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
+import static org.mockito.Mockito.mock;
+
+@RunWith(MockitoJUnitRunner.class)
public class StoragePoolMonitorTest {
private StorageManagerImpl storageManager;
@@ -45,9 +55,9 @@ public class StoragePoolMonitorTest {
@Before
public void setUp() throws Exception {
- storageManager = Mockito.mock(StorageManagerImpl.class);
- poolDao = Mockito.mock(PrimaryDataStoreDao.class);
- storagePoolHostDao = Mockito.mock(StoragePoolHostDao.class);
+ storageManager = mock(StorageManagerImpl.class);
+ poolDao = mock(PrimaryDataStoreDao.class);
+ storagePoolHostDao = mock(StoragePoolHostDao.class);
storagePoolMonitor = new StoragePoolMonitor(storageManager, poolDao,
storagePoolHostDao, null);
host = new HostVO("some-uuid");
@@ -62,21 +72,21 @@ public class StoragePoolMonitorTest {
@Test
public void testProcessConnectStoragePoolNormal() throws Exception {
- HostVO hostMock = Mockito.mock(HostVO.class);
- StartupRoutingCommand startupRoutingCommand =
Mockito.mock(StartupRoutingCommand.class);
- StoragePoolVO poolMock = Mockito.mock(StoragePoolVO.class);
- Mockito.when(poolMock.getScope()).thenReturn(ScopeType.CLUSTER);
- Mockito.when(poolMock.getStatus()).thenReturn(StoragePoolStatus.Up);
- Mockito.when(poolMock.getId()).thenReturn(123L);
-
Mockito.when(poolMock.getPoolType()).thenReturn(Storage.StoragePoolType.Filesystem);
+ HostVO hostMock = mock(HostVO.class);
+ StartupRoutingCommand startupRoutingCommand =
mock(StartupRoutingCommand.class);
+ StoragePoolVO poolMock = mock(StoragePoolVO.class);
+
Mockito.lenient().when(poolMock.getScope()).thenReturn(ScopeType.CLUSTER);
+
Mockito.lenient().when(poolMock.getStatus()).thenReturn(StoragePoolStatus.Up);
+ Mockito.lenient().when(poolMock.getId()).thenReturn(123L);
+
Mockito.lenient().when(poolMock.getPoolType()).thenReturn(Storage.StoragePoolType.Filesystem);
Mockito.when(hostMock.getDataCenterId()).thenReturn(1L);
Mockito.when(hostMock.getPodId()).thenReturn(1L);
Mockito.when(hostMock.getClusterId()).thenReturn(1L);
Mockito.when(startupRoutingCommand.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
- Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L,
1L, 1L, ScopeType.CLUSTER, null)).thenReturn(Collections.singletonList(pool));
- Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L,
null, null, ScopeType.ZONE,
null)).thenReturn(Collections.<StoragePoolVO>emptyList());
- Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L,
null, null, ScopeType.ZONE,
Hypervisor.HypervisorType.KVM)).thenReturn(Collections.<StoragePoolVO>emptyList());
- Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L,
null, null, ScopeType.ZONE,
Hypervisor.HypervisorType.Any)).thenReturn(Collections.<StoragePoolVO>emptyList());
+ Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L,
1L, 1L, ScopeType.CLUSTER, null,
StoragePoolStatus.Up)).thenReturn(Collections.singletonList(pool));
+ Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L,
null, null, ScopeType.ZONE, null,
StoragePoolStatus.Up)).thenReturn(Collections.<StoragePoolVO>emptyList());
+ Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L,
null, null, ScopeType.ZONE, Hypervisor.HypervisorType.KVM,
StoragePoolStatus.Up)).thenReturn(Collections.<StoragePoolVO>emptyList());
+ Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L,
null, null, ScopeType.ZONE, Hypervisor.HypervisorType.Any,
StoragePoolStatus.Up)).thenReturn(Collections.<StoragePoolVO>emptyList());
Mockito.doReturn(true).when(storageManager).connectHostToSharedPool(hostMock,
123L);
storagePoolMonitor.processConnect(hostMock, startupRoutingCommand,
false);
@@ -87,11 +97,81 @@ public class StoragePoolMonitorTest {
@Test
public void testProcessConnectStoragePoolFailureOnHost() throws Exception {
- Mockito.when(poolDao.listBy(Mockito.anyLong(), Mockito.anyLong(),
Mockito.anyLong(),
Mockito.any(ScopeType.class))).thenReturn(Collections.singletonList(pool));
- Mockito.when(poolDao.findZoneWideStoragePoolsByTags(Mockito.anyLong(),
Mockito.any(String[].class),
Mockito.anyBoolean())).thenReturn(Collections.<StoragePoolVO>emptyList());
-
Mockito.when(poolDao.findZoneWideStoragePoolsByHypervisor(Mockito.anyLong(),
Mockito.any(Hypervisor.HypervisorType.class))).thenReturn(Collections.<StoragePoolVO>emptyList());
- Mockito.doThrow(new StorageUnavailableException("unable to mount
storage", 123L)).when(storageManager).connectHostToSharedPool(Mockito.any(),
Mockito.anyLong());
+ Mockito.lenient().when(poolDao.listBy(Mockito.anyLong(),
Mockito.anyLong(), Mockito.anyLong(),
Mockito.any(ScopeType.class))).thenReturn(Collections.singletonList(pool));
+
Mockito.lenient().when(poolDao.findZoneWideStoragePoolsByTags(Mockito.anyLong(),
Mockito.any(String[].class),
Mockito.anyBoolean())).thenReturn(Collections.<StoragePoolVO>emptyList());
+
Mockito.lenient().when(poolDao.findZoneWideStoragePoolsByHypervisor(Mockito.anyLong(),
Mockito.any(Hypervisor.HypervisorType.class))).thenReturn(Collections.<StoragePoolVO>emptyList());
+ Mockito.lenient().doThrow(new StorageUnavailableException("unable to
mount storage",
123L)).when(storageManager).connectHostToSharedPool(Mockito.any(),
Mockito.anyLong());
storagePoolMonitor.processConnect(host, cmd, false);
}
+
+ @Test
+ public void testProcessConnectWithMountDisabledStoragePoolEnabled() throws
Exception {
+ StoragePoolVO disabledZonePool = new StoragePoolVO();
+ disabledZonePool.setId(200L);
+ disabledZonePool.setScope(ScopeType.ZONE);
+ disabledZonePool.setStatus(StoragePoolStatus.Disabled);
+
disabledZonePool.setPoolType(Storage.StoragePoolType.NetworkFilesystem);
+
+ StoragePoolVO disabledClusterPool = new StoragePoolVO();
+ disabledClusterPool.setId(201L);
+ disabledClusterPool.setScope(ScopeType.CLUSTER);
+ disabledClusterPool.setStatus(StoragePoolStatus.Disabled);
+
disabledClusterPool.setPoolType(Storage.StoragePoolType.NetworkFilesystem);
+ HostVO hostMock = mock(HostVO.class);
+ StartupRoutingCommand startupRoutingCommand =
mock(StartupRoutingCommand.class);
+ Mockito.when(hostMock.getDataCenterId()).thenReturn(1L);
+ Mockito.when(hostMock.getPodId()).thenReturn(1L);
+ Mockito.when(hostMock.getClusterId()).thenReturn(1L);
+ Mockito.when(hostMock.getId()).thenReturn(1L);
+
Mockito.when(startupRoutingCommand.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
+
+ try (MockedStatic<StorageManager> storageManagerMockedStatic =
Mockito.mockStatic(StorageManager.class)) {
+ ConfigKey<Boolean> mockConfigKey = mock(ConfigKey.class);
+ Mockito.when(mockConfigKey.value()).thenReturn(true);
+ Mockito.when(mockConfigKey.valueIn(1L)).thenReturn(true);
+
+
storageManagerMockedStatic.when(StorageManager::getMountDisabledStoragePool).thenReturn(mockConfigKey);
+
+
Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L, 1L, 1L,
ScopeType.CLUSTER, null, StoragePoolStatus.Up))
+ .thenReturn(new ArrayList<>());
+
Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L, null, null,
ScopeType.ZONE, null, StoragePoolStatus.Up))
+ .thenReturn(new ArrayList<>());
+
Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L, null, null,
ScopeType.ZONE, Hypervisor.HypervisorType.KVM, StoragePoolStatus.Up))
+ .thenReturn(new ArrayList<>());
+
Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L, null, null,
ScopeType.ZONE, Hypervisor.HypervisorType.Any, StoragePoolStatus.Up))
+ .thenReturn(new ArrayList<>());
+
+ List<StoragePoolVO> zoneDisabledPoolsBySAG = new ArrayList<>();
+ zoneDisabledPoolsBySAG.add(disabledZonePool);
+ Mockito.when(poolDao.findDisabledPoolsByScopeAndAccessGroups(1L,
null, null, ScopeType.ZONE, new String[0]))
+ .thenReturn(zoneDisabledPoolsBySAG);
+
Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L, null, null,
ScopeType.ZONE, null, StoragePoolStatus.Disabled))
+ .thenReturn(new ArrayList<>());
+
+ List<StoragePoolVO> clusterDisabledPoolsBySAG = new ArrayList<>();
+ clusterDisabledPoolsBySAG.add(disabledClusterPool);
+ Mockito.when(poolDao.findDisabledPoolsByScopeAndAccessGroups(1L,
1L, 1L, ScopeType.CLUSTER, new String[0]))
+ .thenReturn(clusterDisabledPoolsBySAG);
+
Mockito.when(poolDao.findStoragePoolsByEmptyStorageAccessGroups(1L, 1L, 1L,
ScopeType.CLUSTER, null, StoragePoolStatus.Disabled))
+ .thenReturn(new ArrayList<>());
+
+ Mockito.when(storageManager.getStorageAccessGroups(null, null,
null, 1L)).thenReturn(new String[0]);
+
Mockito.when(storageManager.findStoragePoolsConnectedToHost(1L)).thenReturn(Collections.emptyList());
+
Mockito.doReturn(true).when(storageManager).connectHostToSharedPool(hostMock,
200L);
+
Mockito.doReturn(true).when(storageManager).connectHostToSharedPool(hostMock,
201L);
+
+ storagePoolMonitor.processConnect(hostMock, startupRoutingCommand,
false);
+
+ Mockito.verify(poolDao,
Mockito.times(1)).findDisabledPoolsByScopeAndAccessGroups(1L, null, null,
ScopeType.ZONE, new String[0]);
+ Mockito.verify(poolDao,
Mockito.times(1)).findStoragePoolsByEmptyStorageAccessGroups(1L, null, null,
ScopeType.ZONE, null, StoragePoolStatus.Disabled);
+ Mockito.verify(poolDao,
Mockito.times(1)).findDisabledPoolsByScopeAndAccessGroups(1L, 1L, 1L,
ScopeType.CLUSTER, new String[0]);
+ Mockito.verify(poolDao,
Mockito.times(1)).findStoragePoolsByEmptyStorageAccessGroups(1L, 1L, 1L,
ScopeType.CLUSTER, null, StoragePoolStatus.Disabled);
+
+ Mockito.verify(storageManager,
Mockito.times(1)).connectHostToSharedPool(Mockito.eq(hostMock),
Mockito.eq(200L));
+ Mockito.verify(storageManager,
Mockito.times(1)).connectHostToSharedPool(Mockito.eq(hostMock),
Mockito.eq(201L));
+ Mockito.verify(storageManager,
Mockito.times(1)).createCapacityEntry(Mockito.eq(200L));
+ Mockito.verify(storageManager,
Mockito.times(1)).createCapacityEntry(Mockito.eq(201L));
+ }
+ }
}