move to OpenCHAMI and update changelog

This commit is contained in:
Alex Lovell-Troy 2023-11-03 09:47:57 -04:00
parent 955c9fb4bd
commit cccf0dfdf2
14 changed files with 96 additions and 91 deletions

View file

@ -10,10 +10,10 @@ builds:
- amd64 - amd64
dockers: dockers:
- image_templates: - image_templates:
- bikeshack/{{.ProjectName}}:latest - ghcr.io/OpenCHAMI/{{.ProjectName}}:latest
- bikeshack/{{.ProjectName}}:{{ .Tag }} - ghcr.io/OpenCHAMI/{{.ProjectName}}:{{ .Tag }}
- bikeshack/{{.ProjectName}}:{{ .Major }} - ghcr.io/OpenCHAMI/{{.ProjectName}}:{{ .Major }}
- bikeshack/{{.ProjectName}}:{{ .Major }}.{{ .Minor }} - ghcr.io/OpenCHAMI/{{.ProjectName}}:{{ .Major }}.{{ .Minor }}
build_flag_templates: build_flag_templates:
- "--pull" - "--pull"
- "--label=org.opencontainers.image.created={{.Date}}" - "--label=org.opencontainers.image.created={{.Date}}"

View file

@ -5,7 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.0.5] - 2023-11-02
### Added
* Ability to update firmware
* Refactored connection handling for faster scanning
* Updated to refelct home at github.com/OpenCHAMI
* Updated to reflect ghcr.io as container home
## [Unreleased]
## [0.0.1] - 2023-09-14 ## [0.0.1] - 2023-09-14

View file

@ -1,10 +1,10 @@
package cmd package cmd
import ( import (
magellan "github.com/OpenChami/magellan/internal" magellan "github.com/OpenCHAMI/magellan/internal"
"github.com/OpenChami/magellan/internal/api/smd" "github.com/OpenCHAMI/magellan/internal/api/smd"
"github.com/OpenChami/magellan/internal/db/sqlite" "github.com/OpenCHAMI/magellan/internal/db/sqlite"
"github.com/OpenChami/magellan/internal/log" "github.com/OpenCHAMI/magellan/internal/log"
"github.com/cznic/mathutil" "github.com/cznic/mathutil"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"

View file

@ -3,7 +3,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/OpenChami/magellan/internal/db/sqlite" "github.com/OpenCHAMI/magellan/internal/db/sqlite"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"

View file

@ -6,18 +6,18 @@ import (
"os" "os"
"path" "path"
magellan "github.com/OpenChami/magellan/internal" magellan "github.com/OpenCHAMI/magellan/internal"
"github.com/OpenChami/magellan/internal/db/sqlite" "github.com/OpenCHAMI/magellan/internal/db/sqlite"
"github.com/cznic/mathutil" "github.com/cznic/mathutil"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var ( var (
begin uint8 begin uint8
end uint8 end uint8
subnets []string subnets []string
subnetMasks []net.IP subnetMasks []net.IP
disableProbing bool disableProbing bool
) )
@ -35,10 +35,10 @@ var scanCmd = &cobra.Command{
return return
} }
if len(subnetMasks) < i + 1 { if len(subnetMasks) < i+1 {
subnetMasks = append(subnetMasks, net.IP{255, 255, 255, 0}) subnetMasks = append(subnetMasks, net.IP{255, 255, 255, 0})
} }
hostsToScan = append(hostsToScan, magellan.GenerateHosts(subnet, &subnetMasks[i])...) hostsToScan = append(hostsToScan, magellan.GenerateHosts(subnet, &subnetMasks[i])...)
} }
} }

View file

