Skip to content

Commit

Permalink
update the fork (#5)
Browse files Browse the repository at this point in the history
* ipmitool and redfish sel clear in place, now to wire it up

* tests next

* tests added

* security: update golang.org/x/net to 0.7.0

* Update go dependencies

* internal/redfishwrapper: expose Tasks() method

* providers/redfish: split up method to support upload based on UpdateService URI

* provides/redfish/tasks: WIP: add a generic Task listing method

moved dell specific tasks handling into its own file

* providers/redfish/firmware: Fix parameters mismatch for unstructuredHttpUpload

* providers/redfish/firmware: Use correct type for multipartHTTP update

* providers/redfish/firmware: implement unstructured HTTP updates

* providers/redfish/tasks: add a function to get current task status for OpenBMC

* providers/redfish/firmware: get task ID for OpenBMC, return Task object for OpenBMC status

* providers/redfish: Add tests for openBMC status

* providers/redfish: Move default task logic into GetTask

* providers/redfish: Detect duplicate update requests

* providers/redfish/firmware: Add TaskIDFromLocationURI and tests

* providers/redfish/firmware: removed firmwareUpdateCompatible

* providers/redfish/tasks: check if a task is running before update

* added feature var for selclear

* added example

* Fix copying of request body:

The request body was being dropped
after the io.Copy causing issues with
further reading of it.

Add a PingMethod for the Open call.
This way we send something for the
client to interpret instead of nothing.

Update tests.

Signed-off-by: Jacob Weinstock <[email protected]>

* Update RPC example

Signed-off-by: Jacob Weinstock <[email protected]>

* addressed feedback: renamed all the things to be clearer, fixed example

* Remove returning the response body:

In testing this was causing issues with
consumers of the provider using the error
string. Also, for security reasons we might
not want to return an arbitrary response body,
especially when it doesn't conform to the response
contract.

Signed-off-by: Jacob Weinstock <[email protected]>

* providers/redfish: client config parameter to disable Etag If-Match headers

Work around for (crappy) vendor implementations where the If-Match
header does not work - even with '*' as the value, requests are
incorrectly denied with an ETag mismatch error.

depends on stmcginnis/gofish#277

* go: update gofish to current

* Add test to pass github validation

* providers/redfish/tasks: returns TaskNotFound on 404

* providers/redfish/tasks: cleanup

* providers/supermicro: list other x11 hardware models supported

* client: expose redfish etag match header disable parameter

* client: move provider register methods into separate methods

* client: remove unused error returns

* User supplied http client in RPC provider:

This plumbs through either the default or user supplied
http client to the RPC provider.

Signed-off-by: Jacob Weinstock <[email protected]>

* Fix session leak in Dell provider:

This was leaving open sessions in non Dell
machines. Closed sessions when the Dell
Open function returns error after successfully
opening.

Signed-off-by: Jacob Weinstock <[email protected]>

* Add error test cases for Open method:

Signed-off-by: Jacob Weinstock <[email protected]>

* Small clean ups

Signed-off-by: Jacob Weinstock <[email protected]>

* Remove erroneous print line

Signed-off-by: Jacob Weinstock <[email protected]>

* asrock/firmware: Different endpoint for E3C256D4I + add state "to be done"

* asrock/helpers: preserve_config param for E3C256D4I

* asrock: Add tests

* redfishwrapper: add method to return list of virtual media currently inserted

* supermicro: Add methods to upload and unmount a floppy image

* Add methods to upload and unmount a floppy image

* examples: Add example to upload and unmount a floppy image

* bmc/floppy: fixes returned error and adds test cases

* Rename UploadFloppyImage -> MountFloppyImage

* providers/redfish: Add Odata ID for MegaRAC/AsRockRack Systems & Managers

* Update go modules

* providers/asrockrack: when checking component, use upper case

* providers/arockrack: use debug variable

* redfishwrapper/fixtures: add mock redfish endpoint data

* redfishwrapper/client: add helper methods to return the manager, bios Odata ID

* redfishwrapper: add Task helper methods

* redfishwrapper: add firmware helper methods

* providers/redfish: move DeviceVendorModel helper method into redfishwrapper

* constants: define the FirmwareInstallStep, OperationApplyTime consts

* asrockrack: use helper method from the common package

* redfishwrapper/client: simpler logger setup

* redfishwrapper: clean up a few commented out bits

* bmc/firmware: rename constant and skip validating its value

Since we need to accept more than just those two OperationApplyTime parameters

* bmc/firmware: adds new interfaces for firmware upload, install uploaded, task status

The FirmwareTaskStatus method is to replace FirmwareInstallStatus

* providers: define the new features

* errors: define a few common errors

* examples: update based on changes

* supermicro/firmware: rework to support x12s and the newer firmware interface methods

* providers/redfish: fix bad import

* go: update to current gofish

* FirmwareUpload interface to accept a *os.File instead

There has been no real use for having an io.Reader passed in
and this interface is to expect a file instead.

* providers/supermicro: define a bmcQueryor interface and implement for x11, x12

based on feedback recieved this approach made more sense

* supermicro: support SMC BMCs that don't implement CSRF tokens

Older X11 BMC firmwares don't include CSRF tokens in requests to the BMC API.

* providers/smc: purge unused error

* client: add WithTraceProvider option to trace client methods

Each traced method is annotated with client metadata

* go: add otel deps

* go: update misc deps

* bmc: Adds a TaskState constant type which is returned by FirmwareTaskStatus

Update the FirmwareTaskStatus method to return the the TaskState
constant. This is to remove the FirmwareInstall prefix from the current
FirmwareInstall* constants and to have a generic Task State type.

* redfishwrapper: to return constants.TaskState

* providers/supermicro: return TaskState constant in FirmwareTaskStatus

* bmc/firmware: import bmclib/errors as bmclibErrors

* bmc/firmware_test: fix unused import

* Add GetBootDeviceOverride support for redfish (bmc-toolbox#367)

Add GetBootDeviceOverride support for redfish

* asrockrack: Return unknown when nil progress and version match

* asrockrack: Rewind file read from beginning in uploadFirmware

* redfish/inventory: move Inventory method under internal/redfishwrapper

This enables other providers to reuse the Inventory method and customise
its use based on the vendor/model

* providers/redfish: firmware methods moved into redfishwrapper

The FirmwareUpload and related methods in redfishwrapper are more
generic and can be re-used by providers with OEM specific update
parameters. Having these methods in the redfish provider makes it
cumbersome to maintain and extend.

* providers/redfish: moved GetBiosConfiguration method under redfishwrapper

The wrapper provides implementations other providers can call into for
code reuse

* redfishwrapper/power: move implementation here for re-use

* providers/redfish: Inventory, FirmwareInstall, PowerSet, PowerState moved method internals

into the redfishwrapper so they can be reused by other providers

* redfishwrapper: minor lint fixes

* redfishwrapper/task: include task message in info

This helps with debugging failed tasks

* redfishwrapper/task: lowercase task status before match

* bmc/firmware: fix up inconsistent metadata obj init and error collection

* providers/redfish: purge un-used methods

* supermicro: implement Inventory, PowerSet, PowerStateGet methods

* providers/supermicro: fix up redfish session init and purge unused methods

* providers/supermicro: fix TestOpen()

* redfish/GetBiosconfiguration: tests and fixtures moved under redfishwrapper package

* redfishwrapper/firmware: lets not strip the JID_ prefix, since the method should be generic

* bmc/firmware: initialize metadata object properly

* bmc/firmware: defines interface to upload and install firmware in the same method

* providers/dell: adds a helper method and implements Inventory(), PowerSet(), PowerStateGet() methods

* providers/dell: Implements FirmwareInstallSteps(), FirmwareInstallUploadedAndInitiate(), FirmwareInstallStatus() methods

* go: update gofish to include Task Oem data fix

stmcginnis/gofish#289

* providers/redfish: task methods moved under redfishwrapper package

* squash

* providers/redfish: dell tests moved under dell provider

* redfishwrapper: minor fix for test

* Retrieve SEL in both opinionated and raw formats

* Fix the conflict

Clipped one line too high when fixing the conflicts earlier

* Updated devcontainer

* openbmc: add provider

* client: register openbmc provider

* constants: remove state which indicates the BMC requires a power cycle

This is replaced by the firmware install step, and subsequently will be
moved into a type FirmwareInstallProperties{} which will replace
FirmwareInstallSteps

* errors: ErrBMCUpdating is returned if the BMC is known to be going through an update

* providers/asrockrack: update for newer Firmware interface methods

- Fix up inventory collection on E3C256D4ID-NL

* providers/asrockrack: rework firmware install methods for newer interface

* providers/asrockrack: GetPowerState() return ErrBMCUpdating when the BMC is under and update

* providers/asrr: use constants for the model names

* providers/dell: implement the BMCResetter interface

* openbmc, supermicro: implement BMCResetter interface

This makes sure when the provider is pinned/filtered* the BmcReset method is
available.

* https://github.com/bmc-toolbox/bmclib#one-time-filtering

* Incorporated changes from review, added test

* Add change after rebase from main

* Fix unit test TestConvertTaskState

* Add DeactivateSOL method

This method will terminate an SOL (serial-over-lan) session currently
active on the BMC (if there is one).  The only provider implementing it
is ipmitool, via 'ipmitool sol deactivate'.

* Add tests for SOL deactivation

* Return err if open fails:

Returning the error will ensure the provider
is removed from future calls.

* Add support for sending NMI

Support for sending an NMI has been added to ipmi, redfish,
redfishwrapper, and all providers that use the redfishwrapper.

* Upgrade go to 1.22 and dependencies

* Use go-version-file rather than go-version

* Add SetBiosConfiguration(ctx, biosConfig) as well as ResetBiosConfiguration(ctx) to redfishwrapper, redfish, etc.

* go get -u -d

* Remove go.opencensus.io otel lib

* ResetBiosConfiguration() functionality

* Clean up unused parameters

* Tidy go.mod

* Utilize gofish's UpdateBiosAttributesApplyAt and force OnReset for ApplyAt

* examples/bios: An example that exercises SetBiosConfiguration, GetBiosConfiguration and ResetBiosConfiguration

* Improve fatal error handling, add support for reading bios config from json file

* Handle invalid mode specification

* Use newMetadata() helper

* providers/supermicro: add x11spo-ntf in supported list

This has been tested and works

* providers/supermicro: Close session if any login dependencies fail

This prevents the client from assumptions that the client has an active
session available

* providers/dell: reuse ErrUnsupportedHardware from defined in bmclib/errors

instead of defining another one

* providers/dell: verify vendor model before proceeding

This is to ensure the code within this provider only executes on dells

* providers/asrr: verify hardware supported before firmware action

* providers/openbmc: verify hardware support in all methods

This is to ensure the Openbmc provider executes code only on hardware
identified to be Openbmc

* Revert "providers/dell: verify vendor model before proceeding"

This reverts commit 43d8535.

* Revert "providers/openbmc: verify hardware support in all methods"

This reverts commit 902ddd1.

* provider/dell: remove unused import

* supermicro/x12: use maps for OEM parameters and add X12SPO-NTF BIOS params

* supermicro/x11: lower case device model before comparison

This is a regression from a rework on the provider done earlier

* Move back to Go 1.18 in go.mod:

We don't seem to have an offical
strategy for the Go version in
go.mod. I believe that, as a library,
we should only bump this version if
there are dependencies we use that
would require us to move to this version.
I don't believe that we have any dependencies
that warrant a bump.

Signed-off-by: Jacob Weinstock <[email protected]>

* Document go.mod version philosophy:

This makes official our philosophy
and policy for the Go version in go.mod.

Signed-off-by: Jacob Weinstock <[email protected]>

* FS-1123: Supermicro (SMC) BIOS config Get, Set and Reset support via SUM

* FS-1123: Update devcontainer Dockerfile to use go 1.22

* FS-1123: Import latest bmc-toolbox/common

* FS-1123: Enhancements to examples/bios

* FS-1123: Supermicro Update Manager (SUM) provider

* FS-1123: Pin to bmc-toolbox/common@cfd9f1a

* go.mod: Update bmc-toolbox/common version

* internal/sum: Convert providers/sum into an internal package

* internal/sum/sum.go: Use explict returns

* go.sum: go mod tidy

* Implement sum test cases and a mocked Executor model

* internal/sum/sum.go: s/Mvcli/Sum/g

* internal/sum/sum.go: Remove unused NewFakeSum func

* internal/sum/sum.go: Provide a link and description re supermicro update mananger(sum)

* internal/sum/sum_test.go: Fix test for Sum.Run(); Upgrade bmc-toolbox/common version

* fixtures/internal/sum/GetBIOSInfo: Add mock data for GetBIOSInfo command

* go.mod: Update bmc-toolbox/common to ba8adc6a35e37791d7e47e5022214224e0e46418

* internal/executor: Remove unused interface funcs

* port to gofish/redfish v0.19.0 (bmc-toolbox#395)

* port to gofish/redfish v0.19.0

* update toolchain, golangci-lint, fix linting issues

* don't use errors.Wrap in new code

* stay on go 1.18

* revert upgrade of golangci-lint

* go 1.21 is required for redfish v0.19.0

* Add SetBiosConfigurationFromFile client functions

* support BootProgress on SMC X12/X13 (bmc-toolbox#396)

* WIP: support BootProgress on SMC X12/X13

* add some requested comments

* Update virtual media mounting:

At least one BMC, Supermicro SYS-E300-D9, did not
support setting inserted and/or writeProtected
properties in redfish calls to do a virtual media
mount. This falls back to not using them if the
initial call with them in the properties fails.

This was test and worked successfully on a
Supermicro (SYS-E300-D9), HP ILO5, and Dell iDRAC9.

Signed-off-by: Jacob Weinstock <[email protected]>

* Return early for improved code clarity:

This helps understand and maintain-ability.
Decreases the complexity of the function too.

Signed-off-by: Jacob Weinstock <[email protected]>

* Add example for virtual media:

This helps users see how to use the virtual
media mounting capabilities.

Signed-off-by: Jacob Weinstock <[email protected]>

* expand response payload processing (bmc-toolbox#399)

In contrast to other server-vendors, SMC does not return the task id in
the Location header of the response to a firmware upload. In BMC version
1.05.03 (Redfish version 1.14.0) the payload format changes from a
TaskAccepted message to a Redfish task, which breaks task id detection.
This change adds an attempt to deserialize the task structure before
falling back to the earlier TaskAccepted message type.

This also corrects the startUpdateURI.

* Allow specifying the Redfish system name:

For Redfish implementations that manage multiple
systems bening able to specify the system name
is required. This is the case with sushy-tools,
which is a redfish emulator for libvirt and others.

Signed-off-by: Jacob Weinstock <[email protected]>

* Update to latest version of golangci-lint

Signed-off-by: Jacob Weinstock <[email protected]>

* Add system name checking to the Managers helper method:

This allows the systemName struct field to filter
the managers. Needed for things like inserting and
ejecting virtual media.

Signed-off-by: Jacob Weinstock <[email protected]>

* Make sure the System helper method is used:

Many of the existing redfish feature methods
weren't using the System helper that filtered
for system name.

Also, for virtual media ejecting, handle BMC's
that don't support the "inserted" property.

Signed-off-by: Jacob Weinstock <[email protected]>

* providers/supermicro/supermicro.go: Initialize sum 'client' during serviceclient init

* Update tests to validate new error return is nil

* providers/supermicro/supermicro.go: Explain why we return nil in NewClient()

* Fix SetBiosFromFile
Fix example

---------

Signed-off-by: Matthew Burns <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
Co-authored-by: Matthew Burns <[email protected]>
Co-authored-by: Olivier FAURAX <[email protected]>
Co-authored-by: Joel Rebello <[email protected]>
Co-authored-by: Olivier FAURAX <[email protected]>
Co-authored-by: Jacob Weinstock <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Matthew Burns <[email protected]>
Co-authored-by: John Mears <[email protected]>
Co-authored-by: John Mears <[email protected]>
Co-authored-by: Zev Weiss <[email protected]>
Co-authored-by: Zev Weiss <[email protected]>
Co-authored-by: James W. Brinkerhoff <[email protected]>
Co-authored-by: James W. Brinkerhoff <[email protected]>
Co-authored-by: Jake Schuurmans <[email protected]>
Co-authored-by: Jake Schuurmans <[email protected]>
  • Loading branch information
16 people authored Nov 11, 2024
1 parent e996081 commit f83ce5d
Show file tree
Hide file tree
Showing 159 changed files with 15,123 additions and 2,048 deletions.
4 changes: 4 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM mcr.microsoft.com/devcontainers/go:1-1.22-bullseye
RUN apt update
RUN apt install ipmitool -y

33 changes: 33 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/go
{
"name": "Go",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
// "image": "mcr.microsoft.com/devcontainers/go:1-1.21-bullseye",
"build": {
"dockerfile": "Dockerfile"
},

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "go version",

// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.makefile-tools",
"zxh404.vscode-proto3",
"humao.rest-client"
]
}
}

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version-file: go.mod
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3
with:
Expand All @@ -34,7 +34,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version-file: go.mod
- name: make all-tests
run: make all-tests
- name: upload codecov
Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,33 @@ The following one-time filters are available:
- `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.

```go
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](https://github.com/bmc-toolbox/bmclib/v1).

## Go version in `go.mod`

As a library we will only bump the version of Go in the `go.mod` file when there are required dependencies in bmclib that necessitate
a version bump. When consuming bmclib in your project, we recommend always building with the latest Go version but this
should be in your hands as a user as much as possible.

## Acknowledgments

bmclib v2 interfaces with Redfish on BMCs through the Gofish library https://github.com/stmcginnis/gofish
Expand Down
191 changes: 186 additions & 5 deletions bmc/bios.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,27 @@ type biosConfigurationGetterProvider struct {
BiosConfigurationGetter
}

type BiosConfigurationSetter interface {
SetBiosConfiguration(ctx context.Context, biosConfig map[string]string) (err error)
SetBiosConfigurationFromFile(ctx context.Context, cfg string) (err error)
}

type biosConfigurationSetterProvider struct {
name string
BiosConfigurationSetter
}

type BiosConfigurationResetter interface {
ResetBiosConfiguration(ctx context.Context) (err error)
}

type biosConfigurationResetterProvider struct {
name string
BiosConfigurationResetter
}

func biosConfiguration(ctx context.Context, generic []biosConfigurationGetterProvider) (biosConfig map[string]string, metadata Metadata, err error) {
var metadataLocal Metadata
metadata = newMetadata()
Loop:
for _, elem := range generic {
if elem.BiosConfigurationGetter == nil {
Expand All @@ -30,20 +49,104 @@ Loop:
err = multierror.Append(err, ctx.Err())
break Loop
default:
metadataLocal.ProvidersAttempted = append(metadataLocal.ProvidersAttempted, elem.name)
metadata.ProvidersAttempted = append(metadata.ProvidersAttempted, elem.name)
biosConfig, vErr := elem.GetBiosConfiguration(ctx)
if vErr != nil {
err = multierror.Append(err, errors.WithMessagef(vErr, "provider: %v", elem.name))
err = multierror.Append(err, vErr)
continue

}
metadataLocal.SuccessfulProvider = elem.name
return biosConfig, metadataLocal, nil
metadata.SuccessfulProvider = elem.name
return biosConfig, metadata, nil
}
}

return biosConfig, metadataLocal, multierror.Append(err, errors.New("failure to get bios configuration"))
return biosConfig, metadata, multierror.Append(err, errors.New("failure to get bios configuration"))
}

func setBiosConfiguration(ctx context.Context, generic []biosConfigurationSetterProvider, biosConfig map[string]string) (metadata Metadata, err error) {
metadata = newMetadata()
Loop:
for _, elem := range generic {
if elem.BiosConfigurationSetter == nil {
continue
}
select {
case <-ctx.Done():
err = multierror.Append(err, ctx.Err())
break Loop
default:
metadata.ProvidersAttempted = append(metadata.ProvidersAttempted, elem.name)
vErr := elem.SetBiosConfiguration(ctx, biosConfig)
if vErr != nil {
err = multierror.Append(err, errors.WithMessagef(vErr, "provider: %v", elem.name))
err = multierror.Append(err, vErr)
continue

}
metadata.SuccessfulProvider = elem.name
return metadata, nil
}
}

return metadata, multierror.Append(err, errors.New("failure to set bios configuration"))
}

func setBiosConfigurationFromFile(ctx context.Context, generic []biosConfigurationSetterProvider, cfg string) (metadata Metadata, err error) {
metadata = newMetadata()
Loop:
for _, elem := range generic {
if elem.BiosConfigurationSetter == nil {
continue
}
select {
case <-ctx.Done():
err = multierror.Append(err, ctx.Err())
break Loop
default:
metadata.ProvidersAttempted = append(metadata.ProvidersAttempted, elem.name)
vErr := elem.SetBiosConfigurationFromFile(ctx, cfg)
if vErr != nil {
err = multierror.Append(err, errors.WithMessagef(vErr, "provider: %v", elem.name))
err = multierror.Append(err, vErr)
continue

}
metadata.SuccessfulProvider = elem.name
return metadata, nil
}
}

return metadata, multierror.Append(err, errors.New("failure to set bios configuration from file"))
}

func resetBiosConfiguration(ctx context.Context, generic []biosConfigurationResetterProvider) (metadata Metadata, err error) {
metadata = newMetadata()
Loop:
for _, elem := range generic {
if elem.BiosConfigurationResetter == nil {
continue
}
select {
case <-ctx.Done():
err = multierror.Append(err, ctx.Err())
break Loop
default:
metadata.ProvidersAttempted = append(metadata.ProvidersAttempted, elem.name)
vErr := elem.ResetBiosConfiguration(ctx)
if vErr != nil {
err = multierror.Append(err, errors.WithMessagef(vErr, "provider: %v", elem.name))
err = multierror.Append(err, vErr)
continue

}
metadata.SuccessfulProvider = elem.name
return metadata, nil
}
}

return metadata, multierror.Append(err, errors.New("failure to reset bios configuration"))
}

func GetBiosConfigurationInterfaces(ctx context.Context, generic []interface{}) (biosConfig map[string]string, metadata Metadata, err error) {
Expand Down Expand Up @@ -71,3 +174,81 @@ func GetBiosConfigurationInterfaces(ctx context.Context, generic []interface{})

return biosConfiguration(ctx, implementations)
}

func SetBiosConfigurationInterfaces(ctx context.Context, generic []interface{}, biosConfig map[string]string) (metadata Metadata, err error) {
implementations := make([]biosConfigurationSetterProvider, 0)
for _, elem := range generic {
temp := biosConfigurationSetterProvider{name: getProviderName(elem)}
switch p := elem.(type) {
case BiosConfigurationSetter:
temp.BiosConfigurationSetter = p
implementations = append(implementations, temp)
default:
e := fmt.Sprintf("not a BiosConfigurationSetter implementation: %T", p)
err = multierror.Append(err, errors.New(e))
}
}
if len(implementations) == 0 {
return metadata, multierror.Append(
err,
errors.Wrap(
bmclibErrs.ErrProviderImplementation,
("no BiosConfigurationSetter implementations found"),
),
)
}

return setBiosConfiguration(ctx, implementations, biosConfig)
}

func SetBiosConfigurationFromFileInterfaces(ctx context.Context, generic []interface{}, cfg string) (metadata Metadata, err error) {
implementations := make([]biosConfigurationSetterProvider, 0)
for _, elem := range generic {
temp := biosConfigurationSetterProvider{name: getProviderName(elem)}
switch p := elem.(type) {
case BiosConfigurationSetter:
temp.BiosConfigurationSetter = p
implementations = append(implementations, temp)
default:
e := fmt.Sprintf("not a BiosConfigurationSetterFromFile implementation: %T", p)
err = multierror.Append(err, errors.New(e))
}
}
if len(implementations) == 0 {
return metadata, multierror.Append(
err,
errors.Wrap(
bmclibErrs.ErrProviderImplementation,
("no BiosConfigurationSetterFromFile implementations found"),
),
)
}

return setBiosConfigurationFromFile(ctx, implementations, cfg)
}

func ResetBiosConfigurationInterfaces(ctx context.Context, generic []interface{}) (metadata Metadata, err error) {
implementations := make([]biosConfigurationResetterProvider, 0)
for _, elem := range generic {
temp := biosConfigurationResetterProvider{name: getProviderName(elem)}
switch p := elem.(type) {
case BiosConfigurationResetter:
temp.BiosConfigurationResetter = p
implementations = append(implementations, temp)
default:
e := fmt.Sprintf("not a BiosConfigurationResetter implementation: %T", p)
err = multierror.Append(err, errors.New(e))
}
}
if len(implementations) == 0 {
return metadata, multierror.Append(
err,
errors.Wrap(
bmclibErrs.ErrProviderImplementation,
("no BiosConfigurationResetter implementations found"),
),
)
}

return resetBiosConfiguration(ctx, implementations)
}
37 changes: 37 additions & 0 deletions bmc/bmc.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package bmc

import (
"strings"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

// Metadata represents details about a bmc method
type Metadata struct {
// SuccessfulProvider is the name of the provider that successfully executed
Expand All @@ -13,3 +20,33 @@ type Metadata struct {
// FailedProviderDetail holds the failed providers error messages for called methods
FailedProviderDetail map[string]string
}

func newMetadata() Metadata {
return Metadata{
FailedProviderDetail: make(map[string]string),
}
}

func (m *Metadata) RegisterSpanAttributes(host string, span trace.Span) {
span.SetAttributes(attribute.String("host", host))

span.SetAttributes(attribute.String("successful-provider", m.SuccessfulProvider))

span.SetAttributes(
attribute.String("successful-open-conns", strings.Join(m.SuccessfulOpenConns, ",")),
)

span.SetAttributes(
attribute.String("successful-close-conns", strings.Join(m.SuccessfulCloseConns, ",")),
)

span.SetAttributes(
attribute.String("attempted-providers", strings.Join(m.ProvidersAttempted, ",")),
)

for p, e := range m.FailedProviderDetail {
span.SetAttributes(
attribute.String("provider-errs-"+p, e),
)
}
}
Loading

0 comments on commit f83ce5d

Please sign in to comment.