Skip to content

Commit

Permalink
VendorConfigManager implementations for dell, supermicro and asrockrack
Browse files Browse the repository at this point in the history
  • Loading branch information
splaspood committed Nov 14, 2023
1 parent 5eb9915 commit 34ae332
Show file tree
Hide file tree
Showing 4 changed files with 392 additions and 0 deletions.
121 changes: 121 additions & 0 deletions config/asrockrack/asrockrack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package config

import (
"github.com/bmc-toolbox/common/config"

"encoding/xml"
"errors"
"strings"
)

var invalidConfigFormatError = errors.New("invalid config format")

Check failure on line 11 in config/asrockrack/asrockrack.go

View workflow job for this annotation

GitHub Actions / lint

`invalidConfigFormatError` is unused (deadcode)

Check failure on line 11 in config/asrockrack/asrockrack.go

View workflow job for this annotation

GitHub Actions / lint

`invalidConfigFormatError` is unused (deadcode)

type ASRockRACKVendorConfigManager struct {
ConfigFormat string
ConfigData *ASRockRACKConfig
}

type ASRockRACKConfig struct {
BiosCfg *ASRockRACKBiosCfg `xml:"BiosCfg"`
}

type ASRockRACKBiosCfg struct {
XMLName xml.Name `xml:"BiosCfg"`
Menus []*ASRockRACKBiosCfgMenu `xml:"Menu"`
}

type ASRockRACKBiosCfgMenu struct {
XMLName xml.Name `xml:"Menu"`
Name string `xml:"name,attr"`
Settings []*ASRockRACKBiosCfgSetting `xml:"Setting"`
Menus []*ASRockRACKBiosCfgMenu `xml:"Menu"`
}

type ASRockRACKBiosCfgSetting struct {
XMLName xml.Name `xml:"Setting"`
Name string `xml:"Name,attr"`
Order string `xml:"order,attr"`
SelectedOption string `xml:"selectedOption,attr"`
Type string `xml:"type,attr"`
}

func New(configFormat string) (config.VendorConfigManager, error) {
asrr := &ASRockRACKVendorConfigManager{}

switch strings.ToLower(configFormat) {
case "json":
asrr.ConfigFormat = strings.ToLower(configFormat)
default:
return nil, errors.New("unknown config format")

Check failure on line 49 in config/asrockrack/asrockrack.go

View workflow job for this annotation

GitHub Actions / lint

err113: do not define dynamic errors, use wrapped static errors instead: "errors.New(\"unknown config format\")" (goerr113)

Check failure on line 49 in config/asrockrack/asrockrack.go

View workflow job for this annotation

GitHub Actions / lint

err113: do not define dynamic errors, use wrapped static errors instead: "errors.New(\"unknown config format\")" (goerr113)
}

asrr.ConfigData = &ASRockRACKConfig{
BiosCfg: &ASRockRACKBiosCfg{},
}

return asrr, nil
}

// FindMenu locates an existing ASRockRACKBiosCfgMenu if one exists in the ConfigData, if not
// it creates one and returns a pointer to that.
func (cm *ASRockRACKVendorConfigManager) FindMenu(menuName string) (m *ASRockRACKBiosCfgMenu) {
for _, m = range cm.ConfigData.BiosCfg.Menus {
if m.Name == menuName {
return
}
}

m.Name = menuName

cm.ConfigData.BiosCfg.Menus = append(cm.ConfigData.BiosCfg.Menus, m)

return
}

// FindMenuSetting locates an existing ASRockRACKBiosCfgSetting if one exists in the
// ConfigData, if not it creates one and returns a pointer to that.
func (cm *ASRockRACKVendorConfigManager) FindMenuSetting(m *ASRockRACKBiosCfgMenu, name string) (s *ASRockRACKBiosCfgSetting) {
for _, s = range m.Settings {
if s.Name == name {
return
}
}

s.Name = name

m.Settings = append(m.Settings, s)

return
}

// TODO(jwb) How do we handle the random nature of sub menus here.. we could make the user pass the explicit pointer to a menu struct, or..
func (cm *ASRockRACKVendorConfigManager) Raw(name, value string, menuPath []string) {
// c := cm.FindComponent(fqdd)

Check failure on line 93 in config/asrockrack/asrockrack.go

View workflow job for this annotation

GitHub Actions / lint

commentedOutCode: may want to remove commented-out code (gocritic)

Check failure on line 93 in config/asrockrack/asrockrack.go

View workflow job for this annotation

GitHub Actions / lint

commentedOutCode: may want to remove commented-out code (gocritic)
// attr := cm.FindComponentAttribute(c, name)
// attr.Value = value
// return nil
}

func (cm *ASRockRACKVendorConfigManager) Marshal() (string, error) {
switch strings.ToLower(cm.ConfigFormat) {
case "xml":
x, err := xml.Marshal(cm.ConfigData)
if err != nil {
return "", err
}

return string(x), nil
default:
return "", errors.New("unknown config format")
}
}

// Generic config options

func (cm *ASRockRACKVendorConfigManager) EnableTPM() {
// Unimplemented
}

