From 7a18af80cedee392dd71d5b9a0266cd8669e2463 Mon Sep 17 00:00:00 2001 From: Pierre-yves Fontaniere Date: Thu, 22 Jan 2026 21:38:18 +0100 Subject: [PATCH] Handle @Redfish.Settings when setting ComputerSystem boot attributes (#11322) * set_boot_override function now uses Redfish Settings URI if available in ComputerSystem resource * Follows code formatting rules * Add changelogs fragments file * Update changelogs/fragments/11322-handle-redfish-settings-in-setbootoverride.yml Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Explicit rewriting as a workaround to keep the "good" path clean. * Adjust changelog fragment. --------- Co-authored-by: Pierre-yves FONTANIERE Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> Co-authored-by: Felix Fontein --- ...le-redfish-settings-in-setbootoverride.yml | 3 + plugins/module_utils/redfish_utils.py | 102 +++++++++++++++++- 2 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/11322-handle-redfish-settings-in-setbootoverride.yml diff --git a/changelogs/fragments/11322-handle-redfish-settings-in-setbootoverride.yml b/changelogs/fragments/11322-handle-redfish-settings-in-setbootoverride.yml new file mode 100644 index 0000000000..887771808b --- /dev/null +++ b/changelogs/fragments/11322-handle-redfish-settings-in-setbootoverride.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - redfish_utils module utils - adds support of ``@Redfish.Settings`` in ``ComputerSystem`` attributes for ``set_boot_override`` function (https://github.com/ansible-collections/community.general/issues/11297, https://github.com/ansible-collections/community.general/pull/11322). diff --git a/plugins/module_utils/redfish_utils.py b/plugins/module_utils/redfish_utils.py index b10f67b867..3e93a6a819 100644 --- a/plugins/module_utils/redfish_utils.py +++ b/plugins/module_utils/redfish_utils.py @@ -2253,6 +2253,94 @@ class RedfishUtils: return response return {"ret": True, "changed": True, "msg": "BIOS set to default settings"} + def set_boot_override_with_settings_uri(self, boot_opts): + # Extract the requested boot override options + bootdevice = boot_opts.get("bootdevice") + uefi_target = boot_opts.get("uefi_target") + boot_next = boot_opts.get("boot_next") + override_enabled = boot_opts.get("override_enabled") + boot_override_mode = boot_opts.get("boot_override_mode") + if not bootdevice and override_enabled != "Disabled": + return {"ret": False, "msg": "bootdevice option required for temporary boot override"} + + # Get the current boot override options from the Boot property + response = self.get_request(self.root_uri + self.systems_uri) + if response["ret"] is False: + return response + data = response["data"] + current_boot = data.get("Boot") + if current_boot is None: + return {"ret": False, "msg": "Boot property not found"} + cur_override_mode = current_boot.get("BootSourceOverrideMode") + rfsettings = data.get("@Redfish.Settings") + + settings_uri = rfsettings["SettingsObject"]["@odata.id"] + response = self.get_request(self.root_uri + settings_uri) + if response["ret"] is False: + return response + data = response["data"] + future_boot = data.get("Boot") + + # Check if the requested target is supported by the system + if override_enabled != "Disabled": + annotation = "BootSourceOverrideTarget@Redfish.AllowableValues" + if annotation in future_boot: + allowable_values = future_boot[annotation] + if isinstance(allowable_values, list) and bootdevice not in allowable_values: + return { + "ret": False, + "msg": f"Boot device {bootdevice} not in list of allowable values ({allowable_values})", + } + + # Build the request payload based on the desired boot override options + if override_enabled == "Disabled": + payload = {"Boot": {"BootSourceOverrideEnabled": override_enabled, "BootSourceOverrideTarget": "None"}} + elif bootdevice == "UefiTarget": + if not uefi_target: + return {"ret": False, "msg": "uefi_target option required to SetOneTimeBoot for UefiTarget"} + payload = { + "Boot": { + "BootSourceOverrideEnabled": override_enabled, + "BootSourceOverrideTarget": bootdevice, + "UefiTargetBootSourceOverride": uefi_target, + } + } + # If needed, also specify UEFI mode + if cur_override_mode == "Legacy": + payload["Boot"]["BootSourceOverrideMode"] = "UEFI" + elif bootdevice == "UefiBootNext": + if not boot_next: + return {"ret": False, "msg": "boot_next option required to SetOneTimeBoot for UefiBootNext"} + payload = { + "Boot": { + "BootSourceOverrideEnabled": override_enabled, + "BootSourceOverrideTarget": bootdevice, + "BootNext": boot_next, + } + } + # If needed, also specify UEFI mode + if cur_override_mode == "Legacy": + payload["Boot"]["BootSourceOverrideMode"] = "UEFI" + else: + payload = {"Boot": {"BootSourceOverrideEnabled": override_enabled, "BootSourceOverrideTarget": bootdevice}} + if boot_override_mode: + payload["Boot"]["BootSourceOverrideMode"] = boot_override_mode + + # Apply the requested boot override request + resp = self.patch_request(self.root_uri + settings_uri, payload, check_pyld=True) + if resp["ret"] is False: + # WORKAROUND + # Older Dell systems do not allow BootSourceOverrideEnabled to be + # specified with UefiTarget as the target device + vendor = self._get_vendor()["Vendor"] + if vendor == "Dell": + if bootdevice == "UefiTarget" and override_enabled != "Disabled": + payload["Boot"].pop("BootSourceOverrideEnabled", None) + resp = self.patch_request(self.root_uri + settings_uri, payload, check_pyld=True) + if resp["ret"] and resp["changed"]: + resp["msg"] = "Updated the boot override settings" + return resp + def set_boot_override(self, boot_opts): # Extract the requested boot override options bootdevice = boot_opts.get("bootdevice") @@ -2268,6 +2356,7 @@ class RedfishUtils: if response["ret"] is False: return response data = response["data"] + rfsettings = data.get("@Redfish.Settings") boot = data.get("Boot") if boot is None: return {"ret": False, "msg": "Boot property not found"} @@ -2321,14 +2410,21 @@ class RedfishUtils: # Apply the requested boot override request resp = self.patch_request(self.root_uri + self.systems_uri, payload, check_pyld=True) if resp["ret"] is False: - # WORKAROUND - # Older Dell systems do not allow BootSourceOverrideEnabled to be - # specified with UefiTarget as the target device vendor = self._get_vendor()["Vendor"] if vendor == "Dell": + # WORKAROUND + # Newer Dell systems (iDRAC10) do not allow to PATCH ComputerSystem resource + # directly. Need to PATCH Settings URI + if rfsettings: + return self.set_boot_override_with_settings_uri(boot_opts) + + # WORKAROUND + # Older Dell systems do not allow BootSourceOverrideEnabled to be + # specified with UefiTarget as the target device if bootdevice == "UefiTarget" and override_enabled != "Disabled": payload["Boot"].pop("BootSourceOverrideEnabled", None) resp = self.patch_request(self.root_uri + self.systems_uri, payload, check_pyld=True) + if resp["ret"] and resp["changed"]: resp["msg"] = "Updated the boot override settings" return resp