api changes for use without NodeInfo

Signed-off-by: Christian Goll <cgoll@suse.com>
This commit is contained in:
Christian Goll
2023-12-15 15:40:51 +01:00
committed by Jonathon Anderson
parent 457c7c16b1
commit ffef31969e
19 changed files with 912 additions and 1106 deletions

View File

@@ -0,0 +1,77 @@
package apinode
import (
"encoding/hex"
"fmt"
"net"
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/pkg/hostlist"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
)
// NodeAdd adds nodes for management by Warewulf.
func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) {
if nap == nil {
return fmt.Errorf("NodeAddParameter is nil")
}
nodeDB, err := node.New()
if err != nil {
return errors.Wrap(err, "failed to open node database")
}
dbHash := nodeDB.Hash()
if hex.EncodeToString(dbHash[:]) != nap.Hash && !nap.Force {
return fmt.Errorf("got wrong hash, not modifying node database")
}
node_args := hostlist.Expand(nap.NodeNames)
var ipv4, ipmiaddr net.IP
for _, a := range node_args {
n, err := nodeDB.AddNode(a)
if err != nil {
return errors.Wrap(err, "failed to add node")
}
err = yaml.Unmarshal([]byte(nap.NodeConfYaml), &n)
if err != nil {
return errors.Wrap(err, "Failed to decode nodeConf")
}
wwlog.Info("Added node: %s:", a)
for _, dev := range n.NetDevs {
if !ipv4.IsUnspecified() && ipv4 != nil {
// if more nodes are added increment IPv4 address
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
}
}
}
err = nodeDB.Persist()
if err != nil {
return errors.Wrap(err, "failed to persist new node")
}
err = warewulfd.DaemonReload()
if err != nil {
return errors.Wrap(err, "failed to reload warewulf daemon")
}
return
}

View File

@@ -0,0 +1,106 @@
package apinode
import (
"encoding/hex"
"fmt"
"os"
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/pkg/hostlist"
"github.com/pkg/errors"
)
// NodeDelete adds nodes for management by Warewulf.
func NodeDelete(ndp *wwapiv1.NodeDeleteParameter) (err error) {
var nodeList []node.NodeConf
nodeList, err = NodeDeleteParameterCheck(ndp, false)
if err != nil {
return
}
nodeDB, err := node.New()
if err != nil {
wwlog.Error("Failed to open node database: %s", err)
return
}
dbHash := nodeDB.Hash()
if hex.EncodeToString(dbHash[:]) != ndp.Hash && !ndp.Force {
return fmt.Errorf("got wrong hash, not modifying node database")
}
for _, n := range nodeList {
err := nodeDB.DelNode(n.Id())
if err != nil {
wwlog.Error("%s", err)
} else {
//count++
wwlog.Verbose("Deleting node: %s\n", n.Id())
}
}
err = nodeDB.Persist()
if err != nil {
return errors.Wrap(err, "failed to persist nodedb")
}
err = warewulfd.DaemonReload()
if err != nil {
return errors.Wrap(err, "failed to reload warewulf daemon")
}
return
}
// NodeDeleteParameterCheck does error checking on NodeDeleteParameter.
// Output to the console if console is true.
// Returns the nodes to delete.
func NodeDeleteParameterCheck(ndp *wwapiv1.NodeDeleteParameter, console bool) (nodeList []node.NodeConf, err error) {
if ndp == nil {
err = fmt.Errorf("NodeDeleteParameter is nil")
return
}
nodeDB, err := node.New()
if err != nil {
wwlog.Error("Failed to open node database: %s", err)
return
}
dbHash := nodeDB.Hash()
if hex.EncodeToString(dbHash[:]) != ndp.Hash && !ndp.Force {
wwlog.Debug("got hash: %s", ndp.Hash)
wwlog.Debug("actual hash: %s", hex.EncodeToString(dbHash[:]))
err = fmt.Errorf("got wrong hash, not modifying node database")
return
}
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Error("Could not get node list: %s", err)
return
}
node_args := hostlist.Expand(ndp.NodeNames)
for _, r := range node_args {
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
}

