Skip to content

Commit 19b4ef1

Browse files
shwstpprDaanHoogland
authored andcommitted
server: reserve backup, bucket resource limits during operations
Changes to check resource limits with reservations for the following resource types: - backup - backup_storage - bnucket - object_storage Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent 8608b4e commit 19b4ef1

File tree

4 files changed

+385
-176
lines changed

4 files changed

+385
-176
lines changed

server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java

Lines changed: 77 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,16 @@
7878
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
7979
import org.apache.cloudstack.poll.BackgroundPollManager;
8080
import org.apache.cloudstack.poll.BackgroundPollTask;
81+
import org.apache.cloudstack.reservation.dao.ReservationDao;
8182
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
8283
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
8384
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
8485
import org.apache.commons.lang.math.NumberUtils;
8586
import org.apache.commons.lang3.BooleanUtils;
8687
import org.apache.commons.lang3.ObjectUtils;
8788
import org.apache.commons.lang3.StringUtils;
89+
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
90+
import org.apache.commons.lang3.builder.ToStringStyle;
8891

8992
import com.amazonaws.util.CollectionUtils;
9093
import com.cloud.alert.AlertManager;
@@ -119,6 +122,7 @@
119122
import com.cloud.offering.DiskOffering;
120123
import com.cloud.offering.ServiceOffering;
121124
import com.cloud.projects.Project;
125+
import com.cloud.resourcelimit.CheckedReservation;
122126
import com.cloud.serializer.GsonHelper;
123127
import com.cloud.service.dao.ServiceOfferingDao;
124128
import com.cloud.storage.DiskOfferingVO;
@@ -170,8 +174,6 @@
170174
import com.google.gson.Gson;
171175
import com.google.gson.GsonBuilder;
172176
import com.google.gson.reflect.TypeToken;
173-
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
174-
import org.apache.commons.lang3.builder.ToStringStyle;
175177

176178
public class BackupManagerImpl extends ManagerBase implements BackupManager {
177179

@@ -237,6 +239,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
237239
private AlertManager alertManager;
238240
@Inject
239241
private GuestOSDao _guestOSDao;
242+
@Inject
243+
ReservationDao reservationDao;
240244

241245
private AsyncJobDispatcher asyncJobDispatcher;
242246
private Timer backupTimer;
@@ -792,14 +796,6 @@ public boolean createBackup(CreateBackupCmd cmd, Object job) throws ResourceAllo
792796
Long backupScheduleId = getBackupScheduleId(job);
793797
boolean isScheduledBackup = backupScheduleId != null;
794798
Account owner = accountManager.getAccount(vm.getAccountId());
795-
try {
796-
resourceLimitMgr.checkResourceLimit(owner, Resource.ResourceType.backup);
797-
} catch (ResourceAllocationException e) {
798-
if (isScheduledBackup) {
799-
sendExceededBackupLimitAlert(owner.getUuid(), Resource.ResourceType.backup);
800-
}
801-
throw e;
802-
}
803799

804800
Long backupSize = 0L;
805801
for (final Volume volume: volumeDao.findByInstance(vmId)) {
@@ -811,40 +807,55 @@ public boolean createBackup(CreateBackupCmd cmd, Object job) throws ResourceAllo
811807
backupSize += volumeSize;
812808
}
813809
}
814-
try {
815-
resourceLimitMgr.checkResourceLimit(owner, Resource.ResourceType.backup_storage, backupSize);
816-
} catch (ResourceAllocationException e) {
817-
if (isScheduledBackup) {
818-
sendExceededBackupLimitAlert(owner.getUuid(), Resource.ResourceType.backup_storage);
819-
}
820-
throw e;
810+
createCheckedBackup(cmd, owner, isScheduledBackup, backupSize, vm, vmId, backupProvider, backupScheduleId);
811+
if (isScheduledBackup) {
812+
deleteOldestBackupFromScheduleIfRequired(vmId, backupScheduleId);
821813
}
814+
return true;
815+
}
822816

