Skip to content

Commit

Permalink
LED States
Browse files Browse the repository at this point in the history
  • Loading branch information
majst01 committed Nov 16, 2024
1 parent f91b6d9 commit 341efcb
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 91 deletions.
2 changes: 1 addition & 1 deletion cli/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var boardCmd = &cli.Command{
return err
}
board := c.Board()
log.Infow("board", "bandtype", bandtype, "host", host, "result", board.String(), "bios", board.BIOS, "powermetric", board.PowerMetric, "powersupplies", board.PowerSupplies, "ledstate", board.IndicatorLED)
log.Infow("board", "bandtype", bandtype, "host", host, "result", board.String(), "redfish version", board.RedfishVersion, "bios", board.BiosVersion, "powermetric", board.PowerMetric, "powersupplies", board.PowerSupplies, "ledstate", board.IndicatorLED)
bmc, err := outBandBMCConnection.BMC()
if err != nil {
return err
Expand Down
53 changes: 47 additions & 6 deletions cli/led.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"github.com/metal-stack/go-hal"
"github.com/urfave/cli/v2"
)

Expand All @@ -9,12 +10,52 @@ var ledCmd = &cli.Command{
Usage: "gather machine led state",
Flags: flags,
Action: func(ctx *cli.Context) error {
// c, err := getHalConnection(log)
// if err != nil {
// return err
// }
// ledstate := c.IdentifyLEDState()
// log.Infow("board", "bandtype", bandtype, "host", host, "result", board.String(), "bios", board.BIOS, "powermetric", board.PowerMetric, "powersupplies", board.PowerSupplies)
c, err := getHalConnection(log)
if err != nil {
return err
}
board := c.Board()
log.Infow("lead", "state", board.IndicatorLED)
return nil
},
Subcommands: []*cli.Command{
{
Name: "on",
Usage: "identify led on",
Flags: flags,
Action: func(ctx *cli.Context) error {
c, err := getHalConnection(log)
if err != nil {
return err
}
err = c.IdentifyLEDState(hal.IdentifyLEDStateOn)
if err != nil {
return err
}
log.Infow("led state set to on")
board := c.Board()
log.Infow("lead", "state", board.IndicatorLED)
return nil
},
},
{
Name: "off",
Usage: "identify led off",
Flags: flags,
Action: func(ctx *cli.Context) error {
c, err := getHalConnection(log)
if err != nil {
return err
}
err = c.IdentifyLEDState(hal.IdentifyLEDStateOff)
if err != nil {
return err
}
log.Infow("led state set to off")
board := c.Board()
log.Infow("lead", "state", board.IndicatorLED)
return nil
},
},
},
}
141 changes: 74 additions & 67 deletions internal/redfish/redfish.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ import (
)

type APIClient struct {
*gofish.APIClient
Gofish *gofish.APIClient
*http.Client
urlPrefix string
user string
password string
basicAuth string
log logger.Logger
urlPrefix string
user string
password string
basicAuth string
log logger.Logger
redfishVersion string
}

