mirror of
https://github.com/davidallendj/magellan.git
synced 2025-12-20 03:27:03 -07:00
Fixed issue with collect requests and other minor changes
This commit is contained in:
parent
a6c95ef646
commit
f7159c9b66
5 changed files with 49 additions and 55 deletions
|
|
@ -7,7 +7,6 @@ import (
|
||||||
magellan "github.com/OpenCHAMI/magellan/internal"
|
magellan "github.com/OpenCHAMI/magellan/internal"
|
||||||
"github.com/OpenCHAMI/magellan/internal/cache/sqlite"
|
"github.com/OpenCHAMI/magellan/internal/cache/sqlite"
|
||||||
"github.com/OpenCHAMI/magellan/internal/util"
|
"github.com/OpenCHAMI/magellan/internal/util"
|
||||||
"github.com/OpenCHAMI/magellan/pkg/client"
|
|
||||||
"github.com/cznic/mathutil"
|
"github.com/cznic/mathutil"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
@ -51,9 +50,10 @@ var collectCmd = &cobra.Command{
|
||||||
|
|
||||||
//
|
//
|
||||||
if concurrency <= 0 {
|
if concurrency <= 0 {
|
||||||
concurrency = mathutil.Clamp(len(scannedResults), 1, 255)
|
concurrency = mathutil.Clamp(len(scannedResults), 1, 10000)
|
||||||
}
|
}
|
||||||
err = magellan.CollectInventory(&scannedResults, &magellan.CollectParams{
|
err = magellan.CollectInventory(&scannedResults, &magellan.CollectParams{
|
||||||
|
URI: host,
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
Timeout: timeout,
|
Timeout: timeout,
|
||||||
|
|
@ -72,14 +72,14 @@ var collectCmd = &cobra.Command{
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
currentUser, _ = user.Current()
|
currentUser, _ = user.Current()
|
||||||
collectCmd.PersistentFlags().StringVar(&client.Host, "host", "", "set the host:port to the SMD API")
|
collectCmd.PersistentFlags().StringVar(&host, "host", "", "Set the URI to the SMD API")
|
||||||
collectCmd.PersistentFlags().StringVar(&username, "username", "", "set the BMC user")
|
collectCmd.PersistentFlags().StringVar(&username, "username", "", "Set the BMC user")
|
||||||
collectCmd.PersistentFlags().StringVar(&password, "password", "", "set the BMC password")
|
collectCmd.PersistentFlags().StringVar(&password, "password", "", "Set the BMC password")
|
||||||
collectCmd.PersistentFlags().StringVar(&scheme, "scheme", "https", "set the scheme used to query")
|
collectCmd.PersistentFlags().StringVar(&scheme, "scheme", "https", "Set the scheme used to query")
|
||||||
collectCmd.PersistentFlags().StringVar(&protocol, "protocol", "tcp", "set the protocol used to query")
|
collectCmd.PersistentFlags().StringVar(&protocol, "protocol", "tcp", "Set the protocol used to query")
|
||||||
collectCmd.PersistentFlags().StringVarP(&outputPath, "output", "o", fmt.Sprintf("/tmp/%smagellan/inventory/", currentUser.Username+"/"), "set the path to store collection data")
|
collectCmd.PersistentFlags().StringVarP(&outputPath, "output", "o", fmt.Sprintf("/tmp/%smagellan/inventory/", currentUser.Username+"/"), "set the path to store collection data")
|
||||||
collectCmd.PersistentFlags().BoolVar(&forceUpdate, "force-update", false, "set flag to force update data sent to SMD")
|
collectCmd.PersistentFlags().BoolVar(&forceUpdate, "force-update", false, "Set flag to force update data sent to SMD")
|
||||||
collectCmd.PersistentFlags().StringVar(&cacertPath, "cacert", "", "path to CA cert. (defaults to system CAs)")
|
collectCmd.PersistentFlags().StringVar(&cacertPath, "cacert", "", "Path to CA cert. (defaults to system CAs)")
|
||||||
|
|
||||||
// set flags to only be used together
|
// set flags to only be used together
|
||||||
collectCmd.MarkFlagsRequiredTogether("username", "password")
|
collectCmd.MarkFlagsRequiredTogether("username", "password")
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"os/user"
|
"os/user"
|
||||||
|
|
||||||
magellan "github.com/OpenCHAMI/magellan/internal"
|
magellan "github.com/OpenCHAMI/magellan/internal"
|
||||||
"github.com/OpenCHAMI/magellan/pkg/client"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
@ -112,14 +111,14 @@ func SetDefaults() {
|
||||||
viper.SetDefault("config", "")
|
viper.SetDefault("config", "")
|
||||||
viper.SetDefault("verbose", false)
|
viper.SetDefault("verbose", false)
|
||||||
viper.SetDefault("debug", false)
|
viper.SetDefault("debug", false)
|
||||||
viper.SetDefault("cache", fmt.Sprintf("/tmp/%s/magellan/magellan.db", currentUser.Username))
|
viper.SetDefault("cache", fmt.Sprintf("/tmp/%s/magellan/assets.db", currentUser.Username))
|
||||||
viper.SetDefault("scan.hosts", []string{})
|
viper.SetDefault("scan.hosts", []string{})
|
||||||
viper.SetDefault("scan.ports", []int{})
|
viper.SetDefault("scan.ports", []int{})
|
||||||
viper.SetDefault("scan.subnets", []string{})
|
viper.SetDefault("scan.subnets", []string{})
|
||||||
viper.SetDefault("scan.subnet-masks", []net.IP{})
|
viper.SetDefault("scan.subnet-masks", []net.IP{})
|
||||||
viper.SetDefault("scan.disable-probing", false)
|
viper.SetDefault("scan.disable-probing", false)
|
||||||
viper.SetDefault("collect.driver", []string{"redfish"})
|
viper.SetDefault("collect.driver", []string{"redfish"})
|
||||||
viper.SetDefault("collect.host", client.Host)
|
viper.SetDefault("collect.host", host)
|
||||||
viper.SetDefault("collect.user", "")
|
viper.SetDefault("collect.user", "")
|
||||||
viper.SetDefault("collect.pass", "")
|
viper.SetDefault("collect.pass", "")
|
||||||
viper.SetDefault("collect.protocol", "tcp")
|
viper.SetDefault("collect.protocol", "tcp")
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ update:
|
||||||
port: 443
|
port: 443
|
||||||
username: "admin"
|
username: "admin"
|
||||||
password: "password"
|
password: "password"
|
||||||
transfer-protocol: "HTTPS"
|
transfer-protocol: "https"
|
||||||
firmware:
|
firmware:
|
||||||
url:
|
url:
|
||||||
version:
|
version:
|
||||||
|
|
|
||||||
|
|
@ -21,17 +21,10 @@ import (
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
IPMI_PORT = 623
|
|
||||||
SSH_PORT = 22
|
|
||||||
HTTPS_PORT = 443
|
|
||||||
)
|
|
||||||
|
|
||||||
// CollectParams is a collection of common parameters passed to the CLI
|
// CollectParams is a collection of common parameters passed to the CLI
|
||||||
// for the 'collect' subcommand.
|
// for the 'collect' subcommand.
|
||||||
type CollectParams struct {
|
type CollectParams struct {
|
||||||
Host string // set by the 'host' flag
|
URI string // set by the 'host' flag
|
||||||
Port int // set by the 'port' flag
|
|
||||||
Username string // set the BMC username with the 'username' flag
|
Username string // set the BMC username with the 'username' flag
|
||||||
Password string // set the BMC password with the 'password' flag
|
Password string // set the BMC password with the 'password' flag
|
||||||
Concurrency int // set the of concurrent jobs with the 'concurrency' flag
|
Concurrency int // set the of concurrent jobs with the 'concurrency' flag
|
||||||
|
|
@ -48,38 +41,38 @@ type CollectParams struct {
|
||||||
//
|
//
|
||||||
// Requests can be made to several of the nodes using a goroutine by setting the q.Concurrency
|
// Requests can be made to several of the nodes using a goroutine by setting the q.Concurrency
|
||||||
// property value between 1 and 255.
|
// property value between 1 and 255.
|
||||||
func CollectInventory(scannedResults *[]RemoteAsset, params *CollectParams) error {
|
func CollectInventory(assets *[]RemoteAsset, params *CollectParams) error {
|
||||||
// check for available probe states
|
// check for available probe states
|
||||||
if scannedResults == nil {
|
if assets == nil {
|
||||||
return fmt.Errorf("no probe states found")
|
return fmt.Errorf("no assets found")
|
||||||
}
|
}
|
||||||
if len(*scannedResults) <= 0 {
|
if len(*assets) <= 0 {
|
||||||
return fmt.Errorf("no probe states found")
|
return fmt.Errorf("no assets found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect bmc information asynchronously
|
// collect bmc information asynchronously
|
||||||
var (
|
var (
|
||||||
offset = 0
|
offset = 0
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
found = make([]string, 0, len(*scannedResults))
|
found = make([]string, 0, len(*assets))
|
||||||
done = make(chan struct{}, params.Concurrency+1)
|
done = make(chan struct{}, params.Concurrency+1)
|
||||||
chanScannedResult = make(chan RemoteAsset, params.Concurrency+1)
|
chanAssets = make(chan RemoteAsset, params.Concurrency+1)
|
||||||
outputPath = path.Clean(params.OutputPath)
|
outputPath = path.Clean(params.OutputPath)
|
||||||
smdClient = client.NewClient[client.SmdClient](
|
smdClient = client.NewClient[client.SmdClient](
|
||||||
client.WithSecureTLS[client.SmdClient](params.CaCertPath),
|
client.WithSecureTLS[client.SmdClient](params.CaCertPath),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
// set the client's host from the CLI param
|
||||||
|
smdClient.URI = params.URI
|
||||||
wg.Add(params.Concurrency)
|
wg.Add(params.Concurrency)
|
||||||
for i := 0; i < params.Concurrency; i++ {
|
for i := 0; i < params.Concurrency; i++ {
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
sr, ok := <-chanScannedResult
|
sr, ok := <-chanAssets
|
||||||
if !ok {
|
if !ok {
|
||||||
wg.Done()
|
wg.Done()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
params.Host = sr.Host
|
|
||||||
params.Port = sr.Port
|
|
||||||
|
|
||||||
// generate custom xnames for bmcs
|
// generate custom xnames for bmcs
|
||||||
node := xnames.Node{
|
node := xnames.Node{
|
||||||
|
|
@ -142,7 +135,7 @@ func CollectInventory(scannedResults *[]RemoteAsset, params *CollectParams) erro
|
||||||
log.Error().Err(err).Msg("failed to make output directory")
|
log.Error().Err(err).Msg("failed to make output directory")
|
||||||
} else {
|
} else {
|
||||||
// write the output to the final path
|
// write the output to the final path
|
||||||
err = os.WriteFile(path.Clean(fmt.Sprintf("%s/%s/%d.json", params.Host, outputPath, time.Now().Unix())), body, os.ModePerm)
|
err = os.WriteFile(path.Clean(fmt.Sprintf("%s/%s/%d.json", params.URI, outputPath, time.Now().Unix())), body, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("failed to write data to file")
|
log.Error().Err(err).Msgf("failed to write data to file")
|
||||||
}
|
}
|
||||||
|
|
@ -151,19 +144,25 @@ func CollectInventory(scannedResults *[]RemoteAsset, params *CollectParams) erro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add all endpoints to smd
|
// add all endpoints to SMD ONLY if a host is provided
|
||||||
err = smdClient.Add(body, headers)
|
if smdClient.URI != "" {
|
||||||
if err != nil {
|
err = smdClient.Add(body, headers)
|
||||||
log.Error().Err(err).Msgf("failed to add Redfish endpoint")
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("failed to add Redfish endpoint")
|
||||||
|
|
||||||
// try updating instead
|
// try updating instead
|
||||||
if params.ForceUpdate {
|
if params.ForceUpdate {
|
||||||
smdClient.Xname = data["ID"].(string)
|
smdClient.Xname = data["ID"].(string)
|
||||||
err = smdClient.Update(body, headers)
|
err = smdClient.Update(body, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("failed to update Redfish endpoint")
|
log.Error().Err(err).Msgf("failed to forcibly update Redfish endpoint")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if params.Verbose {
|
||||||
|
log.Warn().Msg("no request made (host argument is empty)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// got host information, so add to list of already probed hosts
|
// got host information, so add to list of already probed hosts
|
||||||
|
|
@ -173,13 +172,13 @@ func CollectInventory(scannedResults *[]RemoteAsset, params *CollectParams) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// use the found results to query bmc information
|
// use the found results to query bmc information
|
||||||
for _, ps := range *scannedResults {
|
for _, ps := range *assets {
|
||||||
// skip if found info from host
|
// skip if found info from host
|
||||||
foundHost := slices.Index(found, ps.Host)
|
foundHost := slices.Index(found, ps.Host)
|
||||||
if !ps.State || foundHost >= 0 {
|
if !ps.State || foundHost >= 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
chanScannedResult <- ps
|
chanAssets <- ps
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle goroutine paths
|
// handle goroutine paths
|
||||||
|
|
@ -193,13 +192,9 @@ func CollectInventory(scannedResults *[]RemoteAsset, params *CollectParams) erro
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
close(chanScannedResult)
|
close(chanAssets)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
close(done)
|
close(done)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func baseRedfishUrl(q *CollectParams) string {
|
|
||||||
return fmt.Sprintf("%s:%d", q.Host, q.Port)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ func GenerateHostsWithSubnet(subnet string, subnetMask *net.IPMask, additionalPo
|
||||||
// GetDefaultPorts() returns a list of default ports. The only reason to have
|
// GetDefaultPorts() returns a list of default ports. The only reason to have
|
||||||
// this function is to add/remove ports without affecting usage.
|
// this function is to add/remove ports without affecting usage.
|
||||||
func GetDefaultPorts() []int {
|
func GetDefaultPorts() []int {
|
||||||
return []int{HTTPS_PORT}
|
return []int{443}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rawConnect() tries to connect to the host using DialTimeout() and waits
|
// rawConnect() tries to connect to the host using DialTimeout() and waits
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue