mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fix for create template from snapshot (for snapshots on primary storage and storage doesn't support create snapshot to template directly) (#11452)
* Fix for create template from snapshot * code improvements, for create volume from snapshot
This commit is contained in:
parent
ba2d70ab21
commit
f671461d4c
@ -579,14 +579,19 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||||||
VolumeInfo vol = volFactory.getVolume(volume.getId());
|
VolumeInfo vol = volFactory.getVolume(volume.getId());
|
||||||
long zoneId = volume.getDataCenterId();
|
long zoneId = volume.getDataCenterId();
|
||||||
DataStore store = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
|
DataStore store = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
|
||||||
DataStoreRole dataStoreRole = snapshotHelper.getDataStoreRole(snapshot, zoneId);
|
DataStoreRole dataStoreRole = snapshotHelper.getDataStoreRole(snapshot);
|
||||||
SnapshotInfo snapInfo = snapshotFactory.getSnapshotWithRoleAndZone(snapshot.getId(), dataStoreRole, zoneId);
|
SnapshotInfo snapInfo = snapshotFactory.getSnapshotWithRoleAndZone(snapshot.getId(), dataStoreRole, zoneId);
|
||||||
|
boolean kvmSnapshotOnlyInPrimaryStorage = snapshotHelper.isKvmSnapshotOnlyInPrimaryStorage(snapshot, dataStoreRole);
|
||||||
|
logger.debug("Creating volume from snapshot, with dataStore role {} and on primary storage: {}", dataStoreRole, kvmSnapshotOnlyInPrimaryStorage);
|
||||||
|
|
||||||
boolean kvmSnapshotOnlyInPrimaryStorage = snapshotHelper.isKvmSnapshotOnlyInPrimaryStorage(snapshot, dataStoreRole, volume.getDataCenterId());
|
|
||||||
boolean storageSupportSnapshotToTemplateEnabled = snapshotHelper.isStorageSupportSnapshotToTemplate(snapInfo);
|
boolean storageSupportSnapshotToTemplateEnabled = snapshotHelper.isStorageSupportSnapshotToTemplate(snapInfo);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!storageSupportSnapshotToTemplateEnabled) {
|
if (storageSupportSnapshotToTemplateEnabled) { // true only for StorPool now [TODO: Update to check storage supports snapshot to volume (DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_SNAPSHOT) - may impact other storages, or StorPool storage type only]
|
||||||
|
dataStoreRole = snapshotHelper.getDataStoreRole(snapshot, zoneId);
|
||||||
|
snapInfo = snapshotFactory.getSnapshotWithRoleAndZone(snapshot.getId(), dataStoreRole, zoneId);
|
||||||
|
kvmSnapshotOnlyInPrimaryStorage = snapshotHelper.isKvmSnapshotOnlyInPrimaryStorage(snapshot, dataStoreRole, zoneId);
|
||||||
|
logger.debug("Creating volume from snapshot for storage supporting snapshot to template, with dataStore role {} and on primary storage: {}", dataStoreRole, kvmSnapshotOnlyInPrimaryStorage);
|
||||||
|
} else {
|
||||||
snapInfo = snapshotHelper.backupSnapshotToSecondaryStorageIfNotExists(snapInfo, dataStoreRole, snapshot, kvmSnapshotOnlyInPrimaryStorage);
|
snapInfo = snapshotHelper.backupSnapshotToSecondaryStorageIfNotExists(snapInfo, dataStoreRole, snapshot, kvmSnapshotOnlyInPrimaryStorage);
|
||||||
}
|
}
|
||||||
} catch (CloudRuntimeException e) {
|
} catch (CloudRuntimeException e) {
|
||||||
@ -600,7 +605,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||||||
}
|
}
|
||||||
|
|
||||||
// don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary
|
// don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary
|
||||||
if (!DataStoreRole.Primary.equals(dataStoreRole) || !storageSupportSnapshotToTemplateEnabled) {
|
if (!DataStoreRole.Primary.equals(dataStoreRole) || (kvmSnapshotOnlyInPrimaryStorage && !storageSupportSnapshotToTemplateEnabled)) {
|
||||||
try {
|
try {
|
||||||
// sync snapshot to region store if necessary
|
// sync snapshot to region store if necessary
|
||||||
DataStore snapStore = snapInfo.getDataStore();
|
DataStore snapStore = snapInfo.getDataStore();
|
||||||
|
|||||||
@ -1692,18 +1692,21 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||||||
if (store == null) {
|
if (store == null) {
|
||||||
throw new CloudRuntimeException("cannot find an image store for zone " + zoneId);
|
throw new CloudRuntimeException("cannot find an image store for zone " + zoneId);
|
||||||
}
|
}
|
||||||
AsyncCallFuture<TemplateApiResult> future = null;
|
AsyncCallFuture<TemplateApiResult> future;
|
||||||
|
|
||||||
if (snapshotId != null) {
|
if (snapshotId != null) {
|
||||||
DataStoreRole dataStoreRole = snapshotHelper.getDataStoreRole(snapshot, zoneId);
|
DataStoreRole dataStoreRole = snapshotHelper.getDataStoreRole(snapshot);
|
||||||
kvmSnapshotOnlyInPrimaryStorage = snapshotHelper.isKvmSnapshotOnlyInPrimaryStorage(snapshot, dataStoreRole, zoneId);
|
kvmSnapshotOnlyInPrimaryStorage = snapshotHelper.isKvmSnapshotOnlyInPrimaryStorage(snapshot, dataStoreRole);
|
||||||
|
|
||||||
snapInfo = _snapshotFactory.getSnapshotWithRoleAndZone(snapshotId, dataStoreRole, zoneId);
|
snapInfo = _snapshotFactory.getSnapshotWithRoleAndZone(snapshotId, dataStoreRole, zoneId);
|
||||||
boolean kvmIncrementalSnapshot = SnapshotManager.kvmIncrementalSnapshot.valueIn(_hostDao.findClusterIdByVolumeInfo(snapInfo.getBaseVolume()));
|
logger.debug("Creating template from snapshot, with dataStore role {} and on primary storage: {}", dataStoreRole, kvmSnapshotOnlyInPrimaryStorage);
|
||||||
|
|
||||||
|
boolean storageSupportsSnapshotToTemplate = snapshotHelper.isStorageSupportSnapshotToTemplate(snapInfo);
|
||||||
|
if (storageSupportsSnapshotToTemplate) {
|
||||||
|
dataStoreRole = snapshotHelper.getDataStoreRole(snapshot, zoneId);
|
||||||
|
kvmSnapshotOnlyInPrimaryStorage = snapshotHelper.isKvmSnapshotOnlyInPrimaryStorage(snapshot, dataStoreRole, zoneId);
|
||||||
|
snapInfo = _snapshotFactory.getSnapshotWithRoleAndZone(snapshotId, dataStoreRole, zoneId);
|
||||||
|
logger.debug("Creating template from snapshot for storage supporting snapshot to template, with dataStore role {} and on primary storage: {}", dataStoreRole, kvmSnapshotOnlyInPrimaryStorage);
|
||||||
|
|
||||||
boolean skipCopyToSecondary = false;
|
|
||||||
boolean keepOnPrimary = snapshotHelper.isStorageSupportSnapshotToTemplate(snapInfo);
|
|
||||||
if (keepOnPrimary) {
|
|
||||||
ImageStoreVO imageStore = _imgStoreDao.findOneByZoneAndProtocol(zoneId, "nfs");
|
ImageStoreVO imageStore = _imgStoreDao.findOneByZoneAndProtocol(zoneId, "nfs");
|
||||||
if (imageStore == null) {
|
if (imageStore == null) {
|
||||||
throw new CloudRuntimeException(String.format("Could not find an NFS secondary storage pool on zone %s to use as a temporary location " +
|
throw new CloudRuntimeException(String.format("Could not find an NFS secondary storage pool on zone %s to use as a temporary location " +
|
||||||
@ -1713,7 +1716,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||||||
if (dataStore != null) {
|
if (dataStore != null) {
|
||||||
store = dataStore;
|
store = dataStore;
|
||||||
}
|
}
|
||||||
} else if (dataStoreRole == DataStoreRole.Image) {
|
} else if (dataStoreRole == DataStoreRole.Image || kvmSnapshotOnlyInPrimaryStorage) {
|
||||||
snapInfo = snapshotHelper.backupSnapshotToSecondaryStorageIfNotExists(snapInfo, dataStoreRole, snapshot, kvmSnapshotOnlyInPrimaryStorage);
|
snapInfo = snapshotHelper.backupSnapshotToSecondaryStorageIfNotExists(snapInfo, dataStoreRole, snapshot, kvmSnapshotOnlyInPrimaryStorage);
|
||||||
_accountMgr.checkAccess(caller, null, true, snapInfo);
|
_accountMgr.checkAccess(caller, null, true, snapInfo);
|
||||||
DataStore snapStore = snapInfo.getDataStore();
|
DataStore snapStore = snapInfo.getDataStore();
|
||||||
@ -1722,6 +1725,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||||||
store = snapStore; // pick snapshot image store to create template
|
store = snapStore; // pick snapshot image store to create template
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean kvmIncrementalSnapshot = SnapshotManager.kvmIncrementalSnapshot.valueIn(_hostDao.findClusterIdByVolumeInfo(snapInfo.getBaseVolume()));
|
||||||
if (kvmIncrementalSnapshot && DataStoreRole.Image.equals(dataStoreRole)) {
|
if (kvmIncrementalSnapshot && DataStoreRole.Image.equals(dataStoreRole)) {
|
||||||
snapInfo = snapshotHelper.convertSnapshotIfNeeded(snapInfo);
|
snapInfo = snapshotHelper.convertSnapshotIfNeeded(snapInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -156,7 +156,8 @@ public class SnapshotHelper {
|
|||||||
public boolean isStorageSupportSnapshotToTemplate(SnapshotInfo snapInfo) {
|
public boolean isStorageSupportSnapshotToTemplate(SnapshotInfo snapInfo) {
|
||||||
if (DataStoreRole.Primary.equals(snapInfo.getDataStore().getRole())) {
|
if (DataStoreRole.Primary.equals(snapInfo.getDataStore().getRole())) {
|
||||||
Map<String, String> capabilities = snapInfo.getDataStore().getDriver().getCapabilities();
|
Map<String, String> capabilities = snapInfo.getDataStore().getDriver().getCapabilities();
|
||||||
return org.apache.commons.collections4.MapUtils.isNotEmpty(capabilities) && capabilities.containsKey(DataStoreCapabilities.CAN_CREATE_TEMPLATE_FROM_SNAPSHOT.toString());
|
return org.apache.commons.collections4.MapUtils.isNotEmpty(capabilities)
|
||||||
|
&& Boolean.parseBoolean(capabilities.get(DataStoreCapabilities.CAN_CREATE_TEMPLATE_FROM_SNAPSHOT.toString()));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -214,22 +215,24 @@ public class SnapshotHelper {
|
|||||||
* @return true if hypervisor is {@link HypervisorType#KVM} and data store role is {@link DataStoreRole#Primary} and global setting "snapshot.backup.to.secondary" is false,
|
* @return true if hypervisor is {@link HypervisorType#KVM} and data store role is {@link DataStoreRole#Primary} and global setting "snapshot.backup.to.secondary" is false,
|
||||||
* else false.
|
* else false.
|
||||||
*/
|
*/
|
||||||
|
public boolean isKvmSnapshotOnlyInPrimaryStorage(Snapshot snapshot, DataStoreRole dataStoreRole) {
|
||||||
|
return snapshot.getHypervisorType() == Hypervisor.HypervisorType.KVM && dataStoreRole == DataStoreRole.Primary && !backupSnapshotAfterTakingSnapshot;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isKvmSnapshotOnlyInPrimaryStorage(Snapshot snapshot, DataStoreRole dataStoreRole, Long zoneId){
|
public boolean isKvmSnapshotOnlyInPrimaryStorage(Snapshot snapshot, DataStoreRole dataStoreRole, Long zoneId){
|
||||||
List<SnapshotJoinVO> snapshots = snapshotJoinDao.listBySnapshotIdAndZoneId(zoneId, snapshot.getSnapshotId());
|
List<SnapshotJoinVO> snapshots = snapshotJoinDao.listBySnapshotIdAndZoneId(zoneId, snapshot.getSnapshotId());
|
||||||
boolean isKvmSnapshotOnlyInPrimaryStorage = snapshots.stream().filter(s -> s.getStoreRole().equals(DataStoreRole.Image)).count() == 0;
|
boolean isKvmSnapshotOnlyInPrimaryStorage = snapshots.stream().noneMatch(s -> s.getStoreRole().equals(DataStoreRole.Image));
|
||||||
|
|
||||||
return snapshot.getHypervisorType() == Hypervisor.HypervisorType.KVM && dataStoreRole == DataStoreRole.Primary && isKvmSnapshotOnlyInPrimaryStorage;
|
return snapshot.getHypervisorType() == Hypervisor.HypervisorType.KVM && dataStoreRole == DataStoreRole.Primary && isKvmSnapshotOnlyInPrimaryStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataStoreRole getDataStoreRole(Snapshot snapshot) {
|
public DataStoreRole getDataStoreRole(Snapshot snapshot) {
|
||||||
SnapshotDataStoreVO snapshotStore = snapshotDataStoreDao.findOneBySnapshotAndDatastoreRole(snapshot.getId(), DataStoreRole.Primary);
|
SnapshotDataStoreVO snapshotStore = snapshotDataStoreDao.findOneBySnapshotAndDatastoreRole(snapshot.getId(), DataStoreRole.Primary);
|
||||||
|
|
||||||
if (snapshotStore == null) {
|
if (snapshotStore == null) {
|
||||||
return DataStoreRole.Image;
|
return DataStoreRole.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
long storagePoolId = snapshotStore.getDataStoreId();
|
long storagePoolId = snapshotStore.getDataStoreId();
|
||||||
|
|
||||||
StoragePoolVO storagePoolVO = primaryDataStoreDao.findById(storagePoolId);
|
StoragePoolVO storagePoolVO = primaryDataStoreDao.findById(storagePoolId);
|
||||||
if ((storagePoolTypesToValidateWithBackupSnapshotAfterTakingSnapshot.contains(storagePoolVO.getPoolType()) || snapshot.getHypervisorType() == HypervisorType.KVM)
|
if ((storagePoolTypesToValidateWithBackupSnapshotAfterTakingSnapshot.contains(storagePoolVO.getPoolType()) || snapshot.getHypervisorType() == HypervisorType.KVM)
|
||||||
&& !backupSnapshotAfterTakingSnapshot) {
|
&& !backupSnapshotAfterTakingSnapshot) {
|
||||||
@ -237,13 +240,11 @@ public class SnapshotHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataStore dataStore = dataStorageManager.getDataStore(storagePoolId, DataStoreRole.Primary);
|
DataStore dataStore = dataStorageManager.getDataStore(storagePoolId, DataStoreRole.Primary);
|
||||||
|
|
||||||
if (dataStore == null) {
|
if (dataStore == null) {
|
||||||
return DataStoreRole.Image;
|
return DataStoreRole.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();
|
Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();
|
||||||
|
|
||||||
if (MapUtils.isNotEmpty(mapCapabilities) && BooleanUtils.toBoolean(mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString()))) {
|
if (MapUtils.isNotEmpty(mapCapabilities) && BooleanUtils.toBoolean(mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString()))) {
|
||||||
return DataStoreRole.Primary;
|
return DataStoreRole.Primary;
|
||||||
}
|
}
|
||||||
@ -255,11 +256,13 @@ public class SnapshotHelper {
|
|||||||
if (zoneId == null) {
|
if (zoneId == null) {
|
||||||
getDataStoreRole(snapshot);
|
getDataStoreRole(snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SnapshotJoinVO> snapshots = snapshotJoinDao.listBySnapshotIdAndZoneId(zoneId, snapshot.getId());
|
List<SnapshotJoinVO> snapshots = snapshotJoinDao.listBySnapshotIdAndZoneId(zoneId, snapshot.getId());
|
||||||
boolean snapshotOnPrimary = snapshots.stream().anyMatch(s -> s.getStoreRole().equals(DataStoreRole.Primary));
|
boolean snapshotOnPrimary = snapshots.stream().anyMatch(s -> s.getStoreRole().equals(DataStoreRole.Primary));
|
||||||
if (snapshotOnPrimary) {
|
if (snapshotOnPrimary) {
|
||||||
return DataStoreRole.Primary;
|
return DataStoreRole.Primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataStoreRole.Image;
|
return DataStoreRole.Image;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user