diff --git a/driver-requirements.txt b/driver-requirements.txt index 495dcbfe32..aed46ea3e7 100644 --- a/driver-requirements.txt +++ b/driver-requirements.txt @@ -11,7 +11,7 @@ python-dracclient>=3.1.0,<5.0.0 python-xclarityclient>=0.1.6 # The Redfish hardware type uses the Sushy library -sushy>=3.2.0 +sushy>=3.4.0 # Ansible-deploy interface ansible>=2.7 diff --git a/ironic/drivers/modules/redfish/bios.py b/ironic/drivers/modules/redfish/bios.py index 825f876f1b..018a8d9555 100644 --- a/ironic/drivers/modules/redfish/bios.py +++ b/ironic/drivers/modules/redfish/bios.py @@ -175,8 +175,15 @@ class RedfishBIOS(base.BIOSInterface): LOG.debug('Apply BIOS configuration for node %(node_uuid)s: ' '%(settings)r', {'node_uuid': task.node.uuid, 'settings': settings}) + + if bios.supported_apply_times and ( + sushy.APPLY_TIME_ON_RESET in bios.supported_apply_times): + apply_time = sushy.APPLY_TIME_ON_RESET + else: + apply_time = None + try: - bios.set_attributes(attributes) + bios.set_attributes(attributes, apply_time=apply_time) except sushy.exceptions.SushyError as e: error_msg = (_('Redfish BIOS apply configuration failed for ' 'node %(node)s. Error: %(error)s') % diff --git a/ironic/tests/unit/drivers/modules/redfish/test_bios.py b/ironic/tests/unit/drivers/modules/redfish/test_bios.py index 96269f640e..d9c2a14530 100644 --- a/ironic/tests/unit/drivers/modules/redfish/test_bios.py +++ b/ironic/tests/unit/drivers/modules/redfish/test_bios.py @@ -186,17 +186,20 @@ class RedfishBiosTestCase(db_base.DbTestCase): mock_build_agent_options.return_value = {'a': 'b'} with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: + bios = mock_get_system(task.node).bios if step == 'factory_reset': ret = task.driver.bios.factory_reset(task) if step == 'apply_configuration': + bios.apply_time_settings = None + bios.supported_apply_times = [] ret = task.driver.bios.apply_configuration(task, data) mock_get_system.assert_called_with(task.node) mock_power_action.assert_called_once_with(task, states.REBOOT) - bios = mock_get_system(task.node).bios if step == 'factory_reset': bios.reset_bios.assert_called_once() if step == 'apply_configuration': - bios.set_attributes.assert_called_once_with(attributes) + bios.set_attributes.assert_called_once_with( + attributes, apply_time=None) mock_build_agent_options.assert_called_once_with(task.node) mock_prepare.assert_called_once_with(mock.ANY, task, {'a': 'b'}) info = task.node.driver_internal_info @@ -378,3 +381,49 @@ class RedfishBiosTestCase(db_base.DbTestCase): task.driver.bios.apply_configuration(task, settings) task.driver.bios.post_configuration\ .assert_called_once_with(task, settings) + + @mock.patch.object(redfish_boot.RedfishVirtualMediaBoot, 'prepare_ramdisk', + spec_set=True, autospec=True) + @mock.patch.object(deploy_utils, 'build_agent_options', autospec=True) + @mock.patch.object(redfish_utils, 'get_system', autospec=True) + @mock.patch.object(manager_utils, 'node_power_action', autospec=True) + def test_apply_configuration_apply_time_settings(self, mock_power_action, + mock_get_system, + mock_build_agent_options, + mock_prepare): + settings = [{'name': 'ProcTurboMode', 'value': 'Disabled'}, + {'name': 'NicBoot1', 'value': 'NetworkBoot'}] + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + bios = mock_get_system(task.node).bios + bios.apply_time_settings = mock.Mock() + bios.supported_apply_times = ['immediate'] + + task.driver.bios.apply_configuration(task, settings) + + bios.set_attributes.assert_called_once_with( + {s['name']: s['value'] for s in settings}, + apply_time=None) + + @mock.patch.object(redfish_boot.RedfishVirtualMediaBoot, 'prepare_ramdisk', + spec_set=True, autospec=True) + @mock.patch.object(deploy_utils, 'build_agent_options', autospec=True) + @mock.patch.object(redfish_utils, 'get_system', autospec=True) + @mock.patch.object(manager_utils, 'node_power_action', autospec=True) + def test_apply_configuration_apply_time_on_reset(self, mock_power_action, + mock_get_system, + mock_build_agent_options, + mock_prepare): + settings = [{'name': 'ProcTurboMode', 'value': 'Disabled'}, + {'name': 'NicBoot1', 'value': 'NetworkBoot'}] + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + bios = mock_get_system(task.node).bios + bios.apply_time_settings = None + bios.supported_apply_times = [sushy.APPLY_TIME_ON_RESET] + + task.driver.bios.apply_configuration(task, settings) + + bios.set_attributes.assert_called_once_with( + {s['name']: s['value'] for s in settings}, + apply_time=sushy.APPLY_TIME_ON_RESET) diff --git a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py index 2a0378f48d..852fefecd4 100644 --- a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py +++ b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py @@ -155,6 +155,7 @@ SUSHY_SPEC = ( 'STATE_ABSENT', 'VIRTUAL_MEDIA_CD', 'VIRTUAL_MEDIA_FLOPPY', + 'APPLY_TIME_ON_RESET', ) SUSHY_AUTH_SPEC = ( diff --git a/ironic/tests/unit/drivers/third_party_driver_mocks.py b/ironic/tests/unit/drivers/third_party_driver_mocks.py index 547b41c4a0..33ab080226 100644 --- a/ironic/tests/unit/drivers/third_party_driver_mocks.py +++ b/ironic/tests/unit/drivers/third_party_driver_mocks.py @@ -217,6 +217,7 @@ if not sushy: STATE_ABSENT='absent', VIRTUAL_MEDIA_CD='cd', VIRTUAL_MEDIA_FLOPPY='floppy', + APPLY_TIME_ON_RESET='on reset', ) sys.modules['sushy'] = sushy diff --git a/releasenotes/notes/redfish-fix-bios-settings-apply-time-9b50979d2afc0d27.yaml b/releasenotes/notes/redfish-fix-bios-settings-apply-time-9b50979d2afc0d27.yaml new file mode 100644 index 0000000000..1808341667 --- /dev/null +++ b/releasenotes/notes/redfish-fix-bios-settings-apply-time-9b50979d2afc0d27.yaml @@ -0,0 +1,14 @@ +--- +fixes: + - | + Fixes ``redfish`` BIOS interface ``apply_configuration`` cleaning/deploy + step to work with Redfish Services that must be supplied the Distributed + Management Task Force (DMTF) Redfish standard + ``@Redfish.SettingsApplyTime`` annotation [1] to specify when to apply the + requested settings, such as the Dell EMC integrated Dell Remote Acesss + Controller (iDRAC). + + For more information, see `story 2008163 + `_. + + [1] http://redfish.dmtf.org/schemas/DSP0266_1.11.0.html#settings-resource