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 Dec 4, 2023
1 parent 5eb9915 commit 0af8836
Show file tree
Hide file tree
Showing 4 changed files with 393 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 asrockrack

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

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

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

type vendorConfig 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 := &vendorConfig{}

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 *vendorConfig) 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 *vendorConfig) 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 *vendorConfig) 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 *vendorConfig) 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 *vendorConfig) EnableTPM() {
// Unimplemented
}

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

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

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

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

type vendorConfig struct {
ConfigFormat string
ConfigData *dellConfig
}

type dellConfig struct {
SystemConfiguration *dellSystemConfiguration `xml:"SystemConfiguration" json:"SystemConfiguration"`
}

type dellSystemConfiguration struct {
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 {
XMLName xml.Name `xml:"Component"`
FQDD string `xml:"FQDD,attr" json:"FQDD"`
Attributes []*dellComponentAttribute `xml:"Attribute" json:"Attributes"`
}

type dellComponentAttribute struct {
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 := &vendorConfig{}

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

Check failure on line 53 in config/dell/dell.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 53 in config/dell/dell.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)
}

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 *vendorConfig) 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 *vendorConfig) 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 *vendorConfig) Raw(name, value string, menuPath []string) {
c := cm.FindComponent(menuPath[0])
attr := cm.FindComponentAttribute(c, name)
attr.Value = value
}

func (cm *vendorConfig) 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 *vendorConfig) EnableTPM() {
cm.Raw("EnableTPM", "Enabled", []string{"BIOS.Setup.1-1"})
}

func (cm *vendorConfig) EnableSRIOV() {
// TODO(jwb) How do we want to handle enabling this for different NICs
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 supermicro

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

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

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

type vendorConfig 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 := &vendorConfig{}

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

Check failure on line 49 in config/supermicro/supermicro.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/supermicro/supermicro.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)
}

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 *vendorConfig) 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 *vendorConfig) 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 *vendorConfig) Raw(name, value string, menuPath []string) {
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 *vendorConfig) 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 *vendorConfig) EnableTPM() {
cm.Raw(" Security Device Support", "Enable", []string{"Trusted Computing"})
cm.Raw(" SHA-1 PCR Bank", "Enabled", []string{"Trusted Computing"})
}

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

0 comments on commit 0af8836

Please sign in to comment.