From 65d50663941ffe66be587e09d0c63528f970dabd Mon Sep 17 00:00:00 2001 From: Richard Pioso Date: Thu, 17 Sep 2020 18:27:14 -0400 Subject: [PATCH] Fix redfish BIOS to use @Redfish.SettingsApplyTime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change fixes the '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). Such services, typically offered by baseboard management controllers (BMC), require POST of the annotation, along with the future intended state of the settings. Otherwise, they may never be applied. When the annotation is not supported, it is not provided with the future intended state of the settings. [1] http://redfish.dmtf.org/schemas/DSP0266_1.11.0.html#settings-resource Co-Authored-By: Eric Barrera Co-Authored-By: Aija Jauntēva Co-Authored-By: Mike Raineri Story: 2008163 Task: 40913 Depends-On: https://review.opendev.org/#/c/750020/ Change-Id: I28a948f306b40c36b12e6f786e1e43a61e84a0f2 --- driver-requirements.txt | 2 +- ironic/drivers/modules/redfish/bios.py | 9 +++- .../unit/drivers/modules/redfish/test_bios.py | 53 ++++++++++++++++++- .../drivers/third_party_driver_mock_specs.py | 1 + .../unit/drivers/third_party_driver_mocks.py | 1 + ...-settings-apply-time-9b50979d2afc0d27.yaml | 14 +++++ 6 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/redfish-fix-bios-settings-apply-time-9b50979d2afc0d27.yaml 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