Skip to content

Commit 4e01359

Browse files
committed
Add Supermicro OEM Manager object
Signed-off-by: Sean McGinnis <[email protected]>
1 parent 4b8c27e commit 4e01359

File tree

3 files changed

+249
-4
lines changed

3 files changed

+249
-4
lines changed

oem/smc/manager.go

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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+
"github.com/stmcginnis/gofish/redfish"
13+
)
14+
15+
type ManagerConfigResetOption string
16+
17+
const (
18+
PreserveUserManagerConfigResetOption ManagerConfigResetOption = "PreserveUser"
19+
ClearConfigManagerConfigResetOption ManagerConfigResetOption = "ClearConfig"
20+
ResetToAdminManagerConfigResetOption ManagerConfigResetOption = "ResetToADMIN"
21+
)
22+
23+
// Manager is a Supermicro OEM instance of a Manager.
24+
type Manager struct {
25+
redfish.Manager
26+
27+
radius string
28+
mouseMode string
29+
ntp string
30+
ipAccessControl string
31+
smcRAKP string
32+
syslog string
33+
sysLockdown string
34+
memoryPFA string
35+
memoryHealthComp string
36+
snooping string
37+
fanMode string
38+
iKVM string
39+
kcsInterface string
40+
lldp string
41+
licenseManager string
42+
43+
managerConfigResetTarget string
44+
}
45+
46+
// FromManager converts a standard Manager object to the OEM implementation.
47+
func FromManager(manager *redfish.Manager) (*Manager, error) {
48+
m := Manager{
49+
Manager: *manager,
50+
}
51+
52+
var t struct {
53+
Oem struct {
54+
Supermicro struct {
55+
RADIUS common.Link `json:"RADIUS"`
56+
MouseMode common.Link `json:"MouseMode"`
57+
NTP common.Link `json:"NTP"`
58+
IPAccessControl common.Link `json:"IPAccessControl"`
59+
SMCRAKP common.Link `json:"SMCRAKP"`
60+
Syslog common.Link `json:"Syslog"`
61+
SysLockdown common.Link `json:"SysLockdown"`
62+
MemoryPFA common.Link `json:"MemoryPFA"`
63+
MemoryHealthComp common.Link `json:"MemoryHealthComp"`
64+
Snooping common.Link `json:"Snooping"`
65+
FanMode common.Link `json:"FanMode"`
66+
IKVM common.Link `json:"IKVM"`
67+
KCSInterface common.Link `json:"KCSInterface"`
68+
LLDP common.Link `json:"LLDP"`
69+
LicenseManager common.Link `json:"LicenseManager"`
70+
} `json:"Supermicro"`
71+
} `json:"Oem"`
72+
Actions struct {
73+
Oem struct {
74+
ManagerConfigReset common.ActionTarget `json:"#SmcManagerConfig.Reset"`
75+
} `json:"Oem"`
76+
} `json:"Actions"`
77+
}
78+
79+
err := json.Unmarshal(manager.RawData, &t)
80+
if err != nil {
81+
return nil, err
82+
}
83+
84+
m.radius = t.Oem.Supermicro.RADIUS.String()
85+
m.mouseMode = t.Oem.Supermicro.MouseMode.String()
86+
m.ntp = t.Oem.Supermicro.NTP.String()
87+
m.ipAccessControl = t.Oem.Supermicro.IPAccessControl.String()
88+
m.smcRAKP = t.Oem.Supermicro.SMCRAKP.String()
89+
m.syslog = t.Oem.Supermicro.Syslog.String()
90+
m.sysLockdown = t.Oem.Supermicro.SysLockdown.String()
91+
m.memoryPFA = t.Oem.Supermicro.MemoryPFA.String()
92+
m.memoryHealthComp = t.Oem.Supermicro.MemoryHealthComp.String()
93+
m.snooping = t.Oem.Supermicro.Snooping.String()
94+
m.fanMode = t.Oem.Supermicro.FanMode.String()
95+
m.iKVM = t.Oem.Supermicro.IKVM.String()
96+
m.kcsInterface = t.Oem.Supermicro.KCSInterface.String()
97+
m.lldp = t.Oem.Supermicro.LLDP.String()
98+
m.licenseManager = t.Oem.Supermicro.LicenseManager.String()
99+
100+
m.managerConfigResetTarget = t.Actions.Oem.ManagerConfigReset.Target
101+
102+
m.SetClient(manager.GetClient())
103+
return &m, nil
104+
}
105+
106+
// TODO: Add linked objects
107+
108+
// ManagerConfigReset resets the BMC to factory defaults.
109+
func (m *Manager) ManagerConfigReset(option ManagerConfigResetOption) error {
110+
if m.managerConfigResetTarget == "" {
111+
return errors.New("manager config reset not supported by this system")
112+
}
113+
114+
return m.Post(m.managerConfigResetTarget, map[string]interface{}{"Option": option})
115+
}

