mike-tutkowski commented on a change in pull request #2761: Add managed storage 
pool constraints to MigrateWithVolume API method
URL: https://github.com/apache/cloudstack/pull/2761#discussion_r205340486
 
 

 ##########
 File path: 
engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
 ##########
 @@ -2292,73 +2292,143 @@ protected void migrate(final VMInstanceVO vm, final 
long srcHostId, final Deploy
 
     /**
      * 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> 
createMappingVolumeAndStoragePoolEnteredByUser(VirtualMachineProfile profile, 
Host host, Map<Long, Long> volumeToPool) {
+    protected Map<Volume, StoragePool> 
createMappingVolumeAndStoragePoolEnteredByUser(VirtualMachineProfile profile, 
Host targetHost, Map<Long, Long> volumeToPool) {
         Map<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<Volume, 
StoragePool>();
+        buildMapUsingUserInformation(profile, targetHost, volumeToPool, 
volumeToPoolObjectMap);
+
+        List<Volume> volumesNotMapped = 
findVolumesThatWereNotMappedByTheUser(profile, volumeToPoolObjectMap);
+        createStoragePoolMappingsForVolumes(profile, targetHost, 
volumeToPoolObjectMap, volumesNotMapped);
+        return volumeToPoolObjectMap;
+    }
+
+    /**
+     *  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 List<Volume> 
findVolumesThatWereNotMappedByTheUser(VirtualMachineProfile profile, 
Map<Volume, StoragePool> volumeToPoolObjectMap) {
+        List<VolumeVO> allVolumes = 
_volsDao.findUsableVolumesForInstance(profile.getId());
+        List<Volume> volumesNotMapped = new ArrayList<>();
+        for (Volume volume : volumeToPoolObjectMap.keySet()) {
+            if (!allVolumes.contains(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.
+     */
+    private void buildMapUsingUserInformation(VirtualMachineProfile profile, 
Host targetHost, Map<Long, Long> volumeToPool, Map<Volume, StoragePool> 
volumeToPoolObjectMap) {
         for(Long volumeId: volumeToPool.keySet()) {
             VolumeVO volume = _volsDao.findById(volumeId);
 
             Long poolId = volumeToPool.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()));
+            executeManagedStorageChecks(targetHost, currentPool, volume);
+            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()));
             }
             volumeToPoolObjectMap.put(volume, targetPool);
         }
-        return volumeToPoolObjectMap;
     }
 
     /**
-     * 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.
+     * We create the default mapping of volumes and storage pools for the 
migration of the VM to the target host. We execute the following checks an 
operations according to some scenarios:
+     * <ul>
+     *  <li>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.
+     *  <li>If the current storage pool cluster is different from the target 
host cluster, we need to migrate the volume to one storage pool at the target 
cluster where the target host resides on.
+     * </ul>
      */
-    private Map<Volume, StoragePool> 
getDefaultMappingOfVolumesAndStoragePoolForMigration(VirtualMachineProfile 
profile, Host targetHost) {
+    protected 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) {
+        createStoragePoolMappingsForVolumes(profile, targetHost, 
volumeToPoolObjectMap, new ArrayList<>(allVolumes));
+        return volumeToPoolObjectMap;
+    }
+
+    /**
+     * 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.
+     */
+    private 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);
+
+            executeManagedStorageChecks(targetHost, currentPool, volume);
+            if (ScopeType.HOST.equals(currentPool.getScope()) || 
isStorageCrossClusterMigration(targetHost, currentPool)) {
+                createVolumeToStoragePoolMappingIfPossible(profile, 
targetHost, volumeToPoolObjectMap, volume, currentPool);
             } else {
                 volumeToPoolObjectMap.put(volume, currentPool);
 
 Review comment:
   Per a previous comment of mine, we should decide if this line should be 
there. The old code didn't put the volume in the map if its current pool wasn't 
going to change.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to