From b1e83f899f73df485f962fd22ebc955ada10e533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Tue, 27 Feb 2018 02:28:31 +0100 Subject: [PATCH] tests: convert pvgrub tests to core3 API QubesOS/qubes-issues#3563 --- qubes/tests/__init__.py | 1 + qubes/tests/integ/pvgrub.py | 146 ++++++++++++++++++++++++++++++ rpm_spec/core-dom0.spec | 1 + tests/pvgrub.py | 171 ------------------------------------ 4 files changed, 148 insertions(+), 171 deletions(-) create mode 100644 qubes/tests/integ/pvgrub.py delete mode 100644 tests/pvgrub.py diff --git a/qubes/tests/__init__.py b/qubes/tests/__init__.py index 9c11cbfd..367e269e 100644 --- a/qubes/tests/__init__.py +++ b/qubes/tests/__init__.py @@ -1195,6 +1195,7 @@ def load_tests(loader, tests, pattern): # pylint: disable=unused-argument # integration tests 'qubes.tests.integ.basic', 'qubes.tests.integ.storage', + 'qubes.tests.integ.pvgrub', 'qubes.tests.integ.devices_pci', 'qubes.tests.integ.dom0_update', 'qubes.tests.integ.network', diff --git a/qubes/tests/integ/pvgrub.py b/qubes/tests/integ/pvgrub.py new file mode 100644 index 00000000..92a12f29 --- /dev/null +++ b/qubes/tests/integ/pvgrub.py @@ -0,0 +1,146 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# The Qubes OS Project, http://www.qubes-os.org +# +# Copyright (C) 2016 Marek Marczykowski-Górecki +# +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# +# + +import os +import subprocess +import unittest +import qubes.tests +@unittest.skipUnless(os.path.exists('/var/lib/qubes/vm-kernels/pvgrub2'), + 'grub-xen package not installed') +class TC_40_PVGrub(object): + def setUp(self): + super(TC_40_PVGrub, self).setUp() + supported = False + if self.template.startswith('fedora-'): + supported = True + elif self.template.startswith('debian-'): + supported = True + if not supported: + self.skipTest("Template {} not supported by this test".format( + self.template)) + + def install_packages(self, vm): + if self.template.startswith('fedora-'): + cmd_install1 = 'dnf clean expire-cache && ' \ + 'dnf install -y qubes-kernel-vm-support grub2-tools' + cmd_install2 = 'dnf install -y kernel-core && ' \ + 'KVER=$(rpm -q --qf ' \ + '\'%{VERSION}-%{RELEASE}.%{ARCH}\\n\' kernel-core|head -1) && ' \ + 'dnf install --allowerasing -y kernel-devel-$KVER && ' \ + 'dkms autoinstall -k $KVER' + cmd_update_grub = 'grub2-mkconfig -o /boot/grub2/grub.cfg' + elif self.template.startswith('debian-'): + cmd_install1 = 'apt-get update && apt-get install -y ' \ + 'qubes-kernel-vm-support grub2-common' + cmd_install2 = 'apt-get install -y linux-image-amd64' + cmd_update_grub = 'mkdir -p /boot/grub && update-grub2' + else: + assert False, "Unsupported template?!" + + for cmd in [cmd_install1, cmd_install2, cmd_update_grub]: + try: + self.loop.run_until_complete(vm.run_for_stdio( + cmd, user="root")) + except subprocess.CalledProcessError as err: + self.fail("Failed command: {}\nSTDOUT: {}\nSTDERR: {}" + .format(cmd, err.stdout, err.stderr)) + + def get_kernel_version(self, vm): + if self.template.startswith('fedora-'): + cmd_get_kernel_version = 'rpm -q kernel-core|sort -n|tail -1|' \ + 'cut -d - -f 3-' + elif self.template.startswith('debian-'): + cmd_get_kernel_version = \ + 'dpkg-query --showformat=\'${Package}\\n\' --show ' \ + '\'linux-image-*-amd64\'|sort -n|tail -1|cut -d - -f 3-' + else: + raise RuntimeError("Unsupported template?!") + + kver, _ = self.loop.run_until_complete(vm.run_for_stdio( + cmd_get_kernel_version, user="root")) + return kver.strip() + + def test_000_standalone_vm(self): + self.testvm1 = self.app.add_new_vm('StandaloneVM', + name=self.make_vm_name('vm1'), + label='red') + self.testvm1.virt_mode = 'pv' + self.testvm1.features.update(self.app.domains[self.template].features) + self.loop.run_until_complete( + self.testvm1.clone_disk_files(self.app.domains[self.template])) + self.loop.run_until_complete(self.testvm1.start()) + self.install_packages(self.testvm1) + kver = self.get_kernel_version(self.testvm1) + self.loop.run_until_complete(self.testvm1.shutdown(wait=True)) + + self.testvm1.kernel = 'pvgrub2' + self.loop.run_until_complete(self.testvm1.start()) + (actual_kver, _) = self.loop.run_until_complete( + self.testvm1.run_for_stdio('uname -r')) + self.assertEquals(actual_kver.strip(), kver) + + def test_010_template_based_vm(self): + self.test_template = self.app.add_new_vm('TemplateVM', + name=self.make_vm_name('template'), label='red') + self.test_template.virt_mode = 'pv' + self.test_template.features.update(self.app.domains[self.template].features) + self.loop.run_until_complete( + self.test_template.clone_disk_files(self.app.domains[self.template])) + + self.testvm1 = self.app.add_new_vm("AppVM", + template=self.test_template, + name=self.make_vm_name('vm1'), + label='red') + self.testvm1.virt_mode = 'pv' + self.loop.run_until_complete(self.testvm1.create_on_disk()) + self.loop.run_until_complete(self.test_template.start()) + self.install_packages(self.test_template) + kver = self.get_kernel_version(self.test_template) + self.loop.run_until_complete(self.test_template.shutdown(wait=True)) + + self.test_template.kernel = 'pvgrub2' + self.testvm1.kernel = 'pvgrub2' + + # Check if TemplateBasedVM boots and has the right kernel + self.loop.run_until_complete( + self.testvm1.start()) + (actual_kver, _) = self.loop.run_until_complete( + self.testvm1.run_for_stdio('uname -r')) + self.assertEquals(actual_kver.strip(), kver) + + # And the same for the TemplateVM itself + self.loop.run_until_complete(self.test_template.start()) + (actual_kver, _) = self.loop.run_until_complete( + self.test_template.run_for_stdio('uname -r')) + self.assertEquals(actual_kver.strip(), kver) + + +def load_tests(loader, tests, pattern): + for template in qubes.tests.list_templates(): + tests.addTests(loader.loadTestsFromTestCase( + type( + 'TC_40_PVGrub_' + template, + (TC_40_PVGrub, qubes.tests.SystemTestCase), + {'template': template}))) + + return tests diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index 4f3e99b4..de2816d4 100644 --- a/rpm_spec/core-dom0.spec +++ b/rpm_spec/core-dom0.spec @@ -350,6 +350,7 @@ fi %{python3_sitelib}/qubes/tests/integ/dispvm.py %{python3_sitelib}/qubes/tests/integ/dom0_update.py %{python3_sitelib}/qubes/tests/integ/network.py +%{python3_sitelib}/qubes/tests/integ/pvgrub.py %{python3_sitelib}/qubes/tests/integ/salt.py %{python3_sitelib}/qubes/tests/integ/storage.py %{python3_sitelib}/qubes/tests/integ/vm_qrexec_gui.py diff --git a/tests/pvgrub.py b/tests/pvgrub.py deleted file mode 100644 index 86ab8004..00000000 --- a/tests/pvgrub.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# The Qubes OS Project, http://www.qubes-os.org -# -# Copyright (C) 2016 Marek Marczykowski-Górecki -# -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, see . -# -# - -import os -import unittest -import qubes.tests -@unittest.skipUnless(os.path.exists('/var/lib/qubes/vm-kernels/pvgrub2'), - 'grub-xen package not installed') -class TC_40_PVGrub(qubes.tests.SystemTestsMixin): - def setUp(self): - super(TC_40_PVGrub, self).setUp() - supported = False - if self.template.startswith('fedora-'): - supported = True - elif self.template.startswith('debian-'): - supported = True - if not supported: - self.skipTest("Template {} not supported by this test".format( - self.template)) - - def install_packages(self, vm): - if self.template.startswith('fedora-'): - cmd_install1 = 'dnf clean expire-cache && ' \ - 'dnf install -y qubes-kernel-vm-support grub2-tools' - cmd_install2 = 'dnf install -y kernel && ' \ - 'KVER=$(rpm -q --qf %{VERSION}-%{RELEASE}.%{ARCH} kernel) && ' \ - 'dnf install --allowerasing -y kernel-devel-$KVER && ' \ - 'dkms autoinstall -k $KVER' - cmd_update_grub = 'grub2-mkconfig -o /boot/grub2/grub.cfg' - elif self.template.startswith('debian-'): - cmd_install1 = 'apt-get update && apt-get install -y ' \ - 'qubes-kernel-vm-support grub2-common' - cmd_install2 = 'apt-get install -y linux-image-amd64' - cmd_update_grub = 'mkdir /boot/grub && update-grub2' - else: - assert False, "Unsupported template?!" - - for cmd in [cmd_install1, cmd_install2, cmd_update_grub]: - p = vm.run(cmd, user="root", passio_popen=True, passio_stderr=True) - (stdout, stderr) = p.communicate() - self.assertEquals(p.returncode, 0, - "Failed command: {}\nSTDOUT: {}\nSTDERR: {}" - .format(cmd, stdout, stderr)) - - def get_kernel_version(self, vm): - if self.template.startswith('fedora-'): - cmd_get_kernel_version = 'rpm -q kernel|sort -n|tail -1|' \ - 'cut -d - -f 2-' - elif self.template.startswith('debian-'): - cmd_get_kernel_version = \ - 'dpkg-query --showformat=\'${Package}\\n\' --show ' \ - '\'linux-image-*-amd64\'|sort -n|tail -1|cut -d - -f 3-' - else: - raise RuntimeError("Unsupported template?!") - - p = vm.run(cmd_get_kernel_version, user="root", passio_popen=True) - (kver, _) = p.communicate() - self.assertEquals(p.returncode, 0, - "Failed command: {}".format(cmd_get_kernel_version)) - return kver.strip() - - def test_000_standalone_vm(self): - testvm1 = self.qc.add_new_vm("QubesAppVm", - template=None, - name=self.make_vm_name('vm1')) - testvm1.create_on_disk(verbose=False, - source_template=self.qc.get_vm_by_name( - self.template)) - self.app.save() - self.qc.unlock_db() - testvm1 = self.qc[testvm1.qid] - testvm1.start() - self.install_packages(testvm1) - kver = self.get_kernel_version(testvm1) - self.shutdown_and_wait(testvm1) - - self.qc.lock_db_for_writing() - self.qc.load() - testvm1 = self.qc[testvm1.qid] - testvm1.kernel = 'pvgrub2' - self.app.save() - self.qc.unlock_db() - testvm1 = self.qc[testvm1.qid] - testvm1.start() - p = testvm1.run('uname -r', passio_popen=True) - (actual_kver, _) = p.communicate() - self.assertEquals(actual_kver.strip(), kver) - - def test_010_template_based_vm(self): - test_template = self.qc.add_new_vm("QubesTemplateVm", - template=None, - name=self.make_vm_name('template')) - test_template.clone_attrs(self.qc.get_vm_by_name(self.template)) - test_template.clone_disk_files( - src_vm=self.qc.get_vm_by_name(self.template), - verbose=False) - - testvm1 = self.qc.add_new_vm("QubesAppVm", - template=test_template, - name=self.make_vm_name('vm1')) - testvm1.create_on_disk(verbose=False, - source_template=test_template) - self.app.save() - self.qc.unlock_db() - test_template = self.qc[test_template.qid] - testvm1 = self.qc[testvm1.qid] - test_template.start() - self.install_packages(test_template) - kver = self.get_kernel_version(test_template) - self.shutdown_and_wait(test_template) - - self.qc.lock_db_for_writing() - self.qc.load() - test_template = self.qc[test_template.qid] - test_template.kernel = 'pvgrub2' - testvm1 = self.qc[testvm1.qid] - testvm1.kernel = 'pvgrub2' - self.app.save() - self.qc.unlock_db() - - # Check if TemplateBasedVM boots and has the right kernel - testvm1 = self.qc[testvm1.qid] - testvm1.start() - p = testvm1.run('uname -r', passio_popen=True) - (actual_kver, _) = p.communicate() - self.assertEquals(actual_kver.strip(), kver) - - # And the same for the TemplateVM itself - test_template = self.qc[test_template.qid] - test_template.start() - p = test_template.run('uname -r', passio_popen=True) - (actual_kver, _) = p.communicate() - self.assertEquals(actual_kver.strip(), kver) - -def load_tests(loader, tests, pattern): - try: - qc = qubes.qubes.QubesVmCollection() - qc.lock_db_for_reading() - qc.load() - qc.unlock_db() - templates = [vm.name for vm in qc.values() if - isinstance(vm, qubes.qubes.QubesTemplateVm)] - except OSError: - templates = [] - for template in templates: - tests.addTests(loader.loadTestsFromTestCase( - type( - 'TC_40_PVGrub_' + template, - (TC_40_PVGrub, qubes.tests.QubesTestCase), - {'template': template}))) - return tests