Updates to nodeStore

This commit is contained in:
Gregory Kurtzer
2020-11-26 16:38:34 -08:00
parent a4d2e3a0c8
commit 6d3ec350b6
6 changed files with 606 additions and 599 deletions

View File

@@ -0,0 +1,219 @@
package node
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"io/ioutil"
"regexp"
)
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) FindAllNodes() ([]NodeInfo, error) {
var ret []NodeInfo
for groupname, group := range self.NodeGroups {
for nodename, node := range group.Nodes {
var n NodeInfo
var allProfiles []string
if node.Disabled == true || group.Disabled == true {
wwlog.Printf(wwlog.VERBOSE, "Skipping disabled node: %s/%s\n", groupname, nodename)
continue
}
n.Id = nodename
n.Gid = groupname
n.GroupName = groupname
n.HostName = node.Hostname
n.IpmiIpaddr.Set(node.IpmiIpaddr)
n.Profiles = node.Profiles
allProfiles = append(allProfiles, group.Profiles...)
allProfiles = append(allProfiles, node.Profiles...)
for _, p := range allProfiles {
if _, ok := self.NodeProfiles[p]; !ok {
wwlog.Printf(wwlog.WARN, "Profile not found for node '%s': %s\n", nodename, p)
continue
}
n.Vnfs.profile = self.NodeProfiles[p].Vnfs
n.KernelVersion.profile = self.NodeProfiles[p].KernelVersion
n.KernelArgs.profile = self.NodeProfiles[p].KernelArgs
n.Ipxe.profile = self.NodeProfiles[p].Ipxe
n.IpmiUserName.profile = self.NodeProfiles[p].IpmiUserName
n.IpmiPassword.profile = self.NodeProfiles[p].IpmiPassword
n.DomainName.profile = self.NodeProfiles[p].DomainName
n.SystemOverlay.profile = self.NodeProfiles[p].SystemOverlay
n.RuntimeOverlay.profile = self.NodeProfiles[p].RuntimeOverlay
}
n.DomainName.value = node.DomainName
n.DomainName.group = group.DomainName
n.Vnfs.value = node.Vnfs
n.KernelVersion.value = node.KernelVersion
n.KernelArgs.value = node.KernelArgs
n.Ipxe.value = node.Ipxe
n.IpmiUserName.value = node.IpmiUserName
n.IpmiPassword.value = node.IpmiPassword
n.RuntimeOverlay.def = "default"
n.SystemOverlay.def = "default"
n.Ipxe.def = "default"
n.KernelArgs.def = "crashkernel=no quiet"
// config := config.New()
// n.VnfsRoot = config.VnfsChroot(vnfs.CleanName(n.Vnfs))
if n.DomainName.Defined() == true {
n.Fqdn = n.HostName + "." + n.DomainName.Get()
} else {
n.Fqdn = node.Hostname
}
n.NetDevs = node.NetDevs
ret = append(ret, n)
}
}
return ret, nil
}
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
var ret []GroupInfo
for groupname, group := range self.NodeGroups {
var g GroupInfo
g.Id = groupname
g.DomainName = group.DomainName
g.Disabled = group.Disabled
g.Comment = group.Comment
g.Profiles = group.Profiles
// TODO: Validate or die on all inputs
ret = append(ret, g)
}
return ret, nil
}
func (self *nodeYaml) FindAllProfiles() ([]ProfileInfo, error) {
var ret []ProfileInfo
for name, profile := range self.NodeProfiles {
var p ProfileInfo
p.Id = name
p.Comment = profile.Comment
p.Vnfs = profile.Vnfs
p.Ipxe = profile.Ipxe
p.KernelVersion = profile.KernelVersion
p.KernelArgs = profile.KernelArgs
p.IpmiUserName = profile.IpmiUserName
p.IpmiPassword = profile.IpmiPassword
p.DomainName = profile.DomainName
p.RuntimeOverlay = profile.RuntimeOverlay
p.SystemOverlay = profile.SystemOverlay
// TODO: Validate or die on all inputs
ret = append(ret, p)
}
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)
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)
if b == true {
ret = append(ret, node)
}
}
}
return ret, nil
}

View File

