From 028e2ebb8a168112a592ed44d1d07ce0a99fe851 Mon Sep 17 00:00:00 2001 From: Stefan Catargiu <13122921+5kt@users.noreply.github.com> Date: Fri, 3 May 2024 11:04:28 +0200 Subject: [PATCH] Update redfish/ipmi for the new readinfo --- internal/bmc/ipmi.go | 61 +------------------------- internal/bmc/redfish.go | 97 ++++++++++------------------------------- 2 files changed, 26 insertions(+), 132 deletions(-) diff --git a/internal/bmc/ipmi.go b/internal/bmc/ipmi.go index 10dc9a66..e93d2b8a 100644 --- a/internal/bmc/ipmi.go +++ b/internal/bmc/ipmi.go @@ -14,9 +14,6 @@ import ( "time" "github.com/hashicorp/go-multierror" - "golang.org/x/text/cases" - "golang.org/x/text/language" - "github.com/ironcore-dev/metal/internal/log" ) @@ -146,62 +143,8 @@ func (b *IPMIBMC) Connect(ctx context.Context) error { func (b *IPMIBMC) ReadInfo(ctx context.Context) (Info, error) { log.Debug(ctx, "Reading BMC info", "host", b.host) - info := make(map[string]string) - - out, serr, err := ipmiExecuteCommand(ctx, b.host, b.port, b.creds, "ipmitool", "fru", "list", "0") - if err != nil { - return Info{}, fmt.Errorf("cannot get fru info, stderr: %s: %w", serr, err) - } - outputmap(out, &info) - - out, serr, err = ipmiExecuteCommand(ctx, b.host, b.port, b.creds, "ipmitool", "mc", "guid") - if err != nil { - return Info{}, fmt.Errorf("cannot get mc info, stderr: %s: %w", serr, err) - } - outputmap(out, &info) - - out, serr, err = ipmiExecuteCommand(ctx, b.host, b.port, b.creds, "ipmi-chassis", "--get-chassis-status") - if err != nil { - return Info{}, fmt.Errorf("cannot get chassis status, stderr: %s: %w", serr, err) - } - outputmap(out, &info) - - out, serr, err = ipmiExecuteCommand(ctx, b.host, b.port, b.creds, "ipmitool", "bmc", "info") - if err != nil { - return Info{}, fmt.Errorf("cannot get bmc info, stderr: %s: %w", serr, err) - } - outputmap(out, &info) - - uuid, ok := info["System GUID"] - if !ok { - return Info{}, fmt.Errorf("cannot determine uuid for machine") - } - uuid = strings.ToLower(uuid) - powerstate, ok := info["System Power"] - if !ok { - return Info{}, fmt.Errorf("cannot determine the power state for machine") - } - serial := info["Product Serial"] - sku := info["Product SKU"] - manufacturer := info["Manufacturer"] - //TODO: currently we can't handle this correctly as we can't read the state on most hardware - //led, ok := info["Chassis Identify State"] - led := "" - fw := info["Firmware Revision"] - - //TODO: properly detect if sol is supported - return Info{ - UUID: uuid, - Type: "BMC", - Capabilities: []string{"credentials", "power", "led", "console"}, - SerialNumber: serial, - SKU: sku, - Manufacturer: manufacturer, - LocatorLED: LED(led), - Power: Power(cases.Title(language.English).String(powerstate)), - Console: "ipmi", - FWVersion: fw, - }, nil + // TODO: implement proper ipmi readinfo + return Info{}, nil } func ipmiGenerateCommand(ctx context.Context, host string, port int32, creds Credentials, cmd ...string) ([]string, error) { diff --git a/internal/bmc/redfish.go b/internal/bmc/redfish.go index 3cf1d29e..ead011a8 100644 --- a/internal/bmc/redfish.go +++ b/internal/bmc/redfish.go @@ -601,60 +601,9 @@ func (b *RedfishBMC) ReadInfo(ctx context.Context) (Info, error) { defer c.Logout() log.Debug(ctx, "Reading BMC info") - systems, err := c.Service.Systems() - if err != nil { - return Info{}, fmt.Errorf("cannot get systems information: %w", err) - } - if len(systems) == 0 { - return Info{}, fmt.Errorf("cannot get systems information") - } - - uuid := systems[0].UUID - if uuid == "" { - return Info{}, fmt.Errorf("BMC has no UUID attribute") - } - uuid = strings.ToLower(uuid) - - led := LED(systems[0].IndicatorLED) - - // Reading the OS state is supported only on Lenovo hardware - var os, osReason string - if len(systems) > 0 { - sys := systems[0] - sysRaw, err := c.Get(sys.ODataID) - if err != nil { - return Info{}, fmt.Errorf("cannot get systems (raw): %w", err) - } - osStatus := struct { - OEM struct { - Lenovo struct { - SystemStatus *string `json:"SystemStatus"` - } `json:"Lenovo"` - } `json:"OEM"` - }{} - - decoder := json.NewDecoder(sysRaw.Body) - err = decoder.Decode(&osStatus) - if err != nil { - return Info{}, fmt.Errorf("cannot decode information for OS status: %w", err) - } - - if osStatus.OEM.Lenovo.SystemStatus != nil { - if sys.PowerState == redfish.OffPowerState { - osReason = "PoweredOff" - } else if state := *osStatus.OEM.Lenovo.SystemStatus; state == "OSBooted" || state == "BootingOSOrInUndetectedOS" { - os = "Ok" - osReason = state - } else { - osReason = state - } - } - } - - manufacturer := systems[0].Manufacturer - capabilities := []string{"credentials", "power", "led"} - console := "" - fw := "" + info := Info{} + manufacturer := c.Service.Vendor + info.Manufacturer = manufacturer mgr, err := c.Service.Managers() if err != nil { @@ -664,30 +613,32 @@ func (b *RedfishBMC) ReadInfo(ctx context.Context) (Info, error) { consoleList := mgr[0].SerialConsole.ConnectTypesSupported if mgr[0].SerialConsole.ServiceEnabled { if strings.ToLower(manufacturer) == "lenovo" && isConsoleTypeSupported(consoleList, redfish.SSHSerialConnectTypesSupported) { - capabilities = append(capabilities, "console") - console = "ssh-lenovo" + info.Console = "ssh-lenovo" } else if isConsoleTypeSupported(consoleList, redfish.IPMISerialConnectTypesSupported) { - capabilities = append(capabilities, "console") - console = "ipmi" + info.Console = "ipmi" } - fw = mgr[0].FirmwareVersion + info.FirmwareVersion = mgr[0].FirmwareVersion } } - return Info{ - UUID: uuid, - Type: "BMC", - Capabilities: capabilities, - SerialNumber: systems[0].SerialNumber, - SKU: systems[0].SKU, - Manufacturer: manufacturer, - LocatorLED: led, - Power: Power(fmt.Sprintf("%v", systems[0].PowerState)), - OS: os, - OSReason: osReason, - Console: console, - FWVersion: fw, - }, nil + systems, err := c.Service.Systems() + if err != nil { + return Info{}, fmt.Errorf("cannot get systems information: %w", err) + } + for _, system := range systems { + machine := Machine{} + machine.Manufacturer = manufacturer + machine.Power = Power(fmt.Sprintf("%v", system.PowerState)) + machine.SKU = system.SKU + machine.LocatorLED = LED(system.IndicatorLED) + machine.SerialNumber = system.SerialNumber + machine.UUID = strings.ToLower(system.UUID) + if machine.UUID == "" { + return Info{}, fmt.Errorf("System has no UUID") + } + info.Machines = append(info.Machines, machine) + } + return info, nil } func isConsoleTypeSupported(consoleList []redfish.SerialConnectTypesSupported, console redfish.SerialConnectTypesSupported) bool {