Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Supermicro OEM Manager object #369

Merged
merged 1 commit into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions oem/smc/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//
// SPDX-License-Identifier: BSD-3-Clause
//

package smc

import (
"encoding/json"
"errors"

"github.com/stmcginnis/gofish/common"
"github.com/stmcginnis/gofish/redfish"
)

type ManagerConfigResetOption string

const (
PreserveUserManagerConfigResetOption ManagerConfigResetOption = "PreserveUser"
ClearConfigManagerConfigResetOption ManagerConfigResetOption = "ClearConfig"
ResetToAdminManagerConfigResetOption ManagerConfigResetOption = "ResetToADMIN"
)

// Manager is a Supermicro OEM instance of a Manager.
type Manager struct {
redfish.Manager

radius string
mouseMode string
ntp string
ipAccessControl string
smcRAKP string
syslog string
sysLockdown string
memoryPFA string
memoryHealthComp string
snooping string
fanMode string
iKVM string
kcsInterface string
lldp string
licenseManager string

managerConfigResetTarget string
}

// FromManager converts a standard Manager object to the OEM implementation.
func FromManager(manager *redfish.Manager) (*Manager, error) {
m := Manager{
Manager: *manager,
}

var t struct {
Oem struct {
Supermicro struct {
RADIUS common.Link `json:"RADIUS"`
MouseMode common.Link `json:"MouseMode"`
NTP common.Link `json:"NTP"`
IPAccessControl common.Link `json:"IPAccessControl"`
SMCRAKP common.Link `json:"SMCRAKP"`
Syslog common.Link `json:"Syslog"`
SysLockdown common.Link `json:"SysLockdown"`
MemoryPFA common.Link `json:"MemoryPFA"`
MemoryHealthComp common.Link `json:"MemoryHealthComp"`
Snooping common.Link `json:"Snooping"`
FanMode common.Link `json:"FanMode"`
IKVM common.Link `json:"IKVM"`
KCSInterface common.Link `json:"KCSInterface"`
LLDP common.Link `json:"LLDP"`
LicenseManager common.Link `json:"LicenseManager"`
} `json:"Supermicro"`
} `json:"Oem"`
Actions struct {
Oem struct {
ManagerConfigReset common.ActionTarget `json:"#SmcManagerConfig.Reset"`
} `json:"Oem"`
} `json:"Actions"`
}

err := json.Unmarshal(manager.RawData, &t)
if err != nil {
return nil, err
}

m.radius = t.Oem.Supermicro.RADIUS.String()
m.mouseMode = t.Oem.Supermicro.MouseMode.String()
m.ntp = t.Oem.Supermicro.NTP.String()
m.ipAccessControl = t.Oem.Supermicro.IPAccessControl.String()
m.smcRAKP = t.Oem.Supermicro.SMCRAKP.String()
m.syslog = t.Oem.Supermicro.Syslog.String()
m.sysLockdown = t.Oem.Supermicro.SysLockdown.String()
m.memoryPFA = t.Oem.Supermicro.MemoryPFA.String()
m.memoryHealthComp = t.Oem.Supermicro.MemoryHealthComp.String()
m.snooping = t.Oem.Supermicro.Snooping.String()
m.fanMode = t.Oem.Supermicro.FanMode.String()
m.iKVM = t.Oem.Supermicro.IKVM.String()
m.kcsInterface = t.Oem.Supermicro.KCSInterface.String()
m.lldp = t.Oem.Supermicro.LLDP.String()
m.licenseManager = t.Oem.Supermicro.LicenseManager.String()

m.managerConfigResetTarget = t.Actions.Oem.ManagerConfigReset.Target

m.SetClient(manager.GetClient())
return &m, nil
}

// TODO: Add linked objects

// ManagerConfigReset resets the BMC to factory defaults.
func (m *Manager) ManagerConfigReset(option ManagerConfigResetOption) error {
if m.managerConfigResetTarget == "" {
return errors.New("manager config reset not supported by this system")
}

return m.Post(m.managerConfigResetTarget, map[string]interface{}{"Option": option})
}
130 changes: 130 additions & 0 deletions oem/smc/manager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//
// SPDX-License-Identifier: BSD-3-Clause
//

package smc

