Copilot commented on code in PR #12813:
URL: https://github.com/apache/cloudstack/pull/12813#discussion_r3257267515


##########
server/src/main/java/com/cloud/storage/StorageManagerImpl.java:
##########
@@ -2292,6 +2293,34 @@ private void deleteSnapshot(SnapshotVO snapshot, 
SnapshotDataStoreVO snapshotDat
         }
     }
 
+    /**
+     * Cleans up snapshot DB records for snapshots that exist only on primary 
storage (no secondary copy).
+     * This handles the case where snapshot.backup.to.secondary=false and the 
volume
+     * is being deleted during VM expunge — the RBD snapshots will be 
destroyed along with the image,
+     * so the DB records need to be cleaned up to avoid orphaned entries.
+     */
+    protected void cleanupSnapshotRecordsInPrimaryStorageOnly(VolumeVO volume) 
{
+        List<SnapshotVO> snapshots = 
_snapshotDao.listByVolumeId(volume.getId());
+        if (CollectionUtils.isEmpty(snapshots)) {
+            return;
+        }
+        for (SnapshotVO snapshot : snapshots) {
+            if (Snapshot.State.Destroyed.equals(snapshot.getState())) {
+                continue;
+            }
+            List<SnapshotDataStoreVO> snapshotsOnPrimaryStorage = 
_snapshotStoreDao.listBySnapshotAndDataStoreRole(snapshot.getId(), 
DataStoreRole.Primary);
+            List<SnapshotDataStoreVO> snapshotsOnSecondaryStorage = 
_snapshotStoreDao.listBySnapshotAndDataStoreRole(snapshot.getId(), 
DataStoreRole.Image);
+            if (CollectionUtils.isNotEmpty(snapshotsOnPrimaryStorage) && 
CollectionUtils.isEmpty(snapshotsOnSecondaryStorage)) {
+                logger.info("Cleaning up snapshot {} (primary-only, no 
secondary copy) as volume {} is being deleted", snapshot, volume);
+                for (SnapshotDataStoreVO snapshotOnPrimaryStorage : 
snapshotsOnPrimaryStorage) {
+                    
_snapshotStoreDao.expunge(snapshotOnPrimaryStorage.getId());
+                }
+                snapshot.setState(Snapshot.State.Destroyed);
+                _snapshotDao.update(snapshot.getId(), snapshot);

Review Comment:
   This path marks primary-only snapshots as destroyed without applying the 
resource-accounting side effects of normal snapshot deletion. 
`SnapshotManagerImpl.deleteSnapshot` decrements the account's snapshot resource 
count when the snapshot becomes destroyed, so these cleanup-only deletions can 
leave snapshot quota consumed even though the UI no longer shows the snapshot; 
please decrement the snapshot resource count (and any storage usage that 
applies to primary-only snapshots) when this cleanup succeeds, or route through 
a deletion helper that performs the same accounting without touching the 
already-removed RBD snapshot.



##########
server/src/main/java/com/cloud/storage/StorageManagerImpl.java:
##########
@@ -2145,6 +2145,7 @@ public void cleanupStorage(boolean recurring) {
                         }
 
                         try {
+                            cleanupSnapshotRecordsInPrimaryStorageOnly(vol);

Review Comment:
   This removes the snapshot metadata before the asynchronous volume expunge 
has actually succeeded. If `ensureVolumeIsExpungeReady` or `expungeVolumeAsync` 
fails, or if the async delete later returns failure, the RBD image and 
snapshots may still exist but CloudStack has already expunged their 
`snapshot_store_ref` rows and marked the snapshots destroyed, leaving users 
unable to manage valid snapshots. Move this cleanup to the successful 
volume-delete callback path (or otherwise gate it on confirmed volume deletion 
success) while avoiding the storage-side snapshot delete that currently causes 
the orphan issue.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to