Skip to content

Commit 0fb2195

Browse files
committed
Remove preloaded disposables on test tearDown
If it is not done on the test, it will be handled by "qubes/tests/__init__.py", which will attempt to kill the domain. If the preloaded disposable was still starting, exceptions will be handled by also attempting to kill the domain. Both methods will trigger the "_bare_cleanup()", sometimes indirectly via "cleanup()" or "_auto_cleanup()", but if "_bare_cleanup()" happens on the other call, not the one that called kill, it will not await and will attempt to remove the domain from the disk while it is still running (not completely killed). For: #742 For: QubesOS/qubes-issues#1512 Fixes: QubesOS/qubes-issues#10369
1 parent 335c908 commit 0fb2195

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

qubes/tests/integ/dispvm.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,16 @@ def _on_domain_add(self, app, event, vm): # pylint: disable=unused-argument
305305
self._register_handlers(vm)
306306

307307
async def cleanup_preload_run(self, qube):
308-
old_preload = qube.get_feat_preload()
308+
old_preload = qube.features.get("preload-dispvm", "")
309+
old_preload = old_preload.split(" ") if old_preload else []
310+
if not old_preload:
311+
return
312+
logger.info(
313+
"cleaning up preloaded disposables: %s:%s", qube.name, old_preload
314+
)
309315
tasks = [self.app.domains[x].cleanup() for x in old_preload]
310316
await asyncio.gather(*tasks)
317+
self.wait_for_dispvm_destroy(old_preload)
311318

312319
def cleanup_preload(self):
313320
logger.info("start")
@@ -319,13 +326,24 @@ def cleanup_preload(self):
319326
logger.info("deleting global threshold feature")
320327
del self.app.domains["dom0"].features["preload-dispvm-threshold"]
321328
for qube in self.app.domains:
322-
if "preload-dispvm-max" not in qube.features:
329+
if "preload-dispvm-max" not in qube.features or qube not in [
330+
self.app.domains["dom0"],
331+
default_dispvm,
332+
self.disp_base,
333+
self.disp_base_alt,
334+
]:
323335
continue
324336
logger.info("removing preloaded disposables: '%s'", qube.name)
325-
if qube == default_dispvm:
326-
self.loop.run_until_complete(
327-
self.cleanup_preload_run(default_dispvm)
337+
target = qube
338+
if qube.klass == "AdminVM" and default_dispvm:
339+
target = default_dispvm
340+
old_preload_max = qube.features.get("preload-dispvm-max") or 0
341+
self.loop.run_until_complete(
342+
self.wait_preload(
343+
old_preload_max, fail_on_timeout=False, timeout=20
328344
)
345+
)
346+
self.loop.run_until_complete(self.cleanup_preload_run(target))
329347
logger.info("deleting max preload feature")
330348
del qube.features["preload-dispvm-max"]
331349
logger.info("end")

qubes/vm/dispvm.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ async def on_domain_shutdown(self, _event, **_kwargs) -> None:
540540
await self._auto_cleanup()
541541

542542
@qubes.events.handler("domain-remove-from-disk")
543-
async def on_domain_delete(self, _event, **_kwargs) -> None:
543+
async def on_domain_remove_from_disk(self, _event, **_kwargs) -> None:
544544
"""
545545
On volume removal, remove preloaded disposable from ``preload-dispvm``
546546
feature in disposable template. If the feature is still here, it means
@@ -765,7 +765,12 @@ def _preload_cleanup(self) -> None:
765765
"""
766766
Cleanup preload from list.
767767
"""
768-
if self.name in self.template.get_feat_preload():
768+
name = getattr(self, "name", None)
769+
template = getattr(self, "template", None)
770+
if not (name and template):
771+
# Objects from self may be absent.
772+
return
773+
if name in template.get_feat_preload():
769774
self.log.info("Automatic cleanup removes qube from preload list")
770775
self.template.remove_preload_from_list([self.name])
771776

@@ -804,7 +809,7 @@ async def cleanup(self) -> None:
804809
running = False
805810
# Full cleanup will be done automatically if event 'domain-shutdown' is
806811
# triggered and "auto_cleanup=True".
807-
if not running or not self.auto_cleanup:
812+
if not self.auto_cleanup or (not running and self.auto_cleanup):
808813
self._preload_cleanup()
809814
if self in self.app.domains:
810815
await self._bare_cleanup()

0 commit comments

Comments
 (0)