@@ -0,0 +1,123 @@
package node
import (
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"os"
)
type nodeYaml struct {
NodeProfiles map[string]*ProfileConf
NodeGroups map[string]*GroupConf
}
type ProfileConf struct {
Comment string `yaml:"comment"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
DomainName string `yaml:"domain name,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
}
type GroupConf struct {
Comment string `yaml:"comment"`
Disabled bool `yaml:"disabled,omitempty"`
DomainName string `yaml:"domain name"`
Profiles []string `yaml:"profiles,omitempty"`
Nodes map[string]*NodeConf
}
type NodeConf struct {
Comment string `yaml:"comment,omitempty"`
Disabled bool `yaml:"disabled,omitempty"`
Hostname string `yaml:"hostname,omitempty"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
DomainName string `yaml:"domain name,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,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 NodeInfoEntry struct {
value string
profile string
group string
def string
}
type NodeInfo struct {
Id string
Gid string
Uid string
Comment string
GroupName string
HostName string
Fqdn string
DomainName NodeInfoEntry
Vnfs NodeInfoEntry
VnfsRoot NodeInfoEntry
Ipxe NodeInfoEntry
KernelVersion NodeInfoEntry
KernelArgs NodeInfoEntry
IpmiIpaddr NodeInfoEntry
IpmiUserName NodeInfoEntry
IpmiPassword NodeInfoEntry
RuntimeOverlay NodeInfoEntry
SystemOverlay NodeInfoEntry
Profiles []string
NetDevs map[string]*NetDevs
}
type GroupInfo struct {
Id string
Comment string
Disabled bool
DomainName string
Profiles []string
}
type ProfileInfo struct {
Id string
Comment string
Vnfs string
Ipxe string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
DomainName string
RuntimeOverlay string
SystemOverlay string
}
const ConfigFile = "/etc/warewulf/nodes.conf"
func init() {
//TODO: Check to make sure nodes.conf is found
if util.IsFile(ConfigFile) == false {
wwlog.Printf(wwlog.ERROR, "Configuration file not found: %s\n", ConfigFile)
os.Exit(1)
}
}

View File

@@ -0,0 +1,55 @@
package node
func (self *NodeInfoEntry) String() string {
if self.value != "" {
return "node=" + self.value
}
if self.group != "" {
return "group=" + self.group
}
if self.profile != "" {
return "profile=" + self.profile
}
if self.def != "" {
return "default=" + self.def
}
return "--"
}
func (self *NodeInfoEntry) Get() string {
if self.value != "" {
return self.value
}
if self.group != "" {
return self.group
}
if self.profile != "" {
return self.profile
}
if self.def != "" {
return self.def
}
return ""
}
func (self *NodeInfoEntry) Defined() bool {
if self.Get() == "" {
return false
}
return true
}
func (self *NodeInfoEntry) Set(value string) {
if value == "" {
return
}
self.value = value
}
func (self *NodeInfoEntry) Unset() {
self.value = ""
}
func (self *NodeInfoEntry) GetReal() string {
return self.value
}

View File

