You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ra...@apache.org on 2018/09/10 23:09:37 UTC

[cloudstack] branch master updated: Add managed storage pool constraints to MigrateWithVolume API method (#2761)

This is an automated email from the ASF dual-hosted git repository.

rafael pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new f550d70  Add managed storage pool constraints to MigrateWithVolume API method (#2761)
f550d70 is described below

commit f550d703053fb3ccf9df739cee31ab823d132f3a
Author: Rafael Weingärtner <ra...@gmail.com>
AuthorDate: Mon Sep 10 20:09:26 2018 -0300

    Add managed storage pool constraints to MigrateWithVolume API method (#2761)
    
    * Add managed storage pool constraints to MigrateWithVolume API method
    
    * Apply mike's suggestions
    
    * Apply Mike's suggestion in a second review
    
    * Mike's suggestions
    
    * Confused bit
    
    * just executeManagedStorageChecks
    
    * Created methods `executeManagedStorageChecksWhenTargetStoragePoolNotProvided` and `executeManagedStorageChecksWhenTargetStoragePoolProvided`
    
    * improve "executeManagedStorageChecksWhenTargetStoragePoolNotProvided"
    
    * Fix "findVolumesThatWereNotMappedByTheUser" method
    
    * Applu Mike's suggestion to improve "createMappingVolumeAndStoragePool" method
    
    * Unit tests to cover modified code
---
 .../com/cloud/vm/VirtualMachineManagerImpl.java    | 154 ++++---
 .../cloud/vm/VirtualMachineManagerImplTest.java    | 441 ++++++++++++++++++++-
 2 files changed, 539 insertions(+), 56 deletions(-)

diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
index f69d6fe..3e11a2f 100755
--- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -2286,31 +2286,52 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     /**
-     * Create the mapping of volumes and storage pools. If the user did not enter a mapping on her/his own, we create one using {@link #getDefaultMappingOfVolumesAndStoragePoolForMigration(VirtualMachineProfile, Host)}.
-     * If the user provided a mapping, we use whatever the user has provided (check the method {@link #createMappingVolumeAndStoragePoolEnteredByUser(VirtualMachineProfile, Host, Map)}).
+     * We create the mapping of volumes and storage pool to migrate the VMs according to the information sent by the user.
+     * If the user did not enter a complete mapping, the volumes that were left behind will be auto mapped using {@link #createStoragePoolMappingsForVolumes(VirtualMachineProfile, Host, Map, List)}
      */
-    private Map<Volume, StoragePool> getPoolListForVolumesForMigration(VirtualMachineProfile profile, Host targetHost, Map<Long, Long> volumeToPool) {
-        if (MapUtils.isEmpty(volumeToPool)) {
-            return getDefaultMappingOfVolumesAndStoragePoolForMigration(profile, targetHost);
-        }
+    protected Map<Volume, StoragePool> createMappingVolumeAndStoragePool(VirtualMachineProfile profile, Host targetHost, Map<Long, Long> userDefinedMapOfVolumesAndStoragePools) {
+        Map<Volume, StoragePool> volumeToPoolObjectMap = buildMapUsingUserInformation(profile, targetHost, userDefinedMapOfVolumesAndStoragePools);
 
-        return createMappingVolumeAndStoragePoolEnteredByUser(profile, targetHost, volumeToPool);
+        List<Volume> volumesNotMapped = findVolumesThatWereNotMappedByTheUser(profile, volumeToPoolObjectMap);
+        createStoragePoolMappingsForVolumes(profile, targetHost, volumeToPoolObjectMap, volumesNotMapped);
+        return volumeToPoolObjectMap;
     }
 
     /**
-     * We create the mapping of volumes and storage pool to migrate the VMs according to the information sent by the user.
+     *  Given the map of volume to target storage pool entered by the user, we check for other volumes that the VM might have and were not configured.
+     *  This map can be then used by CloudStack to find new target storage pools according to the target host.
      */
-    private Map<Volume, StoragePool> createMappingVolumeAndStoragePoolEnteredByUser(VirtualMachineProfile profile, Host host, Map<Long, Long> volumeToPool) {
-        Map<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<Volume, StoragePool>();
-        for(Long volumeId: volumeToPool.keySet()) {
+    protected List<Volume> findVolumesThatWereNotMappedByTheUser(VirtualMachineProfile profile, Map<Volume, StoragePool> volumeToStoragePoolObjectMap) {
+        List<VolumeVO> allVolumes = _volsDao.findUsableVolumesForInstance(profile.getId());
+        List<Volume> volumesNotMapped = new ArrayList<>();
+        for (Volume volume : allVolumes) {
+            if (!volumeToStoragePoolObjectMap.containsKey(volume)) {
+                volumesNotMapped.add(volume);
+            }
+        }
+        return volumesNotMapped;
+    }
+
+    /**
+     *  Builds the map of storage pools and volumes with the information entered by the user. Before creating the an entry we validate if the migration is feasible checking if the migration is allowed and if the target host can access the defined target storage pool.
+     */
+    protected Map<Volume, StoragePool> buildMapUsingUserInformation(VirtualMachineProfile profile, Host targetHost, Map<Long, Long> userDefinedVolumeToStoragePoolMap) {
+        Map<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<>();
+        if (MapUtils.isEmpty(userDefinedVolumeToStoragePoolMap)) {
+            return volumeToPoolObjectMap;
+        }
+        for(Long volumeId: userDefinedVolumeToStoragePoolMap.keySet()) {
             VolumeVO volume = _volsDao.findById(volumeId);
 
-            Long poolId = volumeToPool.get(volumeId);
+            Long poolId = userDefinedVolumeToStoragePoolMap.get(volumeId);
             StoragePoolVO targetPool = _storagePoolDao.findById(poolId);
             StoragePoolVO currentPool = _storagePoolDao.findById(volume.getPoolId());
 
-            if (_poolHostDao.findByPoolHost(targetPool.getId(), host.getId()) == null) {
-                throw new CloudRuntimeException(String.format("Cannot migrate the volume [%s] to the storage pool [%s] while migrating VM [%s] to target host [%s]. The host does not have access to the storage pool entered.", volume.getUuid(), targetPool.getUuid(), profile.getUuid(), host.getUuid()));
+            executeManagedStorageChecksWhenTargetStoragePoolProvided(currentPool, volume, targetPool);
+            if (_poolHostDao.findByPoolHost(targetPool.getId(), targetHost.getId()) == null) {
+                throw new CloudRuntimeException(
+                        String.format("Cannot migrate the volume [%s] to the storage pool [%s] while migrating VM [%s] to target host [%s]. The host does not have access to the storage pool entered.",
+                                volume.getUuid(), targetPool.getUuid(), profile.getUuid(), targetHost.getUuid()));
             }
             if (currentPool.getId() == targetPool.getId()) {
                 s_logger.info(String.format("The volume [%s] is already allocated in storage pool [%s].", volume.getUuid(), targetPool.getUuid()));
@@ -2321,60 +2342,99 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     /**
-     * We create the default mapping of volumes and storage pools for the migration of the VM to the target host.
-     * If the current storage pool of one of the volumes is using local storage in the host, it then needs to be migrated to a local storage in the target host.
-     * Otherwise, we do not need to migrate, and the volume can be kept in its current storage pool.
+     *  Executes the managed storage checks for the mapping<volume, storage pool> entered by the user. The checks execute by this method are the following.
+     *  <ul>
+     *      <li> If the current storage pool of the volume is not a managed storage, we do not need to validate anything here.
+     *      <li> If the current storage pool is a managed storage and the target storage pool ID is different from the current one, we throw an exception.
+     *  </ul>
      */
-    private Map<Volume, StoragePool> getDefaultMappingOfVolumesAndStoragePoolForMigration(VirtualMachineProfile profile, Host targetHost) {
-        Map<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<Volume, StoragePool>();
-        List<VolumeVO> allVolumes = _volsDao.findUsableVolumesForInstance(profile.getId());
-        for (VolumeVO volume : allVolumes) {
+    protected void executeManagedStorageChecksWhenTargetStoragePoolProvided(StoragePoolVO currentPool, VolumeVO volume, StoragePoolVO targetPool) {
+        if (!currentPool.isManaged()) {
+            return;
+        }
+        if (currentPool.getId() == targetPool.getId()) {
+            return;
+        }
+        throw new CloudRuntimeException(String.format("Currently, a volume on managed storage can only be 'migrated' to itself " + "[volumeId=%s, currentStoragePoolId=%s, targetStoragePoolId=%s].",
+                volume.getUuid(), currentPool.getUuid(), targetPool.getUuid()));
+    }
+
+    /**
+     * For each one of the volumes we will map it to a storage pool that is available via the target host.
+     * An exception is thrown if we cannot find a storage pool that is accessible in the target host to migrate the volume to.
+     */
+    protected void createStoragePoolMappingsForVolumes(VirtualMachineProfile profile, Host targetHost, Map<Volume, StoragePool> volumeToPoolObjectMap, List<Volume> allVolumes) {
+        for (Volume volume : allVolumes) {
             StoragePoolVO currentPool = _storagePoolDao.findById(volume.getPoolId());
-            if (ScopeType.HOST.equals(currentPool.getScope())) {
-                createVolumeToStoragePoolMappingIfNeeded(profile, targetHost, volumeToPoolObjectMap, volume, currentPool);
+
+            executeManagedStorageChecksWhenTargetStoragePoolNotProvided(targetHost, currentPool, volume);
+            if (ScopeType.HOST.equals(currentPool.getScope()) || isStorageCrossClusterMigration(targetHost, currentPool)) {
+                createVolumeToStoragePoolMappingIfPossible(profile, targetHost, volumeToPoolObjectMap, volume, currentPool);
             } else {
                 volumeToPoolObjectMap.put(volume, currentPool);
             }
         }
-        return volumeToPoolObjectMap;
+    }
+
+    /**
+     *  Executes the managed storage checks for the volumes that the user has not entered a mapping of <volume, storage pool>. The following checks are performed.
+     *   <ul>
+     *      <li> If the current storage pool is not a managed storage, we do not need to proceed with this method;
+     *      <li> We check if the target host has access to the current managed storage pool. If it does not have an exception will be thrown.
+     *   </ul>
+     */
+    protected void executeManagedStorageChecksWhenTargetStoragePoolNotProvided(Host targetHost, StoragePoolVO currentPool, Volume volume) {
+        if (!currentPool.isManaged()) {
+            return;
+        }
+        if (_poolHostDao.findByPoolHost(currentPool.getId(), targetHost.getId()) == null) {
+            throw new CloudRuntimeException(String.format("The target host does not have access to the volume's managed storage pool. [volumeId=%s, storageId=%s, targetHostId=%s].", volume.getUuid(),
+                    currentPool.getUuid(), targetHost.getUuid()));
+        }
+    }
+
+    /**
+     *  Return true if the VM migration is a cross cluster migration. To execute that, we check if the volume current storage pool cluster is different from the target host cluster.
+     */
+    protected boolean isStorageCrossClusterMigration(Host targetHost, StoragePoolVO currentPool) {
+        return ScopeType.CLUSTER.equals(currentPool.getScope()) && currentPool.getClusterId() != targetHost.getClusterId();
     }
 
     /**
      * We will add a mapping of volume to storage pool if needed. The conditions to add a mapping are the following:
      * <ul>
-     *  <li> The current storage pool where the volume is allocated can be accessed by the target host
-     *  <li> If not storage pool is found to allocate the volume we throw an exception.
+     *  <li> The candidate storage pool where the volume is to be allocated can be accessed by the target host
+     *  <li> If no storage pool is found to allocate the volume we throw an exception.
      * </ul>
      *
+     * Side note: this method should only be called if the volume is on local storage or if we are executing a cross cluster migration.
      */
-    private void createVolumeToStoragePoolMappingIfNeeded(VirtualMachineProfile profile, Host targetHost, Map<Volume, StoragePool> volumeToPoolObjectMap, VolumeVO volume, StoragePoolVO currentPool) {
-        List<StoragePool> poolList = getCandidateStoragePoolsToMigrateLocalVolume(profile, targetHost, volume);
+    protected void createVolumeToStoragePoolMappingIfPossible(VirtualMachineProfile profile, Host targetHost, Map<Volume, StoragePool> volumeToPoolObjectMap, Volume volume,
+            StoragePoolVO currentPool) {
+        List<StoragePool> storagePoolList = getCandidateStoragePoolsToMigrateLocalVolume(profile, targetHost, volume);
 
-        Collections.shuffle(poolList);
-        boolean canTargetHostAccessVolumeStoragePool = false;
-        for (StoragePool storagePool : poolList) {
+        if (CollectionUtils.isEmpty(storagePoolList)) {
+            throw new CloudRuntimeException(String.format("There is not storage pools available at the target host [%s] to migrate volume [%s]", targetHost.getUuid(), volume.getUuid()));
+        }
+
+        Collections.shuffle(storagePoolList);
+        boolean canTargetHostAccessVolumeCurrentStoragePool = false;
+        for (StoragePool storagePool : storagePoolList) {
             if (storagePool.getId() == currentPool.getId()) {
-                canTargetHostAccessVolumeStoragePool = true;
+                canTargetHostAccessVolumeCurrentStoragePool = true;
                 break;
             }
 
         }
-        if(!canTargetHostAccessVolumeStoragePool && CollectionUtils.isEmpty(poolList)) {
-            throw new CloudRuntimeException(String.format("There is not storage pools avaliable at the target host [%s] to migrate volume [%s]", targetHost.getUuid(), volume.getUuid()));
-        }
-        if (!canTargetHostAccessVolumeStoragePool) {
-            volumeToPoolObjectMap.put(volume, _storagePoolDao.findByUuid(poolList.get(0).getUuid()));
-        }
-        if (!canTargetHostAccessVolumeStoragePool && !volumeToPoolObjectMap.containsKey(volume)) {
-            throw new CloudRuntimeException(String.format("Cannot find a storage pool which is available for volume [%s] while migrating virtual machine [%s] to host [%s]", volume.getUuid(),
-                    profile.getUuid(), targetHost.getUuid()));
+        if (!canTargetHostAccessVolumeCurrentStoragePool) {
+            volumeToPoolObjectMap.put(volume, _storagePoolDao.findByUuid(storagePoolList.get(0).getUuid()));
         }
     }
 
     /**
-     * We use {@link StoragePoolAllocator} objects to find local storage pools connected to the targetHost where we would be able to allocate the given volume.
+     * We use {@link StoragePoolAllocator} objects to find storage pools connected to the targetHost where we would be able to allocate the given volume.
      */
-    private List<StoragePool> getCandidateStoragePoolsToMigrateLocalVolume(VirtualMachineProfile profile, Host targetHost, VolumeVO volume) {
+    protected List<StoragePool> getCandidateStoragePoolsToMigrateLocalVolume(VirtualMachineProfile profile, Host targetHost, Volume volume) {
         List<StoragePool> poolList = new ArrayList<>();
 
         DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
@@ -2392,7 +2452,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 continue;
             }
             for (StoragePool pool : poolListFromAllocator) {
-                if (pool.isLocal()) {
+                if (pool.isLocal() || isStorageCrossClusterMigration(targetHost, volumeStoragePool)) {
                     poolList.add(pool);
                 }
             }
@@ -2487,7 +2547,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         // Create a map of which volume should go in which storage pool.
         final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
-        final Map<Volume, StoragePool> volumeToPoolMap = getPoolListForVolumesForMigration(profile, destHost, volumeToPool);
+        final Map<Volume, StoragePool> volumeToPoolMap = createMappingVolumeAndStoragePool(profile, destHost, volumeToPool);
 
         // If none of the volumes have to be migrated, fail the call. Administrator needs to make a call for migrating
         // a vm and not migrating a vm with storage.
@@ -3971,8 +4031,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     @Override
     public ConfigKey<?>[] getConfigKeys() {
         return new ConfigKey<?>[] {ClusterDeltaSyncInterval, StartRetry, VmDestroyForcestop, VmOpCancelInterval, VmOpCleanupInterval, VmOpCleanupWait,
-                VmOpLockStateRetry,
-                VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval, VmConfigDriveLabel, VmConfigDriveOnPrimaryPool, HaVmRestartHostUp};
+            VmOpLockStateRetry,
+            VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval, VmConfigDriveLabel, VmConfigDriveOnPrimaryPool, HaVmRestartHostUp};
     }
 
     public List<StoragePoolAllocator> getStoragePoolAllocators() {
diff --git a/engine/orchestration/src/test/java/com/cloud/vm/VirtualMachineManagerImplTest.java b/engine/orchestration/src/test/java/com/cloud/vm/VirtualMachineManagerImplTest.java
index c379550..c4844ac 100644
--- a/engine/orchestration/src/test/java/com/cloud/vm/VirtualMachineManagerImplTest.java
+++ b/engine/orchestration/src/test/java/com/cloud/vm/VirtualMachineManagerImplTest.java
@@ -21,16 +21,25 @@ import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.InOrder;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.Spy;
 import org.mockito.runners.MockitoJUnitRunner;
 
@@ -38,12 +47,22 @@ import com.cloud.agent.AgentManager;
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.StopAnswer;
 import com.cloud.agent.api.StopCommand;
+import com.cloud.deploy.DeploymentPlan;
 import com.cloud.deploy.DeploymentPlanner;
+import com.cloud.deploy.DeploymentPlanner.ExcludeList;
 import com.cloud.host.HostVO;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.hypervisor.HypervisorGuru;
 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.StoragePool;
+import com.cloud.storage.StoragePoolHostVO;
+import com.cloud.storage.Volume;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.DiskOfferingDao;
+import com.cloud.storage.dao.StoragePoolHostDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.vm.VirtualMachine.State;
@@ -58,37 +77,76 @@ public class VirtualMachineManagerImplTest {
     @Mock
     private AgentManager agentManagerMock;
     @Mock
-    private VMInstanceDao vmInstanceDao;
+    private VMInstanceDao vmInstanceDaoMock;
     @Mock
-    private ServiceOfferingDao serviceOfferingDao;
+    private ServiceOfferingDao serviceOfferingDaoMock;
     @Mock
-    private VolumeDao volumeDao;
+    private VolumeDao volumeDaoMock;
+    @Mock
+    private PrimaryDataStoreDao storagePoolDaoMock;
     @Mock
     private VMInstanceVO vmInstanceMock;
+    private long vmInstanceVoMockId = 1L;
+
     @Mock
     private ServiceOfferingVO serviceOfferingMock;
+
+    private long hostMockId = 1L;
     @Mock
     private HostVO hostMock;
+
     @Mock
     private VirtualMachineProfile virtualMachineProfileMock;
+    @Mock
+    private StoragePoolVO storagePoolVoMock;
+    private long storagePoolVoMockId = 11L;
+    private long storagePoolVoMockClusterId = 234L;
+
+    @Mock
+    private VolumeVO volumeVoMock;
+    private long volumeMockId = 1111L;
+
+    @Mock
+    private StoragePoolHostDao storagePoolHostDaoMock;
+
+    @Mock
+    private StoragePoolAllocator storagePoolAllocatorMock;
+
+    @Mock
+    private DiskOfferingDao diskOfferingDaoMock;
 
     @Before
     public void setup() {
         virtualMachineManagerImpl.setHostAllocators(new ArrayList<>());
 
-        when(vmInstanceMock.getId()).thenReturn(1L);
+        when(vmInstanceMock.getId()).thenReturn(vmInstanceVoMockId);
         when(vmInstanceMock.getServiceOfferingId()).thenReturn(2L);
         when(vmInstanceMock.getInstanceName()).thenReturn("myVm");
         when(vmInstanceMock.getHostId()).thenReturn(2L);
         when(vmInstanceMock.getType()).thenReturn(VirtualMachine.Type.User);
-        when(hostMock.getId()).thenReturn(1L);
+        when(hostMock.getId()).thenReturn(hostMockId);
+
+        Mockito.doReturn(vmInstanceVoMockId).when(virtualMachineProfileMock).getId();
+
+        Mockito.doReturn(storagePoolVoMockId).when(storagePoolVoMock).getId();
+        Mockito.doReturn(storagePoolVoMockClusterId).when(storagePoolVoMock).getClusterId();
+
+        Mockito.doReturn(volumeMockId).when(volumeVoMock).getId();
+        Mockito.doReturn(storagePoolVoMockId).when(volumeVoMock).getPoolId();
+
+        Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
+        Mockito.doReturn(storagePoolVoMock).when(storagePoolDaoMock).findById(storagePoolVoMockId);
+
+        ArrayList<StoragePoolAllocator> storagePoolAllocators = new ArrayList<>();
+        storagePoolAllocators.add(storagePoolAllocatorMock);
+        virtualMachineManagerImpl.setStoragePoolAllocators(storagePoolAllocators);
     }
 
     @Test(expected = CloudRuntimeException.class)
     public void testScaleVM3() throws Exception {
         when(vmInstanceMock.getHostId()).thenReturn(null);
-        when(vmInstanceDao.findById(anyLong())).thenReturn(vmInstanceMock);
-        when(vmInstanceDao.findByUuid(any(String.class))).thenReturn(vmInstanceMock);
+        when(vmInstanceDaoMock.findById(anyLong())).thenReturn(vmInstanceMock);
+        when(vmInstanceDaoMock.findByUuid(any(String.class))).thenReturn(vmInstanceMock);
         DeploymentPlanner.ExcludeList excludeHostList = new DeploymentPlanner.ExcludeList();
         virtualMachineManagerImpl.findHostAndMigrate(vmInstanceMock.getUuid(), 2l, excludeHostList);
     }
@@ -154,7 +212,7 @@ public class VirtualMachineManagerImplTest {
 
         ServiceOfferingVO mockCurrentServiceOffering = mock(ServiceOfferingVO.class);
 
-        when(serviceOfferingDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn(mockCurrentServiceOffering);
+        when(serviceOfferingDaoMock.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn(mockCurrentServiceOffering);
         when(mockCurrentServiceOffering.getUseLocalStorage()).thenReturn(true);
         when(serviceOfferingMock.getUseLocalStorage()).thenReturn(true);
         when(mockCurrentServiceOffering.getSystemUse()).thenReturn(true);
@@ -164,4 +222,369 @@ public class VirtualMachineManagerImplTest {
 
         virtualMachineManagerImpl.checkIfCanUpgrade(vmInstanceMock, serviceOfferingMock);
     }
-}
+
+    @Test
+    public void isStorageCrossClusterMigrationTestStorageTypeEqualsCluster() {
+        Mockito.doReturn(1L).when(hostMock).getClusterId();
+        Mockito.doReturn(2L).when(storagePoolVoMock).getClusterId();
+        Mockito.doReturn(ScopeType.CLUSTER).when(storagePoolVoMock).getScope();
+
+        boolean returnedValue = virtualMachineManagerImpl.isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+
+        Assert.assertTrue(returnedValue);
+    }
+
+    @Test
+    public void isStorageCrossClusterMigrationTestStorageSameCluster() {
+        Mockito.doReturn(1L).when(hostMock).getClusterId();
+        Mockito.doReturn(1L).when(storagePoolVoMock).getClusterId();
+        Mockito.doReturn(ScopeType.CLUSTER).when(storagePoolVoMock).getScope();
+
+        boolean returnedValue = virtualMachineManagerImpl.isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+
+        Assert.assertFalse(returnedValue);
+    }
+
+    @Test
+    public void isStorageCrossClusterMigrationTestStorageTypeEqualsZone() {
+        Mockito.doReturn(1L).when(hostMock).getClusterId();
+        Mockito.doReturn(2L).when(storagePoolVoMock).getClusterId();
+        Mockito.doReturn(ScopeType.ZONE).when(storagePoolVoMock).getScope();
+
+        boolean returnedValue = virtualMachineManagerImpl.isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+
+        Assert.assertFalse(returnedValue);
+    }
+
+    @Test
+    public void executeManagedStorageChecksWhenTargetStoragePoolProvidedTestCurrentStoragePoolNotManaged() {
+        Mockito.doReturn(false).when(storagePoolVoMock).isManaged();
+
+        virtualMachineManagerImpl.executeManagedStorageChecksWhenTargetStoragePoolProvided(storagePoolVoMock, volumeVoMock, Mockito.mock(StoragePoolVO.class));
+
+        Mockito.verify(storagePoolVoMock).isManaged();
+        Mockito.verify(storagePoolVoMock, Mockito.times(0)).getId();
+    }
+
+    @Test
+    public void executeManagedStorageChecksWhenTargetStoragePoolProvidedTestCurrentStoragePoolEqualsTargetPool() {
+        Mockito.doReturn(true).when(storagePoolVoMock).isManaged();
+
+        virtualMachineManagerImpl.executeManagedStorageChecksWhenTargetStoragePoolProvided(storagePoolVoMock, volumeVoMock, storagePoolVoMock);
+
+        Mockito.verify(storagePoolVoMock).isManaged();
+        Mockito.verify(storagePoolVoMock, Mockito.times(2)).getId();
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void executeManagedStorageChecksWhenTargetStoragePoolProvidedTestCurrentStoragePoolNotEqualsTargetPool() {
+        Mockito.doReturn(true).when(storagePoolVoMock).isManaged();
+
+        virtualMachineManagerImpl.executeManagedStorageChecksWhenTargetStoragePoolProvided(storagePoolVoMock, volumeVoMock, Mockito.mock(StoragePoolVO.class));
+    }
+
+    @Test
+    public void buildMapUsingUserInformationTestUserDefinedMigrationMapEmpty() {
+        HashMap<Long, Long> userDefinedVolumeToStoragePoolMap = Mockito.spy(new HashMap<>());
+
+        Map<Volume, StoragePool> volumeToPoolObjectMap = virtualMachineManagerImpl.buildMapUsingUserInformation(virtualMachineProfileMock, hostMock, userDefinedVolumeToStoragePoolMap);
+
+        Assert.assertTrue(volumeToPoolObjectMap.isEmpty());
+
+        Mockito.verify(userDefinedVolumeToStoragePoolMap, times(0)).keySet();
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void buildMapUsingUserInformationTestTargetHostDoesNotHaveAccessToPool() {
+        HashMap<Long, Long> userDefinedVolumeToStoragePoolMap = new HashMap<>();
+        userDefinedVolumeToStoragePoolMap.put(volumeMockId, storagePoolVoMockId);
+
+        Mockito.doNothing().when(virtualMachineManagerImpl).executeManagedStorageChecksWhenTargetStoragePoolProvided(Mockito.any(StoragePoolVO.class), Mockito.any(VolumeVO.class), Mockito.any(StoragePoolVO.class));
+        Mockito.doReturn(null).when(storagePoolHostDaoMock).findByPoolHost(storagePoolVoMockId, hostMockId);
+
+        virtualMachineManagerImpl.buildMapUsingUserInformation(virtualMachineProfileMock, hostMock, userDefinedVolumeToStoragePoolMap);
+
+    }
+
+    @Test
+    public void buildMapUsingUserInformationTestTargetHostHasAccessToPool() {
+        HashMap<Long, Long> userDefinedVolumeToStoragePoolMap = Mockito.spy(new HashMap<>());
+        userDefinedVolumeToStoragePoolMap.put(volumeMockId, storagePoolVoMockId);
+
+        Mockito.doNothing().when(virtualMachineManagerImpl).executeManagedStorageChecksWhenTargetStoragePoolProvided(Mockito.any(StoragePoolVO.class), Mockito.any(VolumeVO.class),
+                Mockito.any(StoragePoolVO.class));
+        Mockito.doReturn(Mockito.mock(StoragePoolHostVO.class)).when(storagePoolHostDaoMock).findByPoolHost(storagePoolVoMockId, hostMockId);
+
+        Map<Volume, StoragePool> volumeToPoolObjectMap = virtualMachineManagerImpl.buildMapUsingUserInformation(virtualMachineProfileMock, hostMock, userDefinedVolumeToStoragePoolMap);
+
+        Assert.assertFalse(volumeToPoolObjectMap.isEmpty());
+        Assert.assertEquals(storagePoolVoMock, volumeToPoolObjectMap.get(volumeVoMock));
+
+        Mockito.verify(userDefinedVolumeToStoragePoolMap, times(1)).keySet();
+    }
+
+    @Test
+    public void findVolumesThatWereNotMappedByTheUserTest() {
+        Map<Volume, StoragePool> volumeToStoragePoolObjectMap = Mockito.spy(new HashMap<>());
+        volumeToStoragePoolObjectMap.put(volumeVoMock, storagePoolVoMock);
+
+        Volume volumeVoMock2 = Mockito.mock(Volume.class);
+
+        List<Volume> volumesOfVm = new ArrayList<>();
+        volumesOfVm.add(volumeVoMock);
+        volumesOfVm.add(volumeVoMock2);
+
+        Mockito.doReturn(volumesOfVm).when(volumeDaoMock).findUsableVolumesForInstance(vmInstanceVoMockId);
+        List<Volume> volumesNotMapped = virtualMachineManagerImpl.findVolumesThatWereNotMappedByTheUser(virtualMachineProfileMock, volumeToStoragePoolObjectMap);
+
+        Assert.assertEquals(1, volumesNotMapped.size());
+        Assert.assertEquals(volumeVoMock2, volumesNotMapped.get(0));
+    }
+
+    @Test
+    public void executeManagedStorageChecksWhenTargetStoragePoolNotProvidedTestCurrentStoragePoolNotManaged() {
+        Mockito.doReturn(false).when(storagePoolVoMock).isManaged();
+
+        virtualMachineManagerImpl.executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+
+        Mockito.verify(storagePoolVoMock).isManaged();
+        Mockito.verify(storagePoolHostDaoMock, Mockito.times(0)).findByPoolHost(Mockito.anyLong(), Mockito.anyLong());
+    }
+
+    @Test
+    public void executeManagedStorageChecksWhenTargetStoragePoolNotProvidedTestCurrentStoragePoolManagedIsConnectedToHost() {
+        Mockito.doReturn(true).when(storagePoolVoMock).isManaged();
+        Mockito.doReturn(Mockito.mock(StoragePoolHostVO.class)).when(storagePoolHostDaoMock).findByPoolHost(storagePoolVoMockId, hostMockId);
+
+        virtualMachineManagerImpl.executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+
+        Mockito.verify(storagePoolVoMock).isManaged();
+        Mockito.verify(storagePoolHostDaoMock, Mockito.times(1)).findByPoolHost(storagePoolVoMockId, hostMockId);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void executeManagedStorageChecksWhenTargetStoragePoolNotProvidedTestCurrentStoragePoolManagedIsNotConnectedToHost() {
+        Mockito.doReturn(true).when(storagePoolVoMock).isManaged();
+        Mockito.doReturn(null).when(storagePoolHostDaoMock).findByPoolHost(storagePoolVoMockId, hostMockId);
+
+        virtualMachineManagerImpl.executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+    }
+
+    @Test
+    public void getCandidateStoragePoolsToMigrateLocalVolumeTestLocalVolume() {
+        Mockito.doReturn(Mockito.mock(DiskOfferingVO.class)).when(diskOfferingDaoMock).findById(Mockito.anyLong());
+
+        Mockito.doReturn(true).when(storagePoolVoMock).isLocal();
+
+        List<StoragePool> poolListMock = new ArrayList<>();
+        poolListMock.add(storagePoolVoMock);
+
+        Mockito.doReturn(poolListMock).when(storagePoolAllocatorMock).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+
+        List<StoragePool> poolList = virtualMachineManagerImpl.getCandidateStoragePoolsToMigrateLocalVolume(virtualMachineProfileMock, hostMock, volumeVoMock);
+
+        Assert.assertEquals(1, poolList.size());
+        Assert.assertEquals(storagePoolVoMock, poolList.get(0));
+    }
+
+    @Test
+    public void getCandidateStoragePoolsToMigrateLocalVolumeTestCrossClusterMigration() {
+        Mockito.doReturn(Mockito.mock(DiskOfferingVO.class)).when(diskOfferingDaoMock).findById(Mockito.anyLong());
+
+        Mockito.doReturn(false).when(storagePoolVoMock).isLocal();
+
+        List<StoragePool> poolListMock = new ArrayList<>();
+        poolListMock.add(storagePoolVoMock);
+
+        Mockito.doReturn(poolListMock).when(storagePoolAllocatorMock).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+
+        Mockito.doReturn(true).when(virtualMachineManagerImpl).isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+        List<StoragePool> poolList = virtualMachineManagerImpl.getCandidateStoragePoolsToMigrateLocalVolume(virtualMachineProfileMock, hostMock, volumeVoMock);
+
+        Assert.assertEquals(1, poolList.size());
+        Assert.assertEquals(storagePoolVoMock, poolList.get(0));
+    }
+
+    @Test
+    public void getCandidateStoragePoolsToMigrateLocalVolumeTestWithinClusterMigration() {
+        Mockito.doReturn(Mockito.mock(DiskOfferingVO.class)).when(diskOfferingDaoMock).findById(Mockito.anyLong());
+
+        Mockito.doReturn(false).when(storagePoolVoMock).isLocal();
+
+        List<StoragePool> poolListMock = new ArrayList<>();
+        poolListMock.add(storagePoolVoMock);
+
+        Mockito.doReturn(poolListMock).when(storagePoolAllocatorMock).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+
+        Mockito.doReturn(false).when(virtualMachineManagerImpl).isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+        List<StoragePool> poolList = virtualMachineManagerImpl.getCandidateStoragePoolsToMigrateLocalVolume(virtualMachineProfileMock, hostMock, volumeVoMock);
+
+        Assert.assertTrue(poolList.isEmpty());
+    }
+
+    @Test
+    public void getCandidateStoragePoolsToMigrateLocalVolumeTestMoreThanOneAllocator() {
+        StoragePoolAllocator storagePoolAllocatorMock2 = Mockito.mock(StoragePoolAllocator.class);
+        StoragePoolAllocator storagePoolAllocatorMock3 = Mockito.mock(StoragePoolAllocator.class);
+
+        List<StoragePoolAllocator> storagePoolAllocatorsMock = new ArrayList<>();
+        storagePoolAllocatorsMock.add(storagePoolAllocatorMock);
+        storagePoolAllocatorsMock.add(storagePoolAllocatorMock2);
+        storagePoolAllocatorsMock.add(storagePoolAllocatorMock3);
+
+        virtualMachineManagerImpl.setStoragePoolAllocators(storagePoolAllocatorsMock);
+
+        Mockito.doReturn(Mockito.mock(DiskOfferingVO.class)).when(diskOfferingDaoMock).findById(Mockito.anyLong());
+
+        Mockito.doReturn(false).when(storagePoolVoMock).isLocal();
+
+        List<StoragePool> poolListMock = new ArrayList<>();
+        poolListMock.add(storagePoolVoMock);
+
+        Mockito.doReturn(poolListMock).when(storagePoolAllocatorMock).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+
+        Mockito.doReturn(null).when(storagePoolAllocatorMock2).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+
+        Mockito.doReturn(new ArrayList<>()).when(storagePoolAllocatorMock3).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+
+        Mockito.doReturn(false).when(virtualMachineManagerImpl).isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+        List<StoragePool> poolList = virtualMachineManagerImpl.getCandidateStoragePoolsToMigrateLocalVolume(virtualMachineProfileMock, hostMock, volumeVoMock);
+
+        Assert.assertTrue(poolList.isEmpty());
+
+        Mockito.verify(storagePoolAllocatorMock).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+        Mockito.verify(storagePoolAllocatorMock2).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+        Mockito.verify(storagePoolAllocatorMock3).allocateToPool(Mockito.any(DiskProfile.class), Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class),
+                Mockito.any(ExcludeList.class), Mockito.eq(StoragePoolAllocator.RETURN_UPTO_ALL));
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void createVolumeToStoragePoolMappingIfPossibleTestNotStoragePoolsAvailable() {
+        Mockito.doReturn(null).when(virtualMachineManagerImpl).getCandidateStoragePoolsToMigrateLocalVolume(virtualMachineProfileMock, hostMock, volumeVoMock);
+
+        virtualMachineManagerImpl.createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, new HashMap<>(), volumeVoMock, storagePoolVoMock);
+    }
+
+    @Test
+    public void createVolumeToStoragePoolMappingIfPossibleTestTargetHostAccessCurrentStoragePool() {
+        List<StoragePool> storagePoolList = new ArrayList<>();
+        storagePoolList.add(storagePoolVoMock);
+
+        Mockito.doReturn(storagePoolList).when(virtualMachineManagerImpl).getCandidateStoragePoolsToMigrateLocalVolume(virtualMachineProfileMock, hostMock, volumeVoMock);
+
+        HashMap<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<>();
+        virtualMachineManagerImpl.createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumeVoMock, storagePoolVoMock);
+
+        Assert.assertTrue(volumeToPoolObjectMap.isEmpty());
+    }
+
+    @Test
+    public void createVolumeToStoragePoolMappingIfPossibleTestTargetHostDoesNotAccessCurrentStoragePool() {
+        StoragePoolVO storagePoolMockOther = Mockito.mock(StoragePoolVO.class);
+        String storagePoolMockOtherUuid = "storagePoolMockOtherUuid";
+        Mockito.doReturn(storagePoolMockOtherUuid).when(storagePoolMockOther).getUuid();
+        Mockito.doReturn(storagePoolMockOther).when(storagePoolDaoMock).findByUuid(storagePoolMockOtherUuid);
+
+        List<StoragePool> storagePoolList = new ArrayList<>();
+        storagePoolList.add(storagePoolMockOther);
+
+        Mockito.doReturn(storagePoolList).when(virtualMachineManagerImpl).getCandidateStoragePoolsToMigrateLocalVolume(virtualMachineProfileMock, hostMock, volumeVoMock);
+
+        HashMap<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<>();
+        virtualMachineManagerImpl.createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumeVoMock, storagePoolVoMock);
+
+        Assert.assertFalse(volumeToPoolObjectMap.isEmpty());
+        Assert.assertEquals(storagePoolMockOther, volumeToPoolObjectMap.get(volumeVoMock));
+    }
+
+    @Test
+    public void createStoragePoolMappingsForVolumesTestLocalStoragevolume() {
+        ArrayList<Volume> allVolumes = new ArrayList<>();
+        allVolumes.add(volumeVoMock);
+
+        HashMap<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<>();
+
+        Mockito.doReturn(ScopeType.HOST).when(storagePoolVoMock).getScope();
+        Mockito.doNothing().when(virtualMachineManagerImpl).executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+        Mockito.doNothing().when(virtualMachineManagerImpl).createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumeVoMock,
+                storagePoolVoMock);
+
+        virtualMachineManagerImpl.createStoragePoolMappingsForVolumes(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, allVolumes);
+
+        Assert.assertTrue(volumeToPoolObjectMap.isEmpty());
+        Mockito.verify(virtualMachineManagerImpl).executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+        Mockito.verify(virtualMachineManagerImpl).createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumeVoMock, storagePoolVoMock);
+    }
+
+    @Test
+    public void createStoragePoolMappingsForVolumesTestCrossCluterMigration() {
+        ArrayList<Volume> allVolumes = new ArrayList<>();
+        allVolumes.add(volumeVoMock);
+
+        HashMap<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<>();
+
+        Mockito.doReturn(ScopeType.CLUSTER).when(storagePoolVoMock).getScope();
+        Mockito.doNothing().when(virtualMachineManagerImpl).executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+        Mockito.doNothing().when(virtualMachineManagerImpl).createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumeVoMock, storagePoolVoMock);
+        Mockito.doReturn(true).when(virtualMachineManagerImpl).isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+
+        virtualMachineManagerImpl.createStoragePoolMappingsForVolumes(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, allVolumes);
+
+        Assert.assertTrue(volumeToPoolObjectMap.isEmpty());
+        Mockito.verify(virtualMachineManagerImpl).executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+        Mockito.verify(virtualMachineManagerImpl).createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumeVoMock, storagePoolVoMock);
+        Mockito.verify(virtualMachineManagerImpl).isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+    }
+
+    @Test
+    public void createStoragePoolMappingsForVolumesTestNotCrossCluterMigrationWithClusterStorage() {
+        ArrayList<Volume> allVolumes = new ArrayList<>();
+        allVolumes.add(volumeVoMock);
+
+        HashMap<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<>();
+
+        Mockito.doReturn(ScopeType.CLUSTER).when(storagePoolVoMock).getScope();
+        Mockito.doNothing().when(virtualMachineManagerImpl).executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+        Mockito.doNothing().when(virtualMachineManagerImpl).createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumeVoMock, storagePoolVoMock);
+        Mockito.doReturn(false).when(virtualMachineManagerImpl).isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+
+        virtualMachineManagerImpl.createStoragePoolMappingsForVolumes(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, allVolumes);
+
+        Assert.assertFalse(volumeToPoolObjectMap.isEmpty());
+        Assert.assertEquals(storagePoolVoMock, volumeToPoolObjectMap.get(volumeVoMock));
+
+        Mockito.verify(virtualMachineManagerImpl).executeManagedStorageChecksWhenTargetStoragePoolNotProvided(hostMock, storagePoolVoMock, volumeVoMock);
+        Mockito.verify(virtualMachineManagerImpl).isStorageCrossClusterMigration(hostMock, storagePoolVoMock);
+        Mockito.verify(virtualMachineManagerImpl, Mockito.times(0)).createVolumeToStoragePoolMappingIfPossible(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumeVoMock,
+                storagePoolVoMock);
+    }
+
+    @Test
+    public void createMappingVolumeAndStoragePoolTest() {
+        Map<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<>();
+        List<Volume> volumesNotMapped = new ArrayList<>();
+
+        Mockito.doReturn(volumeToPoolObjectMap).when(virtualMachineManagerImpl).buildMapUsingUserInformation(Mockito.eq(virtualMachineProfileMock), Mockito.eq(hostMock),
+                Mockito.anyMapOf(Long.class, Long.class));
+
+        Mockito.doReturn(volumesNotMapped).when(virtualMachineManagerImpl).findVolumesThatWereNotMappedByTheUser(virtualMachineProfileMock, volumeToPoolObjectMap);
+        Mockito.doNothing().when(virtualMachineManagerImpl).createStoragePoolMappingsForVolumes(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumesNotMapped);
+
+        Map<Volume, StoragePool> mappingVolumeAndStoragePool = virtualMachineManagerImpl.createMappingVolumeAndStoragePool(virtualMachineProfileMock, hostMock, new HashMap<>());
+
+        Assert.assertEquals(mappingVolumeAndStoragePool, volumeToPoolObjectMap);
+
+        InOrder inOrder = Mockito.inOrder(virtualMachineManagerImpl);
+        inOrder.verify(virtualMachineManagerImpl).buildMapUsingUserInformation(Mockito.eq(virtualMachineProfileMock), Mockito.eq(hostMock), Mockito.anyMapOf(Long.class, Long.class));
+        inOrder.verify(virtualMachineManagerImpl).findVolumesThatWereNotMappedByTheUser(virtualMachineProfileMock, volumeToPoolObjectMap);
+        inOrder.verify(virtualMachineManagerImpl).createStoragePoolMappingsForVolumes(virtualMachineProfileMock, hostMock, volumeToPoolObjectMap, volumesNotMapped);
+    }
+}
\ No newline at end of file