This is an automated email from the ASF dual-hosted git repository.
sureshanaparti pushed a commit to branch 4.16
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.16 by this push:
new 2774bc1 use physical size instead of virtual size for migration.
(#5750)
2774bc1 is described below
commit 2774bc156f0bcd8a44e031a54f1b4ff0a72d1620
Author: dahn <[email protected]>
AuthorDate: Thu Jan 6 12:48:50 2022 +0100
use physical size instead of virtual size for migration. (#5750)
* Use Physical size to evaluate if migration is possible
* Improve logging and consider files skipped as failure in complete
migration
* skipped can't be negative
* remove useless method
* group multidisk templates for secstor migration
* use enum
* Update
engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/DataMigrationUtility.java
Co-authored-by: sureshanaparti
<[email protected]>
Co-authored-by: Pearl Dsilva <[email protected]>
Co-authored-by: Daan Hoogland <[email protected]>
Co-authored-by: Pearl d'Silva <[email protected]>
---
.../engine/subsystem/api/storage/DataObject.java | 2 +
.../api/storage/SecondaryStorageService.java | 3 +-
.../engine/orchestration/DataMigrationUtility.java | 60 +++++++++++++------
.../engine/orchestration/StorageOrchestrator.java | 69 ++++++++++++++++------
.../storage/image/SecondaryStorageServiceImpl.java | 13 +++-
.../storage/image/store/TemplateObject.java | 9 +++
.../cloudstack/storage/volume/VolumeObject.java | 9 +++
.../diagnostics/to/DiagnosticsDataObject.java | 5 ++
8 files changed, 130 insertions(+), 40 deletions(-)
diff --git
a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
index c57b01c..091c09d 100644
---
a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
+++
b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
@@ -33,6 +33,8 @@ public interface DataObject {
Long getSize();
+ long getPhysicalSize();
+
DataObjectType getType();
String getUuid();
diff --git
a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/SecondaryStorageService.java
b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/SecondaryStorageService.java
index 07828fd..90a25c9 100644
---
a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/SecondaryStorageService.java
+++
b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/SecondaryStorageService.java
@@ -39,5 +39,6 @@ public interface SecondaryStorageService {
}
}
- AsyncCallFuture<DataObjectResult> migrateData(DataObject srcDataObject,
DataStore srcDatastore, DataStore destDatastore, Map<DataObject,
Pair<List<SnapshotInfo>, Long>> snapshotChain);
+ AsyncCallFuture<DataObjectResult> migrateData(DataObject srcDataObject,
DataStore srcDatastore, DataStore destDatastore, Map<DataObject,
Pair<List<SnapshotInfo>, Long>> snapshotChain,
+ Map<DataObject,
Pair<List<TemplateInfo>, Long>> templateChain);
}
diff --git
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/DataMigrationUtility.java
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/DataMigrationUtility.java
index 9d044f3..71b1281 100644
---
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/DataMigrationUtility.java
+++
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/DataMigrationUtility.java
@@ -32,9 +32,11 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import
org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
+import
org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.storage.ImageStoreService;
@@ -59,8 +61,11 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.SecondaryStorageVmDao;
+import org.apache.log4j.Logger;
public class DataMigrationUtility {
+ private static Logger LOGGER =
Logger.getLogger(DataMigrationUtility.class);
+
@Inject
SecondaryStorageVmDao secStorageVmDao;
@Inject
@@ -87,19 +92,22 @@ public class DataMigrationUtility {
* the migration is terminated.
*/
private boolean filesReadyToMigrate(Long srcDataStoreId) {
- String[] validStates = new String[]{"Ready", "Allocated",
"Destroying", "Destroyed", "Failed"};
+ State[] validStates = {State.Ready, State.Allocated, State.Destroying,
State.Destroyed, State.Failed};
boolean isReady = true;
List<TemplateDataStoreVO> templates =
templateDataStoreDao.listByStoreId(srcDataStoreId);
for (TemplateDataStoreVO template : templates) {
- isReady &=
(Arrays.asList(validStates).contains(template.getState().toString()));
+ isReady &=
(Arrays.asList(validStates).contains(template.getState()));
+ LOGGER.trace(String.format("template state: %s",
template.getState()));
}
List<SnapshotDataStoreVO> snapshots =
snapshotDataStoreDao.listByStoreId(srcDataStoreId, DataStoreRole.Image);
for (SnapshotDataStoreVO snapshot : snapshots) {
- isReady &=
(Arrays.asList(validStates).contains(snapshot.getState().toString()));
+ isReady &=
(Arrays.asList(validStates).contains(snapshot.getState()));
+ LOGGER.trace(String.format("snapshot state: %s",
snapshot.getState()));
}
List<VolumeDataStoreVO> volumes =
volumeDataStoreDao.listByStoreId(srcDataStoreId);
for (VolumeDataStoreVO volume : volumes) {
- isReady &=
(Arrays.asList(validStates).contains(volume.getState().toString()));
+ isReady &=
(Arrays.asList(validStates).contains(volume.getState()));
+ LOGGER.trace(String.format("volume state: %s", volume.getState()));
}
return isReady;
}
@@ -113,12 +121,17 @@ public class DataMigrationUtility {
return;
}
- protected Long getFileSize(DataObject file, Map<DataObject,
Pair<List<SnapshotInfo>, Long>> snapshotChain) {
- Long size = file.getSize();
+ protected Long getFileSize(DataObject file, Map<DataObject,
Pair<List<SnapshotInfo>, Long>> snapshotChain, Map<DataObject,
Pair<List<TemplateInfo>, Long>> templateChain) {
+ Long size = file.getPhysicalSize();
Pair<List<SnapshotInfo>, Long> chain = snapshotChain.get(file);
+ Pair<List<TemplateInfo>, Long> tempChain = templateChain.get(file);
+
if (file instanceof SnapshotInfo && chain.first() != null &&
!chain.first().isEmpty()) {
size = chain.second();
}
+ if (file instanceof TemplateInfo && tempChain.first() != null &&
!tempChain.first().isEmpty()) {
+ size = tempChain.second();
+ }
return size;
}
@@ -144,9 +157,10 @@ public class DataMigrationUtility {
return new ArrayList<>(temp.keySet());
}
- protected List<DataObject> getSortedValidSourcesList(DataStore
srcDataStore, Map<DataObject, Pair<List<SnapshotInfo>, Long>> snapshotChains) {
+ protected List<DataObject> getSortedValidSourcesList(DataStore
srcDataStore, Map<DataObject, Pair<List<SnapshotInfo>, Long>> snapshotChains,
+ Map<DataObject,
Pair<List<TemplateInfo>, Long>> childTemplates) {
List<DataObject> files = new ArrayList<>();
- files.addAll(getAllReadyTemplates(srcDataStore));
+ files.addAll(getAllReadyTemplates(srcDataStore, childTemplates));
files.addAll(getAllReadySnapshotsAndChains(srcDataStore,
snapshotChains));
files.addAll(getAllReadyVolumes(srcDataStore));
@@ -159,8 +173,8 @@ public class DataMigrationUtility {
Collections.sort(files, new Comparator<DataObject>() {
@Override
public int compare(DataObject o1, DataObject o2) {
- Long size1 = o1.getSize();
- Long size2 = o2.getSize();
+ Long size1 = o1.getPhysicalSize();
+ Long size2 = o2.getPhysicalSize();
if (o1 instanceof SnapshotInfo) {
size1 = snapshotChains.get(o1).second();
}
@@ -173,19 +187,28 @@ public class DataMigrationUtility {
return files;
}
- protected List<DataObject> getAllReadyTemplates(DataStore srcDataStore) {
+ protected List<DataObject> getAllReadyTemplates(DataStore srcDataStore,
Map<DataObject, Pair<List<TemplateInfo>, Long>> childTemplates) {
- List<DataObject> files = new LinkedList<>();
+ List<TemplateInfo> files = new LinkedList<>();
List<TemplateDataStoreVO> templates =
templateDataStoreDao.listByStoreId(srcDataStore.getId());
for (TemplateDataStoreVO template : templates) {
VMTemplateVO templateVO =
templateDao.findById(template.getTemplateId());
if (template.getState() ==
ObjectInDataStoreStateMachine.State.Ready && templateVO != null &&
(!templateVO.isPublicTemplate() ||
(templateVO.isPublicTemplate() && templateVO.getUrl() == null)) &&
- templateVO.getHypervisorType() !=
Hypervisor.HypervisorType.Simulator) {
+ templateVO.getHypervisorType() !=
Hypervisor.HypervisorType.Simulator && templateVO.getParentTemplateId() ==
null) {
files.add(templateFactory.getTemplate(template.getTemplateId(), srcDataStore));
}
}
- return files;
+ for (TemplateInfo template: files) {
+ List<VMTemplateVO> children =
templateDao.listByParentTemplatetId(template.getId());
+ List<TemplateInfo> temps = new ArrayList<>();
+ temps.add(template);
+ for(VMTemplateVO child : children) {
+ temps.add(templateFactory.getTemplate(child.getId(),
srcDataStore));
+ }
+ childTemplates.put(template, new Pair<>(temps,
getTotalChainSize(temps)));
+ }
+ return (List<DataObject>) (List<?>) files;
}
/** Returns parent snapshots and snapshots that do not have any children;
snapshotChains comprises of the snapshot chain info
@@ -217,21 +240,20 @@ public class DataMigrationUtility {
chain.addAll(children);
}
}
- snapshotChains.put(parent, new Pair<List<SnapshotInfo>,
Long>(chain, getSizeForChain(chain)));
+ snapshotChains.put(parent, new Pair<List<SnapshotInfo>,
Long>(chain, getTotalChainSize(chain)));
}
return (List<DataObject>) (List<?>) files;
}
- protected Long getSizeForChain(List<SnapshotInfo> chain) {
+ protected Long getTotalChainSize(List<? extends DataObject> chain) {
Long size = 0L;
- for (SnapshotInfo snapshot : chain) {
- size += snapshot.getSize();
+ for (DataObject dataObject : chain) {
+ size += dataObject.getPhysicalSize();
}
return size;
}
-
protected List<DataObject> getAllReadyVolumes(DataStore srcDataStore) {
List<DataObject> files = new LinkedList<>();
List<VolumeDataStoreVO> volumes =
volumeDataStoreDao.listByStoreId(srcDataStore.getId());
diff --git
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/StorageOrchestrator.java
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/StorageOrchestrator.java
index 2046ada..01c7f72 100644
---
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/StorageOrchestrator.java
+++
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/StorageOrchestrator.java
@@ -44,6 +44,7 @@ import
org.apache.cloudstack.engine.subsystem.api.storage.SecondaryStorageServic
import
org.apache.cloudstack.engine.subsystem.api.storage.SecondaryStorageService.DataObjectResult;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
@@ -144,10 +145,11 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
migrationHelper.checkIfCompleteMigrationPossible(migrationPolicy,
srcDataStoreId);
DataStore srcDatastore = dataStoreManager.getDataStore(srcDataStoreId,
DataStoreRole.Image);
Map<DataObject, Pair<List<SnapshotInfo>, Long>> snapshotChains = new
HashMap<>();
- files = migrationHelper.getSortedValidSourcesList(srcDatastore,
snapshotChains);
+ Map<DataObject, Pair<List<TemplateInfo>, Long>> childTemplates = new
HashMap<>();
+ files = migrationHelper.getSortedValidSourcesList(srcDatastore,
snapshotChains, childTemplates);
if (files.isEmpty()) {
- return new MigrationResponse("No files in Image store
"+srcDatastore.getId()+ " to migrate", migrationPolicy.toString(), true);
+ return new MigrationResponse(String.format("No files in Image
store: %s to migrate", srcDatastore.getId()), migrationPolicy.toString(), true);
}
Map<Long, Pair<Long, Long>> storageCapacities = new Hashtable<>();
for (Long storeId : destDatastores) {
@@ -155,7 +157,7 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
}
storageCapacities.put(srcDataStoreId, new Pair<>(null, null));
if (migrationPolicy == MigrationPolicy.COMPLETE) {
- s_logger.debug("Setting source image store "+srcDatastore.getId()+
" to read-only");
+ s_logger.debug(String.format("Setting source image store: %s to
read-only", srcDatastore.getId()));
storageService.updateImageStoreStatus(srcDataStoreId, true);
}
@@ -172,6 +174,7 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
return response;
}
+ int skipped = 0;
List<Future<AsyncCallFuture<DataObjectResult>>> futures = new
ArrayList<>();
while (true) {
DataObject chosenFileForMigration = null;
@@ -184,7 +187,7 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
Long destDatastoreId = orderedDS.get(0);
if (chosenFileForMigration == null || destDatastoreId == null ||
(destDatastoreId == srcDatastore.getId() && migrationPolicy ==
MigrationPolicy.BALANCE) ) {
- Pair<String, Boolean> result =
migrateCompleted(destDatastoreId, srcDatastore, files, migrationPolicy);
+ Pair<String, Boolean> result =
migrateCompleted(destDatastoreId, srcDatastore, files, migrationPolicy,
skipped);
message = result.first();
success = result.second();
break;
@@ -194,13 +197,14 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
destDatastoreId = orderedDS.get(1);
}
- if (chosenFileForMigration.getSize() >
storageCapacities.get(destDatastoreId).first()) {
- s_logger.debug("file: " + chosenFileForMigration.getId() + "
too large to be migrated to " + destDatastoreId);
+ if (chosenFileForMigration.getPhysicalSize() >
storageCapacities.get(destDatastoreId).first()) {
+ s_logger.debug(String.format("%s: %s too large to be migrated
to %s", chosenFileForMigration.getType().name() ,
chosenFileForMigration.getUuid(), destDatastoreId));
+ skipped += 1;
continue;
}
- if (shouldMigrate(chosenFileForMigration, srcDatastore.getId(),
destDatastoreId, storageCapacities, snapshotChains, migrationPolicy)) {
- storageCapacities = migrateAway(chosenFileForMigration,
storageCapacities, snapshotChains, srcDatastore, destDatastoreId, executor,
futures);
+ if (shouldMigrate(chosenFileForMigration, srcDatastore.getId(),
destDatastoreId, storageCapacities, snapshotChains, childTemplates,
migrationPolicy)) {
+ storageCapacities = migrateAway(chosenFileForMigration,
storageCapacities, snapshotChains, childTemplates, srcDatastore,
destDatastoreId, executor, futures);
} else {
if (migrationPolicy == MigrationPolicy.BALANCE) {
continue;
@@ -215,7 +219,7 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
return handleResponse(futures, migrationPolicy, message, success);
}
- protected Pair<String, Boolean> migrateCompleted(Long destDatastoreId,
DataStore srcDatastore, List<DataObject> files, MigrationPolicy
migrationPolicy) {
+ protected Pair<String, Boolean> migrateCompleted(Long destDatastoreId,
DataStore srcDatastore, List<DataObject> files, MigrationPolicy
migrationPolicy, int skipped) {
String message = "";
boolean success = true;
if (destDatastoreId == srcDatastore.getId() && !files.isEmpty()) {
@@ -233,14 +237,27 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
}
} else {
message = "Migration completed";
+ if (migrationPolicy == MigrationPolicy.COMPLETE && skipped > 0) {
+ message += ". Not all data objects were migrated. Some were
probably skipped due to lack of storage capacity.";
+ success = false;
+ }
}
return new Pair<String, Boolean>(message, success);
}
- protected Map<Long, Pair<Long, Long>> migrateAway(DataObject
chosenFileForMigration, Map<Long, Pair<Long, Long>> storageCapacities,
- Map<DataObject, Pair<List<SnapshotInfo>, Long>>
snapshotChains, DataStore srcDatastore, Long destDatastoreId,
ThreadPoolExecutor executor,
- List<Future<AsyncCallFuture<DataObjectResult>>> futures) {
- Long fileSize = migrationHelper.getFileSize(chosenFileForMigration,
snapshotChains);
+ protected Map<Long, Pair<Long, Long>> migrateAway(
+ DataObject chosenFileForMigration,
+ Map<Long, Pair<Long, Long>> storageCapacities,
+ Map<DataObject,
+ Pair<List<SnapshotInfo>, Long>> snapshotChains,
+ Map<DataObject, Pair<List<TemplateInfo>, Long>> templateChains,
+ DataStore srcDatastore,
+ Long destDatastoreId,
+ ThreadPoolExecutor executor,
+ List<Future<AsyncCallFuture<DataObjectResult>>> futures) {
+
+ Long fileSize = migrationHelper.getFileSize(chosenFileForMigration,
snapshotChains, templateChains);
+
storageCapacities = assumeMigrate(storageCapacities,
srcDatastore.getId(), destDatastoreId, fileSize);
long activeSsvms = migrationHelper.activeSSVMCount(srcDatastore);
long totalJobs = activeSsvms * numConcurrentCopyTasksPerSSVM;
@@ -254,8 +271,11 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
if (chosenFileForMigration instanceof SnapshotInfo ) {
task.setSnapshotChains(snapshotChains);
}
+ if (chosenFileForMigration instanceof TemplateInfo) {
+ task.setTemplateChain(templateChains);
+ }
futures.add((executor.submit(task)));
- s_logger.debug("Migration of file " + chosenFileForMigration.getId()
+ " is initiated");
+ s_logger.debug(String.format("Migration of %s: %s is initiated. ",
chosenFileForMigration.getType().name(), chosenFileForMigration.getUuid()));
return storageCapacities;
}
@@ -374,13 +394,19 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
* @param migrationPolicy determines whether a "Balance" or "Complete"
migration operation is to be performed
* @return
*/
- private boolean shouldMigrate(DataObject chosenFile, Long srcDatastoreId,
Long destDatastoreId, Map<Long, Pair<Long, Long>> storageCapacities,
- Map<DataObject, Pair<List<SnapshotInfo>,
Long>> snapshotChains, MigrationPolicy migrationPolicy) {
+ private boolean shouldMigrate(
+ DataObject chosenFile,
+ Long srcDatastoreId,
+ Long destDatastoreId,
+ Map<Long, Pair<Long, Long>> storageCapacities,
+ Map<DataObject, Pair<List<SnapshotInfo>, Long>> snapshotChains,
+ Map<DataObject, Pair<List<TemplateInfo>, Long>> templateChains,
+ MigrationPolicy migrationPolicy) {
if (migrationPolicy == MigrationPolicy.BALANCE) {
double meanStdDevCurrent = getStandardDeviation(storageCapacities);
- Long fileSize = migrationHelper.getFileSize(chosenFile,
snapshotChains);
+ Long fileSize = migrationHelper.getFileSize(chosenFile,
snapshotChains, templateChains);
Map<Long, Pair<Long, Long>> proposedCapacities =
assumeMigrate(storageCapacities, srcDatastoreId, destDatastoreId, fileSize);
double meanStdDevAfter = getStandardDeviation(proposedCapacities);
@@ -426,6 +452,7 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
private DataStore srcDataStore;
private DataStore destDataStore;
private Map<DataObject, Pair<List<SnapshotInfo>, Long>> snapshotChain;
+ private Map<DataObject, Pair<List<TemplateInfo>, Long>> templateChain;
public MigrateDataTask(DataObject file, DataStore srcDataStore,
DataStore destDataStore) {
this.file = file;
this.srcDataStore = srcDataStore;
@@ -439,13 +466,19 @@ public class StorageOrchestrator extends ManagerBase
implements StorageOrchestra
public Map<DataObject, Pair<List<SnapshotInfo>, Long>>
getSnapshotChain() {
return snapshotChain;
}
+ public Map<DataObject, Pair<List<TemplateInfo>, Long>>
getTemplateChain() {
+ return templateChain;
+ }
+ public void setTemplateChain(Map<DataObject, Pair<List<TemplateInfo>,
Long>> templateChain) {
+ this.templateChain = templateChain;
+ }
public DataObject getFile() {
return file;
}
@Override
public AsyncCallFuture<DataObjectResult> call() throws Exception {
- return secStgSrv.migrateData(file, srcDataStore, destDataStore,
snapshotChain);
+ return secStgSrv.migrateData(file, srcDataStore, destDataStore,
snapshotChain, templateChain);
}
}
}
diff --git
a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/SecondaryStorageServiceImpl.java
b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/SecondaryStorageServiceImpl.java
index 523c240..5b6d806 100644
---
a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/SecondaryStorageServiceImpl.java
+++
b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/SecondaryStorageServiceImpl.java
@@ -83,7 +83,8 @@ public class SecondaryStorageServiceImpl implements
SecondaryStorageService {
}
@Override
- public AsyncCallFuture<DataObjectResult> migrateData(DataObject
srcDataObject, DataStore srcDatastore, DataStore destDatastore, Map<DataObject,
Pair<List<SnapshotInfo>, Long>> snapshotChain) {
+ public AsyncCallFuture<DataObjectResult> migrateData(DataObject
srcDataObject, DataStore srcDatastore, DataStore destDatastore,
+ Map<DataObject,
Pair<List<SnapshotInfo>, Long>> snapshotChain, Map<DataObject,
Pair<List<TemplateInfo>, Long>> templateChain) {
AsyncCallFuture<DataObjectResult> future = new
AsyncCallFuture<DataObjectResult>();
DataObjectResult res = new DataObjectResult(srcDataObject);
DataObject destDataObject = null;
@@ -114,7 +115,15 @@ public class SecondaryStorageServiceImpl implements
SecondaryStorageService {
break;
}
}
- } else {
+ } else if (srcDataObject instanceof TemplateInfo && templateChain
!= null && templateChain.containsKey(srcDataObject)) {
+ for (TemplateInfo templateInfo :
templateChain.get(srcDataObject).first()) {
+ destDataObject = destDatastore.create(templateInfo);
+
templateInfo.processEvent(ObjectInDataStoreStateMachine.Event.MigrateDataRequested);
+
destDataObject.processEvent(ObjectInDataStoreStateMachine.Event.MigrateDataRequested);
+ migrateJob(future, templateInfo, destDataObject,
destDatastore);
+ }
+ }
+ else {
// Check if template in destination store, if yes, do not
proceed
if (srcDataObject instanceof TemplateInfo) {
s_logger.debug("Checking if template present at
destination");
diff --git
a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/store/TemplateObject.java
b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/store/TemplateObject.java
index c8b78aa..8f857a2 100644
---
a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/store/TemplateObject.java
+++
b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/store/TemplateObject.java
@@ -142,6 +142,15 @@ public class TemplateObject implements TemplateInfo {
}
@Override
+ public long getPhysicalSize() {
+ TemplateDataStoreVO templateDataStoreVO =
templateStoreDao.findByTemplate(imageVO.getId(), DataStoreRole.Image);
+ if (templateDataStoreVO != null) {
+ return templateDataStoreVO.getPhysicalSize();
+ }
+ return imageVO.getSize();
+ }
+
+ @Override
public DataObjectType getType() {
return DataObjectType.TEMPLATE;
}
diff --git
a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java
b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java
index 705d812..29405be 100644
---
a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java
+++
b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java
@@ -232,6 +232,15 @@ public class VolumeObject implements VolumeInfo {
}
@Override
+ public long getPhysicalSize() {
+ VolumeDataStoreVO volumeDataStoreVO =
volumeStoreDao.findByVolume(volumeVO.getId());
+ if (volumeDataStoreVO != null) {
+ return volumeDataStoreVO.getPhysicalSize();
+ }
+ return volumeVO.getSize();
+ }
+
+ @Override
public Long getBytesReadRate() {
return
getLongValueFromDiskOfferingVoMethod(DiskOfferingVO::getBytesReadRate);
}
diff --git
a/server/src/main/java/org/apache/cloudstack/diagnostics/to/DiagnosticsDataObject.java
b/server/src/main/java/org/apache/cloudstack/diagnostics/to/DiagnosticsDataObject.java
index 7736e63..ebe1d7f 100644
---
a/server/src/main/java/org/apache/cloudstack/diagnostics/to/DiagnosticsDataObject.java
+++
b/server/src/main/java/org/apache/cloudstack/diagnostics/to/DiagnosticsDataObject.java
@@ -60,6 +60,11 @@ public class DiagnosticsDataObject implements DataObject {
}
@Override
+ public long getPhysicalSize() {
+ return 0;
+ }
+
+ @Override
public DataObjectType getType() {
return dataTO.getObjectType();
}