From 437f77c97e579477291248bee72773a88af9f44d Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 24 Mar 2026 15:07:36 -0400 Subject: [PATCH] support live vm migration between clvm -> clvm-ng (vice-versa), nfs -> clvm (vice-versa) and nfs->clvm-ng (vice-versa) --- .../com/cloud/agent/api/MigrateCommand.java | 9 ++++ .../StorageSystemDataMotionStrategy.java | 1 + .../wrapper/LibvirtMigrateCommandWrapper.java | 53 ++++++++++--------- .../kvm/storage/KVMStorageProcessor.java | 36 ++++++++++++- .../kvm/storage/LibvirtStorageAdaptor.java | 3 ++ 5 files changed, 75 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/com/cloud/agent/api/MigrateCommand.java b/core/src/main/java/com/cloud/agent/api/MigrateCommand.java index d9fb447d655..a960e6e33a1 100644 --- a/core/src/main/java/com/cloud/agent/api/MigrateCommand.java +++ b/core/src/main/java/com/cloud/agent/api/MigrateCommand.java @@ -185,6 +185,7 @@ public class MigrateCommand extends Command { private final String sourceText; private final String backingStoreText; private boolean isSourceDiskOnStorageFileSystem; + private Storage.StoragePoolType sourcePoolType; private Storage.StoragePoolType destPoolType; public MigrateDiskInfo(final String serialNumber, final DiskType diskType, final DriverType driverType, final Source source, final String sourceText) { @@ -235,6 +236,14 @@ public class MigrateCommand extends Command { this.isSourceDiskOnStorageFileSystem = isDiskOnFileSystemStorage; } + public Storage.StoragePoolType getSourcePoolType() { + return sourcePoolType; + } + + public void setSourcePoolType(Storage.StoragePoolType sourcePoolType) { + this.sourcePoolType = sourcePoolType; + } + public Storage.StoragePoolType getDestPoolType() { return destPoolType; } 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 38ef8ddde2b..f991c8589d0 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 @@ -2121,6 +2121,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy { migrateDiskInfo.setSourceDiskOnStorageFileSystem(isStoragePoolTypeOfFile(sourceStoragePool)); migrateDiskInfoList.add(migrateDiskInfo); } + migrateDiskInfo.setSourcePoolType(sourceStoragePool.getPoolType()); migrateDiskInfo.setDestPoolType(destVolumeInfo.getStoragePoolType()); prepareDiskWithSecretConsumerDetail(vmTO, srcVolumeInfo, destVolumeInfo.getPath()); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java index 5783a71c4bd..d4b57c8f905 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java @@ -244,25 +244,6 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper worker = new MigrateKVMAsync(libvirtComputingResource, dm, dconn, xmlDesc, - effectiveMigrateStorage, migrateNonSharedInc, + migrateStorage, migrateNonSharedInc, command.isAutoConvergence(), vmName, command.getDestinationIp(), migrateDiskLabels); final Future migrateThread = executor.submit(worker); executor.shutdown(); @@ -827,11 +808,8 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper NFS/Local/CLVM_NG (QCOW2) + * - NFS/Local/CLVM_NG (QCOW2) -> CLVM (RAW) + * @param migrationOptions + * @param primaryStore + * @return + */ + private boolean useDestPoolFormat(MigrationOptions migrationOptions, PrimaryDataStoreTO primaryStore) { + boolean useDstPoolFormat = false; + if (migrationOptions != null && migrationOptions.getSrcPoolType() != null) { + StoragePoolType srcPoolType = migrationOptions.getSrcPoolType(); + StoragePoolType dstPoolType = primaryStore.getPoolType(); + + if (srcPoolType != dstPoolType) { + useDstPoolFormat = (srcPoolType == StoragePoolType.CLVM || dstPoolType == StoragePoolType.CLVM); + } + } + return useDstPoolFormat; + } + /** * XML to take disk-only snapshot of the VM.

* 1st parameter: snapshot's name;
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java index c85499e8b0b..b6dfa70d760 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java @@ -2609,6 +2609,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { Script lvcreate = new Script("lvcreate", Duration.millis(timeout), logger); lvcreate.add("-n", volumeUuid); lvcreate.add("-L", lvSize + "B"); + lvcreate.add("--yes"); lvcreate.add(vgName); String result = lvcreate.execute(); @@ -2686,6 +2687,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { Script lvcreate = new Script("lvcreate", Duration.millis(timeout), logger); lvcreate.add("-n", lvName); lvcreate.add("-L", lvSize + "B"); + lvcreate.add("--yes"); lvcreate.add(vgName); String result = lvcreate.execute(); if (result != null) { @@ -2757,6 +2759,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { Script lvcreate = new Script("lvcreate", Duration.millis(timeout), logger); lvcreate.add("-n", volumeName); lvcreate.add("-L", size + "B"); + lvcreate.add("--yes"); lvcreate.add(vgName); String result = lvcreate.execute();