bmclib

package module
v2.2.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 18, 2024 License: Apache-2.0 Imports: 27 Imported by: 14

README

bmclib v2 - board management controller library

Status Go Report Card GoDoc

bmclib v2 is a library to abstract interacting with baseboard management controllers.

Supported BMC interfaces.

Installation

go get github.com/bmc-toolbox/bmclib/v2

Import

import (
  bmclib "github.com/bmc-toolbox/bmclib/v2"
)
Usage

The snippet below connects to a BMC and retrieves the device hardware, firmware inventory.

import (
  bmclib "github.com/bmc-toolbox/bmclib/v2"
)

    // setup logger
    l := logrus.New()
    l.Level = logrus.DebugLevel
    logger := logrusr.New(l)

    clientOpts := []bmclib.Option{bmclib.WithLogger(logger)}

    // init client
    client := bmclib.NewClient(*host, "admin", "hunter2", clientOpts...)

    // open BMC session
    err := client.Open(ctx)
    if err != nil {
        log.Fatal(err, "bmc login failed")
    }

    defer client.Close(ctx)

    // retrieve inventory data
    inventory, err := client.Inventory(ctx)
    if err != nil {
        l.Error(err)
    }

    b, err := json.MarshalIndent(inventory, "", "  ")
    if err != nil {
        l.Error(err)
    }

    fmt.Println(string(b))

More sample code can be found in examples

BMC connections

bmclib performs queries on BMCs using multiple drivers, these drivers are the various services exposed by a BMC - redfish IPMI SSH and vendor API which is basically a custom vendor API endpoint.

The bmclib client determines which driver to use for an action like Power cycle or Create user based on its availability or through a compatibility test (when enabled).

When querying multiple BMCs through bmclib its often useful to to limit the BMCs and drivers that bmclib will attempt to use to connect, the options to limit or filter out BMCs are described below,

Query just using the redfish endpoint.

cl := bmclib.NewClient("192.168.1.1", "admin", "hunter2")
cl.Registry.Drivers = cl.Registry.Using("redfish")

Query using the redfish endpoint and fall back to IPMI

client := bmclib.NewClient("192.168.1.1", "admin", "hunter2")

// overwrite registered drivers by appending Redfish, IPMI drivers in order
drivers := append(registrar.Drivers{}, bmcClient.Registry.Using("redfish")...)
drivers = append(drivers, bmcClient.Registry.Using("ipmi")...)
client.Registry.Drivers = driver

Filter drivers to query based on compatibility, this will attempt to check if the driver is compatible ideally, this method should be invoked when the client is ready to perform a BMC action.

client := bmclib.NewClient("192.168.1.1", "admin", "hunter2")
client.Registry.Drivers = cl.Registry.FilterForCompatible(ctx)

Ignore the Redfish endpoint completely on BMCs running a specific Redfish version.

Note: this version should match the one returned through curl -k "https://<BMC IP>/redfish/v1" | jq .RedfishVersion

opt := bmclib.WithRedfishVersionsNotCompatible([]string{"1.5.0"})

client := bmclib.NewClient("192.168.1.1", "admin", "hunter2", opt...)
cl.Registry.Drivers = cl.Registry.FilterForCompatible(ctx)

Timeouts

bmclib can be configured to apply timeouts to BMC interactions. The following options are available.

Total max timeout only - The total time bmclib will wait for all BMC interactions to complete. This is specified using a single context.WithTimeout or context.WithDeadline that is passed to all method call. With this option, the per provider; per interaction timeout is calculated by the total max timeout divided by the number of providers (currently there are 4 providers).

cl := bmclib.NewClient(host, user, pass, bmclib.WithLogger(log))

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

if err = cl.Open(ctx); err != nil {
  return(err)
}
defer cl.Close(ctx)

state, err := cl.GetPowerState(ctx)

Total max timeout and a per provider; per interaction timeout - The total time bmclib will wait for all BMC interactions to complete. This is specified using a single context.WithTimeout or context.WithDeadline that is passed to all method call. This is honored above all timeouts. The per provider; per interaction timeout is specified using bmclib.WithPerProviderTimeout in the Client constructor.

cl := bmclib.NewClient(host, user, pass, bmclib.WithLogger(log), bmclib.WithPerProviderTimeout(15*time.Second))

ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()

if err = cl.Open(ctx); err != nil {
  return(err)
}
defer cl.Close(ctx)

state, err := cl.GetPowerState(ctx)

