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();
|
Hypervisor.HypervisorType getHypervisor();
|
||||||
|
|
||||||
boolean isManaged();
|
boolean isManaged();
|
||||||
|
|
||||||
|
Long getParent();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -58,4 +58,6 @@ public interface PrimaryDataStoreInfo extends StoragePool {
|
|||||||
Map<String, String> getDetails();
|
Map<String, String> getDetails();
|
||||||
|
|
||||||
PrimaryDataStoreLifeCycle getLifeCycle();
|
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);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user