Skip to content

Commit a6d4354

Browse files
committed
Add Supermicro DumpService object
This adds a DumpService OEM object for Supermicro systems. Signed-off-by: Sean McGinnis <[email protected]>
1 parent 4c227db commit a6d4354

File tree

4 files changed

+232
-4
lines changed

4 files changed

+232
-4
lines changed

oem/smc/dumpservice.go

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
//
4+
5+
package smc
6+
7+
import (
8+
"encoding/json"
9+
"errors"
10+
11+
"github.com/stmcginnis/gofish/common"
12+
)
13+
14+
// Dump represents a dump from the DumpService.
15+
// NOTE: This is another one where the jsonschema reported by SMC appears to be
16+
// wildly inaccurate. Use with caution.
17+
type Dump struct {
18+
common.Entity
19+
20+
AttestationFile []string
21+
}
22+
23+
// GetDump will get a Dump instance from the service.
24+
func GetDump(c common.Client, uri string) (*Dump, error) {
25+
return common.GetObject[Dump](c, uri)
26+
}
27+
28+
// ListReferencedDumps gets the collection of Dumps from
29+
// a provided reference.
30+
func ListReferencedDumps(c common.Client, uri string) ([]*Dump, error) {
31+
return common.GetCollectionObjects[Dump](c, uri)
32+
}
33+
34+
// DumpService is the dump service instance associated with the system.
35+
type DumpService struct {
36+
common.Entity
37+
38+
// Link to a DumpCollection.
39+
dumps string
40+
41+
createDumpTarget string
42+
deleteAllTarget string
43+
collectTarget string
44+
}
45+
46+
// UnmarshalJSON unmarshals an DumpService object from the raw JSON.
47+
func (ds *DumpService) UnmarshalJSON(b []byte) error {
48+
type temp DumpService
49+
var t struct {
50+
temp
51+
Dumps common.Link
52+
Actions struct {
53+
CreateDump common.ActionTarget `json:"#SmcDumpService.CreateDump"`
54+
DeleteAll common.ActionTarget `json:"#SmcDumpService.DeleteAll"`
55+
Collect common.ActionTarget `json:"#OemDumpService.Collect"`
56+
}
57+
}
58+
59+
err := json.Unmarshal(b, &t)
60+
if err != nil {
61+
return err
62+
}
63+
64+
*ds = DumpService(t.temp)
65+
66+
ds.dumps = t.Dumps.String()
67+
68+
ds.createDumpTarget = t.Actions.CreateDump.Target
69+
ds.deleteAllTarget = t.Actions.DeleteAll.Target
70+
ds.collectTarget = t.Actions.Collect.Target
71+
72+
return nil
73+
}
74+
75+
// GetDefaultDumpService will get the default DumpService instance from the service.
76+
func GetDefaultDumpService(c common.Client) (*DumpService, error) {
77+
return common.GetObject[DumpService](c, "/redfish/v1/Oem/Supermicro/DumpService/")
78+
}
79+
80+
// GetDumpService will get a DumpService instance from the service.
81+
func GetDumpService(c common.Client, uri string) (*DumpService, error) {
82+
return common.GetObject[DumpService](c, uri)
83+
}
84+
85+
// CreateDump creates a new dump. Allowable dumpType is usually only
86+
// "Host Dump".
87+
func (ds *DumpService) CreateDump(dumpType string) error {
88+
if ds.createDumpTarget == "" {
89+
return errors.New("create dump is not supported by this system")
90+
}
91+
92+
return ds.Post(ds.createDumpTarget, map[string]any{
93+
"DumpType": dumpType,
94+
})
95+
}
96+
97+
// DeleteAll deletes all dumps.
98+
func (ds *DumpService) DeleteAll() error {
99+
if ds.deleteAllTarget == "" {
100+
return errors.New("delete all is not supported by this system")
101+
}
102+
103+
return ds.Post(ds.deleteAllTarget, nil)
104+
}
105+
106+
// Collect collects a dump.
107+
// dumptType is usually only "HGXLogDump".
108+
// actionType is usually one of "Create", "Delete", "Download", or "Query".
109+
func (ds *DumpService) Collect(dumpType, actionType string) error {
110+
if ds.collectTarget == "" {
111+
return errors.New("collect is not supported by this system")
112+
}
113+
114+
return ds.Post(ds.collectTarget, map[string]any{
115+
"DumpType": dumpType,
116+
"ActionType": actionType,
117+
})
118+
}
119+
120+
// Dumps will get the Dumps from the service.
121+
func (ds *DumpService) Dumps() ([]*Dump, error) {
122+
return ListReferencedDumps(ds.GetClient(), ds.dumps)
123+
}

