176 lines
4.1 KiB
Go
176 lines
4.1 KiB
Go
package nodestatus
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/spf13/cobra"
|
|
warewulfconf "github.com/warewulf/warewulf/internal/pkg/config"
|
|
"github.com/warewulf/warewulf/internal/pkg/hostlist"
|
|
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
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 displayStage(stage string) string {
|
|
switch stage {
|
|
case "efiboot":
|
|
return "EFI"
|
|
case "grub":
|
|
return "GRUB"
|
|
case "ipxe":
|
|
return "IPXE"
|
|
case "kernel":
|
|
return "KERNEL"
|
|
case "image":
|
|
return "IMAGE"
|
|
case "system":
|
|
return "SYSTEM OVERLAY"
|
|
case "runtime":
|
|
return "RUNTIME OVERLAY"
|
|
case "initramfs":
|
|
return "INITRAMFS"
|
|
default:
|
|
return strings.ToUpper(stage)
|
|
}
|
|
}
|
|
|
|
func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
|
|
|
controller := warewulfconf.Get()
|
|
|
|
if controller.Ipaddr == "" {
|
|
return fmt.Errorf("warewulf Server IP Address is not properly configured")
|
|
|
|
}
|
|
|
|
for {
|
|
var elipsis bool
|
|
var height int
|
|
var count int
|
|
rightnow := time.Now().Unix()
|
|
|
|
statusURL := fmt.Sprintf("http://%s:%d/status", controller.Ipaddr, controller.Warewulf.Port)
|
|
wwlog.Verbose("Connecting to: %s", statusURL)
|
|
|
|
resp, err := http.Get(statusURL)
|
|
if err != nil {
|
|
return fmt.Errorf("could not connect to Warewulf server: %w", err)
|
|
}
|
|
|
|
var wwNodeStatus struct {
|
|
Nodes map[string]*nodeStatus `json:"nodes"`
|
|
}
|
|
err = json.NewDecoder(resp.Body).Decode(&wwNodeStatus)
|
|
_ = resp.Body.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("could not decode JSON: %w", err)
|
|
}
|
|
|
|
if SetWatch {
|
|
fmt.Print("\033[H\033[2J")
|
|
_, height, err = term.GetSize(0)
|
|
if err != nil {
|
|
wwlog.Warn("Could not get terminal height, using 24")
|
|
height = 24
|
|
}
|
|
}
|
|
|
|
fmt.Printf("%-20s %-20s %-25s %-10s\n", "NODENAME", "STAGE", "SENT", "LASTSEEN (s)")
|
|
fmt.Printf("%s\n", strings.Repeat("=", 80))
|
|
|
|
wwlog.Verbose("Building sort index")
|
|
var statuses []*nodeStatus
|
|
if len(args) > 0 {
|
|
nodeList := hostlist.Expand(args)
|
|
for _, v := range wwNodeStatus.Nodes {
|
|
for _, name := range nodeList {
|
|
if v.NodeName == name {
|
|
statuses = append(statuses, v)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for _, v := range wwNodeStatus.Nodes {
|
|
statuses = append(statuses, v)
|
|
}
|
|
}
|
|
|
|
wwlog.Verbose("Sorting index")
|
|
if SetSortLast {
|
|
sort.Slice(statuses, func(i, j int) bool {
|
|
if statuses[i].Lastseen > statuses[j].Lastseen {
|
|
return true
|
|
} else if statuses[i].Lastseen < statuses[j].Lastseen {
|
|
return false
|
|
} else {
|
|
return statuses[i].NodeName < statuses[j].NodeName
|
|
}
|
|
})
|
|
} else if SetSortReverse {
|
|
wwlog.Verbose("Reversing sort order")
|
|
sort.Slice(statuses, func(i, j int) bool {
|
|
return statuses[i].NodeName > statuses[j].NodeName
|
|
})
|
|
|
|
} else {
|
|
sort.Slice(statuses, func(i, j int) bool {
|
|
return statuses[i].NodeName < statuses[j].NodeName
|
|
})
|
|
}
|
|
|
|
wwlog.Verbose("Printing results")
|
|
for i := 0; i < len(statuses); i++ {
|
|
o := statuses[i]
|
|
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, displayStage(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, displayStage(o.Stage), o.Sent, rightnow-o.Lastseen)
|
|
} else {
|
|
fmt.Printf("%-20s %-20s %-25s %-10d\n", o.NodeName, displayStage(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(statuses) {
|
|
elipsis = true
|
|
}
|
|
break
|
|
}
|
|
count++
|
|
}
|
|
|
|
if SetWatch {
|
|
if elipsis {
|
|
fmt.Printf("... ")
|
|
}
|
|
time.Sleep(time.Duration(SetUpdate) * time.Millisecond)
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|