diff --git a/doc/source/admin/emulator.conf b/doc/source/admin/emulator.conf index e5bb0e13..5b778a44 100644 --- a/doc/source/admin/emulator.conf +++ b/doc/source/admin/emulator.conf @@ -19,6 +19,15 @@ SUSHY_EMULATOR_OS_CLOUD = None # The libvirt URI to use. This option enables libvirt driver. SUSHY_EMULATOR_LIBVIRT_URI = u'qemu:///system' +# Instruct the libvirt driver to ignore any instructions to +# set the boot device. Allowing the UEFI firmware to instead +# rely on the EFI Boot Manager +# Note: This sets the legacy boot element to dev="fd" +# and relies on the floppy not existing, it likely wont work +# your VM has a floppy drive. +SUSHY_EMULATOR_IGNORE_BOOT_DEVICE = False + + # The map of firmware loaders dependant on the boot mode and # system architecture SUSHY_EMULATOR_BOOT_LOADER_MAP = { diff --git a/sushy_tools/emulator/resources/systems/libvirtdriver.py b/sushy_tools/emulator/resources/systems/libvirtdriver.py index 04cb1d3a..9b9f70c4 100644 --- a/sushy_tools/emulator/resources/systems/libvirtdriver.py +++ b/sushy_tools/emulator/resources/systems/libvirtdriver.py @@ -155,6 +155,8 @@ class LibvirtDriver(AbstractSystemsDriver): 'SUSHY_EMULATOR_BOOT_LOADER_MAP', cls.BOOT_LOADER_MAP) cls.KNOWN_BOOT_LOADERS = set(y for x in cls.BOOT_LOADER_MAP.values() for y in x.values()) + cls.SUSHY_EMULATOR_IGNORE_BOOT_DEVICE = \ + cls._config.get('SUSHY_EMULATOR_IGNORE_BOOT_DEVICE', False) return cls @memoize.memoize() @@ -282,6 +284,11 @@ class LibvirtDriver(AbstractSystemsDriver): :returns: boot device name as `str` or `None` if device name can't be determined """ + + # If not setting Boot devices then just report HDD + if self.SUSHY_EMULATOR_IGNORE_BOOT_DEVICE: + return constants.DEVICE_TYPE_HDD + domain = self._get_domain(identity, readonly=True) tree = ET.fromstring(domain.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)) @@ -347,6 +354,15 @@ class LibvirtDriver(AbstractSystemsDriver): return boot_source_target + def _defineDomain(self, tree): + try: + with libvirt_open(self._uri) as conn: + conn.defineXML(ET.tostring(tree).decode('utf-8')) + except libvirt.libvirtError as e: + msg = ('Error changing boot device at libvirt URI "%(uri)s": ' + '%(error)s' % {'uri': self._uri, 'error': e}) + raise error.FishyError(msg) + def set_boot_device(self, identity, boot_source): """Get/Set computer system boot device name @@ -372,6 +388,13 @@ class LibvirtDriver(AbstractSystemsDriver): for boot_element in os_element.findall('boot'): os_element.remove(boot_element) + if self.SUSHY_EMULATOR_IGNORE_BOOT_DEVICE: + self._logger.warning('Ignoring setting of boot device') + boot_element = ET.SubElement(os_element, 'boot') + boot_element.set('dev', 'fd') + self._defineDomain(tree) + return + target = self.DISK_DEVICE_MAP.get(boot_source) # Process per-device boot configuration @@ -426,15 +449,7 @@ class LibvirtDriver(AbstractSystemsDriver): boot_element = ET.SubElement(target_device_element, 'boot') boot_element.set('order', str(order + 1)) - try: - with libvirt_open(self._uri) as conn: - conn.defineXML(ET.tostring(tree).decode('utf-8')) - - except libvirt.libvirtError as e: - msg = ('Error changing boot device at libvirt URI "%(uri)s": ' - '%(error)s' % {'uri': self._uri, 'error': e}) - - raise error.FishyError(msg) + self._defineDomain(tree) def get_boot_mode(self, identity): """Get computer system boot mode. diff --git a/sushy_tools/tests/unit/emulator/resources/systems/test_libvirt.py b/sushy_tools/tests/unit/emulator/resources/systems/test_libvirt.py index f906e423..39f82751 100644 --- a/sushy_tools/tests/unit/emulator/resources/systems/test_libvirt.py +++ b/sushy_tools/tests/unit/emulator/resources/systems/test_libvirt.py @@ -214,6 +214,27 @@ class LibvirtDriverTestCase(base.BaseTestCase): conn_mock.defineXML.assert_called_once_with(mock.ANY) + @mock.patch('libvirt.open', autospec=True) + def test_set_boot_device_ignored(self, libvirt_mock): + with open('sushy_tools/tests/unit/emulator/' + 'domain_boot_os.xml', 'r') as f: + data = f.read() + + conn_mock = libvirt_mock.return_value + domain_mock = conn_mock.lookupByUUID.return_value + domain_mock.XMLDesc.return_value = data + + self.test_driver.SUSHY_EMULATOR_IGNORE_BOOT_DEVICE = True + + self.test_driver.set_boot_device(self.uuid, 'Hdd') + + conn_mock.defineXML.assert_called_once_with(mock.ANY) + tree = ET.fromstring(conn_mock.defineXML.call_args[0][0]) + self.assertEqual(1, len(tree.findall('.//boot'))) + os_element = tree.find('os') + boot_element = os_element.find('boot') + self.assertEqual('fd', boot_element.get('dev')) + @mock.patch('libvirt.openReadOnly', autospec=True) def test_get_boot_device_disk(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/'