Refactor gRPC-based node functions
Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
@@ -2,14 +2,14 @@ package add
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
apinode "github.com/warewulf/warewulf/internal/pkg/api/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/api/routes/wwapiv1"
|
||||
"github.com/warewulf/warewulf/internal/pkg/hostlist"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/util"
|
||||
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
@@ -60,16 +60,45 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer, err := yaml.Marshal(vars.nodeConf)
|
||||
nodeDB, err := node.New()
|
||||
if err != nil {
|
||||
wwlog.Error("Can't marshall nodeInfo", err)
|
||||
return err
|
||||
return fmt.Errorf("failed to open node database: %w", err)
|
||||
}
|
||||
set := wwapiv1.NodeAddParameter{
|
||||
NodeConfYaml: string(buffer[:]),
|
||||
NodeNames: args,
|
||||
Force: true,
|
||||
nodeArgs := hostlist.Expand(args)
|
||||
changed := cmd.Flags().Changed
|
||||
var ipv4, ipmiaddr net.IP
|
||||
for _, a := range nodeArgs {
|
||||
n, err := nodeDB.AddNode(a)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add node: %w", err)
|
||||
}
|
||||
n.UpdateFrom(&vars.nodeConf, changed)
|
||||
if !changed("profile") && len(vars.nodeConf.Profiles) > 0 {
|
||||
n.Profiles = vars.nodeConf.Profiles
|
||||
}
|
||||
wwlog.Info("Added node: %s", a)
|
||||
for _, dev := range n.NetDevs {
|
||||
if !ipv4.IsUnspecified() && ipv4 != nil {
|
||||
ipv4 = util.IncrementIPv4(ipv4, 1)
|
||||
wwlog.Verbose("Incremented IP addr to %s", ipv4)
|
||||
dev.Ipaddr = ipv4
|
||||
} else if !dev.Ipaddr.IsUnspecified() {
|
||||
ipv4 = dev.Ipaddr
|
||||
}
|
||||
}
|
||||
if n.Ipmi != nil {
|
||||
if !ipmiaddr.IsUnspecified() && ipmiaddr != nil {
|
||||
ipmiaddr = util.IncrementIPv4(ipmiaddr, 1)
|
||||
wwlog.Verbose("Incremented ipmi IP addr to %s", ipmiaddr)
|
||||
n.Ipmi.Ipaddr = ipmiaddr
|
||||
} else if !n.Ipmi.Ipaddr.IsUnspecified() {
|
||||
ipmiaddr = n.Ipmi.Ipaddr
|
||||
}
|
||||
}
|
||||
}
|
||||
return apinode.NodeAdd(&set)
|
||||
if err := nodeDB.Persist(); err != nil {
|
||||
return fmt.Errorf("failed to persist new node: %w", err)
|
||||
}
|
||||
return warewulfd.DaemonReload()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,36 +2,64 @@ package delete
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
apiNode "github.com/warewulf/warewulf/internal/pkg/api/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/api/routes/wwapiv1"
|
||||
"github.com/warewulf/warewulf/internal/pkg/hostlist"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/util"
|
||||
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
nodeDB, err := node.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open node database: %w", err)
|
||||
}
|
||||
|
||||
ndp := wwapiv1.NodeDeleteParameter{
|
||||
Force: SetForce,
|
||||
NodeNames: args,
|
||||
nodes, err := nodeDB.FindAllNodes()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get node list: %w", err)
|
||||
}
|
||||
|
||||
nodeArgs := hostlist.Expand(args)
|
||||
var nodeList []node.Node
|
||||
for _, r := range nodeArgs {
|
||||
var match bool
|
||||
for _, n := range nodes {
|
||||
if n.Id() == r {
|
||||
nodeList = append(nodeList, n)
|
||||
match = true
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: No match for node: %s\n", r)
|
||||
}
|
||||
}
|
||||
|
||||
if len(nodeList) == 0 {
|
||||
fmt.Printf("No nodes found\n")
|
||||
return
|
||||
}
|
||||
|
||||
if !SetYes {
|
||||
var nodeList []node.Node
|
||||
// The checks run twice in the prompt case.
|
||||
// Avoiding putting in a blocking prompt in an API.
|
||||
nodeList, err = apiNode.NodeDeleteParameterCheck(&ndp, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(nodeList) == 0 {
|
||||
return
|
||||
}
|
||||
yes := util.Confirm(fmt.Sprintf("Are you sure you want to delete %d nodes(s)", len(nodeList)))
|
||||
if !yes {
|
||||
return
|
||||
}
|
||||
}
|
||||
return apiNode.NodeDelete(&ndp)
|
||||
|
||||
for _, n := range nodeList {
|
||||
if err := nodeDB.DelNode(n.Id()); err != nil {
|
||||
wwlog.Error("%s", err)
|
||||
} else {
|
||||
wwlog.Verbose("Deleting node: %s\n", n.Id())
|
||||
}
|
||||
}
|
||||
|
||||
if err := nodeDB.Persist(); err != nil {
|
||||
return fmt.Errorf("failed to persist nodedb: %w", err)
|
||||
}
|
||||
return warewulfd.DaemonReload()
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
apinode "github.com/warewulf/warewulf/internal/pkg/api/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/api/routes/wwapiv1"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/util"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -32,9 +30,22 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
if setYes || util.Confirm(fmt.Sprintf("Are you sure you want to modify %d nodes", len(importMap))) {
|
||||
err = apinode.NodeAddFromYaml(&wwapiv1.NodeYaml{NodeConfMapYaml: string(buffer)})
|
||||
nodeDB, err := node.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("got following problem when writing back yaml: %s", err)
|
||||
return fmt.Errorf("could not open NodeDB: %w", err)
|
||||
}
|
||||
for nodeName, nodeData := range importMap {
|
||||
if _, err := nodeDB.GetNodeOnly(nodeName); err == node.ErrNotFound {
|
||||
if _, err := nodeDB.AddNode(nodeName); err != nil {
|
||||
return fmt.Errorf("couldn't add new node: %w", err)
|
||||
}
|
||||
}
|
||||
if err := nodeDB.SetNode(nodeName, *nodeData); err != nil {
|
||||
return fmt.Errorf("couldn't set node: %w", err)
|
||||
}
|
||||
}
|
||||
if err := nodeDB.Persist(); err != nil {
|
||||
return fmt.Errorf("failed to persist nodedb: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +1,117 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/table"
|
||||
apinode "github.com/warewulf/warewulf/internal/pkg/api/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/api/routes/wwapiv1"
|
||||
"github.com/warewulf/warewulf/internal/pkg/hostlist"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) {
|
||||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
req := wwapiv1.GetNodeList{
|
||||
Nodes: args,
|
||||
Type: wwapiv1.GetNodeList_Simple,
|
||||
nodeDB, err := node.New()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if vars.showAll {
|
||||
req.Type = wwapiv1.GetNodeList_All
|
||||
} else if vars.showIpmi {
|
||||
req.Type = wwapiv1.GetNodeList_Ipmi
|
||||
} else if vars.showNet {
|
||||
req.Type = wwapiv1.GetNodeList_Network
|
||||
} else if vars.showLong {
|
||||
req.Type = wwapiv1.GetNodeList_Long
|
||||
} else if vars.showYaml {
|
||||
req.Type = wwapiv1.GetNodeList_YAML
|
||||
} else if vars.showJson {
|
||||
req.Type = wwapiv1.GetNodeList_JSON
|
||||
nodes, err := nodeDB.FindAllNodes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nodeInfo, err := apinode.NodeList(&req)
|
||||
nodeNames := hostlist.Expand(args)
|
||||
sort.Strings(nodeNames)
|
||||
filtered := node.FilterNodeListByName(nodes, nodeNames)
|
||||
|
||||
if len(nodeInfo.Output) > 0 {
|
||||
if req.Type == wwapiv1.GetNodeList_YAML || req.Type == wwapiv1.GetNodeList_JSON {
|
||||
wwlog.Info(nodeInfo.Output[0])
|
||||
} else {
|
||||
t := table.New(cmd.OutOrStdout())
|
||||
t.AddHeader(table.Prep(strings.Split(nodeInfo.Output[0], ":=:"))...)
|
||||
for _, val := range nodeInfo.Output[1:] {
|
||||
t.AddLine(table.Prep(strings.Split(val, ":=:"))...)
|
||||
}
|
||||
t.Print()
|
||||
if vars.showYaml || vars.showJson {
|
||||
nodeMap := make(map[string]node.Node)
|
||||
for _, n := range filtered {
|
||||
nodeMap[n.Id()] = n
|
||||
}
|
||||
var buf []byte
|
||||
if vars.showJson {
|
||||
buf, _ = json.MarshalIndent(nodeMap, "", " ")
|
||||
} else {
|
||||
buf, _ = yaml.Marshal(nodeMap)
|
||||
}
|
||||
wwlog.Info(string(buf))
|
||||
} else if vars.showAll {
|
||||
t := table.New(cmd.OutOrStdout())
|
||||
t.AddHeader("NODE", "FIELD", "PROFILE", "VALUE")
|
||||
for _, n := range filtered {
|
||||
if _, fields, err := nodeDB.MergeNode(n.Id()); err != nil {
|
||||
wwlog.Error("unable to merge node %v: %v", n.Id(), err)
|
||||
continue
|
||||
} else {
|
||||
for _, f := range fields.List(n) {
|
||||
t.AddLine(table.Prep([]string{n.Id(), f.Field, f.Source, f.Value})...)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Print()
|
||||
} else if vars.showIpmi {
|
||||
t := table.New(cmd.OutOrStdout())
|
||||
t.AddHeader("NODE", "IPMI IPADDR", "IPMI PORT", "IPMI USERNAME", "IPMI INTERFACE")
|
||||
for _, n := range filtered {
|
||||
ipaddr, port, username, iface := "", "", "", ""
|
||||
if n.Ipmi != nil {
|
||||
ipaddr = n.Ipmi.Ipaddr.String()
|
||||
port = n.Ipmi.Port
|
||||
username = n.Ipmi.UserName
|
||||
iface = n.Ipmi.Interface
|
||||
}
|
||||
t.AddLine(table.Prep([]string{n.Id(), ipaddr, port, username, iface})...)
|
||||
}
|
||||
t.Print()
|
||||
} else if vars.showNet {
|
||||
t := table.New(cmd.OutOrStdout())
|
||||
t.AddHeader("NODE", "NETWORK", "HWADDR", "IPADDR", "GATEWAY", "DEVICE")
|
||||
for _, n := range filtered {
|
||||
if len(n.NetDevs) > 0 {
|
||||
for name := range n.NetDevs {
|
||||
t.AddLine(table.Prep([]string{n.Id(), name,
|
||||
n.NetDevs[name].Hwaddr,
|
||||
n.NetDevs[name].Ipaddr.String(),
|
||||
n.NetDevs[name].Gateway.String(),
|
||||
n.NetDevs[name].Device})...)
|
||||
}
|
||||
} else {
|
||||
t.AddLine(table.Prep([]string{n.Id(), "", "", "", "", ""})...)
|
||||
}
|
||||
}
|
||||
t.Print()
|
||||
} else if vars.showLong {
|
||||
t := table.New(cmd.OutOrStdout())
|
||||
t.AddHeader("NODE NAME", "KERNEL VERSION", "IMAGE", "OVERLAYS (S/R)")
|
||||
for _, n := range filtered {
|
||||
kernelVersion := ""
|
||||
if n.Kernel != nil {
|
||||
kernelVersion = n.Kernel.Version
|
||||
}
|
||||
t.AddLine(table.Prep([]string{n.Id(),
|
||||
kernelVersion,
|
||||
n.ImageName,
|
||||
strings.Join(n.SystemOverlay, ",") + "/" + strings.Join(n.RuntimeOverlay, ",")})...)
|
||||
}
|
||||
t.Print()
|
||||
} else {
|
||||
// Simple (default)
|
||||
t := table.New(cmd.OutOrStdout())
|
||||
t.AddHeader("NODE NAME", "PROFILES", "NETWORK")
|
||||
for _, n := range filtered {
|
||||
var netNames []string
|
||||
for k := range n.NetDevs {
|
||||
netNames = append(netNames, k)
|
||||
}
|
||||
sort.Strings(netNames)
|
||||
t.AddLine(table.Prep([]string{n.Id(), strings.Join(n.Profiles, ","), strings.Join(netNames, ", ")})...)
|
||||
}
|
||||
t.Print()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,13 +5,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
apinode "github.com/warewulf/warewulf/internal/pkg/api/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/api/routes/wwapiv1"
|
||||
"github.com/warewulf/warewulf/internal/pkg/hostlist"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/util"
|
||||
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) {
|
||||
@@ -48,44 +46,108 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err
|
||||
}
|
||||
delete(vars.nodeConf.Disks, "UNDEF")
|
||||
vars.nodeConf.Ipmi.Tags = vars.nodeAdd.IpmiTagsAdd
|
||||
buffer, err := yaml.Marshal(vars.nodeConf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not marshall nodeInfo: %s", err)
|
||||
}
|
||||
wwlog.Debug("sending following values: %s", string(buffer))
|
||||
args = hostlist.Expand(args)
|
||||
set := wwapiv1.ConfSetParameter{
|
||||
NodeConfYaml: string(buffer),
|
||||
|
||||
NetdevDelete: vars.nodeDel.NetDel,
|
||||
PartitionDelete: vars.nodeDel.PartDel,
|
||||
DiskDelete: vars.nodeDel.DiskDel,
|
||||
FilesystemDelete: vars.nodeDel.FsDel,
|
||||
TagAdd: vars.nodeAdd.TagsAdd,
|
||||
TagDel: vars.nodeDel.TagsDel,
|
||||
NetTagAdd: vars.nodeAdd.NetTagsAdd,
|
||||
NetTagDel: vars.nodeDel.NetTagsDel,
|
||||
IpmiTagAdd: vars.nodeAdd.IpmiTagsAdd,
|
||||
IpmiTagDel: vars.nodeDel.IpmiTagsDel,
|
||||
Netdev: vars.nodeAdd.Net,
|
||||
AllConfs: vars.setNodeAll,
|
||||
Force: vars.setForce,
|
||||
ConfList: args,
|
||||
nodeDB, err := node.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not open configuration: %w", err)
|
||||
}
|
||||
|
||||
args = hostlist.Expand(args)
|
||||
if len(args) == 0 && !vars.setNodeAll {
|
||||
return fmt.Errorf("no nodes specified; use --all to modify all nodes")
|
||||
}
|
||||
if vars.setNodeAll {
|
||||
args = nodeDB.ListAllNodes()
|
||||
wwlog.Warn("this command will modify all nodes")
|
||||
} else if len(nodeDB.ListAllNodes()) == 0 {
|
||||
wwlog.Warn("no nodes/profiles found")
|
||||
return nil
|
||||
}
|
||||
|
||||
changed := cmd.Flags().Changed
|
||||
var count uint
|
||||
for _, nId := range args {
|
||||
wwlog.Debug("evaluating node: %s", nId)
|
||||
nodePtr, err := nodeDB.GetNodeOnlyPtr(nId)
|
||||
if err != nil {
|
||||
wwlog.Warn("invalid node: %s", nId)
|
||||
continue
|
||||
}
|
||||
nodePtr.UpdateFrom(&vars.nodeConf, changed)
|
||||
if vars.nodeDel.NetDel != "" {
|
||||
if _, ok := nodePtr.NetDevs[vars.nodeDel.NetDel]; !ok {
|
||||
return fmt.Errorf("network device name doesn't exist: %s", vars.nodeDel.NetDel)
|
||||
}
|
||||
wwlog.Verbose("Node: %s, Deleting network device: %s", nId, vars.nodeDel.NetDel)
|
||||
delete(nodePtr.NetDevs, vars.nodeDel.NetDel)
|
||||
}
|
||||
if vars.nodeDel.PartDel != "" {
|
||||
for diskname, disk := range nodePtr.Disks {
|
||||
if _, ok := disk.Partitions[vars.nodeDel.PartDel]; ok {
|
||||
wwlog.Verbose("Node: %s, on disk %s, deleting partition: %s", nId, diskname, vars.nodeDel.PartDel)
|
||||
delete(disk.Partitions, vars.nodeDel.PartDel)
|
||||
} else {
|
||||
return fmt.Errorf("partition doesn't exist: %s", vars.nodeDel.PartDel)
|
||||
}
|
||||
}
|
||||
}
|
||||
if vars.nodeDel.DiskDel != "" {
|
||||
if _, ok := nodePtr.Disks[vars.nodeDel.DiskDel]; ok {
|
||||
wwlog.Verbose("Node: %s, deleting disk: %s", nId, vars.nodeDel.DiskDel)
|
||||
delete(nodePtr.Disks, vars.nodeDel.DiskDel)
|
||||
} else {
|
||||
return fmt.Errorf("disk doesn't exist: %s", vars.nodeDel.DiskDel)
|
||||
}
|
||||
}
|
||||
if vars.nodeDel.FsDel != "" {
|
||||
if _, ok := nodePtr.FileSystems[vars.nodeDel.FsDel]; ok {
|
||||
wwlog.Verbose("Node: %s, deleting filesystem: %s", nId, vars.nodeDel.FsDel)
|
||||
delete(nodePtr.FileSystems, vars.nodeDel.FsDel)
|
||||
} else {
|
||||
return fmt.Errorf("filesystem doesn't exist: %s", vars.nodeDel.FsDel)
|
||||
}
|
||||
}
|
||||
for _, key := range vars.nodeDel.TagsDel {
|
||||
delete(nodePtr.Tags, key)
|
||||
}
|
||||
for key, val := range vars.nodeAdd.TagsAdd {
|
||||
if nodePtr.Tags == nil {
|
||||
nodePtr.Tags = make(map[string]string)
|
||||
}
|
||||
nodePtr.Tags[key] = val
|
||||
}
|
||||
for key, val := range vars.nodeAdd.IpmiTagsAdd {
|
||||
if nodePtr.Ipmi.Tags == nil {
|
||||
nodePtr.Ipmi.Tags = make(map[string]string)
|
||||
}
|
||||
nodePtr.Ipmi.Tags[key] = val
|
||||
}
|
||||
for _, key := range vars.nodeDel.IpmiTagsDel {
|
||||
delete(nodePtr.Ipmi.Tags, key)
|
||||
}
|
||||
if netDev, ok := nodePtr.NetDevs[vars.nodeAdd.Net]; ok {
|
||||
for _, key := range vars.nodeDel.NetTagsDel {
|
||||
delete(netDev.Tags, key)
|
||||
}
|
||||
if len(vars.nodeAdd.NetTagsAdd) > 0 && netDev.Tags == nil {
|
||||
netDev.Tags = make(map[string]string)
|
||||
}
|
||||
for key, val := range vars.nodeAdd.NetTagsAdd {
|
||||
netDev.Tags[key] = val
|
||||
}
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
if !vars.setYes {
|
||||
var nodeCount uint
|
||||
// The checks run twice in the prompt case.
|
||||
// Avoiding putting in a blocking prompt in an API.
|
||||
_, nodeCount, err = apinode.NodeSetParameterCheck(&set)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
yes := util.Confirm(fmt.Sprintf("Are you sure you want to modify %d nodes(s)", nodeCount))
|
||||
if !yes {
|
||||
if !util.Confirm(fmt.Sprintf("Are you sure you want to modify %d nodes(s)", count)) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return apinode.NodeSet(&set)
|
||||
|
||||
if err := nodeDB.Persist(); err != nil {
|
||||
return err
|
||||
}
|
||||
return warewulfd.DaemonReload()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -681,6 +681,22 @@ nodes:
|
||||
number: "1"
|
||||
wipe_partition_entry: true`,
|
||||
},
|
||||
"--all modifies all nodes": {
|
||||
args: []string{"--all", "--comment=batch-update"},
|
||||
wantErr: false,
|
||||
inDB: `
|
||||
nodeprofiles: {}
|
||||
nodes:
|
||||
n01: {}
|
||||
n02: {}`,
|
||||
outDB: `
|
||||
nodeprofiles: {}
|
||||
nodes:
|
||||
n01:
|
||||
comment: batch-update
|
||||
n02:
|
||||
comment: batch-update`,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tt := range tests {
|
||||
|
||||
@@ -26,7 +26,7 @@ func GetCommand() *cobra.Command {
|
||||
Short: "Configure node properties",
|
||||
Long: "This command sets configuration properties for nodes matching PATTERN.\n\nNote: use the string 'UNSET' to remove a configuration\n" + hostlist.Docstring,
|
||||
Aliases: []string{"modify"},
|
||||
Args: cobra.MinimumNArgs(1), // require pattern as a mandatory arg
|
||||
Args: cobra.ArbitraryArgs,
|
||||
RunE: CobraRunE(&vars),
|
||||
ValidArgsFunction: completions.Nodes,
|
||||
}
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
package nodestatus
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"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"
|
||||
)
|
||||
|
||||
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":
|
||||
@@ -54,10 +62,21 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
var count int
|
||||
rightnow := time.Now().Unix()
|
||||
|
||||
var nodeStatusResponse *wwapiv1.NodeStatusResponse
|
||||
nodeStatusResponse, err = apinode.NodeStatus([]string{})
|
||||
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 err
|
||||
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 {
|
||||
@@ -73,20 +92,20 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
fmt.Printf("%s\n", strings.Repeat("=", 80))
|
||||
|
||||
wwlog.Verbose("Building sort index")
|
||||
var statuses []*wwapiv1.NodeStatus
|
||||
var statuses []*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])
|
||||
for _, v := range wwNodeStatus.Nodes {
|
||||
for _, name := range nodeList {
|
||||
if v.NodeName == name {
|
||||
statuses = append(statuses, v)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < len(nodeStatusResponse.NodeStatus); i++ {
|
||||
statuses = append(statuses, nodeStatusResponse.NodeStatus[i])
|
||||
for _, v := range wwNodeStatus.Nodes {
|
||||
statuses = append(statuses, v)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user