import (
"encoding/json"
"strings"
"testing"

"github.com/stmcginnis/gofish/redfish"
)

var managerBody = `{
"@odata.type": "#Manager.v1_11_0.Manager",
"@odata.id": "/redfish/v1/Managers/1",
"Id": "1",
"Name": "Manager",
"Description": "BMC",
"ManagerType": "BMC",
"UUID": "00000000-0000-0000-0000-7CC25586E000",
"Model": "ASPEED",
"FirmwareVersion": "01.01.06",
"DateTime": "2024-10-15T21:35:01Z",
"DateTimeLocalOffset": "+00:00",
"Actions": {
"Oem": {
"#SmcManagerConfig.Reset": {
"target": "/redfish/v1/Managers/1/Actions/Oem/SmcManagerConfig.Reset",
"@Redfish.ActionInfo": "/redfish/v1/Managers/1/Oem/Supermicro/ResetActionInfo"
}
},
"#Manager.ResetToDefaults": {
"target": "/redfish/v1/Managers/1/Actions/Manager.ResetToDefaults",
"@Redfish.ActionInfo": "/redfish/v1/Managers/1/ResetToDefaultsActionInfo"
},
"#Manager.Reset": {
"target": "/redfish/v1/Managers/1/Actions/Manager.Reset",
"[email protected]": [
"GracefulRestart"
]
}
},
"Oem": {
"Supermicro": {
"@odata.type": "#SmcManagerExtensions.v1_0_0.Manager",
"RADIUS": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/RADIUS"
},
"MouseMode": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MouseMode"
},
"NTP": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/NTP"
},
"IPAccessControl": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/IPAccessControl"
},
"SMCRAKP": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/SMCRAKP"
},
"Syslog": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/Syslog"
},
"SysLockdown": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/SysLockdown"
},
"MemoryPFA": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MemoryPFA"
},
"MemoryHealthComp": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MemoryHealthComp"
},
"Snooping": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/Snooping"
},
"FanMode": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/FanMode"
},
"IKVM": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/IKVM"
},
"KCSInterface": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/KCSInterface"
},
"LLDP": {
"@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/LLDP"
},
"LicenseManager": {
"@odata.id": "/redfish/v1/Managers/1/LicenseManager"
}
}
},
"@odata.etag": "\"70889f859f8f0399a6f71ffb167c1dc1\""
}`

// TestManager tests the parsing of Manager objects.
func TestManager(t *testing.T) {
var m redfish.Manager
err := json.NewDecoder(strings.NewReader(managerBody)).Decode(&m)
if err != nil {
t.Errorf("Error decoding JSON: %s", err)
}

result, err := FromManager(&m)
if err != nil {
t.Errorf("Error converting Redfish Manager to SMC Manager: %s", err)
}

if result.ID != "1" {
t.Errorf("Received invalid ID: %s", result.ID)
}

if result.Name != "Manager" {
t.Errorf("Received invalid name: %s", result.Name)
}

if result.radius != "/redfish/v1/Managers/1/Oem/Supermicro/RADIUS" {
t.Errorf("Invalid RADIUS link: %s", result.radius)
}

if result.mouseMode != "/redfish/v1/Managers/1/Oem/Supermicro/MouseMode" {
t.Errorf("Invalid MouseMode link: %s", result.mouseMode)
}

if result.managerConfigResetTarget != "/redfish/v1/Managers/1/Actions/Oem/SmcManagerConfig.Reset" {
t.Errorf("Invalid ManagerConfigResetTarget link: %s", result.managerConfigResetTarget)
}
}
8 changes: 4 additions & 4 deletions redfish/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,8 @@ type Manager struct {
// SupportedResetTypes, if provided, is the reset types this system supports.
SupportedResetTypes []ResetType
resetToDefaultsTarget string
// rawData holds the original serialized JSON so we can compare updates.
rawData []byte
// RawData holds the original serialized JSON so we can compare updates.
RawData []byte
}

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

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

return nil
}
Expand All @@ -495,7 +495,7 @@ func (manager *Manager) Update() error {
// Get a representation of the object's original state so we can find what
// to update.
original := new(Manager)
err := original.UnmarshalJSON(manager.rawData)
err := original.UnmarshalJSON(manager.RawData)
if err != nil {
return err
}
Expand Down