Files
warewulf/internal/app/wwctl/node/status/main.go
Jonathon Anderson 939f4290f4 Move stage display formatting to wwctl
Signed-off-by: Jonathon Anderson <janderson@ciq.com>
2026-03-10 16:11:09 -06:00

157 lines
3.8 KiB
Go

package nodestatus
import (
"fmt"
"sort"
"strings"
"time"
"github.com/fatih/color"
"github.com/spf13/cobra"
apinode "github.com/warewulf/warewulf/internal/pkg/api/node"
"github.com/warewulf/warewulf/internal/pkg/api/routes/wwapiv1"
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"
)
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()
var nodeStatusResponse *wwapiv1.NodeStatusResponse
nodeStatusResponse, err = apinode.NodeStatus([]string{})
if err != nil {
return 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 []*wwapiv1.NodeStatus
if len(args) > 0 {
nodeList := hostlist.Expand(args)
for i := 0; i < len(nodeStatusResponse.NodeStatus); i++ {
for j := 0; j < len(nodeList); j++ {
if nodeStatusResponse.NodeStatus[i].NodeName == nodeList[j] {
statuses = append(statuses, nodeStatusResponse.NodeStatus[i])
break
}
}
}
} else {
for i := 0; i < len(nodeStatusResponse.NodeStatus); i++ {
statuses = append(statuses, nodeStatusResponse.NodeStatus[i])
}
}
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
}