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) {
InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find the VM with given id");
throw ex;
}
if (vm.getState() != State.Running) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("VM is not running, cannot migrate the vm" + vm);
}
InvalidParameterValueException ex = new InvalidParameterValueException("VM is not Running, cannot " +
"migrate the vm with specified id");
ex.addProxyObject(vm.getUuid(), "vmId");
throw ex;
}
if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && !vm.getHypervisorType().equals(HypervisorType.VMware)
&& !vm.getHypervisorType().equals(HypervisorType.KVM) && !vm.getHypervisorType().equals(HypervisorType.Ovm)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug(vm + " is not XenServer/VMware/KVM/OVM, cannot migrate this VM.");
}
throw new InvalidParameterValueException("Unsupported Hypervisor Type for VM migration, we support " +
"XenServer/VMware/KVM/Ovm only");
}
long srcHostId = vm.getHostId();
Host srcHost = _hostDao.findById(srcHostId);
if (srcHost == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find the host with id: " + srcHostId + " of this VM:" + vm);
}
InvalidParameterValueException ex = new InvalidParameterValueException(
"Unable to find the host (with specified id) of VM with specified id");
ex.addProxyObject(String.valueOf(srcHostId), "hostId");
ex.addProxyObject(vm.getUuid(), "vmId");
throw ex;
}
// Check if the vm can be migrated with storage.
boolean canMigrateWithStorage = false;
if (vm.getType() == VirtualMachine.Type.User) {
HypervisorCapabilitiesVO capabilities = _hypervisorCapabilitiesDao.findByHypervisorTypeAndVersion(
srcHost.getHypervisorType(), srcHost.getHypervisorVersion());
if (capabilities != null) {
canMigrateWithStorage = capabilities.isStorageMotionSupported();
}
}
// Check if the vm is using any disks on local storage.
VirtualMachineProfile<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
List<VolumeVO> volumes = _volumeDao.findCreatedByInstance(vmProfile.getId());
boolean usesLocal = false;
for (VolumeVO volume : volumes) {
DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
DiskProfile diskProfile = new DiskProfile(volume, diskOffering, vmProfile.getHypervisorType());
if (diskProfile.useLocalStorage()) {
usesLocal = true;
break;
}
}
if (!canMigrateWithStorage && usesLocal) {
throw new InvalidParameterValueException("Unsupported operation, VM uses Local storage, cannot migrate");
}
Type hostType = srcHost.getType();
Pair<List<HostVO>, Integer> allHostsPair = null;
List<HostVO> allHosts = null;
Map<Host, Boolean> requiresStorageMotion = new HashMap<Host, Boolean>();
DataCenterDeployment plan = null;
if (canMigrateWithStorage) {
allHostsPair = searchForServers(startIndex, pageSize, null, hostType, null, srcHost.getDataCenterId(), null,
null, null, null, null, null, srcHost.getHypervisorType(), srcHost.getHypervisorVersion());
allHosts = allHostsPair.first();
allHosts.remove(srcHost);
// Check if the host has storage pools for all the volumes of the vm to be migrated.
for (Iterator<HostVO> iterator = allHosts.iterator(); iterator.hasNext();) {
Host host = iterator.next();
Map<Volume, List<StoragePool>> volumePools = findSuitablePoolsForVolumes(vmProfile, host);
if (volumePools.isEmpty()) {
iterator.remove();
} else {
boolean migrationRequired = true;
if (srcHost.getHypervisorType() == HypervisorType.VMware || srcHost.getHypervisorType() == HypervisorType.KVM) {
// Check if each volume required migrating to other pool or not.
migrationRequired = checkIfMigrationRequired(volumePools);
}
if ((!host.getClusterId().equals(srcHost.getClusterId()) || usesLocal) && migrationRequired) {
requiresStorageMotion.put(host, true);
}
}
}
plan = new DataCenterDeployment(srcHost.getDataCenterId(), null, null, null, null, null);
} else {
Long cluster = srcHost.getClusterId();
if (s_logger.isDebugEnabled()) {
s_logger.debug("Searching for all hosts in cluster " + cluster + " for migrating VM " + vm);
}
allHostsPair = searchForServers(startIndex, pageSize, null, hostType, null, null, null, cluster, null, null,
null, null, null, null);
// Filter out the current host.
allHosts = allHostsPair.first();
allHosts.remove(srcHost);
plan = new DataCenterDeployment(srcHost.getDataCenterId(), srcHost.getPodId(), srcHost.getClusterId(),
null, null, null);
}
//'otherHosts' must use the current value of allHosts as allHosts may get modified later in the allocator
List<HostVO> allHostsCpy = new ArrayList<HostVO>(allHosts);
Pair<List<? extends Host>, Integer> otherHosts = new Pair<List <? extends Host>, Integer>(allHostsCpy,
new Integer(allHostsCpy.size()));
List<Host> suitableHosts = new ArrayList<Host>();
ExcludeList excludes = new ExcludeList();
excludes.addHost(srcHostId);
// call affinitygroup chain
long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId());
if (vmGroupCount > 0) {
for (AffinityGroupProcessor processor : _affinityProcessors) {
processor.process(vmProfile, plan, excludes);
}