Merge branch 'development' into wwlog-newlines
This commit is contained in:
@@ -14,11 +14,34 @@ import (
|
||||
)
|
||||
|
||||
var ConfigFile string
|
||||
var DefaultConfig string
|
||||
|
||||
// used as fallback if DefaultConfig can't be read
|
||||
var FallBackConf = `
|
||||
defaultnode:
|
||||
runtime overlay:
|
||||
- generic
|
||||
system overlay:
|
||||
- wwinit
|
||||
kernel:
|
||||
args: quiet crashkernel=no vga=791 net.naming-scheme=v238
|
||||
init: /sbin/init
|
||||
root: initramfs
|
||||
profiles:
|
||||
- default
|
||||
network devices:
|
||||
dummy:
|
||||
device: eth0
|
||||
type: ethernet
|
||||
netmask: 255.255.255.0`
|
||||
|
||||
func init() {
|
||||
if ConfigFile == "" {
|
||||
ConfigFile = path.Join(buildconfig.SYSCONFDIR(), "warewulf/nodes.conf")
|
||||
}
|
||||
if DefaultConfig == "" {
|
||||
DefaultConfig = path.Join(buildconfig.SYSCONFDIR(), "warewulf/defaults.conf")
|
||||
}
|
||||
}
|
||||
|
||||
func New() (NodeYaml, error) {
|
||||
@@ -54,6 +77,30 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
||||
return ret, err
|
||||
}
|
||||
*/
|
||||
var defConf map[string]*NodeConf
|
||||
wwlog.Verbose("Opening defaults failed %s\n", DefaultConfig)
|
||||
defData, err := ioutil.ReadFile(DefaultConfig)
|
||||
if err != nil {
|
||||
wwlog.Verbose("Couldn't read DefaultConfig :%s\n", err)
|
||||
}
|
||||
wwlog.Debug("Unmarshalling default config\n")
|
||||
err = yaml.Unmarshal(defData, &defConf)
|
||||
if err != nil {
|
||||
wwlog.Verbose("Couldn't unmarshall defaults from file :%s\n", err)
|
||||
wwlog.Verbose("Using building defaults")
|
||||
err = yaml.Unmarshal([]byte(FallBackConf), &defConf)
|
||||
if err != nil {
|
||||
wwlog.Warn("Could not get any defaults")
|
||||
}
|
||||
}
|
||||
var defConfNet *NetDevs
|
||||
if _, ok := defConf["defaultnode"]; ok {
|
||||
if _, ok := defConf["defaultnode"].NetDevs["dummy"]; ok {
|
||||
defConfNet = defConf["defaultnode"].NetDevs["dummy"]
|
||||
}
|
||||
defConf["defaultnode"].NetDevs = nil
|
||||
}
|
||||
|
||||
wwlog.Debug("Finding all nodes...")
|
||||
for nodename, node := range config.Nodes {
|
||||
var n NodeInfo
|
||||
@@ -63,13 +110,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
||||
n.Tags = make(map[string]*Entry)
|
||||
n.Kernel = new(KernelEntry)
|
||||
n.Ipmi = new(IpmiEntry)
|
||||
n.SystemOverlay.SetDefault("wwinit")
|
||||
n.RuntimeOverlay.SetDefault("generic")
|
||||
n.Ipxe.SetDefault("default")
|
||||
n.Init.SetDefault("/sbin/init")
|
||||
n.Root.SetDefault("initramfs")
|
||||
n.Kernel.Args.SetDefault("quiet crashkernel=no vga=791")
|
||||
|
||||
n.SetDefFrom(defConf["defaultnode"])
|
||||
fullname := strings.SplitN(nodename, ".", 2)
|
||||
if len(fullname) > 1 {
|
||||
n.ClusterName.SetDefault(fullname[1])
|
||||
@@ -80,14 +121,18 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
||||
} else {
|
||||
n.Profiles.SetSlice(node.Profiles)
|
||||
}
|
||||
// node explciti nodename field in NodeConf
|
||||
// node explicitly nodename field in NodeConf
|
||||
n.Id.Set(nodename)
|
||||
// backward compatibilty
|
||||
// backward compatibility
|
||||
for keyname, key := range node.Keys {
|
||||
node.Tags[keyname] = key
|
||||
delete(node.Keys, keyname)
|
||||
}
|
||||
n.SetFrom(node)
|
||||
// only now the netdevs start to exist so that default values can be set
|
||||
for _, netdev := range n.NetDevs {
|
||||
netdev.SetDefFrom(defConfNet)
|
||||
}
|
||||
// set default/primary network is just one network exist
|
||||
if len(n.NetDevs) == 1 {
|
||||
// only way to get the key
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
/******
|
||||
* YAML data representations
|
||||
******/
|
||||
|
||||
/*
|
||||
Structure of which goes to disk
|
||||
*/
|
||||
type NodeYaml struct {
|
||||
WWInternal int `yaml:"WW_INTERNAL"`
|
||||
NodeProfiles map[string]*NodeConf
|
||||
@@ -16,7 +13,7 @@ type NodeYaml struct {
|
||||
}
|
||||
|
||||
/*
|
||||
NodeConf is the datastructure which is stored on disk.
|
||||
NodeConf is the datastructure describing a node and a profile which in disk format.
|
||||
*/
|
||||
type NodeConf struct {
|
||||
Comment string `yaml:"comment,omitempty" lopt:"comment" comment:"Set arbitrary string comment"`
|
||||
@@ -24,11 +21,11 @@ type NodeConf struct {
|
||||
ContainerName string `yaml:"container name,omitempty" lopt:"container" sopt:"C" comment:"Set container name"`
|
||||
Ipxe string `yaml:"ipxe template,omitempty" lopt:"ipxe" comment:"Set the iPXE template name"`
|
||||
// Deprecated start
|
||||
// Kernel settings here are deprecated and here for backward comptability
|
||||
// Kernel settings here are deprecated and here for backward compatibility
|
||||
KernelVersion string `yaml:"kernel version,omitempty"`
|
||||
KernelOverride string `yaml:"kernel override,omitempty"`
|
||||
KernelArgs string `yaml:"kernel args,omitempty"`
|
||||
// Ipmi settings herer are deprecated and here for backward comptability
|
||||
// Ipmi settings herer are deprecated and here for backward compatibility
|
||||
IpmiUserName string `yaml:"ipmi username,omitempty"`
|
||||
IpmiPassword string `yaml:"ipmi password,omitempty"`
|
||||
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
|
||||
@@ -82,6 +79,7 @@ type NetDevs struct {
|
||||
Prefix string `yaml:"prefix,omitempty"`
|
||||
Netmask string `yaml:"netmask,omitempty" lopt:"netmask" sopt:"M" comment:"Set the networks netmask"`
|
||||
Gateway string `yaml:"gateway,omitempty" lopt:"gateway" sopt:"G" comment:"Set the node's network device gateway"`
|
||||
MTU string `yaml:"mtu,omitempty" lopt:"mtu" comment:"Set the mtu"`
|
||||
Primary string `yaml:"primary,omitempty" lopt:"primary" comment:"Enable/disable network device as primary (yes/no)"`
|
||||
Default string `yaml:"default,omitempty"` /* backward compatibility */
|
||||
Tags map[string]string `yaml:"tags,omitempty" lopt:"nettagadd" comment:"network tags"`
|
||||
@@ -156,6 +154,7 @@ type NetDevEntry struct {
|
||||
Prefix Entry
|
||||
Netmask Entry
|
||||
Gateway Entry
|
||||
MTU Entry
|
||||
Primary Entry
|
||||
Tags map[string]*Entry
|
||||
}
|
||||
@@ -163,6 +162,8 @@ type NetDevEntry struct {
|
||||
// string which is printed if no value is set
|
||||
const NoValue = "--"
|
||||
|
||||
/*
|
||||
Has no real purpose as only New() needs it
|
||||
func init() {
|
||||
// Check that nodes.conf is found
|
||||
if !util.IsFile(ConfigFile) {
|
||||
@@ -171,3 +172,4 @@ func init() {
|
||||
return
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -26,8 +26,7 @@ func FilterByName(set []NodeInfo, searchList []string) []NodeInfo {
|
||||
if len(searchList) > 0 {
|
||||
for _, search := range searchList {
|
||||
for _, entry := range set {
|
||||
b, _ := regexp.MatchString("^"+search+"$", entry.Id.Get())
|
||||
if b {
|
||||
if match, _ := regexp.MatchString("^"+search+"$", entry.Id.Get()); match {
|
||||
unique[entry.Id.Get()] = entry
|
||||
}
|
||||
}
|
||||
@@ -42,6 +41,24 @@ func FilterByName(set []NodeInfo, searchList []string) []NodeInfo {
|
||||
return ret
|
||||
}
|
||||
|
||||
/*
|
||||
Filter a given map of NodeConf against given regular expression.
|
||||
*/
|
||||
func FilterMapByName(inputMap map[string]*NodeConf, searchList []string) (retMap map[string]*NodeConf) {
|
||||
retMap = map[string]*NodeConf{}
|
||||
if len(searchList) > 0 {
|
||||
for _, search := range searchList {
|
||||
for name, nConf := range inputMap {
|
||||
if match, _ := regexp.MatchString("^"+search+"$", name); match {
|
||||
retMap[name] = nConf
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return retMap
|
||||
}
|
||||
|
||||
/**********
|
||||
*
|
||||
* Sets
|
||||
|
||||
@@ -2,8 +2,10 @@ package node
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -186,6 +188,10 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Create cmd line flags from the NodeConf fields
|
||||
*/
|
||||
func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) {
|
||||
nodeInfoType := reflect.TypeOf(nodeConf)
|
||||
nodeInfoVal := reflect.ValueOf(nodeConf)
|
||||
@@ -303,6 +309,20 @@ func (node *NodeInfo) SetAltFrom(n *NodeConf, profileName string) {
|
||||
node.setterFrom(n, profileName, (*Entry).SetAlt, (*Entry).SetAltSlice)
|
||||
}
|
||||
|
||||
/*
|
||||
Populates all fields of NodeInfo with SetDefault from the
|
||||
values of NodeConf.
|
||||
*/
|
||||
func (node *NodeInfo) SetDefFrom(n *NodeConf) {
|
||||
setWrap := func(entr *Entry, val string, nameArg string) {
|
||||
entr.SetDefault(val)
|
||||
}
|
||||
setSliceWrap := func(entr *Entry, val []string, nameArg string) {
|
||||
entr.SetDefaultSlice(val)
|
||||
}
|
||||
node.setterFrom(n, "", setWrap, setSliceWrap)
|
||||
}
|
||||
|
||||
/*
|
||||
Abstract function which populates a NodeInfo from a NodeConf via
|
||||
setter functionns.
|
||||
@@ -438,3 +458,213 @@ func (info *NodeConf) Flatten() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Populates all fields of NetDevEntry with Set from the
|
||||
values of NetDevs.
|
||||
Actually not used, just for completeness.
|
||||
*/
|
||||
func (netDev *NetDevEntry) SetFrom(netYaml *NetDevs) {
|
||||
setWrap := func(entr *Entry, val string, nameArg string) {
|
||||
entr.Set(val)
|
||||
}
|
||||
setSliceWrap := func(entr *Entry, val []string, nameArg string) {
|
||||
entr.SetSlice(val)
|
||||
}
|
||||
netDev.setterFrom(netYaml, "", setWrap, setSliceWrap)
|
||||
}
|
||||
|
||||
/*
|
||||
Populates all fields of NetDevEntry with SetAlt from the
|
||||
values of NetDevs. The string profileName is used to
|
||||
destermine from which source/NodeInfo the entry came
|
||||
from.
|
||||
Actually not used, just for completeness.
|
||||
*/
|
||||
func (netDev *NetDevEntry) SetAltFrom(netYaml *NetDevs, profileName string) {
|
||||
netDev.setterFrom(netYaml, profileName, (*Entry).SetAlt, (*Entry).SetAltSlice)
|
||||
}
|
||||
|
||||
/*
|
||||
Populates all fields of NodeInfo with SetDefault from the
|
||||
values of NodeConf.
|
||||
*/
|
||||
func (netDev *NetDevEntry) SetDefFrom(netYaml *NetDevs) {
|
||||
setWrap := func(entr *Entry, val string, nameArg string) {
|
||||
entr.SetDefault(val)
|
||||
}
|
||||
setSliceWrap := func(entr *Entry, val []string, nameArg string) {
|
||||
entr.SetDefaultSlice(val)
|
||||
}
|
||||
netDev.setterFrom(netYaml, "", setWrap, setSliceWrap)
|
||||
}
|
||||
|
||||
/*
|
||||
Abstract function for setting a NetDevEntry from a NetDevs
|
||||
*/
|
||||
func (netDev *NetDevEntry) setterFrom(netYaml *NetDevs, nameArg string,
|
||||
setter func(*Entry, string, string),
|
||||
setterSlice func(*Entry, []string, string)) {
|
||||
netValues := reflect.ValueOf(netDev)
|
||||
netInfoType := reflect.TypeOf(*netYaml)
|
||||
netInfoVal := reflect.ValueOf(*netYaml)
|
||||
for j := 0; j < netInfoType.NumField(); j++ {
|
||||
netVal := netValues.Elem().FieldByName(netInfoType.Field(j).Name)
|
||||
if netVal.IsValid() {
|
||||
if netInfoVal.Field(j).Type().Kind() == reflect.String {
|
||||
setter(netVal.Addr().Interface().((*Entry)), netInfoVal.Field(j).String(), nameArg)
|
||||
} else if netVal.Type() == reflect.TypeOf(map[string]string{}) {
|
||||
// danger zone following code is not tested
|
||||
for key, val := range (netVal.Interface()).(map[string]string) {
|
||||
//netTagMap := netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))
|
||||
if _, ok := netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key]; !ok {
|
||||
netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = new(Entry)
|
||||
}
|
||||
setter(netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key], val, nameArg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Create a string slice, where every element represents a yaml entry
|
||||
*/
|
||||
func (nodeConf *NodeConf) UnmarshalConf(excludeList []string) (lines []string) {
|
||||
nodeInfoType := reflect.TypeOf(nodeConf)
|
||||
nodeInfoVal := reflect.ValueOf(nodeConf)
|
||||
// now iterate of every field
|
||||
for i := 0; i < nodeInfoVal.Elem().NumField(); i++ {
|
||||
if nodeInfoType.Elem().Field(i).Tag.Get("lopt") != "" {
|
||||
if ymlStr, ok := getYamlString(nodeInfoType.Elem().Field(i), excludeList); ok {
|
||||
lines = append(lines, ymlStr...)
|
||||
}
|
||||
} else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr {
|
||||
nestType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface())
|
||||
if ymlStr, ok := getYamlString(nodeInfoType.Elem().Field(i), excludeList); ok {
|
||||
lines = append(lines, ymlStr...)
|
||||
}
|
||||
for j := 0; j < nestType.Elem().NumField(); j++ {
|
||||
if nestType.Elem().Field(j).Tag.Get("lopt") != "" &&
|
||||
!util.InSlice(excludeList, nestType.Elem().Field(j).Tag.Get("lopt")) {
|
||||
if ymlStr, ok := getYamlString(nestType.Elem().Field(j), excludeList); ok {
|
||||
for _, str := range ymlStr {
|
||||
lines = append(lines, " "+str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string]*NetDevs(nil)) {
|
||||
netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string]*NetDevs)
|
||||
// add a default network so that it can hold values
|
||||
key := "default"
|
||||
if len(netMap) == 0 {
|
||||
netMap[key] = new(NetDevs)
|
||||
} else {
|
||||
for keyIt := range netMap {
|
||||
key = keyIt
|
||||
break
|
||||
}
|
||||
}
|
||||
if ymlStr, ok := getYamlString(nodeInfoType.Elem().Field(i), excludeList); ok {
|
||||
lines = append(lines, ymlStr[0]+":", " "+key+":")
|
||||
netType := reflect.TypeOf(netMap[key])
|
||||
for j := 0; j < netType.Elem().NumField(); j++ {
|
||||
if ymlStr, ok := getYamlString(netType.Elem().Field(j), excludeList); ok {
|
||||
for _, str := range ymlStr {
|
||||
lines = append(lines, " "+str)
|
||||
}
|
||||
}
|
||||
} // lines
|
||||
} // this
|
||||
} //not
|
||||
} //do
|
||||
return lines
|
||||
}
|
||||
|
||||
/*
|
||||
Get the string of the yaml tag
|
||||
*/
|
||||
func getYamlString(myType reflect.StructField, excludeList []string) ([]string, bool) {
|
||||
ymlStr := myType.Tag.Get("yaml")
|
||||
if len(strings.Split(ymlStr, ",")) > 1 {
|
||||
ymlStr = strings.Split(ymlStr, ",")[0]
|
||||
}
|
||||
if util.InSlice(excludeList, ymlStr) {
|
||||
return []string{""}, false
|
||||
} else if myType.Tag.Get("lopt") == "" && myType.Type.Kind() == reflect.String {
|
||||
return []string{""}, false
|
||||
}
|
||||
if myType.Type.Kind() == reflect.String {
|
||||
ymlStr += ": string"
|
||||
return []string{ymlStr}, true
|
||||
} else if myType.Type == reflect.TypeOf([]string{}) {
|
||||
return []string{ymlStr + ":", " - string"}, true
|
||||
} else if myType.Type == reflect.TypeOf(map[string]string{}) {
|
||||
return []string{ymlStr + ":", " key: value"}, true
|
||||
} else if myType.Type.Kind() == reflect.Ptr {
|
||||
return []string{ymlStr + ":"}, true
|
||||
}
|
||||
return []string{ymlStr}, true
|
||||
}
|
||||
|
||||
/*
|
||||
Set the field of the NodeConf with the given lopt name, returns true if the
|
||||
field was found. String slices must be comma separated. Network must have the form
|
||||
net.$NETNAME.lopt or netname.$NETNAME.lopt
|
||||
*/
|
||||
func (nodeConf *NodeConf) SetLopt(lopt string, value string) (found bool) {
|
||||
found = false
|
||||
nodeInfoType := reflect.TypeOf(nodeConf)
|
||||
nodeInfoVal := reflect.ValueOf(nodeConf)
|
||||
// try to find the normal fields, networks come later
|
||||
for i := 0; i < nodeInfoVal.Elem().NumField(); i++ {
|
||||
//fmt.Println(nodeInfoType.Elem().Field(i).Tag.Get("lopt"), lopt)
|
||||
if nodeInfoType.Elem().Field(i).Tag.Get("lopt") == lopt {
|
||||
if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.String {
|
||||
wwlog.Verbose("Found lopt %s mapping to %s, setting to %s\n",
|
||||
lopt, nodeInfoType.Elem().Field(i).Name, value)
|
||||
confVal := nodeInfoVal.Elem().Field(i).Addr().Interface().(*string)
|
||||
*confVal = value
|
||||
found = true
|
||||
} else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf([]string{}) {
|
||||
wwlog.Verbose("Found lopt %s mapping to %s, setting to %s\n",
|
||||
lopt, nodeInfoType.Elem().Field(i).Name, value)
|
||||
confVal := nodeInfoVal.Elem().Field(i).Addr().Interface().(*[]string)
|
||||
*confVal = strings.Split(value, ",")
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// check network
|
||||
loptSlice := strings.Split(lopt, ".")
|
||||
wwlog.Debug("Trying to get network out of %s\n", loptSlice)
|
||||
if !found && len(loptSlice) == 3 && (loptSlice[0] == "net" || loptSlice[0] == "network" || loptSlice[0] == "netname") {
|
||||
if nodeConf.NetDevs == nil {
|
||||
nodeConf.NetDevs = make(map[string]*NetDevs)
|
||||
}
|
||||
if nodeConf.NetDevs[loptSlice[1]] == nil {
|
||||
nodeConf.NetDevs[loptSlice[1]] = new(NetDevs)
|
||||
}
|
||||
netInfoType := reflect.TypeOf(nodeConf.NetDevs[loptSlice[1]])
|
||||
netInfoVal := reflect.ValueOf(nodeConf.NetDevs[loptSlice[1]])
|
||||
for i := 0; i < netInfoVal.Elem().NumField(); i++ {
|
||||
if netInfoType.Elem().Field(i).Tag.Get("lopt") == loptSlice[2] {
|
||||
if netInfoType.Elem().Field(i).Type.Kind() == reflect.String {
|
||||
wwlog.Verbose("Found lopt %s for network %s mapping to %s, setting to %s\n",
|
||||
lopt, loptSlice[1], netInfoType.Elem().Field(i).Name, value)
|
||||
confVal := netInfoVal.Elem().Field(i).Addr().Interface().(*string)
|
||||
*confVal = value
|
||||
found = true
|
||||
} else if netInfoType.Elem().Field(i).Type == reflect.TypeOf([]string{}) {
|
||||
wwlog.Verbose("Found lopt %s for network %s mapping to %s, setting to %s\n",
|
||||
lopt, loptSlice[1], netInfoType.Elem().Field(i).Name, value)
|
||||
confVal := netInfoVal.Elem().Field(i).Addr().Interface().(*[]string)
|
||||
*confVal = strings.Split(value, ",")
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user