From 618934c3999876fb70382d7d57af5714f5d85739 Mon Sep 17 00:00:00 2001 From: Sean McGinnis Date: Wed, 16 Oct 2024 12:37:58 -0500 Subject: [PATCH] Add Supermicro OEM Manager subobjects This adds a few of the objects that are linked off of the OEM links for a Manager. Signed-off-by: Sean McGinnis --- oem/smc/fanmode.go | 68 ++++++++++++++++++++++++ oem/smc/fanmode_test.go | 46 +++++++++++++++++ oem/smc/ikvm.go | 68 ++++++++++++++++++++++++ oem/smc/ikvm_test.go | 42 +++++++++++++++ oem/smc/ipaccesscontrol.go | 89 ++++++++++++++++++++++++++++++++ oem/smc/ipaccesscontrol_test.go | 44 ++++++++++++++++ oem/smc/kcsinterface.go | 68 ++++++++++++++++++++++++ oem/smc/kcsinterface_test.go | 37 +++++++++++++ oem/smc/licensemanager.go | 86 ++++++++++++++++++++++++++++++ oem/smc/licensemanager_test.go | 89 ++++++++++++++++++++++++++++++++ oem/smc/lldp.go | 74 ++++++++++++++++++++++++++ oem/smc/lldp_test.go | 39 ++++++++++++++ oem/smc/manager.go | 70 ++++++++++++++++++++++++- oem/smc/memoryhealthcomp.go | 70 +++++++++++++++++++++++++ oem/smc/memoryhealthcomp_test.go | 42 +++++++++++++++ oem/smc/memorypfa.go | 73 ++++++++++++++++++++++++++ oem/smc/memorypfa_test.go | 47 +++++++++++++++++ oem/smc/mousemode.go | 75 +++++++++++++++++++++++++++ oem/smc/mousemode_test.go | 42 +++++++++++++++ oem/smc/nodemanager.go | 4 +- oem/smc/ntp.go | 73 ++++++++++++++++++++++++++ oem/smc/ntp_test.go | 52 +++++++++++++++++++ oem/smc/radius.go | 73 ++++++++++++++++++++++++++ oem/smc/radius_test.go | 52 +++++++++++++++++++ oem/smc/smcrakp.go | 77 +++++++++++++++++++++++++++ oem/smc/smcrakp_test.go | 37 +++++++++++++ oem/smc/snooping.go | 21 ++++++++ oem/smc/snooping_test.go | 37 +++++++++++++ oem/smc/syslockdown.go | 67 ++++++++++++++++++++++++ oem/smc/syslockdown_test.go | 37 +++++++++++++ oem/smc/syslog.go | 71 +++++++++++++++++++++++++ oem/smc/syslog_test.go | 47 +++++++++++++++++ 32 files changed, 1814 insertions(+), 3 deletions(-) create mode 100644 oem/smc/fanmode.go create mode 100644 oem/smc/fanmode_test.go create mode 100644 oem/smc/ikvm.go create mode 100644 oem/smc/ikvm_test.go create mode 100644 oem/smc/ipaccesscontrol.go create mode 100644 oem/smc/ipaccesscontrol_test.go create mode 100644 oem/smc/kcsinterface.go create mode 100644 oem/smc/kcsinterface_test.go create mode 100644 oem/smc/licensemanager.go create mode 100644 oem/smc/licensemanager_test.go create mode 100644 oem/smc/lldp.go create mode 100644 oem/smc/lldp_test.go create mode 100644 oem/smc/memoryhealthcomp.go create mode 100644 oem/smc/memoryhealthcomp_test.go create mode 100644 oem/smc/memorypfa.go create mode 100644 oem/smc/memorypfa_test.go create mode 100644 oem/smc/mousemode.go create mode 100644 oem/smc/mousemode_test.go create mode 100644 oem/smc/ntp.go create mode 100644 oem/smc/ntp_test.go create mode 100644 oem/smc/radius.go create mode 100644 oem/smc/radius_test.go create mode 100644 oem/smc/smcrakp.go create mode 100644 oem/smc/smcrakp_test.go create mode 100644 oem/smc/snooping.go create mode 100644 oem/smc/snooping_test.go create mode 100644 oem/smc/syslockdown.go create mode 100644 oem/smc/syslockdown_test.go create mode 100644 oem/smc/syslog.go create mode 100644 oem/smc/syslog_test.go diff --git a/oem/smc/fanmode.go b/oem/smc/fanmode.go new file mode 100644 index 00000000..d0178102 --- /dev/null +++ b/oem/smc/fanmode.go @@ -0,0 +1,68 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// FanMode is an instance of a FanMode object. +type FanMode struct { + common.Entity + + Mode string + AllowableModes []string `json:"Mode@Redfish.AllowableValues"` + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a FanMode object from the raw JSON. +func (i *FanMode) UnmarshalJSON(b []byte) error { + type temp FanMode + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = FanMode(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *FanMode) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(FanMode) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Mode", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetFanMode will get a FanMode instance from the service. +func GetFanMode(c common.Client, uri string) (*FanMode, error) { + return common.GetObject[FanMode](c, uri) +} diff --git a/oem/smc/fanmode_test.go b/oem/smc/fanmode_test.go new file mode 100644 index 00000000..4e879ff2 --- /dev/null +++ b/oem/smc/fanmode_test.go @@ -0,0 +1,46 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var fanModeBody = `{ + "@odata.type": "#FanMode.v1_0_1.FanMode", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/FanMode", + "Name": "FanMode", + "Id": "Fan Mode", + "Mode": "HeavyIO", + "Mode@Redfish.AllowableValues": [ + "FullSpeed", + "Optimal", + "HeavyIO" + ], + "@odata.etag": "\"753bafbafcb8047326ec2c269ad52111\"" +}` + +// TestFanMode tests the parsing of FanMode objects. +func TestFanMode(t *testing.T) { + var result FanMode + err := json.NewDecoder(strings.NewReader(fanModeBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "Fan Mode" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.Mode != "HeavyIO" { + t.Errorf("Invalid fan mode: %s", result.Mode) + } + + if len(result.AllowableModes) != 3 { + t.Errorf("Unexpected allowable modes: %v", result.AllowableModes) + } +} diff --git a/oem/smc/ikvm.go b/oem/smc/ikvm.go new file mode 100644 index 00000000..c9d37b05 --- /dev/null +++ b/oem/smc/ikvm.go @@ -0,0 +1,68 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// IKVM is an instance of a IKVM object. +type IKVM struct { + common.Entity + + CurrentInterface string `json:"Current Interface"` + URI string + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a IKVM object from the raw JSON. +func (i *IKVM) UnmarshalJSON(b []byte) error { + type temp IKVM + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = IKVM(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *IKVM) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(IKVM) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "CurrentInterface", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetIKVM will get a IKVM instance from the service. +func GetIKVM(c common.Client, uri string) (*IKVM, error) { + return common.GetObject[IKVM](c, uri) +} diff --git a/oem/smc/ikvm_test.go b/oem/smc/ikvm_test.go new file mode 100644 index 00000000..be962ac1 --- /dev/null +++ b/oem/smc/ikvm_test.go @@ -0,0 +1,42 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var iKVMBody = `{ + "@odata.type": "#IKVM.v1_0_2.IKVM", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/IKVM", + "Id": "IKVM", + "Name": "IKVM", + "Current interface": "HTML 5", + "URI": "/redfish/VVGBkzp32dNpSOI.IKVM", + "@odata.etag": "\"916e58e6235aa0579147a3114560a596\"" +}` + +// TestIKVM tests the parsing of IKVM objects. +func TestIKVM(t *testing.T) { + var result IKVM + err := json.NewDecoder(strings.NewReader(iKVMBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "IKVM" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.CurrentInterface != "HTML 5" { + t.Errorf("Invalid current interface: %s", result.CurrentInterface) + } + + if result.URI != "/redfish/VVGBkzp32dNpSOI.IKVM" { + t.Errorf("Invalid URI: %s", result.URI) + } +} diff --git a/oem/smc/ipaccesscontrol.go b/oem/smc/ipaccesscontrol.go new file mode 100644 index 00000000..4263f2cb --- /dev/null +++ b/oem/smc/ipaccesscontrol.go @@ -0,0 +1,89 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +type FilterRulePolicy string + +const ( + FilterRulePolicyAllow FilterRulePolicy = "Allow" + FilterRulePolicyDeny FilterRulePolicy = "Deny" +) + +// FilterRule represents an individual filter rule. +type FilterRule struct { + common.Entity + Address string + PrefixLength int + Policy FilterRulePolicy +} + +// IPAccessControl is an instance of an IPAccessControl object. +type IPAccessControl struct { + common.Entity + + Enabled bool `json:"ServiceEnabled"` + filterRules string + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a IPAccessControl object from the raw JSON. +func (i *IPAccessControl) UnmarshalJSON(b []byte) error { + type temp IPAccessControl + var t struct { + temp + FilterRules common.Link `json:"FilterRules"` + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = IPAccessControl(t.temp) + i.filterRules = t.FilterRules.String() + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *IPAccessControl) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(IPAccessControl) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Enabled", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +func (i *IPAccessControl) FilterRules() ([]*FilterRule, error) { + return common.GetCollectionObjects[FilterRule](i.GetClient(), i.filterRules) +} + +// GetIPAccessControl will get a IPAccessControl instance from the service. +func GetIPAccessControl(c common.Client, uri string) (*IPAccessControl, error) { + return common.GetObject[IPAccessControl](c, uri) +} diff --git a/oem/smc/ipaccesscontrol_test.go b/oem/smc/ipaccesscontrol_test.go new file mode 100644 index 00000000..94a6954b --- /dev/null +++ b/oem/smc/ipaccesscontrol_test.go @@ -0,0 +1,44 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var ipAccessControlBody = `{ + "@odata.type": "#IPAccessControl.v1_0_1.IPAccessControl", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/IPAccessControl", + "Id": "IP Access Control", + "Name": "IP Access Control", + "ServiceEnabled": true, + "FilterRules": { + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/IPAccessControl/FilterRules" + }, + "@odata.etag": "\"ecbaa3f8ca55261d32edce302b8e3ddd\"" +}` + +// TestIPAccessControl tests the parsing of IPAccessControl objects. +func TestIPAccessControl(t *testing.T) { + var result IPAccessControl + err := json.NewDecoder(strings.NewReader(ipAccessControlBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "IP Access Control" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if !result.Enabled { + t.Errorf("Invalid enable state: %t", result.Enabled) + } + + if result.filterRules != "/redfish/v1/Managers/1/Oem/Supermicro/IPAccessControl/FilterRules" { + t.Errorf("Invalid filter rule link: %s", result.filterRules) + } +} diff --git a/oem/smc/kcsinterface.go b/oem/smc/kcsinterface.go new file mode 100644 index 00000000..89455430 --- /dev/null +++ b/oem/smc/kcsinterface.go @@ -0,0 +1,68 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// KCSInterface is an instance of a KCSInterface object. +type KCSInterface struct { + common.Entity + + // Privilege shall contain the current KCS privilege setting. + Privilege string + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a KCSInterface object from the raw JSON. +func (i *KCSInterface) UnmarshalJSON(b []byte) error { + type temp KCSInterface + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = KCSInterface(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *KCSInterface) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(KCSInterface) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Privilege", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetKCSInterface will get a KCSInterface instance from the service. +func GetKCSInterface(c common.Client, uri string) (*KCSInterface, error) { + return common.GetObject[KCSInterface](c, uri) +} diff --git a/oem/smc/kcsinterface_test.go b/oem/smc/kcsinterface_test.go new file mode 100644 index 00000000..9c6a9877 --- /dev/null +++ b/oem/smc/kcsinterface_test.go @@ -0,0 +1,37 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var kcsInterfaceBody = `{ + "@odata.type": "#KCSInterface.v1_1_0.KCSInterface", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/KCSInterface", + "Id": "KCS Interface", + "Name": "KCS Interface", + "Privilege": "Administrator", + "@odata.etag": "\"baa7b14122a605d1a202bd7fa12b8125\"" +}` + +// TestKCSInterface tests the parsing of KCSInterface objects. +func TestKCSInterface(t *testing.T) { + var result KCSInterface + err := json.NewDecoder(strings.NewReader(kcsInterfaceBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "KCS Interface" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.Privilege != "Administrator" { + t.Errorf("Invalid privilege: %s", result.Privilege) + } +} diff --git a/oem/smc/licensemanager.go b/oem/smc/licensemanager.go new file mode 100644 index 00000000..5ae376bd --- /dev/null +++ b/oem/smc/licensemanager.go @@ -0,0 +1,86 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "errors" + + "github.com/stmcginnis/gofish/common" +) + +// LicenseManager is the license manager instance associated with the system. +type LicenseManager struct { + common.Entity + + queryLicense string + + activateLicenseTarget string + clearLicenseTarget string +} + +// UnmarshalJSON unmarshals a LicenseManager object from the raw JSON. +func (lm *LicenseManager) UnmarshalJSON(b []byte) error { + type temp LicenseManager + var t struct { + temp + Actions struct { + ActivateLicense common.ActionTarget `json:"#LicenseManager.ActivateLicense"` + ClearLicense common.ActionTarget `json:"#LicenseManager.ClearLicense"` + } + QueryLicense common.Link + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *lm = LicenseManager(t.temp) + lm.queryLicense = t.QueryLicense.String() + lm.activateLicenseTarget = t.Actions.ActivateLicense.Target + lm.clearLicenseTarget = t.Actions.ClearLicense.Target + + return nil +} + +// GetLicenseManager will get a LicenseManager instance from the service. +func GetLicenseManager(c common.Client, uri string) (*LicenseManager, error) { + return common.GetObject[LicenseManager](c, uri) +} + +// ActivateLicense performs the ActivateLicense action of the LicenseManager. +func (lm *LicenseManager) ActivateLicense() error { + if lm.activateLicenseTarget == "" { + return errors.New("ActivateLicense is not supported by this system") + } + + return lm.Post(lm.activateLicenseTarget, nil) +} + +// ClearLicense performs the ClearLicense action of the LicenseManager. +func (lm *LicenseManager) ClearLicense() error { + if lm.clearLicenseTarget == "" { + return errors.New("ClearLicense is not supported by this system") + } + + return lm.Post(lm.clearLicenseTarget, nil) +} + +// QueryLicense will get the license information from the service. +func (lm *LicenseManager) QueryLicense() (*QueryLicense, error) { + return GetQueryLicense(lm.GetClient(), lm.queryLicense) +} + +// QueryLicense contains license information. +type QueryLicense struct { + common.Entity + Licenses []string +} + +// GetQueryLicense will get the QueryLicense instance from the service. +func GetQueryLicense(c common.Client, uri string) (*QueryLicense, error) { + return common.GetObject[QueryLicense](c, uri) +} diff --git a/oem/smc/licensemanager_test.go b/oem/smc/licensemanager_test.go new file mode 100644 index 00000000..12ebb41a --- /dev/null +++ b/oem/smc/licensemanager_test.go @@ -0,0 +1,89 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var licenseManagerBody = `{ + "@odata.type": "#LicenseManager.v1_0_0.LicenseManager", + "@odata.id": "/redfish/v1/Managers/1/LicenseManager", + "Id": "License Manager", + "Name": "License Manager", + "QueryLicense": { + "@odata.id": "/redfish/v1/Managers/1/LicenseManager/QueryLicense" + }, + "Actions": { + "Oem": {}, + "#LicenseManager.ActivateLicense": { + "target": "/redfish/v1/Managers/1/LicenseManager/Actions/LicenseManager.ActivateLicense" + }, + "#LicenseManager.ClearLicense": { + "target": "/redfish/v1/Managers/1/LicenseManager/Actions/LicenseManager.ClearLicense" + } + }, + "@odata.etag": "\"1e5832264809b8196fcffe3926e503d2\"" +}` + +var queryLicenseBody = `{ + "@odata.type": "#QueryLicense.v1_0_0.QueryLicense", + "@odata.id": "/redfish/v1/Managers/1/LicenseManager/QueryLicense", + "Id": "1", + "Name": "LicenseManager", + "Licenses": [ + "{\"ProductKey\":{\"Node\":{\"LicenseID\":\"1\",\"LicenseName\":\"SFT-OOB-LIC\",\"CreateDate\":\"20240918\"},\"Signature\":\"IDCGR8VNy9Uy2ZIVW0iZs19aS3R6oZjelbSHTDHL6LrgF8Pq/kRzBlRQ4jNc36gXmK7Bl75rHAD2dPyjzdimOZDH/N5iR1XuQFI72/FtJhpnaKyN+l+I4QuArSEZodM9IaBQcttz4QQZyu3Oa5qKGx68PySwLG2prNid62Ts1E2Ni7KpjxtxETzczsDedNoLVi9R2g/2FXhTJiY3XIGANcgJxD/oaGWjM9ebHtsQgY1bXaw8bT6MAJv1pD7iwxuMi+RBrWopvOH7qVylD/vTE9FG6RpwOU79RMmvEcAjXOz32ezHyZECpk5NiRQhHXt7/y2uTh1Bclcl8zdnmHiSy==\"}}", + "{\"ProductKey\":{\"Node\":{\"LicenseID\":\"2\",\"LicenseName\":\"SFT-DCMS-SINGLE\",\"CreateDate\":\"20240918\"},\"Signature\":\"oI13iOXFGszhTdfgvd95DWaErCFNMVhMden7uZ/p/vSFno3rXasyeh3eSUEH3j6BsIs/vxdv0QqxR4BfZEhkPh9+3wdqTaQksvulTyiLV5SQ8Pw5iBtz/5KjAQVKuNNsbva0ZH78an5/X7ZARtIxvXHk+Fbbb6UGx4WYQ4qoz4RfQ6wO0aYa7FV1+fMHLhHgxZS85zOmfY5oEwvkoQgnK2qtlrCmhBNe66KyBv+OhukZm1gagW0EoXq43oPplwOXJDMXfzldY9rML7u6MhaY8KQk4Pss3HakO8pmGVpAROs4mpxCPLobHfCiomaJjqv8/bNofzE5E2jCTM8VfcwGV==\"}}" + ], + "@odata.etag": "\"bfb9e657900835da4081bf525cf454d0\"" +}` + +// TestLicenseManager tests the parsing of LicenseManager objects. +func TestLicenseManager(t *testing.T) { + var result LicenseManager + err := json.NewDecoder(strings.NewReader(licenseManagerBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "License Manager" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.queryLicense != "/redfish/v1/Managers/1/LicenseManager/QueryLicense" { + t.Errorf("Invalid query license link: %s", result.queryLicense) + } + + if result.activateLicenseTarget != "/redfish/v1/Managers/1/LicenseManager/Actions/LicenseManager.ActivateLicense" { + t.Errorf("Invalid activate license target link: %s", result.activateLicenseTarget) + } + + if result.clearLicenseTarget != "/redfish/v1/Managers/1/LicenseManager/Actions/LicenseManager.ClearLicense" { + t.Errorf("Invalid clear license target link: %s", result.clearLicenseTarget) + } +} + +// TestQueryLicense tests the parsing of QueryLicense objects. +func TestQueryLicense(t *testing.T) { + var result QueryLicense + err := json.NewDecoder(strings.NewReader(queryLicenseBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "1" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if len(result.Licenses) != 2 { + t.Errorf("Expected 2 licenses, got %d", len(result.Licenses)) + } + + if !strings.Contains(result.Licenses[0], "SFT-OOB-LIC") { + t.Errorf("Expected license to contain a license string, got %s", result.Licenses[0]) + } +} diff --git a/oem/smc/lldp.go b/oem/smc/lldp.go new file mode 100644 index 00000000..7e7f9728 --- /dev/null +++ b/oem/smc/lldp.go @@ -0,0 +1,74 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" + "github.com/stmcginnis/gofish/redfish" +) + +// LLDP is an instance of a LLDP object. +type LLDP struct { + common.Entity + + // Enabled shall contain the state indicating whether to enable LLDP for a port. + // If LLDP is disabled at the adapter level, this property shall be ignored. + Enabled bool `json:"LLDPEnabled"` + // LLDPReceive shall contain the LLDP data being received on this link. + LLDPReceive redfish.LLDPReceive + // LLDPTransmit shall contain the LLDP data being transmit on this link. + LLDPTransmit redfish.LLDPTransmit + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a LLDP object from the raw JSON. +func (i *LLDP) UnmarshalJSON(b []byte) error { + type temp LLDP + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = LLDP(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *LLDP) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(LLDP) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Enabled", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetLLDP will get a LLDP instance from the service. +func GetLLDP(c common.Client, uri string) (*LLDP, error) { + return common.GetObject[LLDP](c, uri) +} diff --git a/oem/smc/lldp_test.go b/oem/smc/lldp_test.go new file mode 100644 index 00000000..4f1b6535 --- /dev/null +++ b/oem/smc/lldp_test.go @@ -0,0 +1,39 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var lldpBody = `{ + "@odata.type": "#LldpService.v1_0_0.LldpService", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/LLDP", + "Id": "LLDP", + "Name": "LLDP", + "Description": "LLDP Service", + "LLDPEnabled": true, + "LLDPReceive": {}, + "@odata.etag": "\"1f8f5d90dca8588b586dbe4ba3657003\"" +}` + +// TestLLDP tests the parsing of LLDP objects. +func TestLLDP(t *testing.T) { + var result LLDP + err := json.NewDecoder(strings.NewReader(lldpBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "LLDP" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if !result.Enabled { + t.Error("LLDP is not enabled") + } +} diff --git a/oem/smc/manager.go b/oem/smc/manager.go index 9896c015..ed100352 100644 --- a/oem/smc/manager.go +++ b/oem/smc/manager.go @@ -103,7 +103,75 @@ func FromManager(manager *redfish.Manager) (*Manager, error) { return &m, nil } -// TODO: Add linked objects +// RADIUS gets the RADIUS instance associated with this manager. +func (m *Manager) RADIUS() (*RADIUS, error) { + return GetRADIUS(m.GetClient(), m.radius) +} + +// MouseMode gets the MouseMode instance associated with this manager. +func (m *Manager) MouseMode() (*MouseMode, error) { + return GetMouseMode(m.GetClient(), m.mouseMode) +} + +// NTP gets the NTP instance associated with this manager. +func (m *Manager) NTP() (*NTP, error) { + return GetNTP(m.GetClient(), m.ntp) +} + +// SMCRAKP gets the SMCRAKP instance associated with this manager. +func (m *Manager) SMCRAKP() (*SMCRAKP, error) { + return GetSMCRAKP(m.GetClient(), m.smcRAKP) +} + +// Syslog gets the Syslog instance associated with this manager. +func (m *Manager) Syslog() (*Syslog, error) { + return GetSyslog(m.GetClient(), m.syslog) +} + +// SysLockdown gets the SysLockdown instance associated with this manager. +func (m *Manager) SysLockdown() (*SysLockdown, error) { + return GetSysLockdown(m.GetClient(), m.sysLockdown) +} + +// MemoryPFA gets the MemoryPFA instance associated with this manager. +func (m *Manager) MemoryPFA() (*MemoryPFA, error) { + return GetMemoryPFA(m.GetClient(), m.memoryPFA) +} + +// MemoryHealthComp gets the MemoryHealthComp instance associated with this manager. +func (m *Manager) MemoryHealthComp() (*MemoryHealthComp, error) { + return GetMemoryHealthComp(m.GetClient(), m.memoryHealthComp) +} + +// Snooping gets the Snooping instance associated with this manager. +func (m *Manager) Snooping() (*Snooping, error) { + return GetSnooping(m.GetClient(), m.snooping) +} + +// FanMode gets the FanMode instance associated with this manager. +func (m *Manager) FanMode() (*FanMode, error) { + return GetFanMode(m.GetClient(), m.fanMode) +} + +// IKVM gets the IKVM instance associated with this manager. +func (m *Manager) IKVM() (*IKVM, error) { + return GetIKVM(m.GetClient(), m.iKVM) +} + +// KCSInterface gets the KCSInterface instance associated with this manager. +func (m *Manager) KCSInterface() (*KCSInterface, error) { + return GetKCSInterface(m.GetClient(), m.kcsInterface) +} + +// LLDP gets the LLDP instance associated with this manager. +func (m *Manager) LLDP() (*LLDP, error) { + return GetLLDP(m.GetClient(), m.lldp) +} + +// LicenseManager gets the LicenseManager instance associated with this manager. +func (m *Manager) LicenseManager() (*LicenseManager, error) { + return GetLicenseManager(m.GetClient(), m.licenseManager) +} // ManagerConfigReset resets the BMC to factory defaults. func (m *Manager) ManagerConfigReset(option ManagerConfigResetOption) error { diff --git a/oem/smc/memoryhealthcomp.go b/oem/smc/memoryhealthcomp.go new file mode 100644 index 00000000..16228f4b --- /dev/null +++ b/oem/smc/memoryhealthcomp.go @@ -0,0 +1,70 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// MemoryHealthComp is an instance of a MemoryHealthComp object. +type MemoryHealthComp struct { + common.Entity + + // Init shall contain the current state from Bios HII value. + Init string `json:"MemoryHealthCompInit"` + // Next shall contain the next status set by tools would like to change the state. + Next string `json:"MemoryHealthCompNext"` + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a MemoryHealthComp object from the raw JSON. +func (i *MemoryHealthComp) UnmarshalJSON(b []byte) error { + type temp MemoryHealthComp + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = MemoryHealthComp(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *MemoryHealthComp) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(MemoryHealthComp) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Next", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetMemoryHealthComp will get a MemoryHealthComp instance from the service. +func GetMemoryHealthComp(c common.Client, uri string) (*MemoryHealthComp, error) { + return common.GetObject[MemoryHealthComp](c, uri) +} diff --git a/oem/smc/memoryhealthcomp_test.go b/oem/smc/memoryhealthcomp_test.go new file mode 100644 index 00000000..770002a0 --- /dev/null +++ b/oem/smc/memoryhealthcomp_test.go @@ -0,0 +1,42 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var memoryHealthCompBody = `{ + "@odata.type": "#MemoryHealthComp.v1_0_0.MemoryHealthComp", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MemoryHealthComp", + "Id": "MemoryHealthComp", + "Name": "MemoryHealthComp", + "MemoryHealthCompInit": "Disable", + "MemoryHealthCompNext": "Disable", + "@odata.etag": "\"af1226ca6b365ca917866f09f3a6b846\"" +}` + +// TestMemoryHealthComp tests the parsing of MemoryHealthComp objects. +func TestMemoryHealthComp(t *testing.T) { + var result MemoryHealthComp + err := json.NewDecoder(strings.NewReader(memoryHealthCompBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "MemoryHealthComp" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.Init != "Disable" { + t.Errorf("Invalid init state: %s", result.Init) + } + + if result.Next != "Disable" { + t.Errorf("Invalid next state: %s", result.Next) + } +} diff --git a/oem/smc/memorypfa.go b/oem/smc/memorypfa.go new file mode 100644 index 00000000..fbe193c1 --- /dev/null +++ b/oem/smc/memorypfa.go @@ -0,0 +1,73 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// MemoryPFA is an instance of a MemoryPFA object. +type MemoryPFA struct { + common.Entity + + // Init shall contain the current state from Bios HII value. + Init string `json:"MemoryPfaInit"` + // Next shall contain the next status set by tools would like to change the state. + Next string `json:"MemoryPfaNext"` + // AlertID shall contain the forward SELs at one specific Alert Id registered by tool. + AlertID int `json:"AlertId"` + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a MemoryPFA object from the raw JSON. +func (i *MemoryPFA) UnmarshalJSON(b []byte) error { + type temp MemoryPFA + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = MemoryPFA(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *MemoryPFA) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(MemoryPFA) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Next", + "AlertID", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetMemoryPFA will get a MemoryPFA instance from the service. +func GetMemoryPFA(c common.Client, uri string) (*MemoryPFA, error) { + return common.GetObject[MemoryPFA](c, uri) +} diff --git a/oem/smc/memorypfa_test.go b/oem/smc/memorypfa_test.go new file mode 100644 index 00000000..a5f4b0a8 --- /dev/null +++ b/oem/smc/memorypfa_test.go @@ -0,0 +1,47 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var memoryPFABody = `{ + "@odata.type": "#MemoryPFA.v1_0_0.MemoryPFA", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MemoryPFA", + "Id": "MemoryPFA", + "Name": "MemoryPFA", + "MemoryPfaInit": "Disabled", + "MemoryPfaNext": "Disabled", + "AlertId": 10, + "@odata.etag": "\"bb528176e3ac4b740b445ae8aa43f1f1\"" +}` + +// TestMemoryPFA tests the parsing of MemoryPFA objects. +func TestMemoryPFA(t *testing.T) { + var result MemoryPFA + err := json.NewDecoder(strings.NewReader(memoryPFABody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "MemoryPFA" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.Init != "Disabled" { + t.Errorf("Invalid init state: %s", result.Init) + } + + if result.Next != "Disabled" { + t.Errorf("Invalid next state: %s", result.Next) + } + + if result.AlertID != 10 { + t.Errorf("Invalid alert ID: %d", result.AlertID) + } +} diff --git a/oem/smc/mousemode.go b/oem/smc/mousemode.go new file mode 100644 index 00000000..e67188a5 --- /dev/null +++ b/oem/smc/mousemode.go @@ -0,0 +1,75 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +type MouseModeSetting string + +const ( + MouseModeSettingSingle MouseModeSetting = "Single" + MouseModeSettingRelative MouseModeSetting = "Relative" + MouseModeSettingAbsolute MouseModeSetting = "Absolute" +) + +// MouseMode is an instance of a MouseMode object. +type MouseMode struct { + common.Entity + + Mode MouseModeSetting `json:"Mode"` + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a MouseMode object from the raw JSON. +func (r *MouseMode) UnmarshalJSON(b []byte) error { + type temp MouseMode + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *r = MouseMode(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + r.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (r *MouseMode) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + rad := new(MouseMode) + err := rad.UnmarshalJSON(r.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Mode", + } + + originalElement := reflect.ValueOf(rad).Elem() + currentElement := reflect.ValueOf(r).Elem() + + return r.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetMouseMode will get a MouseMode instance from the service. +func GetMouseMode(c common.Client, uri string) (*MouseMode, error) { + return common.GetObject[MouseMode](c, uri) +} diff --git a/oem/smc/mousemode_test.go b/oem/smc/mousemode_test.go new file mode 100644 index 00000000..68362f33 --- /dev/null +++ b/oem/smc/mousemode_test.go @@ -0,0 +1,42 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var mouseModeBody = `{ + "@odata.type": "#MouseMode.v1_0_0.MouseMode", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/MouseMode", + "Name": "MouseMode", + "Id": "Mouse Mode", + "Mode": "Absolute", + "Mode@Redfish.AllowableValues": [ + "Absolute", + "Relative", + "Single" + ], + "@odata.etag": "\"9dee13296f2c876a0733eec3371ad4f4\"" +}` + +// TestMouseMode tests the parsing of MouseMode objects. +func TestMouseMode(t *testing.T) { + var result MouseMode + err := json.NewDecoder(strings.NewReader(mouseModeBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "Mouse Mode" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.Mode != "Absolute" { + t.Errorf("Invalid mode: %s", result.Mode) + } +} diff --git a/oem/smc/nodemanager.go b/oem/smc/nodemanager.go index be0743ba..39bb06d8 100644 --- a/oem/smc/nodemanager.go +++ b/oem/smc/nodemanager.go @@ -6,7 +6,7 @@ package smc import ( "encoding/json" - "fmt" + "errors" "github.com/stmcginnis/gofish/common" ) @@ -99,7 +99,7 @@ func GetNodeManager(c common.Client, uri string) (*NodeManager, error) { // ClearAllPolicies clears the configured policies of the NodeManager. func (nm *NodeManager) ClearAllPolicies() error { if nm.clearAllPoliciesTarget == "" { - return fmt.Errorf("ClearAllPolicies is not supported by this system") + return errors.New("ClearAllPolicies is not supported by this system") } return nm.Post(nm.clearAllPoliciesTarget, nil) diff --git a/oem/smc/ntp.go b/oem/smc/ntp.go new file mode 100644 index 00000000..2c6ff1a3 --- /dev/null +++ b/oem/smc/ntp.go @@ -0,0 +1,73 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// NTP is an instance of an NTP object. +type NTP struct { + common.Entity + + Enabled bool `json:"NTPEnable"` + PrimaryServer string `json:"PrimaryNTPServer"` + SecondaryServer string `json:"SecondaryNTPServer"` + DaylightSavingTime bool `json:"DaylightSavingTime"` + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a NTP object from the raw JSON. +func (r *NTP) UnmarshalJSON(b []byte) error { + type temp NTP + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *r = NTP(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + r.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (r *NTP) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + rad := new(NTP) + err := rad.UnmarshalJSON(r.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Enabled", + "PrimaryServer", + "SecondaryServer", + "DaylightSavingTime", + } + + originalElement := reflect.ValueOf(rad).Elem() + currentElement := reflect.ValueOf(r).Elem() + + return r.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetNTP will get a NTP instance from the service. +func GetNTP(c common.Client, uri string) (*NTP, error) { + return common.GetObject[NTP](c, uri) +} diff --git a/oem/smc/ntp_test.go b/oem/smc/ntp_test.go new file mode 100644 index 00000000..baff2011 --- /dev/null +++ b/oem/smc/ntp_test.go @@ -0,0 +1,52 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var ntpBody = `{ + "@odata.type": "#NTP.v1_0_3.NTP", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/NTP", + "Id": "NTP", + "Name": "NTP Service", + "NTPEnable": true, + "PrimaryNTPServer": "localhost", + "SecondaryNTPServer": "127.0.0.1", + "DaylightSavingTime": true, + "@odata.etag": "\"6002d9d6874d76983f5cfb025da6fd57\"" +}` + +// TestNTP tests the parsing of NTP objects. +func TestNTP(t *testing.T) { + var result NTP + err := json.NewDecoder(strings.NewReader(ntpBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.Name != "NTP Service" { + t.Errorf("Received invalid name: %s", result.Name) + } + + if !result.Enabled { + t.Errorf("Invalid enabled state: %t", result.Enabled) + } + + if !result.DaylightSavingTime { + t.Errorf("Invalid daylight savings time state: %t", result.DaylightSavingTime) + } + + if result.PrimaryServer != "localhost" { + t.Errorf("Invalid server: %s", result.PrimaryServer) + } + + if result.SecondaryServer != "127.0.0.1" { + t.Errorf("Invalid server: %s", result.SecondaryServer) + } +} diff --git a/oem/smc/radius.go b/oem/smc/radius.go new file mode 100644 index 00000000..ead07f01 --- /dev/null +++ b/oem/smc/radius.go @@ -0,0 +1,73 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// RADIUS is an instance of a RADIUS object. +type RADIUS struct { + common.Entity + + Enabled bool `json:"RadiusEnabled"` + Server string `json:"RadiusServer"` + Port int `json:"RadiusPortNumber"` + Secret string `json:"RadiusSecret"` + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a RADIUS object from the raw JSON. +func (r *RADIUS) UnmarshalJSON(b []byte) error { + type temp RADIUS + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *r = RADIUS(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + r.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (r *RADIUS) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + rad := new(RADIUS) + err := rad.UnmarshalJSON(r.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Enabled", + "ServerIP", + "PortNumber", + "Secret", + } + + originalElement := reflect.ValueOf(rad).Elem() + currentElement := reflect.ValueOf(r).Elem() + + return r.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetRADIUS will get a RADIUS instance from the service. +func GetRADIUS(c common.Client, uri string) (*RADIUS, error) { + return common.GetObject[RADIUS](c, uri) +} diff --git a/oem/smc/radius_test.go b/oem/smc/radius_test.go new file mode 100644 index 00000000..add42db2 --- /dev/null +++ b/oem/smc/radius_test.go @@ -0,0 +1,52 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var radiusBody = `{ + "@odata.type": "#RADIUS.v1_0_2.RADIUS", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/RADIUS", + "Id": "RADIUS", + "Name": "RADIUS", + "RadiusEnabled": true, + "RadiusServer": "10.10.10.10", + "RadiusPortNumber": 1812, + "RadiusSecret": "SECRET", + "@odata.etag": "\"23907a0ed1b646fed1e96d0fe734ddd9\"" +}` + +// TestRadius tests the parsing of Radius objects. +func TestRadius(t *testing.T) { + var result RADIUS + err := json.NewDecoder(strings.NewReader(radiusBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "RADIUS" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if !result.Enabled { + t.Errorf("Invalid enable state: %t", result.Enabled) + } + + if result.Server != "10.10.10.10" { + t.Errorf("Invalid server: %s", result.Server) + } + + if result.Port != 1812 { + t.Errorf("Invalid port: %d", result.Port) + } + + if result.Secret != "SECRET" { + t.Errorf("Invalid secret: %s", result.Secret) + } +} diff --git a/oem/smc/smcrakp.go b/oem/smc/smcrakp.go new file mode 100644 index 00000000..4ad6e83b --- /dev/null +++ b/oem/smc/smcrakp.go @@ -0,0 +1,77 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +//nolint:revive +type SMCRAKPType string + +const ( + SMCRAKPTypeEnabled SMCRAKPType = "Enabled" + SMCRAKPTypeDisabled SMCRAKPType = "Disabled" +) + +// SMCRAKP is an instance of an SMCRAKP object. +// +//nolint:revive +type SMCRAKP struct { + common.Entity + + Mode SMCRAKPType + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a SMCRAKP object from the raw JSON. +func (i *SMCRAKP) UnmarshalJSON(b []byte) error { + type temp SMCRAKP + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = SMCRAKP(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *SMCRAKP) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(SMCRAKP) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Mode", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetSMCRAKP will get a SMCRAKP instance from the service. +func GetSMCRAKP(c common.Client, uri string) (*SMCRAKP, error) { + return common.GetObject[SMCRAKP](c, uri) +} diff --git a/oem/smc/smcrakp_test.go b/oem/smc/smcrakp_test.go new file mode 100644 index 00000000..afa17db5 --- /dev/null +++ b/oem/smc/smcrakp_test.go @@ -0,0 +1,37 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var smcRAKPBody = `{ + "@odata.type": "#SMCRAKP.v1_0_0.SMCRAKP", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/SMCRAKP", + "Name": "SMCRAKP", + "Id": "SMC RAKP", + "Mode": "Disabled", + "@odata.etag": "\"2e678283a52f99ccf06bc13d8434178a\"" +}` + +// TestSMCRAKP tests the parsing of SMCRAKP objects. +func TestSMCRAKP(t *testing.T) { + var result SMCRAKP + err := json.NewDecoder(strings.NewReader(smcRAKPBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "SMC RAKP" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.Mode != "Disabled" { + t.Errorf("Invalid mode: %s", result.Mode) + } +} diff --git a/oem/smc/snooping.go b/oem/smc/snooping.go new file mode 100644 index 00000000..b21fdd87 --- /dev/null +++ b/oem/smc/snooping.go @@ -0,0 +1,21 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "github.com/stmcginnis/gofish/common" +) + +// Snooping is an instance of a Snooping object. +type Snooping struct { + common.Entity + + PostCode string +} + +// GetSnooping will get a Snooping instance from the service. +func GetSnooping(c common.Client, uri string) (*Snooping, error) { + return common.GetObject[Snooping](c, uri) +} diff --git a/oem/smc/snooping_test.go b/oem/smc/snooping_test.go new file mode 100644 index 00000000..22026bad --- /dev/null +++ b/oem/smc/snooping_test.go @@ -0,0 +1,37 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var snoopingBody = `{ + "@odata.type": "#Snooping.v1_0_0.Snooping", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/Snooping", + "Name": "Snooping", + "Id": "Snooping", + "PostCode": "e3", + "@odata.etag": "\"b6b45c5595e17a1a2c878fa9f47b05c6\"" +}` + +// TestSnooping tests the parsing of Snooping objects. +func TestSnooping(t *testing.T) { + var result Snooping + err := json.NewDecoder(strings.NewReader(snoopingBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "Snooping" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if result.PostCode != "e3" { + t.Errorf("Invalid post code: %s", result.PostCode) + } +} diff --git a/oem/smc/syslockdown.go b/oem/smc/syslockdown.go new file mode 100644 index 00000000..585d05d9 --- /dev/null +++ b/oem/smc/syslockdown.go @@ -0,0 +1,67 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// SysLockdown is an instance of a SysLockdown object. +type SysLockdown struct { + common.Entity + + Enabled bool `json:"SysLockdownEnabled"` + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a SysLockdown object from the raw JSON. +func (i *SysLockdown) UnmarshalJSON(b []byte) error { + type temp SysLockdown + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = SysLockdown(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *SysLockdown) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(SysLockdown) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Enabled", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetSysLockdown will get a SysLockdown instance from the service. +func GetSysLockdown(c common.Client, uri string) (*SysLockdown, error) { + return common.GetObject[SysLockdown](c, uri) +} diff --git a/oem/smc/syslockdown_test.go b/oem/smc/syslockdown_test.go new file mode 100644 index 00000000..1c27c580 --- /dev/null +++ b/oem/smc/syslockdown_test.go @@ -0,0 +1,37 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var sysLockdownBody = `{ + "@odata.type": "#SysLockdown.v1_0_0.SysLockdown", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/SysLockdown", + "Id": "SysLockdown", + "Name": "SysLockdown", + "SysLockdownEnabled": true, + "@odata.etag": "\"8374ed52bcd7c7e92902143a75345193\"" +}` + +// TestSysLockdown tests the parsing of SysLockdown objects. +func TestSysLockdown(t *testing.T) { + var result SysLockdown + err := json.NewDecoder(strings.NewReader(sysLockdownBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "SysLockdown" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if !result.Enabled { + t.Errorf("Invalid enable state: %t", result.Enabled) + } +} diff --git a/oem/smc/syslog.go b/oem/smc/syslog.go new file mode 100644 index 00000000..0f400254 --- /dev/null +++ b/oem/smc/syslog.go @@ -0,0 +1,71 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "reflect" + + "github.com/stmcginnis/gofish/common" +) + +// Syslog is an instance of a Syslog object. +type Syslog struct { + common.Entity + + Enabled bool `json:"EnableSyslog"` + Server string `json:"SyslogServer"` + Port int `json:"SyslogPortNumber"` + + // RawData holds the original serialized JSON so we can compare updates. + RawData []byte +} + +// UnmarshalJSON unmarshals a Syslog object from the raw JSON. +func (i *Syslog) UnmarshalJSON(b []byte) error { + type temp Syslog + var t struct { + temp + } + + err := json.Unmarshal(b, &t) + if err != nil { + return err + } + + *i = Syslog(t.temp) + + // This is a read/write object, so we need to save the raw object data for later + i.RawData = b + + return nil +} + +// Update commits updates to this object's properties to the running system. +func (i *Syslog) Update() error { + // Get a representation of the object's original state so we can find what + // to update. + orig := new(Syslog) + err := orig.UnmarshalJSON(i.RawData) + if err != nil { + return err + } + + readWriteFields := []string{ + "Enabled", + "Port", + "Server", + } + + originalElement := reflect.ValueOf(orig).Elem() + currentElement := reflect.ValueOf(i).Elem() + + return i.Entity.Update(originalElement, currentElement, readWriteFields) +} + +// GetSyslog will get a Syslog instance from the service. +func GetSyslog(c common.Client, uri string) (*Syslog, error) { + return common.GetObject[Syslog](c, uri) +} diff --git a/oem/smc/syslog_test.go b/oem/smc/syslog_test.go new file mode 100644 index 00000000..171468aa --- /dev/null +++ b/oem/smc/syslog_test.go @@ -0,0 +1,47 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// + +package smc + +import ( + "encoding/json" + "strings" + "testing" +) + +var syslogBody = `{ + "@odata.type": "#Syslog.v1_0_1.Syslog", + "@odata.id": "/redfish/v1/Managers/1/Oem/Supermicro/Syslog", + "Id": "Syslog", + "Name": "Syslog", + "EnableSyslog": true, + "SyslogServer": "localhost", + "SyslogPortNumber": 514, + "@odata.etag": "\"b27af6393687bb1810b00fe52874e053\"" +}` + +// TestSyslog tests the parsing of Syslog objects. +func TestSyslog(t *testing.T) { + var result Syslog + err := json.NewDecoder(strings.NewReader(syslogBody)).Decode(&result) + if err != nil { + t.Errorf("Error decoding JSON: %s", err) + } + + if result.ID != "Syslog" { + t.Errorf("Received invalid ID: %s", result.ID) + } + + if !result.Enabled { + t.Errorf("Invalid enable state: %t", result.Enabled) + } + + if result.Server != "localhost" { + t.Errorf("Invalid server: %s", result.Server) + } + + if result.Port != 514 { + t.Errorf("Invalid port: %d", result.Port) + } +}