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

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

commit cc1833cb71b554ed6d5b78db94cec2d8a608469d
Author: Harikrishna Patnala <[email protected]>
AuthorDate: Thu Sep 30 12:58:22 2021 +0530

    Fix resize volume and migrate volume to update volume path if DRS is 
applied on volume in datastore cluster
---
 .../agent/api/storage/MigrateVolumeCommand.java    |  14 +-
 .../agent/api/storage/ResizeVolumeCommand.java     |   8 +-
 .../api/agent/test/CheckNetworkAnswerTest.java     |   2 +-
 .../storage/motion/AncientDataMotionStrategy.java  |   9 +-
 .../motion/StorageSystemDataMotionStrategy.java    |   2 +-
 .../kvm/resource/LibvirtComputingResourceTest.java |  12 +-
 .../hypervisor/vmware/resource/VmwareResource.java | 211 +++++++++++++--------
 .../motion/VmwareStorageMotionStrategy.java        |   7 +-
 .../wrapper/xenbase/CitrixRequestWrapperTest.java  |   2 +-
 .../wrapper/xenbase/XenServer610WrapperTest.java   |   2 +-
 .../CloudStackPrimaryDataStoreDriverImpl.java      |  31 ++-
 .../driver/LinstorPrimaryDataStoreDriverImpl.java  |   2 +-
 12 files changed, 207 insertions(+), 95 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..b960e6d 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;
@@ -41,22 +42,23 @@ public class MigrateVolumeCommand extends Command {
     private Map<String, String> srcDetails;
     private Map<String, String> destDetails;
 
-    public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool 
pool, int timeout) {
+    public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool 
pool, int timeout, String chainInfo) {
         this.volumeId = volumeId;
         this.volumePath = volumePath;
         this.pool = new StorageFilerTO(pool);
+        this.chainInfo = chainInfo;
         this.setWait(timeout);
     }
 
