From 2a4c2c250696a154ccf8a7c8fff8604d893e9258 Mon Sep 17 00:00:00 2001 From: Rakesh Date: Thu, 12 Aug 2021 05:01:15 +0200 Subject: [PATCH] Global setting to select preferred storage pool (#5249) * Global setting to select preferred storage pool Currently all the volumes are allocated on storage pools based on the capacity or the algorithm selected. Sometimes we need to deploy all volumes of particular account in a specific storage pool and in that case its not possible. with this change, we can specify the uuid of the preferred storage pool, so that all volumes of the account will be deployed in this pool * code feedback Co-authored-by: Rakesh Venkatesh --- .../com/cloud/storage/StorageManager.java | 3 ++ .../orchestration/VolumeOrchestrator.java | 34 +++++++++++++++- .../deploy/DeploymentPlanningManagerImpl.java | 40 ++++++++++++++++++- .../com/cloud/storage/StorageManagerImpl.java | 3 +- 4 files changed, 76 insertions(+), 4 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 3d6d0626c55..7976b313167 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 @@ -149,6 +149,9 @@ public interface StorageManager extends StorageService { "If set to true, the disk is created only when there is a suitable storage pool that supports the disk provisioning type specified by the service/disk offering. " + "If set to false, the disk is created with a disk provisioning type supported by the pool. Default value is false, and this is currently supported for VMware only.", true, ConfigKey.Scope.Zone); + ConfigKey PreferredStoragePool = new ConfigKey(String.class, "preferred.storage.pool", "Advanced", "", + "The UUID of preferred storage pool for allocation.", true, ConfigKey.Scope.Account, null); + /** * Returns a comma separated list of tags for the specified storage pool * @param poolId diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 5a42b3a6b93..9322481f211 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -300,6 +301,31 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati return _volsDao.persist(newVol); } + private Optional getMatchingStoragePool(String preferredPoolId, List storagePools) { + if (preferredPoolId == null) { + return Optional.empty(); + } + return storagePools.stream() + .filter(pool -> pool.getUuid().equalsIgnoreCase(preferredPoolId)) + .findFirst(); + } + + private Optional getPreferredStoragePool(List poolList, VirtualMachine vm) { + String accountStoragePoolUuid = StorageManager.PreferredStoragePool.valueIn(vm.getAccountId()); + Optional storagePool = getMatchingStoragePool(accountStoragePoolUuid, poolList); + + if (storagePool.isPresent()) { + s_logger.debug("A storage pool is specified for this account, so we will use this storage pool for allocation: " + + storagePool.get().getUuid()); + } else { + String globalStoragePoolUuid = StorageManager.PreferredStoragePool.value(); + storagePool = getMatchingStoragePool(globalStoragePoolUuid, poolList); + storagePool.ifPresent(pool -> s_logger.debug("A storage pool is specified in global setting, so we will use this storage pool for allocation: " + + pool.getUuid())); + } + return storagePool; + } + @Override public StoragePool findStoragePool(DiskProfile dskCh, DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, final Set avoid) { Long podId = null; @@ -321,9 +347,13 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } DataCenterDeployment plan = new DataCenterDeployment(dc.getId(), podId, clusterId, hostId, null, null); - final List poolList = allocator.allocateToPool(dskCh, profile, plan, avoidList, 1); + final List poolList = allocator.allocateToPool(dskCh, profile, plan, avoidList, StoragePoolAllocator.RETURN_UPTO_ALL); if (poolList != null && !poolList.isEmpty()) { - return (StoragePool)dataStoreMgr.getDataStore(poolList.get(0).getId(), DataStoreRole.Primary); + // Check if the preferred storage pool can be used. If yes, use it. + Optional storagePool = getPreferredStoragePool(poolList, vm); + + return (storagePool.isPresent()) ? (StoragePool) this.dataStoreMgr.getDataStore(storagePool.get().getId(), DataStoreRole.Primary) : + (StoragePool)dataStoreMgr.getDataStore(poolList.get(0).getId(), DataStoreRole.Primary); } } return null; diff --git a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java index afcaacf0143..a225015ebff 100644 --- a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.Timer; import java.util.TreeSet; @@ -1674,7 +1675,7 @@ StateListener, Configurable { for (StoragePoolAllocator allocator : _storagePoolAllocators) { final List suitablePools = allocator.allocateToPool(diskProfile, vmProfile, plan, avoid, returnUpTo); if (suitablePools != null && !suitablePools.isEmpty()) { - suitableVolumeStoragePools.put(toBeCreated, suitablePools); + checkForPreferredStoragePool(suitablePools, vmProfile.getVirtualMachine(), suitableVolumeStoragePools, toBeCreated); foundPotentialPools = true; break; } @@ -1715,6 +1716,43 @@ StateListener, Configurable { return new Pair>, List>(suitableVolumeStoragePools, readyAndReusedVolumes); } + private void checkForPreferredStoragePool(List suitablePools, + VirtualMachine vm, + Map> suitableVolumeStoragePools, + VolumeVO toBeCreated) { + List pools = new ArrayList<>(); + Optional storagePool = getPreferredStoragePool(suitablePools, vm); + storagePool.ifPresent(pools::add); + + pools.addAll(suitablePools); + suitableVolumeStoragePools.put(toBeCreated, pools); + } + + private Optional getMatchingStoragePool(String preferredPoolId, List storagePools) { + if (preferredPoolId == null) { + return Optional.empty(); + } + return storagePools.stream() + .filter(pool -> pool.getUuid().equalsIgnoreCase(preferredPoolId)) + .findFirst(); + } + + private Optional getPreferredStoragePool(List poolList, VirtualMachine vm) { + String accountStoragePoolUuid = StorageManager.PreferredStoragePool.valueIn(vm.getAccountId()); + Optional storagePool = getMatchingStoragePool(accountStoragePoolUuid, poolList); + + if (storagePool.isPresent()) { + s_logger.debug("A storage pool is specified for this account, so we will use this storage pool for allocation: " + + storagePool.get().getUuid()); + } else { + String globalStoragePoolUuid = StorageManager.PreferredStoragePool.value(); + storagePool = getMatchingStoragePool(globalStoragePoolUuid, poolList); + storagePool.ifPresent(pool -> s_logger.debug("A storage pool is specified in global setting, so we will use this storage pool for allocation: " + + pool.getUuid())); + } + return storagePool; + } + private boolean isEnabledForAllocation(long zoneId, Long podId, Long clusterId) { // Check if the zone exists in the system DataCenterVO zone = _dcDao.findById(zoneId); diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index d75f8335787..01932169a38 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -3212,7 +3212,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C PRIMARY_STORAGE_DOWNLOAD_WAIT, SecStorageMaxMigrateSessions, MaxDataMigrationWaitTime, - DiskProvisioningStrictness + DiskProvisioningStrictness, + PreferredStoragePool }; }