func (cm *ASRockRACKVendorConfigManager) EnableSRIOV() {
// Unimplemented
}
130 changes: 130 additions & 0 deletions config/dell/dell.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package dell

import (
"github.com/bmc-toolbox/common/config"

"encoding/json"
"encoding/xml"
"errors"
"strings"
)

var errUnknownConfigFormat = errors.New("unknown config format")

type DellVendorConfigManager struct {

Check failure on line 14 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellVendorConfigManager by other packages, and that stutters; consider calling this VendorConfigManager (golint)

Check failure on line 14 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellVendorConfigManager by other packages, and that stutters; consider calling this VendorConfigManager (golint)
ConfigFormat string
ConfigData *DellConfig
}

type DellConfig struct {

Check failure on line 19 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellConfig by other packages, and that stutters; consider calling this Config (golint)

Check failure on line 19 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellConfig by other packages, and that stutters; consider calling this Config (golint)
SystemConfiguration *DellSystemConfiguration `xml:"SystemConfiguration" json:"SystemConfiguration"`
}

type DellSystemConfiguration struct {

Check failure on line 23 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellSystemConfiguration by other packages, and that stutters; consider calling this SystemConfiguration (golint)

Check failure on line 23 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellSystemConfiguration by other packages, and that stutters; consider calling this SystemConfiguration (golint)
XMLName xml.Name `xml:"SystemConfiguration"`
Model string `xml:"Model,attr" json:"Model"`
Comments []string `xml:"Comments>Comment,omitempty" json:"Comments,omitempty" `
ServiceTag string `xml:"ServiceTag,attr" json:"ServiceTag"`
TimeStamp string `xml:"TimeStamp,attr" json:"TimeStamp"`
Components []*DellComponent `xml:"Component" json:"Components"`
}

type DellComponent struct {

Check failure on line 32 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellComponent by other packages, and that stutters; consider calling this Component (golint)

Check failure on line 32 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellComponent by other packages, and that stutters; consider calling this Component (golint)
XMLName xml.Name `xml:"Component"`
FQDD string `xml:"FQDD,attr" json:"FQDD"`
Attributes []*DellComponentAttribute `xml:"Attribute" json:"Attributes"`
}

type DellComponentAttribute struct {

Check failure on line 38 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellComponentAttribute by other packages, and that stutters; consider calling this ComponentAttribute (golint)

Check failure on line 38 in config/dell/dell.go

View workflow job for this annotation

GitHub Actions / lint

type name will be used as dell.DellComponentAttribute by other packages, and that stutters; consider calling this ComponentAttribute (golint)
XMLName xml.Name `xml:"Attribute"`
Name string `xml:"Name,attr" json:"Name"`
SetOnImport bool `json:"SetOnImport"`
Comment string `json:"Comment"`
Value string `xml:",chardata" json:"Value"`
}

func New(configFormat string) (config.VendorConfigManager, error) {
dell := &DellVendorConfigManager{}

switch strings.ToLower(configFormat) {
case "xml", "json":
dell.ConfigFormat = strings.ToLower(configFormat)
default:
return nil, errors.New("unknown config format")
}

dell.ConfigData = &DellConfig{
SystemConfiguration: &DellSystemConfiguration{},
}

return dell, nil
}

// FindComponent locates an existing DellComponent if one exists in the ConfigData, if not
// it creates one and returns a pointer to that.
func (cm *DellVendorConfigManager) FindComponent(fqdd string) (c *DellComponent) {
for _, c = range cm.ConfigData.SystemConfiguration.Components {
if c.FQDD == fqdd {
return
}
}

c.FQDD = fqdd

cm.ConfigData.SystemConfiguration.Components = append(cm.ConfigData.SystemConfiguration.Components, c)

return
}

// FindComponentAttribute locates an existing DellComponentAttribute if one exists in the
// ConfigData, if not it creates one and returns a pointer to that.
func (cm *DellVendorConfigManager) FindComponentAttribute(c *DellComponent, name string) (a *DellComponentAttribute) {
for _, a = range c.Attributes {
if a.Name == name {
return
}
}

a.Name = name

c.Attributes = append(c.Attributes, a)

return
}

func (cm *DellVendorConfigManager) Raw(name, value string, menuPath []string) {
c := cm.FindComponent(menuPath[0])
attr := cm.FindComponentAttribute(c, name)
attr.Value = value
}

func (cm *DellVendorConfigManager) Marshal() (string, error) {
switch strings.ToLower(cm.ConfigFormat) {
case "xml":
x, err := xml.Marshal(cm.ConfigData)
if err != nil {
return "", err
}

return string(x), nil
case "json":
x, err := json.Marshal(cm.ConfigData)
if err != nil {
return "", err
}

return string(x), nil
default:
return "", errUnknownConfigFormat
}
}

// Generic config options

func (cm *DellVendorConfigManager) EnableTPM() {
cm.Raw("EnableTPM", "Enabled", []string{"BIOS.Setup.1-1"})
}

func (cm *DellVendorConfigManager) EnableSRIOV() {
cm.Raw("VirtualizationMode", "SRIOV", []string{"NIC.Slot.3-1-1"})
}
9 changes: 9 additions & 0 deletions config/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package config

