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 }