diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java index 46f8f5e0429..c8fcf5f3df5 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/StoragePoolAllocator.java @@ -28,6 +28,12 @@ import com.cloud.vm.VirtualMachineProfile; /** */ public interface StoragePoolAllocator extends Adapter { + /** + * Overloaded method calls allocateToPool with bypassStorageTypeCheck = false + * and returns a list of pools suitable. + **/ + List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); + /** * Determines which storage pools are suitable for the guest virtual machine * and returns a list of pools suitable. @@ -45,10 +51,12 @@ public interface StoragePoolAllocator extends Adapter { * @param ExcludeList * avoid * @param int returnUpTo (use -1 to return all possible pools) + * @param boolean bypassStorageTypeCheck allows bypassing useLocalStorage check for provided DiskProfile when true * @return List List of storage pools that are suitable for the * VM **/ - List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); + List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck); + static int RETURN_UPTO_ALL = -1; 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 59fe3f14d39..3375c6ff207 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 @@ -122,6 +122,8 @@ public interface PrimaryDataStoreDao extends GenericDao { List listLocalStoragePoolByPath(long datacenterId, String path); + List findPoolsInClusters(List clusterIds); + void deletePoolTags(long poolId); List listChildStoragePoolsInDatastoreCluster(long poolId); 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 7830df57204..dfe1a6994d5 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 @@ -56,6 +56,7 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase private final SearchBuilder DeleteLvmSearch; private final SearchBuilder DcLocalStorageSearch; private final GenericSearchBuilder StatusCountSearch; + private final SearchBuilder ClustersSearch; @Inject private StoragePoolDetailsDao _detailsDao; @@ -133,6 +134,10 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase DcLocalStorageSearch.and("scope", DcLocalStorageSearch.entity().getScope(), SearchCriteria.Op.EQ); DcLocalStorageSearch.done(); + ClustersSearch = createSearchBuilder(); + ClustersSearch.and("clusterIds", ClustersSearch.entity().getClusterId(), Op.IN); + ClustersSearch.and("status", ClustersSearch.entity().getStatus(), Op.EQ); + } @Override @@ -568,4 +573,12 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase sc.addAnd("removed", SearchCriteria.Op.NULL); return getCount(sc); } + + @Override + public List findPoolsInClusters(List clusterIds) { + SearchCriteria sc = ClustersSearch.create(); + sc.setParameters("clusterIds", clusterIds.toArray()); + sc.setParameters("status", StoragePoolStatus.Up); + return listBy(sc); + } } 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 cfe32c2bd07..82649b9f717 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 @@ -26,15 +26,12 @@ import java.util.Map; 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; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.log4j.Logger; import com.cloud.capacity.Capacity; import com.cloud.capacity.dao.CapacityDao; @@ -42,10 +39,12 @@ import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.StorageUnavailableException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.StorageUtil; import com.cloud.storage.Volume; import com.cloud.storage.dao.VolumeDao; @@ -87,11 +86,16 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement return false; } - protected abstract List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo); + protected abstract List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck); @Override public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { - List pools = select(dskCh, vmProfile, plan, avoid, returnUpTo); + return allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, false); + } + + @Override + public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { + List pools = select(dskCh, vmProfile, plan, avoid, returnUpTo, bypassStorageTypeCheck); return reorderPools(pools, vmProfile, plan); } diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java index 12884d5d62e..9967a2caff9 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ClusterScopeStoragePoolAllocator.java @@ -45,9 +45,13 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat DiskOfferingDao _diskOfferingDao; @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { s_logger.debug("ClusterScopeStoragePoolAllocator looking for storage pool"); + if (!bypassStorageTypeCheck && dskCh.useLocalStorage()) { + return null; + } + List suitablePools = new ArrayList(); long dcId = plan.getDataCenterId(); diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java index b3a1c0d4b10..f02a89811b0 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/GarbageCollectingStoragePoolAllocator.java @@ -47,7 +47,7 @@ public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAl boolean _storagePoolCleanupEnabled; @Override - public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { s_logger.debug("GarbageCollectingStoragePoolAllocator looking for storage pool"); if (!_storagePoolCleanupEnabled) { s_logger.debug("Storage pool cleanup is not enabled, so GarbageCollectingStoragePoolAllocator is being skipped."); @@ -68,7 +68,7 @@ public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAl ExcludeList myAvoids = new ExcludeList(avoid.getDataCentersToAvoid(), avoid.getPodsToAvoid(), avoid.getClustersToAvoid(), avoid.getHostsToAvoid(), avoid.getPoolsToAvoid()); - return allocator.allocateToPool(dskCh, vmProfile, plan, myAvoids, returnUpTo); + return allocator.allocateToPool(dskCh, vmProfile, plan, myAvoids, returnUpTo, bypassStorageTypeCheck); } @Override diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java index 390272ea697..6fc4adaad0e 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java @@ -60,10 +60,10 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator { ConfigurationDao _configDao; @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { s_logger.debug("LocalStoragePoolAllocator trying to find storage pool to fit the vm"); - if (!dskCh.useLocalStorage()) { + if (!bypassStorageTypeCheck && !dskCh.useLocalStorage()) { return null; } diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java index e552a1bf2ca..4b150b26dc4 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/UseLocalForRootAllocator.java @@ -39,12 +39,17 @@ public class UseLocalForRootAllocator extends LocalStoragePoolAllocator implemen @Override public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + return allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, false); + } + + @Override + public List allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); if (!dc.isLocalStorageEnabled()) { return null; } - return super.allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo); + return super.allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, bypassStorageTypeCheck); } @Override diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java index 301704a75a6..e3b29912477 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java @@ -50,10 +50,10 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { @Override - protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + protected List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { LOGGER.debug("ZoneWideStoragePoolAllocator to find storage pool"); - if (dskCh.useLocalStorage()) { + if (!bypassStorageTypeCheck && dskCh.useLocalStorage()) { return null; } diff --git a/plugins/storage-allocators/random/src/main/java/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java b/plugins/storage-allocators/random/src/main/java/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java index 6b912fb74aa..eed623a9ed0 100644 --- a/plugins/storage-allocators/random/src/main/java/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java +++ b/plugins/storage-allocators/random/src/main/java/org/apache/cloudstack/storage/allocator/RandomStoragePoolAllocator.java @@ -35,7 +35,7 @@ public class RandomStoragePoolAllocator extends AbstractStoragePoolAllocator { private static final Logger s_logger = Logger.getLogger(RandomStoragePoolAllocator.class); @Override - public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + public List select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) { List suitablePools = new ArrayList(); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 8df118dcbc7..8f0007aca0c 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.Executors; @@ -40,7 +41,6 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.storage.Storage; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; @@ -573,6 +573,8 @@ import com.cloud.alert.AlertManager; import com.cloud.alert.AlertVO; import com.cloud.alert.dao.AlertDao; import com.cloud.api.ApiDBUtils; +import com.cloud.api.query.dao.StoragePoolJoinDao; +import com.cloud.api.query.vo.StoragePoolJoinVO; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; @@ -657,8 +659,10 @@ import com.cloud.storage.GuestOSHypervisorVO; import com.cloud.storage.GuestOSVO; import com.cloud.storage.GuestOsCategory; import com.cloud.storage.ScopeType; +import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.Volume; import com.cloud.storage.VolumeApiServiceImpl; import com.cloud.storage.VolumeVO; @@ -789,6 +793,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject private PrimaryDataStoreDao _poolDao; @Inject + private StoragePoolJoinDao _poolJoinDao; + @Inject private NetworkDao _networkDao; @Inject private StorageManager _storageMgr; @@ -1145,7 +1151,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return new Pair, Integer>(result.first(), result.second()); } - private HypervisorType getHypervisorType(VMInstanceVO vm, StoragePool srcVolumePool, VirtualMachineProfile profile) { + private HypervisorType getHypervisorType(VMInstanceVO vm, StoragePool srcVolumePool) { HypervisorType type = null; if (vm == null) { StoragePoolVO poolVo = _poolDao.findById(srcVolumePool.getId()); @@ -1155,18 +1161,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe ClusterVO cluster = _clusterDao.findById(clusterId); type = cluster.getHypervisorType(); } - } else if (ScopeType.ZONE.equals(poolVo.getScope())) { - Long zoneId = poolVo.getDataCenterId(); - if (zoneId != null) { - DataCenterVO dc = _dcDao.findById(zoneId); - } } if (null == type) { type = srcVolumePool.getHypervisor(); } } else { - type = profile.getHypervisorType(); + type = vm.getHypervisorType(); } return type; } @@ -1488,12 +1489,17 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } StoragePool srcVolumePool = _poolDao.findById(volume.getPoolId()); - allPools = getAllStoragePoolCompatileWithVolumeSourceStoragePool(srcVolumePool); + HypervisorType hypervisorType = getHypervisorType(vm, srcVolumePool); + Pair> hostClusterPair = getVolumeVmHostClusters(srcVolumePool, vm, hypervisorType); + Host vmHost = hostClusterPair.first(); + List clusters = hostClusterPair.second(); + allPools = getAllStoragePoolCompatibleWithVolumeSourceStoragePool(srcVolumePool, hypervisorType, clusters); allPools.remove(srcVolumePool); if (vm != null) { - suitablePools = findAllSuitableStoragePoolsForVm(volume, vm, srcVolumePool); + suitablePools = findAllSuitableStoragePoolsForVm(volume, vm, vmHost, srcVolumePool, + CollectionUtils.isNotEmpty(clusters) ? clusters.get(0) : null, hypervisorType); } else { - suitablePools = allPools; + suitablePools = findAllSuitableStoragePoolsForDetachedVolume(volume, allPools); } List avoidPools = new ArrayList<>(); if (srcVolumePool.getParent() != 0L) { @@ -1520,6 +1526,30 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } } + private Pair> getVolumeVmHostClusters(StoragePool srcVolumePool, VirtualMachine vm, HypervisorType hypervisorType) { + Host host = null; + List clusters = new ArrayList<>(); + Long clusterId = srcVolumePool.getClusterId(); + if (vm != null) { + Long hostId = vm.getHostId(); + if (hostId == null) { + hostId = vm.getLastHostId(); + } + if (hostId != null) { + host = _hostDao.findById(hostId); + } + } + if (clusterId == null && host != null) { + clusterId = host.getClusterId(); + } + if (clusterId != null && vm != null) { + clusters.add(_clusterDao.findById(clusterId)); + } else { + clusters.addAll(_clusterDao.listByDcHyType(srcVolumePool.getDataCenterId(), hypervisorType.toString())); + } + return new Pair<>(host, clusters); + } + /** * This method looks for all storage pools that are compatible with the given volume. *
    @@ -1527,15 +1557,18 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe *
  • We also all storage available filtering by data center, pod and cluster as the current storage pool used by the given volume.
  • *
*/ - private List getAllStoragePoolCompatileWithVolumeSourceStoragePool(StoragePool srcVolumePool) { + private List getAllStoragePoolCompatibleWithVolumeSourceStoragePool(StoragePool srcVolumePool, HypervisorType hypervisorType, List clusters) { List storagePools = new ArrayList<>(); - List zoneWideStoragePools = _poolDao.findZoneWideStoragePoolsByTags(srcVolumePool.getDataCenterId(), null); + List zoneWideStoragePools = _poolDao.findZoneWideStoragePoolsByHypervisor(srcVolumePool.getDataCenterId(), hypervisorType); if (CollectionUtils.isNotEmpty(zoneWideStoragePools)) { storagePools.addAll(zoneWideStoragePools); } - List clusterAndLocalStoragePools = _poolDao.listBy(srcVolumePool.getDataCenterId(), srcVolumePool.getPodId(), srcVolumePool.getClusterId(), null); - if (CollectionUtils.isNotEmpty(clusterAndLocalStoragePools)) { - storagePools.addAll(clusterAndLocalStoragePools); + if (CollectionUtils.isNotEmpty(clusters)) { + List clusterIds = clusters.stream().map(Cluster::getId).collect(Collectors.toList()); + List clusterAndLocalStoragePools = _poolDao.findPoolsInClusters(clusterIds); + if (CollectionUtils.isNotEmpty(clusterAndLocalStoragePools)) { + storagePools.addAll(clusterAndLocalStoragePools); + } } return storagePools; } @@ -1547,35 +1580,33 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe * * Side note: the idea behind this method is to provide power for administrators of manually overriding deployments defined by CloudStack. */ - private List findAllSuitableStoragePoolsForVm(final VolumeVO volume, VMInstanceVO vm, StoragePool srcVolumePool) { + private List findAllSuitableStoragePoolsForVm(final VolumeVO volume, VMInstanceVO vm, Host vmHost, StoragePool srcVolumePool, Cluster srcCluster, HypervisorType hypervisorType) { List suitablePools = new ArrayList<>(); - - HostVO host = _hostDao.findById(vm.getHostId()); - if (host == null) { - host = _hostDao.findById(vm.getLastHostId()); - } - ExcludeList avoid = new ExcludeList(); avoid.addPool(srcVolumePool.getId()); - - DataCenterDeployment plan = new DataCenterDeployment(volume.getDataCenterId(), srcVolumePool.getPodId(), srcVolumePool.getClusterId(), null, null, null); + Long clusterId = null; + Long podId = null; + if (srcCluster != null) { + clusterId = srcCluster.getId(); + podId = srcCluster.getPodId(); + } + DataCenterDeployment plan = new DataCenterDeployment(volume.getDataCenterId(), podId, clusterId, + null, null, null, null); VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); // OfflineVmwareMigration: vm might be null here; deal! - HypervisorType type = getHypervisorType(vm, srcVolumePool, profile); DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); - //This is an override mechanism so we can list the possible local storage pools that a volume in a shared pool might be able to be migrated to - DiskProfile diskProfile = new DiskProfile(volume, diskOffering, type); - diskProfile.setUseLocalStorage(true); + DiskProfile diskProfile = new DiskProfile(volume, diskOffering, hypervisorType); for (StoragePoolAllocator allocator : _storagePoolAllocators) { - List pools = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL); + List pools = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL, true); if (CollectionUtils.isEmpty(pools)) { continue; } for (StoragePool pool : pools) { - boolean isLocalPoolSameHostAsSourcePool = pool.isLocal() && StringUtils.equals(host.getPrivateIpAddress(), pool.getHostAddress()); - if (isLocalPoolSameHostAsSourcePool || pool.isShared()) { + boolean isLocalPoolSameHostAsVmHost = pool.isLocal() && + (vmHost == null || StringUtils.equals(vmHost.getPrivateIpAddress(), pool.getHostAddress())); + if (isLocalPoolSameHostAsVmHost || pool.isShared()) { suitablePools.add(pool); } @@ -1584,6 +1615,29 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return suitablePools; } + private List findAllSuitableStoragePoolsForDetachedVolume(Volume volume, List allPools) { + List suitablePools = new ArrayList<>(); + if (CollectionUtils.isEmpty(allPools)) { + return suitablePools; + } + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + List tags = new ArrayList<>(); + String[] tagsArray = diskOffering.getTagsArray(); + if (tagsArray != null && tagsArray.length > 0) { + tags = Arrays.asList(tagsArray); + } + Long[] poolIds = allPools.stream().map(StoragePool::getId).toArray(Long[]::new); + List pools = _poolJoinDao.searchByIds(poolIds); + for (StoragePoolJoinVO storagePool : pools) { + if (StoragePoolStatus.Up.equals(storagePool.getStatus()) && + (CollectionUtils.isEmpty(tags) || tags.contains(storagePool.getTag()))) { + Optional match = allPools.stream().filter(x -> x.getId() == storagePool.getId()).findFirst(); + match.ifPresent(suitablePools::add); + } + } + return suitablePools; + } + private Pair, Integer> searchForServers(final Long startIndex, final Long pageSize, final Object name, final Object type, final Object state, final Object zone, final Object pod, final Object cluster, final Object id, final Object keyword, final Object resourceState, final Object haHosts, final Object hypervisorType, final Object hypervisorVersion, final Object... excludes) {