From 94c8e25d3c3e3a9e3cb02577798542f05a1d620b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 13 Apr 2018 15:56:23 +0200 Subject: [PATCH 1/7] storage/lvm: save pool's revision_to_keep property And also report it as part of admin.pool.Info Admin API. QubesOS/qubes-issues#3256 --- qubes/storage/lvm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index aa7c3c12..76e5cdae 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -68,7 +68,8 @@ class ThinPool(qubes.storage.Pool): 'name': self.name, 'volume_group': self.volume_group, 'thin_pool': self.thin_pool, - 'driver': ThinPool.driver + 'driver': ThinPool.driver, + 'revisions_to_keep': self.revisions_to_keep, } def destroy(self): From 2aa14623bf7ddb0a057b1304de5be414b0729712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 13 Apr 2018 15:57:09 +0200 Subject: [PATCH 2/7] storage/lvm: fix reporting lvm command error Escape '%' in error message, as required by Admin API. Fixes QubesOS/qubes-issues#3809 --- qubes/storage/lvm.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index 76e5cdae..c2460249 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -574,6 +574,7 @@ def qubes_lvm(cmd, log=logging.getLogger('qubes.storage.lvm')): p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, env=environ) out, err = p.communicate() + err = err.decode() return_code = p.returncode if out: log.debug(out) @@ -581,6 +582,7 @@ def qubes_lvm(cmd, log=logging.getLogger('qubes.storage.lvm')): log.warning(err) elif return_code != 0: assert err, "Command exited unsuccessful, but printed nothing to stderr" + err = err.replace('%', '%%') raise qubes.storage.StoragePoolException(err) return True From ba82d9dc21c0c8b63d417a4c0640e2f7f2a00c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 13 Apr 2018 16:03:42 +0200 Subject: [PATCH 3/7] vm/qubesvm: check if all required devices are available before start Fail the VM start early if some persistently-assigned device is missing. This will both save time and provide clearer error message. Fixes QubesOS/qubes-issues#3810 --- qubes/vm/qubesvm.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 4730a2aa..20d2da9c 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -865,6 +865,12 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): pre_event=True, start_guid=start_guid, mem_required=mem_required) + for devclass in self.devices: + for dev in self.devices[devclass].persistent(): + if isinstance(dev, qubes.devices.UnknownDevice): + raise qubes.exc.QubesException( + '{} device {} not available'.format(devclass, dev)) + qmemman_client = None try: if self.virt_mode == 'pvh' and self.kernel is None: From 6a191febc3611acb50c960434abcf899fd39327f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 13 Apr 2018 16:07:32 +0200 Subject: [PATCH 4/7] vm/qubesvm: fire 'domain-start-failed' event even if fail was early Fire 'domain-start-failed' even even if failure occurred during 'domain-pre-start' event. This will make sure if _anyone_ have seen 'domain-pre-start' event, will also see 'domain-start-failed'. In some cases it will look like spurious 'domain-start-failed', but it is safer option than the alternative. --- qubes/vm/qubesvm.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 20d2da9c..53d5e2ee 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -861,9 +861,14 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): self.log.info('Starting {}'.format(self.name)) - yield from self.fire_event_async('domain-pre-start', - pre_event=True, - start_guid=start_guid, mem_required=mem_required) + try: + yield from self.fire_event_async('domain-pre-start', + pre_event=True, + start_guid=start_guid, mem_required=mem_required) + except Exception as exc: + yield from self.fire_event_async('domain-start-failed', + reason=str(exc)) + raise for devclass in self.devices: for dev in self.devices[devclass].persistent(): From 69f19bb7bb6b464c4d19b226ca6b3a07a8841b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 13 Apr 2018 21:43:15 +0200 Subject: [PATCH 5/7] tests/extra: add start_guid option to VMWrapper Pass start_guid option to vm.start(), when using core2 compatibility layer. --- qubes/tests/extra.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qubes/tests/extra.py b/qubes/tests/extra.py index 215200e7..c779794e 100644 --- a/qubes/tests/extra.py +++ b/qubes/tests/extra.py @@ -65,8 +65,9 @@ class VMWrapper(object): def __hash__(self): return hash(self._vm) - def start(self): - return self._loop.run_until_complete(self._vm.start()) + def start(self, start_guid=True): + return self._loop.run_until_complete( + self._vm.start(start_guid=start_guid)) def shutdown(self): return self._loop.run_until_complete(self._vm.shutdown()) From 4794232745b2e61888289186e96259263e2dfacd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 13 Apr 2018 21:44:44 +0200 Subject: [PATCH 6/7] tests: fix getting kernel package version inside VM Use `sort -V` instead of `sort -n`. --- qubes/tests/integ/pvgrub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qubes/tests/integ/pvgrub.py b/qubes/tests/integ/pvgrub.py index 92a12f29..fcc67672 100644 --- a/qubes/tests/integ/pvgrub.py +++ b/qubes/tests/integ/pvgrub.py @@ -67,7 +67,7 @@ class TC_40_PVGrub(object): def get_kernel_version(self, vm): if self.template.startswith('fedora-'): - cmd_get_kernel_version = 'rpm -q kernel-core|sort -n|tail -1|' \ + cmd_get_kernel_version = 'rpm -q kernel-core|sort -V|tail -1|' \ 'cut -d - -f 3-' elif self.template.startswith('debian-'): cmd_get_kernel_version = \ From bb40d61af993c150af86350e97da40d521a58e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 14 Apr 2018 21:36:03 +0200 Subject: [PATCH 7/7] storage/lvm: filter out warning about intended over-provisioning Over-provisioning on LVM is intended. Since LVM do not have any option to disable it (see [1] and discussion linked from there), filter the warning in post-processing. [1] https://bugzilla.redhat.com/1347008 Fixes QubesOS/qubes-issues#3744 --- qubes/storage/lvm.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index c2460249..168af3c4 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -575,6 +575,11 @@ def qubes_lvm(cmd, log=logging.getLogger('qubes.storage.lvm')): close_fds=True, env=environ) out, err = p.communicate() err = err.decode() + # Filter out warning about intended over-provisioning. + # Upstream discussion about missing option to silence it: + # https://bugzilla.redhat.com/1347008 + err = '\n'.join(line for line in err.splitlines() + if 'exceeds the size of thin pool' not in line) return_code = p.returncode if out: log.debug(out)