summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNaohiro Tamura <naohirot@jp.fujitsu.com>2016-03-19 19:06:01 +0900
committerNaohiro Tamura <naohirot@jp.fujitsu.com>2016-04-13 14:25:49 +0900
commitd18e2f36dd54616db8d853b340d564a5ca96749d (patch)
treefae12fa1cfdb4e94a1cb1c0e805a7cf347adf670
parent4c7b1f9a426f5017b7bc4f9c2fdd6ac3800e3551 (diff)
downloadironic-d18e2f36dd54616db8d853b340d564a5ca96749d.tar.gz
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 (cherry picked from commit 03fe93abfe5779f27c0eee5495f189e0104a5184)
-rw-r--r--ironic/drivers/modules/irmc/management.py63
-rw-r--r--ironic/tests/unit/drivers/modules/irmc/test_management.py163
-rw-r--r--releasenotes/notes/update-irmc-set-boot-device-fd50d9dce42aaa89.yaml5
3 files changed, 153 insertions, 78 deletions
diff --git a/ironic/drivers/modules/irmc/management.py b/ironic/drivers/modules/irmc/management.py
index 077ebf7e5..c46cfd10c 100644
--- a/ironic/drivers/modules/irmc/management.py
+++ b/ironic/drivers/modules/irmc/management.py
@@ -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)
-
- # 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)
-
+ if device not in self.get_supported_boot_devices(task):
+ raise exception.InvalidParameterValue(_(
+ "Invalid boot device %s specified.") % device)
+
+ 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.
diff --git a/ironic/tests/unit/drivers/modules/irmc/test_management.py b/ironic/tests/unit/drivers/modules/irmc/test_management.py
index 687ea1f54..fb75b394f 100644
--- a/ironic/tests/unit/drivers/modules/irmc/test_management.py
+++ b/ironic/tests/unit/drivers/modules/irmc/test_management.py
@@ -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 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 0x14 0x00 0x00 0x00")
+ "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]
diff --git a/releasenotes/notes/update-irmc-set-boot-device-fd50d9dce42aaa89.yaml b/releasenotes/notes/update-irmc-set-boot-device-fd50d9dce42aaa89.yaml
new file mode 100644
index 000000000..c758b7223
--- /dev/null
+++ b/releasenotes/notes/update-irmc-set-boot-device-fd50d9dce42aaa89.yaml
@@ -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.