@@ -1129,9 +1129,9 @@ public Answer backupSnapshot(final CopyCommand cmd) {
11291129 } else {
11301130 final Script command = new Script (_manageSnapshotPath , cmd .getWaitInMillSeconds (), logger );
11311131 String backupPath ;
1132- if (primaryPool .getType () == StoragePoolType .CLVM ) {
1132+ if (primaryPool .getType () == StoragePoolType .CLVM || primaryPool . getType () == StoragePoolType . CLVM_NG ) {
11331133 backupPath = snapshotDisk .getPath ();
1134- logger .debug ("Using snapshotDisk path for CLVM backup: " + backupPath );
1134+ logger .debug ("Using snapshotDisk path for CLVM/CLVM_NG backup: " + backupPath );
11351135 } else {
11361136 backupPath = isCreatedFromVmSnapshot ? snapshotDisk .getPath () : snapshot .getPath ();
11371137 }
@@ -1181,71 +1181,85 @@ public Answer backupSnapshot(final CopyCommand cmd) {
11811181 }
11821182
11831183 /**
1184- * Delete a CLVM snapshot using comprehensive cleanup.
1185- * For CLVM, the snapshot path stored in DB is: /dev/vgname/volumeuuid/snapshotuuid
1186- * the actual snapshot LV created by CLVM is: /dev/vgname/md5(snapshotuuid)
1184+ * Parse CLVM/CLVM_NG snapshot path and compute MD5 hash.
1185+ * Snapshot path format: /dev/vgname/volumeuuid/snapshotuuid
11871186 *
11881187 * @param snapshotPath The snapshot path from database
1188+ * @param poolType Storage pool type (for logging)
1189+ * @return Array of [vgName, volumeUuid, snapshotUuid, md5Hash] or null if invalid
1190+ */
1191+ private String [] parseClvmSnapshotPath (String snapshotPath , StoragePoolType poolType ) {
1192+ String [] pathParts = snapshotPath .split ("/" );
1193+ if (pathParts .length < 5 ) {
1194+ logger .warn ("Invalid {} snapshot path format: {}, expected format: /dev/vgname/volume-uuid/snapshot-uuid" ,
1195+ poolType , snapshotPath );
1196+ return null ;
1197+ }
1198+
1199+ String vgName = pathParts [2 ];
1200+ String volumeUuid = pathParts [3 ];
1201+ String snapshotUuid = pathParts [4 ];
1202+
1203+ logger .info ("Parsed {} snapshot path - VG: {}, Volume: {}, Snapshot: {}" ,
1204+ poolType , vgName , volumeUuid , snapshotUuid );
1205+
1206+ String md5Hash = computeMd5Hash (snapshotUuid );
1207+ logger .debug ("Computed MD5 hash for snapshot UUID {}: {}" , snapshotUuid , md5Hash );
1208+
1209+ return new String []{vgName , volumeUuid , snapshotUuid , md5Hash };
1210+ }
1211+
1212+ /**
1213+ * Delete a CLVM or CLVM_NG snapshot using managesnapshot.sh script.
1214+ * For both CLVM and CLVM_NG, the snapshot path stored in DB is: /dev/vgname/volumeuuid/snapshotuuid
1215+ * The script handles MD5 transformation and pool-specific deletion commands internally:
1216+ * - CLVM: Uses lvremove to delete LVM snapshot
1217+ * - CLVM_NG: Uses qemu-img snapshot -d to delete QCOW2 internal snapshot
1218+ * This approach is consistent with snapshot creation and backup which also use the script.
1219+ *
1220+ * @param snapshotPath The snapshot path from database
1221+ * @param poolType Storage pool type (CLVM or CLVM_NG)
11891222 * @param checkExistence If true, checks if snapshot exists before cleanup (for explicit deletion)
11901223 * If false, always performs cleanup (for post-backup cleanup)
11911224 * @return true if cleanup was performed, false if snapshot didn't exist (when checkExistence=true)
11921225 */
1193- private boolean deleteClvmSnapshot (String snapshotPath , boolean checkExistence ) {
1194- logger .info ("Starting CLVM snapshot deletion for path: {}, checkExistence: {}" , snapshotPath , checkExistence );
1226+ private boolean deleteClvmSnapshot (String snapshotPath , StoragePoolType poolType , boolean checkExistence ) {
1227+ logger .info ("Starting {} snapshot deletion for path: {}, checkExistence: {}" , poolType , snapshotPath , checkExistence );
11951228
11961229 try {
1197- // Parse the snapshot path: /dev/acsvg/volume-uuid/snapshot-uuid
1198- String [] pathParts = snapshotPath .split ("/" );
1199- if (pathParts .length < 5 ) {
1200- logger .warn ("Invalid CLVM snapshot path format: {}, expected format: /dev/vgname/volume-uuid/snapshot-uuid" , snapshotPath );
1230+ String [] parsed = parseClvmSnapshotPath (snapshotPath , poolType );
1231+ if (parsed == null ) {
12011232 return false ;
12021233 }
12031234
1204- String vgName = pathParts [2 ];
1205- String volumeUuid = pathParts [3 ];
1206- String snapshotUuid = pathParts [4 ];
1207-
1208- logger .info ("Parsed snapshot path - VG: {}, Volume: {}, Snapshot: {}" , vgName , volumeUuid , snapshotUuid );
1209-
1210- // Compute MD5 hash of snapshot UUID (same as managesnapshot.sh does)
1211- String md5Hash = computeMd5Hash (snapshotUuid );
1212- logger .debug ("Computed MD5 hash for snapshot UUID {}: {}" , snapshotUuid , md5Hash );
1213- String snapshotLvPath = vgName + "/" + md5Hash ;
1214- String actualSnapshotPath = "/dev/" + snapshotLvPath ;
1215-
1216- // Check if snapshot exists (if requested)
1217- if (checkExistence ) {
1218- Script checkSnapshot = new Script ("/usr/sbin/lvs" , 5000 , logger );
1219- checkSnapshot .add ("--noheadings" );
1220- checkSnapshot .add (snapshotLvPath );
1221- String checkResult = checkSnapshot .execute ();
1235+ String vgName = parsed [0 ];
1236+ String volumeUuid = parsed [1 ];
1237+ String snapshotUuid = parsed [2 ];
1238+ String volumePath = "/dev/" + vgName + "/" + volumeUuid ;
12221239
1223- if (checkResult != null ) {
1224- // Snapshot doesn't exist - was already cleaned up
1225- logger .info ("CLVM snapshot {} was already deleted, no cleanup needed" , md5Hash );
1226- return false ;
1227- }
1228- logger .info ("CLVM snapshot still exists for {}, performing cleanup" , md5Hash );
1229- }
1230-
1231- // Use native LVM command to remove snapshot (handles all cleanup automatically)
1232- Script removeSnapshot = new Script ("lvremove" , 10000 , logger );
1233- removeSnapshot .add ("-f" );
1234- removeSnapshot .add (snapshotLvPath );
1240+ // Use managesnapshot.sh script for deletion (consistent with create/backup)
1241+ // Script handles MD5 transformation and pool-specific commands internally
1242+ Script deleteCommand = new Script (_manageSnapshotPath , 10000 , logger );
1243+ deleteCommand .add ("-d" , volumePath );
1244+ deleteCommand .add ("-n" , snapshotUuid );
12351245
1236- logger .info ("Executing: lvremove -f {}" , snapshotLvPath );
1237- String removeResult = removeSnapshot .execute ();
1246+ logger .info ("Executing: managesnapshot.sh -d {} -n {} " , volumePath , snapshotUuid );
1247+ String result = deleteCommand .execute ();
12381248
1239- if (removeResult == null ) {
1240- logger .info ("Successfully deleted CLVM snapshot: {} (actual path : {}) " , snapshotPath , actualSnapshotPath );
1249+ if (result == null ) {
1250+ logger .info ("Successfully deleted {} snapshot : {}" , poolType , snapshotPath );
12411251 return true ;
12421252 } else {
1243- logger .warn ("Failed to delete CLVM snapshot {}: {}" , snapshotPath , removeResult );
1253+ if (checkExistence && result .contains ("does not exist" )) {
1254+ logger .info ("{} snapshot {} already deleted, no cleanup needed" , poolType , snapshotPath );
1255+ return true ;
1256+ }
1257+ logger .warn ("Failed to delete {} snapshot {}: {}" , poolType , snapshotPath , result );
12441258 return false ;
12451259 }
12461260
12471261 } catch (Exception ex ) {
1248- logger .error ("Exception while deleting CLVM snapshot {}" , snapshotPath , ex );
1262+ logger .error ("Exception while deleting {} snapshot {}" , poolType , snapshotPath , ex );
12491263 return false ;
12501264 }
12511265 }
@@ -1262,10 +1276,11 @@ private void deleteSnapshotOnPrimary(final CopyCommand cmd, final SnapshotObject
12621276
12631277 if ((backupSnapshotAfterTakingSnapshot == null || BooleanUtils .toBoolean (backupSnapshotAfterTakingSnapshot )) && deleteSnapshotOnPrimary ) {
12641278 try {
1265- if (primaryPool .getType () == StoragePoolType .CLVM ) {
1266- boolean cleanedUp = deleteClvmSnapshot (snapshotPath , false );
1279+ if (primaryPool .getType () == StoragePoolType .CLVM || primaryPool .getType () == StoragePoolType .CLVM_NG ) {
1280+ // Both CLVM and CLVM_NG use the same deletion method via managesnapshot.sh script
1281+ boolean cleanedUp = deleteClvmSnapshot (snapshotPath , primaryPool .getType (), false );
12671282 if (!cleanedUp ) {
1268- logger .info ("No need to delete CLVM snapshot on primary as it doesn't exist: {}" , snapshotPath );
1283+ logger .info ("No need to delete {} snapshot on primary as it doesn't exist: {}" , primaryPool . getType () , snapshotPath );
12691284 }
12701285 } else {
12711286 Files .deleteIfExists (Paths .get (snapshotPath ));
@@ -1637,6 +1652,10 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
16371652 if (attachingDisk .getFormat () == PhysicalDiskFormat .QCOW2 ) {
16381653 diskdef .setDiskFormatType (DiskDef .DiskFmtType .QCOW2 );
16391654 }
1655+ } else if (attachingPool .getType () == StoragePoolType .CLVM_NG ) {
1656+ // CLVM_NG uses QCOW2 format on block devices
1657+ diskdef .defBlockBasedDisk (attachingDisk .getPath (), devId , busT );
1658+ diskdef .setDiskFormatType (DiskDef .DiskFmtType .QCOW2 );
16401659 } else if (attachingDisk .getFormat () == PhysicalDiskFormat .QCOW2 ) {
16411660 diskdef .defFileBasedDisk (attachingDisk .getPath (), devId , busT , DiskDef .DiskFmtType .QCOW2 );
16421661 } else if (attachingDisk .getFormat () == PhysicalDiskFormat .RAW ) {
@@ -1986,7 +2005,7 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
19862005 if (snapshotSize != null ) {
19872006 newSnapshot .setPhysicalSize (snapshotSize );
19882007 }
1989- } else if (primaryPool .getType () == StoragePoolType .CLVM ) {
2008+ } else if (primaryPool .getType () == StoragePoolType .CLVM || primaryPool . getType () == StoragePoolType . CLVM_NG ) {
19902009 CreateObjectAnswer result = takeClvmVolumeSnapshotOfStoppedVm (disk , snapshotName );
19912010 if (result != null ) return result ;
19922011 newSnapshot .setPath (snapshotPath );
@@ -2999,24 +3018,24 @@ public Answer deleteSnapshot(final DeleteCommand cmd) {
29993018 if (snapshotTO .isKvmIncrementalSnapshot ()) {
30003019 deleteCheckpoint (snapshotTO );
30013020 }
3002- } else if (primaryPool .getType () == StoragePoolType .CLVM ) {
3003- // For CLVM, snapshots are typically already deleted from primary storage during backup
3021+ } else if (primaryPool .getType () == StoragePoolType .CLVM || primaryPool . getType () == StoragePoolType . CLVM_NG ) {
3022+ // For CLVM/CLVM_NG , snapshots are typically already deleted from primary storage during backup
30043023 // via deleteSnapshotOnPrimary in the backupSnapshot finally block.
30053024 // This is called when the user explicitly deletes the snapshot via UI/API.
30063025 // We check if the snapshot still exists and clean it up if needed.
3007- logger .info ("Processing CLVM snapshot deletion (id={}, name={}, path={}) on primary storage" ,
3026+ logger .info ("Processing CLVM/CLVM_NG snapshot deletion (id={}, name={}, path={}) on primary storage" ,
30083027 snapshotTO .getId (), snapshotTO .getName (), snapshotTO .getPath ());
30093028
30103029 String snapshotPath = snapshotTO .getPath ();
30113030 if (snapshotPath != null && !snapshotPath .isEmpty ()) {
3012- boolean wasDeleted = deleteClvmSnapshot (snapshotPath , true );
3031+ boolean wasDeleted = deleteClvmSnapshot (snapshotPath , primaryPool . getType (), true );
30133032 if (wasDeleted ) {
3014- logger .info ("Successfully cleaned up CLVM snapshot {} from primary storage" , snapshotName );
3033+ logger .info ("Successfully cleaned up {} snapshot {} from primary storage" , primaryPool . getType () , snapshotName );
30153034 } else {
3016- logger .info ("CLVM snapshot {} was already deleted from primary storage during backup, no cleanup needed" , snapshotName );
3035+ logger .info ("{} snapshot {} was already deleted from primary storage during backup, no cleanup needed" , primaryPool . getType () , snapshotName );
30173036 }
30183037 } else {
3019- logger .debug ("CLVM snapshot path is null or empty, assuming already cleaned up" );
3038+ logger .debug ("{} snapshot path is null or empty, assuming already cleaned up" , primaryPool . getType () );
30203039 }
30213040 } else {
30223041 logger .warn ("Operation not implemented for storage pool type of " + primaryPool .getType ().toString ());
0 commit comments