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

weizhouapache 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 4d54125bb62 CLVM: Fix volume mapping and disk path matching for 
storage migration (#13468)
4d54125bb62 is described below

commit 4d54125bb62de999cba3b3b05622a391fc564985
Author: Pearl Dsilva <[email protected]>
AuthorDate: Fri Jul 10 08:32:36 2026 -0400

    CLVM: Fix volume mapping and disk path matching for storage migration 
(#13468)
---
 .../com/cloud/vm/VirtualMachineManagerImpl.java    |  3 +-
 .../storage/motion/AncientDataMotionStrategy.java  | 21 ++++++++++++
 .../storage/volume/VolumeServiceImpl.java          |  6 ++++
 .../storage/volume/VolumeServiceImplClvmTest.java  | 39 ++++++++++++++++++++--
 .../kvm/resource/LibvirtComputingResource.java     |  2 +-
 .../kvm/storage/KVMStorageProcessor.java           |  6 +++-
 .../CloudStackPrimaryDataStoreDriverImpl.java      | 14 +++-----
 7 files changed, 76 insertions(+), 15 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 a232bdd05da..d5f7937a463 100755
--- 
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++ 
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -3543,7 +3543,8 @@ public class VirtualMachineManagerImpl extends 
ManagerBase implements VirtualMac
     protected boolean shouldMapVolume(VirtualMachineProfile profile, 
StoragePoolVO currentPool) {
         boolean isManaged = currentPool.isManaged();
         boolean isNotKvm = HypervisorType.KVM != profile.getHypervisorType();
-        return isNotKvm || isManaged;
+        boolean isClvm = 
ClvmPoolManager.isClvmPoolType(currentPool.getPoolType());
+        return isNotKvm || isManaged || isClvm;
     }
 
     /**
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 dd54dd58005..bbf775de27a 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
@@ -445,6 +445,9 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
                     answer = new Answer(cmd, false, errMsg);
                 } else {
                     answer = ep.sendMessage(cmd);
+                    if (answer != null && answer.getResult()) {
+                        setClvmLockHostIdIfApplicable(destData, ep);
+                    }
                 }
                 return answer;
             }
@@ -500,6 +503,7 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
                     imageStore.delete(objOnImageStore);
                     return answer;
                 }
+                setClvmLockHostIdIfApplicable(destData, ep);
             } catch (Exception e) {
                 if (imageStore.exists(objOnImageStore)) {
                     objOnImageStore.processEvent(Event.OperationFailed);
@@ -523,6 +527,9 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
                 answer = new Answer(cmd, false, errMsg);
             } else {
                 answer = ep.sendMessage(cmd);
+                if (answer != null && answer.getResult()) {
+                    setClvmLockHostIdIfApplicable(destData, ep);
+                }
             }
             // delete volume on cache store
             if (cacheData != null) {
@@ -532,6 +539,17 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
         }
     }
 
+    private void setClvmLockHostIdIfApplicable(DataObject destData, EndPoint 
ep) {
+        if (ep == null || !(destData instanceof VolumeInfo)) {
+            return;
+        }
+        VolumeInfo destVolume = (VolumeInfo) destData;
+        if (ClvmPoolManager.isClvmPoolType(destVolume.getStoragePoolType())) {
+            clvmPoolManager.setClvmLockHostId(destVolume.getId(), ep.getId());
+            logger.debug("Set CLVM lock host {} for migrated volume {}", 
ep.getId(), destVolume.getUuid());
+        }
+    }
+
     private boolean canBypassSecondaryStorage(DataObject srcData, DataObject 
destData) {
         if (srcData instanceof VolumeInfo) {
             if (((VolumeInfo)srcData).isDirectDownload()) {
@@ -650,6 +668,9 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
             if (destPool.getPoolType() == StoragePoolType.CLVM) {
                 volumeVo.setFormat(ImageFormat.RAW);
             }
+            if (ClvmPoolManager.isClvmPoolType(destPool.getPoolType())) {
+                clvmPoolManager.setClvmLockHostId(volume.getId(), ep.getId());
+            }
             // For SMB, pool credentials are also stored in the uri query 
string.  We trim the query string
             // part  here to make sure the credentials do not get stored in 
the db unencrypted.
             String folder = destPool.getPath();
diff --git 
a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
 
b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
index 8a0f93fe5fc..f8d9cab56f7 100644
--- 
a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
+++ 
b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
@@ -3118,6 +3118,12 @@ public class VolumeServiceImpl implements VolumeService {
         }
 
         if (volumePoolId == null || !volumePoolId.equals(vmPoolId)) {
+            Long volumeLockHostId = findVolumeLockHost(volumeToAttach);
+            if (volumeLockHostId != null && vmHostId != null && 
!volumeLockHostId.equals(vmHostId)) {
+                logger.info("CLVM cross-pool lock transfer required: Volume {} 
on pool {} lock is on host {} but VM is on host {}",
+                        volumeToAttach.getUuid(), volumePoolId, 
volumeLockHostId, vmHostId);
+                return true;
+            }
             return false;
         }
 
diff --git 
a/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceImplClvmTest.java
 
b/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceImplClvmTest.java
index 38af2a7550b..8d355263a6c 100644
--- 
a/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceImplClvmTest.java
+++ 
b/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceImplClvmTest.java
@@ -167,14 +167,49 @@ public class VolumeServiceImplClvmTest {
     }
 
     @Test
-    public void testIsLockTransferRequired_DifferentPools() {
+    public void 
testIsLockTransferRequired_DifferentPools_LockOnDifferentHost() {
+        
when(volumeService.findVolumeLockHost(volumeInfoMock)).thenReturn(HOST_ID_2);
+
+        assertTrue(volumeService.isLockTransferRequired(
+                volumeInfoMock, StoragePoolType.CLVM, StoragePoolType.CLVM,
+                POOL_ID_1, POOL_ID_2, HOST_ID_1));
+    }
+
+    @Test
+    public void testIsLockTransferRequired_DifferentPools_LockOnSameHost() {
+        
when(volumeService.findVolumeLockHost(volumeInfoMock)).thenReturn(HOST_ID_1);
+
+        assertFalse(volumeService.isLockTransferRequired(
+                volumeInfoMock, StoragePoolType.CLVM, StoragePoolType.CLVM,
+                POOL_ID_1, POOL_ID_2, HOST_ID_1));
+    }
+
+    @Test
+    public void testIsLockTransferRequired_DifferentPools_NoLockHost() {
+        
when(volumeService.findVolumeLockHost(volumeInfoMock)).thenReturn(null);
+
         assertFalse(volumeService.isLockTransferRequired(
                 volumeInfoMock, StoragePoolType.CLVM, StoragePoolType.CLVM,
                 POOL_ID_1, POOL_ID_2, HOST_ID_1));
     }
 
     @Test
-    public void testIsLockTransferRequired_NullPoolIds() {
+    public void testIsLockTransferRequired_NullPoolIds_LockOnDifferentHost() {
+        
when(volumeService.findVolumeLockHost(volumeInfoMock)).thenReturn(HOST_ID_2);
+
+        assertTrue(volumeService.isLockTransferRequired(
+                volumeInfoMock, StoragePoolType.CLVM, StoragePoolType.CLVM,
+                null, POOL_ID_1, HOST_ID_1));
+
+        assertTrue(volumeService.isLockTransferRequired(
+                volumeInfoMock, StoragePoolType.CLVM, StoragePoolType.CLVM,
+                POOL_ID_1, null, HOST_ID_1));
+    }
+
+    @Test
+    public void testIsLockTransferRequired_NullPoolIds_NoLockHost() {
+        
when(volumeService.findVolumeLockHost(volumeInfoMock)).thenReturn(null);
+
         assertFalse(volumeService.isLockTransferRequired(
                 volumeInfoMock, StoragePoolType.CLVM, StoragePoolType.CLVM,
                 null, POOL_ID_1, HOST_ID_1));
diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 41716881fa4..acc4a878dea 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -7038,7 +7038,7 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
                         continue;
                     }
                     VolumeObjectTO volumeTO = (VolumeObjectTO) 
diskTO.getData();
-                    if (!diskPath.equals(volumeTO.getPath()) && 
!diskPath.equals(diskTO.getPath())) {
+                    if 
(!diskPath.substring(diskPath.lastIndexOf(File.separator) + 
1).equals(volumeTO.getPath())) {
                         continue;
                     }
                     DataStoreTO dataStore = volumeTO.getDataStore();
diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
index 009e1decee2..0f5c2f0913b 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
@@ -570,7 +570,11 @@ public class KVMStorageProcessor implements 
StorageProcessor {
 
             final VolumeObjectTO newVol = new VolumeObjectTO();
             newVol.setPath(vol.getName());
-            newVol.setSize(volume.getSize());
+            if (StoragePoolType.CLVM_NG.equals(primaryStore.getPoolType()) && 
vol != null && vol.getVirtualSize() > 0) {
+                newVol.setSize(vol.getVirtualSize());
+            } else {
+                newVol.setSize(volume.getSize());
+            }
             if (vol.getQemuEncryptFormat() != null) {
                 newVol.setEncryptFormat(vol.getQemuEncryptFormat().toString());
             }
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 3e9fa8a5438..a12836cdb96 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
@@ -436,17 +436,11 @@ public class CloudStackPrimaryDataStoreDriverImpl 
implements PrimaryDataStoreDri
         CommandResult result = new CommandResult();
         try {
             EndPoint ep = null;
-            VolumeInfo volumeInfo = 
volFactory.getVolume(snapshot.getVolumeId(), DataStoreRole.Primary);
-
-            StoragePoolVO storagePool = 
primaryStoreDao.findById(volumeInfo.getPoolId());
-            if (storagePool != null && storagePool.getPoolType() == 
StoragePoolType.CLVM) {
-                ep = epSelector.select(volumeInfo);
+            if (snapshotOnPrimaryStore != null) {
+                ep = epSelector.select(snapshotOnPrimaryStore);
             } else {
-                if (snapshotOnPrimaryStore != null) {
-                    ep = epSelector.select(snapshotOnPrimaryStore);
-                } else {
-                    ep = epSelector.select(volumeInfo);
-                }
+                VolumeInfo volumeInfo = 
volFactory.getVolume(snapshot.getVolumeId(), DataStoreRole.Primary);
+                ep = epSelector.select(volumeInfo);
             }
 
             if ( ep == null ){

Reply via email to