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
This commit is contained in:
parent
74769fac82
commit
ff2be838b9
@ -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.
|
@ -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 '
|
||||
|
24
sushy_tools/tests/unit/emulator/domain-sata.xml
Normal file
24
sushy_tools/tests/unit/emulator/domain-sata.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<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='pc'>hvm</type>
|
||||
<boot dev='cdrom'/>
|
||||
<loader type='rom'/>
|
||||
</os>
|
||||
<devices>
|
||||
<emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
<disk type='file' device='disk'>
|
||||
<source file='/home/user/fedora.img'/>
|
||||
<target bus='sata' dev='sda'/>
|
||||
<address bus='0' target='0' type='drive' unit='0'/>
|
||||
</disk>
|
||||
<interface type='network'>
|
||||
<source network='default'/>
|
||||
</interface>
|
||||
<graphics type='vnc' port='-1'/>
|
||||
</devices>
|
||||
</domain>
|
24
sushy_tools/tests/unit/emulator/domain-scsi.xml
Normal file
24
sushy_tools/tests/unit/emulator/domain-scsi.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<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='pc'>hvm</type>
|
||||
<boot dev='cdrom'/>
|
||||
<loader type='rom'/>
|
||||
</os>
|
||||
<devices>
|
||||
<emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
<disk type='file' device='disk'>
|
||||
<source file='/home/user/fedora.img'/>
|
||||
<target bus='scsi' dev='sda'/>
|
||||
<address bus='0' target='0' type='drive' unit='0'/>
|
||||
</disk>
|
||||
<interface type='network'>
|
||||
<source network='default'/>
|
||||
</interface>
|
||||
<graphics type='vnc' port='-1'/>
|
||||
</devices>
|
||||
</domain>
|
@ -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 = ('<disk device="cdrom" type="file">'
|
||||
'<target bus="ide" dev="hdc" />'
|
||||
'<address bus="0" controller="0" '
|
||||
'target="0" type="drive" 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'
|
||||
'.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 = ('<disk device="cdrom" type="file">'
|
||||
'<target bus="sata" dev="sdc" />'
|
||||
'<address bus="0" controller="0" '
|
||||
'target="0" type="drive" unit="1" />')
|
||||
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 = ('<disk device="cdrom" type="file">'
|
||||
'<target bus="scsi" dev="sdc" />'
|
||||
'<address bus="0" controller="0" '
|
||||
'target="0" type="drive" unit="1" />')
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user