823-
ActionEventUtils.onStartedActionEvent(User.UID_SYSTEM, vm.getAccountId(),
824-
EventTypes.EVENT_VM_BACKUP_CREATE, "creating backup for VM ID:" + vm.getUuid(),
825-
vmId, ApiCommandResourceType.VirtualMachine.toString(),
826-
true, 0);
817+
private void createCheckedBackup(CreateBackupCmd cmd, Account owner, boolean isScheduledBackup, Long backupSize,
818+
VMInstanceVO vm, Long vmId, BackupProvider backupProvider, Long backupScheduleId)
819+
throws ResourceAllocationException {
820+
try (CheckedReservation backupReservation = new CheckedReservation(owner, Resource.ResourceType.backup,
821+
1L, reservationDao, resourceLimitMgr);
822+
CheckedReservation backupStorageReservation = new CheckedReservation(owner,
823+
Resource.ResourceType.backup_storage, backupSize, reservationDao, resourceLimitMgr)) {
827824

828-
Pair<Boolean, Backup> result = backupProvider.takeBackup(vm, cmd.getQuiesceVM());
829-
if (!result.first()) {
830-
throw new CloudRuntimeException("Failed to create VM backup");
831-
}
832-
Backup backup = result.second();
833-
if (backup != null) {
834-
BackupVO vmBackup = backupDao.findById(result.second().getId());
835-
vmBackup.setBackupScheduleId(backupScheduleId);
836-
if (cmd.getName() != null) {
837-
vmBackup.setName(cmd.getName());
825+
ActionEventUtils.onStartedActionEvent(User.UID_SYSTEM, vm.getAccountId(),
826+
EventTypes.EVENT_VM_BACKUP_CREATE, "creating backup for VM ID:" + vm.getUuid(),
827+
vmId, ApiCommandResourceType.VirtualMachine.toString(),
828+
true, 0);
829+
830+
Pair<Boolean, Backup> result = backupProvider.takeBackup(vm, cmd.getQuiesceVM());
831+
if (!result.first()) {
832+
throw new CloudRuntimeException("Failed to create VM backup");
838833
}
839-
vmBackup.setDescription(cmd.getDescription());
840-
backupDao.update(vmBackup.getId(), vmBackup);
841-
resourceLimitMgr.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.backup);
842-
resourceLimitMgr.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.backup_storage, backup.getSize());
843-
}
844-
if (isScheduledBackup) {
845-
deleteOldestBackupFromScheduleIfRequired(vmId, backupScheduleId);
834+
Backup backup = result.second();
835+
if (backup != null) {
836+
BackupVO vmBackup = backupDao.findById(result.second().getId());
837+
vmBackup.setBackupScheduleId(backupScheduleId);
838+
if (cmd.getName() != null) {
839+
vmBackup.setName(cmd.getName());
840+
}
841+
vmBackup.setDescription(cmd.getDescription());
842+
backupDao.update(vmBackup.getId(), vmBackup);
843+
resourceLimitMgr.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.backup);
844+
resourceLimitMgr.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.backup_storage, backup.getSize());
845+
}
846+
} catch (Exception e) {
847+
if (e instanceof ResourceAllocationException) {
848+
ResourceAllocationException rae = (ResourceAllocationException)e;
849+
if (isScheduledBackup && (Resource.ResourceType.backup.equals(rae.getResourceType()) ||
850+
Resource.ResourceType.backup_storage.equals(rae.getResourceType()))) {
851+
sendExceededBackupLimitAlert(owner.getUuid(), rae.getResourceType());
852+
}
853+
throw rae;
854+
} else if (e instanceof CloudRuntimeException) {
855+
throw (CloudRuntimeException)e;
856+
}
857+
throw new CloudRuntimeException("Failed to create backup for VM with ID: " + vm.getUuid(), e);
846858
}
847-
return true;
848859
}
849860

850861
/**
@@ -1538,19 +1549,35 @@ public boolean deleteBackup(final Long backupId, final Boolean forced) {
15381549
throw new CloudRuntimeException(String.format("Backup offering with ID [%s] does not exist.", backup.getBackupOfferingId()));
15391550
}
15401551
final BackupProvider backupProvider = getBackupProvider(backup.getZoneId());
1541-
boolean result = backupProvider.deleteBackup(backup, forced);
1542-
if (result) {
1543-
resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup);
1544-
Long backupSize = backup.getSize() != null ? backup.getSize() : 0L;
1545-
resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup_storage, backupSize);
1546-
if (backupDao.remove(backup.getId())) {
1547-
checkAndGenerateUsageForLastBackupDeletedAfterOfferingRemove(vm, backup);
1548-
return true;
1549-
} else {
1550-
return false;
1552+
return deleteCheckedBackup(forced, backupProvider, backup, vm);
1553+
}
1554+
1555+
private boolean deleteCheckedBackup(Boolean forced, BackupProvider backupProvider, BackupVO backup, VMInstanceVO vm) {
1556+
Account owner = accountManager.getAccount(backup.getAccountId());
1557+
long backupSize = backup.getSize() != null ? backup.getSize() : 0L;
1558+
try (CheckedReservation backupReservation = new CheckedReservation(owner, Resource.ResourceType.backup,
1559+
backup.getId(), null, -1L, reservationDao, resourceLimitMgr);
1560+
CheckedReservation backupStorageReservation = new CheckedReservation(owner,
1561+
Resource.ResourceType.backup_storage, backup.getId(), null, -1 * backupSize,
1562+
reservationDao, resourceLimitMgr)) {
1563+
boolean result = backupProvider.deleteBackup(backup, forced);
1564+
if (result) {
1565+
resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup);
1566+
resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup_storage, backupSize);
1567+
if (backupDao.remove(backup.getId())) {
1568+
checkAndGenerateUsageForLastBackupDeletedAfterOfferingRemove(vm, backup);
1569+
return true;
1570+
} else {
1571+
return false;
1572+
}
1573+
}
1574+
throw new CloudRuntimeException("Failed to delete the backup");
1575+
} catch (Exception e) {
1576+
if (e instanceof CloudRuntimeException) {
1577+
throw (CloudRuntimeException) e;
15511578
}
1579+
throw new CloudRuntimeException("Failed to delete the backup due to: " + e.getMessage(), e);
15521580
}
1553-
throw new CloudRuntimeException("Failed to delete the backup");
15541581
}
15551582

15561583
/**

0 commit comments

Comments
 (0)