7878import org .apache .cloudstack .managed .context .ManagedContextTimerTask ;
7979import org .apache .cloudstack .poll .BackgroundPollManager ;
8080import org .apache .cloudstack .poll .BackgroundPollTask ;
81+ import org .apache .cloudstack .reservation .dao .ReservationDao ;
8182import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
8283import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
8384import org .apache .cloudstack .utils .reflectiontostringbuilderutils .ReflectionToStringBuilderUtils ;
8485import org .apache .commons .lang .math .NumberUtils ;
8586import org .apache .commons .lang3 .BooleanUtils ;
8687import org .apache .commons .lang3 .ObjectUtils ;
8788import org .apache .commons .lang3 .StringUtils ;
89+ import org .apache .commons .lang3 .builder .ReflectionToStringBuilder ;
90+ import org .apache .commons .lang3 .builder .ToStringStyle ;
8891
8992import com .amazonaws .util .CollectionUtils ;
9093import com .cloud .alert .AlertManager ;
119122import com .cloud .offering .DiskOffering ;
120123import com .cloud .offering .ServiceOffering ;
121124import com .cloud .projects .Project ;
125+ import com .cloud .resourcelimit .CheckedReservation ;
122126import com .cloud .serializer .GsonHelper ;
123127import com .cloud .service .dao .ServiceOfferingDao ;
124128import com .cloud .storage .DiskOfferingVO ;
170174import com .google .gson .Gson ;
171175import com .google .gson .GsonBuilder ;
172176import com .google .gson .reflect .TypeToken ;
173- import org .apache .commons .lang3 .builder .ReflectionToStringBuilder ;
174- import org .apache .commons .lang3 .builder .ToStringStyle ;
175177
176178public 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