Retain boot device selection upon boot image change

When changing boot image in libvirt domain, note current boot
device and restore it if the image being changed resides on
the active boot device.

Prior to this patch, as a side-effect of changing boot image,
boot device selection could get reset.

Change-Id: Ic848882acbd446effbdf9b761d4ac1025d24c324
This commit is contained in:
Ilya Etingof 2019-11-29 17:14:50 +01:00
parent 564ae30f32
commit 907c3ad6d5
3 changed files with 51 additions and 2 deletions

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Fixes situation when changing boot image could invalidate current boot
device selection. The fix is to note current libvirt boot device and restore
it if the image being changed resides on the active boot device.

View File

@ -990,11 +990,14 @@ class LibvirtDriver(AbstractSystemsDriver):
self._remove_boot_images(domain, domain_tree, device)
if boot_image:
boot_device = None
if boot_image:
self._add_boot_image(domain, domain_tree, device,
boot_image, write_protected)
boot_device = self.get_boot_device(identity)
with libvirt_open(self._uri) as conn:
xml = ET.tostring(domain_tree)
@ -1009,6 +1012,9 @@ class LibvirtDriver(AbstractSystemsDriver):
raise error.FishyError(msg)
if device == boot_device:
self.set_boot_device(identity, boot_device)
def _find_device_by_path(self, vol_path):
"""Get device attributes using path

View File

@ -512,7 +512,11 @@ class LibvirtDriverTestCase(base.BaseTestCase):
with mock.patch.object(
self.test_driver, 'get_power_state', return_value='Off'):
self.test_driver.set_boot_image(self.uuid, 'Cd', '/tmp/image.iso')
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()
@ -524,6 +528,39 @@ class LibvirtDriverTestCase(base.BaseTestCase):
conn_mock.defineXML.assert_called_once_with(mock.ANY)
@mock.patch('libvirt.open', autospec=True)
@mock.patch('libvirt.openReadOnly', autospec=True)
@mock.patch(
'sushy_tools.emulator.resources.systems.libvirtdriver.LibvirtDriver'
'.get_power_state', new=mock.MagicMock(return_value='Off'))
@mock.patch(
'sushy_tools.emulator.resources.systems.libvirtdriver.LibvirtDriver'
'.get_boot_device', return_value='Cd')
@mock.patch(
'sushy_tools.emulator.resources.systems.libvirtdriver.LibvirtDriver'
'.set_boot_device')
@mock.patch(
'sushy_tools.emulator.resources.systems.libvirtdriver.LibvirtDriver'
'._add_boot_image', new=mock.MagicMock())
@mock.patch(
'sushy_tools.emulator.resources.systems.libvirtdriver.LibvirtDriver'
'._remove_boot_images', new=mock.MagicMock())
def test_set_boot_image_restore_boot_device(
self, sbd_mock, gbd_mock, libvirt_mock, libvirt_rw_mock):
with open('sushy_tools/tests/unit/emulator/domain.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
self.test_driver.set_boot_image(
self.uuid, 'Cd', '/tmp/image.iso')
gbd_mock.assert_called_once_with(self.uuid)
sbd_mock.assert_called_once_with(self.uuid, 'Cd')
@mock.patch('libvirt.openReadOnly', autospec=True)
def test_get_total_memory(self, libvirt_mock):
conn_mock = libvirt_mock.return_value