From 8bbecb19d5f0a728177512045baaffce9d15b6a3 Mon Sep 17 00:00:00 2001 From: Doctor Vince Date: Mon, 14 Oct 2024 11:02:52 -0400 Subject: [PATCH] expand response payload processing In contrast to other server-vendors, SMC does not return the task id in the Location header of the response to a firmware upload. In BMC version 1.05.03 (Redfish version 1.14.0) the payload format changes from a TaskAccepted message to a Redfish task, which breaks task id detection. This change adds an attempt to deserialize the task structure before falling back to the earlier TaskAccepted message type. This also corrects the startUpdateURI. --- internal/redfishwrapper/firmware.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/internal/redfishwrapper/firmware.go b/internal/redfishwrapper/firmware.go index 81c3f1a5..aed6e3fe 100644 --- a/internal/redfishwrapper/firmware.go +++ b/internal/redfishwrapper/firmware.go @@ -16,6 +16,7 @@ import ( "time" "github.com/pkg/errors" + "github.com/stmcginnis/gofish/redfish" "github.com/bmc-toolbox/bmclib/v2/constants" bmclibErrs "github.com/bmc-toolbox/bmclib/v2/errors" @@ -31,7 +32,7 @@ const ( var ( // the URI for starting a firmware update via StartUpdate is defined in the Redfish Resource and // Schema Guide (2024.1) - startUpdateURI = "redfish/v1/UpdateService/Actions/UpdateService.StartUpdate" + startUpdateURI = "/redfish/v1/UpdateService/Actions/UpdateService.StartUpdate" ) var ( @@ -112,6 +113,16 @@ func (c *Client) FirmwareUpload(ctx context.Context, updateFile *os.File, params return taskIDFromLocationHeader(location) } + rfTask := &redfish.Task{} + if err := rfTask.UnmarshalJSON(response); err != nil { + // we got invalid JSON + return "", fmt.Errorf("unmarshaling redfish response: %w", err) + } + // it's possible to get well-formed JSON that isn't a Task (thanks SMC). Test that we have something sensible. + if strings.Contains(rfTask.ODataType, "Task") { + return rfTask.ID, nil + } + return taskIDFromResponseBody(response) } @@ -146,6 +157,15 @@ func (c *Client) StartUpdateForUploadedFirmware(ctx context.Context) (taskID str return taskIDFromLocationHeader(location) } + rfTask := &redfish.Task{} + if err := rfTask.UnmarshalJSON(response); err != nil { + // we got invalid JSON + return "", fmt.Errorf("unmarshaling redfish response: %w", err) + } + if strings.Contains(rfTask.ODataType, "Task") { + return rfTask.ID, nil + } + return taskIDFromResponseBody(response) }