Skip to content

Commit e666dca

Browse files
authored
linked clone for file based storage (#8911)
1 parent 2e4dd69 commit e666dca

File tree

2 files changed

+43
-32
lines changed

2 files changed

+43
-32
lines changed

engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,25 +1957,26 @@ protected MigrationOptions createFullCloneMigrationOptions(VolumeInfo srcVolumeI
19571957
* - Full clones (no backing file): Take snapshot of the VM prior disk creation
19581958
* Return this information
19591959
*/
1960-
protected void setVolumeMigrationOptions(VolumeInfo srcVolumeInfo, VolumeInfo destVolumeInfo,
1961-
VirtualMachineTO vmTO, Host srcHost, StoragePoolVO destStoragePool) {
1962-
if (!destStoragePool.isManaged()) {
1963-
String srcVolumeBackingFile = getVolumeBackingFile(srcVolumeInfo);
1964-
1965-
String srcPoolUuid = srcVolumeInfo.getDataStore().getUuid();
1966-
StoragePoolVO srcPool = _storagePoolDao.findById(srcVolumeInfo.getPoolId());
1967-
Storage.StoragePoolType srcPoolType = srcPool.getPoolType();
1968-
1969-
MigrationOptions migrationOptions;
1970-
if (StringUtils.isNotBlank(srcVolumeBackingFile)) {
1971-
migrationOptions = createLinkedCloneMigrationOptions(srcVolumeInfo, destVolumeInfo,
1972-
srcVolumeBackingFile, srcPoolUuid, srcPoolType);
1973-
} else {
1974-
migrationOptions = createFullCloneMigrationOptions(srcVolumeInfo, vmTO, srcHost, srcPoolUuid, srcPoolType);
1975-
}
1976-
migrationOptions.setTimeout(StorageManager.KvmStorageOnlineMigrationWait.value());
1977-
destVolumeInfo.setMigrationOptions(migrationOptions);
1960+
protected void setVolumeMigrationOptions(VolumeInfo srcVolumeInfo, VolumeInfo destVolumeInfo, VirtualMachineTO vmTO, Host srcHost, StoragePoolVO destStoragePool,
1961+
MigrationOptions.Type migrationType) {
1962+
if (destStoragePool.isManaged()) {
1963+
return;
1964+
}
1965+
1966+
String srcVolumeBackingFile = getVolumeBackingFile(srcVolumeInfo);
1967+
1968+
String srcPoolUuid = srcVolumeInfo.getDataStore().getUuid();
1969+
StoragePoolVO srcPool = _storagePoolDao.findById(srcVolumeInfo.getPoolId());
1970+
Storage.StoragePoolType srcPoolType = srcPool.getPoolType();
1971+
1972+
MigrationOptions migrationOptions;
1973+
if (MigrationOptions.Type.LinkedClone.equals(migrationType)) {
1974+
migrationOptions = createLinkedCloneMigrationOptions(srcVolumeInfo, destVolumeInfo, srcVolumeBackingFile, srcPoolUuid, srcPoolType);
1975+
} else {
1976+
migrationOptions = createFullCloneMigrationOptions(srcVolumeInfo, vmTO, srcHost, srcPoolUuid, srcPoolType);
19781977
}
1978+
migrationOptions.setTimeout(StorageManager.KvmStorageOnlineMigrationWait.value());
1979+
destVolumeInfo.setMigrationOptions(migrationOptions);
19791980
}
19801981

19811982
/**
@@ -2006,6 +2007,7 @@ public void copyAsync(Map<VolumeInfo, DataStore> volumeDataStoreMap, VirtualMach
20062007
Map<VolumeInfo, VolumeInfo> srcVolumeInfoToDestVolumeInfo = new HashMap<>();
20072008

20082009
boolean managedStorageDestination = false;
2010+
boolean migrateNonSharedInc = false;
20092011
for (Map.Entry<VolumeInfo, DataStore> entry : volumeDataStoreMap.entrySet()) {
20102012
VolumeInfo srcVolumeInfo = entry.getKey();
20112013
DataStore destDataStore = entry.getValue();
@@ -2023,15 +2025,8 @@ public void copyAsync(Map<VolumeInfo, DataStore> volumeDataStoreMap, VirtualMach
20232025
continue;
20242026
}
20252027

2026-
VMTemplateVO vmTemplate = _vmTemplateDao.findById(vmInstance.getTemplateId());
2027-
if (srcVolumeInfo.getTemplateId() != null &&
2028-
Objects.nonNull(vmTemplate) &&
2029-
!Arrays.asList(KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME, VM_IMPORT_DEFAULT_TEMPLATE_NAME).contains(vmTemplate.getName())) {
2030-
LOGGER.debug(String.format("Copying template [%s] of volume [%s] from source storage pool [%s] to target storage pool [%s].", srcVolumeInfo.getTemplateId(), srcVolumeInfo.getId(), sourceStoragePool.getId(), destStoragePool.getId()));
2031-
copyTemplateToTargetFilesystemStorageIfNeeded(srcVolumeInfo, sourceStoragePool, destDataStore, destStoragePool, destHost);
2032-
} else {
2033-
LOGGER.debug(String.format("Skipping copy template from source storage pool [%s] to target storage pool [%s] before migration due to volume [%s] does not have a template.", sourceStoragePool.getId(), destStoragePool.getId(), srcVolumeInfo.getId()));
2034-
}
2028+
MigrationOptions.Type migrationType = decideMigrationTypeAndCopyTemplateIfNeeded(destHost, vmInstance, srcVolumeInfo, sourceStoragePool, destStoragePool, destDataStore);
2029+
migrateNonSharedInc = migrateNonSharedInc || MigrationOptions.Type.LinkedClone.equals(migrationType);
20352030

20362031
VolumeVO destVolume = duplicateVolumeOnAnotherStorage(srcVolume, destStoragePool);
20372032
VolumeInfo destVolumeInfo = _volumeDataFactory.getVolume(destVolume.getId(), destDataStore);
@@ -2043,7 +2038,7 @@ public void copyAsync(Map<VolumeInfo, DataStore> volumeDataStoreMap, VirtualMach
20432038
// move the volume from Ready to Migrating
20442039
destVolumeInfo.processEvent(Event.MigrationRequested);
20452040

2046-
setVolumeMigrationOptions(srcVolumeInfo, destVolumeInfo, vmTO, srcHost, destStoragePool);
2041+
setVolumeMigrationOptions(srcVolumeInfo, destVolumeInfo, vmTO, srcHost, destStoragePool, migrationType);
20472042

20482043
// create a volume on the destination storage
20492044
destDataStore.getDriver().createAsync(destDataStore, destVolumeInfo, null);
@@ -2058,7 +2053,7 @@ public void copyAsync(Map<VolumeInfo, DataStore> volumeDataStoreMap, VirtualMach
20582053

20592054
_volumeDao.update(destVolume.getId(), destVolume);
20602055

2061-
postVolumeCreationActions(srcVolumeInfo, destVolumeInfo, vmTO, srcHost);
2056+
postVolumeCreationActions(srcVolumeInfo, destVolumeInfo);
20622057

20632058
destVolumeInfo = _volumeDataFactory.getVolume(destVolume.getId(), destDataStore);
20642059

@@ -2109,8 +2104,6 @@ public void copyAsync(Map<VolumeInfo, DataStore> volumeDataStoreMap, VirtualMach
21092104
VMInstanceVO vm = _vmDao.findById(vmTO.getId());
21102105
boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
21112106

2112-
boolean migrateNonSharedInc = isSourceAndDestinationPoolTypeOfNfs(volumeDataStoreMap);
2113-
21142107
MigrateCommand migrateCommand = new MigrateCommand(vmTO.getName(), destHost.getPrivateIpAddress(), isWindows, vmTO, true);
21152108
migrateCommand.setWait(StorageManager.KvmStorageOnlineMigrationWait.value());
21162109
migrateCommand.setMigrateStorage(migrateStorage);
@@ -2160,6 +2153,22 @@ public void copyAsync(Map<VolumeInfo, DataStore> volumeDataStoreMap, VirtualMach
21602153
}
21612154
}
21622155

2156+
private MigrationOptions.Type decideMigrationTypeAndCopyTemplateIfNeeded(Host destHost, VMInstanceVO vmInstance, VolumeInfo srcVolumeInfo, StoragePoolVO sourceStoragePool, StoragePoolVO destStoragePool, DataStore destDataStore) {
2157+
VMTemplateVO vmTemplate = _vmTemplateDao.findById(vmInstance.getTemplateId());
2158+
String srcVolumeBackingFile = getVolumeBackingFile(srcVolumeInfo);
2159+
if (StringUtils.isNotBlank(srcVolumeBackingFile) && supportStoragePoolType(destStoragePool.getPoolType(), StoragePoolType.Filesystem) &&
2160+
srcVolumeInfo.getTemplateId() != null &&
2161+
Objects.nonNull(vmTemplate) &&
2162+
!Arrays.asList(KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME, VM_IMPORT_DEFAULT_TEMPLATE_NAME).contains(vmTemplate.getName())) {
2163+
LOGGER.debug(String.format("Copying template [%s] of volume [%s] from source storage pool [%s] to target storage pool [%s].", srcVolumeInfo.getTemplateId(), srcVolumeInfo.getId(), sourceStoragePool.getId(), destStoragePool.getId()));
2164+
copyTemplateToTargetFilesystemStorageIfNeeded(srcVolumeInfo, sourceStoragePool, destDataStore, destStoragePool, destHost);
2165+
return MigrationOptions.Type.LinkedClone;
2166+
}
2167+
LOGGER.debug(String.format("Skipping copy template from source storage pool [%s] to target storage pool [%s] before migration due to volume [%s] does not have a " +
2168+
"template or we are doing full clone migration.", sourceStoragePool.getId(), destStoragePool.getId(), srcVolumeInfo.getId()));
2169+
return MigrationOptions.Type.FullClone;
2170+
}
2171+
21632172
protected String formatMigrationElementsAsJsonToDisplayOnLog(String objectName, Object object, Object from, Object to){
21642173
return String.format("{%s: \"%s\", from: \"%s\", to:\"%s\"}", objectName, object, from, to);
21652174
}
@@ -2421,7 +2430,7 @@ protected void updateCopiedTemplateReference(VolumeInfo srcVolumeInfo, VolumeInf
24212430
/**
24222431
* Handle post destination volume creation actions depending on the migrating volume type: full clone or linked clone
24232432
*/
2424-
protected void postVolumeCreationActions(VolumeInfo srcVolumeInfo, VolumeInfo destVolumeInfo, VirtualMachineTO vmTO, Host srcHost) {
2433+
protected void postVolumeCreationActions(VolumeInfo srcVolumeInfo, VolumeInfo destVolumeInfo) {
24252434
MigrationOptions migrationOptions = destVolumeInfo.getMigrationOptions();
24262435
if (migrationOptions != null) {
24272436
if (migrationOptions.getType() == MigrationOptions.Type.LinkedClone && migrationOptions.isCopySrcTemplate()) {

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/MigrateKVMAsync.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,10 @@ public Domain call() throws LibvirtException {
122122
if (migrateNonSharedInc) {
123123
flags |= VIR_MIGRATE_PERSIST_DEST;
124124
flags |= VIR_MIGRATE_NON_SHARED_INC;
125+
logger.debug("Setting VIR_MIGRATE_NON_SHARED_INC for linked clone migration.");
125126
} else {
126127
flags |= VIR_MIGRATE_NON_SHARED_DISK;
128+
logger.debug("Setting VIR_MIGRATE_NON_SHARED_DISK for full clone migration.");
127129
}
128130
}
129131

0 commit comments

Comments
 (0)