oem/smc/manager_test.go

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
//
4+
5+
package smc
6+
7+
import (
8+
"encoding/json"
9+
"strings"
10+
"testing"
11+
12+
"github.com/stmcginnis/gofish/redfish"
13+
)
14+
15+
var managerBody = `{
16+
"@odata.type": "#Manager.v1_11_0.Manager",
17+
"@odata.id": "/redfish/v1/Managers/1",
18+
"Id": "1",
19+
"Name": "Manager",
20+
"Description": "BMC",
21+
"ManagerType": "BMC",
22+
"UUID": "00000000-0000-0000-0000-7CC25586E000",
23+
"Model": "ASPEED",
24+
"FirmwareVersion": "01.01.06",
25+
"DateTime": "2024-10-15T21:35:01Z",
26+
"DateTimeLocalOffset": "+00:00",
27+
"Actions": {
28+
"Oem": {
29+
"#SmcManagerConfig.Reset": {
30+
"target": "/redfish/v1/Managers/1/Actions/Oem/SmcManagerConfig.Reset",
31+
"@Redfish.ActionInfo": "/redfish/v1/Managers/1/Oem/Supermicro/ResetActionInfo"
32+
}
33+
},
34+
"#Manager.ResetToDefaults": {
35+
"target": "/redfish/v1/Managers/1/Actions/Manager.ResetToDefaults",
36+
"@Redfish.ActionInfo": "/redfish/v1/Managers/1/ResetToDefaultsActionInfo"
37+
},
38+
"#Manager.Reset": {
39+
"target": "/redfish/v1/Managers/1/Actions/Manager.Reset",
40+
41+
"GracefulRestart"
42+
]
43+
}
44+
},
45+
"Oem": {
46+
"Supermicro": {
47+
"@odata.type": "#SmcManagerExtensions.v1_0_0.Manager",
48+
"RADIUS": {
49+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/RADIUS"
50+
},
51+
"MouseMode": {
52+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MouseMode"
53+
},
54+
"NTP": {
55+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/NTP"
56+
},
57+
"IPAccessControl": {
58+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/IPAccessControl"
59+
},
60+
"SMCRAKP": {
61+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/SMCRAKP"
62+
},
63+
"Syslog": {
64+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/Syslog"
65+
},
66+
"SysLockdown": {
67+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/SysLockdown"
68+
},
69+
"MemoryPFA": {
70+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MemoryPFA"
71+
},
72+
"MemoryHealthComp": {
73+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MemoryHealthComp"
74+
},
75+
"Snooping": {
76+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/Snooping"
77+
},
78+
"FanMode": {
79+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/FanMode"
80+
},
81+
"IKVM": {
82+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/IKVM"
83+
},
84+
"KCSInterface": {
85+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/KCSInterface"
86+
},
87+
"LLDP": {
88+
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/LLDP"
89+
},
90+
"LicenseManager": {
91+
"@odata.id": "/redfish/v1/Managers/1/LicenseManager"
92+
}
93+
}
94+
},
95+
"@odata.etag": "\"70889f859f8f0399a6f71ffb167c1dc1\""
96+
}`
97+
98+
// TestManager tests the parsing of Manager objects.
99+
func TestManager(t *testing.T) {
100+
var m redfish.Manager
101+
err := json.NewDecoder(strings.NewReader(managerBody)).Decode(&m)
102+
if err != nil {
103+
t.Errorf("Error decoding JSON: %s", err)
104+
}
105+
106+
result, err := FromManager(&m)
107+
if err != nil {
108+
t.Errorf("Error converting Redfish Manager to SMC Manager: %s", err)
109+
}
110+
111+
if result.ID != "1" {
112+
t.Errorf("Received invalid ID: %s", result.ID)
113+
}
114+
115+
if result.Name != "Manager" {
116+
t.Errorf("Received invalid name: %s", result.Name)
117+
}
118+
119+
if result.radius != "/redfish/v1/Managers/1/Oem/Supermicro/RADIUS" {
120+
t.Errorf("Invalid RADIUS link: %s", result.radius)
121+
}
122+
123+
if result.mouseMode != "/redfish/v1/Managers/1/Oem/Supermicro/MouseMode" {
124+
t.Errorf("Invalid MouseMode link: %s", result.mouseMode)
125+
}
126+
127+
if result.managerConfigResetTarget != "/redfish/v1/Managers/1/Actions/Oem/SmcManagerConfig.Reset" {
128+
t.Errorf("Invalid ManagerConfigResetTarget link: %s", result.managerConfigResetTarget)
129+
}
130+
}

redfish/manager.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,8 @@ type Manager struct {
384384
// SupportedResetTypes, if provided, is the reset types this system supports.
385385
SupportedResetTypes []ResetType
386386
resetToDefaultsTarget string
387-
// rawData holds the original serialized JSON so we can compare updates.
388-
rawData []byte
387+
// RawData holds the original serialized JSON so we can compare updates.
388+
RawData []byte
389389
}
390390

391391
// UnmarshalJSON unmarshals a Manager object from the raw JSON.
@@ -485,7 +485,7 @@ func (manager *Manager) UnmarshalJSON(b []byte) error {
485485
manager.actionInfo = t.Actions.Reset.ActionInfo
486486

487487
// This is a read/write object, so we need to save the raw object data for later
488-
manager.rawData = b
488+
manager.RawData = b
489489

490490
return nil
491491
}
@@ -495,7 +495,7 @@ func (manager *Manager) Update() error {
495495
// Get a representation of the object's original state so we can find what
496496
// to update.
497497
original := new(Manager)
498-
err := original.UnmarshalJSON(manager.rawData)
498+
err := original.UnmarshalJSON(manager.RawData)
499499
if err != nil {
500500
return err
501501
}

0 commit comments

Comments
 (0)