View File

@@ -39,7 +39,7 @@ func FilteredNodes(nodeList *wwapiv1.NodeList) *wwapiv1.NodeYaml {
os.Exit(1)
}
nodeMap := nodeDB.Nodes
nodeMap = node.FilterMapByName(nodeMap, nodeList.Output)
nodeMap = node.FilterNodesByName(nodeMap, nodeList.Output)
buffer, _ := yaml.Marshal(nodeMap)
retVal := wwapiv1.NodeYaml{
NodeConfMapYaml: string(buffer),

View File

@@ -39,7 +39,7 @@ func NodeList(nodeGet *wwapiv1.GetNodeList) (nodeList wwapiv1.NodeList, err erro
}
sort.Strings(netNames)
nodeList.Output = append(nodeList.Output,
fmt.Sprintf("%s:=:%s:=:%s", n.Id.Print(), n.Profiles.Print(), strings.Join(netNames, ", ")))
fmt.Sprintf("%s:=:%s:=:%s", n.Id(), n.Profiles, strings.Join(netNames, ", ")))
}
} else if nodeGet.Type == wwapiv1.GetNodeList_Network {
nodeList.Output = append(nodeList.Output,
@@ -48,14 +48,15 @@ func NodeList(nodeGet *wwapiv1.GetNodeList) (nodeList wwapiv1.NodeList, err erro
if len(n.NetDevs) > 0 {
for name := range n.NetDevs {
nodeList.Output = append(nodeList.Output,
fmt.Sprintf("%s:=:%s:=:%s:=:%s:=:%s:=:%s", n.Id.Print(), name,
n.NetDevs[name].Hwaddr.Print(),
n.NetDevs[name].Ipaddr.Print(),
n.NetDevs[name].Gateway.Print(),
n.NetDevs[name].Device.Print()))
fmt.Sprintf("%s:=:%s:=:%s:=:%s:=:%s:=:%s", n.Id(), name,
n.NetDevs[name].Hwaddr,
n.NetDevs[name].Ipaddr,
n.NetDevs[name].Gateway,
n.NetDevs[name].Device))
}
} else {
fmt.Printf("%s:=:%s:=:%s:=:%s:=:%s:=:%s", n.Id.Print(), "--", "--", "--", "--", "--")
nodeList.Output = append(nodeList.Output,
fmt.Sprintf("%s:=:%s:=:%s:=:%s:=:%s:=:%s", n.Id(), "--", "--", "--", "--", "--"))
}
}
} else if nodeGet.Type == wwapiv1.GetNodeList_Ipmi {
@@ -63,61 +64,41 @@ func NodeList(nodeGet *wwapiv1.GetNodeList) (nodeList wwapiv1.NodeList, err erro
fmt.Sprintf("%s:=:%s:=:%s:=:%s:=:%s", "NODE NAME", "IPMI IPADDR", "IPMI PORT", "IPMI USERNAME", "IPMI INTERFACE"))
for _, n := range node.FilterByName(nodes, nodeGet.Nodes) {
nodeList.Output = append(nodeList.Output,
fmt.Sprintf("%s:=:%s:=:%s:=:%s:=:%s:=:%s", n.Id.Print(),
n.Ipmi.Ipaddr.Print(),
n.Ipmi.Port.Print(),
n.Ipmi.UserName.Print(),
n.Ipmi.Interface.Print(),
n.Ipmi.EscapeChar.Print()))
fmt.Sprintf("%s:=:%s:=:%s:=:%s:=:%s:=:%s", n.Id(),
n.Ipmi.Ipaddr,
n.Ipmi.Port,
n.Ipmi.UserName,
n.Ipmi.Interface,
n.Ipmi.EscapeChar))
}
} else if nodeGet.Type == wwapiv1.GetNodeList_Long {
nodeList.Output = append(nodeList.Output,
fmt.Sprintf("%s:=:%s:=:%s:=:%s", "NODE NAME", "KERNEL OVERRIDE", "CONTAINER", "OVERLAYS (S/R)"))
for _, n := range node.FilterByName(nodes, nodeGet.Nodes) {
nodeList.Output = append(nodeList.Output,
fmt.Sprintf("%s:=:%s:=:%s:=:%s", n.Id.Print(),
n.Kernel.Override.Print(),
n.ContainerName.Print(),
n.SystemOverlay.Print()+"/"+n.RuntimeOverlay.Print()))
fmt.Sprintf("%s:=:%s:=:%s:=:%s", n.Id(),
n.Kernel.Override,
n.ContainerName,
strings.Join(n.SystemOverlay, ",")+"/"+strings.Join(n.RuntimeOverlay, ",")))
}
} else if nodeGet.Type == wwapiv1.GetNodeList_All || nodeGet.Type == wwapiv1.GetNodeList_FullAll {
for _, n := range node.FilterByName(nodes, nodeGet.Nodes) {
nodeList.Output = append(nodeList.Output,
fmt.Sprintf("%s:=:%s:=:%s:=:%s", "NODE", "FIELD", "PROFILE", "VALUE"))
fields := n.GetFields(wwapiv1.GetNodeList_FullAll == nodeGet.Type)
fields := nodeDB.GetFields(n, nodeGet.Type == wwapiv1.GetNodeList_All)
for _, f := range fields {
nodeList.Output = append(nodeList.Output,
fmt.Sprintf("%s:=:%s:=:%s:=:%s", n.Id.Print(), f.Field, f.Source, f.Value))
fmt.Sprintf("%s:=:%s:=:%s:=:%s", n.Id(), f.Field, f.Source, f.Value))
}
}
} else if nodeGet.Type == wwapiv1.GetNodeList_YAML || nodeGet.Type == wwapiv1.GetNodeList_JSON {
nodeResp := node.NodeYaml{
NodeProfiles: make(map[string]*node.NodeConf),
Nodes: make(map[string]*node.NodeConf),
}
filterNodes := node.FilterByName(nodes, nodeGet.Nodes)
for _, nodeInfo := range filterNodes {
myNode := node.NewConf()
myNode.GetFrom(nodeInfo)
myNode.Flatten()
nodeResp.Nodes[nodeInfo.Id.Get()] = &myNode
}
profiles, _ := nodeDB.FindAllProfiles()
for _, profileInfo := range profiles {
myProfile := node.NewConf()
myProfile.GetFrom(profileInfo)
myProfile.Flatten()
nodeResp.NodeProfiles[profileInfo.Id.Get()] = &myProfile
}
var buf []byte
if nodeGet.Type == wwapiv1.GetNodeList_JSON {
buf, _ = json.MarshalIndent(nodeResp, "", " ")
buf, _ = json.MarshalIndent(filterNodes, "", " ")
}
if nodeGet.Type == wwapiv1.GetNodeList_YAML {
buf, _ = yaml.Marshal(nodeResp)
buf, _ = yaml.Marshal(filterNodes)
}
nodeList.Output = append(nodeList.Output, string(buf))

View File

@@ -1,400 +0,0 @@
package apinode
import (
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"os"
"github.com/pkg/errors"
"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/node"
"github.com/warewulf/warewulf/internal/pkg/util"
"github.com/warewulf/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
)
// NodeAdd adds nodes for management by Warewulf.
func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) {
if nap == nil {
return fmt.Errorf("NodeAddParameter is nil")
}
nodeDB, err := node.New()
if err != nil {
return errors.Wrap(err, "failed to open node database")
}
dbHash := nodeDB.Hash()
if hex.EncodeToString(dbHash[:]) != nap.Hash && !nap.Force {
return fmt.Errorf("got wrong hash, not modifying node database")
}
node_args := hostlist.Expand(nap.NodeNames)
var nodeConf node.NodeConf
err = yaml.Unmarshal([]byte(nap.NodeConfYaml), &nodeConf)
if err != nil {
return errors.Wrap(err, "Failed to decode nodeConf")
}
for _, a := range node_args {
var n node.NodeInfo
n, err = nodeDB.AddNode(a)
if err != nil {
return errors.Wrap(err, "failed to add node")
}
wwlog.Info("Added node: %s", a)
var netName string
for netName = range nodeConf.NetDevs {
// as map should only have key this should give is the first and
// only key
}
// setting node from the received yaml
err = nodeConf.Check()
if err != nil {
err = fmt.Errorf("error on check of node %s: %s", n.Id.Get(), err)
return
}
n.SetFrom(&nodeConf)
if netName != "" && nodeConf.NetDevs[netName].Ipaddr != "" {
// if more nodes are added increment IPv4 address
nodeConf.NetDevs[netName].Ipaddr = util.IncrementIPv4(nodeConf.NetDevs[netName].Ipaddr, 1)
wwlog.Verbose("Incremented IP addr to %s", nodeConf.NetDevs[netName].Ipaddr)
}
if nodeConf.Ipmi != nil && nodeConf.Ipmi.Ipaddr != "" {
// if more nodes are added increment IPv4 address
nodeConf.Ipmi.Ipaddr = util.IncrementIPv4(nodeConf.Ipmi.Ipaddr, 1)
wwlog.Verbose("Incremented IP addr to %s", nodeConf.Ipmi.Ipaddr)
}
err = nodeDB.NodeUpdate(n)
if err != nil {
return errors.Wrap(err, "failed to update nodedb")
}
}
err = nodeDB.Persist()
if err != nil {
return errors.Wrap(err, "failed to persist new node")
}
err = warewulfd.DaemonReload()
if err != nil {
return errors.Wrap(err, "failed to reload warewulf daemon")
}
return
}
// NodeDelete adds nodes for management by Warewulf.
func NodeDelete(ndp *wwapiv1.NodeDeleteParameter) (err error) {
var nodeList []node.NodeInfo
nodeList, err = NodeDeleteParameterCheck(ndp, false)
if err != nil {
return
}
nodeDB, err := node.New()
if err != nil {
return fmt.Errorf("failed to open node database: %s", err)
}
dbHash := nodeDB.Hash()
if hex.EncodeToString(dbHash[:]) != ndp.Hash && !ndp.Force {
return fmt.Errorf("got wrong hash, not modifying node database")
}
for _, n := range nodeList {
err := nodeDB.DelNode(n.Id.Get())
if err != nil {
wwlog.Error("%s", err)
} else {
//count++
wwlog.Verbose("Deleting node: %s\n", n.Id.Print())
}
}
err = nodeDB.Persist()
if err != nil {
return errors.Wrap(err, "failed to persist nodedb")
}
err = warewulfd.DaemonReload()
if err != nil {
return errors.Wrap(err, "failed to reload warewulf daemon")
}
return
}
// NodeDeleteParameterCheck does error checking on NodeDeleteParameter.
// Output to the console if console is true.
// Returns the nodes to delete.
func NodeDeleteParameterCheck(ndp *wwapiv1.NodeDeleteParameter, console bool) (nodeList []node.NodeInfo, err error) {
if ndp == nil {
return nodeList, fmt.Errorf("NodeDeleteParameter is nil")
}
nodeDB, err := node.New()
if err != nil {
return nodeList, fmt.Errorf("failed to open node database: %s", err)
}
dbHash := nodeDB.Hash()
if hex.EncodeToString(dbHash[:]) != ndp.Hash && !ndp.Force {
wwlog.Debug("got hash: %s", ndp.Hash)
wwlog.Debug("actual hash: %s", hex.EncodeToString(dbHash[:]))
return nodeList, fmt.Errorf("got wrong hash, not modifying node database")
}
nodes, err := nodeDB.FindAllNodes()
if err != nil {
return nodeList, fmt.Errorf("could not get node list: %s", err)
}
node_args := hostlist.Expand(ndp.NodeNames)
nodeList = node.FilterByName(nodes, node_args)
if len(nodeList) == 0 {
wwlog.Info("No nodes found")
}
return
}
// NodeSet is the wwapiv1 implmentation for updating node fields.
func NodeSet(set *wwapiv1.NodeSetParameter) (err error) {
if set == nil {
return fmt.Errorf("NodeAddParameter is nil")
}
var nodeDB node.NodeYaml
nodeDB, _, err = NodeSetParameterCheck(set, false)
if err != nil {
return
}
return DbSave(&nodeDB)
}
// NodeSetParameterCheck does error checking on NodeSetParameter.
// Output to the console if console is true.
// TODO: Determine if the console switch does wwlog or not.
// - console may end up being textOutput?
func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB node.NodeYaml, nodeCount uint, err error) {
if set == nil {
err = fmt.Errorf("node set parameter is nil")
if console {
fmt.Printf("%v\n", err)
return
}
}
if set.NodeNames == nil {
err = fmt.Errorf("node set parameter: NodeNames is nil")
if console {
fmt.Printf("%v\n", err)
return
}
}
nodeDB, err = node.New()
if err != nil {
wwlog.Error("Could not open node configuration: %s", err)
return
}
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Error("Could not get node list: %s", err)
return
}
// Note: This does not do expansion on the nodes.
if set.AllNodes || (len(set.NodeNames) == 0 && len(nodes) > 0) {
if console {
fmt.Printf("\n*** WARNING: This command will modify all nodes! ***\n\n")
}
} else {
expandNodes := hostlist.Expand(set.NodeNames)
nodes = node.FilterByName(nodes, expandNodes)
}
if len(nodes) == 0 {
if console {
fmt.Printf("No nodes found\n")
}
return
}
for _, n := range nodes {
wwlog.Verbose("Evaluating node: %s", n.Id.Get())
var nodeConf node.NodeConf
err = yaml.Unmarshal([]byte(set.NodeConfYaml), &nodeConf)
if err != nil {
wwlog.Error(fmt.Sprintf("%v", err.Error()))
return
}
err = nodeConf.Check()
if err != nil {
err = fmt.Errorf("error on check of node %s: %s", n.Id.Get(), err)
return
}
n.SetFrom(&nodeConf)
if set.NetdevDelete != "" {
if _, ok := n.NetDevs[set.NetdevDelete]; !ok {
err = fmt.Errorf("network device name doesn't exist: %s", set.NetdevDelete)
wwlog.Error(fmt.Sprintf("%v", err.Error()))
return
}
wwlog.Verbose("Node: %s, Deleting network device: %s", n.Id.Get(), set.NetdevDelete)
delete(n.NetDevs, set.NetdevDelete)
}
if set.PartitionDelete != "" {
deletedPart := false
for diskname, disk := range n.Disks {
if _, ok := disk.Partitions[set.PartitionDelete]; ok {
wwlog.Verbose("Node: %s, on disk %, deleting partition: %s", n.Id.Get(), diskname, set.PartitionDelete)
deletedPart = true
delete(disk.Partitions, set.PartitionDelete)
}
if !deletedPart {
wwlog.Error(fmt.Sprintf("%v", err.Error()))
err = fmt.Errorf("partition doesn't exist: %s", set.PartitionDelete)
return
}
}
}
if set.DiskDelete != "" {
if _, ok := n.Disks[set.DiskDelete]; !ok {
err = fmt.Errorf("disk doesn't exist: %s", set.DiskDelete)
wwlog.Error(fmt.Sprintf("%v", err.Error()))
return
}
wwlog.Verbose("Node: %s, deleting disk: %s", n.Id.Get(), set.DiskDelete)
delete(n.Disks, set.DiskDelete)
}
if set.FilesystemDelete != "" {
if _, ok := n.FileSystems[set.FilesystemDelete]; !ok {
err = fmt.Errorf("filesystem doesn't exist: %s", set.FilesystemDelete)
wwlog.Error(fmt.Sprintf("%v", err.Error()))
return
}
wwlog.Verbose("Node: %s, deleting filesystem: %s", n.Id.Get(), set.FilesystemDelete)
delete(n.FileSystems, set.FilesystemDelete)
}
for _, key := range nodeConf.TagsDel {
wwlog.Debug("deleting tag %s", key)
delete(n.Tags, key)
}
if nodeConf.Ipmi != nil {
for _, key := range nodeConf.Ipmi.TagsDel {
wwlog.Debug("deleting Ipmi tag %s", key)
delete(n.Ipmi.Tags, key)
}
}
for net := range nodeConf.NetDevs {
for _, key := range nodeConf.NetDevs[net].TagsDel {
if _, ok := n.NetDevs[net]; ok {
delete(n.NetDevs[net].Tags, key)
}
}
}
err := nodeDB.NodeUpdate(n)
if err != nil {
wwlog.Error("%s", err)
os.Exit(1)
}
nodeCount++
}
return
}
// NodeStatus returns the imaging state for nodes.
// This requires warewulfd.
func NodeStatus(nodeNames []string) (nodeStatusResponse *wwapiv1.NodeStatusResponse, err error) {
// Local structs for translating json from warewulfd.
type nodeStatusInternal struct {
NodeName string `json:"node name"`
Stage string `json:"stage"`
Sent string `json:"sent"`
Ipaddr string `json:"ipaddr"`
Lastseen int64 `json:"last seen"`
}
// all status is a map with one key (nodes)
// and maps of [nodeName]NodeStatus underneath.
type allStatus struct {
Nodes map[string]*nodeStatusInternal `json:"nodes"`
}
controller := warewulfconf.Get()
if controller.Ipaddr == "" {
err = fmt.Errorf("the Warewulf Server IP Address is not properly configured")
wwlog.Error(fmt.Sprintf("%v", err.Error()))
return
}
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 {
wwlog.Error("Could not connect to Warewulf server: %s", err)
return
}
defer resp.Body.Close()
decoder := json.NewDecoder(resp.Body)
var wwNodeStatus allStatus
err = decoder.Decode(&wwNodeStatus)
if err != nil {
wwlog.Error("Could not decode JSON: %s", err)
return
}
// Translate struct and filter.
nodeStatusResponse = &wwapiv1.NodeStatusResponse{}
if len(nodeNames) == 0 {
for _, v := range wwNodeStatus.Nodes {
nodeStatusResponse.NodeStatus = append(nodeStatusResponse.NodeStatus,
&wwapiv1.NodeStatus{
NodeName: v.NodeName,
Stage: v.Stage,
Sent: v.Sent,
Ipaddr: v.Ipaddr,
Lastseen: v.Lastseen,
})
}
} else {
nodeList := hostlist.Expand(nodeNames)
for _, v := range wwNodeStatus.Nodes {
for j := 0; j < len(nodeList); j++ {
if v.NodeName == nodeList[j] {
nodeStatusResponse.NodeStatus = append(nodeStatusResponse.NodeStatus,
&wwapiv1.NodeStatus{
NodeName: v.NodeName,
Stage: v.Stage,
Sent: v.Sent,
Ipaddr: v.Ipaddr,
Lastseen: v.Lastseen,
})
break
}
}
}
}
return
}