func New(url, user, password string, insecure bool, log logger.Logger) (*APIClient, error) {
Expand All @@ -41,28 +42,30 @@ func New(url, user, password string, insecure bool, log logger.Logger) (*APIClie
if err != nil {
return nil, err
}

return &APIClient{
APIClient: c,
Client: c.HTTPClient,
user: user,
password: password,
basicAuth: base64.StdEncoding.EncodeToString([]byte(user + ":" + password)),
urlPrefix: fmt.Sprintf("%s/redfish/v1", url),
log: log,
Gofish: c,
Client: c.HTTPClient,
redfishVersion: c.Service.RedfishVersion,
user: user,
password: password,
basicAuth: base64.StdEncoding.EncodeToString([]byte(user + ":" + password)),
urlPrefix: fmt.Sprintf("%s/redfish/v1", url),
log: log,
}, nil
}

func (c *APIClient) BoardInfo() (*api.Board, error) {
// Query the chassis data using the session token
if c.Service == nil {
if c.Gofish.Service == nil {
return nil, fmt.Errorf("gofish service root is not available most likely due to missing username")
}

biosVersion := ""
manufacturer := ""
model := ""

systems, err := c.Service.Systems()
systems, err := c.Gofish.Service.Systems()
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
}
Expand All @@ -85,7 +88,7 @@ func (c *APIClient) BoardInfo() (*api.Board, error) {
}
}

chassis, err := c.Service.Chassis()
chassis, err := c.Gofish.Service.Chassis()
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
}
Expand Down Expand Up @@ -122,14 +125,15 @@ func (c *APIClient) BoardInfo() (*api.Board, error) {
"PartNumber", chass.PartNumber, "SerialNumber", chass.SerialNumber,
"BiosVersion", biosVersion, "led", chass.IndicatorLED)
return &api.Board{
VendorString: manufacturer,
Model: model,
PartNumber: chass.PartNumber,
SerialNumber: chass.SerialNumber,
BiosVersion: biosVersion,
IndicatorLED: toMetalLEDState(chass.IndicatorLED),
PowerMetric: powerMetric,
PowerSupplies: powerSupplies,
VendorString: manufacturer,
Model: model,
PartNumber: chass.PartNumber,
SerialNumber: chass.SerialNumber,
BiosVersion: biosVersion,
RedfishVersion: c.redfishVersion,
IndicatorLED: toMetalLEDState(chass.IndicatorLED),
PowerMetric: powerMetric,
PowerSupplies: powerSupplies,
}, nil
}
}
Expand All @@ -149,7 +153,7 @@ func toMetalLEDState(state common.IndicatorLED) string {

// MachineUUID retrieves a unique uuid for this (hardware) machine
func (c *APIClient) MachineUUID() (string, error) {
systems, err := c.Service.Systems()
systems, err := c.Gofish.Service.Systems()
if err != nil {
c.log.Errorw("error during system query, unable to detect uuid", "error", err.Error())
return "", err
Expand All @@ -163,7 +167,7 @@ func (c *APIClient) MachineUUID() (string, error) {
}

func (c *APIClient) PowerState() (hal.PowerState, error) {
systems, err := c.Service.Systems()
systems, err := c.Gofish.Service.Systems()
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
}
Expand Down Expand Up @@ -206,7 +210,7 @@ func (c *APIClient) PowerCycle() error {
}

func (c *APIClient) setPower(resetType redfish.ResetType) error {
systems, err := c.Service.Systems()
systems, err := c.Gofish.Service.Systems()
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
}
Expand Down Expand Up @@ -312,7 +316,7 @@ func (c *APIClient) addHeadersAndAuth(req *http.Request) {
}

func (c *APIClient) setNextBootBIOS() error {
systems, err := c.Service.Systems()
systems, err := c.Gofish.Service.Systems()
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
}
Expand All @@ -329,12 +333,12 @@ func (c *APIClient) setNextBootBIOS() error {
}

func (c *APIClient) BMC() (*api.BMC, error) {
systems, err := c.Service.Systems()
systems, err := c.Gofish.Service.Systems()
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
}

chassis, err := c.Service.Chassis()
chassis, err := c.Gofish.Service.Chassis()
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
}
Expand Down Expand Up @@ -364,51 +368,54 @@ func (c *APIClient) BMC() (*api.BMC, error) {
}

func (c *APIClient) IdentifyLEDState(state hal.IdentifyLEDState) error {
chassis, err := c.Service.Chassis()
var payload map[string]any

switch state {
case hal.IdentifyLEDStateOff:
payload = map[string]any{"LocationIndicatorActive": false}
case hal.IdentifyLEDStateOn:
payload = map[string]any{"LocationIndicatorActive": true}
case hal.IdentifyLEDStateBlinking:
payload = map[string]any{"LocationIndicatorActive": true}
case hal.IdentifyLEDStateUnknown:
return fmt.Errorf("unknown LED state:%s", state)
}
resp, err := c.Gofish.Patch("/redfish/v1/Chassis/System.Embedded.1", payload)
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
c.log.Errorw("unable to set led", "error", err)
}
c.log.Infow("set led", "response", resp.Body)

systems, err := c.Service.Systems()
return nil
}

func (c *APIClient) GetIdentifyLED() (hal.IdentifyLEDState, error) {

resp, err := c.Gofish.Get("/redfish/v1/Chassis/System.Embedded.1")
if err != nil {
return err
c.log.Errorw("unable to get led", "error", err)
return hal.IdentifyLEDStateUnknown, err
}
// Not sure if system or chassis is responsible for LED
for _, system := range systems {
c.log.Infow("setting indicator led via system", "system", system.ID, "state", state)
switch state {
case hal.IdentifyLEDStateOff:
system.LocationIndicatorActive = false
system.IndicatorLED = common.OffIndicatorLED
case hal.IdentifyLEDStateOn:
system.LocationIndicatorActive = true
system.IndicatorLED = common.LitIndicatorLED
case hal.IdentifyLEDStateBlinking:
system.IndicatorLED = common.BlinkingIndicatorLED
case hal.IdentifyLEDStateUnknown:
return fmt.Errorf("unknown LED state:%s", state)
}
c.log.Infow("set led", "response", resp.Body)
var ledstate map[string]string
err = json.NewDecoder(resp.Body).Decode(ledstate)
if err != nil {
c.log.Errorw("unable to parse led state", "error", err)
return hal.IdentifyLEDStateUnknown, err
}

for _, chass := range chassis {
if chass.ChassisType != redfish.RackMountChassisType {
continue
}
c.log.Infow("setting indicator led via chassis", "chassis", chass.ID, "state", state)
switch state {
case hal.IdentifyLEDStateOff:
chass.LocationIndicatorActive = false
chass.IndicatorLED = common.OffIndicatorLED
case hal.IdentifyLEDStateOn:
chass.LocationIndicatorActive = true
chass.IndicatorLED = common.LitIndicatorLED
case hal.IdentifyLEDStateBlinking:
chass.IndicatorLED = common.BlinkingIndicatorLED
case hal.IdentifyLEDStateUnknown:
return fmt.Errorf("unknown LED state:%s", state)
}
state, ok := ledstate["LocationIndicatorActive"]
if !ok {
return hal.IdentifyLEDStateUnknown, fmt.Errorf("ledstate does not contain a LocationIndicatorActive key")
}
return nil

switch state {
case "true":
return hal.IdentifyLEDStateOn, nil
case "false":
return hal.IdentifyLEDStateOff, nil
}
return hal.IdentifyLEDStateUnknown, fmt.Errorf("unknown state:%s", state)
}

func (c *APIClient) IdentifyLEDOn() error {
Expand Down
2 changes: 1 addition & 1 deletion internal/vendors/dell/dell.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (ob *outBand) BMCConnection() api.OutBandBMCConnection {
}

func (ob *outBand) Close() {
ob.Redfish.APIClient.Logout()
ob.Redfish.Gofish.Logout()
}

func (c *bmcConnectionOutBand) BMC() (*api.BMC, error) {
Expand Down
2 changes: 1 addition & 1 deletion internal/vendors/lenovo/lenovo.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func OutBand(r *redfish.APIClient, board *api.Board) hal.OutBand {
}

func (ob *outBand) Close() {
ob.Redfish.APIClient.Logout()
ob.Redfish.Gofish.Logout()
}

// InBand
Expand Down
2 changes: 1 addition & 1 deletion internal/vendors/supermicro/supermicro.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func (c *bmcConnection) User() api.BMCUser {
}

func (ob *outBand) Close() {
ob.Redfish.APIClient.Logout()
ob.Redfish.Gofish.Logout()
}

func (c *bmcConnection) Present() bool {
Expand Down
2 changes: 1 addition & 1 deletion internal/vendors/vagrant/vagrant.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func OutBand(board *api.Board, ip string, ipmiPort int, user, password string) h
}

func (ob *outBand) Close() {
ob.Redfish.APIClient.Logout()
ob.Redfish.Gofish.Logout()
}

// InBand
Expand Down
27 changes: 14 additions & 13 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,20 @@ const (

// Board raw dmi board information
type Board struct {
VM bool
VendorString string
Vendor Vendor
Model string
PartNumber string
SerialNumber string
BiosVersion string
BMC *BMC
BIOS *BIOS
Firmware kernel.FirmwareMode
IndicatorLED string
PowerMetric *PowerMetric
PowerSupplies []PowerSupply
VM bool
VendorString string
Vendor Vendor
Model string
PartNumber string
SerialNumber string
BiosVersion string
RedfishVersion string
BMC *BMC
BIOS *BIOS
Firmware kernel.FirmwareMode
IndicatorLED string
PowerMetric *PowerMetric
PowerSupplies []PowerSupply
}

type PowerMetric struct {
Expand Down

0 comments on commit 341efcb

Please sign in to comment.