Skip to content

Commit c794127

Browse files
authored
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
1 parent fc31b52 commit c794127

3 files changed

Lines changed: 16 additions & 7 deletions

File tree

api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ public interface SnapshotApiService {
8888

8989
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException;
9090

91+
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, Boolean isFromVmSnapshot)
92+
throws ResourceAllocationException;
93+
94+
9195
/**
9296
* Create a snapshot of a volume
9397
*

server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3302,7 +3302,7 @@ public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName,
33023302
throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach this volume to a VM before create snapshot for it");
33033303
}
33043304

3305-
return snapshotMgr.allocSnapshot(volumeId, policyId, snapshotName, locationType);
3305+
return snapshotMgr.allocSnapshot(volumeId, policyId, snapshotName, locationType, false);
33063306
}
33073307

33083308
@Override
@@ -3358,7 +3358,7 @@ public Snapshot allocSnapshotForVm(Long vmId, Long volumeId, String snapshotName
33583358
throw new InvalidParameterValueException("Cannot perform this operation, unsupported on storage pool type " + storagePool.getPoolType());
33593359
}
33603360

3361-
return snapshotMgr.allocSnapshot(volumeId, Snapshot.MANUAL_POLICY_ID, snapshotName, null);
3361+
return snapshotMgr.allocSnapshot(volumeId, Snapshot.MANUAL_POLICY_ID, snapshotName, null, true);
33623362
}
33633363

33643364
@Override

server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ private Type getSnapshotType(IntervalType intvType) {
11261126
return null;
11271127
}
11281128

1129-
private boolean hostSupportSnapsthotForVolume(HostVO host, VolumeInfo volume) {
1129+
private boolean hostSupportsSnapsthotForVolume(HostVO host, VolumeInfo volume, boolean isFromVmSnapshot) {
11301130
if (host.getHypervisorType() != HypervisorType.KVM) {
11311131
return true;
11321132
}
@@ -1138,7 +1138,7 @@ private boolean hostSupportSnapsthotForVolume(HostVO host, VolumeInfo volume) {
11381138
VMInstanceVO vm = _vmDao.findById(vmId);
11391139
if (vm.getState() != VirtualMachine.State.Stopped && vm.getState() != VirtualMachine.State.Destroyed) {
11401140
boolean snapshotEnabled = Boolean.parseBoolean(_configDao.getValue("kvm.snapshot.enabled"));
1141-
if (!snapshotEnabled) {
1141+
if (!snapshotEnabled && !isFromVmSnapshot) {
11421142
s_logger.debug("Snapshot is not supported on host " + host + " for the volume " + volume + " attached to the vm " + vm);
11431143
return false;
11441144
}
@@ -1159,7 +1159,7 @@ private boolean hostSupportSnapsthotForVolume(HostVO host, VolumeInfo volume) {
11591159
return false;
11601160
}
11611161

1162-
private boolean supportedByHypervisor(VolumeInfo volume) {
1162+
private boolean supportedByHypervisor(VolumeInfo volume, boolean isFromVmSnapshot) {
11631163
HypervisorType hypervisorType;
11641164
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getDataStore().getId());
11651165
ScopeType scope = storagePool.getScope();
@@ -1183,7 +1183,7 @@ private boolean supportedByHypervisor(VolumeInfo volume) {
11831183
}
11841184
if (hosts != null && !hosts.isEmpty()) {
11851185
HostVO host = hosts.get(0);
1186-
if (!hostSupportSnapsthotForVolume(host, volume)) {
1186+
if (!hostSupportsSnapsthotForVolume(host, volume, isFromVmSnapshot)) {
11871187
throw new CloudRuntimeException(
11881188
"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.");
11891189
}
@@ -1460,9 +1460,14 @@ public void cleanupSnapshotsByVolume(Long volumeId) {
14601460

14611461
@Override
14621462
public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException {
1463+
return allocSnapshot(volumeId, policyId, snapshotName, locationType, false);
1464+
}
1465+
1466+
@Override
1467+
public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, Boolean isFromVmSnapshot) throws ResourceAllocationException {
14631468
Account caller = CallContext.current().getCallingAccount();
14641469
VolumeInfo volume = volFactory.getVolume(volumeId);
1465-
supportedByHypervisor(volume);
1470+
supportedByHypervisor(volume, isFromVmSnapshot);
14661471

14671472
// Verify permissions
14681473
_accountMgr.checkAccess(caller, null, true, volume);

0 commit comments

Comments
 (0)