diff --git a/README.md b/README.md index 8adaced..a312241 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,52 @@ func main() { err = smcInBand.PowerOff() } ``` + +## Dell + +Sample Lab Machines +172.19.100.107 +User: root +Default PW: 9XW9FR9PN3FF + +172.19.100.108 +User: root +Default PW: K4P4NVAK9KVK + +TODO: + +- Console access must be switched to ssh root@ 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 + +## Supermicro console over ssh + +```bash +ssh -oHostKeyAlgorithms=+ssh-rsa metal@10.1.1.134 +or +ssh -oHostKeyAlgorithms=+ssh-dss metal@10.1.1.134 +metal@10.1.1.134's password: + +Insyde SMASH-CLP System Management Shell, versions +Copyright (c) 2015-2016 by Insyde International CO., Ltd. +All Rights Reserved + + +-> cd system1/sol1 +/system1/sol1 + +-> start +/system1/sol1 + +press , , and then to terminate session +(press the keys in sequence, one after the other) + +metal@shoot--test--fraequ01b-group-cri-0-d65b6-pmfp7:~$ +``` \ No newline at end of file diff --git a/cli/board.go b/cli/board.go new file mode 100644 index 0000000..825f95e --- /dev/null +++ b/cli/board.go @@ -0,0 +1,28 @@ +package main + +import ( + "github.com/urfave/cli/v2" +) + +var boardCmd = &cli.Command{ + Name: "board", + Usage: "gather machine board details", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + board, err := c.Board() + if err != nil { + return err + } + 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 + } + log.Infow("bmc", "result", bmc) + return nil + }, +} diff --git a/cli/boot.go b/cli/boot.go new file mode 100644 index 0000000..002e69e --- /dev/null +++ b/cli/boot.go @@ -0,0 +1,69 @@ +package main + +import ( + "github.com/metal-stack/go-hal" + "github.com/urfave/cli/v2" +) + +var bootCmd = &cli.Command{ + Name: "boot", + Usage: "gather and modify boot order", + Flags: flags, + Action: func(ctx *cli.Context) error { + log.Warnw("getting boot order missing") + return nil + }, + Subcommands: []*cli.Command{ + { + Name: "hdd", + Usage: "boot from hdd", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + err = c.BootFrom(hal.BootTargetDisk) + if err != nil { + return err + } + log.Infow("boot", "set to", hal.BootTargetDisk.String()) + return nil + }, + }, + { + Name: "pxe", + Usage: "boot from pxe", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + err = c.BootFrom(hal.BootTargetPXE) + if err != nil { + return err + } + log.Infow("boot", "set to", hal.BootTargetPXE.String()) + return nil + }, + }, + { + Name: "bios", + Usage: "boot to bios", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + err = c.BootFrom(hal.BootTargetBIOS) + if err != nil { + return err + } + log.Infow("boot", "set to", hal.BootTargetBIOS.String()) + return nil + }, + }, + }, +} diff --git a/cli/led.go b/cli/led.go new file mode 100644 index 0000000..32e2893 --- /dev/null +++ b/cli/led.go @@ -0,0 +1,70 @@ +package main + +import ( + "github.com/metal-stack/go-hal" + "github.com/urfave/cli/v2" +) + +var ledCmd = &cli.Command{ + Name: "led", + Usage: "gather machine led state", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + ledstate, err := c.GetIdentifyLED() + if err != nil { + return err + } + log.Infow("led", "state", ledstate.String()) + 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") + ledstate, err := c.GetIdentifyLED() + if err != nil { + return err + } + log.Infow("led", "state", ledstate.String()) + 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") + ledstate, err := c.GetIdentifyLED() + if err != nil { + return err + } + log.Infow("led", "state", ledstate.String()) + return nil + }, + }, + }, +} diff --git a/cli/main.go b/cli/main.go index 1729e97..91500b7 100644 --- a/cli/main.go +++ b/cli/main.go @@ -1,124 +1,118 @@ package main import ( - "errors" - "flag" "fmt" + "log/slog" "os" "github.com/metal-stack/go-hal" - "github.com/metal-stack/go-hal/connect" + "github.com/metal-stack/go-hal/pkg/api" "github.com/metal-stack/go-hal/pkg/logger" + "github.com/urfave/cli/v2" ) var ( - band = flag.String("bandtype", "outband", "inband/outband") - user = flag.String("user", "ADMIN", "bmc username") - password = flag.String("password", "ADMIN", "bmc password") - host = flag.String("host", "localhost", "bmc host") - port = flag.Int("port", 623, "bmc port") - - errHelp = errors.New("usage: -bandtype inband|outband") -) - -func main() { - flag.Parse() - - log := logger.New() - switch *band { - case "inband": - inband(log) - case "outband": - outband(log) - default: - fmt.Printf("%s\n", errHelp) - os.Exit(1) + log logger.Logger + + bandtype string + user string + password string + host string + port int + redfishPath string + + bandtypeFlag = &cli.StringFlag{ + Name: "bandtype", + Value: "outband", + Usage: "inband/outband", + Destination: &bandtype, } -} - -func inband(log logger.Logger) { - ib, err := connect.InBand(log) - if err != nil { - panic(err) + userFlag = &cli.StringFlag{ + Name: "user", + Value: "ADMIN", + Usage: "bmc user", + Destination: &user, } - uuid, err := ib.UUID() - if err != nil { - panic(err) + passwordFlag = &cli.StringFlag{ + Name: "password", + Value: "", + Usage: "bmc password", + Destination: &password, } - fmt.Printf("UUID:%s\n", uuid) -} - -func outband(log logger.Logger) { - ob, err := connect.OutBand(*host, *port, *user, *password, log) - if err != nil { - panic(err) - } - - uu := make(map[string]string) - ee := make(map[string]error) - - b := ob.Board() - fmt.Printf("Board:\n%#v\n", b) - fmt.Printf("Power:\n%#v\n", b.PowerMetric) - fmt.Printf("PowerSupplies:\n%#v\n", b.PowerSupplies) - - bmc, err := ob.BMCConnection().BMC() - if err != nil { - ee["BMCConnection.BMC"] = err + hostFlag = &cli.StringFlag{ + Name: "host", + Value: "localhost", + Usage: "bmc host", + Destination: &host, } - fmt.Printf("BMC:\n%#v\n", bmc) - - _, err = ob.UUID() - if err != nil { - ee["UUID"] = err + portFlag = &cli.IntFlag{ + Name: "port", + Value: 623, + Usage: "bmc port", + Destination: &port, } - - ps, err := ob.PowerState() - if err != nil { - ee["PowerState"] = err + redfishPathFlag = &cli.StringFlag{ + Name: "redfish-path", + Value: "", + Usage: "redfish raw path", + Destination: &redfishPath, } - if ps == hal.PowerUnknownState { - uu["PowerState"] = "unexpected power state: PowerUnknownState" + flags = []cli.Flag{ + bandtypeFlag, + hostFlag, + portFlag, + userFlag, + passwordFlag, } + outBandBMCConnection api.OutBandBMCConnection +) - // ipmitool sel - err = ob.IdentifyLEDState(hal.IdentifyLEDStateOff) - if err != nil { - ee["IdentifyLEDState"] = err +func main() { + log = logger.NewSlog(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}))) + app := &cli.App{ + Name: "hal", + Usage: "try bmc commands", + Commands: []*cli.Command{ + boardCmd, + bootCmd, + ledCmd, + powerCmd, + redfishCmd, + uuidCmd, + }, + Flags: flags, } - err = ob.IdentifyLEDOn() - if err != nil { - ee["IdentifyLEDOn"] = err + + log.Infow("go hal cli", "host", host, "port", port, "password", password, "bandtype", bandtype) + + if err := app.Run(os.Args); err != nil { + log.Errorw("execution failed", "error", err) } - err = ob.IdentifyLEDOff() - if err != nil { - ee["IdentifyLEDOff"] = err + + if outBandBMCConnection != nil { + outBandBMCConnection.Close() } - //_, err = ob.UpdateBIOS() - //if err != nil { - // ee["UpdateBIOS"] = err - //} - // - //_, err = ob.UpdateBMC() - //if err != nil { - // ee["UpdateBMC"] = err - //} + os.Exit(1) +} - if len(uu) > 0 { - fmt.Println("Unexpected things:") - for m, u := range uu { - fmt.Printf("%s: %s\n", m, u) +func getHalConnection(log logger.Logger) (hal.Hal, error) { + switch bandtype { + case "inband": + ib, err := connect.InBand(log) + if err != nil { + return nil, err } - } - - if len(ee) > 0 { - fmt.Println("Failed checks:") - for m, err := range ee { - fmt.Printf("%s: %s\n", m, err.Error()) + return ib, nil + case "outband": + ob, err := connect.OutBand(host, port, user, password, log) + if err != nil { + return nil, err } - } else { - fmt.Println("Check succeeded") + outBandBMCConnection = ob.BMCConnection() + return ob, nil + default: + return nil, fmt.Errorf("unknown bandtype %s", bandtype) } } diff --git a/cli/power.go b/cli/power.go new file mode 100644 index 0000000..24e21a5 --- /dev/null +++ b/cli/power.go @@ -0,0 +1,143 @@ +package main + +import ( + "fmt" + + "github.com/avast/retry-go/v4" + "github.com/metal-stack/go-hal" + "github.com/urfave/cli/v2" +) + +var powerCmd = &cli.Command{ + Name: "power", + Usage: "gather and modify machine power state", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + state, err := c.PowerState() + if err != nil { + return err + } + log.Infow("power", "state", state.String()) + return nil + }, + Subcommands: []*cli.Command{ + { + Name: "on", + Usage: "power machine on", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + err = c.PowerOn() + if err != nil { + return err + } + err = retry.Do(func() error { + state, err := c.PowerState() + if err != nil { + return err + } + log.Infow("power", "state", state.String()) + if state != hal.PowerOnState { + return fmt.Errorf("state is still not %s", hal.PowerOnState.String()) + } + return nil + }) + if err != nil { + return err + } + state, err := c.PowerState() + if err != nil { + return err + } + log.Infow("power", "state", state.String()) + return nil + }, + }, + { + Name: "off", + Usage: "power machine off", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + err = c.PowerOff() + if err != nil { + return err + } + err = retry.Do(func() error { + state, err := c.PowerState() + if err != nil { + return err + } + log.Infow("power", "state", state.String()) + if state != hal.PowerOffState { + return fmt.Errorf("state is still not %s", hal.PowerOffState.String()) + } + return nil + }) + if err != nil { + return err + } + state, err := c.PowerState() + if err != nil { + return err + } + log.Infow("power", "state", state.String()) + return nil + }, + }, + { + Name: "cycle", + Usage: "power cycle machine", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + state, err := c.PowerState() + if err != nil { + return err + } + log.Infow("power", "state", state.String()) + + err = c.PowerCycle() + if err != nil { + return err + } + return nil + }, + }, + { + Name: "reset", + Usage: "power reset machine", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + state, err := c.PowerState() + if err != nil { + return err + } + log.Infow("power", "state", state.String()) + + err = c.PowerReset() + if err != nil { + return err + } + return nil + }, + }, + }, +} diff --git a/cli/redfish.go b/cli/redfish.go new file mode 100644 index 0000000..58e2681 --- /dev/null +++ b/cli/redfish.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + "io" + + "github.com/stmcginnis/gofish" + "github.com/urfave/cli/v2" +) + +var redfishCmd = &cli.Command{ + Name: "redfish", + Usage: "raw redfish usage", + Description: "for example use --redfish-path /redfish/v1/Chassis/System.Embedded.1 or /redfish/v1 to get the root of the redfish tree", + Flags: append(flags, redfishPathFlag), + Action: func(ctx *cli.Context) error { + config := gofish.ClientConfig{ + Endpoint: "https://" + host, + Username: user, + Password: password, + Insecure: true, + } + c, err := gofish.Connect(config) + if err != nil { + return err + } + defer c.Logout() + + resp, err := c.Get(redfishPath) + if err != nil { + return err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + fmt.Println(string(body)) + return nil + }, +} diff --git a/cli/uuid.go b/cli/uuid.go new file mode 100644 index 0000000..4cfc852 --- /dev/null +++ b/cli/uuid.go @@ -0,0 +1,23 @@ +package main + +import ( + "github.com/urfave/cli/v2" +) + +var uuidCmd = &cli.Command{ + Name: "uuid", + Usage: "gather machine uuid", + Flags: flags, + Action: func(ctx *cli.Context) error { + c, err := getHalConnection(log) + if err != nil { + return err + } + uid, err := c.UUID() + if err != nil { + return err + } + log.Infow("uuid", "bandtype", bandtype, "host", host, "result", uid.String()) + return nil + }, +} diff --git a/connect/connect.go b/connect/connect.go index 07185bc..798ae0e 100644 --- a/connect/connect.go +++ b/connect/connect.go @@ -3,15 +3,15 @@ package connect import ( "fmt" - "github.com/metal-stack/go-hal/internal/vendors/vagrant" - "github.com/metal-stack/go-hal/pkg/logger" - "github.com/metal-stack/go-hal" "github.com/metal-stack/go-hal/internal/dmi" "github.com/metal-stack/go-hal/internal/redfish" + "github.com/metal-stack/go-hal/internal/vendors/dell" "github.com/metal-stack/go-hal/internal/vendors/lenovo" "github.com/metal-stack/go-hal/internal/vendors/supermicro" + "github.com/metal-stack/go-hal/internal/vendors/vagrant" "github.com/metal-stack/go-hal/pkg/api" + "github.com/metal-stack/go-hal/pkg/logger" ) var ( @@ -45,22 +45,28 @@ func InBand(log logger.Logger) (hal.InBand, error) { func OutBand(ip string, ipmiPort int, user, password string, log logger.Logger) (hal.OutBand, error) { r, err := redfish.New("https://"+ip, user, password, true, log) if err != nil { - return nil, fmt.Errorf("Unable to establish redfish connection for ip:%s user:%s error:%w", ip, user, err) + return nil, fmt.Errorf("unable to establish redfish connection for ip:%s user:%s error:%w", ip, user, err) } - b, err := r.BoardInfo() + vendor, vendorString, modelString, err := r.VendorAndModel() if err != nil { - return nil, fmt.Errorf("Unable to get board info via redfish for ip:%s user:%s error:%w", ip, user, err) + return nil, fmt.Errorf("unable to get board info via redfish for ip:%s user:%s error:%w", ip, user, err) + } + b := &api.Board{ + VendorString: vendorString, + Vendor: vendor, + Model: modelString, } - b.Vendor = api.GuessVendor(b.VendorString) log.Debugw("connect", "board", b) - switch b.Vendor { + switch vendor { case api.VendorLenovo: return lenovo.OutBand(r, b), nil case api.VendorSupermicro, api.VendorNovarion: return supermicro.OutBand(r, b, ip, ipmiPort, user, password, log) case api.VendorVagrant: return vagrant.OutBand(b, ip, ipmiPort, user, password), nil - case api.VendorDell, api.VendorUnknown: + case api.VendorDell: + return dell.OutBand(r, b, log) + case api.VendorUnknown: fallthrough default: log.Errorw("connect", "unknown vendor", b.Vendor) diff --git a/go.mod b/go.mod index f0f61a5..a29957f 100644 --- a/go.mod +++ b/go.mod @@ -4,24 +4,28 @@ go 1.23 require ( github.com/avast/retry-go/v4 v4.6.0 - github.com/creack/pty v1.1.23 + github.com/creack/pty v1.1.24 github.com/gliderlabs/ssh v0.3.7 github.com/google/uuid v1.6.0 github.com/sethvargo/go-password v0.3.1 - github.com/stmcginnis/gofish v0.19.0 - github.com/stretchr/testify v1.9.0 + github.com/stmcginnis/gofish v0.20.0 + github.com/stretchr/testify v1.10.0 + github.com/urfave/cli/v2 v2.27.5 github.com/vmware/goipmi v0.0.0-20181114221114-2333cd82d702 - golang.org/x/net v0.29.0 + golang.org/x/net v0.31.0 ) require ( github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect + golang.org/x/crypto v0.29.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index db62b2b..a687a6e 100644 --- a/go.sum +++ b/go.sum @@ -2,9 +2,11 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= -github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= @@ -19,25 +21,31 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU= github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs= -github.com/stmcginnis/gofish v0.19.0 h1:fmxdRZ5WHfs+4ExArMYoeRfoh+SAxLELKtmoVplBkU4= -github.com/stmcginnis/gofish v0.19.0/go.mod h1:lq2jHj2t8Krg0Gx02ABk8MbK7Dz9jvWpO/TGnVksn00= +github.com/stmcginnis/gofish v0.20.0 h1:hH2V2Qe898F2wWT1loApnkDUrXXiLKqbSlMaH3Y1n08= +github.com/stmcginnis/gofish v0.20.0/go.mod h1:PzF5i8ecRG9A2ol8XT64npKUunyraJ+7t0kYMpQAtqU= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/vmware/goipmi v0.0.0-20181114221114-2333cd82d702 h1:yx587LNBbOpIxzCBHBiI94Wx8ryIAFlu1w0lDwm64cA= github.com/vmware/goipmi v0.0.0-20181114221114-2333cd82d702/go.mod h1:YiWonbS/PuCtti3wt9jl+FvNEJ7c0nvmjGoEYxdjyk0= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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= diff --git a/hal.go b/hal.go index a4e1c1a..ebfa30e 100644 --- a/hal.go +++ b/hal.go @@ -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" ) @@ -91,15 +92,53 @@ func GuessPowerState(powerState string) PowerState { return PowerUnknownState } +type Hal interface { + // Board return board information of the current connection + Board() (*api.Board, error) + + // UUID get the machine UUID + // current usage in metal-hammer + UUID() (*uuid.UUID, error) + + // PowerState returns the power state of the server + PowerState() (PowerState, error) + // PowerOn set power state of the server to on + PowerOn() error + // PowerOff set power state of the server to off + PowerOff() error + // PowerReset reset the power state of the server + PowerReset() error + // PowerCycle cycle the power state of the server + PowerCycle() error + + // BootFrom set the boot order of the server to the specified target + BootFrom(BootTarget) error + + GetIdentifyLED() (IdentifyLEDState, error) + // IdentifyLEDState get the identify LED state + IdentifyLEDState(IdentifyLEDState) error + // IdentifyLEDOn set the identify LED to on + IdentifyLEDOn() error + // IdentifyLEDOff set the identify LED to off + IdentifyLEDOff() error + + // Describe print a basic information about this connection + Describe() string +} + // InBand get and set settings from the server via the inband interface. type InBand interface { // Board return board information of the current connection - Board() *api.Board + Board() (*api.Board, error) // UUID get the machine UUID // current usage in metal-hammer UUID() (*uuid.UUID, error) + // PowerState returns the power state of the server + PowerState() (PowerState, error) + // PowerOn set power state of the server to on + PowerOn() error // PowerOff set power state of the server to off PowerOff() error // PowerReset reset the power state of the server @@ -107,6 +146,7 @@ type InBand interface { // PowerCycle cycle the power state of the server PowerCycle() error + GetIdentifyLED() (IdentifyLEDState, error) // IdentifyLEDState get the identify LED state IdentifyLEDState(IdentifyLEDState) error // IdentifyLEDOn set the identify LED to on @@ -141,7 +181,7 @@ type InBand interface { // OutBand get and set settings from the server via the out of band interface. type OutBand interface { // Board return board information of the current connection - Board() *api.Board + Board() (*api.Board, error) // UUID get the machine uuid // current usage in ipmi-catcher UUID() (*uuid.UUID, error) @@ -157,6 +197,7 @@ type OutBand interface { // PowerCycle cycle the power state of the server PowerCycle() error + GetIdentifyLED() (IdentifyLEDState, error) // IdentifyLEDState get the identify LED state IdentifyLEDState(IdentifyLEDState) error // IdentifyLEDOn set the identify LED to on diff --git a/internal/inband/inband.go b/internal/inband/inband.go index 63eaf07..3c0804e 100644 --- a/internal/inband/inband.go +++ b/internal/inband/inband.go @@ -41,8 +41,8 @@ func New(board *api.Board, inspectBMC bool, log logger.Logger) (*InBand, error) }, nil } -func (ib *InBand) Board() *api.Board { - return ib.board +func (ib *InBand) Board() (*api.Board, error) { + return ib.board, nil } func (ib *InBand) UUID() (*uuid.UUID, error) { diff --git a/internal/outband/outband.go b/internal/outband/outband.go index 3df3455..0870a7d 100644 --- a/internal/outband/outband.go +++ b/internal/outband/outband.go @@ -10,7 +10,7 @@ type OutBand struct { Redfish *redfish.APIClient IpmiTool ipmi.IpmiTool board *api.Board - ip string + Ip string ipmiPort int user string password string @@ -29,8 +29,7 @@ func New(r *redfish.APIClient, ipmiTool ipmi.IpmiTool, board *api.Board, ip stri return &OutBand{ Redfish: r, IpmiTool: ipmiTool, - board: board, - ip: ip, + Ip: ip, ipmiPort: ipmiPort, user: user, password: password, @@ -41,19 +40,19 @@ func New(r *redfish.APIClient, ipmiTool ipmi.IpmiTool, board *api.Board, ip stri func ViaGoipmi(board *api.Board, ip string, ipmiPort int, user, password string) *OutBand { return &OutBand{ board: board, - ip: ip, + Ip: ip, ipmiPort: ipmiPort, user: user, password: password, } } -func (ob *OutBand) Board() *api.Board { - return ob.board +func (ob *OutBand) Board() (*api.Board, error) { + return ob.Redfish.BoardInfo() } func (ob *OutBand) IPMIConnection() (string, int, string, string) { - return ob.ip, ob.ipmiPort, ob.user, ob.password + return ob.Ip, ob.ipmiPort, ob.user, ob.password } func (ob *OutBand) Goipmi(f func(*ipmi.Client) error) error { diff --git a/internal/redfish/redfish.go b/internal/redfish/redfish.go index 564a91d..33b9a47 100644 --- a/internal/redfish/redfish.go +++ b/internal/redfish/redfish.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "io" "net/http" "sort" "strings" @@ -20,13 +21,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) { @@ -41,20 +43,54 @@ 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) VendorAndModel() (api.Vendor, string, string, error) { + manufacturer := "" + model := "" + vendor := api.VendorUnknown + // Query the chassis data using the session token + if c.Gofish.Service == nil { + return vendor, manufacturer, model, fmt.Errorf("gofish service root is not available most likely due to missing username") + } + + systems, err := c.Gofish.Service.Systems() + if err != nil { + c.log.Warnw("ignore system query", "error", err.Error()) + } + for _, system := range systems { + if system.Manufacturer != "" { + manufacturer = system.Manufacturer + } + if system.Model != "" { + model = system.Model + } + if manufacturer != "" && model != "" { + break + } + } + if manufacturer == "" || model == "" { + return vendor, manufacturer, model, fmt.Errorf("unable to detect vendor and model") + } + + vendor = api.GuessVendor(manufacturer) + return vendor, manufacturer, model, 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") } @@ -62,7 +98,7 @@ func (c *APIClient) BoardInfo() (*api.Board, error) { 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()) } @@ -85,7 +121,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()) } @@ -122,14 +158,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 } } @@ -149,7 +186,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 @@ -163,7 +200,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()) } @@ -176,10 +213,24 @@ func (c *APIClient) PowerState() (hal.PowerState, error) { } func (c *APIClient) PowerOn() error { - return c.setPower(redfish.ForceOnResetType) + state, err := c.PowerState() + if err != nil { + return err + } + if state == hal.PowerOnState { + return nil + } + return c.setPower(redfish.OnResetType) } func (c *APIClient) PowerOff() error { + state, err := c.PowerState() + if err != nil { + return err + } + if state == hal.PowerOffState { + return nil + } return c.setPower(redfish.ForceOffResetType) } @@ -192,7 +243,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()) } @@ -298,7 +349,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()) } @@ -315,12 +366,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()) } @@ -348,3 +399,65 @@ func (c *APIClient) BMC() (*api.BMC, error) { return bmc, nil } + +func (c *APIClient) IdentifyLEDState(state hal.IdentifyLEDState) error { + 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.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.Errorw("unable to set led", "error", err) + } + defer resp.Body.Close() + + return nil +} + +func (c *APIClient) GetIdentifyLED() (hal.IdentifyLEDState, error) { + + resp, err := c.Gofish.Get("/redfish/v1/Chassis/System.Embedded.1") + if err != nil { + c.log.Errorw("unable to get led", "error", err) + return hal.IdentifyLEDStateUnknown, err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return hal.IdentifyLEDStateUnknown, err + } + + var parsedBody map[string]any + err = json.Unmarshal(body, &parsedBody) + if err != nil { + c.log.Errorw("unable to parse led state", "error", err) + return hal.IdentifyLEDStateUnknown, err + } + + state, ok := parsedBody["LocationIndicatorActive"] + if !ok { + return hal.IdentifyLEDStateUnknown, fmt.Errorf("ledstate does not contain a LocationIndicatorActive key") + } + + switch state.(bool) { + 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 { + return c.IdentifyLEDState(hal.IdentifyLEDStateOn) +} + +func (c *APIClient) IdentifyLEDOff() error { + return c.IdentifyLEDState(hal.IdentifyLEDStateOff) +} diff --git a/internal/vendors/dell/dell.go b/internal/vendors/dell/dell.go new file mode 100644 index 0000000..ddf42bb --- /dev/null +++ b/internal/vendors/dell/dell.go @@ -0,0 +1,146 @@ +package dell + +import ( + "github.com/gliderlabs/ssh" + "github.com/google/uuid" + "github.com/metal-stack/go-hal" + "github.com/metal-stack/go-hal/internal/outband" + "github.com/metal-stack/go-hal/internal/redfish" + "github.com/metal-stack/go-hal/pkg/api" + "github.com/metal-stack/go-hal/pkg/logger" +) + +type ( + outBand struct { + *outband.OutBand + log logger.Logger + } + bmcConnectionOutBand struct { + *outBand + } +) + +// OutBand creates an outband connection to a supermicro server. +func OutBand(r *redfish.APIClient, board *api.Board, log logger.Logger) (hal.OutBand, error) { + return &outBand{ + OutBand: outband.ViaRedfish(r, board), + log: log, + }, nil +} + +// BMCConnection implements hal.OutBand. +func (ob *outBand) BMCConnection() api.OutBandBMCConnection { + return &bmcConnectionOutBand{ + outBand: ob, + } +} + +func (ob *outBand) Close() { + ob.Redfish.Gofish.Logout() +} + +func (c *bmcConnectionOutBand) BMC() (*api.BMC, error) { + board, err := c.outBand.Redfish.BoardInfo() + if err != nil { + return nil, err + } + return &api.BMC{ + IP: c.outBand.Ip, + MAC: "", + ChassisPartNumber: "", + ChassisPartSerial: "", + BoardMfg: "", + BoardMfgSerial: "", + BoardPartNumber: board.PartNumber, + ProductManufacturer: board.VendorString, + ProductPartNumber: "", + ProductSerial: board.SerialNumber, + FirmwareRevision: "", + }, nil +} + +// BootFrom implements hal.OutBand. +func (o *outBand) BootFrom(hal.BootTarget) error { + panic("unimplemented") +} + +// Console implements hal.OutBand. +func (o *outBand) Console(ssh.Session) error { + // Console access must be switched to ssh root@ console com2 + panic("unimplemented") +} + +// Describe implements hal.OutBand. +func (o *outBand) Describe() string { + panic("unimplemented") +} + +// IPMIConnection implements hal.OutBand. +// Subtle: this method shadows the method (*OutBand).IPMIConnection of outBand.OutBand. +func (o *outBand) IPMIConnection() (ip string, port int, user string, password string) { + panic("unimplemented") +} + +func (o *outBand) GetIdentifyLED() (hal.IdentifyLEDState, error) { + return o.Redfish.GetIdentifyLED() +} + +// IdentifyLEDOff implements hal.OutBand. +func (o *outBand) IdentifyLEDOff() error { + return o.Redfish.IdentifyLEDState(hal.IdentifyLEDStateOff) +} + +// IdentifyLEDOn implements hal.OutBand. +func (o *outBand) IdentifyLEDOn() error { + return o.Redfish.IdentifyLEDState(hal.IdentifyLEDStateOn) +} + +// IdentifyLEDState implements hal.OutBand. +func (o *outBand) IdentifyLEDState(state hal.IdentifyLEDState) error { + return o.Redfish.IdentifyLEDState(state) +} + +// PowerCycle implements hal.OutBand. +func (o *outBand) PowerCycle() error { + return o.Redfish.PowerCycle() +} + +// PowerOff implements hal.OutBand. +func (o *outBand) PowerOff() error { + return o.Redfish.PowerOff() +} + +// PowerOn implements hal.OutBand. +func (o *outBand) PowerOn() error { + return o.Redfish.PowerOn() +} + +// PowerReset implements hal.OutBand. +func (o *outBand) PowerReset() error { + return o.Redfish.PowerReset() +} + +// PowerState implements hal.OutBand. +func (o *outBand) PowerState() (hal.PowerState, error) { + return o.Redfish.PowerState() +} + +// UUID implements hal.OutBand. +func (o *outBand) UUID() (*uuid.UUID, error) { + uuidString, err := o.Redfish.MachineUUID() + if err != nil { + return nil, err + } + id, err := uuid.Parse(uuidString) + return &id, err +} + +// UpdateBIOS implements hal.OutBand. +func (o *outBand) UpdateBIOS(url string) error { + panic("unimplemented") +} + +// UpdateBMC implements hal.OutBand. +func (o *outBand) UpdateBMC(url string) error { + panic("unimplemented") +} diff --git a/internal/vendors/lenovo/lenovo.go b/internal/vendors/lenovo/lenovo.go index 3c46995..50cdc9f 100644 --- a/internal/vendors/lenovo/lenovo.go +++ b/internal/vendors/lenovo/lenovo.go @@ -56,11 +56,23 @@ func OutBand(r *redfish.APIClient, board *api.Board) hal.OutBand { } } +func (ob *outBand) Close() { + ob.Redfish.Gofish.Logout() +} + // InBand + +// PowerState implements hal.InBand. +func (ib *inBand) PowerState() (hal.PowerState, error) { + return hal.PowerOnState, nil +} + +func (ib *inBand) PowerOn() error { + return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlPowerDown) +} func (ib *inBand) PowerOff() error { return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlPowerDown) } - func (ib *inBand) PowerCycle() error { return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlPowerCycle) } @@ -68,6 +80,9 @@ func (ib *inBand) PowerCycle() error { func (ib *inBand) PowerReset() error { return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlHardReset) } +func (o *inBand) GetIdentifyLED() (hal.IdentifyLEDState, error) { + return hal.IdentifyLEDStateUnknown, nil +} func (ib *inBand) IdentifyLEDState(state hal.IdentifyLEDState) error { return ib.IpmiTool.SetChassisIdentifyLEDState(state) @@ -132,7 +147,11 @@ func (c *bmcConnection) Present() bool { } func (c *bmcConnection) CreateUserAndPassword(user api.BMCUser, privilege api.IpmiPrivilege) (string, error) { - return c.IpmiTool.CreateUser(user, privilege, "", c.Board().Vendor.PasswordConstraints(), ipmi.LowLevel) + board, err := c.Board() + if err != nil { + return "", err + } + return c.IpmiTool.CreateUser(user, privilege, "", board.Vendor.PasswordConstraints(), ipmi.LowLevel) } func (c *bmcConnection) CreateUser(user api.BMCUser, privilege api.IpmiPrivilege, password string) error { @@ -191,6 +210,10 @@ func (ob *outBand) PowerCycle() error { return ob.Redfish.PowerReset() // PowerCycle is not supported } +func (o *outBand) GetIdentifyLED() (hal.IdentifyLEDState, error) { + return o.Redfish.GetIdentifyLED() +} + func (ob *outBand) IdentifyLEDState(state hal.IdentifyLEDState) error { return errorNotImplemented //TODO https://github.com/metal-stack/go-hal/issues/11 } diff --git a/internal/vendors/supermicro/supermicro.go b/internal/vendors/supermicro/supermicro.go index 7a25ac7..f72440a 100644 --- a/internal/vendors/supermicro/supermicro.go +++ b/internal/vendors/supermicro/supermicro.go @@ -45,6 +45,11 @@ type ( } ) +// PowerState implements hal.InBand. +func (ib *inBand) PowerState() (hal.PowerState, error) { + return hal.PowerOnState, nil +} + // InBand creates an inband connection to a supermicro server. func InBand(board *api.Board, log logger.Logger) (hal.InBand, error) { s, err := newSum(sumBin, board.Model, log) @@ -81,6 +86,9 @@ func OutBand(r *redfish.APIClient, board *api.Board, ip string, ipmiPort int, us func (ib *inBand) PowerOff() error { return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlPowerDown) } +func (ib *inBand) PowerOn() error { + return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlPowerDown) +} func (ib *inBand) PowerCycle() error { return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlPowerCycle) @@ -90,6 +98,10 @@ func (ib *inBand) PowerReset() error { return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlHardReset) } +func (o *inBand) GetIdentifyLED() (hal.IdentifyLEDState, error) { + return hal.IdentifyLEDStateUnknown, nil +} + func (ib *inBand) IdentifyLEDState(state hal.IdentifyLEDState) error { return ib.IpmiTool.SetChassisIdentifyLEDState(state) } @@ -148,12 +160,20 @@ func (c *bmcConnection) User() api.BMCUser { } } +func (ob *outBand) Close() { + ob.Redfish.Gofish.Logout() +} + func (c *bmcConnection) Present() bool { return c.IpmiTool.DevicePresent() } func (c *bmcConnection) CreateUserAndPassword(user api.BMCUser, privilege api.IpmiPrivilege) (string, error) { - return c.IpmiTool.CreateUser(user, privilege, "", c.Board().Vendor.PasswordConstraints(), ipmi.HighLevel) + board, err := c.Board() + if err != nil { + return "", err + } + return c.IpmiTool.CreateUser(user, privilege, "", board.Vendor.PasswordConstraints(), ipmi.HighLevel) } func (c *bmcConnection) CreateUser(user api.BMCUser, privilege api.IpmiPrivilege, password string) error { @@ -234,6 +254,10 @@ func (ob *outBand) PowerCycle() error { }) } +func (o *outBand) GetIdentifyLED() (hal.IdentifyLEDState, error) { + return o.Redfish.GetIdentifyLED() +} + func (ob *outBand) IdentifyLEDState(state hal.IdentifyLEDState) error { return ob.Goipmi(func(client *ipmi.Client) error { return client.SetChassisIdentifyLEDState(state) diff --git a/internal/vendors/vagrant/vagrant.go b/internal/vendors/vagrant/vagrant.go index c978db7..a1a03a2 100644 --- a/internal/vendors/vagrant/vagrant.go +++ b/internal/vendors/vagrant/vagrant.go @@ -54,7 +54,20 @@ func OutBand(board *api.Board, ip string, ipmiPort int, user, password string) h } } +func (ob *outBand) Close() { + ob.Redfish.Gofish.Logout() +} + // InBand + +// PowerState implements hal.InBand. +func (ib *inBand) PowerState() (hal.PowerState, error) { + return hal.PowerOnState, nil +} +func (ib *inBand) PowerOn() error { + return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlPowerDown) +} + func (ib *inBand) PowerOff() error { return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlPowerDown) } @@ -66,7 +79,9 @@ func (ib *inBand) PowerCycle() error { func (ib *inBand) PowerReset() error { return ib.IpmiTool.SetChassisControl(ipmi.ChassisControlHardReset) } - +func (o *inBand) GetIdentifyLED() (hal.IdentifyLEDState, error) { + return hal.IdentifyLEDStateUnknown, nil +} func (ib *inBand) IdentifyLEDState(state hal.IdentifyLEDState) error { return nil } @@ -174,6 +189,10 @@ func (ob *outBand) PowerCycle() error { }) } +func (o *outBand) GetIdentifyLED() (hal.IdentifyLEDState, error) { + return hal.IdentifyLEDStateUnknown, nil +} + func (ob *outBand) IdentifyLEDState(state hal.IdentifyLEDState) error { return nil } diff --git a/pkg/api/types.go b/pkg/api/types.go index b8bcb25..e4d5f9c 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -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 { @@ -115,6 +116,8 @@ type BMCConnection interface { type OutBandBMCConnection interface { // BMC returns the actual BMC details BMC() (*BMC, error) + // Close this session + Close() } // BMC Base Management Controller details diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index 064fd77..dd853d0 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -27,7 +27,7 @@ func New() Logger { return halslog.New(log) } -// NewSlog returns an zap instance of logger +// NewSlog returns an slog instance of logger func NewSlog(logger *slog.Logger) Logger { return halslog.New(logger) } diff --git a/redfish-output/dell/chassis.json b/redfish-output/dell/chassis.json new file mode 100644 index 0000000..c1205fc --- /dev/null +++ b/redfish-output/dell/chassis.json @@ -0,0 +1,319 @@ +{ + "@odata.context": "/redfish/v1/$metadata#Chassis.Chassis", + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1", + "@odata.type": "#Chassis.v1_25_1.Chassis", + "Actions": { + "#Chassis.Reset": { + "ResetType@Redfish.AllowableValues": [ + "On", + "ForceOff", + "PowerCycle" + ], + "target": "/redfish/v1/Chassis/System.Embedded.1/Actions/Chassis.Reset" + }, + "Oem": { + "#DellOemChassis.ExtendedReset": { + "FinalPowerState@Redfish.AllowableValues": [ + "On", + "Off" + ], + "ResetType@Redfish.AllowableValues": [ + "PowerCycle" + ], + "target": "/redfish/v1/Chassis/System.Embedded.1/Actions/Oem/DellOemChassis.ExtendedReset" + } + } + }, + "Assembly": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Assembly" + }, + "AssetTag": null, + "ChassisType": "RackMount", + "Description": "It represents the properties for physical components for any system.It represent racks, rackmount servers, blades, standalone, modular systems,enclosures, and all other containers.The non-cpu/device centric parts of the schema are all accessed either directly or indirectly through this resource.", + "EnvironmentMetrics": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/EnvironmentMetrics" + }, + "EnvironmentalClass": "A2", + "Id": "System.Embedded.1", + "IndicatorLED": "Lit", + "IndicatorLED@Redfish.Deprecated": "Please migrate to use LocationIndicatorActive property", + "Links": { + "ComputerSystems": [ + { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1" + } + ], + "ComputerSystems@odata.count": 1, + "Contains": [ + { + "@odata.id": "/redfish/v1/Chassis/Enclosure.Internal.0-1" + } + ], + "Contains@odata.count": 1, + "CooledBy": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/5" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/6" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/8" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/9" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/10" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/11" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/12" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/13" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/14" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/15" + } + ], + "CooledBy@odata.count": 16, + "Drives": [], + "Drives@odata.count": 0, + "ManagedBy": [ + { + "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1" + } + ], + "ManagedBy@odata.count": 1, + "ManagersInChassis": [ + { + "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1" + } + ], + "ManagersInChassis@odata.count": 1, + "PCIeDevices": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-20" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/68-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/67-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/195-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/194-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/198-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-1" + } + ], + "PCIeDevices@Redfish.Deprecated": "Please migrate to use /redfish/v1/Chassis/System.Embedded.1/PCIeDevices", + "PCIeDevices@odata.count": 28, + "PoweredBy": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Power#/PowerSupplies/0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Power#/PowerSupplies/1" + } + ], + "PoweredBy@odata.count": 2, + "Processors": [ + { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Processors/CPU.Socket.1" + } + ], + "Processors@odata.count": 1, + "Storage": [ + { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Storage/CPU.1" + }, + { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Storage/AHCI.Embedded.1-1" + } + ], + "Storage@odata.count": 2 + }, + "Location": { + "Info": ";;;;0", + "InfoFormat": "DataCenter;RoomName;Aisle;RackName;RackSlot", + "Placement": { + "Rack": "", + "RackOffset": 0, + "RackOffsetUnits": "EIA_310", + "Row": "" + }, + "PostalAddress": { + "Building": "", + "Room": "" + } + }, + "LocationIndicatorActive": false, + "Manufacturer": "Dell Inc.", + "Memory": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Memory" + }, + "Model": "PowerEdge R6615", + "Name": "Computer System Chassis", + "NetworkAdapters": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/NetworkAdapters" + }, + "Oem": { + "Dell": { + "@odata.type": "#DellOemChassis.v1_2_0.DellOemChassis", + "BezelAirFilter": {}, + "DellChassis": { + "@odata.context": "/redfish/v1/$metadata#DellChassis.DellChassis", + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Oem/Dell/DellChassis/mainsystemchassis", + "@odata.type": "#DellChassis.v1_0_0.DellChassis", + "CanBeFRUed": true, + "Description": "This resource shall provide information about the enclosure or chassis the system is in.", + "Id": "mainsystemchassis", + "Links": { + "ComputerSystem": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1" + } + }, + "Name": "DellChassis", + "SystemID": 2806 + } + } + }, + "PCIeDevices": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices" + }, + "PCIeSlots": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeSlots" + }, + "PartNumber": "067N9TA07", + "PhysicalSecurity": { + "IntrusionSensor": "Normal", + "IntrusionSensorNumber": 115, + "IntrusionSensorReArm": "Automatic" + }, + "Power": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Power" + }, + "Power@Redfish.Deprecated": "Please migrate to use /redfish/v1/Chassis/System.Embedded.1/PowerSubsystem", + "PowerState": "On", + "PowerSubsystem": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PowerSubsystem" + }, + "PoweredByParent": false, + "SKU": "4DMRC64", + "Sensors": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Sensors" + }, + "SerialNumber": "VNFCV0049D00ML", + "Status": { + "Health": "OK", + "HealthRollup": "OK", + "State": "Enabled" + }, + "Thermal": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal" + }, + "Thermal@Redfish.Deprecated": "Please migrate to use /redfish/v1/Chassis/System.Embedded.1/ThermalSubsystem", + "ThermalManagedByParent": false, + "ThermalSubsystem": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/ThermalSubsystem" + }, + "TrustedComponents": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/TrustedComponents" + }, + "UUID": "4c4c4544-0044-4d10-8052-b4c04f433634" +} diff --git a/redfish-output/dell/cpu.json b/redfish-output/dell/cpu.json new file mode 100644 index 0000000..342f5a3 --- /dev/null +++ b/redfish-output/dell/cpu.json @@ -0,0 +1,122 @@ +{ + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Processors/CPU.Socket.1", + "@odata.type": "#Processor.v1_20_0.Processor", + "@odata.context": "/redfish/v1/$metadata#Processor.Processor", + "Assembly": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Assembly" + }, + "Description": "Represents the properties of a Processor attached to this System", + "Enabled": true, + "EnvironmentMetrics": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Processors/CPU.Socket.1/EnvironmentMetrics" + }, + "Id": "CPU.Socket.1", + "InstructionSet": "x86-64", + "Links": { + "Chassis": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1" + }, + "Memory": [ + { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Memory/DIMM.Socket.A3" + }, + { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Memory/DIMM.Socket.A2" + }, + { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Memory/DIMM.Socket.A4" + }, + { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Memory/DIMM.Socket.A1" + } + ], + "Memory@odata.count": 4 + }, + "Manufacturer": "AMD", + "MaxSpeedMHz": 4400, + "MemorySummary": { + "TotalCacheSizeMiB": 81, + "TotalMemorySizeMiB": 131072 + }, + "Model": "AMD EPYC 9124 16-Core Processor", + "Name": "CPU 1", + "Oem": { + "Dell": { + "@odata.type": "#DellOem.v1_3_0.DellOemResources", + "DellProcessor": { + "CPUFamily": "AMDZenProcessorFamily", + "CPUStatus": "CPUEnabled", + "Cache1Associativity": "8-WaySet-Associative", + "Cache1ErrorMethodology": "Parity", + "Cache1InstalledSizeKB": 1024, + "Cache1Level": "L1", + "Cache1Location": "Internal", + "Cache1PrimaryStatus": "OK", + "Cache1SRAMType": "Unknown", + "Cache1SizeKB": 1024, + "Cache1Type": "Unified", + "Cache1WritePolicy": "WriteBack", + "Cache2Associativity": "8-WaySet-Associative", + "Cache2ErrorMethodology": "Multi-bitECC", + "Cache2InstalledSizeKB": 16384, + "Cache2Level": "L2", + "Cache2Location": "Internal", + "Cache2PrimaryStatus": "OK", + "Cache2SRAMType": "Unknown", + "Cache2SizeKB": 16384, + "Cache2Type": "Unified", + "Cache2WritePolicy": "WriteBack", + "Cache3Associativity": "16-WaySet-Associative", + "Cache3ErrorMethodology": "Multi-bitECC", + "Cache3InstalledSizeKB": 65536, + "Cache3Level": "L3", + "Cache3Location": "Internal", + "Cache3PrimaryStatus": "OK", + "Cache3SRAMType": "Unknown", + "Cache3SizeKB": 65536, + "Cache3Type": "Unified", + "Cache3WritePolicy": "WriteBack", + "CurrentClockSpeedMhz": 3000, + "ExecuteDisabledCapable": "Yes", + "ExecuteDisabledEnabled": "Yes", + "ExternalBusClockSpeedMhz": 0, + "HyperThreadingCapable": "Yes", + "HyperThreadingEnabled": "Yes", + "Id": "CPU.Socket.1", + "LastSystemInventoryTime": "2024-11-21T18:36:41+00:00", + "LastUpdateTime": "2024-10-24T23:54:36+00:00", + "Name": "DellProcessor", + "TurboModeCapable": "Yes", + "TurboModeEnabled": "Yes", + "VirtualizationTechnologyCapable": "Yes", + "VirtualizationTechnologyEnabled": "Yes", + "Volts": "1.8", + "@odata.context": "/redfish/v1/$metadata#DellProcessor.DellProcessor", + "@odata.type": "#DellProcessor.v1_2_0.DellProcessor", + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Processors/CPU.Socket.1/Oem/Dell/DellProcessors/CPU.Socket.1" + } + } + }, + "OperatingSpeedMHz": 3000, + "ProcessorArchitecture": "x86", + "ProcessorId": { + "EffectiveFamily": "15", + "EffectiveModel": "17", + "IdentificationRegisters": "0x00A10F11", + "MicrocodeInfo": "0xA101148", + "ProtectedIdentificationNumber": "02B705273A900029", + "Step": "1", + "VendorId": "AuthenticAMD" + }, + "ProcessorType": "CPU", + "Socket": "CPU.Socket.1", + "Status": { + "Health": "OK", + "State": "Enabled" + }, + "TotalCores": 16, + "TotalEnabledCores": 16, + "TotalThreads": 32, + "TurboState": "Enabled", + "Version": "Model 17 Stepping 1" +} diff --git a/redfish-output/dell/dell-bootoptions.json b/redfish-output/dell/dell-bootoptions.json new file mode 100644 index 0000000..2084657 --- /dev/null +++ b/redfish-output/dell/dell-bootoptions.json @@ -0,0 +1,49 @@ +{ + "@Redfish.Settings": { + "@odata.context": "/redfish/v1/$metadata#Settings.Settings", + "@odata.type": "#Settings.v1_4_0.Settings", + "SettingsObject": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellBootSources/Settings" + }, + "SupportedApplyTimes": [ + "OnReset", + "AtMaintenanceWindowStart", + "InMaintenanceWindowOnReset" + ] + }, + "@odata.context": "/redfish/v1/$metadata#DellBootSources.DellBootSources", + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellBootSources", + "@odata.type": "#DellBootSources.v1_1_0.DellBootSources", + "AttributeRegistry": "DellBootSourcesRegistry.v1_1_0", + "Attributes": { + "UefiBootSeq": [ + { + "Enabled": true, + "Id": "BIOS.Setup.1-1#UefiBootSeq#Disk.Bay.0:Enclosure.Internal.0-1#a850edc89070957751ce0eeaf6c11403", + "Index": 0, + "Name": "Disk.Bay.0:Enclosure.Internal.0-1" + }, + { + "Enabled": true, + "Id": "BIOS.Setup.1-1#UefiBootSeq#NIC.PxeDevice.1-1#709c0888d3f7fb4aa12e13c31f22ef1b", + "Index": 1, + "Name": "NIC.PxeDevice.1-1" + }, + { + "Enabled": true, + "Id": "BIOS.Setup.1-1#UefiBootSeq#Floppy.iDRACVirtual.1-1#08f2555d043e0db604a2b5868d81e51f", + "Index": 2, + "Name": "Floppy.iDRACVirtual.1-1" + }, + { + "Enabled": true, + "Id": "BIOS.Setup.1-1#UefiBootSeq#Optical.iDRACVirtual.1-1#74fff76b2296325c63f15ee7c5ece77d", + "Index": 3, + "Name": "Optical.iDRACVirtual.1-1" + } + ] + }, + "Description": "Boot Sources Current Settings", + "Id": "DellBootSources", + "Name": "Boot Sources Configuration Current Settings" +} diff --git a/redfish-output/dell/system.json b/redfish-output/dell/system.json new file mode 100644 index 0000000..850be4f --- /dev/null +++ b/redfish-output/dell/system.json @@ -0,0 +1,567 @@ +{ + "@Redfish.Settings": { + "@odata.context": "/redfish/v1/$metadata#Settings.Settings", + "@odata.type": "#Settings.v1_4_0.Settings", + "SettingsObject": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Settings" + }, + "SupportedApplyTimes": [ + "OnReset" + ] + }, + "@odata.context": "/redfish/v1/$metadata#ComputerSystem.ComputerSystem", + "@odata.id": "/redfish/v1/Systems/System.Embedded.1", + "@odata.type": "#ComputerSystem.v1_22_1.ComputerSystem", + "Actions": { + "#ComputerSystem.Reset": { + "target": "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset", + "ResetType@Redfish.AllowableValues": [ + "On", + "ForceOff", + "ForceRestart", + "GracefulRestart", + "GracefulShutdown", + "PushPowerButton", + "Nmi", + "PowerCycle" + ] + } + }, + "AssetTag": "", + "Bios": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Bios" + }, + "BiosVersion": "1.9.5", + "BootProgress": { + "LastState": "OSRunning" + }, + "Boot": { + "BootOptions": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/BootOptions" + }, + "Certificates": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Boot/Certificates" + }, + "BootOrder": [ + "Boot0003", + "Boot0002", + "Boot0000", + "Boot0001" + ], + "BootOrder@odata.count": 4, + "BootSourceOverrideEnabled": "Disabled", + "BootSourceOverrideMode": "UEFI", + "BootSourceOverrideTarget": "None", + "UefiTargetBootSourceOverride": null, + "BootSourceOverrideTarget@Redfish.AllowableValues": [ + "None", + "Pxe", + "Floppy", + "Cd", + "Hdd", + "BiosSetup", + "Utilities", + "UefiTarget", + "SDCard", + "UefiHttp" + ], + "StopBootOnFault": "Never" + }, + "Description": "Computer System which represents a machine (physical or virtual) and the local resources such as memory, cpu and other devices that can be accessed from that machine.", + "EthernetInterfaces": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/EthernetInterfaces" + }, + "GraphicalConsole": { + "ConnectTypesSupported": [ + "KVMIP" + ], + "ConnectTypesSupported@odata.count": 1, + "MaxConcurrentSessions": 6, + "ServiceEnabled": true + }, + "HostName": "", + "HostWatchdogTimer": { + "FunctionEnabled": false, + "Status": { + "State": "Disabled" + }, + "TimeoutAction": "None" + }, + "HostingRoles": [], + "HostingRoles@odata.count": 0, + "Id": "System.Embedded.1", + "IndicatorLED": "Lit", + "IndicatorLED@Redfish.Deprecated": "Please migrate to use LocationIndicatorActive property", + "Links": { + "Chassis": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1" + } + ], + "Chassis@odata.count": 1, + "CooledBy": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/5" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/6" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/8" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/9" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/10" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/11" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/12" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/13" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/14" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/15" + } + ], + "CooledBy@odata.count": 16, + "ManagedBy": [ + { + "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1" + } + ], + "ManagedBy@odata.count": 1, + "Oem": { + "Dell": { + "@odata.type": "#DellOem.v1_3_0.DellOemLinks", + "BootOrder": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellBootSources" + }, + "DellBootSources": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellBootSources" + }, + "DellSoftwareInstallationService": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellSoftwareInstallationService" + }, + "DellVideoCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellVideo" + }, + "DellChassisCollection": { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Oem/Dell/DellChassis" + }, + "DellPresenceAndStatusSensorCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellPresenceAndStatusSensors" + }, + "DellSensorCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellSensors" + }, + "DellRollupStatusCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRollupStatus" + }, + "DellPSNumericSensorCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellPSNumericSensors" + }, + "DellVideoNetworkCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellVideoNetwork" + }, + "DellOSDeploymentService": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellOSDeploymentService" + }, + "DellMetricService": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellMetricService" + }, + "DellGPUSensorCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellGPUSensors" + }, + "DellRaidService": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService" + }, + "DellNumericSensorCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellNumericSensors" + }, + "DellBIOSService": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellBIOSService" + }, + "DellSlotCollection": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellSlots" + } + } + }, + "PoweredBy": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Power#/PowerSupplies/0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Power#/PowerSupplies/1" + } + ], + "PoweredBy@odata.count": 2, + "TrustedComponents": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/TrustedComponents/TPM" + } + ], + "TrustedComponents@odata.count": 1 + }, + "LastResetTime": "2024-11-21T12:36:49-06:00", + "LocationIndicatorActive": false, + "Manufacturer": "Dell Inc.", + "Memory": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Memory" + }, + "MemorySummary": { + "MemoryMirroring": "None", + "Status": { + "Health": "OK", + "HealthRollup": "OK", + "State": "Enabled" + }, + "Status@Redfish.Deprecated": "Please migrate to use Status in the individual Memory resources", + "TotalSystemMemoryGiB": 128 + }, + "Model": "PowerEdge R6615", + "Name": "System", + "NetworkInterfaces": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/NetworkInterfaces" + }, + "Oem": { + "Dell": { + "@odata.type": "#DellOem.v1_3_0.DellOemResources", + "DellSystem": { + "BIOSReleaseDate": "09/12/2024", + "BaseBoardChassisSlot": "NA", + "BatteryRollupStatus": "OK", + "BladeGeometry": "NotApplicable", + "CMCIP": null, + "CMCRollupStatus": null, + "CPURollupStatus": "OK", + "ChassisModel": null, + "ChassisName": "Main System Chassis", + "ChassisServiceTag": "4DMRC64", + "ChassisSystemHeightUnit": 1, + "CoolingRollupStatus": "OK", + "CurrentRollupStatus": "OK", + "EstimatedExhaustTemperatureCelsius": 255, + "EstimatedSystemAirflowCFM": 255, + "ExpressServiceCode": "9531416668", + "FanRollupStatus": "OK", + "Id": "System.Embedded.1", + "IDSDMRedundancyStatus": null, + "IDSDMRollupStatus": null, + "IntrusionRollupStatus": "OK", + "IsOEMBranded": "False", + "LastSystemInventoryTime": "2024-11-21T18:36:41+00:00", + "LastUpdateTime": "2024-10-24T23:54:36+00:00", + "LicensingRollupStatus": "OK", + "ManagedSystemSize": "1 U", + "MaxCPUSockets": 1, + "MaxDIMMSlots": 12, + "MaxPCIeSlots": 3, + "MaxSystemMemoryMiB": 3145728, + "MemoryOperationMode": "Unknown", + "Name": "DellSystem", + "NodeID": "4DMRC64", + "PSRollupStatus": "OK", + "PlatformGUID": "3436434f-c0b4-5280-4d10-00444c4c4544", + "PopulatedDIMMSlots": 4, + "PopulatedPCIeSlots": 0, + "PowerCapEnabledState": "Disabled", + "SDCardRollupStatus": null, + "SELRollupStatus": "OK", + "ServerAllocationWatts": null, + "StorageRollupStatus": "OK", + "SysMemErrorMethodology": "Multi-bitECC", + "SysMemFailOverState": "NotInUse", + "SysMemLocation": "SystemBoardOrMotherboard", + "SysMemPrimaryStatus": "OK", + "SystemGeneration": "16G Monolithic", + "SystemHealthRollupStatus": "OK", + "SystemID": 2806, + "SystemRevision": "I", + "TempRollupStatus": "OK", + "TempStatisticsRollupStatus": "OK", + "UUID": "4c4c4544-0044-4d10-8052-b4c04f433634", + "VoltRollupStatus": "OK", + "smbiosGUID": "44454c4c-4400-104d-8052-b4c04f433634", + "@odata.context": "/redfish/v1/$metadata#DellSystem.DellSystem", + "@odata.type": "#DellSystem.v1_4_0.DellSystem", + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellSystem/System.Embedded.1" + } + } + }, + "PCIeDevices": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-20" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/68-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/67-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/195-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/194-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/198-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-4" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-7" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-1" + } + ], + "PCIeDevices@odata.count": 28, + "PCIeFunctions": [ + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-4/PCIeFunctions/0-4-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-20/PCIeFunctions/0-20-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-20/PCIeFunctions/0-20-3" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-2/PCIeFunctions/0-2-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-7/PCIeFunctions/0-7-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-3/PCIeFunctions/0-3-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-7/PCIeFunctions/0-7-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/0-1/PCIeFunctions/0-1-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/68-0/PCIeFunctions/68-0-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/67-0/PCIeFunctions/67-0-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-4/PCIeFunctions/128-4-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/195-0/PCIeFunctions/195-0-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-2/PCIeFunctions/128-2-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-7/PCIeFunctions/128-7-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-3/PCIeFunctions/128-3-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-7/PCIeFunctions/128-7-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-1/PCIeFunctions/128-1-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0/PCIeFunctions/196-0-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0/PCIeFunctions/196-0-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-3/PCIeFunctions/192-3-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-7/PCIeFunctions/192-7-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/195-0/PCIeFunctions/195-0-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-7/PCIeFunctions/192-7-2" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-1/PCIeFunctions/192-1-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-7/PCIeFunctions/192-7-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-2/PCIeFunctions/192-2-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-4/PCIeFunctions/192-4-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/194-0/PCIeFunctions/194-0-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/198-0/PCIeFunctions/198-0-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/192-0/PCIeFunctions/192-0-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-4/PCIeFunctions/64-4-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-2/PCIeFunctions/64-2-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-7/PCIeFunctions/64-7-1" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-3/PCIeFunctions/64-3-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-7/PCIeFunctions/64-7-0" + }, + { + "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/64-1/PCIeFunctions/64-1-0" + } + ], + "PCIeFunctions@odata.count": 36, + "PartNumber": "067N9TA07", + "PowerState": "On", + "ProcessorSummary": { + "Count": 1, + "CoreCount": 16, + "LogicalProcessorCount": 32, + "Model": "AMD EPYC 9124 16-Core Processor", + "Status": { + "Health": "OK", + "HealthRollup": "OK", + "State": "Enabled" + }, + "Status@Redfish.Deprecated": "Please migrate to use Status in the individual Processor resources", + "ThreadingEnabled": true + }, + "Processors": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Processors" + }, + "SKU": "4DMRC64", + "SecureBoot": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/SecureBoot" + }, + "SerialNumber": "VNFCV0049D00ML", + "SimpleStorage": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/SimpleStorage" + }, + "Status": { + "Health": "OK", + "HealthRollup": "OK", + "State": "Enabled" + }, + "Storage": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Storage" + }, + "SystemType": "Physical", + "TrustedModules": [ + { + "FirmwareVersion": "7.2.3.1", + "InterfaceType": "TPM2_0", + "Status": { + "State": "Enabled" + } + } + ], + "TrustedModules@odata.count": 1, + "UUID": "4c4c4544-0044-4d10-8052-b4c04f433634", + "VirtualMedia": { + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/VirtualMedia" + }, + "VirtualMediaConfig": { + "ServiceEnabled": true + } +} diff --git a/redfish-output/supermicro/bigtwin-chassis.json b/redfish-output/supermicro/bigtwin-chassis.json new file mode 100644 index 0000000..d14e31c --- /dev/null +++ b/redfish-output/supermicro/bigtwin-chassis.json @@ -0,0 +1,64 @@ +{ + "@odata.type": "#Chassis.v1_10_0.Chassis", + "@odata.id": "/redfish/v1/Chassis/1", + "Id": "1", + "Name": "Computer System Chassis", + "ChassisType": "RackMount", + "SerialNumber": "C217BAH23AE0090", + "PartNumber": "CSE-217BHQ+-R2K22BP2", + "AssetTag": "", + "IndicatorLED": "Off", + "Status": { + "State": "Enabled", + "Health": "OK", + "HealthRollup": "OK" + }, + "PhysicalSecurity": { + "IntrusionSensorNumber": 170, + "IntrusionSensor": "Normal", + "IntrusionSensorReArm": "Manual" + }, + "Power": { + "@odata.id": "/redfish/v1/Chassis/1/Power" + }, + "PCIeDevices": { + "@odata.id": "/redfish/v1/Chassis/1/PCIeDevices" + }, + "Thermal": { + "@odata.id": "/redfish/v1/Chassis/1/Thermal" + }, + "NetworkAdapters": { + "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters" + }, + "PCIeSlots": { + "@odata.id": "/redfish/v1/Chassis/1/PCIeSlots" + }, + "Sensors": { + "@odata.id": "/redfish/v1/Chassis/1/Sensors" + }, + "Links": { + "ComputerSystems": [ + { + "@odata.id": "/redfish/v1/Systems/1" + } + ], + "ManagedBy": [ + { + "@odata.id": "/redfish/v1/Managers/1" + } + ], + "ManagersInChassis": [ + { + "@odata.id": "/redfish/v1/Managers/1" + } + ] + }, + "Oem": { + "Supermicro": { + "@odata.type": "#SmcChassisExtensions.v1_0_0.Chassis", + "BoardSerialNumber": "HM18AS006642", + "GUID": "34313031-4D53-AC1F-6B35-5AF800000000", + "BoardID": "0x962" + } + } +} \ No newline at end of file diff --git a/redfish-output/supermicro/bigtwin-managers.json b/redfish-output/supermicro/bigtwin-managers.json new file mode 100644 index 0000000..b454d91 --- /dev/null +++ b/redfish-output/supermicro/bigtwin-managers.json @@ -0,0 +1,125 @@ +{ + "@odata.type": "#Manager.v1_5_2.Manager", + "@odata.id": "/redfish/v1/Managers/1", + "Id": "1", + "Name": "Manager", + "Description": "BMC", + "ManagerType": "BMC", + "UUID": "00000000-0000-0000-0000-AC1F6B355AF8", + "Model": "ASPEED", + "FirmwareVersion": "01.73.11", + "DateTime": "2024-11-25T07:40:21Z", + "DateTimeLocalOffset": "+00:00", + "Status": { + "State": "Enabled", + "Health": "OK" + }, + "GraphicalConsole": { + "ServiceEnabled": true, + "MaxConcurrentSessions": 4, + "ConnectTypesSupported": [ + "KVMIP" + ] + }, + "SerialConsole": { + "ServiceEnabled": true, + "MaxConcurrentSessions": 1, + "ConnectTypesSupported": [ + "SSH", + "IPMI" + ] + }, + "CommandShell": { + "ServiceEnabled": true, + "MaxConcurrentSessions": 0, + "ConnectTypesSupported": [ + "SSH" + ] + }, + "EthernetInterfaces": { + "@odata.id": "/redfish/v1/Managers/1/EthernetInterfaces" + }, + "SerialInterfaces": { + "@odata.id": "/redfish/v1/Managers/1/SerialInterfaces" + }, + "NetworkProtocol": { + "@odata.id": "/redfish/v1/Managers/1/NetworkProtocol" + }, + "LogServices": { + "@odata.id": "/redfish/v1/Managers/1/LogServices" + }, + "VirtualMedia": { + "@odata.id": "/redfish/v1/Managers/1/VirtualMedia" + }, + "Links": { + "ManagerForServers": [ + { + "@odata.id": "/redfish/v1/Systems/1" + } + ], + "ManagerForChassis": [ + { + "@odata.id": "/redfish/v1/Chassis/1" + } + ], + "Oem": {} + }, + "Actions": { + "Oem": { + "#ManagerConfig.Reset": { + "target": "/redfish/v1/Managers/1/Actions/Oem/ManagerConfig.Reset", + "@Redfish.ActionInfo": "/redfish/v1/Managers/1/ResetActionInfo" + } + }, + "#Manager.Reset": { + "target": "/redfish/v1/Managers/1/Actions/Manager.Reset" + } + }, + "Oem": { + "Supermicro": { + "@odata.type": "#SmcManagerExtensions.v1_0_0.Manager", + "ActiveDirectory": { + "@odata.id": "/redfish/v1/Managers/1/ActiveDirectory" + }, + "SMTP": { + "@odata.id": "/redfish/v1/Managers/1/SMTP" + }, + "RADIUS": { + "@odata.id": "/redfish/v1/Managers/1/RADIUS" + }, + "MouseMode": { + "@odata.id": "/redfish/v1/Managers/1/MouseMode" + }, + "NTP": { + "@odata.id": "/redfish/v1/Managers/1/NTP" + }, + "LDAP": { + "@odata.id": "/redfish/v1/Managers/1/LDAP" + }, + "IPAccessControl": { + "@odata.id": "/redfish/v1/Managers/1/IPAccessControl" + }, + "SMCRAKP": { + "@odata.id": "/redfish/v1/Managers/1/SMCRAKP" + }, + "SNMP": { + "@odata.id": "/redfish/v1/Managers/1/SNMP" + }, + "Syslog": { + "@odata.id": "/redfish/v1/Managers/1/Syslog" + }, + "Snooping": { + "@odata.id": "/redfish/v1/Managers/1/Snooping" + }, + "FanMode": { + "@odata.id": "/redfish/v1/Managers/1/FanMode" + }, + "IKVM": { + "@odata.id": "/redfish/v1/Managers/1/IKVM" + }, + "KCSInterface": { + "@odata.id": "/redfish/v1/Managers/1/KCSInterface" + } + } + } +} \ No newline at end of file diff --git a/redfish-output/supermicro/bigtwin-redfish.json b/redfish-output/supermicro/bigtwin-redfish.json new file mode 100644 index 0000000..4f8d0b5 --- /dev/null +++ b/redfish-output/supermicro/bigtwin-redfish.json @@ -0,0 +1,49 @@ +{ + "@odata.type": "#ServiceRoot.v1_5_2.ServiceRoot", + "@odata.id": "/redfish/v1/", + "Id": "RootService", + "Name": "Root Service", + "RedfishVersion": "1.8.0", + "UUID": "00000000-0000-0000-0000-AC1F6B355AF8", + "Systems": { + "@odata.id": "/redfish/v1/Systems" + }, + "Chassis": { + "@odata.id": "/redfish/v1/Chassis" + }, + "Managers": { + "@odata.id": "/redfish/v1/Managers" + }, + "Tasks": { + "@odata.id": "/redfish/v1/TaskService" + }, + "SessionService": { + "@odata.id": "/redfish/v1/SessionService" + }, + "AccountService": { + "@odata.id": "/redfish/v1/AccountService" + }, + "EventService": { + "@odata.id": "/redfish/v1/EventService" + }, + "UpdateService": { + "@odata.id": "/redfish/v1/UpdateService" + }, + "CertificateService": { + "@odata.id": "/redfish/v1/CertificateService" + }, + "Registries": { + "@odata.id": "/redfish/v1/Registries" + }, + "JsonSchemas": { + "@odata.id": "/redfish/v1/JsonSchemas" + }, + "Links": { + "Sessions": { + "@odata.id": "/redfish/v1/SessionService/Sessions" + } + }, + "Oem": { + "Supermicro": {} + } +} \ No newline at end of file diff --git a/redfish-output/supermicro/bigtwin-systems.json b/redfish-output/supermicro/bigtwin-systems.json new file mode 100644 index 0000000..8d0a4cc --- /dev/null +++ b/redfish-output/supermicro/bigtwin-systems.json @@ -0,0 +1,114 @@ +{ + "@odata.type": "#ComputerSystem.v1_8_0.ComputerSystem", + "@odata.id": "/redfish/v1/Systems/1", + "Id": "1", + "Name": "System", + "Description": "Description of server", + "Status": { + "State": "Enabled", + "Health": "OK" + }, + "SerialNumber": "A328789X9101143", + "PartNumber": "SYS-2029BT-HNTR", + "SystemType": "Physical", + "BiosVersion": "3.3", + "Manufacturer": "Supermicro", + "Model": "SYS-2029BT-HNTR", + "SKU": "To be filled by O.E.M.", + "UUID": "00000000-0000-0000-0000-AC1F6BD39026", + "ProcessorSummary": { + "Count": 2, + "Model": "Intel(R) Xeon(R) processor", + "Status": { + "State": "Enabled", + "Health": "OK", + "HealthRollup": "OK" + }, + "Metrics": { + "@odata.id": "/redfish/v1/Systems/1/ProcessorSummary/ProcessorMetrics" + } + }, + "MemorySummary": { + "TotalSystemMemoryGiB": 96, + "MemoryMirroring": "System", + "Status": { + "State": "Enabled", + "Health": "OK", + "HealthRollup": "OK" + }, + "Metrics": { + "@odata.id": "/redfish/v1/Systems/1/MemorySummary/MemoryMetrics" + } + }, + "IndicatorLED": "Off", + "PowerState": "On", + "Boot": { + "BootSourceOverrideEnabled": "Continuous", + "BootSourceOverrideMode": "UEFI", + "BootSourceOverrideTarget": "Hdd", + "BootSourceOverrideTarget@Redfish.AllowableValues": [ + "None", + "Pxe", + "Floppy", + "Cd", + "Usb", + "Hdd", + "BiosSetup", + "UsbCd" + ] + }, + "Processors": { + "@odata.id": "/redfish/v1/Systems/1/Processors" + }, + "Memory": { + "@odata.id": "/redfish/v1/Systems/1/Memory" + }, + "EthernetInterfaces": { + "@odata.id": "/redfish/v1/Systems/1/EthernetInterfaces" + }, + "NetworkInterfaces": { + "@odata.id": "/redfish/v1/Systems/1/NetworkInterfaces" + }, + "SimpleStorage": { + "@odata.id": "/redfish/v1/Systems/1/SimpleStorage" + }, + "Storage": { + "@odata.id": "/redfish/v1/Systems/1/Storage" + }, + "LogServices": { + "@odata.id": "/redfish/v1/Systems/1/LogServices" + }, + "SecureBoot": { + "@odata.id": "/redfish/v1/Systems/1/SecureBoot" + }, + "Bios": { + "@odata.id": "/redfish/v1/Systems/1/Bios" + }, + "Links": { + "Chassis": [ + { + "@odata.id": "/redfish/v1/Chassis/1" + } + ], + "ManagedBy": [ + { + "@odata.id": "/redfish/v1/Managers/1" + } + ] + }, + "Actions": { + "Oem": {}, + "#ComputerSystem.Reset": { + "target": "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset", + "@Redfish.ActionInfo": "/redfish/v1/Systems/1/ResetActionInfo" + } + }, + "Oem": { + "Supermicro": { + "@odata.type": "#SmcSystemExtensions.v1_0_0.System", + "NodeManager": { + "@odata.id": "/redfish/v1/Systems/1/SmcNodeManager" + } + } + } +} \ No newline at end of file diff --git a/redfish-output/supermicro/microcloud-chassis.json b/redfish-output/supermicro/microcloud-chassis.json new file mode 100644 index 0000000..759cfc1 --- /dev/null +++ b/redfish-output/supermicro/microcloud-chassis.json @@ -0,0 +1,64 @@ +{ + "@odata.type": "#Chassis.v1_10_0.Chassis", + "@odata.id": "/redfish/v1/Chassis/1", + "Id": "1", + "Name": "Computer System Chassis", + "ChassisType": "RackMount", + "SerialNumber": "C9380AJ02P50085", + "PartNumber": "CSE-938NH-R1K68BP", + "AssetTag": "", + "IndicatorLED": "Off", + "Status": { + "State": "Enabled", + "Health": "OK", + "HealthRollup": "OK" + }, + "PhysicalSecurity": { + "IntrusionSensorNumber": 170, + "IntrusionSensor": "Normal", + "IntrusionSensorReArm": "Manual" + }, + "Power": { + "@odata.id": "/redfish/v1/Chassis/1/Power" + }, + "PCIeDevices": { + "@odata.id": "/redfish/v1/Chassis/1/PCIeDevices" + }, + "Thermal": { + "@odata.id": "/redfish/v1/Chassis/1/Thermal" + }, + "NetworkAdapters": { + "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters" + }, + "PCIeSlots": { + "@odata.id": "/redfish/v1/Chassis/1/PCIeSlots" + }, + "Sensors": { + "@odata.id": "/redfish/v1/Chassis/1/Sensors" + }, + "Links": { + "ComputerSystems": [ + { + "@odata.id": "/redfish/v1/Systems/1" + } + ], + "ManagedBy": [ + { + "@odata.id": "/redfish/v1/Managers/1" + } + ], + "ManagersInChassis": [ + { + "@odata.id": "/redfish/v1/Managers/1" + } + ] + }, + "Oem": { + "Supermicro": { + "@odata.type": "#SmcChassisExtensions.v1_0_0.Chassis", + "BoardSerialNumber": "WM198S002827", + "GUID": "34313031-4D53-0025-90BD-139500000000", + "BoardID": "0x1b1c" + } + } +} \ No newline at end of file diff --git a/redfish-output/supermicro/microcloud-redfish.json b/redfish-output/supermicro/microcloud-redfish.json new file mode 100644 index 0000000..b363c2b --- /dev/null +++ b/redfish-output/supermicro/microcloud-redfish.json @@ -0,0 +1,49 @@ +{ + "@odata.type": "#ServiceRoot.v1_5_2.ServiceRoot", + "@odata.id": "/redfish/v1/", + "Id": "RootService", + "Name": "Root Service", + "RedfishVersion": "1.8.0", + "UUID": "00000000-0000-0000-0000-002590BD1395", + "Systems": { + "@odata.id": "/redfish/v1/Systems" + }, + "Chassis": { + "@odata.id": "/redfish/v1/Chassis" + }, + "Managers": { + "@odata.id": "/redfish/v1/Managers" + }, + "Tasks": { + "@odata.id": "/redfish/v1/TaskService" + }, + "SessionService": { + "@odata.id": "/redfish/v1/SessionService" + }, + "AccountService": { + "@odata.id": "/redfish/v1/AccountService" + }, + "EventService": { + "@odata.id": "/redfish/v1/EventService" + }, + "UpdateService": { + "@odata.id": "/redfish/v1/UpdateService" + }, + "CertificateService": { + "@odata.id": "/redfish/v1/CertificateService" + }, + "Registries": { + "@odata.id": "/redfish/v1/Registries" + }, + "JsonSchemas": { + "@odata.id": "/redfish/v1/JsonSchemas" + }, + "Links": { + "Sessions": { + "@odata.id": "/redfish/v1/SessionService/Sessions" + } + }, + "Oem": { + "Supermicro": {} + } +} \ No newline at end of file diff --git a/redfish-output/supermicro/microcloud-systems.json b/redfish-output/supermicro/microcloud-systems.json new file mode 100644 index 0000000..989e2a3 --- /dev/null +++ b/redfish-output/supermicro/microcloud-systems.json @@ -0,0 +1,108 @@ +{ + "@odata.type": "#ComputerSystem.v1_8_0.ComputerSystem", + "@odata.id": "/redfish/v1/Systems/1", + "Id": "1", + "Name": "System", + "Description": "Description of server", + "Status": { + "State": "Enabled", + "Health": "OK" + }, + "SerialNumber": "E340538X1400702H", + "PartNumber": "SYS-5039MD8-H8TNR", + "SystemType": "Physical", + "BiosVersion": "1.4b", + "Manufacturer": "Supermicro", + "Model": "SYS-5039MD8-H8TNR", + "SKU": "091715D9", + "UUID": "48EB9200-BE80-11E9-8000-3CECEF22FC1A", + "ProcessorSummary": { + "Count": 1, + "Model": "Intel(R) Xeon(R) processor", + "Status": { + "State": "Enabled", + "Health": "OK", + "HealthRollup": "OK" + }, + "Metrics": { + "@odata.id": "/redfish/v1/Systems/1/ProcessorSummary/ProcessorMetrics" + } + }, + "MemorySummary": { + "TotalSystemMemoryGiB": 32, + "MemoryMirroring": "System", + "Status": { + "State": "Enabled", + "Health": "OK", + "HealthRollup": "OK" + }, + "Metrics": { + "@odata.id": "/redfish/v1/Systems/1/MemorySummary/MemoryMetrics" + } + }, + "IndicatorLED": "Off", + "PowerState": "On", + "Boot": { + "BootSourceOverrideEnabled": "Continuous", + "BootSourceOverrideMode": "UEFI", + "BootSourceOverrideTarget": "Hdd", + "BootSourceOverrideTarget@Redfish.AllowableValues": [ + "None", + "Pxe", + "Floppy", + "Cd", + "Usb", + "Hdd", + "BiosSetup", + "UsbCd" + ] + }, + "Processors": { + "@odata.id": "/redfish/v1/Systems/1/Processors" + }, + "Memory": { + "@odata.id": "/redfish/v1/Systems/1/Memory" + }, + "EthernetInterfaces": { + "@odata.id": "/redfish/v1/Systems/1/EthernetInterfaces" + }, + "NetworkInterfaces": { + "@odata.id": "/redfish/v1/Systems/1/NetworkInterfaces" + }, + "SimpleStorage": { + "@odata.id": "/redfish/v1/Systems/1/SimpleStorage" + }, + "Storage": { + "@odata.id": "/redfish/v1/Systems/1/Storage" + }, + "LogServices": { + "@odata.id": "/redfish/v1/Systems/1/LogServices" + }, + "Links": { + "Chassis": [ + { + "@odata.id": "/redfish/v1/Chassis/1" + } + ], + "ManagedBy": [ + { + "@odata.id": "/redfish/v1/Managers/1" + } + ] + }, + "Actions": { + "Oem": {}, + "#ComputerSystem.Reset": { + "target": "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset", + "@Redfish.ActionInfo": "/redfish/v1/Systems/1/ResetActionInfo" + } + }, + "Oem": { + "Supermicro": { + "@odata.type": "#SmcSystemExtensions.v1_0_0.System", + "NodeManager": { + "@odata.id": "/redfish/v1/Systems/1/SmcNodeManager" + } + } + } +} \ No newline at end of file diff --git a/ssh-console.go b/ssh-console.go new file mode 100644 index 0000000..04864f7 --- /dev/null +++ b/ssh-console.go @@ -0,0 +1,79 @@ +package main + +import ( + "fmt" + "io" + "log" + "os" + + "golang.org/x/crypto/ssh" +) + +func main() { + // Define BMC SSH connection details + bmcIP := "1.1.1.1" // Replace with your BMC IP + username := "foo" // Replace with your username + password := "bar" // Replace with your password + + // Create SSH client configuration + config := &ssh.ClientConfig{ + User: username, + Auth: []ssh.AuthMethod{ + ssh.Password(password), + }, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), // Use proper verification in production + } + + // Connect to the BMC + conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", bmcIP), config) + if err != nil { + log.Fatalf("Failed to connect to BMC: %v", err) + } + defer conn.Close() + + // Start a session + session, err := conn.NewSession() + if err != nil { + log.Fatalf("Failed to create SSH session: %v", err) + } + defer session.Close() + + // Request a pseudo-terminal for interactive sessions + err = session.RequestPty("xterm", 80, 40, ssh.TerminalModes{ + ssh.ECHO: 0, // Disable echo + ssh.TTY_OP_ISPEED: 14400, // Input speed + ssh.TTY_OP_OSPEED: 14400, // Output speed + }) + if err != nil { + log.Fatalf("Failed to request pseudo-terminal: %v", err) + } + + // Start the SOL session + stdin, err := session.StdinPipe() + if err != nil { + log.Fatalf("Failed to get stdin pipe: %v", err) + } + stdout, err := session.StdoutPipe() + if err != nil { + log.Fatalf("Failed to get stdout pipe: %v", err) + } + + go io.Copy(os.Stdout, stdout) // Stream the SOL output to the terminal + + err = session.Start("console 1") // Replace with your BMC's SOL command + if err != nil { + log.Fatalf("Failed to start SOL command: %v", err) + } + + fmt.Println("Serial-over-LAN session active. Press Ctrl+C to exit.") + go func() { + // Allow sending input to the session (optional) + io.Copy(stdin, os.Stdin) + }() + + // Wait for the session to end + err = session.Wait() + if err != nil { + log.Fatalf("Error during SOL session: %v", err) + } +}