Skip to content

Commit f1cbf21

Browse files
committed
Force auto cleanup conditionally
Relying simple on domain not being running resulted in storage errors of attempting to remove it while still in use (domain still running). Didn't identify the cause, which is unfortunate as now it requires an extra parameter. For: #742 For: QubesOS/qubes-issues#1512 Fixes: QubesOS/qubes-issues#10369
1 parent 0fb2195 commit f1cbf21

File tree

3 files changed

+22
-28
lines changed

3 files changed

+22
-28
lines changed

qubes/tests/api_admin.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3977,7 +3977,6 @@ def test_642_vm_create_disposable_not_allowed(self, storage_mock):
39773977
self.call_mgmt_func(b"admin.vm.CreateDisposable", b"test-vm1")
39783978
self.assertFalse(self.app.save.called)
39793979

3980-
@unittest.mock.patch("qubes.vm.dispvm.DispVM._bare_cleanup")
39813980
@unittest.mock.patch("qubes.vm.dispvm.DispVM.start")
39823981
@unittest.mock.patch("qubes.storage.Storage.verify")
39833982
@unittest.mock.patch("qubes.storage.Storage.create")
@@ -3986,12 +3985,10 @@ def test_643_vm_create_disposable_preload_autostart(
39863985
mock_storage_create,
39873986
mock_storage_verify,
39883987
mock_dispvm_start,
3989-
mock_bare_cleanup,
39903988
):
39913989
mock_storage_create.side_effect = self.dummy_coro
39923990
mock_storage_verify.side_effect = self.dummy_coro
39933991
mock_dispvm_start.side_effect = self.dummy_coro
3994-
mock_bare_cleanup.side_effect = self.dummy_coro
39953992
self.vm.template_for_dispvms = True
39963993
self.app.default_dispvm = self.vm
39973994
self.vm.add_handler(

qubes/vm/dispvm.py

Lines changed: 21 additions & 24 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_remove_from_disk(self, _event, **_kwargs) -> None:
543+
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
@@ -774,31 +774,32 @@ def _preload_cleanup(self) -> None:
774774
self.log.info("Automatic cleanup removes qube from preload list")
775775
self.template.remove_preload_from_list([self.name])
776776

777-
async def _bare_cleanup(self) -> None:
778-
"""
779-
Cleanup bare disposable objects.
780-
"""
781-
if self in self.app.domains:
782-
del self.app.domains[self]
783-
await self.remove_from_disk()
784-
self.app.save()
785-
786-
async def _auto_cleanup(self) -> None:
777+
async def _auto_cleanup(self, force: bool = False) -> None:
787778
"""
788779
Do auto cleanup if enabled.
780+
781+
:param bool force: Auto clean up even if property is disabled
789782
"""
790-
if not self.auto_cleanup:
783+
if not self.auto_cleanup and not force:
791784
return
792785
self._preload_cleanup()
793-
if self in self.app.domains:
794-
await self._bare_cleanup()
786+
if self not in self.app.domains:
787+
return
788+
del self.app.domains[self]
789+
await self.remove_from_disk()
790+
self.app.save()
795791

796-
async def cleanup(self) -> None:
792+
async def cleanup(self, force: bool = False) -> None:
797793
"""
798794
Clean up after the disposable.
799795
800796
This stops the disposable qube and removes it from the store.
801797
This method modifies :file:`qubes.xml` file.
798+
799+
:param bool force: Auto clean up if property is enabled and domain \
800+
is not running, should be used in special circumstances only \
801+
as the sole purpose of this option is because using it may not \
802+
be reliable.
802803
"""
803804
if self not in self.app.domains:
804805
return
@@ -809,10 +810,10 @@ async def cleanup(self) -> None:
809810
running = False
810811
# Full cleanup will be done automatically if event 'domain-shutdown' is
811812
# triggered and "auto_cleanup=True".
812-
if not self.auto_cleanup or (not running and self.auto_cleanup):
813-
self._preload_cleanup()
814-
if self in self.app.domains:
815-
await self._bare_cleanup()
813+
if not self.auto_cleanup or (
814+
force and not running and self.auto_cleanup
815+
):
816+
await self._auto_cleanup(force=force)
816817

817818
async def start(self, **kwargs):
818819
"""
@@ -829,11 +830,7 @@ async def start(self, **kwargs):
829830
await super().start(**kwargs)
830831
except:
831832
# Cleanup also on failed startup
832-
try:
833-
await self.kill()
834-
except qubes.exc.QubesVMNotStartedError:
835-
pass
836-
await self._auto_cleanup()
833+
await self.cleanup()
837834
raise
838835

839836
def create_qdb_entries(self) -> None:

qubes/vm/mix/dvmtemplate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def on_domain_loaded(self, event) -> None:
105105
[qube.name for qube in preload_in_progress]
106106
)
107107
for dispvm in preload_in_progress:
108-
asyncio.ensure_future(dispvm.cleanup())
108+
asyncio.ensure_future(dispvm.cleanup(force=True))
109109

110110
if changes:
111111
self.app.save()

0 commit comments

Comments
 (0)