Fix migrate vm and volume APIs in case if datastore cluster

This commit is contained in:
Harikrishna Patnala 2020-07-30 10:06:37 +05:30
parent fc05d3168f
commit 61dd85876b
11 changed files with 84 additions and 3 deletions

View File

@ -106,4 +106,6 @@ public interface StoragePool extends Identity, InternalIdentity {
Hypervisor.HypervisorType getHypervisor();
boolean isManaged();
Long getParent();
}

View File

@ -100,6 +100,10 @@ public class DiskProfile {
return name;
}
public void setTags(String[] tags) {
this.tags = tags;
}
/**
* @return tags for the disk. This can be used to match it to different storage pools.
*/

View File

@ -84,6 +84,8 @@ public interface VolumeOrchestrationService {
String getVmNameOnVolume(Volume volume);
StoragePool findChildDataStoreInDataStoreCluster(DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Long datastoreClusterId);
VolumeInfo createVolumeFromSnapshot(Volume volume, Snapshot snapshot, UserVm vm) throws StorageUnavailableException;
Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageUnavailableException;

View File

@ -58,4 +58,6 @@ public interface PrimaryDataStoreInfo extends StoragePool {
Map<String, String> getDetails();
PrimaryDataStoreLifeCycle getLifeCycle();
Long getParent();
}

View File

@ -51,4 +51,6 @@ public interface StoragePoolAllocator extends Adapter {
List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo);
static int RETURN_UPTO_ALL = -1;
List<StoragePool> reorderPools(List<StoragePool> pools, VirtualMachineProfile vmProfile, DeploymentPlan plan);
}

View File

@ -296,6 +296,34 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
return null;
}
@Override
public StoragePool findChildDataStoreInDataStoreCluster(DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Long datastoreClusterId) {
Long podId = null;
if (pod != null) {
podId = pod.getId();
} else if (clusterId != null) {
Cluster cluster = _entityMgr.findById(Cluster.class, clusterId);
if (cluster != null) {
podId = cluster.getPodId();
}
}
List<StoragePoolVO> childDatastores = _storagePoolDao.listChildStoragePoolsInDatastoreCluster(datastoreClusterId);
List<StoragePool> suitablePools = new ArrayList<StoragePool>();
for (StoragePoolVO childDatastore: childDatastores)
suitablePools.add((StoragePool)dataStoreMgr.getDataStore(childDatastore.getId(), DataStoreRole.Primary));
VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
for (StoragePoolAllocator allocator : _storagePoolAllocators) {
DataCenterDeployment plan = new DataCenterDeployment(dc.getId(), podId, clusterId, hostId, null, null);
final List<StoragePool> poolList = allocator.reorderPools(suitablePools, profile, plan);
if (poolList != null && !poolList.isEmpty()) {
return (StoragePool)dataStoreMgr.getDataStore(poolList.get(0).getId(), DataStoreRole.Primary);
}
}
return null;
}
public Pair<Pod, Long> findPod(VirtualMachineTemplate template, ServiceOffering offering, DataCenter dc, long accountId, Set<Long> avoids) {
for (PodAllocator allocator : _podAllocators) {
final Pair<Pod, Long> pod = allocator.allocateTo(template, offering, dc, accountId, avoids);

View File

@ -90,7 +90,7 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
@Override
public List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) {
List<StoragePool> pools = select(dskCh, vmProfile, plan, avoid, returnUpTo);
return reOrder(pools, vmProfile, plan);
return reorderPools(pools, vmProfile, plan);
}
protected List<StoragePool> reorderPoolsByCapacity(DeploymentPlan plan,
@ -156,7 +156,8 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
return reorderedPools;
}
protected List<StoragePool> reOrder(List<StoragePool> pools, VirtualMachineProfile vmProfile, DeploymentPlan plan) {
@Override
public List<StoragePool> reorderPools(List<StoragePool> pools, VirtualMachineProfile vmProfile, DeploymentPlan plan) {
if (pools == null) {
return null;
}

View File

@ -241,6 +241,11 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
return pdsv.isManaged();
}
@Override
public Long getParent() {
return pdsv.getParent();
}
private boolean canCloneVolume() {
return Boolean.valueOf(getDriver().getCapabilities().get(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_VOLUME.toString()));
}

View File

@ -27,10 +27,13 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@ -1482,10 +1485,26 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
} else {
suitablePools = allPools;
}
abstractDataStoreClustersList((List<StoragePool>) allPools);
abstractDataStoreClustersList((List<StoragePool>) suitablePools);
return new Pair<List<? extends StoragePool>, List<? extends StoragePool>>(allPools, suitablePools);
}
private void abstractDataStoreClustersList(List<StoragePool> storagePools) {
Predicate<StoragePool> childDatastorePredicate = pool -> (pool.getParent() != 0);
List<StoragePool> childDatastores = storagePools.stream().filter(childDatastorePredicate).collect(Collectors.toList());
if (!childDatastores.isEmpty()) {
storagePools.removeAll(childDatastores);
Set<Long> parentStoragePoolIds = childDatastores.stream().map(mo -> mo.getParent()).collect(Collectors.toSet());
for (Long parentStoragePoolId : parentStoragePoolIds) {
StoragePool parentPool = _poolDao.findById(parentStoragePoolId);
if (!storagePools.contains(parentPool))
storagePools.add(parentPool);
}
}
}
/**
* This method looks for all storage pools that are compatible with the given volume.
* <ul>

View File

@ -30,6 +30,7 @@ import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
import com.cloud.dc.Pod;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
@ -2192,6 +2193,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
throw new InvalidParameterValueException("Cannot migrate volume " + vol + "to the destination storage pool " + destPool.getName() + " as the storage pool is in maintenance mode.");
}
if (destPool.getPoolType() == Storage.StoragePoolType.DatastoreCluster) {
DataCenter dc = _entityMgr.findById(DataCenter.class, vol.getDataCenterId());
Pod destPoolPod = _entityMgr.findById(Pod.class, destPool.getPodId());
destPool = _volumeMgr.findChildDataStoreInDataStoreCluster(dc, destPoolPod, destPool.getClusterId(), null, null, destPool.getId());
}
if (!storageMgr.storagePoolHasEnoughSpace(Collections.singletonList(vol), destPool)) {
throw new CloudRuntimeException("Storage pool " + destPool.getName() + " does not have enough space to migrate volume " + vol.getName());
}

View File

@ -504,6 +504,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
private ResourceTagDao resourceTagDao;
@Inject
private TemplateOVFPropertiesDao templateOVFPropertiesDao;
@Inject
private VolumeOrchestrationService _volumeMgr;
private ScheduledExecutorService _executor = null;
private ScheduledExecutorService _vmIpFetchExecutor = null;
@ -5556,6 +5558,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
checkDestinationHypervisorType(destPool, vm);
if (destPool.getPoolType() == Storage.StoragePoolType.DatastoreCluster) {
DataCenter dc = _entityMgr.findById(DataCenter.class, vm.getDataCenterId());
Pod destPoolPod = _entityMgr.findById(Pod.class, destPool.getPodId());
destPool = _volumeMgr.findChildDataStoreInDataStoreCluster(dc, destPoolPod, destPool.getClusterId(), null, null, destPool.getId());
}
_itMgr.storageMigration(vm.getUuid(), destPool);
return _vmDao.findById(vm.getId());