Force iRMC vmedia boot from remotely connected CD/DVD
This patch forces iRMC vmedia boot from remotely connected (redirected) CD/DVD using 'ipmitool raw' command instead of 'ipmitool chassis bootdev cdrom'. Closes-Bug: #1561852 Change-Id: I606e4d3a630ddc4eed071773afcb5274ee64a439
This commit is contained in:
parent
8e81b964a5
commit
03fe93abfe
@ -35,7 +35,12 @@ LOG = logging.getLogger(__name__)
|
||||
# Set/Get System Boot Options Command, IPMI spec v2.0.
|
||||
_BOOTPARAM5_DATA2 = {boot_devices.PXE: '0x04',
|
||||
boot_devices.DISK: '0x08',
|
||||
boot_devices.CDROM: '0x14',
|
||||
# note (naohirot)
|
||||
# boot_devices.CDROM is tentatively set to '0x20' rather
|
||||
# than '0x14' as a work-around to force iRMC vmedia boot.
|
||||
# 0x14 = Force boot from default CD/DVD
|
||||
# 0x20 = Force boot from remotely connected CD/DVD
|
||||
boot_devices.CDROM: '0x20',
|
||||
boot_devices.BIOS: '0x18',
|
||||
boot_devices.SAFE: '0x0c',
|
||||
}
|
||||
@ -141,33 +146,37 @@ class IRMCManagement(ipmitool.IPMIManagement):
|
||||
:raises: IPMIFailure on an error from ipmitool.
|
||||
|
||||
"""
|
||||
if driver_utils.get_node_capability(task.node, 'boot_mode') == 'uefi':
|
||||
if device not in self.get_supported_boot_devices(task):
|
||||
raise exception.InvalidParameterValue(_(
|
||||
"Invalid boot device %s specified.") % device)
|
||||
timeout_disable = "0x00 0x08 0x03 0x08"
|
||||
ipmitool.send_raw(task, timeout_disable)
|
||||
if device not in self.get_supported_boot_devices(task):
|
||||
raise exception.InvalidParameterValue(_(
|
||||
"Invalid boot device %s specified.") % device)
|
||||
|
||||
# note(naohirot): As of ipmitool version 1.8.13,
|
||||
# in case of chassis command, the efiboot option doesn't
|
||||
# get set with persistent at the same time.
|
||||
# $ ipmitool chassis bootdev pxe options=efiboot,persistent
|
||||
# In case of raw command, however, both can be set at the
|
||||
# same time.
|
||||
# $ ipmitool raw 0x00 0x08 0x05 0xe0 0x04 0x00 0x00 0x00
|
||||
# data1^^ ^^data2
|
||||
# ipmi cmd '0x08' : Set System Boot Options
|
||||
# data1 '0xe0' : persistent and uefi
|
||||
# data1 '0xa0' : next boot only and uefi
|
||||
#
|
||||
data1 = '0xe0' if persistent else '0xa0'
|
||||
bootparam5 = '0x00 0x08 0x05 %s %s 0x00 0x00 0x00'
|
||||
cmd08 = bootparam5 % (data1, _BOOTPARAM5_DATA2[device])
|
||||
ipmitool.send_raw(task, cmd08)
|
||||
uefi_mode = (
|
||||
driver_utils.get_node_capability(task.node, 'boot_mode') == 'uefi')
|
||||
|
||||
# disable 60 secs timer
|
||||
timeout_disable = "0x00 0x08 0x03 0x08"
|
||||
ipmitool.send_raw(task, timeout_disable)
|
||||
|
||||
# note(naohirot):
|
||||
# Set System Boot Options : ipmi cmd '0x08', bootparam '0x05'
|
||||
#
|
||||
# $ ipmitool raw 0x00 0x08 0x05 data1 data2 0x00 0x00 0x00
|
||||
#
|
||||
# data1 : '0xe0' persistent + uefi
|
||||
# '0xc0' persistent + bios
|
||||
# '0xa0' next only + uefi
|
||||
# '0x80' next only + bios
|
||||
# data2 : boot device defined in the dict _BOOTPARAM5_DATA2
|
||||
|
||||
bootparam5 = '0x00 0x08 0x05 %s %s 0x00 0x00 0x00'
|
||||
if persistent:
|
||||
data1 = '0xe0' if uefi_mode else '0xc0'
|
||||
else:
|
||||
super(IRMCManagement, self).set_boot_device(
|
||||
task, device, persistent)
|
||||
data1 = '0xa0' if uefi_mode else '0x80'
|
||||
data2 = _BOOTPARAM5_DATA2[device]
|
||||
|
||||
cmd8 = bootparam5 % (data1, data2)
|
||||
ipmitool.send_raw(task, cmd8)
|
||||
|
||||
def get_sensors_data(self, task):
|
||||
"""Get sensors data method.
|
||||
|
@ -86,108 +86,169 @@ class IRMCManagementTestCase(db_base.DbTestCase):
|
||||
self.assertEqual(sorted(expected), sorted(task.driver.management.
|
||||
get_supported_boot_devices(task)))
|
||||
|
||||
@mock.patch.object(ipmitool.IPMIManagement, 'set_boot_device',
|
||||
spec_set=True, autospec=True)
|
||||
def test_management_interface_set_boot_device_no_mode_ok(
|
||||
self,
|
||||
set_boot_device_mock):
|
||||
"""no boot mode specified."""
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.management.set_boot_device(task, boot_devices.PXE)
|
||||
set_boot_device_mock.assert_called_once_with(
|
||||
task.driver.management, task,
|
||||
boot_devices.PXE,
|
||||
False)
|
||||
|
||||
@mock.patch.object(ipmitool.IPMIManagement, 'set_boot_device',
|
||||
spec_set=True, autospec=True)
|
||||
def test_management_interface_set_boot_device_bios_ok(
|
||||
self,
|
||||
set_boot_device_mock):
|
||||
"""bios mode specified."""
|
||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||
driver_utils.add_node_capability(task, 'boot_mode', 'bios')
|
||||
task.driver.management.set_boot_device(task, boot_devices.PXE)
|
||||
set_boot_device_mock.assert_called_once_with(
|
||||
task.driver.management, task,
|
||||
boot_devices.PXE,
|
||||
False)
|
||||
|
||||
@mock.patch.object(irmc_management.ipmitool, "send_raw", spec_set=True,
|
||||
autospec=True)
|
||||
def _test_management_interface_set_boot_device_uefi_ok(self, params,
|
||||
expected_raw_code,
|
||||
send_raw_mock):
|
||||
def _test_management_interface_set_boot_device_ok(
|
||||
self, boot_mode, params, expected_raw_code, send_raw_mock):
|
||||
send_raw_mock.return_value = [None, None]
|
||||
|
||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||
task.node.properties['capabilities'] = ''
|
||||
driver_utils.add_node_capability(task, 'boot_mode', 'uefi')
|
||||
if boot_mode:
|
||||
driver_utils.add_node_capability(task, 'boot_mode', boot_mode)
|
||||
self.driver.management.set_boot_device(task, **params)
|
||||
send_raw_mock.assert_has_calls([
|
||||
mock.call(task, "0x00 0x08 0x03 0x08"),
|
||||
mock.call(task, expected_raw_code)])
|
||||
|
||||
def test_management_interface_set_boot_device_uefi_ok_pxe(self):
|
||||
def test_management_interface_set_boot_device_ok_pxe(self):
|
||||
params = {'device': boot_devices.PXE, 'persistent': False}
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x04 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x04 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xa0 0x04 0x00 0x00 0x00")
|
||||
|
||||
params['persistent'] = True
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x04 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x04 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xe0 0x04 0x00 0x00 0x00")
|
||||
|
||||
def test_management_interface_set_boot_device_uefi_ok_disk(self):
|
||||
def test_management_interface_set_boot_device_ok_disk(self):
|
||||
params = {'device': boot_devices.DISK, 'persistent': False}
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x08 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x08 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xa0 0x08 0x00 0x00 0x00")
|
||||
|
||||
params['persistent'] = True
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x08 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x08 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xe0 0x08 0x00 0x00 0x00")
|
||||
|
||||
def test_management_interface_set_boot_device_uefi_ok_cdrom(self):
|
||||
def test_management_interface_set_boot_device_ok_cdrom(self):
|
||||
params = {'device': boot_devices.CDROM, 'persistent': False}
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0xa0 0x14 0x00 0x00 0x00")
|
||||
"0x00 0x08 0x05 0x80 0x20 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x20 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xa0 0x20 0x00 0x00 0x00")
|
||||
|
||||
params['persistent'] = True
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0xe0 0x14 0x00 0x00 0x00")
|
||||
"0x00 0x08 0x05 0xc0 0x20 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x20 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xe0 0x20 0x00 0x00 0x00")
|
||||
|
||||
def test_management_interface_set_boot_device_uefi_ok_bios(self):
|
||||
def test_management_interface_set_boot_device_ok_bios(self):
|
||||
params = {'device': boot_devices.BIOS, 'persistent': False}
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x18 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x18 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xa0 0x18 0x00 0x00 0x00")
|
||||
|
||||
params['persistent'] = True
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x18 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x18 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xe0 0x18 0x00 0x00 0x00")
|
||||
|
||||
def test_management_interface_set_boot_device_uefi_ok_safe(self):
|
||||
def test_management_interface_set_boot_device_ok_safe(self):
|
||||
params = {'device': boot_devices.SAFE, 'persistent': False}
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x0c 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0x80 0x0c 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xa0 0x0c 0x00 0x00 0x00")
|
||||
|
||||
params['persistent'] = True
|
||||
self._test_management_interface_set_boot_device_uefi_ok(
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
None,
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x0c 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'bios',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xc0 0x0c 0x00 0x00 0x00")
|
||||
self._test_management_interface_set_boot_device_ok(
|
||||
'uefi',
|
||||
params,
|
||||
"0x00 0x08 0x05 0xe0 0x0c 0x00 0x00 0x00")
|
||||
|
||||
@mock.patch.object(irmc_management.ipmitool, "send_raw", spec_set=True,
|
||||
autospec=True)
|
||||
def test_management_interface_set_boot_device_uefi_ng(self,
|
||||
send_raw_mock):
|
||||
def test_management_interface_set_boot_device_ng(self, send_raw_mock):
|
||||
"""uefi mode, next boot only, unknown device."""
|
||||
send_raw_mock.return_value = [None, None]
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
fixes:
|
||||
- This forces iRMC vmedia boot from remotely connected (redirected)
|
||||
CD/DVD instead of default CD/DVD. See
|
||||
https://bugs.launchpad.net/ironic/+bug/1561852 for details.
|
Loading…
Reference in New Issue
Block a user