From 81bff4b7a1c2f0dc8b0d66cad332412ef96cf5b5 Mon Sep 17 00:00:00 2001 From: "James W. Brinkerhoff" Date: Tue, 28 May 2024 09:26:39 -0400 Subject: [PATCH] FS-1123: Supermicro (SMC) BIOS config Get, Set and Reset support via SUM --- client.go | 24 +++++++++++++++++++ examples/bios/main.go | 37 ++++++++++++++++++++++++++++-- providers/providers.go | 3 +++ providers/redfish/redfish.go | 8 +++++++ providers/supermicro/firmware.go | 8 +++---- providers/supermicro/supermicro.go | 2 +- 6 files changed, 75 insertions(+), 7 deletions(-) diff --git a/client.go b/client.go index e9bd76ca..7ed7d5aa 100644 --- a/client.go +++ b/client.go @@ -23,6 +23,7 @@ import ( "github.com/bmc-toolbox/bmclib/v2/providers/openbmc" "github.com/bmc-toolbox/bmclib/v2/providers/redfish" "github.com/bmc-toolbox/bmclib/v2/providers/rpc" + "github.com/bmc-toolbox/bmclib/v2/providers/sum" "github.com/bmc-toolbox/bmclib/v2/providers/supermicro" "github.com/bmc-toolbox/common" "github.com/go-logr/logr" @@ -72,6 +73,7 @@ type providerConfig struct { supermicro supermicro.Config rpc rpc.Provider openbmc openbmc.Config + sum sum.Exec } // NewClient returns a new Client struct @@ -109,6 +111,7 @@ func NewClient(host, user, pass string, opts ...Option) *Client { openbmc: openbmc.Config{ Port: "443", }, + sum: sum.Exec{}, }, } @@ -262,6 +265,23 @@ func (c *Client) registerOpenBMCProvider() { c.Registry.Register(openbmc.ProviderName, openbmc.ProviderProtocol, openbmc.Features, nil, driver) } +// register sum provider +func (c *Client) registerSumProvider() error { + sumOpts := []sum.Option{ + sum.WithLogger(c.Logger), + sum.WithSumPath(c.providerConfig.sum.SumPath), + } + + driverSum, err := sum.New(c.Auth.Host, c.Auth.User, c.Auth.Pass, sumOpts...) + if err != nil { + return err + } + + c.Registry.Register(sum.ProviderName, sum.ProviderProtocol, sum.Features, nil, driverSum) + + return nil +} + func (c *Client) registerProviders() { // register the rpc provider // without the consumer URL there is no way to send RPC requests. @@ -279,6 +299,10 @@ func (c *Client) registerProviders() { c.Logger.Info("ipmitool provider not available", "error", err.Error()) } + if err := c.registerSumProvider(); err != nil { + c.Logger.Info("sum provider not available", "error", err.Error()) + } + c.registerASRRProvider() c.registerGofishProvider() c.registerIntelAMTProvider() diff --git a/examples/bios/main.go b/examples/bios/main.go index 16def4aa..3acd683b 100644 --- a/examples/bios/main.go +++ b/examples/bios/main.go @@ -32,14 +32,19 @@ func main() { // Logger configuration l := logrus.New() - l.Level = logrus.DebugLevel + // l.Level = logrus.TraceLevel logger := logrusr.New(l) + logger.V(9) // bmclib client abstraction clientOpts := []bmclib.Option{bmclib.WithLogger(logger)} client := bmclib.NewClient(*host, *user, *pass, clientOpts...) - client.Registry.Drivers = client.Registry.Supports(providers.FeatureGetBiosConfiguration, providers.FeatureSetBiosConfiguration, providers.FeatureResetBiosConfiguration) + client.Registry.Drivers = client.Registry.Supports( + providers.FeatureGetBiosConfiguration, + providers.FeatureSetBiosConfiguration, + providers.FeatureResetBiosConfiguration, + providers.FeatureSetBiosConfigurationFromFile) err := client.Open(ctx) if err != nil { @@ -82,6 +87,34 @@ func main() { fmt.Println("Attempting to set BIOS configuration:") fmt.Printf("exampleConfig: %+v\n", exampleConfig) + err := client.SetBiosConfiguration(ctx, exampleConfig) + if err != nil { + l.Error(err) + } + case "setfile": + exampleConfig := make(map[string]string) + + if *dfile != "" { + jsonFile, err := os.Open(*dfile) + if err != nil { + l.Fatal(err) + } + + defer jsonFile.Close() + + jsonData, _ := io.ReadAll(jsonFile) + + err = json.Unmarshal(jsonData, &exampleConfig) + if err != nil { + l.Fatal(err) + } + } else { + exampleConfig["TpmSecurity"] = "Off" + } + + fmt.Println("Attempting to set BIOS configuration:") + fmt.Printf("exampleConfig: %+v\n", exampleConfig) + err := client.SetBiosConfiguration(ctx, exampleConfig) if err != nil { l.Error(err) diff --git a/providers/providers.go b/providers/providers.go index 0699e7cb..2791c777 100644 --- a/providers/providers.go +++ b/providers/providers.go @@ -70,6 +70,9 @@ const ( // FeatureSetBiosConfiguration means an implementation that can set bios configuration from an input k/v map FeatureSetBiosConfiguration registrar.Feature = "setbiosconfig" + // FeatureSetBiosConfigurationFromFile means an implementation that can set bios configuration from a vendor specific text file + FeatureSetBiosConfigurationFromFile registrar.Feature = "setbiosconfigfile" + // FeatureGetBiosConfiguration means an implementation that can get bios configuration in a simple k/v map FeatureGetBiosConfiguration registrar.Feature = "getbiosconfig" ) diff --git a/providers/redfish/redfish.go b/providers/redfish/redfish.go index 1541feb2..89830272 100644 --- a/providers/redfish/redfish.go +++ b/providers/redfish/redfish.go @@ -36,6 +36,9 @@ var ( providers.FeatureInventoryRead, providers.FeatureBmcReset, providers.FeatureClearSystemEventLog, + providers.FeatureGetBiosConfiguration, + providers.FeatureSetBiosConfiguration, + providers.FeatureResetBiosConfiguration, } ) @@ -223,6 +226,11 @@ func (c *Conn) SetBiosConfiguration(ctx context.Context, biosConfig map[string]s return c.redfishwrapper.SetBiosConfiguration(ctx, biosConfig) } +// ResetBiosConfiguration set bios configuration +func (c *Conn) ResetBiosConfiguration(ctx context.Context) (err error) { + return c.redfishwrapper.ResetBiosConfiguration(ctx) +} + // SendNMI tells the BMC to issue an NMI to the device func (c *Conn) SendNMI(ctx context.Context) error { return c.redfishwrapper.SendNMI(ctx) diff --git a/providers/supermicro/firmware.go b/providers/supermicro/firmware.go index 2deebd32..379a17f4 100644 --- a/providers/supermicro/firmware.go +++ b/providers/supermicro/firmware.go @@ -34,7 +34,7 @@ var ( // bmc client interface implementations methods func (c *Client) FirmwareInstallSteps(ctx context.Context, component string) ([]constants.FirmwareInstallStep, error) { - if err := c.serviceClient.supportsFirmwareInstall(ctx, c.bmc.deviceModel()); err != nil { + if err := c.serviceClient.supportsFirmwareInstall(c.bmc.deviceModel()); err != nil { return nil, err } @@ -42,7 +42,7 @@ func (c *Client) FirmwareInstallSteps(ctx context.Context, component string) ([] } func (c *Client) FirmwareUpload(ctx context.Context, component string, file *os.File) (taskID string, err error) { - if err := c.serviceClient.supportsFirmwareInstall(ctx, c.bmc.deviceModel()); err != nil { + if err := c.serviceClient.supportsFirmwareInstall(c.bmc.deviceModel()); err != nil { return "", err } @@ -56,7 +56,7 @@ func (c *Client) FirmwareUpload(ctx context.Context, component string, file *os. } func (c *Client) FirmwareInstallUploaded(ctx context.Context, component, uploadTaskID string) (installTaskID string, err error) { - if err := c.serviceClient.supportsFirmwareInstall(ctx, c.bmc.deviceModel()); err != nil { + if err := c.serviceClient.supportsFirmwareInstall(c.bmc.deviceModel()); err != nil { return "", err } @@ -70,7 +70,7 @@ func (c *Client) FirmwareInstallUploaded(ctx context.Context, component, uploadT // FirmwareTaskStatus returns the status of a firmware related task queued on the BMC. func (c *Client) FirmwareTaskStatus(ctx context.Context, kind constants.FirmwareInstallStep, component, taskID, installVersion string) (state constants.TaskState, status string, err error) { - if err := c.serviceClient.supportsFirmwareInstall(ctx, c.bmc.deviceModel()); err != nil { + if err := c.serviceClient.supportsFirmwareInstall(c.bmc.deviceModel()); err != nil { return "", "", errors.Wrap(bmclibErrs.ErrFirmwareInstallStatus, err.Error()) } diff --git a/providers/supermicro/supermicro.go b/providers/supermicro/supermicro.go index 2ba88d33..902aa94f 100644 --- a/providers/supermicro/supermicro.go +++ b/providers/supermicro/supermicro.go @@ -426,7 +426,7 @@ func (c *serviceClient) redfishSession(ctx context.Context) (err error) { return nil } -func (c *serviceClient) supportsFirmwareInstall(ctx context.Context, model string) error { +func (c *serviceClient) supportsFirmwareInstall(model string) error { if model == "" { return errors.Wrap(ErrModelUnknown, "unable to determine firmware install compatibility") }