Per provider; per interaction timeout. No total max timeout - The time bmclib will wait for a specific provider to complete. This is specified using bmclib.WithPerProviderTimeout in the Client constructor.

cl := bmclib.NewClient(host, user, pass, bmclib.WithLogger(log), bmclib.WithPerProviderTimeout(15*time.Second))

ctx := context.Background()

if err = cl.Open(ctx); err != nil {
  return(err)
}
defer cl.Close(ctx)

state, err := cl.GetPowerState(ctx)

Default timeout - If no timeout is specified with a context or with bmclib.WithPerProviderTimeout the default is used. 30 seconds per provider; per interaction.

cl := bmclib.NewClient(host, user, pass, bmclib.WithLogger(log))

ctx := context.Background()

if err = cl.Open(ctx); err != nil {
  return(err)
}
defer cl.Close(ctx)

state, err := cl.GetPowerState(ctx)

Filtering

The bmclib.Client can be configured to filter BMC calls based on a few different criteria. Filtering modifies the order and/or the number of providers for BMC calls. This filtering can be permanent or on a one-time basis.

All providers are stored in a registry (see Client.Registry) and the default order for providers in the registry is ipmitool, asrockrack, gofish, IntelAMT. The default order is defined here.

Permanent Filtering

Permanent filtering modifies the order and/or the number of providers for BMC calls for all client methods (for example: Open, SetPowerState, etc) calls.

cl := bmclib.NewClient(host, user, pass)
// This will modify the order for all subsequent BMC calls
cl.Registry.Drivers = cl.Registry.PreferDriver("gofish")
if err := cl.Open(ctx); err != nil {
  return(err)
}

The following permanent filters are available:

  • cl.Registry.PreferDriver("gofish") - This moves the gofish provider to be the first provider in the registry.
  • cl.Registry.Supports(providers.FeaturePowerSet) - This removes any provider from the registry that does not support the setting the power state.
  • cl.Registry.Using("redfish") - This removes any provider from the registry that does not support the redfish protocol.
  • cl.Registry.For("gofish") - This removes any provider from the registry that is not the gofish provider.
  • cl.Registry.PreferProtocol("redfish") - This moves any provider that implements the redfish protocol to the beginning of the registry.
One-time Filtering

One-time filtering modifies the order and/or the number of providers for BMC calls only for a single method call.

cl := bmclib.NewClient(host, user, pass)
// This will modify the order for only this BMC call
if err := cl.PreferProvider("gofish").Open(ctx); err != nil {
  return(err)
}

The following one-time filters are available:

  • cl.PreferProtocol("gofish").GetPowerState(ctx) - This moves the gofish provider to be the first provider in the registry.
  • cl.Supports(providers.FeaturePowerSet).GetPowerState(ctx) - This removes any provider from the registry that does not support the setting the power state.
  • cl.Using("redfish").GetPowerState(ctx) - This removes any provider from the registry that does not support the redfish protocol.
  • cl.For("gofish").GetPowerState(ctx) - This removes any provider from the registry that is not the gofish provider.
  • cl.PreferProtocol("redfish").GetPowerState(ctx) - This moves any provider that implements the redfish protocol to the beginning of the registry.
Tracing

To collect trace telemetry, set the WithTraceProvider() option on the client which results in trace spans being collected for each client method.

cl := bmclib.NewClient(
          host,
          user,
          pass,
          bmclib.WithLogger(log),
          bmclib.WithTracerProvider(otel.GetTracerProvider()),
      )

Versions

The current bmclib version is v2 and is being developed on the main branch.

The previous bmclib version is in maintenance mode and can be found here v1.

Acknowledgments

bmclib v2 interfaces with Redfish on BMCs through the Gofish library https://github.com/stmcginnis/gofish

bmclib was originally developed for Booking.com. With approval from Booking.com, the code and specification were generalized and published as Open Source on github, for which the authors would like to express their gratitude.

Authors

Documentation

Overview

Package bmclib client.go is intended to be the main public API. Its purpose is to make interacting with bmclib as friendly as possible.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Auth

type Auth struct {
	Host string
	User string
	Pass string
}

Auth details for connecting to a BMC

type Client

type Client struct {
	Auth     Auth
	Logger   logr.Logger
	Registry *registrar.Registry
	// contains filtered or unexported fields
}

Client for BMC interactions

func NewClient

func NewClient(host, user, pass string, opts ...Option) *Client

NewClient returns a new Client struct

func (*Client) ClearSystemEventLog

