4444import org .apache .cloudstack .engine .subsystem .api .storage .SecondaryStorageService .DataObjectResult ;
4545import org .apache .cloudstack .engine .subsystem .api .storage .SnapshotDataFactory ;
4646import org .apache .cloudstack .engine .subsystem .api .storage .SnapshotInfo ;
47+ import org .apache .cloudstack .engine .subsystem .api .storage .TemplateInfo ;
4748import org .apache .cloudstack .framework .async .AsyncCallFuture ;
4849import org .apache .cloudstack .framework .config .ConfigKey ;
4950import org .apache .cloudstack .framework .config .Configurable ;
@@ -144,18 +145,19 @@ public MigrationResponse migrateData(Long srcDataStoreId, List<Long> destDatasto
144145 migrationHelper .checkIfCompleteMigrationPossible (migrationPolicy , srcDataStoreId );
145146 DataStore srcDatastore = dataStoreManager .getDataStore (srcDataStoreId , DataStoreRole .Image );
146147 Map <DataObject , Pair <List <SnapshotInfo >, Long >> snapshotChains = new HashMap <>();
147- files = migrationHelper .getSortedValidSourcesList (srcDatastore , snapshotChains );
148+ Map <DataObject , Pair <List <TemplateInfo >, Long >> childTemplates = new HashMap <>();
149+ files = migrationHelper .getSortedValidSourcesList (srcDatastore , snapshotChains , childTemplates );
148150
149151 if (files .isEmpty ()) {
150- return new MigrationResponse ("No files in Image store " + srcDatastore .getId ()+ " to migrate" , migrationPolicy .toString (), true );
152+ return new MigrationResponse (String . format ( "No files in Image store: %s to migrate" , srcDatastore .getId ()) , migrationPolicy .toString (), true );
151153 }
152154 Map <Long , Pair <Long , Long >> storageCapacities = new Hashtable <>();
153155 for (Long storeId : destDatastores ) {
154156 storageCapacities .put (storeId , new Pair <>(null , null ));
155157 }
156158 storageCapacities .put (srcDataStoreId , new Pair <>(null , null ));
157159 if (migrationPolicy == MigrationPolicy .COMPLETE ) {
158- s_logger .debug ("Setting source image store " + srcDatastore . getId ()+ " to read-only" );
160+ s_logger .debug (String . format ( "Setting source image store: %s to read-only" , srcDatastore . getId ()) );
159161 storageService .updateImageStoreStatus (srcDataStoreId , true );
160162 }
161163
@@ -172,6 +174,7 @@ public MigrationResponse migrateData(Long srcDataStoreId, List<Long> destDatasto
172174 return response ;
173175 }
174176
177+ int skipped = 0 ;
175178 List <Future <AsyncCallFuture <DataObjectResult >>> futures = new ArrayList <>();
176179 while (true ) {
177180 DataObject chosenFileForMigration = null ;
@@ -184,7 +187,7 @@ public MigrationResponse migrateData(Long srcDataStoreId, List<Long> destDatasto
184187 Long destDatastoreId = orderedDS .get (0 );
185188
186189 if (chosenFileForMigration == null || destDatastoreId == null || (destDatastoreId == srcDatastore .getId () && migrationPolicy == MigrationPolicy .BALANCE ) ) {
187- Pair <String , Boolean > result = migrateCompleted (destDatastoreId , srcDatastore , files , migrationPolicy );
190+ Pair <String , Boolean > result = migrateCompleted (destDatastoreId , srcDatastore , files , migrationPolicy , skipped );
188191 message = result .first ();
189192 success = result .second ();
190193 break ;
@@ -194,13 +197,14 @@ public MigrationResponse migrateData(Long srcDataStoreId, List<Long> destDatasto
194197 destDatastoreId = orderedDS .get (1 );
195198 }
196199
197- if (chosenFileForMigration .getSize () > storageCapacities .get (destDatastoreId ).first ()) {
198- s_logger .debug ("file: " + chosenFileForMigration .getId () + " too large to be migrated to " + destDatastoreId );
200+ if (chosenFileForMigration .getPhysicalSize () > storageCapacities .get (destDatastoreId ).first ()) {
201+ s_logger .debug (String .format ("%s: %s too large to be migrated to %s" , chosenFileForMigration .getType ().name () , chosenFileForMigration .getUuid (), destDatastoreId ));
202+ skipped += 1 ;
199203 continue ;
200204 }
201205
202- if (shouldMigrate (chosenFileForMigration , srcDatastore .getId (), destDatastoreId , storageCapacities , snapshotChains , migrationPolicy )) {
203- storageCapacities = migrateAway (chosenFileForMigration , storageCapacities , snapshotChains , srcDatastore , destDatastoreId , executor , futures );
206+ if (shouldMigrate (chosenFileForMigration , srcDatastore .getId (), destDatastoreId , storageCapacities , snapshotChains , childTemplates , migrationPolicy )) {
207+ storageCapacities = migrateAway (chosenFileForMigration , storageCapacities , snapshotChains , childTemplates , srcDatastore , destDatastoreId , executor , futures );
204208 } else {
205209 if (migrationPolicy == MigrationPolicy .BALANCE ) {
206210 continue ;
@@ -215,7 +219,7 @@ public MigrationResponse migrateData(Long srcDataStoreId, List<Long> destDatasto
215219 return handleResponse (futures , migrationPolicy , message , success );
216220 }
217221
218- protected Pair <String , Boolean > migrateCompleted (Long destDatastoreId , DataStore srcDatastore , List <DataObject > files , MigrationPolicy migrationPolicy ) {
222+ protected Pair <String , Boolean > migrateCompleted (Long destDatastoreId , DataStore srcDatastore , List <DataObject > files , MigrationPolicy migrationPolicy , int skipped ) {
219223 String message = "" ;
220224 boolean success = true ;
221225 if (destDatastoreId == srcDatastore .getId () && !files .isEmpty ()) {
@@ -233,14 +237,27 @@ protected Pair<String, Boolean> migrateCompleted(Long destDatastoreId, DataStore
233237 }
234238 } else {
235239 message = "Migration completed" ;
240+ if (migrationPolicy == MigrationPolicy .COMPLETE && skipped > 0 ) {
241+ message += ". Not all data objects were migrated. Some were probably skipped due to lack of storage capacity." ;
242+ success = false ;
243+ }
236244 }
237245 return new Pair <String , Boolean >(message , success );
238246 }
239247
240- protected Map <Long , Pair <Long , Long >> migrateAway (DataObject chosenFileForMigration , Map <Long , Pair <Long , Long >> storageCapacities ,
241- Map <DataObject , Pair <List <SnapshotInfo >, Long >> snapshotChains , DataStore srcDatastore , Long destDatastoreId , ThreadPoolExecutor executor ,
242- List <Future <AsyncCallFuture <DataObjectResult >>> futures ) {
243- Long fileSize = migrationHelper .getFileSize (chosenFileForMigration , snapshotChains );
248+ protected Map <Long , Pair <Long , Long >> migrateAway (
249+ DataObject chosenFileForMigration ,
250+ Map <Long , Pair <Long , Long >> storageCapacities ,
251+ Map <DataObject ,
252+ Pair <List <SnapshotInfo >, Long >> snapshotChains ,
253+ Map <DataObject , Pair <List <TemplateInfo >, Long >> templateChains ,
254+ DataStore srcDatastore ,
255+ Long destDatastoreId ,
256+ ThreadPoolExecutor executor ,
257+ List <Future <AsyncCallFuture <DataObjectResult >>> futures ) {
258+
259+ Long fileSize = migrationHelper .getFileSize (chosenFileForMigration , snapshotChains , templateChains );
260+
244261 storageCapacities = assumeMigrate (storageCapacities , srcDatastore .getId (), destDatastoreId , fileSize );
245262 long activeSsvms = migrationHelper .activeSSVMCount (srcDatastore );
246263 long totalJobs = activeSsvms * numConcurrentCopyTasksPerSSVM ;
@@ -254,8 +271,11 @@ protected Map<Long, Pair<Long, Long>> migrateAway(DataObject chosenFileForMigrat
254271 if (chosenFileForMigration instanceof SnapshotInfo ) {
255272 task .setSnapshotChains (snapshotChains );
256273 }
274+ if (chosenFileForMigration instanceof TemplateInfo ) {
275+ task .setTemplateChain (templateChains );
276+ }
257277 futures .add ((executor .submit (task )));
258- s_logger .debug ("Migration of file " + chosenFileForMigration .getId () + " is initiated" );
278+ s_logger .debug (String . format ( "Migration of %s: %s is initiated. " , chosenFileForMigration .getType (). name (), chosenFileForMigration . getUuid ()) );
259279 return storageCapacities ;
260280 }
261281
@@ -374,13 +394,19 @@ private Map<Long, Pair<Long, Long>> assumeMigrate(Map<Long, Pair<Long, Long>> st
374394 * @param migrationPolicy determines whether a "Balance" or "Complete" migration operation is to be performed
375395 * @return
376396 */
377- private boolean shouldMigrate (DataObject chosenFile , Long srcDatastoreId , Long destDatastoreId , Map <Long , Pair <Long , Long >> storageCapacities ,
378- Map <DataObject , Pair <List <SnapshotInfo >, Long >> snapshotChains , MigrationPolicy migrationPolicy ) {
397+ private boolean shouldMigrate (
398+ DataObject chosenFile ,
399+ Long srcDatastoreId ,
400+ Long destDatastoreId ,
401+ Map <Long , Pair <Long , Long >> storageCapacities ,
402+ Map <DataObject , Pair <List <SnapshotInfo >, Long >> snapshotChains ,
403+ Map <DataObject , Pair <List <TemplateInfo >, Long >> templateChains ,
404+ MigrationPolicy migrationPolicy ) {
379405
380406 if (migrationPolicy == MigrationPolicy .BALANCE ) {
381407 double meanStdDevCurrent = getStandardDeviation (storageCapacities );
382408
383- Long fileSize = migrationHelper .getFileSize (chosenFile , snapshotChains );
409+ Long fileSize = migrationHelper .getFileSize (chosenFile , snapshotChains , templateChains );
384410 Map <Long , Pair <Long , Long >> proposedCapacities = assumeMigrate (storageCapacities , srcDatastoreId , destDatastoreId , fileSize );
385411 double meanStdDevAfter = getStandardDeviation (proposedCapacities );
386412
@@ -426,6 +452,7 @@ private class MigrateDataTask implements Callable<AsyncCallFuture<DataObjectResu
426452 private DataStore srcDataStore ;
427453 private DataStore destDataStore ;
428454 private Map <DataObject , Pair <List <SnapshotInfo >, Long >> snapshotChain ;
455+ private Map <DataObject , Pair <List <TemplateInfo >, Long >> templateChain ;
429456 public MigrateDataTask (DataObject file , DataStore srcDataStore , DataStore destDataStore ) {
430457 this .file = file ;
431458 this .srcDataStore = srcDataStore ;
@@ -439,13 +466,19 @@ public void setSnapshotChains(Map<DataObject, Pair<List<SnapshotInfo>, Long>> sn
439466 public Map <DataObject , Pair <List <SnapshotInfo >, Long >> getSnapshotChain () {
440467 return snapshotChain ;
441468 }
469+ public Map <DataObject , Pair <List <TemplateInfo >, Long >> getTemplateChain () {
470+ return templateChain ;
471+ }
472+ public void setTemplateChain (Map <DataObject , Pair <List <TemplateInfo >, Long >> templateChain ) {
473+ this .templateChain = templateChain ;
474+ }
442475 public DataObject getFile () {
443476 return file ;
444477 }
445478
446479 @ Override
447480 public AsyncCallFuture <DataObjectResult > call () throws Exception {
448- return secStgSrv .migrateData (file , srcDataStore , destDataStore , snapshotChain );
481+ return secStgSrv .migrateData (file , srcDataStore , destDataStore , snapshotChain , templateChain );
449482 }
450483 }
451484}
0 commit comments