223 lines
7.0 KiB
Go
223 lines
7.0 KiB
Go
package node
|
|
|
|
import (
|
|
"github.com/hpcng/warewulf/internal/pkg/errors"
|
|
"github.com/hpcng/warewulf/internal/pkg/util"
|
|
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
|
|
|
"gopkg.in/yaml.v2"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
func (self *nodeYaml) AddGroup(groupID string) error {
|
|
var group nodeGroup
|
|
|
|
if _, ok := self.NodeGroups[groupID]; ok {
|
|
return errors.New("Group name already exists: " + groupID)
|
|
}
|
|
|
|
self.NodeGroups[groupID] = &group
|
|
self.NodeGroups[groupID].DomainSuffix = groupID
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *nodeYaml) AddNode(groupID string, nodeID string) error {
|
|
var node nodeEntry
|
|
|
|
wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID)
|
|
|
|
if _, ok := self.NodeGroups[groupID]; ok {
|
|
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
|
|
return errors.New("Nodename already exists in group: " + nodeID)
|
|
}
|
|
} else {
|
|
return errors.New("Group does not exist: "+groupID)
|
|
}
|
|
|
|
self.NodeGroups[groupID].Nodes[nodeID] = &node
|
|
self.NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *nodeYaml) DelNode(groupID string, nodeID string) error {
|
|
|
|
if _, ok := self.NodeGroups[groupID]; ok {
|
|
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
|
|
delete(self.NodeGroups[groupID].Nodes, nodeID)
|
|
wwlog.Printf(wwlog.VERBOSE, "Deleting node: %s/%s\n", groupID, nodeID)
|
|
} else {
|
|
return errors.New("Node '"+nodeID+"' was not found in group '"+groupID+"'")
|
|
}
|
|
} else {
|
|
return errors.New("Group '"+groupID+"' was not found")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *nodeYaml) DelNodeNet(groupID string, nodeID string, netDev string) error {
|
|
|
|
if _, ok := self.NodeGroups[groupID]; ok {
|
|
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
|
|
if _, ok := self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev]; ok {
|
|
wwlog.Printf(wwlog.VERBOSE, "Deleting node network device: %s/%s:%s\n", groupID, nodeID, netDev)
|
|
delete(self.NodeGroups[groupID].Nodes[nodeID].NetDevs, netDev)
|
|
} else {
|
|
return errors.New("Network device '"+netDev+"' was not found in node '"+groupID+"/"+nodeID+"'")
|
|
}
|
|
} else {
|
|
return errors.New("Node '"+nodeID+"' was not found in group '"+groupID+"'")
|
|
}
|
|
} else {
|
|
return errors.New("Group '"+groupID+"' was not found")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
func (self *nodeYaml) DelGroup(groupname string) error {
|
|
if _, ok := self.NodeGroups[groupname]; ok {
|
|
delete(self.NodeGroups, groupname)
|
|
} else {
|
|
return errors.New("Node group undefined: " + groupname)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *nodeYaml) SetGroupVal(groupID string, entry string, value string) error {
|
|
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
|
|
value = ""
|
|
}
|
|
|
|
if _, ok := self.NodeGroups[groupID]; ok {
|
|
wwlog.Printf(wwlog.VERBOSE, "Setting group %s to: %s = '%s'\n", groupID, entry, value )
|
|
|
|
switch strings.ToUpper(entry) {
|
|
case "DOMAINSUFFIX":
|
|
util.ValidateOrDie("Domain", entry, "^[a-zA-Z0-9-._]*$")
|
|
self.NodeGroups[groupID].DomainSuffix = value
|
|
}
|
|
|
|
} else {
|
|
return errors.New("Group does not exist: " +groupID)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *nodeYaml) SetNodeVal(groupID string, nodeID string, entry string, value string) error {
|
|
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
|
|
value = ""
|
|
}
|
|
if _, ok := self.NodeGroups[groupID]; ok {
|
|
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
|
|
wwlog.Printf(wwlog.VERBOSE, "Setting node %s/%s to: %s = '%s'\n", groupID, nodeID, entry, value )
|
|
|
|
switch strings.ToUpper(entry) {
|
|
case "VNFS":
|
|
util.ValidateOrDie("VNFS", entry, "^[a-zA-Z0-9-._]*$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].Vnfs = value
|
|
case "KERNEL":
|
|
util.ValidateOrDie("Kernel Version", entry, "^[a-zA-Z0-9-._]*$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].KernelVersion = value
|
|
case "DOMAINSUFFIX":
|
|
util.ValidateOrDie("Domain", entry, "^[a-zA-Z0-9-._]*$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].DomainSuffix = value
|
|
case "IPXE":
|
|
util.ValidateOrDie("iPXE Template", entry, "^[a-zA-Z0-9-._]*$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].Ipxe = value
|
|
case "HOSTNAME":
|
|
util.ValidateOrDie("Hostname", entry, "^[a-zA-Z0-9-._]*$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].Hostname = value
|
|
case "IPMIIPADDR":
|
|
util.ValidateOrDie("IPMI IP Address", entry, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].IpmiIpaddr = value
|
|
case "IPMIUSERNAME":
|
|
util.ValidateOrDie("IPMI Username", entry, "^[a-zA-Z0-9-._]*$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].IpmiUserName = value
|
|
case "IPMIPASSWORD":
|
|
util.ValidateOrDie("IPMI Password", entry, "^[a-zA-Z0-9-._]*$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].IpmiPassword = value
|
|
|
|
}
|
|
} else {
|
|
return errors.New("Node does not exist: " +groupID+ "/" +nodeID)
|
|
}
|
|
} else {
|
|
return errors.New("Group does not exist: " +groupID)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *nodeYaml) SetNodeNet(groupID string, nodeID string, netDev string, entry string, value string) error {
|
|
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
|
|
value = ""
|
|
}
|
|
|
|
if _, ok := self.NodeGroups[groupID]; ok {
|
|
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
|
|
if _, ok := self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev]; ok {
|
|
wwlog.Printf(wwlog.VERBOSE, "Editing existing node NetDev entry for node: %s/%s\n", groupID, nodeID)
|
|
} else {
|
|
var nd NetDevs
|
|
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev] = &nd
|
|
}
|
|
} else {
|
|
return errors.New("Node does not exist: "+groupID+"/"+nodeID)
|
|
}
|
|
} else {
|
|
return errors.New("Group does not exist: "+groupID)
|
|
}
|
|
|
|
switch strings.ToUpper(entry) {
|
|
case "IPADDR":
|
|
util.ValidateOrDie("IP address", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Ipaddr = value
|
|
case "NETMASK":
|
|
util.ValidateOrDie("Netmask", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Netmask = value
|
|
case "GATEWAY":
|
|
util.ValidateOrDie("Gateway", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Gateway = value
|
|
case "TYPE":
|
|
util.ValidateOrDie("Network device type", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Type = value
|
|
case "HWADDR":
|
|
util.ValidateOrDie("HW address", value, "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")
|
|
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Hwaddr = value
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *nodeYaml) Persist() error {
|
|
|
|
out, err := yaml.Marshal(self)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
file, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
|
if err != nil {
|
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
_, err = file.WriteString(string(out))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|