Browse Source

Merge remote-tracking branch 'qubesos/pr/156'

* qubesos/pr/156:
  tests: Add unit tests for pvh virt_mode
  Don't allow attached PCI devices and virt_mode = 'pvh'
Marek Marczykowski-Górecki 6 years ago
parent
commit
3217c3ac4e
3 changed files with 84 additions and 0 deletions
  1. 4 0
      qubes/ext/pci.py
  2. 77 0
      qubes/tests/vm/qubesvm.py
  3. 3 0
      qubes/vm/qubesvm.py

+ 4 - 0
qubes/ext/pci.py

@@ -224,6 +224,10 @@ class PCIDeviceExtension(qubes.ext.Extension):
             raise qubes.exc.QubesException(
                 'Invalid PCI device: {}'.format(device.ident))
 
+        if vm.virt_mode == 'pvh':
+            raise qubes.exc.QubesException(
+                "Can't attach PCI device to VM in pvh mode")
+
         if not vm.is_running():
             return
 

+ 77 - 0
qubes/tests/vm/qubesvm.py

@@ -47,6 +47,13 @@ class TestProp(object):
     # pylint: disable=too-few-public-methods
     __name__ = 'testprop'
 
+class TestDeviceCollection(object):
+    def __init__(self):
+        self._list = []
+
+    def persistent(self):
+        return self._list
+
 class TestVM(object):
     # pylint: disable=too-few-public-methods
     app = TestApp()
@@ -56,6 +63,7 @@ class TestVM(object):
         self.installed_by_rpm = False
         for k, v in kwargs.items():
             setattr(self, k, v)
+        self.devices = {'pci': TestDeviceCollection()}
 
     def is_running(self):
         return self.running
@@ -108,6 +116,12 @@ class TC_00_setters(qubes.tests.QubesTestCase):
         self.assertEqual(
             qubes.vm.qubesvm._setter_virt_mode(self.vm, self.prop, 'PV'),
             'pv')
+        self.assertEqual(
+            qubes.vm.qubesvm._setter_virt_mode(self.vm, self.prop, 'pvh'),
+            'pvh')
+        self.vm.devices['pci']._list.append(object())
+        with self.assertRaises(ValueError):
+            qubes.vm.qubesvm._setter_virt_mode(self.vm, self.prop, 'pvh')
         with self.assertRaises(ValueError):
             qubes.vm.qubesvm._setter_virt_mode(self.vm, self.prop, 'True')
 
@@ -608,3 +622,66 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
         libvirt_xml = vm.create_config_file()
         self.assertXMLEqual(lxml.etree.XML(libvirt_xml),
             lxml.etree.XML(expected))
+
+    def test_600_libvirt_xml_pvh(self):
+        expected = '''<domain type="xen">
+        <name>test-inst-test</name>
+        <uuid>7db78950-c467-4863-94d1-af59806384ea</uuid>
+        <memory unit="MiB">500</memory>
+        <currentMemory unit="MiB">400</currentMemory>
+        <vcpu placement="static">2</vcpu>
+        <cpu mode='host-passthrough'>
+            <!-- disable nested HVM -->
+            <feature name='vmx' policy='disable'/>
+            <feature name='svm' policy='disable'/>
+            <!-- disable SMAP inside VM, because of Linux bug -->
+            <feature name='smap' policy='disable'/>
+        </cpu>
+        <os>
+            <type arch="x86_64" machine="xenfv">hvm</type>
+            <kernel>/tmp/kernel/vmlinuz</kernel>
+            <initrd>/tmp/kernel/initramfs</initrd>
+            <cmdline>root=/dev/mapper/dmroot ro nomodeset console=hvc0 rd_NO_PLYMOUTH rd.plymouth.enable=0 plymouth.enable=0 nopat</cmdline>
+        </os>
+        <features>
+            <pae/>
+            <acpi/>
+            <apic/>
+            <viridian/>
+        </features>
+        <clock offset='utc' adjustment='reset'>
+            <timer name="tsc" mode="native"/>
+        </clock>
+        <on_poweroff>destroy</on_poweroff>
+        <on_reboot>destroy</on_reboot>
+        <on_crash>destroy</on_crash>
+        <devices>
+            <disk type="block" device="disk">
+                <driver name="phy" />
+                <source dev="/tmp/kernel/modules.img" />
+                <target dev="xvdd" />
+                <backenddomain name="dom0" />
+            </disk>
+            <emulator type="none" />
+            <console type="pty">
+                <target type="xen" port="0"/>
+            </console>
+        </devices>
+        </domain>
+        '''
+        my_uuid = '7db78950-c467-4863-94d1-af59806384ea'
+        vm = self.get_vm(uuid=my_uuid)
+        vm.netvm = None
+        vm.virt_mode = 'pvh'
+        # tests for storage are later
+        vm.volumes['kernel'] = unittest.mock.Mock(**{
+            'kernels_dir': '/tmp/kernel',
+            'block_device.return_value.domain': 'dom0',
+            'block_device.return_value.script': None,
+            'block_device.return_value.path': '/tmp/kernel/modules.img',
+            'block_device.return_value.devtype': 'disk',
+            'block_device.return_value.name': 'kernel',
+        })
+        libvirt_xml = vm.create_config_file()
+        self.assertXMLEqual(lxml.etree.XML(libvirt_xml),
+            lxml.etree.XML(expected))

+ 3 - 0
qubes/vm/qubesvm.py

@@ -95,6 +95,9 @@ def _setter_virt_mode(self, prop, value):
     if value not in ('hvm', 'pv', 'pvh'):
         raise qubes.exc.QubesPropertyValueError(self, prop, value,
             'Invalid virtualization mode, supported values: hvm, pv, pvh')
+    if value == 'pvh' and list(self.devices['pci'].persistent()):
+        raise qubes.exc.QubesPropertyValueError(self, prop, value,
+            "pvh mode can't be set if pci devices are attached")
     return value