Skip to content

Commit e0ef3a6

Browse files
DaanHooglandDaan Hoogland
authored andcommitted
Check resource reservation on volume snapshot creation
1 parent 3b987f2 commit e0ef3a6

2 files changed

Lines changed: 31 additions & 17 deletions

File tree

server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import javax.inject.Inject;
3333
import javax.naming.ConfigurationException;
3434

35+
import com.cloud.resourcelimit.CheckedReservation;
3536
import org.apache.cloudstack.acl.SecurityChecker;
3637
import com.cloud.api.ApiDBUtils;
3738
import org.apache.cloudstack.annotation.AnnotationService;
@@ -67,6 +68,7 @@
6768
import org.apache.cloudstack.framework.config.Configurable;
6869
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
6970
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
71+
import org.apache.cloudstack.reservation.dao.ReservationDao;
7072
import org.apache.cloudstack.resourcedetail.SnapshotPolicyDetailVO;
7173
import org.apache.cloudstack.resourcedetail.dao.SnapshotPolicyDetailsDao;
7274
import org.apache.cloudstack.snapshot.SnapshotHelper;
@@ -240,6 +242,8 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
240242
@Inject
241243
private AnnotationDao annotationDao;
242244

245+
@Inject
246+
private ReservationDao reservationDao;
243247
@Inject
244248
protected SnapshotHelper snapshotHelper;
245249
@Inject
@@ -1705,20 +1709,6 @@ public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName,
17051709
Type snapshotType = getSnapshotType(policyId);
17061710
Account owner = _accountMgr.getAccount(volume.getAccountId());
17071711

1708-
ResourceType storeResourceType = getStoreResourceType(volume.getDataCenterId(), locationType);
1709-
try {
1710-
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.snapshot);
1711-
_resourceLimitMgr.checkResourceLimit(owner, storeResourceType, volume.getSize());
1712-
} catch (ResourceAllocationException e) {
1713-
if (snapshotType != Type.MANUAL) {
1714-
String msg = String.format("Snapshot resource limit exceeded for account %s. Failed to create recurring snapshots", owner);
1715-
logger.warn(msg);
1716-
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, "Snapshot resource limit exceeded for account id : " + owner.getId()
1717-
+ ". Failed to create recurring snapshots; please use updateResourceLimit to increase the limit");
1718-
}
1719-
throw e;
1720-
}
1721-
17221712
// Determine the name for this snapshot
17231713
// Snapshot Name: VMInstancename + volumeName + timeString
17241714
String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT);
@@ -1750,6 +1740,14 @@ public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName,
17501740
hypervisorType = volume.getHypervisorType();
17511741
}
17521742

1743+
ResourceType storeResourceType = ResourceType.secondary_storage;
1744+
if (!isBackupSnapshotToSecondaryForZone(volume.getDataCenterId()) ||
1745+
Snapshot.LocationType.PRIMARY.equals(locationType)) {
1746+
storeResourceType = ResourceType.primary_storage;
1747+
}
1748+
1749+
try (CheckedReservation volumeSnapshotReservation = new CheckedReservation(owner, ResourceType.snapshot, null, null, 1L, reservationDao, _resourceLimitMgr);
1750+
CheckedReservation storageReservation = new CheckedReservation(owner, storeResourceType, null, null, volume.getSize(), reservationDao, _resourceLimitMgr)) {
17531751
SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), snapshotName,
17541752
(short)snapshotType.ordinal(), snapshotType.name(), volume.getSize(), volume.getMinIops(), volume.getMaxIops(), hypervisorType, locationType);
17551753

@@ -1761,6 +1759,17 @@ public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName,
17611759
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.snapshot);
17621760
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), storeResourceType, volume.getSize());
17631761
return snapshot;
1762+
} catch (Exception e) {
1763+
if (e instanceof ResourceAllocationException) {
1764+
if (snapshotType != Type.MANUAL) {
1765+
String msg = String.format("Snapshot resource limit exceeded for account id : %s. Failed to create recurring snapshots", owner.getId());
1766+
logger.warn(msg);
1767+
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, msg + ". Please, use updateResourceLimit to increase the limit");
1768+
}
1769+
throw (ResourceAllocationException) e;
1770+
}
1771+
throw new CloudRuntimeException(e);
1772+
}
17641773
}
17651774

17661775
@Override

server/src/test/java/com/cloud/storage/snapshot/SnapshotManagerTest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
import com.cloud.api.ApiDBUtils;
3838
import com.cloud.exception.PermissionDeniedException;
39+
import com.cloud.resourcelimit.CheckedReservation;
3940
import com.cloud.storage.Storage;
4041
import org.apache.cloudstack.api.command.user.snapshot.ExtractSnapshotCmd;
4142
import org.apache.cloudstack.context.CallContext;
@@ -65,6 +66,7 @@
6566
import org.mockito.BDDMockito;
6667
import org.mockito.InjectMocks;
6768
import org.mockito.Mock;
69+
import org.mockito.MockedConstruction;
6870
import org.mockito.MockedStatic;
6971
import org.mockito.Mockito;
7072
import org.mockito.junit.MockitoJUnitRunner;
@@ -233,8 +235,6 @@ public void setup() throws ResourceAllocationException {
233235
when(_storageStrategyFactory.getSnapshotStrategy(Mockito.any(SnapshotVO.class), Mockito.eq(SnapshotOperation.BACKUP))).thenReturn(snapshotStrategy);
234236
when(_storageStrategyFactory.getSnapshotStrategy(Mockito.any(SnapshotVO.class), Mockito.eq(SnapshotOperation.REVERT))).thenReturn(snapshotStrategy);
235237

236-
doNothing().when(_resourceLimitMgr).checkResourceLimit(any(Account.class), any(ResourceType.class));
237-
doNothing().when(_resourceLimitMgr).checkResourceLimit(any(Account.class), any(ResourceType.class), anyLong());
238238
doNothing().when(_resourceLimitMgr).decrementResourceCount(anyLong(), any(ResourceType.class), anyLong());
239239
doNothing().when(_resourceLimitMgr).incrementResourceCount(anyLong(), any(ResourceType.class));
240240
doNothing().when(_resourceLimitMgr).incrementResourceCount(anyLong(), any(ResourceType.class), anyLong());
@@ -317,7 +317,12 @@ public void testAllocSnapshotF4() throws ResourceAllocationException {
317317
when(mockList2.size()).thenReturn(0);
318318
when(_vmSnapshotDao.listByInstanceId(TEST_VM_ID, VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging)).thenReturn(mockList2);
319319
when(_snapshotDao.persist(any(SnapshotVO.class))).thenReturn(snapshotMock);
320-
_snapshotMgr.allocSnapshot(TEST_VOLUME_ID, Snapshot.MANUAL_POLICY_ID, null, null);
320+
321+
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
322+
_snapshotMgr.allocSnapshot(TEST_VOLUME_ID, Snapshot.MANUAL_POLICY_ID, null, null);
323+
} catch (ResourceAllocationException e) {
324+
Assert.fail(String.format("Failure with exception: %s", e.getMessage()));
325+
}
321326
}
322327

323328
@Test(expected = InvalidParameterValueException.class)

0 commit comments

Comments
 (0)