Skip to content

Commit

Permalink
Merge branch 'main' into get-systemeventlog
Browse files Browse the repository at this point in the history
  • Loading branch information
mattcburns authored Dec 6, 2023
2 parents de61fa1 + 1063371 commit f7408e4
Show file tree
Hide file tree
Showing 16 changed files with 585 additions and 139 deletions.
21 changes: 21 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/bmc-toolbox/bmclib/v2/providers/dell"
"github.com/bmc-toolbox/bmclib/v2/providers/intelamt"
"github.com/bmc-toolbox/bmclib/v2/providers/ipmitool"
"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/supermicro"
Expand Down Expand Up @@ -71,6 +72,7 @@ type providerConfig struct {
dell dell.Config
supermicro supermicro.Config
rpc rpc.Provider
openbmc openbmc.Config
}

// NewClient returns a new Client struct
Expand Down Expand Up @@ -105,6 +107,9 @@ func NewClient(host, user, pass string, opts ...Option) *Client {
Port: "443",
},
rpc: rpc.Provider{},
openbmc: openbmc.Config{
Port: "443",
},
},
}

Expand Down Expand Up @@ -243,6 +248,21 @@ func (c *Client) registerSupermicroProvider() {
c.Registry.Register(supermicro.ProviderName, supermicro.ProviderProtocol, supermicro.Features, nil, driverSupermicro)
}

func (c *Client) registerOpenBMCProvider() {
httpClient := *c.httpClient
httpClient.Transport = c.httpClient.Transport.(*http.Transport).Clone()
driver := openbmc.New(
c.Auth.Host,
c.Auth.User,
c.Auth.Pass,
c.Logger,
openbmc.WithHttpClient(&httpClient),
openbmc.WithPort(c.providerConfig.openbmc.Port),
)

c.Registry.Register(openbmc.ProviderName, openbmc.ProviderProtocol, openbmc.Features, nil, driver)
}

