Skip to content

Commit 5f9e51c

Browse files
CSTACKEX-18_2: rollback in case of any failures
1 parent 9138e20 commit 5f9e51c

File tree

2 files changed

+33
-34
lines changed

2 files changed

+33
-34
lines changed

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/vmsnapshot/OntapVMSnapshotStrategy.java

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,13 @@ public StrategyPriority canHandle(VMSnapshot vmSnapshot) {
155155
return StrategyPriority.CANT_HANDLE;
156156
}
157157

158-
// For new snapshots on ONTAP storage, we handle ALL snapshot types to prevent
159-
// mixed snapshot chains. Memory snapshots will be rejected in takeVMSnapshot()
160-
// with a clear error message rather than falling back to libvirt snapshots.
158+
// For new snapshots (Allocated state), check if we can handle this VM
159+
// ONTAP only supports disk-only snapshots, not memory snapshots
161160
if (allVolumesOnOntapManagedStorage(vmSnapshot.getVmId())) {
161+
if (vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory) {
162+
logger.debug("canHandle: Memory snapshots (DiskAndMemory) are not supported for VMs on ONTAP storage. VMSnapshot [{}]", vmSnapshot.getId());
163+
return StrategyPriority.CANT_HANDLE;
164+
}
162165
return StrategyPriority.HIGHEST;
163166
}
164167

@@ -167,9 +170,17 @@ public StrategyPriority canHandle(VMSnapshot vmSnapshot) {
167170

168171
@Override
169172
public StrategyPriority canHandle(Long vmId, Long rootPoolId, boolean snapshotMemory) {
170-
// For VMs on ONTAP storage, we handle ALL snapshot types to prevent mixed
171-
// snapshot chains. Memory snapshots will be rejected in takeVMSnapshot()
172-
// with a clear error message rather than falling back to libvirt snapshots.
173+
// ONTAP FlexVolume snapshots only support disk-only (crash-consistent) snapshots.
174+
// Memory snapshots (snapshotMemory=true) are not supported because:
175+
// 1. ONTAP snapshots capture disk state only, not VM memory
176+
// 2. Allowing memory snapshots would require falling back to libvirt snapshots,
177+
// creating mixed snapshot chains that would cause issues during revert
178+
// Return CANT_HANDLE so VMSnapshotManagerImpl can provide a clear error message.
179+
if (snapshotMemory) {
180+
logger.debug("canHandle: Memory snapshots (snapshotMemory=true) are not supported for VMs on ONTAP storage. VM [{}]", vmId);
181+
return StrategyPriority.CANT_HANDLE;
182+
}
183+
173184
if (allVolumesOnOntapManagedStorage(vmId)) {
174185
return StrategyPriority.HIGHEST;
175186
}
@@ -260,28 +271,13 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
260271
UserVm userVm = userVmDao.findById(vmSnapshot.getVmId());
261272
VMSnapshotVO vmSnapshotVO = (VMSnapshotVO) vmSnapshot;
262273

263-
// ── Reject memory snapshots with a clear error message ──
264-
// Memory snapshots (snapshotmemory=true) are not supported for VMs on ONTAP storage.
265-
// This is because ONTAP uses FlexVolume-level snapshots which capture disk state only.
266-
// To avoid mixed snapshot chains (ONTAP disk + libvirt memory), we reject memory
267-
// snapshots outright rather than falling back to libvirt which would cause issues.
268-
if (vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory) {
269-
String errorMsg = String.format(
270-
"Memory snapshots (snapshotmemory=true) are not supported for VMs on ONTAP managed storage. " +
271-
"VM [%s] uses ONTAP storage which only supports disk-only (crash-consistent) snapshots. " +
272-
"Please use snapshotmemory=false for disk-only snapshots.",
273-
userVm.getInstanceName());
274-
logger.error("takeVMSnapshot: {}", errorMsg);
275-
// Clean up the VM snapshot record that was created in Allocated state before throwing
276-
// This prevents orphaned snapshot records from showing in the UI
277-
try {
278-
vmSnapshotDao.remove(vmSnapshotVO.getId());
279-
logger.debug("takeVMSnapshot: Removed VM snapshot record [{}] after memory snapshot validation failure", vmSnapshotVO.getId());
280-
} catch (Exception cleanupEx) {
281-
logger.warn("takeVMSnapshot: Failed to remove VM snapshot record [{}] during cleanup: {}",
282-
vmSnapshotVO.getId(), cleanupEx.getMessage());
283-
}
284-
throw new CloudRuntimeException(errorMsg);
274+
// Transition to Creating state FIRST - this is required so that the finally block
275+
// can properly transition to Error state via OperationFailed event if anything fails.
276+
// (OperationFailed can only transition FROM Creating state, not from Allocated)
277+
try {
278+
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshotVO, VMSnapshot.Event.CreateRequested);
279+
} catch (NoTransitionException e) {
280+
throw new CloudRuntimeException(e.getMessage());
285281
}
286282

287283
FreezeThawVMAnswer freezeAnswer = null;
@@ -292,12 +288,6 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
292288
// Track which FlexVolume snapshots were created (for rollback)
293289
List<FlexVolSnapshotDetail> createdSnapshots = new ArrayList<>();
294290

295-
try {
296-
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshotVO, VMSnapshot.Event.CreateRequested);
297-
} catch (NoTransitionException e) {
298-
throw new CloudRuntimeException(e.getMessage());
299-
}
300-
301291
boolean result = false;
302292
try {
303293
GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId());

server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,15 @@ public VMSnapshot allocVMSnapshot(Long vmId, String vsDisplayName, String vsDesc
384384
//Other Storage volume plugins could integrate this with their own functionality for group snapshots
385385
VMSnapshotStrategy snapshotStrategy = storageStrategyFactory.getVmSnapshotStrategy(userVmVo.getId(), rootVolumePool.getId(), snapshotMemory);
386386
if (snapshotStrategy == null) {
387+
// Check if this is ONTAP managed storage with memory snapshot request - provide specific error message
388+
if (snapshotMemory && rootVolumePool.isManaged() &&
389+
"ONTAP".equals(rootVolumePool.getStorageProviderName())) {
390+
String message = String.format("Memory snapshots (snapshotmemory=true) are not supported for VMs on ONTAP managed storage. " +
391+
"Instance [%s] uses ONTAP storage which only supports disk-only (crash-consistent) snapshots. " +
392+
"Please use snapshotmemory=false for disk-only snapshots.", userVmVo.getUuid());
393+
logger.error(message);
394+
throw new CloudRuntimeException(message);
395+
}
387396
String message = String.format("No strategy was able to handle requested snapshot for Instance [%s].", userVmVo.getUuid());
388397
logger.error(message);
389398
throw new CloudRuntimeException(message);

0 commit comments

Comments
 (0)