1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00

fix(instances): a snapshot file another VM uses is not called left behind

After a snapshot revert or delete, files libvirt could not remove are
named in a warning that says nothing uses them and asks to remove them
by hand. A file another VM on the same host uses (as a disk, a backing
file or a snapshot file) is no longer named: removing it would break
that VM. The warning now says no VM on this host uses the files.
This commit is contained in:
catborise 2026-10-13 07:56:19 +03:00
parent c970f8e853
commit 097a91592c
3 changed files with 32 additions and 5 deletions

View file

@ -1383,7 +1383,7 @@ def _warn_left_behind(request, files):
messages.warning(
request,
_(
"These snapshot files were not removed, although nothing uses them any more: %(files)s. "
"These snapshot files were not removed, although no VM on this host uses them any more: %(files)s. "
"On NFS libvirt removes them as the qemu user, who needs write access to their directory. "
"Remove them by hand."
)

View file

@ -1715,9 +1715,10 @@ class wvmInstance(wvmConnect):
logs a warning then (on NFS it removes them as the qemu user, who
needs write access to their directory). Only a snapshot's own file or
an overlay on a snapshot point counts; a disk a revert detached is
kept on purpose. A file outside every storage pool is not checked,
nor is anything when the pools could not be refreshed: a stale pool
still lists the removed files."""
kept on purpose, and a file another VM on this host uses (or one
below it) is not reported. A file outside every storage pool is not
checked, nor is anything when the pools could not be refreshed: a
stale pool still lists the removed files."""
disks, own, points = before
if not self._refresh_pools_after_snapshot():
return []
@ -1734,6 +1735,14 @@ class wvmInstance(wvmConnect):
except libvirtError: # not in a pool, or removed meanwhile
continue
left.append(path)
if left:
# another VM on this host may use one; their own backing files
# do not keep each other, but a file in use keeps the files below it
in_use = self.paths_in_use(own=left)
for path in [path for path in left if path in in_use]:
while (path := self._backing_path(path)) and path not in in_use:
in_use.add(path)
left = [path for path in left if path not in in_use]
return left
@staticmethod

View file

@ -4,7 +4,7 @@ cases are in instances/tests/test_live_snapshots.py."""
import unittest
from datetime import datetime
from unittest.mock import MagicMock
from unittest.mock import MagicMock, patch
from django.conf import settings
@ -440,6 +440,24 @@ class LeftBehindTestCase(unittest.TestCase):
["/pool/a.one", "/pool/vm.one.mem"],
)
def test_a_file_another_vm_uses_is_not_reported(self):
# on NFS libvirt could not remove it, but another VM uses it now
with patch.object(wvmInstance, "paths_in_use", return_value={"/pool/a.one"}) as in_use, \
patch.object(wvmInstance, "_backing_path", return_value=None):
left = self.run_delete({"/pool/a.one", "/pool/vm.one.mem", "/pool/a.two", "/pool/a.qcow2"})
self.assertEqual(left, ["/pool/vm.one.mem"])
# their own backing files do not keep each other
in_use.assert_called_once_with(own=["/pool/a.one", "/pool/vm.one.mem"])
def test_a_file_below_one_another_vm_uses_is_not_reported(self):
# the other VM is shut off: its definition does not list the backing
# file, and the in-use top's own backing reference does not count
backing = {"/pool/a.one": "/pool/vm.one.mem"}
with patch.object(wvmInstance, "paths_in_use", return_value={"/pool/a.one"}), \
patch.object(wvmInstance, "_backing_path", side_effect=backing.get):
left = self.run_delete({"/pool/a.one", "/pool/vm.one.mem", "/pool/a.two", "/pool/a.qcow2"})
self.assertEqual(left, [])
def test_nothing_is_reported_when_libvirt_removed_them(self):
# files still in use (base, the newer overlay) are never reported
self.assertEqual(self.run_delete({"/pool/a.two", "/pool/a.qcow2"}), [])