func (c *Client) ClearSystemEventLog(ctx context.Context) (err error)

func (*Client) Close

func (c *Client) Close(ctx context.Context) (err error)

Close pass through to library function

func (*Client) CreateUser

func (c *Client) CreateUser(ctx context.Context, user, pass, role string) (ok bool, err error)

CreateUser pass through to library function

func (*Client) DeactivateSOL added in v2.2.1

func (c *Client) DeactivateSOL(ctx context.Context) (err error)

DeactivateSOL pass through library function to deactivate active SOL sessions

func (*Client) DeleteUser

func (c *Client) DeleteUser(ctx context.Context, user string) (ok bool, err error)

DeleteUser pass through to library function

func (*Client) FilterForCompatible

func (c *Client) FilterForCompatible(ctx context.Context)

FilterForCompatible removes any drivers/providers that are not compatible. It wraps the Client.Registry.FilterForCompatible func in order to provide a per provider timeout.

func (*Client) FirmwareInstall

func (c *Client) FirmwareInstall(ctx context.Context, component string, operationApplyTime string, forceInstall bool, reader io.Reader) (taskID string, err error)

FirmwareInstall pass through library function to upload firmware and install firmware

func (*Client) FirmwareInstallStatus

func (c *Client) FirmwareInstallStatus(ctx context.Context, installVersion, component, taskID string) (status string, err error)

Note: this interface is to be deprecated in favour of a more generic FirmwareTaskStatus.

FirmwareInstallStatus pass through library function to check firmware install status

func (*Client) FirmwareInstallSteps added in v2.2.0

func (c *Client) FirmwareInstallSteps(ctx context.Context, component string) (actions []constants.FirmwareInstallStep, err error)

FirmwareInstallSteps return the order of actions required install firmware for a component.

func (*Client) FirmwareInstallUploadAndInitiate added in v2.2.0

func (c *Client) FirmwareInstallUploadAndInitiate(ctx context.Context, component string, file *os.File) (taskID string, err error)

func (*Client) FirmwareInstallUploaded added in v2.2.0

func (c *Client) FirmwareInstallUploaded(ctx context.Context, component, uploadVerifyTaskID string) (installTaskID string, err error)

FirmwareInstallUploaded kicks off firmware install for a firmware uploaded with FirmwareUpload.

func (*Client) FirmwareTaskStatus added in v2.2.0

func (c *Client) FirmwareTaskStatus(ctx context.Context, kind constants.FirmwareInstallStep, component, taskID, installVersion string) (state constants.TaskState, status string, err error)

FirmwareTaskStatus pass through library function to check firmware task statuses

func (*Client) FirmwareUpload added in v2.2.0

func (c *Client) FirmwareUpload(ctx context.Context, component string, file *os.File) (uploadVerifyTaskID string, err error)

FirmwareUpload just uploads the firmware for install, it returns a task ID to verify the upload status.

func (*Client) For

func (c *Client) For(provider string) *Client

For removes any provider from the registry that is not the given provider. This is a one time/temporary reordering of the providers in the registry. This reorder is not preserved. It is only used for the call that uses the returned Client.

func (*Client) GetBiosConfiguration

func (c *Client) GetBiosConfiguration(ctx context.Context) (biosConfig map[string]string, err error)

func (*Client) GetBootDeviceOverride added in v2.2.0

func (c *Client) GetBootDeviceOverride(ctx context.Context) (override bmc.BootDeviceOverride, err error)

GetBootDeviceOverride pass through to library function

func (*Client) GetMetadata

func (c *Client) GetMetadata() bmc.Metadata

GetMetadata returns the metadata that is populated after each BMC function/method call

func (*Client) GetPowerState

func (c *Client) GetPowerState(ctx context.Context) (state string, err error)

GetPowerState pass through to library function

func (*Client) GetSystemEventLog added in v2.2.0

func (c *Client) GetSystemEventLog(ctx context.Context) (entries bmc.SystemEventLogEntries, err error)

GetSystemEventLog queries for the SEL and returns the entries in an opinionated format.

func (*Client) GetSystemEventLogRaw added in v2.2.0

func (c *Client) GetSystemEventLogRaw(ctx context.Context) (eventlog string, err error)

GetSystemEventLogRaw queries for the SEL and returns the raw response.

func (*Client) Inventory

func (c *Client) Inventory(ctx context.Context) (device *common.Device, err error)

Inventory pass through library function to collect hardware and firmware inventory

