From 05fa43a5dc9ebbf1f5e042bcb1ddeba416474627 Mon Sep 17 00:00:00 2001 From: Sean McGinnis Date: Tue, 15 Oct 2024 10:28:58 -0500 Subject: [PATCH] Add Supermicro OEM Chassis object This adds an OEM-specific Chassis that enables accessing the OEM properties of a chassis. Signed-off-by: Sean McGinnis --- oem/smc/chassis.go | 48 +++++++++++++++++ oem/smc/chassis_test.go | 116 ++++++++++++++++++++++++++++++++++++++++ redfish/chassis.go | 6 +-- 3 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 oem/smc/chassis.go create mode 100644 oem/smc/chassis_test.go diff --git a/oem/smc/chassis.go b/oem/smc/chassis.go new file mode 100644 index 00000000..0553bbf5 --- /dev/null +++ b/oem/smc/chassis.go @@ -0,0 +1,48 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + + "github.com/stmcginnis/gofish/redfish" +) + +// Chassis is a Supermicro OEM instance of a Chassis. +type Chassis struct { + redfish.Chassis + BoardSerialNumber string + GUID string + BoardID string +} + +// FromChassis converts a standard Chassis object to the OEM implementation. +func FromChassis(chassis *redfish.Chassis) (*Chassis, error) { + cs := Chassis{ + Chassis: *chassis, + } + + var t struct { + Oem struct { + Supermicro struct { + BoardSerialNumber string `json:"BoardSerialNumber"` + GUID string `json:"GUID"` + BoardID string `json:"BoardID"` + } `json:"Supermicro"` + } `json:"Oem"` + } + + err := json.Unmarshal(chassis.RawData, &t) + if err != nil { + return nil, err + } + + cs.BoardSerialNumber = t.Oem.Supermicro.BoardSerialNumber + cs.GUID = t.Oem.Supermicro.GUID + cs.BoardID = t.Oem.Supermicro.BoardID + + cs.SetClient(chassis.GetClient()) + return &cs, nil +} diff --git a/oem/smc/chassis_test.go b/oem/smc/chassis_test.go new file mode 100644 index 00000000..5c3d793b --- /dev/null +++ b/oem/smc/chassis_test.go @@ -0,0 +1,116 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" + + "github.com/stmcginnis/gofish/redfish" +) + +var chassisBody = `{ + "@odata.type": "#Chassis.v1_14_0.Chassis", + "@odata.id": "/redfish/v1/Chassis/1", + "Id": "1", + "Name": "Computer System Chassis", + "ChassisType": "RackMount", + "Manufacturer": "Supermicro", + "Model": "X13DEG-OAD", + "SerialNumber": "C8000MN18AC0000", + "PartNumber": "CSE-GP801TS-R000NPF", + "AssetTag": null, + "IndicatorLED": "Off", + "LocationIndicatorActive": false, + "MaxPowerWatts": 18000, + "PowerState": "On", + "Status": { + "State": "Enabled", + "Health": "OK", + "HealthRollup": "OK" + }, + "Power": { + "@odata.id": "/redfish/v1/Chassis/1/Power" + }, + "PCIeDevices": { + "@odata.id": "/redfish/v1/Chassis/1/PCIeDevices" + }, + "Thermal": { + "@odata.id": "/redfish/v1/Chassis/1/Thermal" + }, + "NetworkAdapters": { + "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters" + }, + "PCIeSlots": { + "@odata.id": "/redfish/v1/Chassis/1/PCIeSlots" + }, + "Sensors": { + "@odata.id": "/redfish/v1/Chassis/1/Sensors" + }, + "Memory": { + "@odata.id": "/redfish/v1/Systems/1/Memory" + }, + "Links": { + "ComputerSystems": [ + { + "@odata.id": "/redfish/v1/Systems/1" + } + ], + "ManagedBy": [ + { + "@odata.id": "/redfish/v1/Managers/1" + } + ], + "ManagersInChassis": [ + { + "@odata.id": "/redfish/v1/Managers/1" + } + ] + }, + "Oem": { + "Supermicro": { + "@odata.type": "#SmcChassisExtensions.v1_0_0.Chassis", + "BoardSerialNumber": "HM241S008000", + "GUID": "35353031-4D53-0000-0000-E49200000000", + "BoardID": "0x1d14" + } + }, + "@odata.etag": "\"41b7a1190aa686f7ac4cf7abad27a8a2\"" +}` + +// TestChassis tests the parsing of Chassis objects. +func TestChassis(t *testing.T) { + var cs redfish.Chassis + err := json.NewDecoder(strings.NewReader(chassisBody)).Decode(&cs) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + result, err := FromChassis(&cs) + if err != nil { + t.Errorf("Error converting Redfish Chassis to SMC Chassis: %s", err) + } + + if result.ID != "1" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.Name != "Computer System Chassis" { + t.Errorf("Received invalid name: %s", result.Name) + } + + if result.BoardSerialNumber != "HM241S008000" { + t.Errorf("Unexpected board serial number: %s", result.BoardSerialNumber) + } + + if result.GUID != "35353031-4D53-0000-0000-E49200000000" { + t.Errorf("Unexpected GUID: %s", result.GUID) + } + + if result.BoardID != "0x1d14" { + t.Errorf("Unexpected board ID: %s", result.BoardID) + } +} diff --git a/redfish/chassis.go b/redfish/chassis.go index 58013203..ae3a8336 100644 --- a/redfish/chassis.go +++ b/redfish/chassis.go @@ -359,7 +359,7 @@ type Chassis struct { // millimeters, as specified by the manufacturer. WidthMm float64 // rawData holds the original serialized JSON so we can compare updates. - rawData []byte + RawData []byte // Deprecated properties @@ -561,7 +561,7 @@ func (chassis *Chassis) UnmarshalJSON(b []byte) error { } // This is a read/write object, so we need to save the raw object data for later - chassis.rawData = b + chassis.RawData = b return nil } @@ -571,7 +571,7 @@ func (chassis *Chassis) Update() error { // Get a representation of the object's original state so we can find what // to update. original := new(Chassis) - err := original.UnmarshalJSON(chassis.rawData) + err := original.UnmarshalJSON(chassis.RawData) if err != nil { return err }