func (c *Client) registerProviders() {
// register the rpc provider
// without the consumer URL there is no way to send RPC requests.
Expand All @@ -265,6 +285,7 @@ func (c *Client) registerProviders() {
c.registerIntelAMTProvider()
c.registerDellProvider()
c.registerSupermicroProvider()
c.registerOpenBMCProvider()
}

// GetMetadata returns the metadata that is populated after each BMC function/method call
Expand Down
10 changes: 6 additions & 4 deletions constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@ const (
FirmwareInstallPowerCycleHost = "powercycle-host"
PowerCycleHost TaskState = "powercycle-host"

// FirmwareInstallPowerCycleBMC indicates the firmware install requires a BMC power cycle
FirmwareInstallPowerCycleBMC = "powercycle-bmc"
PowerCycleBMC TaskState = "powercycle-bmc"

FirmwareInstallUnknown = "unknown"
Unknown TaskState = "unknown"

Expand All @@ -103,6 +99,12 @@ const (
// FirmwareInstallStepPowerOffHost indicates the host requires to be powered off.
FirmwareInstallStepPowerOffHost FirmwareInstallStep = "power-off-host"

// FirmwareInstallStepResetBMCPostInstall indicates the BMC requires a reset after the install.
FirmwareInstallStepResetBMCPostInstall FirmwareInstallStep = "reset-bmc-post-install"

// FirmwareInstallStepResetBMCOnInstallFailure indicates the BMC requires a reset if an install fails.
FirmwareInstallStepResetBMCOnInstallFailure FirmwareInstallStep = "reset-bmc-on-install-failure"

// device BIOS/UEFI POST code bmclib identifiers
POSTStateBootINIT = "boot-init/pxe"
POSTStateUEFI = "uefi"
Expand Down
3 changes: 3 additions & 0 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ var (

// ErrRedfishNoSystems is returned when the API of the device provides and empty array of systems.
ErrRedfishNoSystems = errors.New("redfish: no Systems were found on the device")

// ErrBMCUpdating is returned when the BMC is going through an update and will not serve other queries.
ErrBMCUpdating = errors.New("a BMC firmware update is in progress")
)

type ErrUnsupportedHardware struct {
Expand Down
67 changes: 50 additions & 17 deletions providers/asrockrack/asrockrack.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,46 @@
package asrockrack

import (
"bytes"
"context"
"crypto/x509"
"fmt"
"net/http"
"strings"

"github.com/bmc-toolbox/bmclib/v2/constants"
"github.com/bmc-toolbox/bmclib/v2/internal/httpclient"
"github.com/bmc-toolbox/bmclib/v2/providers"
"github.com/bmc-toolbox/common"
"github.com/go-logr/logr"
"github.com/jacobweinstock/registrar"
"github.com/pkg/errors"
)

const (
// ProviderName for the provider implementation
ProviderName = "asrockrack"
// ProviderProtocol for the provider implementation
ProviderProtocol = "vendorapi"

E3C256D4ID_NL = "E3C256D4ID-NL"
E3C246D4ID_NL = "E3C246D4ID-NL"
E3C246D4I_NL = "E3C246D4I-NL"
)

var (
// Features implemented by asrockrack https
Features = registrar.Features{
providers.FeatureInventoryRead,
providers.FeatureFirmwareInstall,
providers.FeatureFirmwareInstallStatus,
providers.FeaturePostCodeRead,
providers.FeatureBmcReset,
providers.FeatureUserCreate,
providers.FeatureUserUpdate,
providers.FeatureFirmwareUpload,
providers.FeatureFirmwareInstallUploaded,
providers.FeatureFirmwareTaskStatus,
providers.FeatureFirmwareInstallSteps,
providers.FeatureInventoryRead,
providers.FeaturePowerSet,
providers.FeaturePowerState,
}
)

Expand All @@ -38,6 +49,7 @@ type ASRockRack struct {
ip string
username string
password string
deviceModel string
loginSession *loginSession
httpClient *http.Client
resetRequired bool // Indicates if the BMC requires a reset
Expand Down Expand Up @@ -100,24 +112,45 @@ func (a *ASRockRack) Name() string {
return ProviderName
}

// Compatible implements the registrar.Verifier interface
// returns true if the BMC is identified to be an asrockrack
func (a *ASRockRack) Compatible(ctx context.Context) bool {
resp, statusCode, err := a.queryHTTPS(ctx, "/", "GET", nil, nil, 0)
if err != nil {
return false
// Open a connection to a BMC, implements the Opener interface
func (a *ASRockRack) Open(ctx context.Context) (err error) {
if err := a.httpsLogin(ctx); err != nil {
return err
}

if statusCode != 200 {
return false
return a.supported(ctx)
}

func (a *ASRockRack) supported(ctx context.Context) error {
supported := []string{
E3C256D4ID_NL,
E3C246D4ID_NL,
E3C246D4I_NL,
}

return bytes.Contains(resp, []byte(`ASRockRack`))
}
if a.deviceModel == "" {
device := common.NewDevice()
device.Metadata = map[string]string{}

// Open a connection to a BMC, implements the Opener interface
func (a *ASRockRack) Open(ctx context.Context) (err error) {
return a.httpsLogin(ctx)
err := a.fruAttributes(ctx, &device)
if err != nil {
return errors.Wrap(err, "failed to identify device model")
}

if device.Model == "" {
return errors.Wrap(err, "failed to identify device model - empty model attribute")
}

a.deviceModel = device.Model
}

for _, s := range supported {
if strings.EqualFold(a.deviceModel, s) {
return nil
}
}

return fmt.Errorf("device model not supported: %s", a.deviceModel)
}

// Close a connection to a BMC, implements the Closer interface
Expand Down
19 changes: 8 additions & 11 deletions providers/asrockrack/asrockrack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,12 @@ import (
"context"
"os"
"testing"
"time"

"gopkg.in/go-playground/assert.v1"
)

func Test_Compatible(t *testing.T) {
b := aClient.Compatible(context.TODO())
if !b {
t.Errorf("expected true, got false")
}
}

func Test_httpLogin(t *testing.T) {
func TestHttpLogin(t *testing.T) {
err := aClient.httpsLogin(context.TODO())
if err != nil {
t.Errorf(err.Error())
Expand All @@ -24,7 +18,7 @@ func Test_httpLogin(t *testing.T) {
assert.Equal(t, "l5L29IP7", aClient.loginSession.CSRFToken)
}

func Test_Close(t *testing.T) {
func TestClose(t *testing.T) {
err := aClient.httpsLogin(context.TODO())
if err != nil {
t.Errorf(err.Error())
Expand All @@ -36,7 +30,7 @@ func Test_Close(t *testing.T) {
}
}

func Test_FirwmwareUpdateBMC(t *testing.T) {
func TestFirwmwareUpdateBMC(t *testing.T) {
err := aClient.httpsLogin(context.TODO())
if err != nil {
t.Errorf(err.Error())
Expand All @@ -54,7 +48,10 @@ func Test_FirwmwareUpdateBMC(t *testing.T) {
}

defer fh.Close()
err = aClient.firmwareInstallBMC(context.TODO(), fh, 0)
ctx, cancel := context.WithTimeout(context.TODO(), time.Minute*15)
defer cancel()

err = aClient.firmwareUploadBMC(ctx, fh)
if err != nil {
t.Errorf(err.Error())
}
Expand Down
Loading

0 comments on commit f7408e4

Please sign in to comment.