@@ -0,0 +1,209 @@
package node
import (
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"os"
)
/****
*
* NODE MODIFIERS
*
****/
func (self *nodeYaml) AddNode(groupID string, nodeID string) error {
var node NodeConf
wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID)
if _, ok := self.NodeGroups[groupID]; !ok {
return errors.New("Group does not exist: " + groupID)
}
if _, ok := self.NodeGroups[groupID].Nodes[groupID]; ok {
return errors.New("Nodename already exists in group: " + nodeID)
}
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 {
return errors.New("Group '" + groupID + "' was not found")
}
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; !ok {
return errors.New("Node '" + nodeID + "' was not found in group '" + groupID + "'")
}
wwlog.Printf(wwlog.VERBOSE, "Deleting node network device: %s/%s\n", groupID, nodeID)
delete(self.NodeGroups[groupID].Nodes, nodeID)
return nil
}
func(self *nodeYaml) NodeUpdate(node NodeInfo) error {
groupID := node.Gid
nodeID := node.Id
if _, ok := self.NodeGroups[groupID]; !ok {
return errors.New("Group '" + groupID + "' was not found")
}
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; !ok {
return errors.New("Node '" + nodeID + "' was not found in group '" + groupID + "'")
}
self.NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName
self.NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].DomainName = node.DomainName.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].Ipxe = node.Ipxe.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].KernelVersion = node.KernelVersion.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].IpmiIpaddr = node.IpmiIpaddr.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].IpmiUserName = node.IpmiUserName.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].IpmiPassword = node.IpmiPassword.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].Profiles = node.Profiles
self.NodeGroups[groupID].Nodes[nodeID].NetDevs = node.NetDevs
return nil
}
/****
*
* GROUP MODIFIERS
*
****/
func (self *nodeYaml) AddGroup(groupID string) error {
var group GroupConf
wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID)
if _, ok := self.NodeGroups[groupID]; ok {
return errors.New("Group name already exists: " + groupID)
}
self.NodeGroups[groupID] = &group
self.NodeGroups[groupID].DomainName = groupID
return nil
}
func (self *nodeYaml) DelGroup(groupID string) error {
if _, ok := self.NodeGroups[groupID]; !ok {
return errors.New("Group '" + groupID + "' was not found")
}
wwlog.Printf(wwlog.VERBOSE, "Deleting group: %s\n", groupID)
delete(self.NodeGroups, groupID)
return nil
}
func(self *nodeYaml) GroupUpdate(group GroupInfo) error {
groupID := group.Id
if _, ok := self.NodeGroups[groupID]; !ok {
return errors.New("Group '" + groupID + "' was not found")
}
self.NodeGroups[groupID].DomainName = group.DomainName
return nil
}
/****
*
* PROFILE MODIFIERS
*
****/
func (self *nodeYaml) AddProfile(profileID string) error {
var profile ProfileConf
wwlog.Printf(wwlog.VERBOSE, "Adding new profile: %s/%s\n", profileID)
if _, ok := self.NodeProfiles[profileID]; ok {
return errors.New("Profile name already exists: " + profileID)
}
self.NodeProfiles[profileID] = &profile
return nil
}
func (self *nodeYaml) DelProfile(profileID string) error {
if _, ok := self.NodeProfiles[profileID]; ! ok {
return errors.New("Group '" + profileID + "' was not found")
}
wwlog.Printf(wwlog.VERBOSE, "Deleting profile: %s\n", profileID)
delete(self.NodeProfiles, profileID)
return nil
}
func(self *nodeYaml) ProfileUpdate(profile ProfileInfo) error {
profileID := profile.Id
if _, ok := self.NodeProfiles[profileID]; ! ok {
return errors.New("Group '" + profileID + "' was not found")
}
self.NodeProfiles[profileID].DomainName = profile.DomainName
self.NodeProfiles[profileID].Vnfs = profile.Vnfs
self.NodeProfiles[profileID].Ipxe = profile.Ipxe
self.NodeProfiles[profileID].KernelVersion = profile.KernelVersion
self.NodeProfiles[profileID].IpmiUserName = profile.IpmiUserName
self.NodeProfiles[profileID].IpmiPassword = profile.IpmiPassword
self.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay
self.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay
return nil
}
/****
*
* PERSISTENCE
*
****/
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
}

View File

@@ -1,222 +0,0 @@
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
}

View File

