324 lines
7.7 KiB
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
|
|
}
|