-    public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool 
pool, String attachedVmName, Volume.Type volumeType, int timeout) {
-        this(volumeId,volumePath,pool,timeout);
+    public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool 
pool, String attachedVmName, Volume.Type volumeType, int timeout, String 
chainInfo) {
+        this(volumeId, volumePath, pool, timeout, chainInfo);
         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, 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 +136,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..161f064 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;
@@ -37,7 +38,7 @@ public class ResizeVolumeCommand extends Command {
     protected ResizeVolumeCommand() {
     }
 
-    public ResizeVolumeCommand(String path, StorageFilerTO pool, Long 
currentSize, Long newSize, boolean shrinkOk, String vmInstance) {
+    public ResizeVolumeCommand(String path, StorageFilerTO pool, Long 
currentSize, Long newSize, boolean shrinkOk, String vmInstance, String 
chainInfo) {
         this.path = path;
         this.pool = pool;
         this.currentSize = currentSize;
@@ -45,11 +46,12 @@ public class ResizeVolumeCommand extends Command {
         this.shrinkOk = shrinkOk;
         this.vmInstance = vmInstance;
         this.managed = false;
+        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);
+        this(path, pool, currentSize, newSize, shrinkOk, vmInstance, null);
 
         this.iScsiName = iScsiName;
         this.managed = isManaged;
@@ -81,6 +83,8 @@ public class ResizeVolumeCommand extends Command {
 
     public String get_iScsiName() {return iScsiName; }
 
+    public String getChainInfo() {return chainInfo; }
+
     /**
      * {@inheritDoc}
      */
diff --git 
a/core/src/test/java/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java
 
b/core/src/test/java/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java
index 8b25501..f554cb5 100644
--- 
a/core/src/test/java/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java
+++ 
b/core/src/test/java/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java
@@ -209,7 +209,7 @@ public class CheckNetworkAnswerTest {
         Long newSize = 4194304L;
         Long currentSize = 1048576L;
 
-        ResizeVolumeCommand rv = new ResizeVolumeCommand("dummydiskpath", new 
StorageFilerTO(dummypool), currentSize, newSize, false, "vmName");
+        ResizeVolumeCommand rv = new ResizeVolumeCommand("dummydiskpath", new 
StorageFilerTO(dummypool), currentSize, newSize, false, "vmName", null);
 
         @Test
         public void testExecuteInSequence() {
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/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
index aee1f75..99de054 100644
--- 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
+++ 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
@@ -740,7 +740,7 @@ public class StorageSystemDataMotionStrategy implements 
DataMotionStrategy {
         StoragePool destPool = 
(StoragePool)dataStoreMgr.getDataStore(destVolumeInfo.getDataStore().getId(), 
DataStoreRole.Primary);
 
         MigrateVolumeCommand command = new 
MigrateVolumeCommand(srcVolumeInfo.getId(), srcVolumeInfo.getPath(), destPool, 
srcVolumeInfo.getAttachedVmName(),
-                srcVolumeInfo.getVolumeType(), waitInterval);
+                srcVolumeInfo.getVolumeType(), waitInterval, null);
 
         Map<String, String> details = new HashMap<>();
 
diff --git 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
index 27399ea..1ef8a9e 100644
--- 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
+++ 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
@@ -4836,7 +4836,7 @@ public class LibvirtComputingResourceTest {
         final boolean shrinkOk = true;
         final String vmInstance = "Test";
 
-        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance);
+        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance, null);
 
         final KVMStoragePoolManager storagePoolMgr = 
Mockito.mock(KVMStoragePoolManager.class);
         final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class);
@@ -4889,7 +4889,7 @@ public class LibvirtComputingResourceTest {
         final boolean shrinkOk = false;
         final String vmInstance = "Test";
 
-        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance);
+        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance, null);
 
         final KVMStoragePoolManager storagePoolMgr = 
Mockito.mock(KVMStoragePoolManager.class);
         final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class);
@@ -4929,7 +4929,7 @@ public class LibvirtComputingResourceTest {
         final boolean shrinkOk = false;
         final String vmInstance = "Test";
 
-        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance);
+        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance, null);
 
         final LibvirtRequestWrapper wrapper = 
LibvirtRequestWrapper.getInstance();
         assertNotNull(wrapper);
@@ -4947,7 +4947,7 @@ public class LibvirtComputingResourceTest {
         final boolean shrinkOk = true;
         final String vmInstance = "Test";
 
-        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance);
+        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance, null);
 
         final KVMStoragePoolManager storagePoolMgr = 
Mockito.mock(KVMStoragePoolManager.class);
         final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class);
@@ -4976,7 +4976,7 @@ public class LibvirtComputingResourceTest {
         final boolean shrinkOk = false;
         final String vmInstance = "Test";
 
-        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance);
+        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance, null);
 
         final KVMStoragePoolManager storagePoolMgr = 
Mockito.mock(KVMStoragePoolManager.class);
         final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class);
@@ -5024,7 +5024,7 @@ public class LibvirtComputingResourceTest {
         final boolean shrinkOk = false;
         final String vmInstance = "Test";
 
-        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance);
+        final ResizeVolumeCommand command = new ResizeVolumeCommand(path, 
pool, currentSize, newSize, shrinkOk, vmInstance, null);
 
         final KVMStoragePoolManager storagePoolMgr = 
Mockito.mock(KVMStoragePoolManager.class);
         final KVMStoragePool storagePool = Mockito.mock(KVMStoragePool.class);
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..0fd718f 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;
@@ -852,26 +856,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,6 +878,53 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
                 _storageProcessor.expandDatastore(hostDatastoreSystem, dsMo);
             }
 
