From d7862626be058118209e723858cf697f57fe1a25 Mon Sep 17 00:00:00 2001 From: vanquyen020920 Date: Tue, 2 Jun 2026 21:20:33 +0700 Subject: [PATCH 1/3] Allow KVM live volume migration flow --- .../main/java/com/cloud/storage/VolumeApiServiceImpl.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 6872d2070d66..e76f1ec3f3b0 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -3531,9 +3531,8 @@ public Volume migrateVolume(MigrateVolumeCmd cmd) { StoragePoolVO destinationStoragePoolVo = _storagePoolDao.findById(storagePoolId); if (isSourceOrDestNotOnStorPool(srcStoragePoolVO, destinationStoragePoolVo)) { - throw new InvalidParameterValueException("KVM does not support volume live migration due to the limited possibility to refresh VM XML domain. " + - "Therefore, to live migrate a volume between storage pools, one must migrate the VM to a different host as well to force the VM XML domain update. " + - "Use 'migrateVirtualMachineWithVolumes' instead."); + logger.debug("Allowing KVM live volume migration between different storage pools. VM [{}], volume [{}], source pool [{}], destination pool [{}].", + vm, vol, srcStoragePoolVO, destinationStoragePoolVo); } srcAndDestOnStorPool = isSourceAndDestOnStorPool(srcStoragePoolVO, destinationStoragePoolVo); } From d5070af467b856637db0fadef79150ff4c6dce3e Mon Sep 17 00:00:00 2001 From: vanquyen020920 Date: Tue, 2 Jun 2026 21:25:07 +0700 Subject: [PATCH 2/3] Pass source and destination data to migrate volume command --- .../cloudstack/storage/motion/AncientDataMotionStrategy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8145158dfa40..018dc87b6394 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 @@ -545,7 +545,7 @@ protected Answer migrateVolumeToPool(DataObject srcData, DataObject destData) { 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, volume.getChainInfo()); + MigrateVolumeCommand command = new MigrateVolumeCommand(srcData.getTO(), destData.getTO(), null, null, waitInterval); if (srcPool.getParent() != 0) { command.setContextParam(DiskTO.PROTOCOL_TYPE, Storage.StoragePoolType.DatastoreCluster.toString()); } From a6ec38ac5eaf8254330ad43042c9ef5198d22c22 Mon Sep 17 00:00:00 2001 From: vanquyen020920 Date: Tue, 2 Jun 2026 21:28:51 +0700 Subject: [PATCH 3/3] Avoid null src data in KVM migrate volume wrapper --- .../resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java index 85574c447417..263d0980345a 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java @@ -75,6 +75,11 @@ public class LibvirtMigrateVolumeCommandWrapper extends CommandWrapper