Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
joelrebel committed Oct 31, 2023
1 parent f845db0 commit 71e9ae8
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 63 deletions.
44 changes: 22 additions & 22 deletions bmc/firmware.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type FirmwareInstaller interface {
//
// return values:
// taskID - A taskID is returned if the update process on the BMC returns an identifier for the update process.
FirmwareInstall(ctx context.Context, component string, operationApplyTime constants.OperationApplyTime, forceInstall bool, reader io.Reader) (taskID string, err error)
FirmwareInstall(ctx context.Context, component string, operationApplyTime string, forceInstall bool, reader io.Reader) (taskID string, err error)
}

// firmwareInstallerProvider is an internal struct to correlate an implementation/provider and its name
Expand All @@ -34,7 +34,7 @@ type firmwareInstallerProvider struct {
}

// firmwareInstall uploads and initiates firmware update for the component
func firmwareInstall(ctx context.Context, component string, operationApplyTime constants.OperationApplyTime, forceInstall bool, reader io.Reader, generic []firmwareInstallerProvider) (taskID string, metadata Metadata, err error) {
func firmwareInstall(ctx context.Context, component, operationApplyTime string, forceInstall bool, reader io.Reader, generic []firmwareInstallerProvider) (taskID string, metadata Metadata, err error) {
var metadataLocal Metadata

for _, elem := range generic {
Expand Down Expand Up @@ -64,7 +64,7 @@ func firmwareInstall(ctx context.Context, component string, operationApplyTime c
}

// FirmwareInstallFromInterfaces identifies implementations of the FirmwareInstaller interface and passes the found implementations to the firmwareInstall() wrapper
func FirmwareInstallFromInterfaces(ctx context.Context, component string, operationApplyTime constants.OperationApplyTime, forceInstall bool, reader io.Reader, generic []interface{}) (taskID string, metadata Metadata, err error) {
func FirmwareInstallFromInterfaces(ctx context.Context, component, operationApplyTime string, forceInstall bool, reader io.Reader, generic []interface{}) (taskID string, metadata Metadata, err error) {
implementations := make([]firmwareInstallerProvider, 0)
for _, elem := range generic {
temp := firmwareInstallerProvider{name: getProviderName(elem)}
Expand Down Expand Up @@ -250,27 +250,27 @@ func FirmwareInstallWithOptionsFromInterfaces(ctx context.Context, component str
return firmwareInstallWithOptions(ctx, component, reader, opts, implementations)
}

type FirmwareActionsGetter interface {
FirmwareInstallActions(ctx context.Context, component string) ([]constants.FirmwareAction, error)
type FirmwareInstallStepsGetter interface {
FirmwareInstallSteps(ctx context.Context, component string) ([]constants.FirmwareInstallStep, error)
}

// firmwareInstallActionsGetterProvider is an internal struct to correlate an implementation/provider and its name
type firmwareInstallActionsGetterProvider struct {
// firmwareInstallStepsGetterProvider is an internal struct to correlate an implementation/provider and its name
type firmwareInstallStepsGetterProvider struct {
name string
FirmwareActionsGetter
FirmwareInstallStepsGetter
}

// FirmwareActionsFromInterfaces identifies implementations of the FirmwareActionsGetter interface and passes the found implementations to the firmwareInstallActions() wrapper.
func FirmwareActionsFromInterfaces(ctx context.Context, component string, generic []interface{}) (steps []constants.FirmwareAction, metadata Metadata, err error) {
implementations := make([]firmwareInstallActionsGetterProvider, 0)
// FirmwareInstallStepsFromInterfaces identifies implementations of the FirmwareInstallStepsGetter interface and passes the found implementations to the firmwareInstallSteps() wrapper.
func FirmwareInstallStepsFromInterfaces(ctx context.Context, component string, generic []interface{}) (steps []constants.FirmwareInstallStep, metadata Metadata, err error) {
implementations := make([]firmwareInstallStepsGetterProvider, 0)
for _, elem := range generic {
temp := firmwareInstallActionsGetterProvider{name: getProviderName(elem)}
temp := firmwareInstallStepsGetterProvider{name: getProviderName(elem)}
switch p := elem.(type) {
case FirmwareActionsGetter:
temp.FirmwareActionsGetter = p
case FirmwareInstallStepsGetter:
temp.FirmwareInstallStepsGetter = p
implementations = append(implementations, temp)
default:
e := fmt.Sprintf("not a FirmwareActionsGetter implementation: %T", p)
e := fmt.Sprintf("not a FirmwareInstallStepsGetter implementation: %T", p)
err = multierror.Append(err, errors.New(e))
}
}
Expand All @@ -279,19 +279,19 @@ func FirmwareActionsFromInterfaces(ctx context.Context, component string, generi
err,
errors.Wrap(
bmclibErrs.ErrProviderImplementation,
("no FirmwareActionsGetter implementations found"),
("no FirmwareInstallStepsGetter implementations found"),
),
)
}

return firmwareInstallActions(ctx, component, implementations)
return firmwareInstallSteps(ctx, component, implementations)
}

func firmwareInstallActions(ctx context.Context, component string, generic []firmwareInstallActionsGetterProvider) (steps []constants.FirmwareAction, metadata Metadata, err error) {
func firmwareInstallSteps(ctx context.Context, component string, generic []firmwareInstallStepsGetterProvider) (steps []constants.FirmwareInstallStep, metadata Metadata, err error) {
var metadataLocal Metadata

for _, elem := range generic {
if elem.FirmwareActionsGetter == nil {
if elem.FirmwareInstallStepsGetter == nil {
continue
}
select {
Expand All @@ -301,7 +301,7 @@ func firmwareInstallActions(ctx context.Context, component string, generic []fir
return steps, metadata, err
default:
metadataLocal.ProvidersAttempted = append(metadataLocal.ProvidersAttempted, elem.name)
steps, vErr := elem.FirmwareInstallActions(ctx, component)
steps, vErr := elem.FirmwareInstallSteps(ctx, component)
if vErr != nil {
err = multierror.Append(err, errors.WithMessagef(vErr, "provider: %v", elem.name))
err = multierror.Append(err, vErr)
Expand All @@ -313,7 +313,7 @@ func firmwareInstallActions(ctx context.Context, component string, generic []fir
}
}

return steps, metadataLocal, multierror.Append(err, errors.New("failure in FirmwareActions"))
return steps, metadataLocal, multierror.Append(err, errors.New("failure in FirmwareInstallSteps"))
}

type FirmwareUploader interface {
Expand All @@ -327,7 +327,7 @@ type firmwareUploaderProvider struct {
}

// FirmwareUploaderFromInterfaces identifies implementations of the FirmwareUploader interface and passes the found implementations to the firmwareUpload() wrapper.
func FirmwareUploaderFromInterfaces(ctx context.Context, component string, reader io.Reader, generic []interface{}) (taskID string, metadata Metadata, err error) {
func FirmwareUploadFromInterfaces(ctx context.Context, component string, reader io.Reader, generic []interface{}) (taskID string, metadata Metadata, err error) {
implementations := make([]firmwareUploaderProvider, 0)
for _, elem := range generic {
temp := firmwareUploaderProvider{name: getProviderName(elem)}
Expand Down
10 changes: 5 additions & 5 deletions bmc/firmware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ func TestFirmwareInstall(t *testing.T) {
providerName string
providersAttempted int
}{
{"success with metadata", common.SlugBIOS, constants.OnReset, false, nil, "1234", nil, 5 * time.Second, "foo", 1},
{"failure with metadata", common.SlugBIOS, constants.OnReset, false, nil, "1234", errors.ErrNon200Response, 5 * time.Second, "foo", 1},
{"failure with context timeout", common.SlugBIOS, constants.OnReset, false, nil, "1234", context.DeadlineExceeded, 1 * time.Nanosecond, "foo", 1},
{"success with metadata", common.SlugBIOS, string(constants.OnReset), false, nil, "1234", nil, 5 * time.Second, "foo", 1},
{"failure with metadata", common.SlugBIOS, string(constants.OnReset), false, nil, "1234", errors.ErrNon200Response, 5 * time.Second, "foo", 1},
{"failure with context timeout", common.SlugBIOS, string(constants.OnReset), false, nil, "1234", context.DeadlineExceeded, 1 * time.Nanosecond, "foo", 1},
}

for _, tc := range testCases {
Expand Down Expand Up @@ -79,8 +79,8 @@ func TestFirmwareInstallFromInterfaces(t *testing.T) {
providerName string
badImplementation bool
}{
{"success with metadata", common.SlugBIOS, constants.OnReset, false, nil, "1234", nil, "foo", false},
{"failure with metadata", common.SlugBIOS, constants.OnReset, false, nil, "1234", bmclibErrs.ErrProviderImplementation, "foo", true},
{"success with metadata", common.SlugBIOS, string(constants.OnReset), false, nil, "1234", nil, "foo", false},
{"failure with metadata", common.SlugBIOS, string(constants.OnReset), false, nil, "1234", bmclibErrs.ErrProviderImplementation, "foo", true},
}

for _, tc := range testCases {
Expand Down
23 changes: 22 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ func (c *Client) GetBiosConfiguration(ctx context.Context) (biosConfig map[strin
}

// FirmwareInstall pass through library function to upload firmware and install firmware
func (c *Client) FirmwareInstall(ctx context.Context, component string, operationApplyTime constants.OperationApplyTime, forceInstall bool, reader io.Reader) (taskID string, err error) {
func (c *Client) FirmwareInstall(ctx context.Context, component string, operationApplyTime string, forceInstall bool, reader io.Reader) (taskID string, err error) {
taskID, metadata, err := bmc.FirmwareInstallFromInterfaces(ctx, component, operationApplyTime, forceInstall, reader, c.registry().GetDriverInterfaces())
c.setMetadata(metadata)
return taskID, err
Expand Down Expand Up @@ -453,3 +453,24 @@ func (c *Client) ClearSystemEventLog(ctx context.Context) (err error) {
c.setMetadata(metadata)
return err
}

// FirmwareInstallSteps return the order of actions required install firmware for a component.
func (c *Client) FirmwareInstallSteps(ctx context.Context, component string) (actions []constants.FirmwareInstallStep, err error) {
status, metadata, err := bmc.FirmwareInstallStepsFromInterfaces(ctx, component, c.registry().GetDriverInterfaces())
c.setMetadata(metadata)
return status, err
}

// FirmwareInstallWithOptions kicks off firmware install, it is to deprecate the existing FirmwareInstall interface method.
func (c *Client) FirmwareInstallWithOptions(ctx context.Context, component string, reader io.Reader, opts *bmc.FirmwareInstallOptions) (installTaskID string, err error) {
installTaskID, metadata, err := bmc.FirmwareInstallWithOptionsFromInterfaces(ctx, component, reader, opts, c.registry().GetDriverInterfaces())
c.setMetadata(metadata)
return installTaskID, err
}

// FirmwareUpload just uploads the firmware for install, it returns a task ID to verify the upload status.
func (c *Client) FirmwareUpload(ctx context.Context, component string, reader io.Reader) (uploadVerifyTaskID string, err error) {
uploadVerifyTaskID, metadata, err := bmc.FirmwareUploadFromInterfaces(ctx, component, reader, c.Registry.GetDriverInterfaces())
c.setMetadata(metadata)
return uploadVerifyTaskID, err
}
16 changes: 8 additions & 8 deletions constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package constants
type (
OperationApplyTime string

// The FirmwareAction identifies each phase of a firmware install process.
FirmwareAction string
// The FirmwareInstallStep identifies each phase of a firmware install process.
FirmwareInstallStep string
)

const (
Expand Down Expand Up @@ -74,13 +74,13 @@ const (

FirmwareInstallUnknown = "unknown"

// FirmwareActionUpload is an identifier for the firmware upload step in the firmware install process.
FirmwareActionUpload = "upload"
FirmwareActionVerifyUpload = "verify-upload"
// FirmwareInstallStepUpload is an identifier for the firmware upload step in the firmware install process.
FirmwareInstallStepUpload FirmwareInstallStep = "upload"
FirmwareInstallStepUploadStatus FirmwareInstallStep = "upload-status"

// FirmwareActionInstall is an identifier for the firmware install step after a firmware has been uploaded.
FirmwareActionInstall = "install"
FirmwareActionVerifyInstall = "verify-install"
// FirmwareInstallStepInstall is an identifier for the firmware install step after a firmware has been uploaded.
FirmwareInstallStepInstall FirmwareInstallStep = "install"
FirmwareInstallStepInstallStatus FirmwareInstallStep = "install-status"

// device BIOS/UEFI POST code bmclib identifiers
POSTStateBootINIT = "boot-init/pxe"
Expand Down
2 changes: 1 addition & 1 deletion examples/install-firmware/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func main() {
}
defer fh.Close()

taskID, err := cl.FirmwareInstall(ctx, *component, constants.OnReset, true, fh)
taskID, err := cl.FirmwareInstall(ctx, *component, string(constants.OnReset), true, fh)
if err != nil {
l.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions providers/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ const (
// FeatureClearSystemEventLog means an implementation that clears the BMC System Event Log (SEL)
FeatureClearSystemEventLog registrar.Feature = "clearsystemeventlog"

// FeatureFirmwareActions means an implementation returns the steps part of the firmware update process.
FeatureFirmwareActions registrar.Feature = "firmwareinstallactions"
// FeatureFirmwareInstallSteps means an implementation returns the steps part of the firmware update process.
FeatureFirmwareInstallSteps registrar.Feature = "firmwareinstallactions"

// FeatureFirmwareUpload means an implementation that uploads firmware for installing.
FeatureFirmwareUpload registrar.Feature = "firmwareupload"
Expand Down
4 changes: 2 additions & 2 deletions providers/supermicro/firmware.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ var (
errUploadTaskIDExpected = errors.New("expected an firmware upload taskID")
)

func (c *Client) FirmwareInstallActions(ctx context.Context, component string) ([]constants.FirmwareAction, error) {
func (c *Client) FirmwareInstallSteps(ctx context.Context, component string) ([]constants.FirmwareInstallStep, error) {
if err := c.firmwareInstallSupported(ctx); err != nil {
return nil, err
}

switch {
case strings.HasPrefix(strings.ToLower(c.model), "x12"):
return c.x12().firmwareInstallActions(component)
return c.x12().firmwareInstallSteps(component)
case strings.HasPrefix(strings.ToLower(c.model), "x11"):
//return c.x11().statusBMCFirmwareInstall(ctx)
}
Expand Down
7 changes: 5 additions & 2 deletions providers/supermicro/test/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@ func main() {
defer c.Close(ctx)

// open file handle
fh, err := os.Open("BMC_X12AST2600-F201MS_20220627_1.13.04_STDsp.bin")
//f := "BMC_X12AST2600-F201MS_20220627_1.13.04_STDsp.bin"
f := "BIOS_X12STH-1C3A_20230607_1.6_STDsp.bin"
fh, err := os.Open(f)
if err != nil {
l.Fatal(err)
}
defer fh.Close()

component := common.SlugBMC
// component := common.SlugBMC
component := common.SlugBIOS

uploadTaskID, err := c.FirmwareUpload(ctx, component, fh)
if err != nil {
Expand Down
42 changes: 22 additions & 20 deletions providers/supermicro/x12_firmware.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,34 @@ func (c *x12) componentSupported(component string) error {

return nil
}
func (c *x12) firmwareInstallActions(component string) ([]constants.FirmwareAction, error) {
func (c *x12) firmwareInstallSteps(component string) ([]constants.FirmwareInstallStep, error) {
errComponentNotSupported := errors.New("firmware install for component on x12 hardware not supported")

switch component {
case common.SlugBMC:
return c.firmwareInstallActionsBMC()
return c.firmwareInstallStepsBMC()
case common.SlugBIOS:
return c.firmwareInstallActionsBIOS()
return c.firmwareInstallStepsBIOS()
default:
return nil, errors.Wrap(errComponentNotSupported, component)
}
}

func (c *x12) firmwareInstallActionsBIOS() ([]constants.FirmwareAction, error) {
return []constants.FirmwareAction{
constants.FirmwareActionUpload,
constants.FirmwareActionVerifyUpload,
constants.FirmwareActionInstall,
constants.FirmwareActionVerifyInstall,
func (c *x12) firmwareInstallStepsBIOS() ([]constants.FirmwareInstallStep, error) {
return []constants.FirmwareInstallStep{
constants.FirmwareInstallStepUpload,
constants.FirmwareInstallStepUploadStatus,
constants.FirmwareInstallStepInstall,
constants.FirmwareInstallStepInstallStatus,
}, nil
}

func (c *x12) firmwareInstallActionsBMC() ([]constants.FirmwareAction, error) {
return []constants.FirmwareAction{
constants.FirmwareActionUpload,
constants.FirmwareActionVerifyUpload,
constants.FirmwareActionInstall,
constants.FirmwareActionVerifyInstall,
func (c *x12) firmwareInstallStepsBMC() ([]constants.FirmwareInstallStep, error) {
return []constants.FirmwareInstallStep{
constants.FirmwareInstallStepUpload,
constants.FirmwareInstallStepUploadStatus,
constants.FirmwareInstallStepInstall,
constants.FirmwareInstallStepInstallStatus,
}, nil
}

Expand Down Expand Up @@ -198,8 +198,8 @@ type BMC struct {
}

type Supermicro struct {
BIOS `json:"BIOS,omitempty"`
BMC `json:"BMC,omitempty"`
*BIOS `json:"BIOS,omitempty"`
*BMC `json:"BMC,omitempty"`
}

type OEM struct {
Expand All @@ -213,7 +213,7 @@ func (c *x12) redfishParameters(component, targetODataID string) (*rfw.RedfishUp

switch strings.ToUpper(component) {
case common.SlugBIOS:
oem.Supermicro.BIOS = BIOS{
oem.Supermicro.BIOS = &BIOS{
PreserveME: false,
PreserveNVRAM: false,
PreserveSMBIOS: true,
Expand All @@ -224,7 +224,7 @@ func (c *x12) redfishParameters(component, targetODataID string) (*rfw.RedfishUp
PreserveBOOTCONF: true,
}
case common.SlugBMC:
oem.Supermicro.BMC = BMC{
oem.Supermicro.BMC = &BMC{
PreserveCfg: true,
PreserveSdr: true,
PreserveSsl: true,
Expand Down Expand Up @@ -252,7 +252,9 @@ func (c *x12) redfishOdataID(ctx context.Context, component string) (string, err
case common.SlugBMC:
return c.redfish.ManagerOdataID(ctx)
case common.SlugBIOS:
return c.redfish.SystemsBIOSOdataID(ctx)
// hardcoded since SMCs without the DCMS license will throw license errors
return "/redfish/v1/Systems/1/Bios", nil
//return c.redfish.SystemsBIOSOdataID(ctx)
}

return "", errUnsupported
Expand Down

0 comments on commit 71e9ae8

Please sign in to comment.