From b85aae84c3178c0e6f2a199f093e9c0c9822e4d0 Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Tue, 24 Oct 2023 08:04:14 -0600 Subject: [PATCH 1/5] Fixed HTTP response status code check for all successful codes --- internal/api/smd/smd.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/api/smd/smd.go b/internal/api/smd/smd.go index f257ad2..291ea79 100644 --- a/internal/api/smd/smd.go +++ b/internal/api/smd/smd.go @@ -5,7 +5,6 @@ package smd // https://github.com/alexlovelltroy/hms-smd import ( "fmt" - "net/http" "github.com/bikeshack/magellan/internal/util" // hms "github.com/alexlovelltroy/hms-smd" @@ -52,7 +51,8 @@ func AddRedfishEndpoint(data []byte, headers map[string]string) error { url := makeEndpointUrl("/Inventory/RedfishEndpoints") res, body, err := util.MakeRequest(url, "POST", data, headers) if res != nil { - if res.StatusCode != http.StatusOK { + statusOk := res.StatusCode >= 200 && res.StatusCode < 300 + if !statusOk { return fmt.Errorf("could not add redfish endpoint") } fmt.Printf("%v (%v)\n%s\n", url, res.Status, string(body)) @@ -69,7 +69,8 @@ func UpdateRedfishEndpoint(xname string, data []byte, headers map[string]string) res, body, err := util.MakeRequest(url, "PUT", data, headers) fmt.Printf("%v (%v)\n%s\n", url, res.Status, string(body)) if res != nil { - if res.StatusCode != http.StatusOK { + statusOk := res.StatusCode >= 200 && res.StatusCode < 300 + if !statusOk { return fmt.Errorf("could not update redfish endpoint") } } From 14447ee51e02d7fb0f092f7e550f4ad910ed1322 Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Tue, 24 Oct 2023 08:04:53 -0600 Subject: [PATCH 2/5] Formatted commands in `magellan.sh` script --- bin/magellan.sh | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/bin/magellan.sh b/bin/magellan.sh index 4c34a82..3482337 100755 --- a/bin/magellan.sh +++ b/bin/magellan.sh @@ -7,9 +7,10 @@ USER="" PASS="" SMD_HOST="" SMD_PORT="" -THREADS="-1" +THREADS="1" TIMEOUT="30" ARGS="" +FORCE_UPDATE=false function build(){ @@ -18,7 +19,11 @@ function build(){ function scan() { # ./magellan scan --subnet 172.16.0.0 --port 443 - ${EXE} scan --subnet ${SUBNETS} --port ${PORTS} --timeout ${TIMEOUT} --threads ${THREADS} + ${EXE} scan \ + --subnet ${SUBNETS} \ + --port ${PORTS} \ + --timeout ${TIMEOUT} \ + --threads ${THREADS} } function list(){ @@ -28,7 +33,14 @@ function list(){ function collect() { # ./magellan collect --user admin --pass password - ${EXE} collect --user ${USER} --pass ${PASS} --timeout ${TIMEOUT} --threads ${THREADS} --host ${SMD_HOST} --port ${SMD_PORT} + ${EXE} collect \ + --user ${USER} \ + --pass ${PASS} \ + --timeout ${TIMEOUT} \ + --threads ${THREADS} \ + --host ${SMD_HOST} \ + --port ${SMD_PORT} \ + --force-update ${FORCE_UPDATE} } @@ -93,6 +105,8 @@ echo "SMD port = ${SMD_PORT}" echo "subnets = ${SUBNETS}" echo "ports = ${PORTS}" echo "user = ${USER}" +echo "threads = ${THREADS}" +echo "timeout = ${TIMEOUT}" echo "pass = ..." if [[ -n $1 ]]; then From 7a1c799910b2f3d3ac45b496099354ef3dbfe3fa Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Tue, 24 Oct 2023 08:21:30 -0600 Subject: [PATCH 3/5] Changed `Collect*` function calls to reuse gofish client --- internal/collect.go | 45 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/internal/collect.go b/internal/collect.go index 9e63253..10f6ae3 100644 --- a/internal/collect.go +++ b/internal/collect.go @@ -175,8 +175,13 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err json.Unmarshal(inventory, &rm) data["Inventory"] = rm["Inventory"] + c, err := connectGofish(q) + if err != nil { + l.Log.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) + } + // chassis - chassis, err := CollectChassis(q) + chassis, err := CollectChassis(c, q) if err != nil { l.Log.Errorf("could not query chassis: %v", err) continue @@ -212,7 +217,7 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err // data["Processors"] = rm["Processors"] // systems - systems, err := CollectSystems(client, q) + systems, err := CollectSystems(c, q) if err != nil { l.Log.Errorf("could not query systems: %v", err) } @@ -442,12 +447,7 @@ func CollectBios(client *bmclib.Client, q *QueryParams) ([]byte, error) { return b, err } -func CollectEthernetInterfaces(client *bmclib.Client, q *QueryParams, systemID string) ([]byte, error) { - c, err := connectGofish(q) - if err != nil { - return nil, fmt.Errorf("could not connect to bmc: %v", err) - } - +func CollectEthernetInterfaces(c *gofish.APIClient, q *QueryParams, systemID string) ([]byte, error) { systems, err := c.Service.Systems() if err != nil { return nil, fmt.Errorf("could not query storage systems (%v:%v): %v", q.Host, q.Port, err) @@ -478,11 +478,7 @@ func CollectEthernetInterfaces(client *bmclib.Client, q *QueryParams, systemID s return b, nil } -func CollectChassis(q *QueryParams) ([]byte, error) { - c, err := connectGofish(q) - if err != nil { - return nil, fmt.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) - } +func CollectChassis(c *gofish.APIClient, q *QueryParams) ([]byte, error) { chassis, err := c.Service.Chassis() if err != nil { return nil, fmt.Errorf("could not query chassis (%v:%v): %v", q.Host, q.Port, err) @@ -500,12 +496,7 @@ func CollectChassis(q *QueryParams) ([]byte, error) { return b, nil } -func CollectStorage(q *QueryParams) ([]byte, error) { - c, err := connectGofish(q) - if err != nil { - return nil, fmt.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) - } - +func CollectStorage(c *gofish.APIClient, q *QueryParams) ([]byte, error) { systems, err := c.Service.StorageSystems() if err != nil { return nil, fmt.Errorf("could not query storage systems (%v:%v): %v", q.Host, q.Port, err) @@ -533,12 +524,7 @@ func CollectStorage(q *QueryParams) ([]byte, error) { return b, nil } -func CollectSystems(client *bmclib.Client, q *QueryParams) ([]byte, error) { - c, err := connectGofish(q) - if err != nil { - return nil, fmt.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) - } - +func CollectSystems(c *gofish.APIClient, q *QueryParams) ([]byte, error) { systems, err := c.Service.Systems() if err != nil { return nil, fmt.Errorf("could not query systems (%v:%v): %v", q.Host, q.Port, err) @@ -547,7 +533,7 @@ func CollectSystems(client *bmclib.Client, q *QueryParams) ([]byte, error) { // query the system's ethernet interfaces var temp []map[string]any for _, system := range systems { - interfaces, err := CollectEthernetInterfaces(client, q, system.ID) + interfaces, err := CollectEthernetInterfaces(c, q, system.ID) if err != nil { continue } @@ -571,12 +557,7 @@ func CollectSystems(client *bmclib.Client, q *QueryParams) ([]byte, error) { return b, nil } -func CollectRegisteries(q *QueryParams) ([]byte, error) { - c, err := connectGofish(q) - if err != nil { - return nil, fmt.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) - } - +func CollectRegisteries(c *gofish.APIClient, q *QueryParams) ([]byte, error) { registries, err := c.Service.Registries() if err != nil { return nil, fmt.Errorf("could not query storage systems (%v:%v): %v", q.Host, q.Port, err) From b610eda4d8ba1d408b132b8655ad5f9df7866818 Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Tue, 24 Oct 2023 09:20:48 -0600 Subject: [PATCH 4/5] Moved clients out of goroutine to be reused through collection process --- internal/collect.go | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/internal/collect.go b/internal/collect.go index 10f6ae3..67fb2de 100644 --- a/internal/collect.go +++ b/internal/collect.go @@ -130,6 +130,16 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err NodeBMC: -1, } + bmclibClient, err := NewClient(l, q) + if err != nil { + l.Log.Errorf("could not make client: %v", err) + } + + c, err := connectGofish(q) + if err != nil { + l.Log.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) + } + // collect bmc information asynchronously var wg sync.WaitGroup wg.Add(q.Threads) @@ -144,12 +154,6 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err q.Host = ps.Host q.Port = ps.Port - client, err := NewClient(l, q) - if err != nil { - l.Log.Errorf("could not make client: %v", err) - continue - } - node.NodeBMC += 1 // data to be sent to smd @@ -168,18 +172,13 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err var rm map[string]json.RawMessage // inventories - inventory, err := CollectInventory(client, q) + inventory, err := CollectInventory(bmclibClient, q) if err != nil { l.Log.Errorf("could not query inventory (%v:%v): %v", q.Host, q.Port, err) } json.Unmarshal(inventory, &rm) data["Inventory"] = rm["Inventory"] - c, err := connectGofish(q) - if err != nil { - l.Log.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) - } - // chassis chassis, err := CollectChassis(c, q) if err != nil { @@ -345,7 +344,6 @@ func CollectInventory(client *bmclib.Client, q *QueryParams) ([]byte, error) { ctxCancel() return nil, fmt.Errorf("could not open client: %v", err) } - defer client.Close(ctx) inventory, err := client.Inventory(ctx) if err != nil { @@ -377,7 +375,6 @@ func CollectPowerState(client *bmclib.Client, q *QueryParams) ([]byte, error) { ctxCancel() return nil, fmt.Errorf("could not open client: %v", err) } - defer client.Close(ctx) powerState, err := client.GetPowerState(ctx) if err != nil { @@ -545,7 +542,7 @@ func CollectSystems(c *gofish.APIClient, q *QueryParams) ([]byte, error) { }) } - data := map[string]any{"Systems": temp } + data := map[string]any{"Systems": temp} b, err := json.MarshalIndent(data, "", " ") if err != nil { return nil, fmt.Errorf("could not marshal JSON: %v", err) From 6a59ba2a41f5c647b08c7364c3ce6ac58c80f07d Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Tue, 24 Oct 2023 10:03:33 -0600 Subject: [PATCH 5/5] Moved clients back into goroutine and add checks --- internal/collect.go | 112 ++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 72 deletions(-) diff --git a/internal/collect.go b/internal/collect.go index 67fb2de..a8fb815 100644 --- a/internal/collect.go +++ b/internal/collect.go @@ -130,15 +130,6 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err NodeBMC: -1, } - bmclibClient, err := NewClient(l, q) - if err != nil { - l.Log.Errorf("could not make client: %v", err) - } - - c, err := connectGofish(q) - if err != nil { - l.Log.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) - } // collect bmc information asynchronously var wg sync.WaitGroup @@ -156,6 +147,16 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err node.NodeBMC += 1 + bmclibClient, err := NewClient(l, q) + if err != nil { + l.Log.Errorf("could not make client: %v", err) + } + + gofishClient, err := connectGofish(q) + if err != nil { + l.Log.Errorf("could not connect to bmc (%v:%v): %v", q.Host, q.Port, err) + } + // data to be sent to smd data := map[string]any{ "ID": fmt.Sprintf("%v", node.String()[:len(node.String())-2]), @@ -172,73 +173,40 @@ func CollectAll(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) err var rm map[string]json.RawMessage // inventories - inventory, err := CollectInventory(bmclibClient, q) - if err != nil { - l.Log.Errorf("could not query inventory (%v:%v): %v", q.Host, q.Port, err) + if bmclibClient != nil { + inventory, err := CollectInventory(bmclibClient, q) + if err != nil { + l.Log.Errorf("could not query inventory (%v:%v): %v", q.Host, q.Port, err) + } + json.Unmarshal(inventory, &rm) + data["Inventory"] = rm["Inventory"] } - json.Unmarshal(inventory, &rm) - data["Inventory"] = rm["Inventory"] // chassis - chassis, err := CollectChassis(c, q) - if err != nil { - l.Log.Errorf("could not query chassis: %v", err) - continue + if gofishClient != nil { + chassis, err := CollectChassis(gofishClient, q) + if err != nil { + l.Log.Errorf("could not query chassis: %v", err) + continue + } + json.Unmarshal(chassis, &rm) + data["Chassis"] = rm["Chassis"] + + // systems + systems, err := CollectSystems(gofishClient, q) + if err != nil { + l.Log.Errorf("could not query systems: %v", err) + } + json.Unmarshal(systems, &rm) + data["Systems"] = rm["Systems"] + + // add other fields from systems + if len(rm["Systems"]) > 0 { + var s map[string][]interface{} + json.Unmarshal(rm["Systems"], &s) + data["Name"] = s["Name"] + } } - json.Unmarshal(chassis, &rm) - data["Chassis"] = rm["Chassis"] - - // ethernet interfaces - // interfaces, err := QueryEthernetInterfaces(client, q) - // if err != nil { - // l.Log.Errorf("could not query ethernet interfaces: %v", err) - // continue - // } - // json.Unmarshal(interfaces, &rm) - // data["Interfaces"] = rm["Interfaces"] - - // storage - // storage, err := QueryStorage(q) - // if err != nil { - // l.Log.Errorf("could not query storage: %v", err) - // continue - // } - // json.Unmarshal(storage, &rm) - // data["Storage"] = rm["Storage"] - - // get specific processor info - // procs, err := QueryProcessors(q) - // if err != nil { - // l.Log.Errorf("could not query processors: %v", err) - // } - // var p map[string]interface{} - // json.Unmarshal(procs, &p) - // data["Processors"] = rm["Processors"] - - // systems - systems, err := CollectSystems(c, q) - if err != nil { - l.Log.Errorf("could not query systems: %v", err) - } - json.Unmarshal(systems, &rm) - data["Systems"] = rm["Systems"] - - // add other fields from systems - if len(rm["Systems"]) > 0 { - var s map[string][]interface{} - json.Unmarshal(rm["Systems"], &s) - data["Name"] = s["Name"] - } - - // data["Type"] = rm[""] - - // registries - // registries, err := QueryRegisteries(q) - // if err != nil { - // l.Log.Errorf("could not query registries: %v", err) - // } - // json.Unmarshal(registries, &rm) - // data["Registries"] = rm["Registries"] headers := make(map[string]string) headers["Content-Type"] = "application/json"