From ff2be838b9da25998202a93f2120d1350f2a1f6e Mon Sep 17 00:00:00 2001 From: Julia Kreger Date: Wed, 1 Jul 2020 09:01:12 -0700 Subject: [PATCH] Support non-ide virtual media buses Also fix a minor possible bug with interpretation of XML returning a string trying to be compared to a number, and adds two test files and associated tests for the injection of SATA or SCSI removable disk drives. Story: 2007881 Task: 40249 Change-Id: Ia926a8f9d8debaff9763aeebcd986f9056cca700 --- ...-media-alternate-bus-6d984ae45acb7ac4.yaml | 5 + .../resources/systems/libvirtdriver.py | 24 ++++- .../tests/unit/emulator/domain-sata.xml | 24 +++++ .../tests/unit/emulator/domain-scsi.xml | 24 +++++ .../resources/systems/test_libvirt.py | 97 ++++++++++++++++++- 5 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/virtual-media-alternate-bus-6d984ae45acb7ac4.yaml create mode 100644 sushy_tools/tests/unit/emulator/domain-sata.xml create mode 100644 sushy_tools/tests/unit/emulator/domain-scsi.xml diff --git a/releasenotes/notes/virtual-media-alternate-bus-6d984ae45acb7ac4.yaml b/releasenotes/notes/virtual-media-alternate-bus-6d984ae45acb7ac4.yaml new file mode 100644 index 00000000..0512ca59 --- /dev/null +++ b/releasenotes/notes/virtual-media-alternate-bus-6d984ae45acb7ac4.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Adds basic support for virtual media devices on non-IDE buses, such as SATA and + SCSI, as IDE devices are not supported on Q35 libvirt domains. diff --git a/sushy_tools/emulator/resources/systems/libvirtdriver.py b/sushy_tools/emulator/resources/systems/libvirtdriver.py index 36016c39..e7c3a3e5 100644 --- a/sushy_tools/emulator/resources/systems/libvirtdriver.py +++ b/sushy_tools/emulator/resources/systems/libvirtdriver.py @@ -118,10 +118,10 @@ class LibvirtDriver(AbstractSystemsDriver): DEVICE_TYPE_MAP_REV = {v: k for k, v in DEVICE_TYPE_MAP.items()} - # target device, controller ID + # target device, controller ID for libvirt domain DEVICE_TARGET_MAP = { constants.DEVICE_TYPE_FLOPPY: ('fda', 'fdc'), - constants.DEVICE_TYPE_CD: ('hdc', 'ide') + constants.DEVICE_TYPE_CD: ('hdc', 'ide'), } DEFAULT_BIOS_ATTRIBUTES = {"BootMode": "Uefi", @@ -864,7 +864,21 @@ class LibvirtDriver(AbstractSystemsDriver): raise error.FishyError( 'Unknown device %s at %s' % (device, identity)) - tgt_dev, tgt_bus = self.DEVICE_TARGET_MAP[device] + 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: + continue + elif target_element.attrib.get('bus') == 'scsi': + controller_type = 'scsi' + elif target_element.attrib.get('bus') == 'sata': + controller_type = 'sata' + + if controller_type == 'ide': + tgt_dev, tgt_bus = self.DEVICE_TARGET_MAP[device] + else: + tgt_dev, tgt_bus = ('sdc', controller_type) # Enumerate existing disks to find a free unit on the bus @@ -889,8 +903,8 @@ class LibvirtDriver(AbstractSystemsDriver): if unit_num is None: continue - if unit_num in free_units: - free_units.remove(unit_num) + if int(unit_num) in free_units: + free_units.remove(int(unit_num)) if not free_units: msg = ('No free %(bus)s bus unit found in the libvirt domain ' diff --git a/sushy_tools/tests/unit/emulator/domain-sata.xml b/sushy_tools/tests/unit/emulator/domain-sata.xml new file mode 100644 index 00000000..6920bb67 --- /dev/null +++ b/sushy_tools/tests/unit/emulator/domain-sata.xml @@ -0,0 +1,24 @@ + + QEmu-fedora-i686 + c7a5fdbd-cdaf-9455-926a-d65c16db1809 + 219200 + 219200 + 2 + + hvm + + + + + /usr/bin/qemu-system-x86_64 + + + +
+ + + + + + + diff --git a/sushy_tools/tests/unit/emulator/domain-scsi.xml b/sushy_tools/tests/unit/emulator/domain-scsi.xml new file mode 100644 index 00000000..74fa61a3 --- /dev/null +++ b/sushy_tools/tests/unit/emulator/domain-scsi.xml @@ -0,0 +1,24 @@ + + QEmu-fedora-i686 + c7a5fdbd-cdaf-9455-926a-d65c16db1809 + 219200 + 219200 + 2 + + hvm + + + + + /usr/bin/qemu-system-x86_64 + + + +
+ + + + + + + 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 beb94a32..7245aa4e 100644 --- a/sushy_tools/tests/unit/emulator/resources/systems/test_libvirt.py +++ b/sushy_tools/tests/unit/emulator/resources/systems/test_libvirt.py @@ -525,7 +525,102 @@ class LibvirtDriverTestCase(base.BaseTestCase): volume_mock = pool_mock.createXML.return_value volume_mock.upload.assert_called_once_with(mock.ANY, 0, mock.ANY) - conn_mock.defineXML.assert_called_once_with(mock.ANY) + expected_disk = ('' + '' + '
') + 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_sata(self, libvirt_mock, libvirt_rw_mock, + open_mock, stat_mock): + with open('sushy_tools/tests/unit/emulator/domain-sata.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 = ('' + '' + '
') + 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_scsi(self, libvirt_mock, libvirt_rw_mock, + open_mock, stat_mock): + with open('sushy_tools/tests/unit/emulator/domain-scsi.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 = ('' + '' + '
') + self.assertEqual(1, conn_mock.defineXML.call_count) + self.assertIn(expected_disk, conn_mock.defineXML.call_args[0][0]) @mock.patch('libvirt.open', autospec=True) @mock.patch('libvirt.openReadOnly', autospec=True)