oem/smc/dumpservice_test.go

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
//
4+
5+
package smc
6+
7+
import (
8+
"encoding/json"
9+
"testing"
10+
)
11+
12+
var dumpServiceBody = `{
13+
"@odata.type": "#DumpService.v1_0_2.DumpService",
14+
"@odata.id": "/redfish/v1/Oem/Supermicro/DumpService",
15+
"Id": "DumpService",
16+
"Name": "Dump Service",
17+
"Description": "Dump Service",
18+
"Dumps": {
19+
"@odata.id": "/redfish/v1/Oem/Supermicro/DumpService/Dumps"
20+
},
21+
"Actions": {
22+
"Oem": {},
23+
"#SmcDumpService.CreateDump": {
24+
"target": "/redfish/v1/Oem/Supermicro/DumpService/Actions/SmcDumpService.CreateDump",
25+
"@Redfish.ActionInfo": "/redfish/v1/Oem/Supermicro/DumpService/CreateDumpActionInfo"
26+
},
27+
"#SmcDumpService.DeleteAll": {
28+
"target": "/redfish/v1/Oem/Supermicro/DumpService/Actions/SmcDumpService.DeleteAll"
29+
},
30+
"#OemDumpService.Collect": {
31+
"target": "/redfish/v1/Oem/Supermicro/DumpService/Actions/OemDumpService.Collect",
32+
"@Redfish.ActionInfo": "/redfish/v1/Oem/Supermicro/DumpService/CollectActionInfo"
33+
}
34+
},
35+
"@odata.etag": "\"697e2b05b6d5d49940bc0fd68803608b\""
36+
}`
37+
38+
var dumpBody = `{
39+
"@odata.type": "#Dump.v1_1_0.Dump",
40+
"@odata.id": "/redfish/v1/Oem/Supermicro/DumpService/Dumps/AttestationDump",
41+
"Id": "AttestationDump",
42+
"Name": "AttestationDump",
43+
"Description": "Supermicro Attestation Dump Service",
44+
"AttestationFile": [
45+
"attd_BS=OM243S046922_2024-09-18T18:10:52-07:00.bin",
46+
"attd_BS=OM243S046922_MB_2024-05-23T13:54:08+08:00.bin"
47+
],
48+
"Actions": {
49+
"Oem": {},
50+
"#SmcAttestationDump.Generate": {
51+
"target": "/redfish/v1/Oem/Supermicro/DumpService/Dumps/AttestationDump/Actions/SmcAttestationDump.Generate"
52+
},
53+
"#SmcAttestationDump.Download": {
54+
"target": "/redfish/v1/Oem/Supermicro/DumpService/Dumps/AttestationDump/Actions/SmcAttestationDump.Download"
55+
},
56+
"#SmcAttestationDump.Delete": {
57+
"target": "/redfish/v1/Oem/Supermicro/DumpService/Dumps/AttestationDump/Actions/SmcAttestationDump.Delete"
58+
}
59+
},
60+
"@odata.etag": "\"0e25db1a4c2d3d4a28cda306e1b29abe\""
61+
}`
62+
63+
// TestSmcDumpService tests the parsing of the DumpService oem field
64+
func TestSmcDumpService(t *testing.T) {
65+
ds := &DumpService{}
66+
if err := json.Unmarshal([]byte(dumpServiceBody), ds); err != nil {
67+
t.Fatalf("error decoding json: %v", err)
68+
}
69+
70+
if ds.ID != "DumpService" {
71+
t.Errorf("unexpected ID: %s", ds.ID)
72+
}
73+
74+
if ds.collectTarget != "/redfish/v1/Oem/Supermicro/DumpService/Actions/OemDumpService.Collect" {
75+
t.Errorf("unexpected install target: %s", ds.collectTarget)
76+
}
77+
78+
if ds.createDumpTarget != "/redfish/v1/Oem/Supermicro/DumpService/Actions/SmcDumpService.CreateDump" {
79+
t.Errorf("unexpected ssl cert link: %s", ds.createDumpTarget)
80+
}
81+
82+
if ds.deleteAllTarget != "/redfish/v1/Oem/Supermicro/DumpService/Actions/SmcDumpService.DeleteAll" {
83+
t.Errorf("unexpected ipmi config link: %s", ds.deleteAllTarget)
84+
}
85+
86+
if ds.dumps != "/redfish/v1/Oem/Supermicro/DumpService/Dumps" {
87+
t.Errorf("unexpected dumps link: %s", ds.dumps)
88+
}
89+
}
90+
91+
// TestSmcDump tests the parsing of the Dumpobject.
92+
func TestSmcDump(t *testing.T) {
93+
ds := &Dump{}
94+
if err := json.Unmarshal([]byte(dumpBody), ds); err != nil {
95+
t.Fatalf("error decoding json: %v", err)
96+
}
97+
98+
if ds.ID != "AttestationDump" {
99+
t.Errorf("unexpected ID: %s", ds.ID)
100+
}
101+
102+
if len(ds.AttestationFile) != 2 {
103+
t.Errorf("unexpected number of attestation files: %d", len(ds.AttestationFile))
104+
}
105+
}

oem/smc/updateservice.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ func GetUpdateService(c common.Client, uri string) (*UpdateService, error) {
168168
return common.GetObject[UpdateService](c, uri)
169169
}
170170

171-
// ActivateLicense performs the ActivateLicense action of the UpdateService.
171+
// Install performs an install of an update.
172172
func (us *UpdateService) Install(targets, installOptions []string) error {
173173
if us.installTarget == "" {
174-
return errors.New("Install is not supported by this system")
174+
return errors.New("install is not supported by this system")
175175
}
176176

177177
return us.Post(us.installTarget, map[string]any{

oem/smc/updateservice_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ var updateServiceBody = `{
5656
"@odata.etag": "\"e9b94401dae9992fef2e71ef30cbcfdc\""
5757
}`
5858

59-
// TestSmcUpdateServiceOem tests the parsing of the UpdateService oem field
60-
func TestSmcUpdateServiceOem(t *testing.T) {
59+
// TestSmcUpdateService tests the parsing of the UpdateService oem field
60+
func TestSmcUpdateService(t *testing.T) {
6161
us := &redfish.UpdateService{}
6262
if err := json.Unmarshal([]byte(updateServiceBody), us); err != nil {
6363
t.Fatalf("error decoding json: %v", err)

0 commit comments

Comments
 (0)