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

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


The following commit(s) were added to refs/heads/main by this push:
     new cd4e7e0  Fix resize volume and migrate volume to update volume path if 
DRS is applied on volume in datastore cluster (#5539)
cd4e7e0 is described below

commit cd4e7e031adcf99856802038359f93a41ce31a3e
Author: Harikrishna <[email protected]>
AuthorDate: Tue Oct 5 05:28:25 2021 +0530

    Fix resize volume and migrate volume to update volume path if DRS is 
applied on volume in datastore cluster (#5539)
    
    * Fix resize volume and migrate volume to update volume path if DRS is 
applied on volume in datastore cluster
    
    * Change in constructors
    
    * Naming changes
    
    * Remove commented code
    
    * Refactor code for more readability
    
    * Addressed review comments on code refactor
---
 .../agent/api/storage/MigrateVolumeCommand.java    |  17 +-
 .../agent/api/storage/ResizeVolumeCommand.java     |   8 +
 .../storage/motion/AncientDataMotionStrategy.java  |   9 +-
 .../hypervisor/vmware/resource/VmwareResource.java | 290 ++++++++++++++-------
 .../motion/VmwareStorageMotionStrategy.java        |   7 +-
 .../CloudStackPrimaryDataStoreDriverImpl.java      |  34 ++-
 6 files changed, 260 insertions(+), 105 deletions(-)

diff --git 
a/core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java 
b/core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java
index 2dd4023..9fed0f9 100644
--- a/core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java
+++ b/core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java
@@ -30,6 +30,7 @@ import com.cloud.storage.Volume;
 public class MigrateVolumeCommand extends Command {
     long volumeId;
     String volumePath;
+    String chainInfo;
     StorageFilerTO pool;
     StorageFilerTO sourcePool;
     String attachedVmName;
@@ -49,14 +50,22 @@ public class MigrateVolumeCommand extends Command {
     }
 
     public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool 
pool, String attachedVmName, Volume.Type volumeType, int timeout) {
-        this(volumeId,volumePath,pool,timeout);
+        this(volumeId, volumePath, pool, timeout);
         this.attachedVmName = attachedVmName;
         this.volumeType = volumeType;
         this.setWait(timeout);
     }
 
-    public MigrateVolumeCommand(long volumeId, String volumePath, String 
attachedVmName, StoragePool sourcePool, StoragePool targetPool, String 
hostGuidInTargetCluster) {
-        this(volumeId,volumePath,targetPool, attachedVmName, 
Volume.Type.UNKNOWN, -1);
+    public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool 
pool, String attachedVmName, Volume.Type volumeType, int timeout, String 
chainInfo) {
+        this(volumeId, volumePath, pool, timeout);
+        this.attachedVmName = attachedVmName;
+        this.volumeType = volumeType;
+        this.chainInfo = chainInfo;
+        this.setWait(timeout);
+    }
+
+    public MigrateVolumeCommand(long volumeId, String volumePath, String 
attachedVmName, StoragePool sourcePool, StoragePool targetPool, String 
hostGuidInTargetCluster, String chainInfo) {
+        this(volumeId,volumePath,targetPool, attachedVmName, 
Volume.Type.UNKNOWN, -1, chainInfo);
         this.sourcePool = new StorageFilerTO(sourcePool);
         this.hostGuidInTargetCluster = hostGuidInTargetCluster;
     }
@@ -134,4 +143,6 @@ public class MigrateVolumeCommand extends Command {
     public int getWaitInMillSeconds() {
         return getWait() * 1000;
     }
+
+    public String getChainInfo() { return chainInfo; }
 }
diff --git 
a/core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java 
b/core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java
index 22cff13..70d4d3e 100644
--- a/core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java
+++ b/core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java
@@ -29,6 +29,7 @@ public class ResizeVolumeCommand extends Command {
     private Long newSize;
     private boolean shrinkOk;
     private String vmInstance;
+    private String chainInfo;
 
     /* For managed storage */
     private boolean managed;
@@ -47,6 +48,11 @@ public class ResizeVolumeCommand extends Command {
         this.managed = false;
     }
 
+    public ResizeVolumeCommand(String path, StorageFilerTO pool, Long 
currentSize, Long newSize, boolean shrinkOk, String vmInstance, String 
chainInfo) {
+        this(path, pool, currentSize, newSize, shrinkOk, vmInstance);
+        this.chainInfo = chainInfo;
+    }
+
     public ResizeVolumeCommand(String path, StorageFilerTO pool, Long 
currentSize, Long newSize, boolean shrinkOk, String vmInstance,
                                boolean isManaged, String iScsiName) {
         this(path, pool, currentSize, newSize, shrinkOk, vmInstance);
@@ -81,6 +87,8 @@ public class ResizeVolumeCommand extends Command {
 
     public String get_iScsiName() {return iScsiName; }
 
+    public String getChainInfo() {return chainInfo; }
+
     /**
      * {@inheritDoc}
      */
diff --git 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index 51e0c97..74de765 100644
--- 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -24,6 +24,8 @@ import java.util.Map;
 
 import javax.inject.Inject;
 
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.storage.Storage;
 import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
 import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
@@ -447,8 +449,13 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
         int waitInterval = NumbersUtil.parseInt(value, 
Integer.parseInt(Config.MigrateWait.getDefaultValue()));
 
         VolumeInfo volume = (VolumeInfo)srcData;
+        StoragePool srcPool = 
(StoragePool)dataStoreMgr.getDataStore(srcData.getDataStore().getId(), 
DataStoreRole.Primary);
         StoragePool destPool = 
(StoragePool)dataStoreMgr.getDataStore(destData.getDataStore().getId(), 
DataStoreRole.Primary);
-        MigrateVolumeCommand command = new 
MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool, 
volume.getAttachedVmName(), volume.getVolumeType(), waitInterval);
+        MigrateVolumeCommand command = new 
MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool, 
volume.getAttachedVmName(), volume.getVolumeType(), waitInterval, 
volume.getChainInfo());
+        if (srcPool.getParent() != 0) {
+            command.setContextParam(DiskTO.PROTOCOL_TYPE, 
Storage.StoragePoolType.DatastoreCluster.toString());
+        }
+
         EndPoint ep = selector.select(srcData, StorageAction.MIGRATEVOLUME);
         Answer answer = null;
         if (ep == null) {
diff --git 
a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
 
b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 0e93398..9958b22 100644
--- 
a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ 
b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -775,9 +775,13 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
         String vmName = cmd.getInstanceName();
         long newSize = cmd.getNewSize() / ResourceType.bytesToKiB;
         long oldSize = cmd.getCurrentSize() / ResourceType.bytesToKiB;
+        boolean managed = cmd.isManaged();
+        String poolUUID = cmd.getPoolUuid();
+        String chainInfo = cmd.getChainInfo();
         boolean useWorkerVm = false;
 
-        VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext());
+        VmwareContext context = getServiceContext();
+        VmwareHypervisorHost hyperHost = getHyperHost(context);
         VirtualMachineMO vmMo = null;
 
         String vmdkDataStorePath = null;
@@ -789,24 +793,6 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
             } else if (newSize == oldSize) {
                 return new ResizeVolumeAnswer(cmd, true, "success", newSize * 
ResourceType.bytesToKiB);
             }
-            /*
-            // FR41 this is yet to fix
-            ManagedObjectReference morDS1 = 
HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, 
cmd.getPoolUuid());
-            DatastoreMO dsMo1 = new DatastoreMO(hyperHost.getContext(), 
morDS1);
-            vmdkDataStorePath = 
VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo1, path + 
VMDK_EXTENSION);
-            DatastoreFile dsFile1 = new DatastoreFile(vmdkDataStorePath);
-
-            s_logger.debug("vDiskid does not exist for volume " + 
vmdkDataStorePath + " registering the disk now");
-            VirtualStorageObjectManagerMO vStorageObjectManagerMO = new 
VirtualStorageObjectManagerMO(getServiceContext());
-            try {
-                VStorageObject vStorageObject = 
vStorageObjectManagerMO.registerVirtualDisk(dsFile1, null, 
dsMo1.getOwnerDatacenter().second());
-                VStorageObjectConfigInfo diskConfigInfo = 
vStorageObject.getConfig();
-                ID vdiskId = diskConfigInfo.getId();
-            } catch (Throwable e) {
-                if (e instanceof AlreadyExistsFaultMsg) {
-
-                }
-            }*/
 
             if (vmName.equalsIgnoreCase("none")) {
                 // OfflineVmwareMigration: we need to refactor the worker vm 
creation out for use in migration methods as well as here
@@ -852,26 +838,8 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
                 throw new Exception(msg);
             }
 
-            // OfflineVmwareMigration: 5. ignore/replace the rest of the 
try-block; It is the functional bit
-            Pair<VirtualDisk, String> vdisk = vmMo.getDiskDevice(path);
-
-            if (vdisk == null) {
-                if (s_logger.isTraceEnabled()) {
-                    s_logger.trace("resize volume done (failed)");
-                }
-
-                throw new Exception("No such disk device: " + path);
-            }
-
-            // IDE virtual disk cannot be re-sized if VM is running
-            if (vdisk.second() != null && vdisk.second().contains("ide")) {
-                throw new Exception("Re-sizing a virtual disk over an IDE 
controller is not supported in the VMware hypervisor. " +
-                        "Please re-try when virtual disk is attached to a VM 
using a SCSI controller.");
-            }
-
-            if (cmd.isManaged()) {
-                VmwareContext context = getServiceContext();
 
+            if (managed) {
                 ManagedObjectReference morCluster = 
hyperHost.getHyperHostCluster();
                 ClusterMO clusterMO = new ClusterMO(context, morCluster);
 
@@ -892,15 +860,26 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
                 _storageProcessor.expandDatastore(hostDatastoreSystem, dsMo);
             }
 
-            if (vdisk.second() != null && 
!vdisk.second().toLowerCase().startsWith("scsi")) {
-                s_logger.error("Unsupported disk device bus " + 
vdisk.second());
-                throw new Exception("Unsupported disk device bus " + 
vdisk.second());
+            boolean volumePathChangeObserved = false;
+            boolean datastoreChangeObserved = false;
+
+            Pair<String, String> pathAndChainInfo = 
getNewPathAndChainInfoInDatastoreCluster(vmMo, path, chainInfo, managed, 
cmd.get_iScsiName(), poolUUID, cmd.getContextParam(DiskTO.PROTOCOL_TYPE));
+            Pair<String, String> poolUUIDandChainInfo = 
getNewPoolUUIDAndChainInfoInDatastoreCluster(vmMo, path, chainInfo, managed, 
cmd.get_iScsiName(), poolUUID, cmd.getContextParam(DiskTO.PROTOCOL_TYPE));
+
+            if (pathAndChainInfo != null) {
+                volumePathChangeObserved = true;
+                path = pathAndChainInfo.first();
+                chainInfo = pathAndChainInfo.second();
             }
-            VirtualDisk disk = vdisk.first();
-            if ((VirtualDiskFlatVer2BackingInfo) disk.getBacking() != null && 
((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent() != null) {
-                s_logger.error("Resize is not supported because Disk device 
has Parent " + ((VirtualDiskFlatVer2BackingInfo) 
disk.getBacking()).getParent().getUuid());
-                throw new Exception("Resize is not supported because Disk 
device has Parent " + ((VirtualDiskFlatVer2BackingInfo) 
disk.getBacking()).getParent().getUuid());
+
+            if (poolUUIDandChainInfo != null) {
+                datastoreChangeObserved = true;
+                poolUUID = poolUUIDandChainInfo.first();
+                chainInfo = poolUUIDandChainInfo.second();
             }
+
+            // OfflineVmwareMigration: 5. ignore/replace the rest of the 
try-block; It is the functional bit
+            VirtualDisk disk = getDiskAfterResizeDiskValidations(vmMo, path);
             String vmdkAbsFile = getAbsoluteVmdkFile(disk);
 
             if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
@@ -922,7 +901,17 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
                 throw new Exception("Failed to configure VM to resize disk. 
vmName: " + vmName);
             }
 
-            return new ResizeVolumeAnswer(cmd, true, "success", newSize * 
1024);
+            ResizeVolumeAnswer answer = new ResizeVolumeAnswer(cmd, true, 
"success", newSize * 1024);
+            if (datastoreChangeObserved) {
+                answer.setContextParam("datastoreUUID", poolUUID);
+                answer.setContextParam("chainInfo", chainInfo);
+            }
+
+            if (volumePathChangeObserved) {
+                answer.setContextParam("volumePath", path);
+                answer.setContextParam("chainInfo", chainInfo);
+            }
+            return answer;
         } catch (Exception e) {
             s_logger.error("Unable to resize volume", e);
 
@@ -944,6 +933,79 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
         }
     }
 
+    private VirtualDisk getDiskAfterResizeDiskValidations(VirtualMachineMO 
vmMo, String volumePath) throws Exception {
+        Pair<VirtualDisk, String> vdisk = vmMo.getDiskDevice(volumePath);
+        if (vdisk == null) {
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("resize volume done (failed)");
+            }
+            throw new Exception("No such disk device: " + volumePath);
+        }
+
+        // IDE virtual disk cannot be re-sized if VM is running
+        if (vdisk.second() != null && vdisk.second().contains("ide")) {
+            throw new Exception("Re-sizing a virtual disk over an IDE 
controller is not supported in the VMware hypervisor. " +
+                    "Please re-try when virtual disk is attached to a VM using 
a SCSI controller.");
+        }
+
+        if (vdisk.second() != null && 
!vdisk.second().toLowerCase().startsWith("scsi")) {
+            s_logger.error("Unsupported disk device bus " + vdisk.second());
+            throw new Exception("Unsupported disk device bus " + 
vdisk.second());
+        }
+        VirtualDisk disk = vdisk.first();
+        if ((VirtualDiskFlatVer2BackingInfo) disk.getBacking() != null && 
((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent() != null) {
+            s_logger.error("Resize is not supported because Disk device has 
Parent " + ((VirtualDiskFlatVer2BackingInfo) 
disk.getBacking()).getParent().getUuid());
+            throw new Exception("Resize is not supported because Disk device 
has Parent " + ((VirtualDiskFlatVer2BackingInfo) 
disk.getBacking()).getParent().getUuid());
+        }
+        return disk;
+    }
+
+    private Pair<String, String> 
getNewPathAndChainInfoInDatastoreCluster(VirtualMachineMO vmMo, String path, 
String chainInfo, boolean managed, String iscsiName, String poolUUID, String 
poolType) throws Exception {
+        VmwareContext context = getServiceContext();
+        VmwareHypervisorHost hyperHost = getHyperHost(context);
+        if (poolType != null && 
poolType.equalsIgnoreCase(Storage.StoragePoolType.DatastoreCluster.toString())) 
{
+            VirtualMachineDiskInfoBuilder diskInfoBuilder = 
vmMo.getDiskInfoBuilder();
+            VirtualMachineDiskInfo matchingExistingDisk = 
getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, path, chainInfo, 
managed, iscsiName, poolUUID, hyperHost, context);
+            if (diskInfoBuilder != null && matchingExistingDisk != null) {
+                String[] diskChain = matchingExistingDisk.getDiskChain();
+                DatastoreFile file = new DatastoreFile(diskChain[0]);
+                if (!file.getFileBaseName().equalsIgnoreCase(path)) {
+                    if (s_logger.isInfoEnabled())
+                        s_logger.info("Detected disk-chain top file change on 
volume: " + path + " -> " + file.getFileBaseName());
+                    path = file.getFileBaseName();
+                    chainInfo = _gson.toJson(matchingExistingDisk);
+                    return new Pair<>(path, chainInfo);
+                }
+            }
+        }
+        return null;
+    }
+
+    private Pair<String, String> 
getNewPoolUUIDAndChainInfoInDatastoreCluster(VirtualMachineMO vmMo, String 
path, String chainInfo, boolean managed, String iscsiName, String poolUUID, 
String poolType) throws Exception {
+        VmwareContext context = getServiceContext();
+        VmwareHypervisorHost hyperHost = getHyperHost(context);
+        if (poolType != null && 
poolType.equalsIgnoreCase(Storage.StoragePoolType.DatastoreCluster.toString())) 
{
+            VirtualMachineDiskInfoBuilder diskInfoBuilder = 
vmMo.getDiskInfoBuilder();
+            VirtualMachineDiskInfo matchingExistingDisk = 
getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, path, chainInfo, 
managed, iscsiName, poolUUID, hyperHost, context);
+            if (diskInfoBuilder != null && matchingExistingDisk != null) {
+                String[] diskChain = matchingExistingDisk.getDiskChain();
+                DatastoreFile file = new DatastoreFile(diskChain[0]);
+                DatacenterMO dcMo = new DatacenterMO(hyperHost.getContext(), 
hyperHost.getHyperHostDatacenter());
+                DatastoreMO diskDatastoreMofromVM = new DatastoreMO(context, 
dcMo.findDatastore(file.getDatastoreName()));
+                if (diskDatastoreMofromVM != null) {
+                    String actualPoolUuid = 
diskDatastoreMofromVM.getCustomFieldValue(CustomFieldConstants.CLOUD_UUID);
+                    if (!actualPoolUuid.equalsIgnoreCase(poolUUID)) {
+                        s_logger.warn(String.format("Volume %s found to be in 
a different storage pool %s", path, actualPoolUuid));
+                        poolUUID = actualPoolUuid;
+                        chainInfo = _gson.toJson(matchingExistingDisk);
+                        return new Pair<>(poolUUID, chainInfo);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
     protected Answer execute(CheckNetworkCommand cmd) {
         if (s_logger.isInfoEnabled()) {
             s_logger.info("Executing resource CheckNetworkCommand " + 
_gson.toJson(cmd));
@@ -1911,7 +1973,7 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
                                 s_logger.error(msg);
                                 throw new Exception(msg);
                             }
-                        if (rootDisk.getDetails().get(DiskTO.PROTOCOL_TYPE) != 
null && 
rootDisk.getDetails().get(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase("DatastoreCluster"))
 {
+                        if (rootDisk.getDetails().get(DiskTO.PROTOCOL_TYPE) != 
null && 
rootDisk.getDetails().get(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase(Storage.StoragePoolType.DatastoreCluster.toString()))
 {
                             if (diskInfoBuilder != null) {
                                 DatastoreMO diskDatastoreMofromVM = 
getDataStoreWhereDiskExists(hyperHost, context, diskInfoBuilder, rootDisk, 
diskDatastores);
                                 if (diskDatastoreMofromVM != null) {
@@ -3254,70 +3316,82 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
             nicIndex++;
         }
     }
+    private VirtualMachineDiskInfo 
getMatchingExistingDiskWithVolumeDetails(VirtualMachineDiskInfoBuilder 
diskInfoBuilder, String volumePath,
+                                                                             
String chainInfo, boolean isManaged, String iScsiName, String datastoreUUID,
+                                                                             
VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception {
 
-    private VirtualMachineDiskInfo 
getMatchingExistingDisk(VirtualMachineDiskInfoBuilder diskInfoBuilder, DiskTO 
vol, VmwareHypervisorHost hyperHost, VmwareContext context)
-            throws Exception {
-        if (diskInfoBuilder != null) {
-            VolumeObjectTO volume = (VolumeObjectTO) vol.getData();
-
-            String dsName = null;
-            String diskBackingFileBaseName = null;
-
-            Map<String, String> details = vol.getDetails();
-            boolean isManaged = details != null && 
Boolean.parseBoolean(details.get(DiskTO.MANAGED));
-
-            if (isManaged) {
-                String iScsiName = details.get(DiskTO.IQN);
-
-                // if the storage is managed, iScsiName should not be null
-                dsName = VmwareResource.getDatastoreName(iScsiName);
-
-                diskBackingFileBaseName = new 
DatastoreFile(volume.getPath()).getFileBaseName();
-            } else {
-                ManagedObjectReference morDs = 
HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, 
volume.getDataStore().getUuid());
-                DatastoreMO dsMo = new DatastoreMO(context, morDs);
-
-                dsName = dsMo.getName();
+        Pair<String, String> dsNameAndFileName = getVMDiskInfo(volumePath, 
isManaged, iScsiName, datastoreUUID, hyperHost, context);
+        String dsName = dsNameAndFileName.first();
+        String diskBackingFileBaseName = dsNameAndFileName.second();
 
-                diskBackingFileBaseName = volume.getPath();
-            }
-
-            VirtualMachineDiskInfo diskInfo = 
diskInfoBuilder.getDiskInfoByBackingFileBaseName(diskBackingFileBaseName, 
dsName);
-            if (diskInfo != null) {
-                s_logger.info("Found existing disk info from volume path: " + 
volume.getPath());
-                return diskInfo;
-            } else {
-                String chainInfo = volume.getChainInfo();
-                if (chainInfo != null) {
-                    VirtualMachineDiskInfo infoInChain = 
_gson.fromJson(chainInfo, VirtualMachineDiskInfo.class);
-                    if (infoInChain != null) {
-                        String[] disks = infoInChain.getDiskChain();
-                        if (disks.length > 0) {
-                            for (String diskPath : disks) {
-                                DatastoreFile file = new 
DatastoreFile(diskPath);
-                                diskInfo = 
diskInfoBuilder.getDiskInfoByBackingFileBaseName(file.getFileBaseName(), 
dsName);
-                                if (diskInfo != null) {
-                                    s_logger.info("Found existing disk from 
chain info: " + diskPath);
-                                    return diskInfo;
-                                }
-                            }
-                        }
-
-                        if (diskInfo == null) {
-                            diskInfo = 
diskInfoBuilder.getDiskInfoByDeviceBusName(infoInChain.getDiskDeviceBusName());
+        VirtualMachineDiskInfo diskInfo = 
diskInfoBuilder.getDiskInfoByBackingFileBaseName(diskBackingFileBaseName, 
dsName);
+        if (diskInfo != null) {
+            s_logger.info("Found existing disk info from volume path: " + 
volumePath);
+            return diskInfo;
+        } else {
+            if (chainInfo != null) {
+                VirtualMachineDiskInfo infoInChain = _gson.fromJson(chainInfo, 
VirtualMachineDiskInfo.class);
+                if (infoInChain != null) {
+                    String[] disks = infoInChain.getDiskChain();
+                    if (disks.length > 0) {
+                        for (String diskPath : disks) {
+                            DatastoreFile file = new DatastoreFile(diskPath);
+                            diskInfo = 
diskInfoBuilder.getDiskInfoByBackingFileBaseName(file.getFileBaseName(), 
dsName);
                             if (diskInfo != null) {
-                                s_logger.info("Found existing disk from from 
chain device bus information: " + infoInChain.getDiskDeviceBusName());
+                                s_logger.info("Found existing disk from chain 
info: " + diskPath);
                                 return diskInfo;
                             }
                         }
                     }
+
+                    if (diskInfo == null) {
+                        diskInfo = 
diskInfoBuilder.getDiskInfoByDeviceBusName(infoInChain.getDiskDeviceBusName());
+                        if (diskInfo != null) {
+                            s_logger.info("Found existing disk from from chain 
device bus information: " + infoInChain.getDiskDeviceBusName());
+                            return diskInfo;
+                        }
+                    }
                 }
             }
         }
-
         return null;
     }
 
+    private Pair<String, String> getVMDiskInfo(String volumePath, boolean 
isManaged, String iScsiName, String datastoreUUID,
+                                               VmwareHypervisorHost hyperHost, 
VmwareContext context) throws Exception {
+        String dsName = null;
+        String diskBackingFileBaseName = null;
+
+        if (isManaged) {
+            // if the storage is managed, iScsiName should not be null
+            dsName = VmwareResource.getDatastoreName(iScsiName);
+            diskBackingFileBaseName = new 
DatastoreFile(volumePath).getFileBaseName();
+        } else {
+            ManagedObjectReference morDs = 
HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, 
datastoreUUID);
+            DatastoreMO dsMo = new DatastoreMO(context, morDs);
+            dsName = dsMo.getName();
+            diskBackingFileBaseName = volumePath;
+        }
+
+        return new Pair<>(dsName, diskBackingFileBaseName);
+    }
+
+    private VirtualMachineDiskInfo 
getMatchingExistingDisk(VirtualMachineDiskInfoBuilder diskInfoBuilder, DiskTO 
vol, VmwareHypervisorHost hyperHost, VmwareContext context)
+            throws Exception {
+        if (diskInfoBuilder != null) {
+            VolumeObjectTO volume = (VolumeObjectTO) vol.getData();
+            String chainInfo = volume.getChainInfo();
+            Map<String, String> details = vol.getDetails();
+            boolean isManaged = details != null && 
Boolean.parseBoolean(details.get(DiskTO.MANAGED));
+            String iScsiName = details.get(DiskTO.IQN);
+            String datastoreUUID = volume.getDataStore().getUuid();
+
+            return getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, 
volume.getPath(), chainInfo, isManaged, iScsiName, datastoreUUID, hyperHost, 
context);
+        } else {
+            return null;
+        }
+    }
+
     private String getDiskController(VirtualMachineMO vmMo, 
VirtualMachineDiskInfo matchingExistingDisk, DiskTO vol, Pair<String, String> 
controllerInfo, boolean deployAsIs) throws Exception {
         DiskControllerType controllerType = DiskControllerType.none;
         if (deployAsIs && matchingExistingDisk != null) {
@@ -4791,7 +4865,9 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
     // OfflineVmwareMigration: refactor to be able to handle a detached volume
     private Answer execute(MigrateVolumeCommand cmd) {
         String volumePath = cmd.getVolumePath();
+        String chainInfo = cmd.getChainInfo();
         StorageFilerTO poolTo = cmd.getPool();
+        VolumeObjectTO volumeObjectTO = (VolumeObjectTO)cmd.getSrcData();
 
         if (s_logger.isInfoEnabled()) {
             s_logger.info("Executing resource MigrateVolumeCommand: " + 
_gson.toJson(cmd));
@@ -4838,6 +4914,22 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
             }
 
             DatastoreMO targetDsMo = new 
DatastoreMO(srcHyperHost.getContext(), morDs);
+            if (cmd.getContextParam(DiskTO.PROTOCOL_TYPE) != null && 
cmd.getContextParam(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase("DatastoreCluster")) 
{
+                VmwareContext context = getServiceContext();
+                VmwareHypervisorHost hyperHost = getHyperHost(context);
+                VirtualMachineDiskInfoBuilder diskInfoBuilder = 
vmMo.getDiskInfoBuilder();
+                VirtualMachineDiskInfo matchingExistingDisk = 
getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, volumePath, 
chainInfo, false, null, poolTo.getUuid(), hyperHost, context);
+                if (diskInfoBuilder != null && matchingExistingDisk != null) {
+                    String[] diskChain = matchingExistingDisk.getDiskChain();
+                    DatastoreFile file = new DatastoreFile(diskChain[0]);
+                    if (!file.getFileBaseName().equalsIgnoreCase(volumePath)) {
+                        if (s_logger.isInfoEnabled())
+                            s_logger.info("Detected disk-chain top file change 
on volume: " + volumePath + " -> " + file.getFileBaseName());
+                        volumePath = file.getFileBaseName();
+                    }
+                }
+            }
+
             String fullVolumePath = 
VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(targetDsMo, 
vmName, volumePath + VMDK_EXTENSION);
             Pair<VirtualDisk, String> diskInfo = getVirtualDiskInfo(vmMo, 
appendFileType(volumePath, VMDK_EXTENSION));
             String vmdkAbsFile = getAbsoluteVmdkFile(diskInfo.first());
@@ -4892,7 +4984,7 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
                     }
             }
             VirtualMachineDiskInfoBuilder diskInfoBuilder = 
vmMo.getDiskInfoBuilder();
-            String chainInfo = 
_gson.toJson(diskInfoBuilder.getDiskInfoByBackingFileBaseName(volumePath, 
targetDsMo.getName()));
+            chainInfo = 
_gson.toJson(diskInfoBuilder.getDiskInfoByBackingFileBaseName(volumePath, 
targetDsMo.getName()));
             MigrateVolumeAnswer answer = new MigrateVolumeAnswer(cmd, true, 
null, volumePath);
             answer.setVolumeChainInfo(chainInfo);
             return answer;
diff --git 
a/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
 
b/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
index 04111bc..9c41885 100644
--- 
a/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
+++ 
b/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
@@ -26,6 +26,8 @@ import java.util.Map;
 
 import javax.inject.Inject;
 
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.storage.Storage;
 import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
@@ -247,7 +249,10 @@ public class VmwareStorageMotionStrategy implements 
DataMotionStrategy {
                 , vm != null ? vm.getInstanceName() : null
                 , sourcePool
                 , targetPool
-                , hostIdForVmAndHostGuidInTargetCluster.second());
+                , hostIdForVmAndHostGuidInTargetCluster.second(), 
((VolumeObjectTO) srcData.getTO()).getChainInfo());
+        if (sourcePool.getParent() != 0) {
+            cmd.setContextParam(DiskTO.PROTOCOL_TYPE, 
Storage.StoragePoolType.DatastoreCluster.toString());
+        }
         Answer answer;
         if (hostId != null) {
             answer = agentMgr.easySend(hostId, cmd);
diff --git 
a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
 
b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
index 9326946..fff15fd 100644
--- 
a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
+++ 
b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
@@ -26,6 +26,8 @@ import java.util.UUID;
 
 import javax.inject.Inject;
 
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.storage.VolumeVO;
 import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
@@ -408,7 +410,10 @@ public class CloudStackPrimaryDataStoreDriverImpl 
implements PrimaryDataStoreDri
 
         ResizeVolumeCommand resizeCmd =
                 new ResizeVolumeCommand(vol.getPath(), new 
StorageFilerTO(pool), vol.getSize(), resizeParameter.newSize, 
resizeParameter.shrinkOk,
-                        resizeParameter.instanceName);
+                        resizeParameter.instanceName, vol.getChainInfo());
+        if (pool.getParent() != 0) {
+            resizeCmd.setContextParam(DiskTO.PROTOCOL_TYPE, 
Storage.StoragePoolType.DatastoreCluster.toString());
+        }
         CreateCmdResult result = new CreateCmdResult(null, null);
         try {
             ResizeVolumeAnswer answer = (ResizeVolumeAnswer) 
storageMgr.sendToPool(pool, resizeParameter.hosts, resizeCmd);
@@ -418,6 +423,8 @@ public class CloudStackPrimaryDataStoreDriverImpl 
implements PrimaryDataStoreDri
 
                 vol.setSize(finalSize);
                 vol.update();
+
+                updateVolumePathDetails(vol, answer);
             } else if (answer != null) {
                 result.setResult(answer.getDetails());
             } else {
@@ -433,6 +440,31 @@ public class CloudStackPrimaryDataStoreDriverImpl 
implements PrimaryDataStoreDri
         callback.complete(result);
     }
 
+    private void updateVolumePathDetails(VolumeObject vol, ResizeVolumeAnswer 
answer) {
+        VolumeVO volumeVO = volumeDao.findById(vol.getId());
+        String datastoreUUID = answer.getContextParam("datastoreUUID");
+        if (datastoreUUID != null) {
+            StoragePoolVO storagePoolVO = 
primaryStoreDao.findByUuid(datastoreUUID);
+            if (storagePoolVO != null) {
+                volumeVO.setPoolId(storagePoolVO.getId());
+            } else {
+                s_logger.warn(String.format("Unable to find datastore %s while 
updating the new datastore of the volume %d", datastoreUUID, vol.getId()));
+            }
+        }
+
+        String volumePath = answer.getContextParam("volumePath");
+        if (volumePath != null) {
+            volumeVO.setPath(volumePath);
+        }
+
+        String chainInfo = answer.getContextParam("chainInfo");
+        if (chainInfo != null) {
+            volumeVO.setChainInfo(chainInfo);
+        }
+
+        volumeDao.update(volumeVO.getId(), volumeVO);
+    }
+
     @Override
     public void handleQualityOfServiceForVolumeMigration(VolumeInfo 
volumeInfo, QualityOfServiceState qualityOfServiceState) {}
 

Reply via email to