diff --git a/ironic/drivers/modules/redfish/management.py b/ironic/drivers/modules/redfish/management.py index 59520de001..32f6b80946 100644 --- a/ironic/drivers/modules/redfish/management.py +++ b/ironic/drivers/modules/redfish/management.py @@ -114,11 +114,17 @@ class RedfishManagement(base.ManagementInterface): """ system = redfish_utils.get_system(task.node) + desired_persistence = BOOT_DEVICE_PERSISTENT_MAP_REV[persistent] + current_persistence = system.boot.get('enabled') + + # NOTE(etingof): this can be racy, esp if BMC is not RESTful + enabled = (desired_persistence + if desired_persistence != current_persistence else None) + try: try: system.set_system_boot_options( - BOOT_DEVICE_MAP_REV[device], - enabled=BOOT_DEVICE_PERSISTENT_MAP_REV[persistent]) + BOOT_DEVICE_MAP_REV[device], enabled=enabled) except AttributeError: system.set_system_boot_source( BOOT_DEVICE_MAP_REV[device], diff --git a/ironic/tests/unit/drivers/modules/redfish/test_management.py b/ironic/tests/unit/drivers/modules/redfish/test_management.py index 19241fcbcd..bf9887f5cc 100644 --- a/ironic/tests/unit/drivers/modules/redfish/test_management.py +++ b/ironic/tests/unit/drivers/modules/redfish/test_management.py @@ -146,6 +146,31 @@ class RedfishManagementTestCase(db_base.DbTestCase): fake_system.set_system_boot_options.reset_mock() mock_get_system.reset_mock() + @mock.patch.object(redfish_utils, 'get_system', autospec=True) + def test_set_boot_device_persistency_no_change(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 = [ + (True, sushy.BOOT_SOURCE_ENABLED_CONTINUOUS), + (False, sushy.BOOT_SOURCE_ENABLED_ONCE) + ] + + for target, expected in expected_values: + fake_system.boot.get.return_value = expected + + task.driver.management.set_boot_device( + task, boot_devices.PXE, persistent=target) + + fake_system.set_system_boot_options.assert_called_once_with( + sushy.BOOT_SOURCE_TARGET_PXE, enabled=None) + mock_get_system.assert_called_once_with(task.node) + + # Reset mocks + fake_system.set_system_boot_options.reset_mock() + mock_get_system.reset_mock() + @mock.patch.object(sushy, 'Sushy', autospec=True) @mock.patch.object(redfish_utils, 'get_system', autospec=True) def test_set_boot_device_fail(self, mock_get_system, mock_sushy): diff --git a/releasenotes/notes/improve-redfish-set-boot-device-e38e9e9442ab5750.yaml b/releasenotes/notes/improve-redfish-set-boot-device-e38e9e9442ab5750.yaml new file mode 100644 index 0000000000..a2ff17280d --- /dev/null +++ b/releasenotes/notes/improve-redfish-set-boot-device-e38e9e9442ab5750.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Makes management interface of ``redfish`` hardware type not changing + current boot frequency if currently set is the same as the desired one. + The goal is to avoid touching potentially faulty BMC option whenever + possible.