View File

@@ -0,0 +1,140 @@
package apinode
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
)
// NodeSet is the wwapiv1 implmentation for updating node fields.
func NodeSet(set *wwapiv1.ConfSetParameter) (err error) {
if set == nil {
return fmt.Errorf("NodeSetParameter is nil")
}
var nodeDB node.NodeYaml
nodeDB, _, err = NodeSetParameterCheck(set)
if err != nil {
return err
}
if err = nodeDB.Persist(); err != nil {
return err
}
if err = warewulfd.DaemonReload(); err != nil {
return err
}
return
}
/*
NodeSetParameterCheck does error checking and returns a modified
NodeYml which than can be persisted
*/
func NodeSetParameterCheck(set *wwapiv1.ConfSetParameter) (nodeDB node.NodeYaml, count uint, err error) {
nodeDB, err = node.New()
if err != nil {
wwlog.Error("Could not open configuration: %s", err)
return
}
//func AbstractSetParameterCheck(set *wwapiv1.ConfSetParameter, confMap map[string]*node.NodeConf, confs []string) (count uint, err error) {
if set == nil {
err = fmt.Errorf("profile set parameter is nil")
return
}
if set.ConfList == nil {
err = fmt.Errorf("node nodes to set!")
return
}
confs := nodeDB.ListAllNodes()
// Note: This does not do expansion on the nodes.
if set.AllConfs || (len(set.ConfList) == 0) {
wwlog.Warn("this command will modify all nodes/profiles")
} else if len(confs) == 0 {
wwlog.Warn("no nodes/profiles found")
return
} else {
confs = set.ConfList
}
//var confobject node.NodeConf
for _, p := range set.ConfList {
if util.InSlice(set.ConfList, p) {
wwlog.Verbose("evaluating profile: %s", p)
if _, ok := nodeDB.Nodes[p]; !ok {
continue
}
err = yaml.Unmarshal([]byte(set.NodeConfYaml), nodeDB.Nodes[p])
if err != nil {
return
}
if set.NetdevDelete != "" {
if _, ok := nodeDB.Nodes[p].NetDevs[set.NetdevDelete]; !ok {
err = fmt.Errorf("network device name doesn't exist: %s", set.NetdevDelete)
wwlog.Error(fmt.Sprintf("%v", err.Error()))
return
}
wwlog.Verbose("Profile: %s, Deleting network device: %s", p, set.NetdevDelete)
delete(nodeDB.Nodes[p].NetDevs, set.NetdevDelete)
}
if set.PartitionDelete != "" {
for diskname, disk := range nodeDB.Nodes[p].Disks {
if _, ok := disk.Partitions[set.PartitionDelete]; ok {
wwlog.Verbose("Node: %s, on disk %, deleting partition: %s", p, diskname, set.PartitionDelete)
delete(disk.Partitions, set.PartitionDelete)
} else {
return nodeDB, count, fmt.Errorf("partition doesn't exist: %s", set.PartitionDelete)
}
}
}
if set.DiskDelete != "" {
if _, ok := nodeDB.Nodes[p].Disks[set.DiskDelete]; ok {
wwlog.Verbose("Node: %s, deleting disk: %s", p, set.DiskDelete)
delete(nodeDB.Nodes[p].Disks, set.DiskDelete)
} else {
return nodeDB, count, fmt.Errorf("disk doesn't exist: %s", set.DiskDelete)
}
}
if set.FilesystemDelete != "" {
if _, ok := nodeDB.Nodes[p].FileSystems[set.FilesystemDelete]; ok {
wwlog.Verbose("Node: %s, deleting filesystem: %s", p, set.FilesystemDelete)
delete(nodeDB.Nodes[p].FileSystems, set.FilesystemDelete)
} else {
return nodeDB, count, fmt.Errorf("disk doesn't exist: %s", set.FilesystemDelete)
}
}
for _, key := range set.TagDel {
delete(nodeDB.Nodes[p].Tags, key)
}
for key, val := range set.TagAdd {
if nodeDB.Nodes[p].Tags == nil {
nodeDB.Nodes[p].Tags = make(map[string]string)
}
nodeDB.Nodes[p].Tags[key] = val
}
for key, val := range set.IpmiTagAdd {
if nodeDB.Nodes[p].Ipmi.Tags == nil {
nodeDB.Nodes[p].Ipmi.Tags = make(map[string]string)
}
nodeDB.Nodes[p].Ipmi.Tags[key] = val
}
for _, key := range set.IpmiTagDel {
delete(nodeDB.Nodes[p].Ipmi.Tags, key)
}
if _, ok := nodeDB.Nodes[p].NetDevs[set.Netdev]; ok {
for _, key := range set.NetTagDel {
delete(nodeDB.Nodes[p].NetDevs[set.Netdev].Tags, key)
}
for key, val := range set.TagAdd {
nodeDB.Nodes[p].NetDevs[set.Netdev].Tags[key] = val
}
}
count++
}
}
return
}