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);
}