Skip to content

Commit 7780a93

Browse files
CSTACKEX-18_2: revert snapshot fixes for API not found
1 parent 1b0bba9 commit 7780a93

File tree

1 file changed

+43
-40
lines changed

1 file changed

+43
-40
lines changed

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

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public StrategyPriority canHandle(VMSnapshot vmSnapshot) {
157157

158158
// For new snapshots, check if Disk-only and all volumes on ONTAP
159159
if (vmSnapshotVO.getType() != VMSnapshot.Type.Disk) {
160-
logger.error("ONTAP VM snapshot strategy cannot handle memory snapshots for VM [{}]", vmSnapshot.getVmId());
160+
logger.error("canHandle: ONTAP VM snapshot strategy cannot handle memory snapshots for VM [{}]", vmSnapshot.getVmId());
161161
throw new CloudRuntimeException("ONTAP VM snapshot strategy cannot handle memory snapshots for VM [" + vmSnapshot.getVmId() + "]");
162162
}
163163

@@ -171,7 +171,7 @@ public StrategyPriority canHandle(VMSnapshot vmSnapshot) {
171171
@Override
172172
public StrategyPriority canHandle(Long vmId, Long rootPoolId, boolean snapshotMemory) {
173173
if (snapshotMemory) {
174-
logger.debug("ONTAP VM snapshot strategy cannot handle memory snapshots for VM [{}]", vmId);
174+
logger.debug("canHandle: ONTAP VM snapshot strategy cannot handle memory snapshots for VM [{}]", vmId);
175175
return StrategyPriority.CANT_HANDLE;
176176
}
177177

@@ -188,12 +188,12 @@ public StrategyPriority canHandle(Long vmId, Long rootPoolId, boolean snapshotMe
188188
boolean allVolumesOnOntapManagedStorage(long vmId) {
189189
UserVm userVm = userVmDao.findById(vmId);
190190
if (userVm == null) {
191-
logger.debug("VM with id [{}] not found", vmId);
191+
logger.debug("allVolumesOnOntapManagedStorage: VM with id [{}] not found", vmId);
192192
return false;
193193
}
194194

195195
if (!Hypervisor.HypervisorType.KVM.equals(userVm.getHypervisorType())) {
196-
logger.debug("ONTAP VM snapshot strategy only supports KVM hypervisor, VM [{}] uses [{}]",
196+
logger.debug("allVolumesOnOntapManagedStorage: ONTAP VM snapshot strategy only supports KVM hypervisor, VM [{}] uses [{}]",
197197
vmId, userVm.getHypervisorType());
198198
return false;
199199
}
@@ -210,7 +210,7 @@ boolean allVolumesOnOntapManagedStorage(long vmId) {
210210

211211
List<VolumeVO> volumes = volumeDao.findByInstance(vmId);
212212
if (volumes == null || volumes.isEmpty()) {
213-
logger.debug("No volumes found for VM [{}]", vmId);
213+
logger.debug("allVolumesOnOntapManagedStorage: No volumes found for VM [{}]", vmId);
214214
return false;
215215
}
216216

@@ -223,18 +223,18 @@ boolean allVolumesOnOntapManagedStorage(long vmId) {
223223
return false;
224224
}
225225
if (!pool.isManaged()) {
226-
logger.debug("Volume [{}] is on non-managed storage pool [{}], not ONTAP",
226+
logger.debug("allVolumesOnOntapManagedStorage: Volume [{}] is on non-managed storage pool [{}], not ONTAP",
227227
volume.getId(), pool.getName());
228228
return false;
229229
}
230230
if (!Constants.ONTAP_PLUGIN_NAME.equals(pool.getStorageProviderName())) {
231-
logger.debug("Volume [{}] is on managed pool [{}] with provider [{}], not ONTAP",
231+
logger.debug("allVolumesOnOntapManagedStorage: Volume [{}] is on managed pool [{}] with provider [{}], not ONTAP",
232232
volume.getId(), pool.getName(), pool.getStorageProviderName());
233233
return false;
234234
}
235235
}
236236

237-
logger.debug("All volumes of VM [{}] are on ONTAP managed storage, this strategy can handle", vmId);
237+
logger.debug("allVolumesOnOntapManagedStorage: All volumes of VM [{}] are on ONTAP managed storage, this strategy can handle", vmId);
238238
return true;
239239
}
240240

@@ -298,13 +298,13 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
298298
boolean shouldFreezeThaw = quiescevm && vmIsRunning;
299299

300300
if (!vmIsRunning) {
301-
logger.info("VM [{}] is in state [{}] (not Running). Skipping freeze/thaw - " +
301+
logger.info("takeVMSnapshot: VM [{}] is in state [{}] (not Running). Skipping freeze/thaw - " +
302302
"FlexVolume snapshot will be taken directly.", userVm.getInstanceName(), userVm.getState());
303303
} else if (quiescevm) {
304-
logger.info("Quiesce option is enabled for ONTAP VM Snapshot of VM [{}]. " +
304+
logger.info("takeVMSnapshot: Quiesce option is enabled for ONTAP VM Snapshot of VM [{}]. " +
305305
"VM file systems will be frozen/thawed for application-consistent snapshots.", userVm.getInstanceName());
306306
} else {
307-
logger.info("Quiesce option is disabled for ONTAP VM Snapshot of VM [{}]. " +
307+
logger.info("takeVMSnapshot: Quiesce option is disabled for ONTAP VM Snapshot of VM [{}]. " +
308308
"Snapshots will be crash-consistent only.", userVm.getInstanceName());
309309
}
310310

@@ -320,7 +320,7 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
320320
CreateVMSnapshotCommand ccmd = new CreateVMSnapshotCommand(
321321
userVm.getInstanceName(), userVm.getUuid(), target, volumeTOs, guestOS.getDisplayName());
322322

323-
logger.info("Creating ONTAP FlexVolume VM Snapshot for VM [{}] with quiesce={}", userVm.getInstanceName(), quiescevm);
323+
logger.info("takeVMSnapshot: Creating ONTAP FlexVolume VM Snapshot for VM [{}] with quiesce={}", userVm.getInstanceName(), quiescevm);
324324

325325
// Prepare volume info list and calculate sizes
326326
for (VolumeObjectTO volumeObjectTO : volumeTOs) {
@@ -332,7 +332,7 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
332332
// ── Group volumes by FlexVolume UUID ──
333333
Map<String, FlexVolGroupInfo> flexVolGroups = groupVolumesByFlexVol(volumeTOs);
334334

335-
logger.info("VM [{}] has {} volumes across {} unique FlexVolume(s)",
335+
logger.info("takeVMSnapshot: VM [{}] has {} volumes across {} unique FlexVolume(s)",
336336
userVm.getInstanceName(), volumeTOs.size(), flexVolGroups.size());
337337

338338
// ── Step 1: Freeze the VM (only if quiescing is requested AND VM is running) ──
@@ -351,9 +351,9 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
351351
"] for ONTAP snapshot. Ensure qemu-guest-agent is installed and running. Details: " + detail);
352352
}
353353

354-
logger.info("VM [{}] frozen successfully via QEMU guest agent", userVm.getInstanceName());
354+
logger.info("takeVMSnapshot: VM [{}] frozen successfully via QEMU guest agent", userVm.getInstanceName());
355355
} else {
356-
logger.info("Skipping VM freeze for VM [{}] (quiesce={}, vmIsRunning={})",
356+
logger.info("takeVMSnapshot: Skipping VM freeze for VM [{}] (quiesce={}, vmIsRunning={})",
357357
userVm.getInstanceName(), quiescevm, vmIsRunning);
358358
}
359359

@@ -376,7 +376,7 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
376376
FlexVolSnapshot snapshotRequest = new FlexVolSnapshot(snapshotNameBase,
377377
"CloudStack VM snapshot " + vmSnapshot.getName() + " for VM " + userVm.getInstanceName());
378378

379-
logger.info("Creating ONTAP FlexVolume snapshot [{}] on FlexVol UUID [{}] covering {} volume(s)",
379+
logger.info("takeVMSnapshot: Creating ONTAP FlexVolume snapshot [{}] on FlexVol UUID [{}] covering {} volume(s)",
380380
snapshotNameBase, flexVolUuid, groupInfo.volumeIds.size());
381381

382382
JobResponse jobResponse = snapshotClient.createSnapshot(authHeader, flexVolUuid, snapshotRequest);
@@ -403,7 +403,7 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
403403
createdSnapshots.add(detail);
404404
}
405405

406-
logger.info("ONTAP FlexVolume snapshot [{}] (uuid={}) on FlexVol [{}] completed in {} ms. Covers volumes: {}",
406+
logger.info("takeVMSnapshot: ONTAP FlexVolume snapshot [{}] (uuid={}) on FlexVol [{}] completed in {} ms. Covers volumes: {}",
407407
snapshotNameBase, snapshotUuid, flexVolUuid,
408408
TimeUnit.MILLISECONDS.convert(System.nanoTime() - startSnapshot, TimeUnit.NANOSECONDS),
409409
groupInfo.volumeIds);
@@ -414,15 +414,15 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
414414
try {
415415
thawAnswer = (FreezeThawVMAnswer) agentMgr.send(hostId, thawCmd);
416416
if (thawAnswer != null && thawAnswer.getResult()) {
417-
logger.info("VM [{}] thawed successfully. Total freeze duration: {} ms",
417+
logger.info("takeVMSnapshot: VM [{}] thawed successfully. Total freeze duration: {} ms",
418418
userVm.getInstanceName(),
419419
TimeUnit.MILLISECONDS.convert(System.nanoTime() - startFreeze, TimeUnit.NANOSECONDS));
420420
} else {
421-
logger.warn("Failed to thaw VM [{}]: {}", userVm.getInstanceName(),
421+
logger.warn("takeVMSnapshot: Failed to thaw VM [{}]: {}", userVm.getInstanceName(),
422422
(thawAnswer != null) ? thawAnswer.getDetails() : "no response");
423423
}
424424
} catch (Exception thawEx) {
425-
logger.error("Exception while thawing VM [{}]: {}", userVm.getInstanceName(), thawEx.getMessage(), thawEx);
425+
logger.error("takeVMSnapshot: Exception while thawing VM [{}]: {}", userVm.getInstanceName(), thawEx.getMessage(), thawEx);
426426
}
427427
}
428428
}
@@ -438,7 +438,7 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
438438
answer.setVolumeTOs(volumeTOs);
439439

440440
processAnswer(vmSnapshotVO, userVm, answer, null);
441-
logger.info("ONTAP FlexVolume VM Snapshot [{}] created successfully for VM [{}] ({} FlexVol snapshot(s))",
441+
logger.info("takeVMSnapshot: ONTAP FlexVolume VM Snapshot [{}] created successfully for VM [{}] ({} FlexVol snapshot(s))",
442442
vmSnapshot.getName(), userVm.getInstanceName(), createdSnapshots.size());
443443

444444
long new_chain_size = 0;
@@ -453,10 +453,10 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
453453
return vmSnapshot;
454454

455455
} catch (OperationTimedoutException e) {
456-
logger.error("ONTAP VM Snapshot [{}] timed out: {}", vmSnapshot.getName(), e.getMessage());
456+
logger.error("takeVMSnapshot: ONTAP VM Snapshot [{}] timed out: {}", vmSnapshot.getName(), e.getMessage());
457457
throw new CloudRuntimeException("Creating Instance Snapshot: " + vmSnapshot.getName() + " timed out: " + e.getMessage());
458458
} catch (AgentUnavailableException e) {
459-
logger.error("ONTAP VM Snapshot [{}] failed, agent unavailable: {}", vmSnapshot.getName(), e.getMessage());
459+
logger.error("takeVMSnapshot: ONTAP VM Snapshot [{}] failed, agent unavailable: {}", vmSnapshot.getName(), e.getMessage());
460460
throw new CloudRuntimeException("Creating Instance Snapshot: " + vmSnapshot.getName() + " failed: " + e.getMessage());
461461
} catch (CloudRuntimeException e) {
462462
throw e;
@@ -471,7 +471,7 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
471471
rollbackFlexVolSnapshot(detail);
472472
rolledBack.put(dedupeKey, Boolean.TRUE);
473473
} catch (Exception rollbackEx) {
474-
logger.error("Failed to rollback FlexVol snapshot [{}] on FlexVol [{}]: {}",
474+
logger.error("takeVMSnapshot: Failed to rollback FlexVol snapshot [{}] on FlexVol [{}]: {}",
475475
detail.snapshotUuid, detail.flexVolUuid, rollbackEx.getMessage());
476476
}
477477
}
@@ -480,10 +480,10 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
480480
// Ensure VM is thawed if we haven't done so
481481
if (thawAnswer == null && freezeAnswer != null && freezeAnswer.getResult()) {
482482
try {
483-
logger.info("Thawing VM [{}] during error cleanup", userVm.getInstanceName());
483+
logger.info("takeVMSnapshot: Thawing VM [{}] during error cleanup", userVm.getInstanceName());
484484
thawAnswer = (FreezeThawVMAnswer) agentMgr.send(hostId, thawCmd);
485485
} catch (Exception ex) {
486-
logger.error("Could not thaw VM during cleanup: {}", ex.getMessage());
486+
logger.error("takeVMSnapshot: Could not thaw VM during cleanup: {}", ex.getMessage());
487487
}
488488
}
489489

@@ -497,7 +497,7 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
497497
}
498498
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
499499
} catch (NoTransitionException e1) {
500-
logger.error("Cannot set VM Snapshot state to OperationFailed: {}", e1.getMessage());
500+
logger.error("takeVMSnapshot: Cannot set VM Snapshot state to OperationFailed: {}", e1.getMessage());
501501
}
502502
}
503503
}
@@ -601,8 +601,8 @@ public boolean revertVMSnapshot(VMSnapshot vmSnapshot) {
601601
processAnswer(vmSnapshotVO, userVm, answer, null);
602602
result = true;
603603
} catch (CloudRuntimeException e) {
604-
logger.error("Revert ONTAP VM Snapshot [{}] failed: {}", vmSnapshot.getName(), e.getMessage(), e);
605-
throw new CloudRuntimeException(e);
604+
logger.error("revertVMSnapshot: Revert ONTAP VM Snapshot [{}] failed: {}", vmSnapshot.getName(), e.getMessage(), e);
605+
throw new CloudRuntimeException("Revert ONTAP VM Snapshot ["+ vmSnapshot.getName() +"] failed.");
606606
} finally {
607607
if (!result) {
608608
try {
@@ -723,15 +723,15 @@ void rollbackFlexVolSnapshot(FlexVolSnapshotDetail detail) {
723723
SnapshotFeignClient client = storageStrategy.getSnapshotFeignClient();
724724
String authHeader = storageStrategy.getAuthHeader();
725725

726-
logger.info("Rolling back FlexVol snapshot [{}] (uuid={}) on FlexVol [{}]",
726+
logger.info("rollbackFlexVolSnapshot: Rolling back FlexVol snapshot [{}] (uuid={}) on FlexVol [{}]",
727727
detail.snapshotName, detail.snapshotUuid, detail.flexVolUuid);
728728

729729
JobResponse jobResponse = client.deleteSnapshot(authHeader, detail.flexVolUuid, detail.snapshotUuid);
730730
if (jobResponse != null && jobResponse.getJob() != null) {
731731
storageStrategy.jobPollForSuccess(jobResponse.getJob().getUuid(), 10, 2);
732732
}
733733
} catch (Exception e) {
734-
logger.error("Rollback of FlexVol snapshot failed: {}", e.getMessage(), e);
734+
logger.error("rollbackFlexVolSnapshot: Rollback of FlexVol snapshot failed: {}", e.getMessage(), e);
735735
}
736736
}
737737

@@ -757,7 +757,7 @@ void deleteFlexVolSnapshots(List<VMSnapshotDetailsVO> flexVolDetails) {
757757
SnapshotFeignClient client = storageStrategy.getSnapshotFeignClient();
758758
String authHeader = storageStrategy.getAuthHeader();
759759

760-
logger.info("Deleting ONTAP FlexVol snapshot [{}] (uuid={}) on FlexVol [{}]",
760+
logger.info("deleteFlexVolSnapshots: Deleting ONTAP FlexVol snapshot [{}] (uuid={}) on FlexVol [{}]",
761761
detail.snapshotName, detail.snapshotUuid, detail.flexVolUuid);
762762

763763
JobResponse jobResponse = client.deleteSnapshot(authHeader, detail.flexVolUuid, detail.snapshotUuid);
@@ -766,7 +766,7 @@ void deleteFlexVolSnapshots(List<VMSnapshotDetailsVO> flexVolDetails) {
766766
}
767767

768768
deletedSnapshots.put(dedupeKey, Boolean.TRUE);
769-
logger.info("Deleted ONTAP FlexVol snapshot [{}] on FlexVol [{}]", detail.snapshotName, detail.flexVolUuid);
769+
logger.info("deleteFlexVolSnapshots: Deleted ONTAP FlexVol snapshot [{}] on FlexVol [{}]", detail.snapshotName, detail.flexVolUuid);
770770
}
771771

772772
// Always remove the DB detail row
@@ -796,7 +796,7 @@ void revertFlexVolSnapshots(List<VMSnapshotDetailsVO> flexVolDetails) {
796796

797797
if (detail.volumePath == null || detail.volumePath.isEmpty()) {
798798
// Legacy detail row without volumePath – cannot do single-file restore
799-
logger.warn("FlexVol snapshot detail for FlexVol [{}] has no volumePath (legacy format). " +
799+
logger.warn("revertFlexVolSnapshots: FlexVol snapshot detail for FlexVol [{}] has no volumePath (legacy format). " +
800800
"Skipping single-file restore for this entry.", detail.flexVolUuid);
801801
continue;
802802
}
@@ -806,28 +806,31 @@ void revertFlexVolSnapshots(List<VMSnapshotDetailsVO> flexVolDetails) {
806806
SnapshotFeignClient snapshotClient = storageStrategy.getSnapshotFeignClient();
807807
String authHeader = storageStrategy.getAuthHeader();
808808

809-
logger.info("Restoring volume [{}] from FlexVol snapshot [{}] (uuid={}) on FlexVol [{}] (protocol={})",
810-
detail.volumePath, detail.snapshotName, detail.snapshotUuid,
809+
// Prepare the file path for ONTAP API (ensure it starts with "/")
810+
String ontapFilePath = detail.volumePath.startsWith("/") ? detail.volumePath : "/" + detail.volumePath;
811+
812+
logger.info("revertFlexVolSnapshots: Restoring volume [{}] from FlexVol snapshot [{}] (uuid={}) on FlexVol [{}] (protocol={})",
813+
ontapFilePath, detail.snapshotName, detail.snapshotUuid,
811814
detail.flexVolUuid, detail.protocol);
812815

813816
// POST /api/storage/volumes/{vol}/snapshots/{snap}/files/{path}/restore
814817
// with body: { "destination_path": "<volumePath>" }
815818
SnapshotFileRestoreRequest restoreRequest = new SnapshotFileRestoreRequest(detail.volumePath);
816819

817820
JobResponse jobResponse = snapshotClient.restoreFileFromSnapshot(
818-
authHeader, detail.flexVolUuid, detail.snapshotUuid, detail.volumePath, restoreRequest);
821+
authHeader, detail.flexVolUuid, detail.snapshotUuid, ontapFilePath, restoreRequest);
819822

820823
if (jobResponse != null && jobResponse.getJob() != null) {
821824
Boolean success = storageStrategy.jobPollForSuccess(jobResponse.getJob().getUuid(), 60, 2);
822825
if (!success) {
823826
throw new CloudRuntimeException("Snapshot file restore failed for volume path [" +
824-
detail.volumePath + "] from snapshot [" + detail.snapshotName +
827+
ontapFilePath + "] from snapshot [" + detail.snapshotName +
825828
"] on FlexVol [" + detail.flexVolUuid + "]");
826829
}
827830
}
828831

829-
logger.info("Successfully restored volume [{}] from snapshot [{}] on FlexVol [{}]",
830-
detail.volumePath, detail.snapshotName, detail.flexVolUuid);
832+
logger.info("revertFlexVolSnapshots: Successfully restored volume [{}] from snapshot [{}] on FlexVol [{}]",
833+
ontapFilePath, detail.snapshotName, detail.flexVolUuid);
831834
}
832835
}
833836

0 commit comments

Comments
 (0)