func (*Client) MountFloppyImage added in v2.2.0

func (c *Client) MountFloppyImage(ctx context.Context, image io.Reader) (err error)

func (*Client) Open

func (c *Client) Open(ctx context.Context) error

Open calls the OpenConnectionFromInterfaces library function Any providers/drivers that do not successfully connect are removed from the client.Registry.Drivers. If client.Registry.Drivers ends up being empty then we error.

func (*Client) PostCode

func (c *Client) PostCode(ctx context.Context) (status string, code int, err error)

PostCodeGetter pass through library function to return the BIOS/UEFI POST code

func (*Client) PreferProtocol

func (c *Client) PreferProtocol(protocols ...string) *Client

PreferProtocol reorders the providers in the registry to have the given protocol first. Matching providers order is preserved. This is a one time/temporary reordering of the providers in the registry. This reorder is not preserved. It is only used for the call that uses the returned Client.

func (*Client) PreferProvider

func (c *Client) PreferProvider(name string) *Client

PreferProvider reorders the registry to have the given provider first. This is a one time/temporary reordering of the providers in the registry. This reorder is not preserved. It is only used for the call that uses the returned Client. Update the Client.Registry to make the change permanent. For example, `cl.Registry.Drivers = cl.Registry.PreferDriver("ipmitool")`

func (*Client) ReadUsers

func (c *Client) ReadUsers(ctx context.Context) (users []map[string]string, err error)

ReadUsers pass through to library function

func (*Client) RegisterSpanAttributes added in v2.2.0

func (c *Client) RegisterSpanAttributes(m bmc.Metadata, span oteltrace.Span)

func (*Client) ResetBMC

func (c *Client) ResetBMC(ctx context.Context, resetType string) (ok bool, err error)

ResetBMC pass through to library function

func (*Client) ResetBiosConfiguration added in v2.2.4

func (c *Client) ResetBiosConfiguration(ctx context.Context) (err error)

func (*Client) Screenshot

func (c *Client) Screenshot(ctx context.Context) (image []byte, fileType string, err error)

func (*Client) SendNMI added in v2.2.3

func (c *Client) SendNMI(ctx context.Context) error

SendNMI tells the BMC to issue an NMI to the device

func (*Client) SetBiosConfiguration added in v2.2.4

func (c *Client) SetBiosConfiguration(ctx context.Context, biosConfig map[string]string) (err error)

func (*Client) SetBootDevice

func (c *Client) SetBootDevice(ctx context.Context, bootDevice string, setPersistent, efiBoot bool) (ok bool, err error)

SetBootDevice pass through to library function

func (*Client) SetPowerState

func (c *Client) SetPowerState(ctx context.Context, state string) (ok bool, err error)

SetPowerState pass through to library function

func (*Client) SetVirtualMedia

func (c *Client) SetVirtualMedia(ctx context.Context, kind string, mediaURL string) (ok bool, err error)

SetVirtualMedia controls the virtual media simulated by the BMC as being connected to the server. Specifically, the method ejects any currently attached virtual media, and then if mediaURL isn't empty, attaches a virtual media device of type kind whose contents are streamed from the indicated URL.

func (*Client) Supports

func (c *Client) Supports(features ...registrar.Feature) *Client

Supports removes any provider from the registry that does not support the given features. This is a one time/temporary reordering of the providers in the registry. This reorder is not preserved. It is only used for the call that uses the returned Client.

func (*Client) UnmountFloppyImage added in v2.2.0

func (c *Client) UnmountFloppyImage(ctx context.Context) (err error)

func (*Client) UpdateUser

func (c *Client) UpdateUser(ctx context.Context, user, pass, role string) (ok bool, err error)

UpdateUser pass through to library function

func (*Client) Using

func (c *Client) Using(protocol string) *Client

Using removes any provider from the registry that does not support the given protocol. This is a one time/temporary reordering of the providers in the registry. This reorder is not preserved. It is only used for the call that uses the returned Client.

type Option

type Option func(*Client)

Option for setting optional Client values

func WithAsrockrackHTTPClient

func WithAsrockrackHTTPClient(httpClient *http.Client) Option

func WithAsrockrackPort

func WithAsrockrackPort(port string) Option

func WithDellRedfishUseBasicAuth

func WithDellRedfishUseBasicAuth(useBasicAuth bool) Option

func WithDellRedfishVersionsNotCompatible

func WithDellRedfishVersionsNotCompatible(versions []string) Option

