Files
warewulf/internal/pkg/node/constructors.go
2020-12-01 23:33:01 -08:00

316 lines
8.1 KiB
Go

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 controllername, controller := range self.Controllers {
for groupname, group := range controller.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.SetNode(nodename)
n.Gid.SetNode(groupname)
n.Cid.SetNode(controllername)
n.HostName.SetNode(node.Hostname)
n.IpmiIpaddr.SetNode(node.IpmiIpaddr)
n.IpmiNetmask.SetNode(node.IpmiNetmask)
n.DomainName.SetNode(node.DomainName)
n.Vnfs.SetNode(node.Vnfs)
n.KernelVersion.SetNode(node.KernelVersion)
n.KernelArgs.SetNode(node.KernelArgs)
n.Ipxe.SetNode(node.Ipxe)
n.IpmiUserName.SetNode(node.IpmiUserName)
n.IpmiPassword.SetNode(node.IpmiPassword)
n.SystemOverlay.SetNode(node.SystemOverlay)
n.RuntimeOverlay.SetNode(node.RuntimeOverlay)
n.DomainName.SetGroup(group.DomainName)
n.Vnfs.SetGroup(group.Vnfs)
n.KernelVersion.SetGroup(group.KernelVersion)
n.KernelArgs.SetGroup(group.KernelArgs)
n.Ipxe.SetGroup(group.Ipxe)
n.IpmiNetmask.SetGroup(group.IpmiNetmask)
n.IpmiUserName.SetGroup(group.IpmiUserName)
n.IpmiPassword.SetGroup(group.IpmiPassword)
n.SystemOverlay.SetGroup(group.SystemOverlay)
n.RuntimeOverlay.SetGroup(group.RuntimeOverlay)
n.RuntimeOverlay.SetDefault("default")
n.SystemOverlay.SetDefault("default")
n.Ipxe.SetDefault("default")
n.KernelArgs.SetDefault("crashkernel=no quiet")
n.GroupProfiles = group.Profiles
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.DomainName.SetProfile(self.NodeProfiles[p].DomainName)
n.Vnfs.SetProfile(self.NodeProfiles[p].Vnfs)
n.KernelVersion.SetProfile(self.NodeProfiles[p].KernelVersion)
n.KernelArgs.SetProfile(self.NodeProfiles[p].KernelArgs)
n.Ipxe.SetProfile(self.NodeProfiles[p].Ipxe)
n.IpmiNetmask.SetProfile(self.NodeProfiles[p].IpmiNetmask)
n.IpmiUserName.SetProfile(self.NodeProfiles[p].IpmiUserName)
n.IpmiPassword.SetProfile(self.NodeProfiles[p].IpmiPassword)
n.SystemOverlay.SetProfile(self.NodeProfiles[p].SystemOverlay)
n.RuntimeOverlay.SetProfile(self.NodeProfiles[p].RuntimeOverlay)
}
if n.DomainName.Defined() == true {
n.Fqdn.SetNode(node.Hostname + "." + n.DomainName.Get())
} else {
n.Fqdn.SetNode(node.Hostname)
}
n.NetDevs = node.NetDevs
ret = append(ret, n)
}
}
}
return ret, nil
}
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
var ret []GroupInfo
for controllername, controller := range self.Controllers {
for groupname, group := range controller.NodeGroups {
var g GroupInfo
g.Id.SetGroup(groupname)
g.Cid.SetGroup(controllername)
g.DomainName.SetGroup(group.DomainName)
g.Comment.SetGroup(group.Comment)
g.Vnfs.SetGroup(group.Vnfs)
g.KernelVersion.SetGroup(group.KernelVersion)
g.KernelArgs.SetGroup(group.KernelArgs)
g.IpmiNetmask.SetGroup(group.IpmiNetmask)
g.IpmiPassword.SetGroup(group.IpmiPassword)
g.IpmiUserName.SetGroup(group.IpmiUserName)
g.SystemOverlay.SetGroup(group.SystemOverlay)
g.RuntimeOverlay.SetGroup(group.RuntimeOverlay)
g.Profiles = group.Profiles
for _, p := range group.Profiles {
if _, ok := self.NodeProfiles[p]; !ok {
wwlog.Printf(wwlog.WARN, "Profile not found for group '%s': %s\n", groupname, p)
continue
}
g.DomainName.SetProfile(self.NodeProfiles[p].DomainName)
g.Vnfs.SetProfile(self.NodeProfiles[p].Vnfs)
g.KernelVersion.SetProfile(self.NodeProfiles[p].KernelVersion)
g.KernelArgs.SetProfile(self.NodeProfiles[p].KernelArgs)
g.Ipxe.SetProfile(self.NodeProfiles[p].Ipxe)
g.IpmiNetmask.SetProfile(self.NodeProfiles[p].IpmiNetmask)
g.IpmiUserName.SetProfile(self.NodeProfiles[p].IpmiUserName)
g.IpmiPassword.SetProfile(self.NodeProfiles[p].IpmiPassword)
g.SystemOverlay.SetProfile(self.NodeProfiles[p].SystemOverlay)
g.RuntimeOverlay.SetProfile(self.NodeProfiles[p].RuntimeOverlay)
}
// TODO: Validate or die on all inputs
ret = append(ret, g)
}
}
return ret, nil
}
func (self *nodeYaml) FindAllControllers() ([]ControllerInfo, error) {
var ret []ControllerInfo
for controllername, controller := range self.Controllers {
var c ControllerInfo
c.Id = controllername
c.Ipaddr = controller.Ipaddr
c.Comment = controller.Comment
c.Fqdn = controller.Fqdn
//TODO: Is there a better way to do this, cause EWWW!
c.Services = struct {
Warewulfd struct {
Port string
Secure bool
StartCmd string
RestartCmd string
EnableCmd string
}
Dhcp struct {
Enabled bool
Template string
RangeStart string
RangeEnd string
ConfigFile string
StartCmd string
RestartCmd string
EnableCmd string
}
Tftp struct {
Enabled bool
TftpRoot string
StartCmd string
RestartCmd string
EnableCmd string
}
Nfs struct {
Enabled bool
Exports []string
StartCmd string
RestartCmd string
EnableCmd string
}
}(controller.Services)
// Validations //
if c.Ipaddr == "" {
wwlog.Printf(wwlog.WARN, "Controller IP address is unset: %s\n", c.Id)
}
if c.Services.Warewulfd.Port == "" {
c.Services.Warewulfd.Port = "987"
}
// TODO: Validate or die on all inputs
ret = append(ret, c)
}
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.IpmiNetmask = profile.IpmiNetmask
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.Get())
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.Get())
if b == true {
ret = append(ret, node)
}
}
}
return ret, nil
}