Files
warewulf/internal/pkg/node/node.go

324 lines
7.7 KiB
Go

package node
import (
"fmt"
"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"
"io/ioutil"
"regexp"
)
const ConfigFile = "/etc/warewulf/nodes.conf"
const LocalStateDir = "/var/warewulf"
func init() {
//TODO: Check to make sure nodes.conf is found
}
type nodeYaml struct {
NodeGroups map[string]*nodeGroup //`yaml:"nodegroups"`
Hwaddrs map[string]NodeInfo
}
type nodeGroup struct {
Comment string
Vnfs string `yaml:"vnfs"`
Ipxe string `yaml:"ipxe template,omitempty"`
SystemOverlay string `yaml:"system overlay,omitempty""`
RuntimeOverlay string `yaml:"runtime overlay""`
DomainSuffix string `yaml:"domain suffix"`
KernelVersion string `yaml:"kernel version"`
KernelArgs string `yaml:"kernel args"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
Nodes map[string]*nodeEntry
}
type nodeEntry struct {
Hostname string `yaml:"hostname,omitempty"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
SystemOverlay string `yaml:"system overlay,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay,omitempty"`
DomainSuffix string `yaml:"domain suffix,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
NetDevs map[string]*netDevs
}
type netDevs struct {
Type string `yaml:"type,omitempty"`
Hwaddr string
Ipaddr string
Netmask string
Gateway string `yaml:"gateway,omitempty"`
}
type EntryInfo struct {
Value string
override string
def string
}
type NodeInfo struct {
Id EntryInfo
Gid EntryInfo
Uid EntryInfo
GroupName EntryInfo
HostName EntryInfo
DomainName EntryInfo
Fqdn EntryInfo
Vnfs EntryInfo
Ipxe EntryInfo
SystemOverlay EntryInfo
RuntimeOverlay EntryInfo
KernelVersion EntryInfo
KernelArgs EntryInfo
IpmiIpaddr EntryInfo
IpmiUserName EntryInfo
IpmiPassword EntryInfo
NetDevs map[string]*netDevs
}
type GroupInfo struct {
Id EntryInfo
GroupName EntryInfo
DomainName EntryInfo
Vnfs EntryInfo
Ipxe EntryInfo
SystemOverlay EntryInfo
RuntimeOverlay EntryInfo
KernelVersion EntryInfo
KernelArgs EntryInfo
IpmiUserName EntryInfo
IpmiPassword EntryInfo
}
func (i *EntryInfo) Default (value string) {
if value == "" {
return
}
i.def = value
}
func (i *EntryInfo) Set (value string) {
if value == "" {
return
}
i.Value = value
i.override = ""
}
func (i *EntryInfo) Override (value string) {
if value == "" {
return
}
i.override = value
}
func (i *EntryInfo) String () string {
if i.override != "" {
return i.override
} else if i.Value != "" {
return i.Value
}
return i.def
}
func (i *EntryInfo) Defined () bool {
if i.String() == "" {
return false
}
return true
}
func (i *EntryInfo) Fprint () string {
if i.override != "" {
return "["+ i.override +"]"
} else if i.Value != "" {
return i.Value
} else if i.def != "" {
return "("+ i.def +")"
}
return "--"
}
func New() (nodeYaml, error) {
var ret nodeYaml
wwlog.Printf(wwlog.DEBUG, "Opening node configuration file: %s\n", ConfigFile)
data, err := ioutil.ReadFile(ConfigFile)
if err != nil {
fmt.Printf("error reading node configuration file\n")
return ret, err
}
err = yaml.Unmarshal(data, &ret)
if err != nil {
return ret, err
}
return ret, nil
}
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
var ret []GroupInfo
for groupname, group := range self.NodeGroups {
var g GroupInfo
g.Id.Set(groupname)
g.GroupName.Set(groupname)
g.RuntimeOverlay.Set(group.RuntimeOverlay)
g.SystemOverlay.Set(group.SystemOverlay)
g.Ipxe.Set(group.Ipxe)
g.KernelVersion.Set(group.KernelVersion)
g.KernelArgs.Set(group.KernelArgs)
g.Vnfs.Set(group.Vnfs)
g.IpmiUserName.Set(group.IpmiUserName)
g.IpmiPassword.Set(group.IpmiPassword)
g.DomainName.Set(group.DomainSuffix)
// TODO: Validate or die on all inputs
ret = append(ret, g)
}
return ret, nil
}
func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
var ret []NodeInfo
for groupname, group := range self.NodeGroups {
for nodename, node := range group.Nodes {
var n NodeInfo
n.Id.Set(nodename)
n.Gid.Set(groupname)
n.GroupName.Set(groupname)
n.HostName.Set(node.Hostname)
n.IpmiIpaddr.Set(node.IpmiIpaddr)
n.Vnfs.Set(group.Vnfs)
n.SystemOverlay.Set(group.SystemOverlay)
n.RuntimeOverlay.Set(group.RuntimeOverlay)
n.KernelVersion.Set(group.KernelVersion)
n.KernelArgs.Set(group.KernelArgs)
n.DomainName.Set(group.DomainSuffix)
n.Ipxe.Set(group.Ipxe)
n.IpmiUserName.Set(group.IpmiUserName)
n.IpmiPassword.Set(group.IpmiPassword)
n.Vnfs.Override(node.Vnfs)
n.SystemOverlay.Override(node.SystemOverlay)
n.RuntimeOverlay.Override(node.RuntimeOverlay)
n.KernelVersion.Override(node.KernelVersion)
n.KernelArgs.Override(node.KernelArgs)
n.DomainName.Override(node.DomainSuffix)
n.Ipxe.Override(node.Ipxe)
n.IpmiUserName.Override(node.IpmiUserName)
n.IpmiPassword.Override(node.IpmiPassword)
n.RuntimeOverlay.Default("default")
n.SystemOverlay.Default("default")
n.Ipxe.Default("default")
if n.DomainName.Defined() == true {
if group.DomainSuffix != "" {
n.Fqdn.Set(node.Hostname + "." + group.DomainSuffix)
} else if node.DomainSuffix != "" {
n.Fqdn.Set(node.Hostname + "." + node.DomainSuffix)
} else {
n.Fqdn.Set(node.Hostname)
}
}
n.NetDevs = node.NetDevs
util.ValidateOrDie(n.Fqdn.String() +":group name", n.GroupName.String(), "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn.String() +":vnfs", n.Vnfs.String(), "^[a-zA-Z0-9-._:/]*$")
util.ValidateOrDie(n.Fqdn.String() +":system overlay", n.SystemOverlay.String(), "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn.String() +":runtime overlay", n.RuntimeOverlay.String(), "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn.String() +":domain suffix", n.DomainName.String(), "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn.String() +":hostname", n.HostName.String(), "^[a-zA-Z0-9-_]*$")
util.ValidateOrDie(n.Fqdn.String() +":kernel version", n.KernelVersion.String(), "^[a-zA-Z0-9-._]*$")
ret = append(ret, n)
}
}
return ret, nil
}
func (self *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
var ret NodeInfo
n, _ := self.FindAllNodes()
for _, node := range n {
for _, dev := range node.NetDevs {
if dev.Hwaddr == hwa {
return node, nil
}
}
}
return ret, errors.New("No nodes found with HW Addr: " + hwa)
}
func (self *nodeYaml) FindByIpaddr(ipaddr string) (NodeInfo, error) {
var ret NodeInfo
n, _ := self.FindAllNodes()
for _, node := range n {
for _, dev := range node.NetDevs {
if dev.Ipaddr == ipaddr {
return node, nil
}
}
}
return ret, errors.New("No nodes found with IP Addr: " + ipaddr)
}
func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) {
var ret []NodeInfo
n, _ := nodes.FindAllNodes()
for _, node := range n {
b, _ := regexp.MatchString(search, node.Fqdn.String())
if b == true {
ret = append(ret, node)
}
}
return ret, nil
}
func (nodes *nodeYaml) SearchByNameList(searchList []string) ([]NodeInfo, error) {
var ret []NodeInfo
n, _ := nodes.FindAllNodes()
for _, search := range searchList {
for _, node := range n {
b, _ := regexp.MatchString(search, node.Fqdn.String())
if b == true {
ret = append(ret, node)
}
}
}
return ret, nil
}