Files
warewulf/internal/app/wwctl/node/status/main.go
2022-02-09 20:53:47 +00:00

181 lines
4.1 KiB
Go

package nodestatus
import (
"encoding/json"
"fmt"
"net/http"
"os"
"sort"
"strings"
"time"
"github.com/fatih/color"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/pkg/hostlist"
"github.com/spf13/cobra"
"golang.org/x/term"
)
type allStatus struct {
Nodes map[string]*NodeStatus `json:"nodes"`
}
type NodeStatus struct {
NodeName string `json:"node name"`
Stage string `json:"stage"`
Sent string `json:"sent"`
Ipaddr string `json:"ipaddr"`
Lastseen int64 `json:"last seen"`
}
func CobraRunE(cmd *cobra.Command, args []string) error {
controller, err := warewulfconf.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if controller.Ipaddr == "" {
wwlog.Printf(wwlog.ERROR, "The Warewulf Server IP Address is not properly configured\n")
os.Exit(1)
}
statusURL := fmt.Sprintf("http://%s:%d/status", controller.Ipaddr, controller.Warewulf.Port)
for {
var elipsis bool
var height int
var count int
rightnow := time.Now().Unix()
wwlog.Printf(wwlog.VERBOSE, "Connecting to: %s\n", statusURL)
resp, err := http.Get(statusURL)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not connect to Warewulf server: %s\n", err)
os.Exit(1)
}
defer resp.Body.Close()
decoder := json.NewDecoder(resp.Body)
var nodeStatus allStatus
err = decoder.Decode(&nodeStatus)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not decode JSON: %s\n", err)
os.Exit(1)
}
if SetWatch {
fmt.Print("\033[H\033[2J")
_, height, err = term.GetSize(0)
if err != nil {
wwlog.Printf(wwlog.WARN, "Could not get terminal height, using 24\n")
height = 24
}
}
fmt.Printf("%-20s %-20s %-25s %-10s\n", "NODENAME", "STAGE", "SENT", "LASTSEEN (s)")
fmt.Printf("%s\n", strings.Repeat("=", 80))
keys := make([]*NodeStatus, 0, len(nodeStatus.Nodes))
wwlog.Printf(wwlog.VERBOSE, "Building sort index\n")
if len(args) > 0 {
tmpMap := make(map[string]bool)
nodeList := hostlist.Expand(args)
for _, name := range nodeList {
tmpMap[name] = true
}
for name := range nodeStatus.Nodes {
if _, ok := tmpMap[name]; ok {
keys = append(keys, nodeStatus.Nodes[name])
}
}
} else {
for name := range nodeStatus.Nodes {
keys = append(keys, nodeStatus.Nodes[name])
}
}
wwlog.Printf(wwlog.VERBOSE, "Sorting index\n")
if SetSortLast {
sort.Slice(keys, func(i, j int) bool {
if keys[i].Lastseen > keys[j].Lastseen {
return true
} else if keys[i].Lastseen < keys[j].Lastseen {
return false
} else {
if keys[i].NodeName < keys[j].NodeName {
return true
} else {
return false
}
}
//return keys[i].Lastseen > keys[j].Lastseen
})
} else {
sort.Slice(keys, func(i, j int) bool {
return keys[i].NodeName < keys[j].NodeName
})
}
if SetSortReverse {
var tmpsort []*NodeStatus
wwlog.Printf(wwlog.VERBOSE, "Reversing sort order\n")
for l := len(keys) - 1; l >= 0; l-- {
tmpsort = append(tmpsort, keys[l])
}
keys = tmpsort
}
wwlog.Printf(wwlog.VERBOSE, "Printing results\n")
for _, o := range keys {
if SetTime > 0 && o.Lastseen < SetTime {
continue
}
if o.Lastseen > 0 {
if SetUnknown {
continue
}
if rightnow-o.Lastseen >= int64(controller.Warewulf.UpdateInterval*2) {
color.Red("%-20s %-20s %-25s %-10d\n", o.NodeName, o.Stage, o.Sent, rightnow-o.Lastseen)
} else if rightnow-o.Lastseen >= int64(controller.Warewulf.UpdateInterval+5) {
color.Yellow("%-20s %-20s %-25s %-10d\n", o.NodeName, o.Stage, o.Sent, rightnow-o.Lastseen)
} else {
fmt.Printf("%-20s %-20s %-25s %-10d\n", o.NodeName, o.Stage, o.Sent, rightnow-o.Lastseen)
}
} else {
color.HiBlack("%-20s %-20s %-25s %-10s\n", o.NodeName, "--", "--", "--")
}
if count+4 >= height && SetWatch {
if count+1 != len(keys) {
elipsis = true
}
break
}
count++
}
if SetWatch {
if elipsis {
fmt.Printf("... ")
}
time.Sleep(time.Duration(SetUpdate) * time.Millisecond)
} else {
break
}
}
return nil
}