mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fix migrate vm and volume APIs in case if datastore cluster
This commit is contained in:
parent
fc05d3168f
commit
61dd85876b
@ -106,4 +106,6 @@ public interface StoragePool extends Identity, InternalIdentity {
|
||||
Hypervisor.HypervisorType getHypervisor();
|
||||
|
||||
boolean isManaged();
|
||||
|
||||
Long getParent();
|
||||
}
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -58,4 +58,6 @@ public interface PrimaryDataStoreInfo extends StoragePool {
|
||||
Map<String, String> getDetails();
|
||||
|
||||
PrimaryDataStoreLifeCycle getLifeCycle();
|
||||
|
||||
Long getParent();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user