From 1f61fc1ecabb654f1859245d92fa15728a54bb78 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur <dtantsur@protonmail.com> Date: Fri, 30 Oct 2020 16:02:27 +0100 Subject: [PATCH] Fix virtual media with q35 machines This machine type does not have IDE controllers, don't try using them. Change-Id: I0be094e25e5d72230c2d4db1b50eafc782530f1b --- releasenotes/notes/q35-aea1a63ff2c7c72b.yaml | 4 ++ .../resources/systems/libvirtdriver.py | 15 +++++- .../tests/unit/emulator/domain-q35.xml | 28 ++++++++++ .../resources/systems/test_libvirt.py | 53 +++++++++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/q35-aea1a63ff2c7c72b.yaml create mode 100644 sushy_tools/tests/unit/emulator/domain-q35.xml diff --git a/releasenotes/notes/q35-aea1a63ff2c7c72b.yaml b/releasenotes/notes/q35-aea1a63ff2c7c72b.yaml new file mode 100644 index 00000000..d7f46148 --- /dev/null +++ b/releasenotes/notes/q35-aea1a63ff2c7c72b.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - | + No longer tries to use IDE controllers on q35 machines. diff --git a/sushy_tools/emulator/resources/systems/libvirtdriver.py b/sushy_tools/emulator/resources/systems/libvirtdriver.py index e7c3a3e5..8151abf3 100644 --- a/sushy_tools/emulator/resources/systems/libvirtdriver.py +++ b/sushy_tools/emulator/resources/systems/libvirtdriver.py @@ -842,6 +842,18 @@ class LibvirtDriver(AbstractSystemsDriver): return image_path + def _default_controller(self, domain_tree): + os_element = domain_tree.find('os') + if os_element is not None: + type_element = os_element.find('type') + if type_element is not None: + machine = type_element.attrib.get('machine') + if machine and 'q35' in machine: + # No IDE support for newer q35 machine types + return 'sata' + + return 'ide' + def _add_boot_image(self, domain, domain_tree, device, boot_image, write_protected): @@ -853,6 +865,8 @@ class LibvirtDriver(AbstractSystemsDriver): '"%(identity)s" configuration' % {'identity': identity}) raise error.FishyError(msg) + controller_type = self._default_controller(domain_tree) + with libvirt_open(self._uri) as conn: image_path = self._upload_image(domain, conn, boot_image) @@ -865,7 +879,6 @@ class LibvirtDriver(AbstractSystemsDriver): 'Unknown device %s at %s' % (device, identity)) disk_elements = device_element.findall('disk') - controller_type = 'ide' for disk_element in disk_elements: target_element = disk_element.find('target') if target_element is None: diff --git a/sushy_tools/tests/unit/emulator/domain-q35.xml b/sushy_tools/tests/unit/emulator/domain-q35.xml new file mode 100644 index 00000000..4e792154 --- /dev/null +++ b/sushy_tools/tests/unit/emulator/domain-q35.xml @@ -0,0 +1,28 @@ +<domain type='qemu'> + <name>QEmu-fedora-i686</name> + <uuid>c7a5fdbd-cdaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>2</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='cdrom'/> + <loader type='rom'/> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='cdrom'> + <source file='/home/user/boot.iso'/> + <target dev='hdc'/> + <readonly/> + </disk> + <disk type='file' device='disk'> + <source file='/home/user/fedora.img'/> + <target dev='hda'/> + </disk> + <interface type='network'> + <source network='default'/> + </interface> + <graphics type='vnc' port='-1'/> + </devices> +</domain> 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 8ba846c0..119126bb 100644 --- a/sushy_tools/tests/unit/emulator/resources/systems/test_libvirt.py +++ b/sushy_tools/tests/unit/emulator/resources/systems/test_libvirt.py @@ -540,6 +540,59 @@ class LibvirtDriverTestCase(base.BaseTestCase): self.assertEqual(1, conn_mock.defineXML.call_count) self.assertIn(expected_disk, conn_mock.defineXML.call_args[0][0]) + @mock.patch('sushy_tools.emulator.resources.systems.libvirtdriver' + '.os.stat', autospec=True) + @mock.patch('sushy_tools.emulator.resources.systems.libvirtdriver' + '.open') + @mock.patch('libvirt.open', autospec=True) + @mock.patch('libvirt.openReadOnly', autospec=True) + def test_set_boot_image_q35(self, libvirt_mock, libvirt_rw_mock, + open_mock, stat_mock): + with open('sushy_tools/tests/unit/emulator/domain-q35.xml', 'r') as f: + data = f.read() + + conn_mock = libvirt_rw_mock.return_value + domain_mock = conn_mock.lookupByUUID.return_value + domain_mock.XMLDesc.return_value = data + + pool_mock = conn_mock.storagePoolLookupByName.return_value + + with open('sushy_tools/tests/unit/emulator/pool.xml', 'r') as f: + data = f.read() + + pool_mock.XMLDesc.return_value = data + + with mock.patch.object( + self.test_driver, 'get_power_state', return_value='Off'): + with mock.patch.object( + self.test_driver, 'get_boot_device', return_value=None): + + self.test_driver.set_boot_image( + self.uuid, 'Cd', '/tmp/image.iso') + + conn_mock = libvirt_rw_mock.return_value + pool_mock.listAllVolumes.assert_called_once_with() + stat_mock.assert_called_once_with('/tmp/image.iso') + pool_mock.createXML.assert_called_once_with(mock.ANY) + + volume_mock = pool_mock.createXML.return_value + volume_mock.upload.assert_called_once_with(mock.ANY, 0, mock.ANY) + + expected_disk = ('<disk device="cdrom" type="file">' + '<target bus="sata" dev="sdc" />' + '<address bus="0" controller="0" ' + 'target="0" type="drive" unit="0" />') + + # NOTE(rpittau): starting from Python 3.8 the tostring() function + # preserves the attribute order specified by the user. + if sys.version_info[1] >= 8: + expected_disk = ('<disk type="file" device="cdrom">' + '<target dev="sdc" bus="sata" />' + '<address type="drive" controller="0"' + ' bus="0" target="0" unit="0" />') + self.assertEqual(1, conn_mock.defineXML.call_count) + self.assertIn(expected_disk, conn_mock.defineXML.call_args[0][0]) + @mock.patch('sushy_tools.emulator.resources.systems.libvirtdriver' '.os.stat', autospec=True) @mock.patch('sushy_tools.emulator.resources.systems.libvirtdriver'