type VendorConfigManager interface {
EnableTPM()
EnableSRIOV()

Raw(name, value string, menuPath []string)
Marshal() (string, error)
}
132 changes: 132 additions & 0 deletions config/supermicro/supermicro.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package config

import (
"encoding/xml"
"errors"
"strings"

"github.com/bmc-toolbox/common/config"
)

var errUnknownConfigFormat = errors.New("unknown config format")

type SupermicroVendorConfigManager struct {
ConfigFormat string
ConfigData *SupermicroConfig
}

type SupermicroConfig struct {
BiosCfg *SupermicroBiosCfg `xml:"BiosCfg"`
}

type SupermicroBiosCfg struct {
XMLName xml.Name `xml:"BiosCfg"`
Menus []*SupermicroBiosCfgMenu `xml:"Menu"`
}

type SupermicroBiosCfgMenu struct {
XMLName xml.Name `xml:"Menu"`
Name string `xml:"name,attr"`
Settings []*SupermicroBiosCfgSetting `xml:"Setting"`
Menus []*SupermicroBiosCfgMenu `xml:"Menu"`
}

type SupermicroBiosCfgSetting struct {
XMLName xml.Name `xml:"Setting"`
Name string `xml:"Name,attr"`
Order string `xml:"order,attr"`
SelectedOption string `xml:"selectedOption,attr"`
Type string `xml:"type,attr"`
}

func New(configFormat string) (config.VendorConfigManager, error) {
supermicro := &SupermicroVendorConfigManager{}

switch strings.ToLower(configFormat) {
case "xml":
supermicro.ConfigFormat = strings.ToLower(configFormat)
default:
return nil, errors.New("unknown config format")
}

supermicro.ConfigData = &SupermicroConfig{
BiosCfg: &SupermicroBiosCfg{},
}

return supermicro, nil
}

// FindMenu locates an existing SupermicroBiosCfgMenu if one exists in the ConfigData, if not
// it creates one and returns a pointer to that.
func (cm *SupermicroVendorConfigManager) FindMenu(menuName string, menuRoot *SupermicroBiosCfgMenu) (m *SupermicroBiosCfgMenu) {
// root is cm.ConfigData.BiosCfg.Menus
for _, m = range menuRoot.Menus {
if m.Name == menuName {
return
}
}

m.Name = menuName

menuRoot.Menus = append(menuRoot.Menus, m)

return
}

// FindMenuSetting locates an existing SupermicroBiosCfgSetting if one exists in the
// ConfigData, if not it creates one and returns a pointer to that.
func (cm *SupermicroVendorConfigManager) FindMenuSetting(m *SupermicroBiosCfgMenu, name string) (s *SupermicroBiosCfgSetting) {
for _, s = range m.Settings {
if s.Name == name {
return
}
}

s.Name = name

m.Settings = append(m.Settings, s)

return
}

// TODO(jwb) How do we handle the random nature of sub menus here.. we could make the user pass the explicit pointer to a menu struct, or..
func (cm *SupermicroVendorConfigManager) Raw(name string, value string, menuPath []string) {

Check failure on line 93 in config/supermicro/supermicro.go

View workflow job for this annotation

GitHub Actions / lint

paramTypeCombine: func(name string, value string, menuPath []string) could be replaced with func(name, value string, menuPath []string) (gocritic)

Check failure on line 93 in config/supermicro/supermicro.go

View workflow job for this annotation

GitHub Actions / lint

paramTypeCombine: func(name string, value string, menuPath []string) could be replaced with func(name, value string, menuPath []string) (gocritic)
var menus []*SupermicroBiosCfgMenu

Check failure on line 94 in config/supermicro/supermicro.go

View workflow job for this annotation

GitHub Actions / lint

Consider pre-allocating `menus` (prealloc)

Check failure on line 94 in config/supermicro/supermicro.go

View workflow job for this annotation

GitHub Actions / lint

Consider pre-allocating `menus` (prealloc)

for i, name := range menuPath {
var m *SupermicroBiosCfgMenu

if i == 0 {
m = cm.FindMenu(name, cm.ConfigData.BiosCfg.Menus[0])
} else {
m = cm.FindMenu(name, menus[i-1])
}

menus = append(menus, m)
}
}

func (cm *SupermicroVendorConfigManager) Marshal() (string, error) {
switch strings.ToLower(cm.ConfigFormat) {
case "xml":
x, err := xml.Marshal(cm.ConfigData)
if err != nil {
return "", err
}

return string(x), nil
default:
return "", errUnknownConfigFormat
}
}

// Generic config options

func (cm *SupermicroVendorConfigManager) EnableTPM() {
cm.Raw(" Security Device Support", "Enable", []string{"Trusted Computing"})
cm.Raw(" SHA-1 PCR Bank", "Enabled", []string{"Trusted Computing"})
}

func (cm *SupermicroVendorConfigManager) EnableSRIOV() {
cm.Raw("SR-IOV Support", "Enabled", []string{"Advanced", "PCIe/PCI/PnP Configuration"})
}

0 comments on commit 34ae332

Please sign in to comment.