1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-09 03:36:48 +00:00

feat(instances): external snapshots first, internal ones a fallback

The Snapshots tab had three sub-tabs: internal, external and the
lists, with the two kinds side by side as equals. The owner set the
direction: external snapshots are the way; internal ones pause the VM
while its memory is saved and can take long, so they stay only as a
fallback for a VM that cannot take an external one.

The tab now has the external snapshot form on top, its name and
description on one line, with its memory and freeze options; the
internal snapshot under a folded "fallback" line with its warning; and
one list of all snapshots, newest first, each on one line with its
name, description, kind and date, and Revert and Delete.

Codex reviewed snapshots end to end; these are fixed:

- The pause and memory lines follow the VM's state and the kind.
- An internal snapshot is reverted to on a shut-off VM only, on the
  server too; the tab alone held that rule.
- A paused VM's revert says it comes back paused, not that it starts.
- An external snapshot waits, with the reason, while snapshots newer
  than the one reverted to exist; the server refused it unexplained.
- Deleting an external snapshot says its files are merged with the
  disks; "into the next one" was wrong for the last one.
- The description has no 45-character limit only the browser kept.
- Freezing is not shown ticked where it cannot be offered, and
  unticking memory gives back the earlier freeze choice.
- Internal create, revert and delete refuse a saved state or a running
  disk job, as external ones do.
This commit is contained in:
catborise 2026-10-30 21:40:00 +03:00
parent 60f12cefa1
commit 7fc55537e5
7 changed files with 186 additions and 203 deletions

View file

@ -1771,6 +1771,7 @@ class wvmInstance(wvmConnect):
self.instance.snapshotCreateXML(xml, flag)
def create_snapshot(self, name, desc=None):
self._check_snapshot_state()
if self.instance.snapshotListNames(VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL):
raise util.OperationError("The VM has external snapshots; internal snapshots cannot be mixed with them")
state = "shutoff" if self.get_status() == 5 else "running"
@ -2071,6 +2072,7 @@ class wvmInstance(wvmConnect):
"description": tree.findtext("description") or "",
"memory": tree.find("memory[@snapshot='external']") is not None,
"current": bool(snap.isCurrent(0)),
"children": snap.numChildren(0),
"detaches": [{"dev": dev, "path": path} for dev, path in detaches.items()],
}
)
@ -2222,18 +2224,24 @@ class wvmInstance(wvmConnect):
return self.instance.snapshotLookupByName(name, 0)
def _check_snapshot_state(self):
"""Refusals shared by external snapshot create, revert and delete. The
internal/external mix is checked only on create, so a VM that is
already mixed can still be cleaned up."""
"""Refusals shared by snapshot create, revert and delete, internal and
external. The internal/external mix is checked only on create, so a
VM that is already mixed can still be cleaned up."""
if self.instance.hasManagedSaveImage(0):
raise util.OperationError("The VM has a saved state; start it or remove the saved state first")
if self.get_snapshot_jobs():
raise util.OperationError("A snapshot job is still running on this VM; try again when it ends")
def snapshot_delete(self, snapshot):
self._check_snapshot_state()
self._snapshot(snapshot, external=False).delete(0)
def snapshot_revert(self, snapshot):
"""An internal snapshot is reverted to on a shut-off VM; one of a
running VM starts it again as it was then."""
if self.get_status() != 5:
raise util.OperationError("Shut the VM down to revert to an internal snapshot")
self._check_snapshot_state()
self.instance.revertToSnapshot(self._snapshot(snapshot, external=False), 0)
def get_managed_save_image(self):