@@ -1,377 +0,0 @@
package node
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"io/ioutil"
"regexp"
)
const ConfigFile = "/etc/warewulf/nodes.conf"
func init() {
//TODO: Check to make sure nodes.conf is found
}
type nodeYaml struct {
Profiles map[string]*profileConfig
NodeGroups map[string]*nodeGroup
Hwaddrs map[string]NodeInfo
}
type profileConfig struct {
Vnfs string `yaml:"vnfs"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version"`
KernelArgs string `yaml:"kernel args"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
DomainSuffix string `yaml:"domain suffix,omitempty"`
RuntimeOverlay []OverlayEntry `yaml:"runtime overlay files,omitempty"`
SystemOverlay []OverlayEntry `yaml:"system overlay files,omitempty"`
}
type OverlayEntry struct {
Path string `yaml:"path,omitempty"`
File bool `yaml:"file,omitempty"`
Dir bool `yaml:"dir,omitempty"`
Link bool `yaml:"link,omitempty"`
Template bool `yaml:"template,omitempty"`
Mode int32 `yaml:"mode,omitempty"`
Owner string `yaml:"owner,omitempty"`
Group string `yaml:"group,omitempty"`
Source string `yaml:"source,omitempty"`
Sources []string `yaml:"sources,omitempty"`
}
type nodeGroup struct {
Comment string
DomainSuffix string `yaml:"domain suffix"`
Profiles []string `yaml:"profiles"`
Nodes map[string]*nodeEntry
}
type nodeEntry struct {
Hostname string `yaml:"hostname,omitempty"`
Vnfs string `yaml:"vnfs"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version"`
KernelArgs string `yaml:"kernel args"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
DomainSuffix string `yaml:"domain suffix,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
Profiles []string `yaml:"profiles"`
RuntimeOverlay []OverlayEntry `yaml:"system overlay files,omitempty"`
SystemOverlay []OverlayEntry `yaml:"runtime overlay files,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 string
Gid string
Uid string
GroupName string
HostName string
DomainName string
Fqdn string
Vnfs string
VnfsRoot string
Ipxe string
KernelVersion string
KernelArgs string
IpmiIpaddr string
IpmiUserName string
IpmiPassword string
Profiles []string
RuntimeOverlay []OverlayEntry
SystemOverlay []OverlayEntry
NetDevs map[string]*NetDevs
}
type GroupInfo struct {
Id string
GroupName string
DomainName string
Vnfs string
Ipxe string
SystemOverlay string
RuntimeOverlay string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
}
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 = groupname
g.GroupName = groupname
g.DomainName = 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 = nodename
n.Gid = groupname
n.GroupName = groupname
n.HostName = node.Hostname
n.Profiles = node.Profiles
n.IpmiIpaddr = node.IpmiIpaddr
if len(n.Profiles) == 0 {
n.Profiles = append(n.Profiles, "default")
}
for _, p := range n.Profiles {
if _, ok := self.Profiles[p]; ok {
} else {
continue
}
if self.Profiles[p].Vnfs != "" {
n.Vnfs = self.Profiles[p].Vnfs
}
if self.Profiles[p].KernelVersion != "" {
n.KernelVersion = self.Profiles[p].KernelVersion
}
if self.Profiles[p].KernelArgs != "" {
n.KernelArgs = self.Profiles[p].KernelArgs
}
if self.Profiles[p].Ipxe != "" {
n.Ipxe = self.Profiles[p].Ipxe
}
if self.Profiles[p].IpmiUserName != "" {
n.IpmiUserName = self.Profiles[p].IpmiUserName
}
if self.Profiles[p].IpmiPassword != "" {
n.IpmiPassword = self.Profiles[p].IpmiPassword
}
if self.Profiles[p].DomainSuffix != "" {
n.DomainName = self.Profiles[p].DomainSuffix
}
for _, ro := range self.Profiles[p].RuntimeOverlay {
n.RuntimeOverlay = append(n.RuntimeOverlay, ro)
}
for _, so := range self.Profiles[p].SystemOverlay {
n.SystemOverlay = append(n.SystemOverlay, so)
}
}
if node.DomainSuffix != "" {
n.DomainName = node.DomainSuffix
} else if group.DomainSuffix != "" {
n.DomainName = group.DomainSuffix
}
if node.Vnfs != "" {
n.Vnfs = node.Vnfs
}
if node.KernelVersion != "" {
n.KernelVersion = node.KernelVersion
}
if node.KernelArgs != "" {
n.KernelArgs = node.KernelArgs
}
if node.Ipxe != "" {
n.Ipxe = node.Ipxe
}
if node.IpmiUserName != "" {
n.IpmiUserName = node.IpmiUserName
}
if node.IpmiPassword != "" {
n.IpmiPassword = node.IpmiPassword
}
if n.Ipxe == "" {
n.Ipxe = "default"
}
if n.KernelArgs == "" {
n.KernelArgs = "crashkernel=no quiet"
}
config := config.New()
n.VnfsRoot = config.VnfsChroot(vnfs.CleanName(n.Vnfs))
if n.DomainName != "" {
n.Fqdn = node.Hostname + "." + n.DomainName
} else {
n.Fqdn = node.Hostname
}
n.NetDevs = node.NetDevs
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)
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)
if b == true {
ret = append(ret, node)
}
}
}
return ret, nil
}