Added Redfish boot mode management
This change adds node boot mode management to the Redfish driver. Story: 1731013 Task: 9271 Change-Id: I3aa11cc0ce9da9cf6c801300370bd7ce420f434a
This commit is contained in:
parent
ce9bdbffb1
commit
7c5f655794
@ -17,6 +17,7 @@ from oslo_log import log
|
||||
from oslo_utils import importutils
|
||||
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import boot_modes
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.conductor import task_manager
|
||||
@ -37,6 +38,13 @@ if sushy:
|
||||
|
||||
BOOT_DEVICE_MAP_REV = {v: k for k, v in BOOT_DEVICE_MAP.items()}
|
||||
|
||||
BOOT_MODE_MAP = {
|
||||
sushy.BOOT_SOURCE_MODE_UEFI: boot_modes.UEFI,
|
||||
sushy.BOOT_SOURCE_MODE_BIOS: boot_modes.LEGACY_BIOS
|
||||
}
|
||||
|
||||
BOOT_MODE_MAP_REV = {v: k for k, v in BOOT_MODE_MAP.items()}
|
||||
|
||||
BOOT_DEVICE_PERSISTENT_MAP = {
|
||||
sushy.BOOT_SOURCE_ENABLED_CONTINUOUS: True,
|
||||
sushy.BOOT_SOURCE_ENABLED_ONCE: False
|
||||
@ -103,9 +111,7 @@ class RedfishManagement(base.ManagementInterface):
|
||||
:raises: RedfishError on an error from the Sushy library
|
||||
"""
|
||||
system = redfish_utils.get_system(task.node)
|
||||
# TODO(lucasagomes): set_system_boot_source() also supports mode
|
||||
# for UEFI and BIOS we should get it from instance_info and pass
|
||||
# it along this call
|
||||
|
||||
try:
|
||||
system.set_system_boot_source(
|
||||
BOOT_DEVICE_MAP_REV[device],
|
||||
@ -141,6 +147,81 @@ class RedfishManagement(base.ManagementInterface):
|
||||
'persistent': BOOT_DEVICE_PERSISTENT_MAP.get(
|
||||
system.boot.get('enabled'))}
|
||||
|
||||
def get_supported_boot_modes(self, task):
|
||||
"""Get a list of the supported boot modes.
|
||||
|
||||
:param task: A task from TaskManager.
|
||||
:returns: A list with the supported boot modes defined
|
||||
in :mod:`ironic.common.boot_modes`. If boot
|
||||
mode support can't be determined, empty list
|
||||
is returned.
|
||||
"""
|
||||
return list(BOOT_MODE_MAP_REV)
|
||||
|
||||
@task_manager.require_exclusive_lock
|
||||
def set_boot_mode(self, task, mode):
|
||||
"""Set the boot mode for a node.
|
||||
|
||||
Set the boot mode to use on next reboot of the node.
|
||||
|
||||
:param task: A task from TaskManager.
|
||||
:param mode: The boot mode, one of
|
||||
:mod:`ironic.common.boot_modes`.
|
||||
:raises: InvalidParameterValue if an invalid boot mode is
|
||||
specified.
|
||||
:raises: MissingParameterValue if a required parameter is missing
|
||||
:raises: RedfishConnectionError when it fails to connect to Redfish
|
||||
:raises: RedfishError on an error from the Sushy library
|
||||
"""
|
||||
system = redfish_utils.get_system(task.node)
|
||||
|
||||
boot_device = system.boot.get('target')
|
||||
if not boot_device:
|
||||
error_msg = (_('Cannot change boot mode on node %(node)s '
|
||||
'because its boot device is not set.') %
|
||||
{'node': task.node.uuid})
|
||||
LOG.error(error_msg)
|
||||
raise exception.RedfishError(error_msg)
|
||||
|
||||
boot_override = system.boot.get('enabled')
|
||||
if not boot_override:
|
||||
error_msg = (_('Cannot change boot mode on node %(node)s '
|
||||
'because its boot source override is not set.') %
|
||||
{'node': task.node.uuid})
|
||||
LOG.error(error_msg)
|
||||
raise exception.RedfishError(error_msg)
|
||||
|
||||
try:
|
||||
system.set_system_boot_source(
|
||||
boot_device,
|
||||
enabled=boot_override,
|
||||
mode=BOOT_MODE_MAP_REV[mode])
|
||||
|
||||
except sushy.exceptions.SushyError as e:
|
||||
error_msg = (_('Setting boot mode to %(mode)s '
|
||||
'failed for node %(node)s. '
|
||||
'Error: %(error)s') %
|
||||
{'node': task.node.uuid, 'mode': mode,
|
||||
'error': e})
|
||||
LOG.error(error_msg)
|
||||
raise exception.RedfishError(error=error_msg)
|
||||
|
||||
def get_boot_mode(self, task):
|
||||
"""Get the current boot mode for a node.
|
||||
|
||||
Provides the current boot mode of the node.
|
||||
|
||||
:param task: A task from TaskManager.
|
||||
:raises: MissingParameterValue if a required parameter is missing
|
||||
:raises: DriverOperationError or its derivative in case
|
||||
of driver runtime error.
|
||||
:returns: The boot mode, one of :mod:`ironic.common.boot_mode` or
|
||||
None if it is unknown.
|
||||
"""
|
||||
system = redfish_utils.get_system(task.node)
|
||||
|
||||
return BOOT_MODE_MAP.get(system.boot.get('mode'))
|
||||
|
||||
def get_sensors_data(self, task):
|
||||
"""Get sensors data.
|
||||
|
||||
|
@ -17,6 +17,7 @@ import mock
|
||||
from oslo_utils import importutils
|
||||
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import boot_modes
|
||||
from ironic.common import exception
|
||||
from ironic.conductor import task_manager
|
||||
from ironic.drivers.modules.redfish import management as redfish_mgmt
|
||||
@ -153,6 +154,68 @@ class RedfishManagementTestCase(db_base.DbTestCase):
|
||||
'persistent': True}
|
||||
self.assertEqual(expected, response)
|
||||
|
||||
def test_get_supported_boot_modes(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
supported_boot_modes = (
|
||||
task.driver.management.get_supported_boot_modes(task))
|
||||
self.assertEqual(list(redfish_mgmt.BOOT_MODE_MAP_REV),
|
||||
supported_boot_modes)
|
||||
|
||||
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||
def test_set_boot_mode(self, mock_get_system):
|
||||
fake_system = mock.Mock()
|
||||
mock_get_system.return_value = fake_system
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
expected_values = [
|
||||
(boot_modes.LEGACY_BIOS, sushy.BOOT_SOURCE_MODE_BIOS),
|
||||
(boot_modes.UEFI, sushy.BOOT_SOURCE_MODE_UEFI)
|
||||
]
|
||||
|
||||
for mode, expected in expected_values:
|
||||
task.driver.management.set_boot_mode(task, mode=mode)
|
||||
|
||||
# Asserts
|
||||
fake_system.set_system_boot_source.assert_called_once_with(
|
||||
mock.ANY, enabled=mock.ANY, mode=mode)
|
||||
mock_get_system.assert_called_once_with(task.node)
|
||||
|
||||
# Reset mocks
|
||||
fake_system.set_system_boot_source.reset_mock()
|
||||
mock_get_system.reset_mock()
|
||||
|
||||
@mock.patch('ironic.drivers.modules.redfish.management.sushy')
|
||||
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||
def test_set_boot_mode_fail(self, mock_get_system, mock_sushy):
|
||||
fake_system = mock.Mock()
|
||||
mock_sushy.exceptions.SushyError = MockedSushyError
|
||||
fake_system.set_system_boot_source.side_effect = MockedSushyError
|
||||
mock_get_system.return_value = fake_system
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
self.assertRaisesRegex(
|
||||
exception.RedfishError, 'Setting boot mode',
|
||||
task.driver.management.set_boot_mode, task, boot_modes.UEFI)
|
||||
fake_system.set_system_boot_source.assert_called_once_with(
|
||||
mock.ANY, enabled=mock.ANY, mode=boot_modes.UEFI)
|
||||
mock_get_system.assert_called_once_with(task.node)
|
||||
|
||||
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||
def test_get_boot_mode(self, mock_get_system):
|
||||
boot_attribute = {
|
||||
'target': sushy.BOOT_SOURCE_TARGET_PXE,
|
||||
'enabled': sushy.BOOT_SOURCE_ENABLED_CONTINUOUS,
|
||||
'mode': sushy.BOOT_SOURCE_MODE_BIOS,
|
||||
}
|
||||
fake_system = mock.Mock(boot=boot_attribute)
|
||||
mock_get_system.return_value = fake_system
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
response = task.driver.management.get_boot_mode(task)
|
||||
expected = boot_modes.LEGACY_BIOS
|
||||
self.assertEqual(expected, response)
|
||||
|
||||
def test_get_sensors_data(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
|
@ -163,6 +163,8 @@ SUSHY_CONSTANTS_SPEC = (
|
||||
'RESET_NMI',
|
||||
'BOOT_SOURCE_ENABLED_CONTINUOUS',
|
||||
'BOOT_SOURCE_ENABLED_ONCE',
|
||||
'BOOT_SOURCE_MODE_BIOS',
|
||||
'BOOT_SOURCE_MODE_UEFI',
|
||||
)
|
||||
|
||||
XCLARITY_SPEC = (
|
||||
|
@ -241,7 +241,9 @@ if not sushy:
|
||||
RESET_FORCE_RESTART='force restart',
|
||||
RESET_NMI='nmi',
|
||||
BOOT_SOURCE_ENABLED_CONTINUOUS='continuous',
|
||||
BOOT_SOURCE_ENABLED_ONCE='once'
|
||||
BOOT_SOURCE_ENABLED_ONCE='once',
|
||||
BOOT_SOURCE_MODE_BIOS='bios',
|
||||
BOOT_SOURCE_MODE_UEFI='uefi'
|
||||
)
|
||||
|
||||
sys.modules['sushy'] = sushy
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- Adds support for reading and setting bare metal node's boot mode
|
||||
using the ``redfish`` management interface.
|
Loading…
x
Reference in New Issue
Block a user