From 77f48ddd9edc483f27a0a9fc8b78ed15d3b5df37 Mon Sep 17 00:00:00 2001 From: Pearl1594 Date: Thu, 22 Oct 2026 15:39:22 -0400 Subject: [PATCH] Add support for clvm incremental volume snaps --- .../kvm/storage/KVMStorageProcessor.java | 18 ++++++++++-------- .../storage/snapshot/SnapshotManagerImpl.java | 7 ++++--- 2 files changed, 14 insertions(+), 11 deletions(-) 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 0cb32da318ea..c14b875a0f2b 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 @@ -2095,7 +2095,15 @@ public Answer createSnapshot(final CreateObjectCommand cmd) { String diskPath = disk.getPath(); String snapshotPath = diskPath + File.separator + snapshotName; SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); - if (DomainInfo.DomainState.VIR_DOMAIN_RUNNING.equals(state) && !primaryPool.isExternalSnapshot()) { + boolean isClvmNgIncremental = primaryPool.getType() == StoragePoolType.CLVM_NG && snapshotTO.isKvmIncrementalSnapshot(); + if (isClvmNgIncremental && secondaryPool == null) { + String errorMsg = String.format("Incremental snapshots for CLVM_NG require secondary storage. " + + "Please configure secondary storage or disable incremental snapshots for volume [%s].", volume.getName()); + logger.error(errorMsg); + return new CreateObjectAnswer(errorMsg); + } + boolean isLiveClvmNgIncremental = isClvmNgIncremental && (DomainInfo.DomainState.VIR_DOMAIN_RUNNING.equals(state) || DomainInfo.DomainState.VIR_DOMAIN_PAUSED.equals(state)); + if ((DomainInfo.DomainState.VIR_DOMAIN_RUNNING.equals(state) && !primaryPool.isExternalSnapshot()) || isLiveClvmNgIncremental) { if (snapshotTO.isKvmIncrementalSnapshot()) { newSnapshot = takeIncrementalVolumeSnapshotOfRunningVm(snapshotTO, primaryPool, secondaryPool, imageStoreTo != null ? imageStoreTo.getUrl() : null, snapshotName, volume, vm, conn, cmd.getWait()); } else { @@ -2109,13 +2117,7 @@ public Answer createSnapshot(final CreateObjectCommand cmd) { newSnapshot.setPhysicalSize(snapshotSize); } } else if (primaryPool.getType() == StoragePoolType.CLVM || primaryPool.getType() == StoragePoolType.CLVM_NG) { - if (primaryPool.getType() == StoragePoolType.CLVM_NG && snapshotTO.isKvmIncrementalSnapshot()) { - if (secondaryPool == null) { - String errorMsg = String.format("Incremental snapshots for CLVM_NG require secondary storage. " + - "Please configure secondary storage or disable incremental snapshots for volume [%s].", volume.getName()); - logger.error(errorMsg); - return new CreateObjectAnswer(errorMsg); - } + if (isClvmNgIncremental) { logger.info("Taking incremental snapshot of CLVM_NG volume [{}] using QCOW2 backup to secondary storage.", volume.getName()); newSnapshot = takeIncrementalVolumeSnapshotOfStoppedVm(snapshotTO, primaryPool, secondaryPool, imageStoreTo.getUrl(), snapshotName, volume, conn, cmd.getWait()); diff --git a/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 2d23e22a0152..1ee1a1fde648 100755 --- a/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -1638,8 +1638,9 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc boolean backupSnapToSecondary = isBackupSnapshotToSecondaryForZone(volume.getDataCenterId()); StoragePoolType poolType = volume.getStoragePoolType(); + boolean isClvmNgIncrementalCandidate = StoragePoolType.CLVM_NG == poolType && kvmIncrementalSnapshot.valueIn(clusterId); - if (isKvmAndFileBasedStorage && backupSnapToSecondary) { + if ((isKvmAndFileBasedStorage || isClvmNgIncrementalCandidate) && backupSnapToSecondary) { DataStore imageStore = snapshotSrv.findSnapshotImageStore(snapshot); if (imageStore == null) { throw new CloudRuntimeException(String.format("Could not find any secondary storage to allocate snapshot [%s].", snapshot)); @@ -1663,7 +1664,7 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc SnapshotInfo snapshotOnPrimary = snapshotStrategy.takeSnapshot(snapshot); if (backupSnapToSecondary) { - if (!isKvmAndFileBasedStorage) { + if (!isKvmAndFileBasedStorage && !isClvmNgIncrementalCandidate) { backupSnapshotToSecondary(payload.getAsyncBackup(), snapshotStrategy, snapshotOnPrimary, payload.getZoneIds(), payload.getStoragePoolIds()); if (!payload.getAsyncBackup() && ClvmPoolManager.isClvmPoolType(storagePool.getPoolType())) { _snapshotStoreDao.removeBySnapshotStore(snapshotId, snapshotOnPrimary.getDataStore().getId(), snapshotOnPrimary.getDataStore().getRole()); @@ -1877,7 +1878,7 @@ private void updateSnapshotPayload(long storagePoolId, CreateSnapshotPayload pay payload.setLocationType(null); } - if (isKvmAndFileBasedStorage && kvmIncrementalSnapshot.valueIn(clusterId)) { + if ((isKvmAndFileBasedStorage || StoragePoolType.CLVM_NG == poolType) && kvmIncrementalSnapshot.valueIn(clusterId)) { payload.setKvmIncrementalSnapshot(true); } }