@ -1,45 +1,45 @@
package cmd package cmd
import ( import (
magellan "github.com/OpenChami/magellan/internal" magellan "github.com/OpenCHAMI/magellan/internal"
"github.com/OpenChami/magellan/internal/log" "github.com/OpenCHAMI/magellan/internal/log"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var ( var (
host string host string
port int port int
firmwareUrl string firmwareUrl string
firmwareVersion string firmwareVersion string
component string component string
transferProtocol string transferProtocol string
status bool status bool
) )
var updateCmd = &cobra.Command{ var updateCmd = &cobra.Command{
Use: "update", Use: "update",
Short: "Update BMC node firmware", Short: "Update BMC node firmware",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
l := log.NewLogger(logrus.New(), logrus.DebugLevel) l := log.NewLogger(logrus.New(), logrus.DebugLevel)
q := &magellan.UpdateParams { q := &magellan.UpdateParams{
FirmwarePath: firmwareUrl, FirmwarePath: firmwareUrl,
FirmwareVersion: firmwareVersion, FirmwareVersion: firmwareVersion,
Component: component, Component: component,
TransferProtocol: transferProtocol, TransferProtocol: transferProtocol,
QueryParams: magellan.QueryParams{ QueryParams: magellan.QueryParams{
Drivers: []string{"redfish"}, Drivers: []string{"redfish"},
Preferred: "redfish", Preferred: "redfish",
Protocol: protocol, Protocol: protocol,
Host: host, Host: host,
User: user, User: user,
Pass: pass, Pass: pass,
Timeout: timeout, Timeout: timeout,
Port: port, Port: port,
WithSecureTLS: withSecureTLS, WithSecureTLS: withSecureTLS,
}, },
} }
// check if required params are set // check if required params are set
if host == "" || user == "" || pass == "" { if host == "" || user == "" || pass == "" {
l.Log.Fatal("requires host, user, and pass to be set") l.Log.Fatal("requires host, user, and pass to be set")
@ -53,7 +53,7 @@ var updateCmd = &cobra.Command{
} }
return return
} }
// client, err := magellan.NewClient(l, &q.QueryParams) // client, err := magellan.NewClient(l, &q.QueryParams)
// if err != nil { // if err != nil {
// l.Log.Errorf("could not make client: %v", err) // l.Log.Errorf("could not make client: %v", err)
@ -79,4 +79,4 @@ func init() {
updateCmd.Flags().BoolVar(&withSecureTLS, "secure-tls", false, "enable secure TLS") updateCmd.Flags().BoolVar(&withSecureTLS, "secure-tls", false, "enable secure TLS")
updateCmd.Flags().BoolVar(&status, "status", false, "get the status of the update") updateCmd.Flags().BoolVar(&status, "status", false, "get the status of the update")
rootCmd.AddCommand(updateCmd) rootCmd.AddCommand(updateCmd)
} }

2
go.mod
View file

@ -1,4 +1,4 @@
module github.com/OpenChami/magellan module github.com/OpenCHAMI/magellan
go 1.20 go 1.20

View file

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/OpenChami/magellan/internal/util" "github.com/OpenCHAMI/magellan/internal/util"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
) )

View file

@ -6,7 +6,7 @@ package smd
import ( import (
"fmt" "fmt"
"github.com/OpenChami/magellan/internal/util" "github.com/OpenCHAMI/magellan/internal/util"
// hms "github.com/alexlovelltroy/hms-smd" // hms "github.com/alexlovelltroy/hms-smd"
) )

View file

