This is an automated email from the ASF dual-hosted git repository.
sureshanaparti pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.22 by this push:
new 7ba5240b311 Block backup deletion while create-VM-from-backup or
restore jobs are in progress (#12792)
7ba5240b311 is described below
commit 7ba5240b311f4b66ff4d2c2ced0a14292d7cd62f
Author: Daman Arora <[email protected]>
AuthorDate: Wed Apr 8 22:39:01 2026 -0700
Block backup deletion while create-VM-from-backup or restore jobs are in
progress (#12792)
* Block backup deletion while create-VM-from-backup or restore jobs are in
progress
* Add tests
* Fix exception message
* Update test
Co-authored-by: Abhisar Sinha <[email protected]>
---
.../cloudstack/backup/BackupManagerImpl.java | 14 ++++++++++
.../cloudstack/backup/BackupManagerTest.java | 30 ++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git
a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
index d5663ed3272..e9ed8e42eaa 100644
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@ -1531,6 +1531,8 @@ public class BackupManagerImpl extends ManagerBase
implements BackupManager {
validateBackupForZone(backup.getZoneId());
accountManager.checkAccess(CallContext.current().getCallingAccount(),
null, true, vm == null ? backup : vm);
+
+ checkForPendingBackupJobs(backup);
final BackupOffering offering =
backupOfferingDao.findByIdIncludingRemoved(backup.getBackupOfferingId());
if (offering == null) {
throw new CloudRuntimeException(String.format("Backup offering
with ID [%s] does not exist.", backup.getBackupOfferingId()));
@@ -1551,6 +1553,18 @@ public class BackupManagerImpl extends ManagerBase
implements BackupManager {
throw new CloudRuntimeException("Failed to delete the backup");
}
+ private void checkForPendingBackupJobs(final BackupVO backup) {
+ String backupUuid = backup.getUuid();
+ long pendingJobs = asyncJobManager.countPendingJobs(backupUuid,
+ CreateVMFromBackupCmd.class.getName(),
+ CreateVMFromBackupCmdByAdmin.class.getName(),
+ RestoreBackupCmd.class.getName(),
+ RestoreVolumeFromBackupAndAttachToVMCmd.class.getName());
+ if (pendingJobs > 0) {
+ throw new CloudRuntimeException("Cannot delete Backup while a
create Instance from Backup or restore Backup operation is in progress, please
try again later.");
+ }
+ }
+
/**
* Get the pair: hostIp, datastoreUuid in which to restore the volume,
based on the VM to be attached information
*/
diff --git
a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 8b13fd47494..2c9d11612c4 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -91,6 +91,7 @@ import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.junit.After;
import org.junit.Assert;
@@ -241,6 +242,9 @@ public class BackupManagerTest {
@Mock
private GuestOSDao _guestOSDao;
+ @Mock
+ AsyncJobManager asyncJobManager;
+
private Gson gson;
private String[] hostPossibleValues = {"127.0.0.1", "hostname"};
@@ -1489,6 +1493,7 @@ public class BackupManagerTest {
when(backup.getAccountId()).thenReturn(accountId);
when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
when(backup.getSize()).thenReturn(100L);
+ when(backup.getUuid()).thenReturn("backup-uuid");
overrideBackupFrameworkConfigValue();
@@ -1523,6 +1528,31 @@ public class BackupManagerTest {
}
}
+ @Test(expected = CloudRuntimeException.class)
+ public void testDeleteBackupBlockedByPendingJobs() {
+ Long backupId = 1L;
+ Long vmId = 2L;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getVmId()).thenReturn(vmId);
+ when(backup.getUuid()).thenReturn("backup-uuid");
+ when(backup.getZoneId()).thenReturn(1L);
+ when(backupDao.findByIdIncludingRemoved(backupId)).thenReturn(backup);
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+
+ overrideBackupFrameworkConfigValue();
+
+ when(asyncJobManager.countPendingJobs("backup-uuid",
+
"org.apache.cloudstack.api.command.user.vm.CreateVMFromBackupCmd",
+
"org.apache.cloudstack.api.command.admin.vm.CreateVMFromBackupCmdByAdmin",
+
"org.apache.cloudstack.api.command.user.backup.RestoreBackupCmd",
+
"org.apache.cloudstack.api.command.user.backup.RestoreVolumeFromBackupAndAttachToVMCmd")).thenReturn(1L);
+
+ backupManager.deleteBackup(backupId, false);
+ }
+
@Test
public void testNewBackupResponse() {
Long vmId = 1L;