2626import java .util .Date ;
2727import java .util .HashMap ;
2828import java .util .HashSet ;
29+ import java .util .Iterator ;
2930import java .util .LinkedHashMap ;
3031import java .util .List ;
3132import java .util .Map ;
@@ -1964,24 +1965,26 @@ protected void migrate(VMInstanceVO vm, long srcHostId, DeployDestination dest)
19641965 }
19651966 }
19661967
1967- private Map <Volume , StoragePool > getPoolListForVolumesForMigration (VirtualMachineProfile profile , Host host , Map <Volume , StoragePool > volumeToPool ) {
1968+ private Map <Volume , StoragePool > getPoolListForVolumesForMigration (VirtualMachineProfile profile , Host host , Map <Long , Long > volumeToPool ) {
19681969 List <VolumeVO > allVolumes = _volsDao .findUsableVolumesForInstance (profile .getId ());
1970+ Map <Volume , StoragePool > volumeToPoolObjectMap = new HashMap <Volume , StoragePool > ();
19691971 for (VolumeVO volume : allVolumes ) {
1970- StoragePool pool = volumeToPool .get (volume );
1971- DiskOfferingVO diskOffering = _diskOfferingDao .findById (volume . getDiskOfferingId () );
1972+ Long poolId = volumeToPool .get (Long . valueOf ( volume . getId ()) );
1973+ StoragePoolVO pool = _storagePoolDao .findById (poolId );
19721974 StoragePoolVO currentPool = _storagePoolDao .findById (volume .getPoolId ());
1975+ DiskOfferingVO diskOffering = _diskOfferingDao .findById (volume .getDiskOfferingId ());
19731976 if (pool != null ) {
19741977 // Check if pool is accessible from the destination host and disk offering with which the volume was
19751978 // created is compliant with the pool type.
19761979 if (_poolHostDao .findByPoolHost (pool .getId (), host .getId ()) == null || pool .isLocal () != diskOffering .getUseLocalStorage ()) {
19771980 // Cannot find a pool for the volume. Throw an exception.
19781981 throw new CloudRuntimeException ("Cannot migrate volume " + volume + " to storage pool " + pool + " while migrating vm to host " + host +
1979- ". Either the pool is not accessible from the " + " host or because of the offering with which the volume is created it cannot be placed on " +
1982+ ". Either the pool is not accessible from the host or because of the offering with which the volume is created it cannot be placed on " +
19801983 "the given pool." );
19811984 } else if (pool .getId () == currentPool .getId ()) {
1982- // If the pool to migrate too is the same as current pool, remove the volume from the list of
1983- // volumes to be migrated.
1984- volumeToPool . remove (volume );
1985+ // If the pool to migrate too is the same as current pool, the volume doesn't need to be migrated.
1986+ } else {
1987+ volumeToPoolObjectMap . put (volume , pool );
19851988 }
19861989 } else {
19871990 // Find a suitable pool for the volume. Call the storage pool allocator to find the list of pools.
@@ -1990,31 +1993,41 @@ private Map<Volume, StoragePool> getPoolListForVolumesForMigration(VirtualMachin
19901993 ExcludeList avoid = new ExcludeList ();
19911994 boolean currentPoolAvailable = false ;
19921995
1996+ List <StoragePool > poolList = new ArrayList <StoragePool >();
19931997 for (StoragePoolAllocator allocator : _storagePoolAllocators ) {
1994- List <StoragePool > poolList = allocator .allocateToPool (diskProfile , profile , plan , avoid , StoragePoolAllocator .RETURN_UPTO_ALL );
1995- if (poolList != null && !poolList .isEmpty ()) {
1996- // Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the
1997- // volume to a pool only if it is required; that is the current pool on which the volume resides
1998- // is not available on the destination host.
1999- if (poolList .contains (currentPool )) {
1998+ List <StoragePool > poolListFromAllocator = allocator .allocateToPool (diskProfile , profile , plan , avoid , StoragePoolAllocator .RETURN_UPTO_ALL );
1999+ if (poolListFromAllocator != null && !poolListFromAllocator .isEmpty ()) {
2000+ poolList .addAll (poolListFromAllocator );
2001+ }
2002+ }
2003+
2004+ if (poolList != null && !poolList .isEmpty ()) {
2005+ // Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the
2006+ // volume to a pool only if it is required; that is the current pool on which the volume resides
2007+ // is not available on the destination host.
2008+ Iterator <StoragePool > iter = poolList .iterator ();
2009+ while (iter .hasNext ()) {
2010+ if (currentPool .getId () == iter .next ().getId ()) {
20002011 currentPoolAvailable = true ;
2001- } else {
2002- volumeToPool .put (volume , _storagePoolDao .findByUuid (poolList .get (0 ).getUuid ()));
2012+ break ;
20032013 }
2014+ }
20042015
2005- break ;
2016+ if (!currentPoolAvailable ) {
2017+ volumeToPoolObjectMap .put (volume , _storagePoolDao .findByUuid (poolList .get (0 ).getUuid ()));
20062018 }
20072019 }
20082020
2009- if (!currentPoolAvailable && !volumeToPool .containsKey (volume )) {
2021+
2022+ if (!currentPoolAvailable && !volumeToPoolObjectMap .containsKey (volume )) {
20102023 // Cannot find a pool for the volume. Throw an exception.
20112024 throw new CloudRuntimeException ("Cannot find a storage pool which is available for volume " + volume + " while migrating virtual machine " +
20122025 profile .getVirtualMachine () + " to host " + host );
20132026 }
20142027 }
20152028 }
20162029
2017- return volumeToPool ;
2030+ return volumeToPoolObjectMap ;
20182031 }
20192032
20202033 private <T extends VMInstanceVO > void moveVmToMigratingState (T vm , Long hostId , ItWorkVO work ) throws ConcurrentOperationException {
@@ -2044,7 +2057,7 @@ private <T extends VMInstanceVO> void moveVmOutofMigratingStateOnSuccess(T vm, L
20442057 }
20452058
20462059 @ Override
2047- public void migrateWithStorage (String vmUuid , long srcHostId , long destHostId , Map <Volume , StoragePool > volumeToPool )
2060+ public void migrateWithStorage (String vmUuid , long srcHostId , long destHostId , Map <Long , Long > volumeToPool )
20482061 throws ResourceUnavailableException , ConcurrentOperationException {
20492062
20502063 AsyncJobExecutionContext jobContext = AsyncJobExecutionContext .getCurrentExecutionContext ();
@@ -2088,7 +2101,7 @@ else if (jobException instanceof Throwable)
20882101 }
20892102 }
20902103
2091- private void orchestrateMigrateWithStorage (String vmUuid , long srcHostId , long destHostId , Map <Volume , StoragePool > volumeToPool ) throws ResourceUnavailableException ,
2104+ private void orchestrateMigrateWithStorage (String vmUuid , long srcHostId , long destHostId , Map <Long , Long > volumeToPool ) throws ResourceUnavailableException ,
20922105 ConcurrentOperationException {
20932106
20942107 VMInstanceVO vm = _vmDao .findByUuid (vmUuid );
@@ -2104,11 +2117,11 @@ private void orchestrateMigrateWithStorage(String vmUuid, long srcHostId, long d
21042117
21052118 // Create a map of which volume should go in which storage pool.
21062119 VirtualMachineProfile profile = new VirtualMachineProfileImpl (vm );
2107- volumeToPool = getPoolListForVolumesForMigration (profile , destHost , volumeToPool );
2120+ Map < Volume , StoragePool > volumeToPoolMap = getPoolListForVolumesForMigration (profile , destHost , volumeToPool );
21082121
21092122 // If none of the volumes have to be migrated, fail the call. Administrator needs to make a call for migrating
21102123 // a vm and not migrating a vm with storage.
2111- if (volumeToPool .isEmpty ()) {
2124+ if (volumeToPoolMap == null || volumeToPoolMap .isEmpty ()) {
21122125 throw new InvalidParameterValueException ("Migration of the vm " + vm + "from host " + srcHost + " to destination host " + destHost +
21132126 " doesn't involve migrating the volumes." );
21142127 }
@@ -2138,7 +2151,7 @@ private void orchestrateMigrateWithStorage(String vmUuid, long srcHostId, long d
21382151 boolean migrated = false ;
21392152 try {
21402153 // Migrate the vm and its volume.
2141- volumeMgr .migrateVolumes (vm , to , srcHost , destHost , volumeToPool );
2154+ volumeMgr .migrateVolumes (vm , to , srcHost , destHost , volumeToPoolMap );
21422155
21432156 // Put the vm back to running state.
21442157 moveVmOutofMigratingStateOnSuccess (vm , destHost .getId (), work );
@@ -4768,7 +4781,7 @@ public Object[] doInTransaction(TransactionStatus status) {
47684781
47694782 public Outcome <VirtualMachine > migrateVmWithStorageThroughJobQueue (
47704783 final String vmUuid , final long srcHostId , final long destHostId ,
4771- final Map <Volume , StoragePool > volumeToPool ) {
4784+ final Map <Long , Long > volumeToPool ) {
47724785
47734786 final CallContext context = CallContext .current ();
47744787 final User user = context .getCallingUser ();
0 commit comments