diff --git a/oem/smc/drive.go b/oem/smc/drive.go new file mode 100644 index 00000000..a69d51fd --- /dev/null +++ b/oem/smc/drive.go @@ -0,0 +1,62 @@ +package smc + +import ( + "encoding/json" + + "github.com/stmcginnis/gofish/redfish" +) + +type Drive struct { + redfish.Drive + Oem DriveOem `json:"Oem"` +} + +type DriveOem struct { + Supermicro struct { + Temperature int + PercentageDriveLifeUsed int + DriveFunctional bool + } `json:"Supermicro"` +} + +type DriveTarget struct { + Target string `json:"target"` + ActionInfo string `json:"@Redfish.ActionInfo"` +} + +type DriveActions struct { + redfish.DriveActions + Oem struct { + DriveIndicate DriveTarget `json:"#Drive.Indicate"` + SmcDriveIndicate DriveTarget `json:"#SmcDrive.Indicate"` + } `json:"Oem"` +} + +func FromDrive(drive *redfish.Drive) (Drive, error) { + var oem DriveOem + err := json.Unmarshal(drive.Oem, &oem) + + return Drive{ + Drive: *drive, + Oem: oem, + }, err +} + +func FromDriveActions(da *redfish.DriveActions) (DriveActions, error) { + oemActions := DriveActions{ + DriveActions: *da, + } + + err := json.Unmarshal(da.Oem, &oemActions.Oem) + return oemActions, err +} + +// DriveIndicateTarget checks both the SmcDriveIndicate and DriveIndicateTarget +// Oem entries and returns the first populated target, due to key inconsistencies +func (da DriveActions) DriveIndicateTarget() string { + if len(da.Oem.SmcDriveIndicate.Target) > 0 { + return da.Oem.SmcDriveIndicate.Target + } + + return da.Oem.DriveIndicate.Target +} diff --git a/oem/smc/drive_test.go b/oem/smc/drive_test.go new file mode 100644 index 00000000..d8045935 --- /dev/null +++ b/oem/smc/drive_test.go @@ -0,0 +1,80 @@ +package smc + +import ( + "encoding/json" + "testing" + + "github.com/stmcginnis/gofish/redfish" +) + +var smcDriveBody = `{ + "@odata.type": "#Drive.v1_6_2.Drive", + "@odata.id": "/redfish/v1/Chassis/NVMeSSD.0.Group.0.StorageBackplane/Drives/Disk.Bay.22", + "Name": "Disk.Bay.22", + "Id": "22", + "Manufacturer": "INTEL", + "SerialNumber": "PHLWOOFMEOWIAMCATDOG", + "Model": "INTEL SSDPE2KX080T8O", + "StatusIndicator": "OK", + "FailurePredicted": false, + "CapacityBytes": 8001563222016, + "CapableSpeedGbs": 31.5, + "Oem": { + "Supermicro": { + "@odata.type": "#SmcDriveExtensions.v1_0_0.Drive", + "Temperature": 33, + "PercentageDriveLifeUsed": 3, + "DriveFunctional": true + } + }, + "IndicatorLED": "Off", + "Status": { + "State": "Enabled", + "Health": "OK" + }, + "Links": { + "Volumes": [] + }, + "Actions": { + "Oem": { + "#Drive.Indicate": { + "target": "/redfish/v1/Chassis/NVMeSSD.0.Group.0.StorageBackplane/Drives/Disk.Bay.22/Actions/Oem/Drive.Indicate", + "@Redfish.ActionInfo": "/redfish/v1/Chassis/NVMeSSD.0.Group.0.StorageBackplane/Drives/Disk.Bay.22/IndicateActionInfo" + } + } + } +}` + +// TestSmcDriveOem tests the parsing of the Drive oem field +func TestSmcDriveOem(t *testing.T) { + drive := &redfish.Drive{} + if err := json.Unmarshal([]byte(smcDriveBody), drive); err != nil { + t.Fatalf("error decoding json: %v", err) + } + + smcDrive, err := FromDrive(drive) + if err != nil { + t.Fatalf("error getting oem info from drive: %v", err) + } + + if smcDrive.Oem.Supermicro.Temperature != 33 { + t.Errorf("unexpected oem drive temerature: %d", smcDrive.Oem.Supermicro.Temperature) + } +} + +// TestSmcDriveActionOem tests the parsing of the Drive Actions field +func TestSmcDriveActionOem(t *testing.T) { + drive := &redfish.Drive{} + if err := json.Unmarshal([]byte(smcDriveBody), drive); err != nil { + t.Fatalf("error decoding json: %v", err) + } + + smcDriveActions, err := FromDriveActions(&drive.Actions) + if err != nil { + t.Fatalf("error getting oem info from drive: %v", err) + } + + if smcDriveActions.DriveIndicateTarget() != "/redfish/v1/Chassis/NVMeSSD.0.Group.0.StorageBackplane/Drives/Disk.Bay.22/Actions/Oem/Drive.Indicate" { + t.Errorf("unexpected oem drive indicator target: %s", smcDriveActions.DriveIndicateTarget()) + } +}