problem
Live migrating a VM with storage to a SharedMountPoint target pool fails with:
LibvirtException: Operation not supported: pre-creation of storage target for incremental storage migration of disk 'sda' is not supported
The failure affects both THIN and FAT provisioned volumes on SharedMountPoint destinations, caused by two separate bugs in StorageSystemDataMotionStrategy:
Bug 1: getVolumeBackingFile incorrectly returns non-null for FAT provisioned volumes
getVolumeBackingFile() determines whether a volume has a QCOW2 backing chain by looking up the template in template_spool_ref, not by inspecting the actual disk. For FAT provisioned volumes, template_id is still set in the volumes table and the template is still registered in template_spool_ref, so the method returns the template's install path even though the actual QCOW2 disk on disk has no backing file at all. This causes FAT volumes to be incorrectly classified as linked clones.
Bug 2: decideMigrationTypeAndCopyTemplateIfNeeded treats SharedMountPoint the same as NFS
supportStoragePoolType() always includes SharedMountPoint in its accepted types alongside NetworkFilesystem. So any volume with a non-null srcVolumeBackingFile (THIN) destined for a SharedMountPoint pool is routed to LinkedClone migration. This sets the libvirt flag VIR_MIGRATE_NON_SHARED_INC (128), which requires QEMU to pre-create the destination disk with a backing chain. QEMU does not support this pre-creation step on SharedMountPoint storage, causing the migration to fail. NFS works because QEMU can freely create QCOW2 files with backing chains on a flat filesystem.
Together, both bugs result in migrateNonSharedInc = true for all volume types on SharedMountPoint destinations, always triggering the libvirt failure.
The bug does not trigger if template_id is set to null in the volumes table, because getVolumeBackingFile() returns null in that case, causing the code to fall through to FullClone which uses VIR_MIGRATE_NON_SHARED_DISK (64) — a flag QEMU supports on SharedMountPoint storage.
versions
4.22.0/4.22.1
The steps to reproduce the bug
- Set up a CloudStack KVM environment with a SharedMountPoint primary storage pool.
- Deploy a VM from a standard template — reproduce with both THIN and FAT provisioned disk offerings.
- Add a second SharedMountPoint primary storage pool as the migration target.
- Trigger a live migration of the VM with storage to the target pool (migrateVirtualMachineWithVolume).
- Observe the migration fails with the error above for both THIN and FAT provisioned volumes.
Workaround: Set template_id = NULL in the volumes table for the affected volumes before migrating. This forces FullClone migration and avoids the libvirt flag.
What to do about it?
Two 1-line fixes, both in StorageSystemDataMotionStrategy.java:
Fix 1: getVolumeBackingFile: skip FAT volumes (covers FAT on all storage types)
if (srcVolumeInfo.getHypervisorType() == HypervisorType.KVM &&
srcVolumeInfo.getTemplateId() != null && srcVolumeInfo.getPoolId() != null &&
+ srcVolumeInfo.getProvisioningType() != Storage.ProvisioningType.FAT) {
Fix 2: decideMigrationTypeAndCopyTemplateIfNeeded: exclude SharedMountPoint (covers THIN on SharedMountPoint)
if (StringUtils.isNotBlank(srcVolumeBackingFile) &&
supportStoragePoolType(destStoragePool.getPoolType(), StoragePoolType.Filesystem) &&
+ destStoragePool.getPoolType() != StoragePoolType.SharedMountPoint &&
srcVolumeInfo.getTemplateId() != null &&
Objects.nonNull(vmTemplate) &&
!Arrays.asList(KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME, VM_IMPORT_DEFAULT_TEMPLATE_NAME)
.contains(vmTemplate.getName())) {
Both fixes force the affected paths to return FullClone → VIR_MIGRATE_NON_SHARED_DISK, which QEMU supports on SharedMountPoint storage. The template pre-copy step is also correctly skipped in both cases.
problem
Live migrating a VM with storage to a SharedMountPoint target pool fails with:
LibvirtException: Operation not supported: pre-creation of storage target for incremental storage migration of disk 'sda' is not supportedThe failure affects both THIN and FAT provisioned volumes on SharedMountPoint destinations, caused by two separate bugs in StorageSystemDataMotionStrategy:
Bug 1: getVolumeBackingFile incorrectly returns non-null for FAT provisioned volumes
getVolumeBackingFile() determines whether a volume has a QCOW2 backing chain by looking up the template in template_spool_ref, not by inspecting the actual disk. For FAT provisioned volumes, template_id is still set in the volumes table and the template is still registered in template_spool_ref, so the method returns the template's install path even though the actual QCOW2 disk on disk has no backing file at all. This causes FAT volumes to be incorrectly classified as linked clones.
Bug 2: decideMigrationTypeAndCopyTemplateIfNeeded treats SharedMountPoint the same as NFS
supportStoragePoolType() always includes SharedMountPoint in its accepted types alongside NetworkFilesystem. So any volume with a non-null srcVolumeBackingFile (THIN) destined for a SharedMountPoint pool is routed to LinkedClone migration. This sets the libvirt flag VIR_MIGRATE_NON_SHARED_INC (128), which requires QEMU to pre-create the destination disk with a backing chain. QEMU does not support this pre-creation step on SharedMountPoint storage, causing the migration to fail. NFS works because QEMU can freely create QCOW2 files with backing chains on a flat filesystem.
Together, both bugs result in migrateNonSharedInc = true for all volume types on SharedMountPoint destinations, always triggering the libvirt failure.
The bug does not trigger if template_id is set to null in the volumes table, because getVolumeBackingFile() returns null in that case, causing the code to fall through to FullClone which uses VIR_MIGRATE_NON_SHARED_DISK (64) — a flag QEMU supports on SharedMountPoint storage.
versions
4.22.0/4.22.1
The steps to reproduce the bug
Workaround: Set template_id = NULL in the volumes table for the affected volumes before migrating. This forces FullClone migration and avoids the libvirt flag.
What to do about it?
Two 1-line fixes, both in StorageSystemDataMotionStrategy.java:
Fix 1: getVolumeBackingFile: skip FAT volumes (covers FAT on all storage types)
Fix 2: decideMigrationTypeAndCopyTemplateIfNeeded: exclude SharedMountPoint (covers THIN on SharedMountPoint)
Both fixes force the affected paths to return FullClone → VIR_MIGRATE_NON_SHARED_DISK, which QEMU supports on SharedMountPoint storage. The template pre-copy step is also correctly skipped in both cases.