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(); Hypervisor.HypervisorType getHypervisor();
boolean isManaged(); boolean isManaged();
Long getParent();
} }

View File

@ -100,6 +100,10 @@ public class DiskProfile {
return name; 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. * @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); 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; VolumeInfo createVolumeFromSnapshot(Volume volume, Snapshot snapshot, UserVm vm) throws StorageUnavailableException;
Volume migrateVolume(Volume volume, StoragePool destPool) 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(); Map<String, String> getDetails();
PrimaryDataStoreLifeCycle getLifeCycle(); 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); List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo);
static int RETURN_UPTO_ALL = -1; 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; 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) { public Pair<Pod, Long> findPod(VirtualMachineTemplate template, ServiceOffering offering, DataCenter dc, long accountId, Set<Long> avoids) {
for (PodAllocator allocator : _podAllocators) { for (PodAllocator allocator : _podAllocators) {
final Pair<Pod, Long> pod = allocator.allocateTo(template, offering, dc, accountId, avoids); 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 @Override
public List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { public List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) {
List<StoragePool> pools = select(dskCh, vmProfile, plan, avoid, 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, protected List<StoragePool> reorderPoolsByCapacity(DeploymentPlan plan,
@ -156,7 +156,8 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
return reorderedPools; 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) { if (pools == null) {
return null; return null;
} }

View File

@ -241,6 +241,11 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
return pdsv.isManaged(); return pdsv.isManaged();
} }
@Override
public Long getParent() {
return pdsv.getParent();
}
private boolean canCloneVolume() { private boolean canCloneVolume() {
return Boolean.valueOf(getDriver().getCapabilities().get(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_VOLUME.toString())); 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.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.crypto.Mac; import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
@ -1482,10 +1485,26 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
} else { } else {
suitablePools = allPools; suitablePools = allPools;
} }
abstractDataStoreClustersList((List<StoragePool>) allPools);
abstractDataStoreClustersList((List<StoragePool>) suitablePools);
return new Pair<List<? extends StoragePool>, List<? extends StoragePool>>(allPools, 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. * This method looks for all storage pools that are compatible with the given volume.
* <ul> * <ul>

View File

@ -30,6 +30,7 @@ import java.util.concurrent.ExecutionException;
import javax.inject.Inject; 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.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; 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."); 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)) { if (!storageMgr.storagePoolHasEnoughSpace(Collections.singletonList(vol), destPool)) {
throw new CloudRuntimeException("Storage pool " + destPool.getName() + " does not have enough space to migrate volume " + vol.getName()); 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; private ResourceTagDao resourceTagDao;
@Inject @Inject
private TemplateOVFPropertiesDao templateOVFPropertiesDao; private TemplateOVFPropertiesDao templateOVFPropertiesDao;
@Inject
private VolumeOrchestrationService _volumeMgr;
private ScheduledExecutorService _executor = null; private ScheduledExecutorService _executor = null;
private ScheduledExecutorService _vmIpFetchExecutor = null; private ScheduledExecutorService _vmIpFetchExecutor = null;
@ -5556,6 +5558,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
checkDestinationHypervisorType(destPool, vm); 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); _itMgr.storageMigration(vm.getUuid(), destPool);
return _vmDao.findById(vm.getId()); return _vmDao.findById(vm.getId());