Allow creating snapshot from VM snapshot (#4739)

If `kvm.snapshot.enabled` is set to false then we cant create snapshot from
VM snapshot. With this change, its possible to create snapshot from VM
snapshot even when the global setting is set to false.
Note that you still cant directly create a snapshot from volume though
This commit is contained in:
Rakesh 2022-04-14 06:16:59 +02:00 committed by GitHub
parent fc31b527b1
commit c7941278f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 7 deletions

View File

@ -88,6 +88,10 @@ public interface SnapshotApiService {
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException;
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, Boolean isFromVmSnapshot)
throws ResourceAllocationException;
/**
* Create a snapshot of a volume
*

View File

@ -3302,7 +3302,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach this volume to a VM before create snapshot for it");
}
return snapshotMgr.allocSnapshot(volumeId, policyId, snapshotName, locationType);
return snapshotMgr.allocSnapshot(volumeId, policyId, snapshotName, locationType, false);
}
@Override
@ -3358,7 +3358,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
throw new InvalidParameterValueException("Cannot perform this operation, unsupported on storage pool type " + storagePool.getPoolType());
}
return snapshotMgr.allocSnapshot(volumeId, Snapshot.MANUAL_POLICY_ID, snapshotName, null);
return snapshotMgr.allocSnapshot(volumeId, Snapshot.MANUAL_POLICY_ID, snapshotName, null, true);
}
@Override

View File

@ -1126,7 +1126,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
return null;
}
private boolean hostSupportSnapsthotForVolume(HostVO host, VolumeInfo volume) {
private boolean hostSupportsSnapsthotForVolume(HostVO host, VolumeInfo volume, boolean isFromVmSnapshot) {
if (host.getHypervisorType() != HypervisorType.KVM) {
return true;
}
@ -1138,7 +1138,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
VMInstanceVO vm = _vmDao.findById(vmId);
if (vm.getState() != VirtualMachine.State.Stopped && vm.getState() != VirtualMachine.State.Destroyed) {
boolean snapshotEnabled = Boolean.parseBoolean(_configDao.getValue("kvm.snapshot.enabled"));
if (!snapshotEnabled) {
if (!snapshotEnabled && !isFromVmSnapshot) {
s_logger.debug("Snapshot is not supported on host " + host + " for the volume " + volume + " attached to the vm " + vm);
return false;
}
@ -1159,7 +1159,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
return false;
}
private boolean supportedByHypervisor(VolumeInfo volume) {
private boolean supportedByHypervisor(VolumeInfo volume, boolean isFromVmSnapshot) {
HypervisorType hypervisorType;
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getDataStore().getId());
ScopeType scope = storagePool.getScope();
@ -1183,7 +1183,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
}
if (hosts != null && !hosts.isEmpty()) {
HostVO host = hosts.get(0);
if (!hostSupportSnapsthotForVolume(host, volume)) {
if (!hostSupportsSnapsthotForVolume(host, volume, isFromVmSnapshot)) {
throw new CloudRuntimeException(
"KVM Snapshot is not supported for Running VMs. It is disabled by default due to a possible volume corruption in certain cases. To enable it set global settings kvm.snapshot.enabled to True. See the documentation for more details.");
}
@ -1460,9 +1460,14 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
@Override
public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException {
return allocSnapshot(volumeId, policyId, snapshotName, locationType, false);
}
@Override
public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, Boolean isFromVmSnapshot) throws ResourceAllocationException {
Account caller = CallContext.current().getCallingAccount();
VolumeInfo volume = volFactory.getVolume(volumeId);
supportedByHypervisor(volume);
supportedByHypervisor(volume, isFromVmSnapshot);
// Verify permissions
_accountMgr.checkAccess(caller, null, true, volume);