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 <rakeshv@apache.org>
This commit is contained in:
Rakesh 2021-08-12 05:01:15 +02:00 committed by GitHub
parent 0011d45b22
commit 2a4c2c2506
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 4 deletions

View File

@ -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<String> PreferredStoragePool = new ConfigKey<String>(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

View File

@ -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<StoragePool> getMatchingStoragePool(String preferredPoolId, List<StoragePool> storagePools) {
if (preferredPoolId == null) {
return Optional.empty();
}
return storagePools.stream()
.filter(pool -> pool.getUuid().equalsIgnoreCase(preferredPoolId))
.findFirst();
}
private Optional<StoragePool> getPreferredStoragePool(List<StoragePool> poolList, VirtualMachine vm) {
String accountStoragePoolUuid = StorageManager.PreferredStoragePool.valueIn(vm.getAccountId());
Optional<StoragePool> 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<StoragePool> 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<StoragePool> poolList = allocator.allocateToPool(dskCh, profile, plan, avoidList, 1);
final List<StoragePool> 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> 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;

View File

@ -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<State, VirtualMachine.Event, VirtualMachine>, Configurable {
for (StoragePoolAllocator allocator : _storagePoolAllocators) {
final List<StoragePool> 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<State, VirtualMachine.Event, VirtualMachine>, Configurable {
return new Pair<Map<Volume, List<StoragePool>>, List<Volume>>(suitableVolumeStoragePools, readyAndReusedVolumes);
}
private void checkForPreferredStoragePool(List<StoragePool> suitablePools,
VirtualMachine vm,
Map<Volume, List<StoragePool>> suitableVolumeStoragePools,
VolumeVO toBeCreated) {
List<StoragePool> pools = new ArrayList<>();
Optional<StoragePool> storagePool = getPreferredStoragePool(suitablePools, vm);
storagePool.ifPresent(pools::add);
pools.addAll(suitablePools);
suitableVolumeStoragePools.put(toBeCreated, pools);
}
private Optional<StoragePool> getMatchingStoragePool(String preferredPoolId, List<StoragePool> storagePools) {
if (preferredPoolId == null) {
return Optional.empty();
}
return storagePools.stream()
.filter(pool -> pool.getUuid().equalsIgnoreCase(preferredPoolId))
.findFirst();
}
private Optional<StoragePool> getPreferredStoragePool(List<StoragePool> poolList, VirtualMachine vm) {
String accountStoragePoolUuid = StorageManager.PreferredStoragePool.valueIn(vm.getAccountId());
Optional<StoragePool> 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);

View File

@ -3212,7 +3212,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
PRIMARY_STORAGE_DOWNLOAD_WAIT,
SecStorageMaxMigrateSessions,
MaxDataMigrationWaitTime,
DiskProvisioningStrictness
DiskProvisioningStrictness,
PreferredStoragePool
};
}