diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java index 9b63043b90c..08e89684ef3 100755 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -41,6 +41,8 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; + import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; @@ -69,7 +71,6 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; @@ -162,6 +163,7 @@ import com.cloud.resource.ResourceManager; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.ScopeType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StoragePool; import com.cloud.storage.Volume; @@ -1826,8 +1828,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) { - s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId()); - throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId()); + List volumes = _volsDao.findCreatedByInstance(vm.getId()); + for (VolumeVO volume : volumes) { + if (!(_storagePoolDao.findById(volume.getPoolId())).getScope().equals(ScopeType.ZONE)) { + s_logger.info("Source and destination host are not in same cluster and all volumes are not on zone wide primary store, unable to migrate to host: " + + dest.getHost().getId()); + throw new CloudRuntimeException( + "Source and destination host are not in same cluster and all volumes are not on zone wide primary store, unable to migrate to host: " + + dest.getHost().getId()); + } + } } VirtualMachineGuru vmGuru = getVmGuru(vm); @@ -3284,9 +3294,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @SuppressWarnings("unchecked") public AgentVmInfo(String name, VMInstanceVO vm, State state, String host) { - name = name; - state = state; - vm = vm; + this.name = name; + this.state = state; + this.vm = vm; hostUuid = host; } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index dd4ce0fc023..f373e8b5daf 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -20,7 +20,6 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; -import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -38,6 +37,9 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; + import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; @@ -507,8 +509,6 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.GetVncPortAnswer; @@ -1171,29 +1171,28 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe List allHosts = null; Map requiresStorageMotion = new HashMap(); DataCenterDeployment plan = null; - boolean zoneWideStoragePool = false; + if (canMigrateWithStorage) { - allHostsPair = searchForServers(startIndex, pageSize, null, hostType, null, srcHost.getDataCenterId(), null, null, null, null, null, null, srcHost.getHypervisorType(), - srcHost.getHypervisorVersion()); + 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 iterator = allHosts.iterator(); iterator.hasNext();) { - Host host = iterator.next(); - Map> volumePools = findSuitablePoolsForVolumes(vmProfile, host); - if (volumePools.isEmpty()) { - iterator.remove(); - } else { - if (srcHost.getHypervisorType() == HypervisorType.VMware || srcHost.getHypervisorType() == HypervisorType.KVM) { - zoneWideStoragePool = checkForZoneWideStoragePool(volumePools); - } - if ((!host.getClusterId().equals(srcHost.getClusterId()) || usesLocal) && !zoneWideStoragePool) { - requiresStorageMotion.put(host, true); + for (VolumeVO volume : volumes) { + Long volClusterId = _poolDao.findById(volume.getPoolId()).getClusterId(); + // only check for volume which are not in zone wide primary store, as only those may require storage motion + if (volClusterId != null) { + for (Iterator iterator = allHosts.iterator(); iterator.hasNext();) { + Host host = iterator.next(); + if (!host.getClusterId().equals(volClusterId) || usesLocal) { + if (hasSuitablePoolsForVolume(volume, host, vmProfile)) { + requiresStorageMotion.put(host, true); + } else { + iterator.remove(); + } + } } } } - plan = new DataCenterDeployment(srcHost.getDataCenterId(), null, null, null, null, null); } else { Long cluster = srcHost.getClusterId(); @@ -1244,50 +1243,20 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return new Ternary, Integer>, List, Map>(otherHosts, suitableHosts, requiresStorageMotion); } - private boolean checkForZoneWideStoragePool(Map> volumePools) { - boolean zoneWideStoragePool = false; - Collection> pools = volumePools.values(); - List aggregatePoolList = new ArrayList(); - for (Iterator> volumePoolsIter = pools.iterator(); volumePoolsIter.hasNext();) { - aggregatePoolList.addAll(volumePoolsIter.next()); - } - for (StoragePool pool : aggregatePoolList) { - if (null == pool.getClusterId()) { - zoneWideStoragePool = true; - break; - } - } - return zoneWideStoragePool; - } + private boolean hasSuitablePoolsForVolume(VolumeVO volume, Host host, VirtualMachineProfile vmProfile) { + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + DiskProfile diskProfile = new DiskProfile(volume, diskOffering, vmProfile.getHypervisorType()); + DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), host.getId(), null, null); + ExcludeList avoid = new ExcludeList(); - private Map> findSuitablePoolsForVolumes(VirtualMachineProfile vmProfile, Host host) { - List volumes = _volumeDao.findCreatedByInstance(vmProfile.getId()); - Map> suitableVolumeStoragePools = new HashMap>(); - - // For each volume find list of suitable storage pools by calling the allocators - for (VolumeVO volume : volumes) { - DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); - DiskProfile diskProfile = new DiskProfile(volume, diskOffering, vmProfile.getHypervisorType()); - DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), host.getId(), null, null); - ExcludeList avoid = new ExcludeList(); - - boolean foundPools = false; - for (StoragePoolAllocator allocator : _storagePoolAllocators) { - List poolList = allocator.allocateToPool(diskProfile, vmProfile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL); - if (poolList != null && !poolList.isEmpty()) { - suitableVolumeStoragePools.put(volume, poolList); - foundPools = true; - break; - } - } - - if (!foundPools) { - suitableVolumeStoragePools.clear(); - break; + for (StoragePoolAllocator allocator : _storagePoolAllocators) { + List poolList = allocator.allocateToPool(diskProfile, vmProfile, plan, avoid, 1); + if (poolList != null && !poolList.isEmpty()) { + return true; } } - return suitableVolumeStoragePools; + return false; } @Override