refactor: migrate vm with storage (#5030)

* refactor: migrate with storage host capability check

Refactors Boolean HypervisorCapabilitiesDao::isStorageMotionSupported to boolean HypervisorCapabilitiesDao::isStorageMotionSupported for simplifying callers.
Refactors log messages.

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* simplify

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* refactor

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* changes

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* review comments addressed

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* var rename

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Abhishek Kumar 2021-07-15 12:57:13 +05:30 committed by GitHub
parent 757bc2d917
commit 50a16979c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 119 additions and 102 deletions

View File

@ -19,7 +19,6 @@ package com.cloud.storage;
import java.math.BigDecimal;
import java.util.List;
import com.cloud.agent.api.ModifyStoragePoolAnswer;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -27,6 +26,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.ModifyStoragePoolAnswer;
import com.cloud.agent.api.StoragePoolInfo;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DiskTO;
@ -252,7 +252,7 @@ public interface StorageManager extends StorageService {
boolean storagePoolCompatibleWithVolumePool(StoragePool pool, Volume volume);
boolean isStoragePoolComplaintWithStoragePolicy(List<Volume> volumes, StoragePool pool) throws StorageUnavailableException;
boolean isStoragePoolCompliantWithStoragePolicy(List<Volume> volumes, StoragePool pool) throws StorageUnavailableException;
boolean registerHostListener(String providerUuid, HypervisorHostListener listener);

View File

@ -38,5 +38,5 @@ public interface HypervisorCapabilitiesDao extends GenericDao<HypervisorCapabili
List<HypervisorType> getHypervisorsWithDefaultEntries();
Boolean isStorageMotionSupported(HypervisorType hypervisorType, String hypervisorVersion);
boolean isStorageMotionSupported(HypervisorType hypervisorType, String hypervisorVersion);
}

View File

@ -121,7 +121,7 @@ public class HypervisorCapabilitiesDaoImpl extends GenericDaoBase<HypervisorCapa
}
@Override
public Boolean isStorageMotionSupported(HypervisorType hypervisorType, String hypervisorVersion) {
public boolean isStorageMotionSupported(HypervisorType hypervisorType, String hypervisorVersion) {
HypervisorCapabilitiesVO hostCapabilities = findByHypervisorTypeAndVersion(hypervisorType, hypervisorVersion);
if (hostCapabilities == null && HypervisorType.KVM.equals(hypervisorType)) {
List<HypervisorCapabilitiesVO> hypervisorCapabilitiesList = listAllByHypervisorType(HypervisorType.KVM);

View File

@ -241,7 +241,7 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
}
try {
boolean isStoragePoolStoragepolicyComplaince = storageMgr.isStoragePoolComplaintWithStoragePolicy(requestVolumes, pool);
boolean isStoragePoolStoragepolicyComplaince = storageMgr.isStoragePoolCompliantWithStoragePolicy(requestVolumes, pool);
if (!isStoragePoolStoragepolicyComplaince) {
return false;
}

View File

@ -1411,7 +1411,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
hostCanAccessPool = true;
if (potentialHost.getHypervisorType() == HypervisorType.VMware) {
try {
boolean isStoragePoolStoragepolicyComplaince = _storageMgr.isStoragePoolComplaintWithStoragePolicy(allVolumes, storagePool);
boolean isStoragePoolStoragepolicyComplaince = _storageMgr.isStoragePoolCompliantWithStoragePolicy(allVolumes, storagePool);
if (!isStoragePoolStoragepolicyComplaince) {
continue;
}
@ -1450,7 +1450,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
if (potentialHost.getHypervisorType() == HypervisorType.VMware) {
try {
boolean isStoragePoolStoragepolicyComplaince = _storageMgr.isStoragePoolComplaintWithStoragePolicy(requestVolumes, potentialSPool);
boolean isStoragePoolStoragepolicyComplaince = _storageMgr.isStoragePoolCompliantWithStoragePolicy(requestVolumes, potentialSPool);
if (!isStoragePoolStoragepolicyComplaince) {
continue;
}

View File

@ -1291,7 +1291,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
boolean canMigrateWithStorage = false;
if (VirtualMachine.Type.User.equals(vm.getType()) || HypervisorType.VMware.equals(vm.getHypervisorType())) {
canMigrateWithStorage = Boolean.TRUE.equals(_hypervisorCapabilitiesDao.isStorageMotionSupported(srcHost.getHypervisorType(), srcHostVersion));
canMigrateWithStorage = _hypervisorCapabilitiesDao.isStorageMotionSupported(srcHost.getHypervisorType(), srcHostVersion);
}
// Check if the vm is using any disks on local storage.
@ -1345,11 +1345,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
// source volume.
iterator.remove();
} else {
boolean hostSupportsStorageMigration = false;
if ((srcHostVersion != null && srcHostVersion.equals(hostVersion)) ||
Boolean.TRUE.equals(_hypervisorCapabilitiesDao.isStorageMotionSupported(host.getHypervisorType(), hostVersion))) {
hostSupportsStorageMigration = true;
}
boolean hostSupportsStorageMigration = (srcHostVersion != null && srcHostVersion.equals(hostVersion)) ||
_hypervisorCapabilitiesDao.isStorageMotionSupported(host.getHypervisorType(), hostVersion);
if (hostSupportsStorageMigration && hasSuitablePoolsForVolume(volume, host, vmProfile)) {
requiresStorageMotion.put(host, true);
} else {

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.storage;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
@ -29,11 +31,11 @@ import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.LinkedHashSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@ -41,11 +43,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.dc.VsphereStoragePolicyVO;
import com.cloud.dc.dao.VsphereStoragePolicyDao;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.utils.StringUtils;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd;
@ -53,8 +50,8 @@ import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.SyncStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@ -121,12 +118,13 @@ import com.cloud.agent.api.GetStorageStatsAnswer;
import com.cloud.agent.api.GetStorageStatsCommand;
import com.cloud.agent.api.GetVolumeStatsAnswer;
import com.cloud.agent.api.GetVolumeStatsCommand;
import com.cloud.agent.api.ModifyStoragePoolAnswer;
import com.cloud.agent.api.ModifyStoragePoolCommand;
import com.cloud.agent.api.StoragePoolInfo;
import com.cloud.agent.api.VolumeStatsEntry;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.ModifyStoragePoolCommand;
import com.cloud.agent.api.ModifyStoragePoolAnswer;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.manager.Commands;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.dao.TemplateJoinDao;
@ -143,8 +141,10 @@ import com.cloud.configuration.ConfigurationManagerImpl;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.VsphereStoragePolicyVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VsphereStoragePolicyDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.exception.AgentUnavailableException;
@ -172,6 +172,7 @@ import com.cloud.org.Grouping.AllocationState;
import com.cloud.resource.ResourceState;
import com.cloud.server.ConfigurationServer;
import com.cloud.server.ManagementServer;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume.Type;
@ -195,6 +196,7 @@ import com.cloud.user.dao.UserDao;
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.UriUtils;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.ManagerBase;
@ -218,8 +220,6 @@ import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.VMInstanceDao;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
@Component
public class StorageManagerImpl extends ManagerBase implements StorageManager, ClusterManagerListener, Configurable {
private static final Logger s_logger = Logger.getLogger(StorageManagerImpl.class);
@ -2392,8 +2392,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
}
@Override
public boolean isStoragePoolComplaintWithStoragePolicy(List<Volume> volumes, StoragePool pool) throws StorageUnavailableException {
if (volumes == null || volumes.isEmpty()) {
public boolean isStoragePoolCompliantWithStoragePolicy(List<Volume> volumes, StoragePool pool) throws StorageUnavailableException {
if (CollectionUtils.isEmpty(volumes)) {
return false;
}
List<Pair<Volume, Answer>> answers = new ArrayList<Pair<Volume, Answer>>();

View File

@ -2441,7 +2441,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
HypervisorType hypervisorType = _volsDao.getHypervisorType(volumeId);
if (hypervisorType.equals(HypervisorType.VMware)) {
try {
boolean isStoragePoolStoragepolicyComplaince = storageMgr.isStoragePoolComplaintWithStoragePolicy(Arrays.asList(vol), destPool);
boolean isStoragePoolStoragepolicyComplaince = storageMgr.isStoragePoolCompliantWithStoragePolicy(Arrays.asList(vol), destPool);
if (!isStoragePoolStoragepolicyComplaince) {
throw new CloudRuntimeException(String.format("Storage pool %s is not storage policy compliance with the volume %s", poolUuid, vol.getUuid()));
}

View File

@ -582,6 +582,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
private static final ConfigKey<Boolean> VmDestroyForcestop = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.destroy.forcestop", "false",
"On destroy, force-stop takes this value ", true);
public static final List<HypervisorType> VM_STORAGE_MIGRATION_SUPPORTING_HYPERVISORS = new ArrayList<>(Arrays.asList(
HypervisorType.KVM,
HypervisorType.VMware,
HypervisorType.XenServer,
HypervisorType.Simulator
));
@Override
public UserVmVO getVirtualMachine(long vmId) {
return _vmDao.findById(vmId);
@ -6266,56 +6273,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return true;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true)
public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, Map<String, String> volumeToPool) throws ResourceUnavailableException,
ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException {
// Access check - only root administrator can migrate VM.
Account caller = CallContext.current().getCallingAccount();
if (!_accountMgr.isRootAdmin(caller.getId())) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Caller is not a root admin, permission denied to migrate the VM");
}
throw new PermissionDeniedException("No permission to migrate VM, Only Root Admin can migrate a VM!");
}
VMInstanceVO vm = _vmInstanceDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("Unable to find the vm by id " + vmId);
}
// OfflineVmwareMigration: this would be it ;) if multiple paths exist: unify
if (vm.getState() != State.Running) {
// OfflineVmwareMigration: and not vmware
if (s_logger.isDebugEnabled()) {
s_logger.debug("VM is not Running, unable to migrate the vm " + vm);
}
CloudRuntimeException ex = new CloudRuntimeException("VM is not Running, unable to migrate the vm with" + " specified id");
ex.addProxyObject(vm.getUuid(), "vmId");
throw ex;
}
if(serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
}
// OfflineVmwareMigration: this condition is to complicated. (already a method somewhere)
if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && !vm.getHypervisorType().equals(HypervisorType.VMware) && !vm.getHypervisorType().equals(HypervisorType.KVM)
&& !vm.getHypervisorType().equals(HypervisorType.Ovm) && !vm.getHypervisorType().equals(HypervisorType.Hyperv)
&& !vm.getHypervisorType().equals(HypervisorType.Simulator)) {
throw new InvalidParameterValueException("Unsupported hypervisor type for vm migration, we support" + " XenServer/VMware/KVM only");
}
private Pair<Host, Host> getHostsForMigrateVmWithStorage(VMInstanceVO vm, Host destinationHost) throws VirtualMachineMigrationException {
long srcHostId = vm.getHostId();
Host srcHost = _resourceMgr.getHost(srcHostId);
if (srcHost == null) {
throw new InvalidParameterValueException("Cannot migrate VM, host with id: " + srcHostId + " for VM not found");
throw new InvalidParameterValueException("Cannot migrate VM, host with ID: " + srcHostId + " for VM not found");
}
// Check if source and destination hosts are valid and migrating to same host
if (destinationHost.getId() == srcHostId) {
throw new InvalidParameterValueException("Cannot migrate VM, VM is already present on this host, please" + " specify valid destination host to migrate the VM");
throw new InvalidParameterValueException(String.format("Cannot migrate VM as it is already present on host %s (ID: %s), please specify valid destination host to migrate the VM",
destinationHost.getName(), destinationHost.getUuid()));
}
String srcHostVersion = srcHost.getHypervisorVersion();
@ -6345,39 +6314,45 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
}
if (!Boolean.TRUE.equals(_hypervisorCapabilitiesDao.isStorageMotionSupported(srcHost.getHypervisorType(), srcHostVersion))) {
throw new CloudRuntimeException("Migration with storage isn't supported for source host ID: " + srcHost.getUuid() + " on hypervisor " + srcHost.getHypervisorType() + " of version " + srcHost.getHypervisorVersion());
if (!_hypervisorCapabilitiesDao.isStorageMotionSupported(srcHost.getHypervisorType(), srcHostVersion)) {
throw new CloudRuntimeException(String.format("Migration with storage isn't supported for source host %s (ID: %s) on hypervisor %s with version %s", srcHost.getName(), srcHost.getUuid(), srcHost.getHypervisorType(), srcHost.getHypervisorVersion()));
}
if (srcHostVersion == null || !srcHostVersion.equals(destHostVersion)) {
if (!Boolean.TRUE.equals(_hypervisorCapabilitiesDao.isStorageMotionSupported(destinationHost.getHypervisorType(), destHostVersion))) {
throw new CloudRuntimeException("Migration with storage isn't supported for target host ID: " + srcHost.getUuid() + " on hypervisor " + srcHost.getHypervisorType() + " of version " + srcHost.getHypervisorVersion());
if (!_hypervisorCapabilitiesDao.isStorageMotionSupported(destinationHost.getHypervisorType(), destHostVersion)) {
throw new CloudRuntimeException(String.format("Migration with storage isn't supported for target host %s (ID: %s) on hypervisor %s with version %s", destinationHost.getName(), destinationHost.getUuid(), destinationHost.getHypervisorType(), destinationHost.getHypervisorVersion()));
}
}
// Check if destination host is up.
if (destinationHost.getState() != com.cloud.host.Status.Up || destinationHost.getResourceState() != ResourceState.Enabled) {
throw new CloudRuntimeException("Cannot migrate VM, destination host is not in correct state, has " + "status: " + destinationHost.getState() + ", state: "
+ destinationHost.getResourceState());
throw new CloudRuntimeException(String.format("Cannot migrate VM, destination host %s (ID: %s) is not in correct state, has status: %s, state: %s",
destinationHost.getName(), destinationHost.getUuid(), destinationHost.getState(), destinationHost.getResourceState()));
}
// Check that Vm does not have VM Snapshots
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
throw new InvalidParameterValueException("VM with VM Snapshots cannot be migrated with storage, please remove all VM snapshots");
// Check max guest vm limit for the destinationHost.
if (_capacityMgr.checkIfHostReachMaxGuestLimit(destinationHost)) {
throw new VirtualMachineMigrationException(String.format("Cannot migrate VM as destination host %s (ID: %s) already has max running vms (count includes system VMs)",
destinationHost.getName(), destinationHost.getUuid()));
}
return new Pair<>(srcHost, destinationHost);
}
private List<VolumeVO> getVmVolumesForMigrateVmWithStorage(VMInstanceVO vm) {
List<VolumeVO> vmVolumes = _volsDao.findUsableVolumesForInstance(vm.getId());
Map<Long, Long> volToPoolObjectMap = new HashMap<Long, Long>();
if (!isVMUsingLocalStorage(vm) && MapUtils.isEmpty(volumeToPool)
&& (destinationHost.getClusterId().equals(srcHost.getClusterId()) || isVmVolumesOnZoneWideStore(vm))){
// If volumes do not have to be migrated
// call migrateVirtualMachine for non-user VMs else throw exception
if (!VirtualMachine.Type.User.equals(vm.getType())) {
return migrateVirtualMachine(vmId, destinationHost);
for (VolumeVO volume : vmVolumes) {
if (volume.getState() != Volume.State.Ready) {
throw new CloudRuntimeException(String.format("Volume %s (ID: %s) of the VM is not in Ready state. Cannot migrate the VM %s (ID: %s) with its volumes", volume.getName(), volume.getUuid(), vm.getInstanceName(), vm.getUuid()));
}
throw new InvalidParameterValueException("Migration of the vm " + vm + "from host " + srcHost + " to destination host " + destinationHost
+ " doesn't involve migrating the volumes.");
}
return vmVolumes;
}
private Map<Long, Long> getVolumePoolMappingForMigrateVmWithStorage(VMInstanceVO vm, Map<String, String> volumeToPool) {
Map<Long, Long> volToPoolObjectMap = new HashMap<Long, Long>();
List<VolumeVO> vmVolumes = getVmVolumesForMigrateVmWithStorage(vm);
if (MapUtils.isNotEmpty(volumeToPool)) {
// Check if all the volumes and pools passed as parameters are valid.
@ -6394,15 +6369,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} else {
// Verify the volume given belongs to the vm.
if (!vmVolumes.contains(volume)) {
throw new InvalidParameterValueException("There volume " + volume + " doesn't belong to " + "the virtual machine " + vm + " that has to be migrated");
throw new InvalidParameterValueException(String.format("Volume " + volume + " doesn't belong to the VM %s (ID: %s) that has to be migrated", vm.getInstanceName(), vm.getUuid()));
}
volToPoolObjectMap.put(Long.valueOf(volume.getId()), Long.valueOf(pool.getId()));
volToPoolObjectMap.put(volume.getId(), pool.getId());
}
HypervisorType hypervisorType = _volsDao.getHypervisorType(volume.getId());
if (hypervisorType.equals(HypervisorType.VMware)) {
try {
boolean isStoragePoolStoragepolicyComplaince = storageManager.isStoragePoolComplaintWithStoragePolicy(Arrays.asList(volume), pool);
if (!isStoragePoolStoragepolicyComplaince) {
boolean isStoragePoolStoragepolicyCompliance = storageManager.isStoragePoolCompliantWithStoragePolicy(Arrays.asList(volume), pool);
if (!isStoragePoolStoragepolicyCompliance) {
throw new CloudRuntimeException(String.format("Storage pool %s is not storage policy compliance with the volume %s", pool.getUuid(), volume.getUuid()));
}
} catch (StorageUnavailableException e) {
@ -6411,24 +6386,69 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
}
}
return volToPoolObjectMap;
}
// Check if all the volumes are in the correct state.
for (VolumeVO volume : vmVolumes) {
if (volume.getState() != Volume.State.Ready) {
throw new CloudRuntimeException("Volume " + volume + " of the VM is not in Ready state. Cannot " + "migrate the vm with its volumes.");
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true)
public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, Map<String, String> volumeToPool) throws ResourceUnavailableException,
ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException {
// Access check - only root administrator can migrate VM.
Account caller = CallContext.current().getCallingAccount();
if (!_accountMgr.isRootAdmin(caller.getId())) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Caller is not a root admin, permission denied to migrate the VM");
}
throw new PermissionDeniedException("No permission to migrate VM, Only Root Admin can migrate a VM!");
}
// Check max guest vm limit for the destinationHost.
HostVO destinationHostVO = _hostDao.findById(destinationHost.getId());
if (_capacityMgr.checkIfHostReachMaxGuestLimit(destinationHostVO)) {
throw new VirtualMachineMigrationException("Host name: " + destinationHost.getName() + ", hostId: " + destinationHost.getId()
+ " already has max running vms (count includes system VMs). Cannot" + " migrate to this host");
VMInstanceVO vm = _vmInstanceDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("Unable to find the VM by ID " + vmId);
}
checkHostsDedication(vm, srcHostId, destinationHost.getId());
// OfflineVmwareMigration: this would be it ;) if multiple paths exist: unify
if (vm.getState() != State.Running) {
// OfflineVmwareMigration: and not vmware
if (s_logger.isDebugEnabled()) {
s_logger.debug("VM is not Running, unable to migrate the vm " + vm);
}
CloudRuntimeException ex = new CloudRuntimeException(String.format("Unable to migrate the VM %s (ID: %s) as it is not in Running state", vm.getInstanceName(), vm.getUuid()));
ex.addProxyObject(vm.getUuid(), "vmId");
throw ex;
}
_itMgr.migrateWithStorage(vm.getUuid(), srcHostId, destinationHost.getId(), volToPoolObjectMap);
if(serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
}
if (VM_STORAGE_MIGRATION_SUPPORTING_HYPERVISORS.contains(vm.getHypervisorType())) {
throw new InvalidParameterValueException(String.format("Unsupported hypervisor: %s for VM migration, we support XenServer/VMware/KVM only", vm.getHypervisorType()));
}
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
throw new InvalidParameterValueException("VM with VM Snapshots cannot be migrated with storage, please remove all VM snapshots");
}
Pair<Host, Host> sourceDestinationHosts = getHostsForMigrateVmWithStorage(vm, destinationHost);
Host srcHost = sourceDestinationHosts.first();
if (!isVMUsingLocalStorage(vm) && MapUtils.isEmpty(volumeToPool)
&& (destinationHost.getClusterId().equals(srcHost.getClusterId()) || isVmVolumesOnZoneWideStore(vm))){
// If volumes do not have to be migrated
// call migrateVirtualMachine for non-user VMs else throw exception
if (!VirtualMachine.Type.User.equals(vm.getType())) {
return migrateVirtualMachine(vmId, destinationHost);
}
throw new InvalidParameterValueException(String.format("Migration of the VM: %s (ID: %s) from host %s (ID: %s) to destination host %s (ID: %s) doesn't involve migrating the volumes",
vm.getInstanceName(), vm.getUuid(), srcHost.getName(), srcHost.getUuid(), destinationHost.getName(), destinationHost.getUuid()));
}
Map<Long, Long> volToPoolObjectMap = getVolumePoolMappingForMigrateVmWithStorage(vm, volumeToPool);
checkHostsDedication(vm, srcHost.getId(), destinationHost.getId());
_itMgr.migrateWithStorage(vm.getUuid(), srcHost.getId(), destinationHost.getId(), volToPoolObjectMap);
return findMigratedVm(vm.getId(), vm.getType());
}