Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dell #72

Draft
wants to merge 20 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
Progress
majst01 committed Nov 14, 2024
commit 1f4d720dce0cb743b4a817f2edffa9c78b541aa1
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -30,3 +30,25 @@ func main() {
err = smcInBand.PowerOff()
}
```

## Dell

Sample Lab Machines
172.19.100.107
Default PW: 9XW9FR9PN3FF

172.19.100.108
Default PW: K4P4NVAK9KVK

TODO:

- Console access must be switched to ssh root@<IP> console com2
Can password access switched to pubkey ?

- Identify LED ON/OFF and State does not work

- IPMI is disabled by default, unsure if Redfish Password can be set from Inband

- Redfish Sessions must be closed, see: https://github.com/stmcginnis/gofish/blob/main/examples/query_sessions.md

- Dell iDrac Redfish Samples: https://github.com/dell/iDRAC-Redfish-Scripting
69 changes: 43 additions & 26 deletions cli/main.go
Original file line number Diff line number Diff line change
@@ -82,42 +82,59 @@ func outband(log logger.Logger) {
if ps == hal.PowerUnknownState {
uu["PowerState"] = "unexpected power state: PowerUnknownState"
}

err = ob.PowerOff()
if err != nil {
fmt.Printf("error during power off: %v\n", err)
}

time.Sleep(10 * time.Second)
board := ob.Board()
fmt.Println("LED: " + board.IndicatorLED)

err = ob.PowerOn()
err = ob.PowerCycle()
if err != nil {
fmt.Printf("error during power on: %v\n", err)
ee["PowerCycle"] = err
}

// ipmitool sel
err = ob.IdentifyLEDState(hal.IdentifyLEDStateOff)
if err != nil {
ee["IdentifyLEDState"] = err
}
err = ob.IdentifyLEDOn()
if err != nil {
ee["IdentifyLEDOn"] = err
}
err = ob.IdentifyLEDOff()
if err != nil {
ee["IdentifyLEDOff"] = err
}
board = ob.Board()
fmt.Println("LED: " + board.IndicatorLED)

if false {
err = ob.PowerOff()
if err != nil {
fmt.Printf("error during power off: %v\n", err)
}

//_, err = ob.UpdateBIOS()
//if err != nil {
// ee["UpdateBIOS"] = err
//}
//
//_, err = ob.UpdateBMC()
//if err != nil {
// ee["UpdateBMC"] = err
//}
time.Sleep(10 * time.Second)

err = ob.PowerOn()
if err != nil {
fmt.Printf("error during power on: %v\n", err)
}

// ipmitool sel
err = ob.IdentifyLEDState(hal.IdentifyLEDStateOff)
if err != nil {
ee["IdentifyLEDState"] = err
}
err = ob.IdentifyLEDOn()
if err != nil {
ee["IdentifyLEDOn"] = err
}
err = ob.IdentifyLEDOff()
if err != nil {
ee["IdentifyLEDOff"] = err
}

//_, err = ob.UpdateBIOS()
//if err != nil {
// ee["UpdateBIOS"] = err
//}
//
//_, err = ob.UpdateBMC()
//if err != nil {
// ee["UpdateBMC"] = err
//}
}

if len(uu) > 0 {
fmt.Println("Unexpected things:")
71 changes: 71 additions & 0 deletions cli/redfish/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package main

import (
"log/slog"
"os"

"github.com/google/uuid"
"github.com/stmcginnis/gofish"
)

func main() {
log := slog.Default()
ip := os.Args[1]
pw := os.Args[2]
user := "root"

config := gofish.ClientConfig{
Endpoint: "https://" + ip,
Username: user,
Password: pw,
Insecure: true,
}
c, err := gofish.Connect(config)
if err != nil {
panic(err)
}
defer c.Logout()

systems, err := c.Service.Systems()
if err != nil {
panic(err)
}

for _, system := range systems {
log.Info("System", "indicator led", system.IndicatorLED, "locator led", system.LocationIndicatorActive)
system.LocationIndicatorActive = false
log.Info("System", "system", string(system.RawData))
}

systems, err = c.Service.Systems()
if err != nil {
panic(err)
}
for _, system := range systems {
log.Info("System", "indicator led", system.IndicatorLED, "locator led", system.LocationIndicatorActive)
}

chassis, err := c.Service.Chassis()
if err != nil {
panic(err)
}

for _, chass := range chassis {
log.Info("Chassis", "indicator led", chass.IndicatorLED, "locator led", chass.LocationIndicatorActive)
}

uid := ""
for _, system := range systems {
if system.UUID != "" {
uid = system.UUID
break
}
}

u, err := uuid.Parse(uid)
if err != nil {
panic(err)
}

log.Info("BMC", "UUID", u.String())
}
5 changes: 4 additions & 1 deletion hal.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package hal

import (
"github.com/gliderlabs/ssh"
"strings"

"github.com/gliderlabs/ssh"

"github.com/google/uuid"
"github.com/metal-stack/go-hal/pkg/api"
)
@@ -42,6 +43,8 @@ const (
IdentifyLEDStateOn
// IdentifyLEDStateOff the LED is off
IdentifyLEDStateOff
// IdentifyLEDStateBlinking the LED is blinking
IdentifyLEDStateBlinking
)
const (
// FirmwareModeUnknown server is in unknown firmware state
59 changes: 58 additions & 1 deletion internal/redfish/redfish.go
Original file line number Diff line number Diff line change
@@ -176,7 +176,8 @@ func (c *APIClient) PowerState() (hal.PowerState, error) {
}

func (c *APIClient) PowerOn() error {
return c.setPower(redfish.ForceOnResetType)
// TODO: check if this is enough for supermicro
return c.setPower(redfish.OnResetType)
}

func (c *APIClient) PowerOff() error {
@@ -348,3 +349,59 @@ func (c *APIClient) BMC() (*api.BMC, error) {

return bmc, nil
}

func (c *APIClient) IdentifyLEDState(state hal.IdentifyLEDState) error {
chassis, err := c.Service.Chassis()
if err != nil {
c.log.Warnw("ignore system query", "error", err.Error())
}

systems, err := c.Service.Systems()
if err != nil {
return 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)
}
}

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)
}
}
return nil
}

func (c *APIClient) IdentifyLEDOn() error {
return c.IdentifyLEDState(hal.IdentifyLEDStateOn)
}

func (c *APIClient) IdentifyLEDOff() error {
return c.IdentifyLEDState(hal.IdentifyLEDStateOff)
}
9 changes: 5 additions & 4 deletions internal/vendors/dell/dell.go
Original file line number Diff line number Diff line change
@@ -67,6 +67,7 @@ func (o *outBand) BootFrom(hal.BootTarget) error {

// Console implements hal.OutBand.
func (o *outBand) Console(ssh.Session) error {
// Console access must be switched to ssh root@<IP> console com2
panic("unimplemented")
}

@@ -83,17 +84,17 @@ func (o *outBand) IPMIConnection() (ip string, port int, user string, password s

// IdentifyLEDOff implements hal.OutBand.
func (o *outBand) IdentifyLEDOff() error {
panic("unimplemented")
return o.Redfish.IdentifyLEDState(hal.IdentifyLEDStateOff)
}

// IdentifyLEDOn implements hal.OutBand.
func (o *outBand) IdentifyLEDOn() error {
panic("unimplemented")
return o.Redfish.IdentifyLEDState(hal.IdentifyLEDStateOn)
}

// IdentifyLEDState implements hal.OutBand.
func (o *outBand) IdentifyLEDState(hal.IdentifyLEDState) error {
panic("unimplemented")
func (o *outBand) IdentifyLEDState(state hal.IdentifyLEDState) error {
return o.Redfish.IdentifyLEDState(state)
}

// PowerCycle implements hal.OutBand.