+            boolean datastoreChangeObserved = false;
+            boolean volumePathChangeObserved = false;
+
+            if (cmd.getContextParam(DiskTO.PROTOCOL_TYPE) != null && 
cmd.getContextParam(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase("DatastoreCluster")) 
{
+                VirtualMachineDiskInfoBuilder diskInfoBuilder = 
vmMo.getDiskInfoBuilder();
+                VirtualMachineDiskInfo matchingExistingDisk = 
getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, path, chainInfo, 
managed, cmd.get_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();
+                        volumePathChangeObserved = true;
+                        chainInfo = _gson.toJson(matchingExistingDisk);
+                    }
+                    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));
+                            datastoreChangeObserved = true;
+                            poolUUID = actualPoolUuid;
+                            chainInfo = _gson.toJson(matchingExistingDisk);
+                        }
+                    }
+                }
+            }
+
+            // 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 (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());
@@ -922,7 +955,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("datastoreName", 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);
 
@@ -1473,7 +1516,7 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
             // restore allocation mask in case of exceptions
             String nicMasksStr = 
vmMo.getCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK);
             int nicMasks = Integer.parseInt(nicMasksStr);
-            nicMasks &= ~(1 << nicIndex);
+            nicMasks &= ~(1 <<   nicIndex);
             vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, 
String.valueOf(nicMasks));
 
             throw e;
@@ -3254,70 +3297,72 @@ 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 {
+        String dsName = null;
+        String diskBackingFileBaseName = null;
 
-    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();
-
-                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 (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;
+        }
 
-                        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 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 +4836,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 +4885,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 +4955,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/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRequestWrapperTest.java
 
b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRequestWrapperTest.java
index 219c76a..9d18e73 100755
--- 
a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRequestWrapperTest.java
+++ 
b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRequestWrapperTest.java
@@ -430,7 +430,7 @@ public class CitrixRequestWrapperTest {
     public void testResizeVolumeCommand() {
         final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class);
 
-        final ResizeVolumeCommand resizeCommand = new 
ResizeVolumeCommand("Test", pool, 1l, 3l, false, "Tests-1");
+        final ResizeVolumeCommand resizeCommand = new 
ResizeVolumeCommand("Test", pool, 1l, 3l, false, "Tests-1", null);
 
         final CitrixRequestWrapper wrapper = 
CitrixRequestWrapper.getInstance();
         assertNotNull(wrapper);
diff --git 
a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java
 
b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java
index 8fa68f5..e1368d3 100644
--- 
a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java
+++ 
b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java
@@ -486,7 +486,7 @@ public class XenServer610WrapperTest {
         final Map<String, String> other = new HashMap<String, String>();
         other.put("live", "true");
 
-        final MigrateVolumeCommand createStorageCommand = new 
MigrateVolumeCommand(volumeId, volumePath, pool, timeout);
+        final MigrateVolumeCommand createStorageCommand = new 
MigrateVolumeCommand(volumeId, volumePath, pool, timeout, null);
 
         final CitrixRequestWrapper wrapper = 
CitrixRequestWrapper.getInstance();
         assertNotNull(wrapper);
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..1f8d376 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,30 @@ public class CloudStackPrimaryDataStoreDriverImpl 
implements PrimaryDataStoreDri
 
                 vol.setSize(finalSize);
                 vol.update();
+
+                VolumeVO volumeVO = volumeDao.findById(vol.getId());
+                String datastoreName = answer.getContextParam("datastoreName");
+                if (datastoreName != null) {
+                    StoragePoolVO storagePoolVO = 
primaryStoreDao.findByUuid(datastoreName);
+                    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", datastoreName, 
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);
+
             } else if (answer != null) {
                 result.setResult(answer.getDetails());
             } else {
diff --git 
a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java
 
b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java
index 19cf297..3208603 100644
--- 
a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java
+++ 
b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java
@@ -617,7 +617,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements 
PrimaryDataStoreDriver
 
         ResizeVolumeCommand resizeCmd =
             new ResizeVolumeCommand(vol.getPath(), new StorageFilerTO(pool), 
oldSize, resizeParameter.newSize, resizeParameter.shrinkOk,
-                resizeParameter.instanceName);
+                resizeParameter.instanceName, null);
         CreateCmdResult result = new CreateCmdResult(null, null);
         try {
             ResizeVolumeAnswer answer = (ResizeVolumeAnswer) 
_storageMgr.sendToPool(pool, resizeParameter.hosts, resizeCmd);

Reply via email to