From a5f01add4fb6b04ae2052ed2dab3b85c7cfe6ba4 Mon Sep 17 00:00:00 2001 From: Jacob Weinstock Date: Tue, 11 Jul 2023 21:21:28 -0600 Subject: [PATCH 1/3] Add pure go ipmi provider: This provider is written in pure Go and speaks the ipmi protocol. This means we can communicate via ipmi without the ipmitool binary available on the system. Signed-off-by: Jacob Weinstock --- client.go | 16 +++ go.mod | 7 ++ go.sum | 16 ++- option.go | 6 + providers/goipmi/goipmi.go | 230 +++++++++++++++++++++++++++++++++++++ 5 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 providers/goipmi/goipmi.go diff --git a/client.go b/client.go index 4bd09517..ed3eb01e 100644 --- a/client.go +++ b/client.go @@ -18,6 +18,7 @@ import ( "github.com/bmc-toolbox/bmclib/v2/internal/httpclient" "github.com/bmc-toolbox/bmclib/v2/providers/asrockrack" "github.com/bmc-toolbox/bmclib/v2/providers/dell" + "github.com/bmc-toolbox/bmclib/v2/providers/goipmi" "github.com/bmc-toolbox/bmclib/v2/providers/intelamt" "github.com/bmc-toolbox/bmclib/v2/providers/ipmitool" "github.com/bmc-toolbox/bmclib/v2/providers/openbmc" @@ -72,6 +73,7 @@ type providerConfig struct { supermicro supermicro.Config rpc rpc.Provider openbmc openbmc.Config + goipmi goipmi.Config } // NewClient returns a new Client struct @@ -109,6 +111,10 @@ func NewClient(host, user, pass string, opts ...Option) *Client { openbmc: openbmc.Config{ Port: "443", }, + goipmi: goipmi.Config{ + CipherSuite: 3, + Port: 623, + }, }, } @@ -246,6 +252,16 @@ func (c *Client) registerSupermicroProvider() { ) c.Registry.Register(supermicro.ProviderName, supermicro.ProviderProtocol, supermicro.Features, nil, driverSupermicro) + + // register goipmi provider + goipmiOpts := []goipmi.Option{goipmi.WithCipherSuite(c.providerConfig.goipmi.CipherSuite)} + driverGoipmi, err := goipmi.New(c.Auth.Host, c.providerConfig.goipmi.Port, c.Auth.User, c.Auth.Pass, goipmiOpts...) + if err != nil { + c.Logger.Info("goipmi provider not available", "error", err.Error()) + } else { + driverGoipmi.Log = c.Logger + c.Registry.Register(goipmi.ProviderName, goipmi.ProviderProtocol, goipmi.Features, nil, driverGoipmi) + } } func (c *Client) registerOpenBMCProvider() { diff --git a/go.mod b/go.mod index 6c2601fc..ca434774 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/Jeffail/gabs/v2 v2.7.0 github.com/bmc-toolbox/common v0.0.0-20241031162543-6b96e5981a0d github.com/bombsimon/logrusr/v2 v2.0.1 + github.com/bougou/go-ipmi v0.6.0 github.com/ghodss/yaml v1.0.0 github.com/go-logr/logr v1.4.2 github.com/go-logr/zerologr v1.2.3 @@ -31,10 +32,16 @@ require ( github.com/VictorLowther/simplexml v0.0.0-20180716164440-0bff93621230 // indirect github.com/VictorLowther/soap v0.0.0-20150314151524-8e36fca84b22 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/google/uuid v1.1.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.6.1 // indirect github.com/satori/go.uuid v1.2.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect diff --git a/go.sum b/go.sum index df0e4d53..b3392c3d 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/bmc-toolbox/common v0.0.0-20241031162543-6b96e5981a0d h1:dMmFDAAEpXiz github.com/bmc-toolbox/common v0.0.0-20241031162543-6b96e5981a0d/go.mod h1:Cdnkm+edb6C0pVkyCrwh3JTXAe0iUF9diDG/DztPI9I= github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM= github.com/bombsimon/logrusr/v2 v2.0.1/go.mod h1:ByVAX+vHdLGAfdroiMg6q0zgq2FODY2lc5YJvzmOJio= +github.com/bougou/go-ipmi v0.6.0 h1:pA/LDYrnOMwIHepNigFd8r2uwFSGsmlI47ZrvRkWbNc= +github.com/bougou/go-ipmi v0.6.0/go.mod h1:h3JPPoIK/caMQQJiW0BUtqYPcV8zkLobq1hnKwITlmk= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -25,6 +27,8 @@ github.com/go-logr/zerologr v1.2.3/go.mod h1:BxwGo7y5zgSHYR1BjbnHPyF/5ZjVKfKxAZA github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -35,8 +39,10 @@ github.com/jacobweinstock/iamt v0.0.0-20230502042727-d7cdbe67d9ef/go.mod h1:Fgmi github.com/jacobweinstock/registrar v0.4.7 h1:s4dOExccgD+Pc7rJC+f3Mc3D+NXHcXUaOibtcEsPxOc= github.com/jacobweinstock/registrar v0.4.7/go.mod h1:PWmkdGFG5/ZdCqgMo7pvB3pXABOLHc5l8oQ0sgmBNDU= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -47,10 +53,16 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -90,8 +102,10 @@ golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/option.go b/option.go index 3039cfdc..1675980a 100644 --- a/option.go +++ b/option.go @@ -167,3 +167,9 @@ func WithTracerProvider(provider oteltrace.TracerProvider) Option { } } } + +func WithGoipmiCipherSuite(cipherSuite int) Option { + return func(args *Client) { + args.providerConfig.goipmi.CipherSuite = cipherSuite + } +} diff --git a/providers/goipmi/goipmi.go b/providers/goipmi/goipmi.go new file mode 100644 index 00000000..cfe330c0 --- /dev/null +++ b/providers/goipmi/goipmi.go @@ -0,0 +1,230 @@ +package goipmi + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/bmc-toolbox/bmclib/v2/providers" + "github.com/bougou/go-ipmi" + "github.com/go-logr/logr" + "github.com/jacobweinstock/registrar" +) + +const ( + // ProviderName for the provider pure go ipmi (go-ipmi) implementation. + ProviderName = "goipmi" + // ProviderProtocol for the provider pure go ipmi (go-ipmi) implementation. + ProviderProtocol = "ipmi" +) + +var ( + // Features implemented by goipmi. + Features = registrar.Features{ + providers.FeaturePowerSet, + providers.FeaturePowerState, + providers.FeatureBootDeviceSet, + providers.FeatureUserRead, + } +) + +// Config for goipmi provider. +type Config struct { + CipherSuite int + Log logr.Logger + Port int + + client *ipmi.Client +} + +// Option for setting optional Client values. +type Option func(*Config) + +func New(host string, port int, user, pass string, opts ...Option) (*Config, error) { + cl, err := ipmi.NewClient(host, port, user, pass) + if err != nil { + return nil, err + } + c := &Config{ + CipherSuite: 3, + Log: logr.Discard(), + client: cl, + } + for _, opt := range opts { + opt(c) + } + c.client.WithInterface(ipmi.InterfaceLanplus) + c.client.WithCipherSuiteID(toCipherSuiteID(c.CipherSuite)) + + return c, nil +} + +func WithCipherSuite(cipherSuite int) Option { + return func(c *Config) { + c.CipherSuite = cipherSuite + } +} + +func (c *Config) Name() string { + return ProviderName +} + +func (c *Config) Open(ctx context.Context) error { + c.client.WithTimeout(getTimeout(ctx)) + return c.client.Connect() +} + +func getTimeout(ctx context.Context) time.Duration { + deadline, ok := ctx.Deadline() + if !ok { + return 30 * time.Second + } + + return time.Until(deadline) +} + +func (c *Config) Close(_ context.Context) error { + return c.client.Close() +} + +func (c *Config) PowerStateGet(_ context.Context) (string, error) { + r, err := c.client.GetChassisStatus() + if err != nil { + return "", err + } + state := "off" + if r.PowerIsOn { + state = "on" + } + + return state, nil +} + +func (c *Config) PowerSet(_ context.Context, state string) (bool, error) { + var action ipmi.ChassisControl + switch strings.ToLower(state) { + case "on": + action = ipmi.ChassisControlPowerUp + case "off": + action = ipmi.ChassisControlPowerDown + case "soft": + action = ipmi.ChassisControlSoftShutdown + case "reset": + action = ipmi.ChassisControlHardwareRest + case "cycle": + action = ipmi.ChassisControlPowerCycle + default: + return false, fmt.Errorf("unknown or unimplemented state request: %v", state) + } + + // ipmi.ChassisControlResponse is an empty struct. + // No methods return any actual response. So we ignore it. + _, err := c.client.ChassisControl(action) + if err != nil { + return false, err + } + + return true, nil +} + +func (c *Config) BootDeviceSet(_ context.Context, bootDevice string, setPersistent, efiBoot bool) (ok bool, err error) { + d := ipmi.BootDeviceSelectorNoOverride + switch strings.ToLower(bootDevice) { + case "pxe": + d = ipmi.BootDeviceSelectorForcePXE + case "disk": + d = ipmi.BootDeviceSelectorForceHardDrive + case "safe": + d = ipmi.BootDeviceSelectorForceHardDriveSafe + case "diag": + d = ipmi.BootDeviceSelectorForceDiagnosticPartition + case "cdrom": + d = ipmi.BootDeviceSelectorForceCDROM + case "bios": + d = ipmi.BootDeviceSelectorForceBIOSSetup + case "floppy": + d = ipmi.BootDeviceSelectorForceFloppy + } + bt := ipmi.BIOSBootTypeLegacy + if efiBoot { + bt = ipmi.BIOSBootTypeEFI + } + + if err := c.client.SetBootDevice(d, bt, setPersistent); err != nil { + return false, err + } + + return true, nil +} + +func (c *Config) UserRead(_ context.Context) (users []map[string]string, err error) { + u, err := c.client.ListUser(0) + if err != nil { + return nil, err + } + + for _, v := range u { + if v.Name == "" { + continue + } + users = append(users, map[string]string{ + "id": fmt.Sprintf("%v", v.ID), + "name": v.Name, + "callin": fmt.Sprintf("%v", v.Callin), + "linkAuth": fmt.Sprintf("%v", v.LinkAuthEnabled), + "ipmiMsg": fmt.Sprintf("%v", v.IPMIMessagingEnabled), + "channelPrivLimit": fmt.Sprintf("%v", v.MaxPrivLevel), + }) + } + + return users, nil +} + +func toCipherSuiteID(c int) ipmi.CipherSuiteID { + switch c { + case 0: + return ipmi.CipherSuiteID0 + case 1: + return ipmi.CipherSuiteID1 + case 2: + return ipmi.CipherSuiteID2 + case 3: + return ipmi.CipherSuiteID3 + case 4: + return ipmi.CipherSuiteID4 + case 5: + return ipmi.CipherSuiteID5 + case 6: + return ipmi.CipherSuiteID6 + case 7: + return ipmi.CipherSuiteID7 + case 8: + return ipmi.CipherSuiteID8 + case 9: + return ipmi.CipherSuiteID9 + case 10: + return ipmi.CipherSuiteID10 + case 11: + return ipmi.CipherSuiteID11 + case 12: + return ipmi.CipherSuiteID12 + case 13: + return ipmi.CipherSuiteID13 + case 14: + return ipmi.CipherSuiteID14 + case 15: + return ipmi.CipherSuiteID15 + case 16: + return ipmi.CipherSuiteID16 + case 17: + return ipmi.CipherSuiteID17 + case 18: + return ipmi.CipherSuiteID18 + case 19: + return ipmi.CipherSuiteID19 + default: + return ipmi.CipherSuiteID3 + } + +} From 70dc9f1675d794fe99bedfe5b6e422b589b3afa8 Mon Sep 17 00:00:00 2001 From: Jacob Weinstock Date: Tue, 11 Jul 2023 21:26:03 -0600 Subject: [PATCH 2/3] Update README: Add goipmi, supermicro, and a short note about finding the supported features per provider. Signed-off-by: Jacob Weinstock --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ce9cb280..0b5e36c1 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,15 @@ bmclib v2 is a library to abstract interacting with baseboard management controllers. -## Supported BMC interfaces. - - - [Redfish](https://github.com/bmc-toolbox/bmclib/tree/main/providers/redfish) - - [IPMItool](https://github.com/bmc-toolbox/bmclib/tree/main/providers/ipmitool) - - [Intel AMT](https://github.com/bmc-toolbox/bmclib/tree/main/providers/intelamt) - - [Asrockrack](https://github.com/bmc-toolbox/bmclib/tree/main/providers/asrockrack) - - [RPC](providers/rpc/) +## Supported BMC interfaces + +- [Redfish](https://github.com/bmc-toolbox/bmclib/tree/main/providers/redfish) +- [IPMItool](https://github.com/bmc-toolbox/bmclib/tree/main/providers/ipmitool) +- [Intel AMT](https://github.com/bmc-toolbox/bmclib/tree/main/providers/intelamt) +- [Asrockrack](https://github.com/bmc-toolbox/bmclib/tree/main/providers/asrockrack) +- [Pure Go IPMI](https://github.com/bmc-toolbox/bmclib/tree/main/providers/goipmi) +- [Supermicro](https://github.com/bmc-toolbox/bmclib/tree/main/providers/supermicro) +- [RPC](providers/rpc/) ## Installation From 460a7bf889e58cb6f9eef3e72603c1adf32a3093 Mon Sep 17 00:00:00 2001 From: Jacob Weinstock Date: Wed, 8 Jan 2025 17:32:34 -0700 Subject: [PATCH 3/3] Add context to all calls: The latest version includes context to all calls. Signed-off-by: Jacob Weinstock --- providers/goipmi/goipmi.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/providers/goipmi/goipmi.go b/providers/goipmi/goipmi.go index cfe330c0..71920e4a 100644 --- a/providers/goipmi/goipmi.go +++ b/providers/goipmi/goipmi.go @@ -72,7 +72,7 @@ func (c *Config) Name() string { func (c *Config) Open(ctx context.Context) error { c.client.WithTimeout(getTimeout(ctx)) - return c.client.Connect() + return c.client.Connect(ctx) } func getTimeout(ctx context.Context) time.Duration { @@ -84,12 +84,12 @@ func getTimeout(ctx context.Context) time.Duration { return time.Until(deadline) } -func (c *Config) Close(_ context.Context) error { - return c.client.Close() +func (c *Config) Close(ctx context.Context) error { + return c.client.Close(ctx) } -func (c *Config) PowerStateGet(_ context.Context) (string, error) { - r, err := c.client.GetChassisStatus() +func (c *Config) PowerStateGet(ctx context.Context) (string, error) { + r, err := c.client.GetChassisStatus(ctx) if err != nil { return "", err } @@ -101,7 +101,7 @@ func (c *Config) PowerStateGet(_ context.Context) (string, error) { return state, nil } -func (c *Config) PowerSet(_ context.Context, state string) (bool, error) { +func (c *Config) PowerSet(ctx context.Context, state string) (bool, error) { var action ipmi.ChassisControl switch strings.ToLower(state) { case "on": @@ -111,7 +111,7 @@ func (c *Config) PowerSet(_ context.Context, state string) (bool, error) { case "soft": action = ipmi.ChassisControlSoftShutdown case "reset": - action = ipmi.ChassisControlHardwareRest + action = ipmi.ChassisControlHardReset case "cycle": action = ipmi.ChassisControlPowerCycle default: @@ -120,7 +120,7 @@ func (c *Config) PowerSet(_ context.Context, state string) (bool, error) { // ipmi.ChassisControlResponse is an empty struct. // No methods return any actual response. So we ignore it. - _, err := c.client.ChassisControl(action) + _, err := c.client.ChassisControl(ctx, action) if err != nil { return false, err } @@ -128,7 +128,7 @@ func (c *Config) PowerSet(_ context.Context, state string) (bool, error) { return true, nil } -func (c *Config) BootDeviceSet(_ context.Context, bootDevice string, setPersistent, efiBoot bool) (ok bool, err error) { +func (c *Config) BootDeviceSet(ctx context.Context, bootDevice string, setPersistent, efiBoot bool) (ok bool, err error) { d := ipmi.BootDeviceSelectorNoOverride switch strings.ToLower(bootDevice) { case "pxe": @@ -151,15 +151,15 @@ func (c *Config) BootDeviceSet(_ context.Context, bootDevice string, setPersiste bt = ipmi.BIOSBootTypeEFI } - if err := c.client.SetBootDevice(d, bt, setPersistent); err != nil { + if err := c.client.SetBootDevice(ctx, d, bt, setPersistent); err != nil { return false, err } return true, nil } -func (c *Config) UserRead(_ context.Context) (users []map[string]string, err error) { - u, err := c.client.ListUser(0) +func (c *Config) UserRead(ctx context.Context) (users []map[string]string, err error) { + u, err := c.client.ListUser(ctx, 0) if err != nil { return nil, err }