@@ -2088,57 +2088,61 @@ private boolean checkAndProcessSnapshotAlreadyExistInStore(long snapshotId, Data
20882088
20892089 @ DB
20902090 private boolean copySnapshotToZone (SnapshotDataStoreVO snapshotDataStoreVO , DataStore srcSecStore ,
2091- DataCenterVO dstZone , DataStore dstSecStore , Account account , boolean kvmIncrementalSnapshot )
2091+ DataCenterVO dstZone , DataStore dstSecStore , Account account , boolean kvmIncrementalSnapshot , boolean shouldCheckResourceLimits )
20922092 throws ResourceAllocationException {
20932093 final long snapshotId = snapshotDataStoreVO .getSnapshotId ();
20942094 final long dstZoneId = dstZone .getId ();
20952095 if (checkAndProcessSnapshotAlreadyExistInStore (snapshotId , dstSecStore )) {
20962096 return true ;
20972097 }
2098- _resourceLimitMgr .checkResourceLimit (account , ResourceType .secondary_storage , snapshotDataStoreVO .getSize ());
2099- // snapshotId may refer to ID of a removed parent snapshot
2100- SnapshotInfo snapshotOnSecondary = snapshotFactory .getSnapshot (snapshotId , srcSecStore );
2101- if (kvmIncrementalSnapshot ) {
2102- snapshotOnSecondary = snapshotHelper .convertSnapshotIfNeeded (snapshotOnSecondary );
2103- }
2104- String copyUrl = null ;
2105- try {
2106- AsyncCallFuture <CreateCmdResult > future = snapshotSrv .queryCopySnapshot (snapshotOnSecondary );
2107- CreateCmdResult result = future .get ();
2108- if (!result .isFailed ()) {
2109- copyUrl = result .getPath ();
2110- }
2111- } catch (InterruptedException | ExecutionException | ResourceUnavailableException ex ) {
2112- logger .error ("Failed to prepare URL for copy for snapshot ID: {} on store: {}" , snapshotId , srcSecStore , ex );
2113- }
2114- if (StringUtils .isEmpty (copyUrl )) {
2115- logger .error ("Unable to prepare URL for copy for snapshot ID: {} on store: {}" , snapshotId , srcSecStore );
2116- return false ;
2117- }
2118- logger .debug (String .format ("Copying snapshot ID: %d to destination zones using download URL: %s" , snapshotId , copyUrl ));
2119- try {
2120- AsyncCallFuture <SnapshotResult > future = snapshotSrv .copySnapshot (snapshotOnSecondary , copyUrl , dstSecStore );
2121- SnapshotResult result = future .get ();
2122- if (result .isFailed ()) {
2123- logger .debug ("Copy snapshot ID: {} failed for image store {}: {}" , snapshotId , dstSecStore , result .getResult ());
2124- return false ;
2098+ // Resource limit checks are not performed here at the moment, but they were added in case this method is used
2099+ // in the future to copy a standalone snapshot
2100+ long requiredSecondaryStorageSpace = shouldCheckResourceLimits ? snapshotDataStoreVO .getSize () : 0L ;
2101+ try (CheckedReservation secondaryStorageReservation = new CheckedReservation (account , ResourceType .secondary_storage , null , null , null , requiredSecondaryStorageSpace , null , reservationDao , _resourceLimitMgr )) {
2102+ // snapshotId may refer to ID of a removed parent snapshot
2103+ SnapshotInfo snapshotOnSecondary = snapshotFactory .getSnapshot (snapshotId , srcSecStore );
2104+ if (kvmIncrementalSnapshot ) {
2105+ snapshotOnSecondary = snapshotHelper .convertSnapshotIfNeeded (snapshotOnSecondary );
21252106 }
2126- snapshotZoneDao .addSnapshotToZone (snapshotId , dstZoneId );
2127- _resourceLimitMgr .incrementResourceCount (account .getId (), ResourceType .secondary_storage , snapshotDataStoreVO .getSize ());
2128- if (account .getId () != Account .ACCOUNT_ID_SYSTEM ) {
2129- SnapshotVO snapshotVO = _snapshotDao .findByIdIncludingRemoved (snapshotId );
2130- UsageEventUtils .publishUsageEvent (EventTypes .EVENT_SNAPSHOT_COPY , account .getId (), dstZoneId , snapshotId , null , null , null , snapshotVO .getSize (),
2131- snapshotVO .getSize (), snapshotVO .getClass ().getName (), snapshotVO .getUuid ());
2107+ String copyUrl = null ;
2108+ try {
2109+ AsyncCallFuture <CreateCmdResult > future = snapshotSrv .queryCopySnapshot (snapshotOnSecondary );
2110+ CreateCmdResult result = future .get ();
2111+ if (!result .isFailed ()) {
2112+ copyUrl = result .getPath ();
2113+ }
2114+ } catch (InterruptedException | ExecutionException | ResourceUnavailableException ex ) {
2115+ logger .error ("Failed to prepare URL for copy for snapshot ID: {} on store: {}" , snapshotId , srcSecStore , ex );
21322116 }
2133- if (kvmIncrementalSnapshot ) {
2134- ((ImageStoreEntity ) srcSecStore ).deleteExtractUrl (snapshotOnSecondary .getPath (), copyUrl , Upload .Type .SNAPSHOT );
2117+ if (StringUtils .isEmpty (copyUrl )) {
2118+ logger .error ("Unable to prepare URL for copy for snapshot ID: {} on store: {}" , snapshotId , srcSecStore );
2119+ return false ;
21352120 }
2121+ logger .debug (String .format ("Copying snapshot ID: %d to destination zones using download URL: %s" , snapshotId , copyUrl ));
2122+ try {
2123+ AsyncCallFuture <SnapshotResult > future = snapshotSrv .copySnapshot (snapshotOnSecondary , copyUrl , dstSecStore );
2124+ SnapshotResult result = future .get ();
2125+ if (result .isFailed ()) {
2126+ logger .debug ("Copy snapshot ID: {} failed for image store {}: {}" , snapshotId , dstSecStore , result .getResult ());
2127+ return false ;
2128+ }
2129+ snapshotZoneDao .addSnapshotToZone (snapshotId , dstZoneId );
2130+ _resourceLimitMgr .incrementResourceCount (account .getId (), ResourceType .secondary_storage , snapshotDataStoreVO .getSize ());
2131+ if (account .getId () != Account .ACCOUNT_ID_SYSTEM ) {
2132+ SnapshotVO snapshotVO = _snapshotDao .findByIdIncludingRemoved (snapshotId );
2133+ UsageEventUtils .publishUsageEvent (EventTypes .EVENT_SNAPSHOT_COPY , account .getId (), dstZoneId , snapshotId , null , null , null , snapshotVO .getSize (),
2134+ snapshotVO .getSize (), snapshotVO .getClass ().getName (), snapshotVO .getUuid ());
2135+ }
2136+ if (kvmIncrementalSnapshot ) {
2137+ ((ImageStoreEntity ) srcSecStore ).deleteExtractUrl (snapshotOnSecondary .getPath (), copyUrl , Upload .Type .SNAPSHOT );
2138+ }
21362139
2137- return true ;
2138- } catch (InterruptedException | ExecutionException | ResourceUnavailableException ex ) {
2139- logger .debug ("Failed to copy snapshot ID: {} to image store: {}" , snapshotId , dstSecStore );
2140+ return true ;
2141+ } catch (InterruptedException | ExecutionException | ResourceUnavailableException ex ) {
2142+ logger .debug ("Failed to copy snapshot ID: {} to image store: {}" , snapshotId , dstSecStore );
2143+ }
2144+ return false ;
21402145 }
2141- return false ;
21422146 }
21432147
21442148 @ DB
@@ -2170,13 +2174,6 @@ private boolean copySnapshotChainToZone(SnapshotVO snapshotVO, DataStore srcSecS
21702174 if (CollectionUtils .isEmpty (snapshotChain )) {
21712175 return true ;
21722176 }
2173- try {
2174- _resourceLimitMgr .checkResourceLimit (account , ResourceType .secondary_storage , size );
2175- } catch (ResourceAllocationException e ) {
2176- logger .error (String .format ("Unable to allocate secondary storage resources for snapshot chain for %s with size: %d" , snapshotVO , size ), e );
2177- return false ;
2178- }
2179- Collections .reverse (snapshotChain );
21802177 if (dstSecStore == null ) {
21812178 // find all eligible image stores for the destination zone
21822179 List <DataStore > dstSecStores = dataStoreMgr .getImageStoresByScopeExcludingReadOnly (new ZoneScope (destZoneId ));
@@ -2188,15 +2185,21 @@ private boolean copySnapshotChainToZone(SnapshotVO snapshotVO, DataStore srcSecS
21882185 throw new StorageUnavailableException ("Destination zone is not ready, no image store with free capacity" , DataCenter .class , destZoneId );
21892186 }
21902187 }
2191- logger .debug ("Copying snapshot chain for snapshot ID: {} on secondary store: {} of zone ID: {}" , snapshotVO , dstSecStore , destZone );
2192- for (SnapshotDataStoreVO snapshotDataStoreVO : snapshotChain ) {
2193- if (!copySnapshotToZone (snapshotDataStoreVO , srcSecStore , destZone , dstSecStore , account , kvmIncrementalSnapshot )) {
2194- logger .error ("Failed to copy snapshot: {} to zone: {} due to failure to copy snapshot ID: {} from snapshot chain" ,
2195- snapshotVO , destZone , snapshotDataStoreVO .getSnapshotId ());
2196- return false ;
2188+ try (CheckedReservation secondaryStorageReservation = new CheckedReservation (account , ResourceType .secondary_storage , null , null , null , size , null , reservationDao , _resourceLimitMgr )) {
2189+ logger .debug ("Copying snapshot chain for snapshot ID: {} on secondary store: {} of zone ID: {}" , snapshotVO , dstSecStore , destZone );
2190+ Collections .reverse (snapshotChain );
2191+ for (SnapshotDataStoreVO snapshotDataStoreVO : snapshotChain ) {
2192+ if (!copySnapshotToZone (snapshotDataStoreVO , srcSecStore , destZone , dstSecStore , account , kvmIncrementalSnapshot , false )) {
2193+ logger .error ("Failed to copy snapshot: {} to zone: {} due to failure to copy snapshot ID: {} from snapshot chain" ,
2194+ snapshotVO , destZone , snapshotDataStoreVO .getSnapshotId ());
2195+ return false ;
2196+ }
21972197 }
2198+ return true ;
2199+ } catch (ResourceAllocationException e ) {
2200+ logger .error (String .format ("Unable to allocate secondary storage resources for snapshot chain for %s with size: %d" , snapshotVO , size ), e );
2201+ return false ;
21982202 }
2199- return true ;
22002203 }
22012204
22022205 @ DB
0 commit comments