From 148d1cda783b3c63dfd3547f3b2f15cd25d64025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 8 Jul 2017 02:36:39 +0200 Subject: [PATCH 1/3] vm/dispvm: fix DispVM storage definition Specify empty 'source' field, so it gets filled with appropriate template's images. Then also fix recursive 'source' handling - DispVM root volume should point at TemplateVM's root volume as a source, not a AppVM's one - which is also only a snapshot. Fixes QubesOS/qubes-issues#2896 --- qubes/storage/__init__.py | 6 +++++- qubes/vm/dispvm.py | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/qubes/storage/__init__.py b/qubes/storage/__init__.py index 63ce351b..92cfb634 100644 --- a/qubes/storage/__init__.py +++ b/qubes/storage/__init__.py @@ -351,7 +351,7 @@ class Storage(object): for name, conf in self.vm.volume_config.items(): if 'source' in conf: template = getattr(vm, 'template', None) - if template: + while template: # we have no control over VM load order, # so initialize storage recursively if needed if template.storage is None: @@ -360,6 +360,10 @@ class Storage(object): # maybe we don't need it at all if it's always from # VM's template? conf['source'] = template.volumes[name] + if conf['source'].source is not None: + template = getattr(template, 'template', None) + else: + break self.init_volume(name, conf) diff --git a/qubes/vm/dispvm.py b/qubes/vm/dispvm.py index 97d67d49..55b2f48c 100644 --- a/qubes/vm/dispvm.py +++ b/qubes/vm/dispvm.py @@ -47,6 +47,7 @@ class DispVM(qubes.vm.qubesvm.QubesVM): 'snap_on_start': True, 'save_on_stop': False, 'rw': False, + 'source': None, }, 'private': { 'name': 'private', @@ -54,6 +55,7 @@ class DispVM(qubes.vm.qubesvm.QubesVM): 'snap_on_start': True, 'save_on_stop': False, 'rw': True, + 'source': None, }, 'volatile': { 'name': 'volatile', From c32f0db5821f44b204181681faf555dd112a9ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 8 Jul 2017 02:53:09 +0200 Subject: [PATCH 2/3] vm/dispvm: convert DispVM related function to coroutines Some functions used there (create_on_disk, remove_from_disk, kill) are coroutines, so callers needs to be too. Fixes QubesOS/qubes-issues#2896 --- qubes/api/internal.py | 6 ++---- qubes/vm/dispvm.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/qubes/api/internal.py b/qubes/api/internal.py index c58c5964..97232d02 100644 --- a/qubes/api/internal.py +++ b/qubes/api/internal.py @@ -69,8 +69,7 @@ class QubesInternalAPI(qubes.api.AbstractQubesAPI): def create_dispvm(self): assert not self.arg - # TODO convert to coroutine - dispvm = qubes.vm.dispvm.DispVM.from_appvm(self.dest) + dispvm = yield from qubes.vm.dispvm.DispVM.from_appvm(self.dest) return dispvm.name @qubes.api.method('internal.vm.CleanupDispVM', no_payload=True) @@ -78,8 +77,7 @@ class QubesInternalAPI(qubes.api.AbstractQubesAPI): def cleanup_dispvm(self): assert not self.arg - # TODO convert to coroutine - self.dest.cleanup() + yield from self.dest.cleanup() @qubes.api.method('internal.vm.volume.ImportEnd') @asyncio.coroutine diff --git a/qubes/vm/dispvm.py b/qubes/vm/dispvm.py index 55b2f48c..24b65892 100644 --- a/qubes/vm/dispvm.py +++ b/qubes/vm/dispvm.py @@ -23,6 +23,8 @@ import copy +import asyncio + import qubes.vm.qubesvm import qubes.vm.appvm import qubes.config @@ -116,6 +118,7 @@ class DispVM(qubes.vm.qubesvm.QubesVM): 'Cannot change template of Disposable VM') @classmethod + @asyncio.coroutine def from_appvm(cls, appvm, **kwargs): '''Create a new instance from given AppVM @@ -147,10 +150,11 @@ class DispVM(qubes.vm.qubesvm.QubesVM): proplist = [prop for prop in dispvm.property_list() if prop.clone and prop.__name__ not in ['template']] dispvm.clone_properties(app.domains[appvm], proplist=proplist) - dispvm.create_on_disk() + yield from dispvm.create_on_disk() app.save() return dispvm + @asyncio.coroutine def cleanup(self): '''Clean up after the DispVM @@ -158,9 +162,10 @@ class DispVM(qubes.vm.qubesvm.QubesVM): This method modifies :file:`qubes.xml` file. ''' try: - self.force_shutdown() + # pylint: disable=not-an-iterable + yield from self.kill() except qubes.exc.QubesVMNotStartedError: pass - self.remove_from_disk() + yield from self.remove_from_disk() del self.app.domains[self] self.app.save() From 1e45d297b3086c9b1f686c6ee153336428f77704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 12 Jul 2017 21:37:12 +0200 Subject: [PATCH 3/3] storage: add comment about source volume lookup --- qubes/storage/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qubes/storage/__init__.py b/qubes/storage/__init__.py index 92cfb634..3cb912c9 100644 --- a/qubes/storage/__init__.py +++ b/qubes/storage/__init__.py @@ -351,6 +351,9 @@ class Storage(object): for name, conf in self.vm.volume_config.items(): if 'source' in conf: template = getattr(vm, 'template', None) + # recursively lookup source volume - templates may be + # chained (TemplateVM -> AppVM -> DispVM, where the + # actual source should be used from TemplateVM) while template: # we have no control over VM load order, # so initialize storage recursively if needed