This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new c681d0d0a2f Change `vmsnapshot.max` setting scope to the account level 
(#11616)
c681d0d0a2f is described below

commit c681d0d0a2f53a7ef52de5cc2a4bb0d7d2aa864a
Author: Bernardo De Marco Gonçalves <[email protected]>
AuthorDate: Thu Jan 29 06:01:54 2026 -0300

    Change `vmsnapshot.max` setting scope to the account level (#11616)
---
 .../java/com/cloud/vm/snapshot/VMSnapshotManager.java     |  2 +-
 .../java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java |  7 ++++---
 .../java/com/cloud/vm/snapshot/VMSnapshotManagerTest.java | 15 +++++++++++++++
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git 
a/engine/components-api/src/main/java/com/cloud/vm/snapshot/VMSnapshotManager.java
 
b/engine/components-api/src/main/java/com/cloud/vm/snapshot/VMSnapshotManager.java
index 6478469f190..6831552b83d 100644
--- 
a/engine/components-api/src/main/java/com/cloud/vm/snapshot/VMSnapshotManager.java
+++ 
b/engine/components-api/src/main/java/com/cloud/vm/snapshot/VMSnapshotManager.java
@@ -31,7 +31,7 @@ public interface VMSnapshotManager extends VMSnapshotService, 
Manager {
     static final ConfigKey<Integer> VMSnapshotExpireInterval = new 
ConfigKey<Integer>("Advanced", Integer.class, "vmsnapshot.expire.interval", 
"-1",
             "VM Snapshot expire interval in hours", true, 
ConfigKey.Scope.Account);
 
-    ConfigKey<Integer> VMSnapshotMax = new ConfigKey<Integer>("Advanced", 
Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a single vm", 
true, ConfigKey.Scope.Global);
+    ConfigKey<Integer> VMSnapshotMax = new ConfigKey<Integer>("Advanced", 
Integer.class, "vmsnapshot.max", "10", "Maximum VM snapshots for a single VM", 
true, ConfigKey.Scope.Account);
 
     /**
      * Delete all VM snapshots belonging to one VM
diff --git 
a/server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java 
b/server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index 617a4e54a6e..d5e25adcd5f 100644
--- a/server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -400,10 +400,11 @@ public class VMSnapshotManagerImpl extends 
MutualExclusiveIdsManagerBase impleme
         _accountMgr.checkAccess(caller, null, true, userVmVo);
 
         // check max snapshot limit for per VM
-        int vmSnapshotMax = VMSnapshotManager.VMSnapshotMax.value();
-
+        boolean vmBelongsToProject = 
_accountMgr.getAccount(userVmVo.getAccountId()).getType() == 
Account.Type.PROJECT;
+        long accountIdToRetrieveConfigurationValueFrom = vmBelongsToProject ? 
caller.getId() : userVmVo.getAccountId();
+        int vmSnapshotMax = 
VMSnapshotManager.VMSnapshotMax.valueIn(accountIdToRetrieveConfigurationValueFrom);
         if (_vmSnapshotDao.findByVm(vmId).size() >= vmSnapshotMax) {
-            throw new CloudRuntimeException("Creating Instance Snapshot failed 
due to a Instance can just have : " + vmSnapshotMax + " Instance Snapshots. 
Please delete old ones");
+            throw new CloudRuntimeException(String.format("Each VM can have at 
most [%s] VM snapshots.", vmSnapshotMax));
         }
 
         // check if there are active volume snapshots tasks
diff --git 
a/server/src/test/java/com/cloud/vm/snapshot/VMSnapshotManagerTest.java 
b/server/src/test/java/com/cloud/vm/snapshot/VMSnapshotManagerTest.java
index a0f09981a40..b696d743ac6 100644
--- a/server/src/test/java/com/cloud/vm/snapshot/VMSnapshotManagerTest.java
+++ b/server/src/test/java/com/cloud/vm/snapshot/VMSnapshotManagerTest.java
@@ -41,6 +41,7 @@ import com.cloud.storage.dao.SnapshotDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
+import com.cloud.user.AccountVO;
 import com.cloud.user.dao.AccountDao;
 import com.cloud.user.dao.UserDao;
 import com.cloud.uservm.UserVm;
@@ -136,6 +137,8 @@ public class VMSnapshotManagerTest {
     VMSnapshotDetailsDao _vmSnapshotDetailsDao;
     @Mock
     UserVmManager _userVmManager;
+    @Mock
+    private AccountVO accountVOMock;
 
     private static final long TEST_VM_ID = 3L;
     private static final long SERVICE_OFFERING_ID = 1L;
@@ -285,8 +288,12 @@ public class VMSnapshotManagerTest {
     @SuppressWarnings("unchecked")
     @Test(expected = CloudRuntimeException.class)
     public void testAllocVMSnapshotF4() throws ResourceAllocationException {
+        long accountId = 1L;
         List<VMSnapshotVO> mockList = mock(List.class);
         when(mockList.size()).thenReturn(10);
+        when(_userVMDao.findById(TEST_VM_ID)).thenReturn(vmMock);
+        when(userVm.getAccountId()).thenReturn(accountId);
+        when(_accountMgr.getAccount(accountId)).thenReturn(accountVOMock);
         when(_vmSnapshotDao.findByVm(TEST_VM_ID)).thenReturn(mockList);
         _vmSnapshotMgr.allocVMSnapshot(TEST_VM_ID, "", "", true);
     }
@@ -295,8 +302,12 @@ public class VMSnapshotManagerTest {
     @SuppressWarnings("unchecked")
     @Test(expected = CloudRuntimeException.class)
     public void testAllocVMSnapshotF5() throws ResourceAllocationException {
+        long accountId = 1L;
         List<SnapshotVO> mockList = mock(List.class);
         when(mockList.size()).thenReturn(1);
+        when(_userVMDao.findById(TEST_VM_ID)).thenReturn(vmMock);
+        when(userVm.getAccountId()).thenReturn(accountId);
+        when(_accountMgr.getAccount(accountId)).thenReturn(accountVOMock);
         when(_snapshotDao.listByInstanceId(TEST_VM_ID, 
Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, 
Snapshot.State.BackingUp)).thenReturn(mockList);
         _vmSnapshotMgr.allocVMSnapshot(TEST_VM_ID, "", "", true);
     }
@@ -304,6 +315,10 @@ public class VMSnapshotManagerTest {
     // successful creation case
     @Test
     public void testCreateVMSnapshot() throws AgentUnavailableException, 
OperationTimedoutException, ResourceAllocationException, NoTransitionException {
+        long accountId = 1L;
+        when(_userVMDao.findById(TEST_VM_ID)).thenReturn(vmMock);
+        when(userVm.getAccountId()).thenReturn(accountId);
+        when(_accountMgr.getAccount(accountId)).thenReturn(accountVOMock);
         when(vmMock.getState()).thenReturn(State.Running);
         _vmSnapshotMgr.allocVMSnapshot(TEST_VM_ID, "", "", true);
     }

Reply via email to