@ -12,10 +12,10 @@ import (
"sync" "sync"
"time" "time"
"github.com/OpenChami/magellan/internal/log" "github.com/OpenCHAMI/magellan/internal/log"
"github.com/OpenChami/magellan/internal/api/smd" "github.com/OpenCHAMI/magellan/internal/api/smd"
"github.com/OpenChami/magellan/internal/util" "github.com/OpenCHAMI/magellan/internal/util"
"github.com/Cray-HPE/hms-xname/xnames" "github.com/Cray-HPE/hms-xname/xnames"
bmclib "github.com/bmc-toolbox/bmclib/v2" bmclib "github.com/bmc-toolbox/bmclib/v2"
@ -33,7 +33,6 @@ const (
HTTPS_PORT = 443 HTTPS_PORT = 443
) )
// NOTE: ...params were getting too long... // NOTE: ...params were getting too long...
type QueryParams struct { type QueryParams struct {
Host string Host string
@ -121,7 +120,7 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err
found := make([]string, 0, len(*probeStates)) found := make([]string, 0, len(*probeStates))
done := make(chan struct{}, q.Threads+1) done := make(chan struct{}, q.Threads+1)
chanProbeState := make(chan ScannedResult, q.Threads+1) chanProbeState := make(chan ScannedResult, q.Threads+1)
// collect bmc information asynchronously // collect bmc information asynchronously
var offset = 0 var offset = 0
var wg sync.WaitGroup var wg sync.WaitGroup
@ -136,7 +135,7 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err
} }
q.Host = ps.Host q.Host = ps.Host
q.Port = ps.Port q.Port = ps.Port
// generate custom xnames for bmcs // generate custom xnames for bmcs
node := xnames.Node{ node := xnames.Node{
Cabinet: 1000, Cabinet: 1000,
@ -158,13 +157,13 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err
// data to be sent to smd // data to be sent to smd
data := map[string]any{ data := map[string]any{
"ID": fmt.Sprintf("%v", node.String()[:len(node.String())-2]), "ID": fmt.Sprintf("%v", node.String()[:len(node.String())-2]),
"Type": "", "Type": "",
"Name": "", "Name": "",
"FQDN": ps.Host, "FQDN": ps.Host,
"User": q.User, "User": q.User,
"Password": q.Pass, "Password": q.Pass,
"MACRequired": true, "MACRequired": true,
"RediscoverOnUpdate": false, "RediscoverOnUpdate": false,
} }
@ -220,7 +219,7 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err
} }
// write JSON data to file // write JSON data to file
err = os.WriteFile(path.Clean(outputPath + "/" + q.Host + ".json"), body, os.ModePerm) err = os.WriteFile(path.Clean(outputPath+"/"+q.Host+".json"), body, os.ModePerm)
if err != nil { if err != nil {
l.Log.Errorf("could not write data to file: %v", err) l.Log.Errorf("could not write data to file: %v", err)
} }
@ -319,7 +318,6 @@ func CollectInventory(client *bmclib.Client, q *QueryParams) ([]byte, error) {
return nil, fmt.Errorf("could not get inventory: %v", err) return nil, fmt.Errorf("could not get inventory: %v", err)
} }
// retrieve inventory data // retrieve inventory data
data := map[string]any{"Inventory": inventory} data := map[string]any{"Inventory": inventory}
b, err := json.MarshalIndent(data, "", " ") b, err := json.MarshalIndent(data, "", " ")
@ -379,7 +377,7 @@ func CollectUsers(client *bmclib.Client, q *QueryParams) ([]byte, error) {
} }
// retrieve inventory data // retrieve inventory data
data := map[string]any {"Users": users} data := map[string]any{"Users": users}
b, err := json.MarshalIndent(data, "", " ") b, err := json.MarshalIndent(data, "", " ")
if err != nil { if err != nil {
ctxCancel() ctxCancel()
@ -407,13 +405,13 @@ func CollectEthernetInterfaces(c *gofish.APIClient, q *QueryParams, systemID str
var interfaces []*redfish.EthernetInterface var interfaces []*redfish.EthernetInterface
for _, system := range systems { for _, system := range systems {
i, err := redfish.ListReferencedEthernetInterfaces(c, "/redfish/v1/Systems/" + system.ID + "/EthernetInterfaces/") i, err := redfish.ListReferencedEthernetInterfaces(c, "/redfish/v1/Systems/"+system.ID+"/EthernetInterfaces/")
if err != nil { if err != nil {
continue continue
} }
interfaces = append(interfaces, i...) interfaces = append(interfaces, i...)
} }
if len(interfaces) <= 0 { if len(interfaces) <= 0 {
return nil, fmt.Errorf("could not get ethernet interfaces: %v", err) return nil, fmt.Errorf("could not get ethernet interfaces: %v", err)
} }
@ -442,7 +440,7 @@ func CollectChassis(c *gofish.APIClient, q *QueryParams) ([]byte, error) {
return b, nil return b, nil
} }
func CollectStorage(c *gofish.APIClient, q *QueryParams) ([]byte, error) { func CollectStorage(c *gofish.APIClient, q *QueryParams) ([]byte, error) {
systems, err := c.Service.StorageSystems() systems, err := c.Service.StorageSystems()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not query storage systems (%v:%v): %v", q.Host, q.Port, err) return nil, fmt.Errorf("could not query storage systems (%v:%v): %v", q.Host, q.Port, err)
@ -455,7 +453,7 @@ func CollectStorage(c *gofish.APIClient, q *QueryParams) ([]byte, error) {
data := map[string]any{ data := map[string]any{
"Storage": map[string]any{ "Storage": map[string]any{
"Systems": systems, "Systems": systems,
"Services": services, "Services": services,
}, },
} }
@ -483,7 +481,7 @@ func CollectSystems(c *gofish.APIClient, q *QueryParams) ([]byte, error) {
var i map[string]any var i map[string]any
json.Unmarshal(interfaces, &i) json.Unmarshal(interfaces, &i)
temp = append(temp, map[string]any{ temp = append(temp, map[string]any{
"Data": system, "Data": system,
"EthernetInterfaces": i["EthernetInterfaces"], "EthernetInterfaces": i["EthernetInterfaces"],
}) })
} }
@ -503,7 +501,7 @@ func CollectRegisteries(c *gofish.APIClient, q *QueryParams) ([]byte, error) {
return nil, fmt.Errorf("could not query storage systems (%v:%v): %v", q.Host, q.Port, err) return nil, fmt.Errorf("could not query storage systems (%v:%v): %v", q.Host, q.Port, err)
} }
data := map[string]any{"Registries": registries } data := map[string]any{"Registries": registries}
b, err := json.MarshalIndent(data, "", " ") b, err := json.MarshalIndent(data, "", " ")
if err != nil { if err != nil {
return nil, fmt.Errorf("could not marshal JSON: %v", err) return nil, fmt.Errorf("could not marshal JSON: %v", err)
@ -543,7 +541,7 @@ func CollectProcessors(q *QueryParams) ([]byte, error) {
} }
} }
data := map[string]any{"Processors": procs } data := map[string]any{"Processors": procs}
b, err := json.MarshalIndent(data, "", " ") b, err := json.MarshalIndent(data, "", " ")
if err != nil { if err != nil {
return nil, fmt.Errorf("could not marshal JSON: %v", err) return nil, fmt.Errorf("could not marshal JSON: %v", err)
@ -563,7 +561,7 @@ func connectGofish(q *QueryParams) (*gofish.APIClient, error) {
c.Service.ProtocolFeaturesSupported = gofish.ProtocolFeaturesSupported{ c.Service.ProtocolFeaturesSupported = gofish.ProtocolFeaturesSupported{
ExpandQuery: gofish.Expand{ ExpandQuery: gofish.Expand{
ExpandAll: true, ExpandAll: true,
Links: true, Links: true,
}, },
} }
} }

View file

@ -3,7 +3,7 @@ package sqlite
import ( import (
"fmt" "fmt"
magellan "github.com/OpenChami/magellan/internal" magellan "github.com/OpenCHAMI/magellan/internal"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
) )

View file

@ -8,7 +8,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/OpenChami/magellan/internal/util" "github.com/OpenCHAMI/magellan/internal/util"
) )
type ScannedResult struct { type ScannedResult struct {
@ -51,7 +51,6 @@ func rawConnect(host string, ports []int, timeout int, keepOpenOnly bool) []Scan
return results return results
} }
func GenerateHosts(subnet string, subnetMask *net.IP) []string { func GenerateHosts(subnet string, subnetMask *net.IP) []string {
if subnet == "" || subnetMask == nil { if subnet == "" || subnetMask == nil {
return nil return nil
@ -68,7 +67,7 @@ func GenerateHosts(subnet string, subnetMask *net.IP) []string {
subnetIp = ip subnetIp = ip
if network != nil { if network != nil {
t := net.IP(network.Mask) t := net.IP(network.Mask)
subnetMask = &t subnetMask = &t
} }
} }
@ -82,7 +81,7 @@ func generateHosts(ip *net.IP, mask *net.IPMask) []string {
// get all IP addresses in network // get all IP addresses in network
ones, _ := mask.Size() ones, _ := mask.Size()
hosts := []string{} hosts := []string{}
end := int(math.Pow(2, float64((32-ones))))-1 end := int(math.Pow(2, float64((32-ones)))) - 1
for i := 0; i < end; i++ { for i := 0; i < end; i++ {
// ip[3] = byte(i) // ip[3] = byte(i)
ip = util.GetNextIP(ip, 1) ip = util.GetNextIP(ip, 1)

View file

@ -10,30 +10,29 @@ import (
"strings" "strings"
"time" "time"
"github.com/OpenChami/magellan/internal/log" "github.com/OpenCHAMI/magellan/internal/log"
"github.com/OpenChami/magellan/internal/util" "github.com/OpenCHAMI/magellan/internal/util"
bmclib "github.com/bmc-toolbox/bmclib/v2" bmclib "github.com/bmc-toolbox/bmclib/v2"
"github.com/bmc-toolbox/bmclib/v2/constants" "github.com/bmc-toolbox/bmclib/v2/constants"
bmclibErrs "github.com/bmc-toolbox/bmclib/v2/errors" bmclibErrs "github.com/bmc-toolbox/bmclib/v2/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
type UpdateParams struct { type UpdateParams struct {
QueryParams QueryParams
FirmwarePath string FirmwarePath string
FirmwareVersion string FirmwareVersion string
Component string Component string
TransferProtocol string TransferProtocol string
} }
// NOTE: Does not work since OpenBMC, whic bmclib uses underneath, does not // NOTE: Does not work since OpenBMC, whic bmclib uses underneath, does not
// support multipart updates. See issue: https://github.com/bmc-toolbox/bmclib/issues/341 // support multipart updates. See issue: https://github.com/bmc-toolbox/bmclib/issues/341
func UpdateFirmware(client *bmclib.Client, l *log.Logger, q *UpdateParams) error { func UpdateFirmware(client *bmclib.Client, l *log.Logger, q *UpdateParams) error {
if q.Component == "" { if q.Component == "" {
return fmt.Errorf("component is required") return fmt.Errorf("component is required")
} }
// open BMC session and update driver registry // open BMC session and update driver registry
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(q.Timeout)) ctx, ctxCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(q.Timeout))
client.Registry.FilterForCompatible(ctx) client.Registry.FilterForCompatible(ctx)
@ -121,20 +120,20 @@ func UpdateFirmware(client *bmclib.Client, l *log.Logger, q *UpdateParams) error
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
} }
return nil return nil
} }
func UpdateFirmwareRemote(q *UpdateParams) error { func UpdateFirmwareRemote(q *UpdateParams) error {
url := baseRedfishUrl(&q.QueryParams) + "/redfish/v1/UpdateService/Actions/SimpleUpdate" url := baseRedfishUrl(&q.QueryParams) + "/redfish/v1/UpdateService/Actions/SimpleUpdate"
headers := map[string]string { headers := map[string]string{
"Content-Type": "application/json", "Content-Type": "application/json",
"cache-control": "no-cache", "cache-control": "no-cache",
} }
b := map[string]any{ b := map[string]any{
"UpdateComponent": q.Component, // BMC, BIOS "UpdateComponent": q.Component, // BMC, BIOS
"TransferProtocol": q.TransferProtocol, "TransferProtocol": q.TransferProtocol,
"ImageURI": q.FirmwarePath, "ImageURI": q.FirmwarePath,
} }
data, err := json.Marshal(b) data, err := json.Marshal(b)
if err != nil { if err != nil {
@ -184,12 +183,10 @@ func GetUpdateStatus(q *UpdateParams) error {
// return fmt.Errorf("could not read file: %v", err) // return fmt.Errorf("could not read file: %v", err)
// } // }
// switch q.TransferProtocol { // switch q.TransferProtocol {
// case "HTTP": // case "HTTP":
// default: // default:
// return fmt.Errorf("transfer protocol not supported") // return fmt.Errorf("transfer protocol not supported")
// } // }
// return nil // return nil
// } // }

View file

@ -1,7 +1,7 @@
package main package main
import ( import (
"github.com/OpenChami/magellan/cmd" "github.com/OpenCHAMI/magellan/cmd"
) )
func main() { func main() {