WithDellRedfishVersionsNotCompatible sets the list of incompatible redfish versions.

With this option set, The bmclib.Registry.FilterForCompatible(ctx) method will not proceed on devices with the given redfish version(s).

func WithHTTPClient

func WithHTTPClient(c *http.Client) Option

WithHTTPClient sets an http client

func WithIntelAMTHostScheme

func WithIntelAMTHostScheme(hostScheme string) Option

func WithIntelAMTPort

func WithIntelAMTPort(port uint32) Option

func WithIpmitoolCipherSuite

func WithIpmitoolCipherSuite(cipherSuite string) Option

func WithIpmitoolPath

func WithIpmitoolPath(path string) Option

func WithIpmitoolPort

func WithIpmitoolPort(port string) Option

func WithLogger

func WithLogger(logger logr.Logger) Option

WithLogger sets the logger

func WithPerProviderTimeout

func WithPerProviderTimeout(timeout time.Duration) Option

WithPerProviderTimeout sets the timeout when interacting with a BMC. This timeout value is applied per provider. When not defined and a context with a timeout is passed to a method, the default timeout will be the context timeout duration divided by the number of providers in the registry, meaning, the len(Client.Registry.Drivers). If this per provider timeout is not defined and no context timeout is defined, the defaultConnectTimeout is used.

func WithRPCOpt

func WithRPCOpt(opt rpc.Provider) Option

func WithRedfishEtagMatchDisabled

func WithRedfishEtagMatchDisabled(d bool) Option

func WithRedfishHTTPClient

func WithRedfishHTTPClient(httpClient *http.Client) Option

func WithRedfishPort

func WithRedfishPort(port string) Option

func WithRedfishUseBasicAuth

func WithRedfishUseBasicAuth(useBasicAuth bool) Option

func WithRedfishVersionsNotCompatible

func WithRedfishVersionsNotCompatible(versions []string) Option

WithRedfishVersionsNotCompatible sets the list of incompatible redfish versions.

With this option set, The bmclib.Registry.FilterForCompatible(ctx) method will not proceed on devices with the given redfish version(s).

func WithRegistry

func WithRegistry(registry *registrar.Registry) Option

WithRegistry sets the Registry

func WithSecureTLS

func WithSecureTLS(rootCAs *x509.CertPool) Option

WithSecureTLS enforces trusted TLS connections, with an optional CA certificate pool. Using this option with an nil pool uses the system CAs.

func WithTracerProvider added in v2.2.0

func WithTracerProvider(provider oteltrace.TracerProvider) Option

WithTracerProvider specifies a tracer provider to use for creating a tracer. If none is specified a noop tracerprovider is used.

Directories

Path Synopsis
examples
bios
bios is an example commmand that retrieves BIOS configuration information and prints it out
bios is an example commmand that retrieves BIOS configuration information and prints it out
create-users
create-users is an example commmand that utilizes the 'v1' bmclib interface methods to create user entries in a BMC using the redfish driver.
create-users is an example commmand that utilizes the 'v1' bmclib interface methods to create user entries in a BMC using the redfish driver.
floppy-image
inventory is an example commmand that utilizes the 'v1' bmclib interface methods to upload and mount, unmount a floppy image.
inventory is an example commmand that utilizes the 'v1' bmclib interface methods to upload and mount, unmount a floppy image.
install-firmware
install-firmware is an example command that utilizes the 'v1' bmclib interface methods to flash a firmware image to a BMC.
install-firmware is an example command that utilizes the 'v1' bmclib interface methods to flash a firmware image to a BMC.
inventory
inventory is an example commmand that utilizes the 'v1' bmclib interface methods to gather inventory from a BMC using the redfish driver.
inventory is an example commmand that utilizes the 'v1' bmclib interface methods to gather inventory from a BMC using the redfish driver.
rpc
screenshot
status is an example commmand that utilizes the 'v1' bmclib interface methods to capture a screenshot.
status is an example commmand that utilizes the 'v1' bmclib interface methods to capture a screenshot.
sel
status
status is an example commmand that utilizes the 'v1' bmclib interface methods to gather the BMC version, power state, and bios version from a BMC using the redfish driver.
status is an example commmand that utilizes the 'v1' bmclib interface methods to gather the BMC version, power state, and bios version from a BMC using the redfish driver.
rpc
Package rpc is a provider that defines an HTTP request/response contract for handling BMC interactions.
Package rpc is a provider that defines an HTTP request/response contract for handling BMC interactions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL