From efd761f7c380a546de4f5f7435027b5816e02686 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 15 Sep 2022 10:33:27 +0200 Subject: [PATCH 1/6] Read the defaults for anode from defaults.conf --- .gitignore | 1 + Makefile | 7 +++- cmd/print_defaults/print_defaults.go | 17 ++++++++++ internal/pkg/node/constructors.go | 50 +++++++++++++++++++++++----- internal/pkg/node/datastructure.go | 8 ++--- internal/pkg/node/transformers.go | 14 ++++++++ 6 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 cmd/print_defaults/print_defaults.go diff --git a/.gitignore b/.gitignore index 35665e4d..cc7db570 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ /wwapic /wwapid /wwapird +/print_defaults # other created files /man_pages diff --git a/Makefile b/Makefile index 00a48716..add0a600 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ export GOPROXY # built tags needed for wwbuild binary WW_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree -all: config vendor wwctl wwclient bash_completion.d man_pages config_defaults wwapid wwapic wwapird +all: config vendor wwctl wwclient bash_completion.d man_pages config_defaults print_defaults wwapid wwapic wwapird build: lint test-it vet all @@ -174,6 +174,7 @@ files: all test -f $(DESTDIR)$(SYSCONFDIR)/warewulf/wwapic.conf || install -m 644 etc/wwapic.conf $(DESTDIR)$(SYSCONFDIR)/warewulf/ test -f $(DESTDIR)$(SYSCONFDIR)/warewulf/wwapid.conf || install -m 644 etc/wwapid.conf $(DESTDIR)$(SYSCONFDIR)/warewulf/ test -f $(DESTDIR)$(SYSCONFDIR)/warewulf/wwapird.conf || install -m 644 etc/wwapird.conf $(DESTDIR)$(SYSCONFDIR)/warewulf/ + test -f $(DESTDIR)$(SYSCONFDIR)/warewulf/defaults.conf || ./print_defaults > $(DESTDIR)$(SYSCONFDIR)/warewulf/defaults.conf cp -r etc/examples $(DESTDIR)$(WWCONFIGDIR)/ cp -r etc/ipxe $(DESTDIR)$(WWCONFIGDIR)/ cp -r overlays/* $(DESTDIR)$(WWOVERLAYDIR)/ @@ -237,6 +238,9 @@ config_defaults: vendor cmd/config_defaults/config_defaults.go -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../config_defaults +print_defaults: vendor cmd/print_defaults/print_defaults.go + cd cmd/print_defaults && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'" -o ../../print_defaults + update_configuration: vendor cmd/update_configuration/update_configuration.go cd cmd/update_configuration && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ @@ -297,6 +301,7 @@ clean: rm -rf $(TOOLS_DIR) rm -f config_defaults rm -f update_configuration + rm -f print_defaults install: files install_wwclient diff --git a/cmd/print_defaults/print_defaults.go b/cmd/print_defaults/print_defaults.go new file mode 100644 index 00000000..397294dd --- /dev/null +++ b/cmd/print_defaults/print_defaults.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" + + "github.com/hpcng/warewulf/internal/pkg/node" +) + +/* +Print the build in defaults for the nodes. +Called via Makefile so that there is single upstream +source of the defaults which is FallBackConf +*/ + +func main() { + fmt.Println(node.FallBackConf) +} diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 6237df47..1ea70def 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -14,11 +14,28 @@ import ( ) var ConfigFile string +var DefaultConfig string + +// used as fallback if DefaultConfig can't be read +var FallBackConf = ` +runtime overlay: +- generic +system overlay: +- wwinit +kernel: + args: quiet crashkernel=no vga=791 +init: /sbin/init +root: initramfs +profiles: +- default` 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 +71,27 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { return ret, err } */ + var defConf NodeConf + readBuildin := false + 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 { + readBuildin = true + wwlog.Verbose("Couldn't unmarshall defaults from file :%s\n", err) + } + if readBuildin { + wwlog.Verbose("Using building defaults") + err = yaml.Unmarshal([]byte(FallBackConf), &defConf) + if err != nil { + wwlog.Warn("Could not get any defaults") + } + } + wwlog.Debug("Finding all nodes...\n") for nodename, node := range config.Nodes { var n NodeInfo @@ -63,13 +101,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) fullname := strings.SplitN(nodename, ".", 2) if len(fullname) > 1 { n.ClusterName.SetDefault(fullname[1]) @@ -80,9 +112,9 @@ 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) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index fa9fd33d..f16eb163 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -1,10 +1,5 @@ package node -import ( - "github.com/hpcng/warewulf/internal/pkg/util" - "github.com/hpcng/warewulf/internal/pkg/wwlog" -) - /****** * YAML data representations ******/ @@ -163,6 +158,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 +168,4 @@ func init() { return } } +*/ diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index a50ca263..86177650 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -303,6 +303,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. From 91e032d7a204053d2750fc62f0b8f22212fedd58 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 30 Sep 2022 14:55:19 +0200 Subject: [PATCH 2/6] added code for setting default values for NetDev --- internal/pkg/node/constructors.go | 45 ++++++++++++-------- internal/pkg/node/transformers.go | 68 +++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 16 deletions(-) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 1ea70def..8e1e125c 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -18,16 +18,22 @@ var DefaultConfig string // used as fallback if DefaultConfig can't be read var FallBackConf = ` -runtime overlay: -- generic -system overlay: -- wwinit -kernel: - args: quiet crashkernel=no vga=791 -init: /sbin/init -root: initramfs -profiles: -- default` +defaultnode: + runtime overlay: + - generic + system overlay: + - wwinit + kernel: + args: quiet crashkernel=no vga=791 + init: /sbin/init + root: initramfs + profiles: + - default + network devices: + dummy: + device: eth0 + type: ethernet + netmask: 255.255.255.0` func init() { if ConfigFile == "" { @@ -71,8 +77,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { return ret, err } */ - var defConf NodeConf - readBuildin := false + var defConf map[string]*NodeConf wwlog.Verbose("Opening defaults failed %s\n", DefaultConfig) defData, err := ioutil.ReadFile(DefaultConfig) if err != nil { @@ -81,16 +86,20 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { wwlog.Debug("Unmarshalling default config\n") err = yaml.Unmarshal(defData, &defConf) if err != nil { - readBuildin = true wwlog.Verbose("Couldn't unmarshall defaults from file :%s\n", err) - } - if readBuildin { 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...\n") for nodename, node := range config.Nodes { @@ -101,7 +110,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Tags = make(map[string]*Entry) n.Kernel = new(KernelEntry) n.Ipmi = new(IpmiEntry) - n.SetDefFrom(&defConf) + n.SetDefFrom(defConf["defaultnode"]) fullname := strings.SplitN(nodename, ".", 2) if len(fullname) > 1 { n.ClusterName.SetDefault(fullname[1]) @@ -120,6 +129,10 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { 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 diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index 86177650..8ba52b68 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -452,3 +452,71 @@ 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) + } + } + } + } +} From d57128dbd76527c119f615575bd3fae4e9423532 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 30 Sep 2022 16:12:11 +0200 Subject: [PATCH 3/6] added overlay for NetworkManager --- .../system-connections/ww4-managed.ww | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww diff --git a/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww b/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww new file mode 100644 index 00000000..b4d64fc1 --- /dev/null +++ b/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww @@ -0,0 +1,43 @@ +{{- $host := .BuildHost }} +{{- $time := .BuildTime }} +{{- $source := .BuildSource }} +{{- range $devname, $netdev := .NetDevs }} +{{- $filename := print "warewulf-" $devname ".conf" }} +{{- file $filename }} +# This file is autogenerated by warewulf +# Host: {{ $host }} +# Time: {{ $time }} +# Source: {{ $source }} +[connection] +id={{ $devname }} +interface-name={{ $netdev.Device }} +{{ if $netdev.Type -}} +type={{ $netdev.Type }} +{{ end -}} +autoconnect=true + +{{ if $netdev.Hwaddr -}} +{{ if eq $netdev.Type "ethernet" -}} +[ethernet] +mac-address={{ $netdev.Hwaddr }} +{{ end -}} +{{ end -}} + +{{ if $netdev.IpCIDR -}} +[ipv4] +address={{ $netdev.IpCIDR }} +{{ if $netdev.Gateway -}} +gateway={{ $netdev.Gateway }} +{{ end -}} +method=manual +{{ end -}} + +{{/* always autoconfigure ipv6 */}} +[ipv6] +addr-gen-mode=stable-privacy +method=ignore +never-default=true +{{ if $netdev.Ipaddr6 -}} +ipaddr="{{ $netdev.Ipaddr6 }}" +{{ end -}} +{{ end -}} From b1a02c7f631ce487ab886264c6e69b4e56d19f12 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 30 Sep 2022 16:12:11 +0200 Subject: [PATCH 4/6] added overlay for NetworkManager --- .../system-connections/ww4-managed.ww | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww diff --git a/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww b/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww new file mode 100644 index 00000000..b4d64fc1 --- /dev/null +++ b/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww @@ -0,0 +1,43 @@ +{{- $host := .BuildHost }} +{{- $time := .BuildTime }} +{{- $source := .BuildSource }} +{{- range $devname, $netdev := .NetDevs }} +{{- $filename := print "warewulf-" $devname ".conf" }} +{{- file $filename }} +# This file is autogenerated by warewulf +# Host: {{ $host }} +# Time: {{ $time }} +# Source: {{ $source }} +[connection] +id={{ $devname }} +interface-name={{ $netdev.Device }} +{{ if $netdev.Type -}} +type={{ $netdev.Type }} +{{ end -}} +autoconnect=true + +{{ if $netdev.Hwaddr -}} +{{ if eq $netdev.Type "ethernet" -}} +[ethernet] +mac-address={{ $netdev.Hwaddr }} +{{ end -}} +{{ end -}} + +{{ if $netdev.IpCIDR -}} +[ipv4] +address={{ $netdev.IpCIDR }} +{{ if $netdev.Gateway -}} +gateway={{ $netdev.Gateway }} +{{ end -}} +method=manual +{{ end -}} + +{{/* always autoconfigure ipv6 */}} +[ipv6] +addr-gen-mode=stable-privacy +method=ignore +never-default=true +{{ if $netdev.Ipaddr6 -}} +ipaddr="{{ $netdev.Ipaddr6 }}" +{{ end -}} +{{ end -}} From 7b958984c8ee67aa3438b20ebe2b96a817730974 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 6 Oct 2022 17:37:38 +0200 Subject: [PATCH 5/6] constant net naming scheme and NetworkManager rule Apperently the rules in /etc/systemd/network are not honored by NetworkManager which loads earlier than systemd-networkd, so adding a rule for NetworkManager --- internal/pkg/node/constructors.go | 2 +- overlays/wwinit/etc/udev/rules.d/70-ww4-netname.rules | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 overlays/wwinit/etc/udev/rules.d/70-ww4-netname.rules diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 8e1e125c..7f6fe700 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -24,7 +24,7 @@ defaultnode: system overlay: - wwinit kernel: - args: quiet crashkernel=no vga=791 + args: quiet crashkernel=no vga=791 net.naming-scheme=v238 init: /sbin/init root: initramfs profiles: diff --git a/overlays/wwinit/etc/udev/rules.d/70-ww4-netname.rules b/overlays/wwinit/etc/udev/rules.d/70-ww4-netname.rules new file mode 100644 index 00000000..b15fac55 --- /dev/null +++ b/overlays/wwinit/etc/udev/rules.d/70-ww4-netname.rules @@ -0,0 +1,9 @@ +# This file is autogenerated by warewulf +# Host: {{.BuildHost}} +# Time: {{.BuildTime}} +# Source: {{.BuildSource}} +{{range $devname, $netdev := .NetDevs}} +{{- if $netdev.Hwaddr }} +SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="{{ $netdev.Hwaddr }}", NAME="{{ $netdev.Device }}" +{{ end -}} +{{ end -}} \ No newline at end of file From 552e405560e941e7724bff0702dbf6b4a7bd6e8b Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 7 Oct 2022 09:28:17 +0200 Subject: [PATCH 6/6] add NetworkManager infiniband stuff --- .../etc/NetworkManager/system-connections/ww4-managed.ww | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww b/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww index b4d64fc1..b58d1733 100644 --- a/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww +++ b/overlays/wwinit/etc/NetworkManager/system-connections/ww4-managed.ww @@ -23,6 +23,11 @@ mac-address={{ $netdev.Hwaddr }} {{ end -}} {{ end -}} +{{ if eq $netdev.Type "infiniband" -}} +[infiniband] +transport-mode=datagram +{{ end -}} + {{ if $netdev.IpCIDR -}} [ipv4] address={{ $netdev.IpCIDR }}