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));
+        }
+    }
 }

Reply via email to