Systemd-networkd overlay with IPV6 support

Signed-off-by: Timothy Middelkoop <tmiddelkoop@internet2.edu>
This commit is contained in:
Timothy Middelkoop
2025-11-28 04:46:47 +00:00
parent d9b4317034
commit 4c82de92c7
6 changed files with 235 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- `wwclient.aarch64` overlay always provides an aarch64 wwclient executable.
- `wwclient.x86_64` overlay always provides an x86_64 wwclient executable.
- systemd-networkd overlay with IPv6 support
### Changed

View File

@@ -0,0 +1,20 @@
nodes:
node1:
network devices:
default:
device: wwnet0
ipaddr: 192.168.3.21
netmask: 255.255.255.0
gateway: 192.168.3.1
mtu: 1500
secondary:
device: wwnet1
ipaddr: 192.168.3.22
netmask: 255.255.255.0
gateway: 192.168.3.1
mtu: 9000
tags:
route1: "192.168.1.0/24,192.168.3.254"
ipaddr6: 2001:db8::23
prefixlen6: 64
gateway6: 2001:db8::1

View File

@@ -0,0 +1,22 @@
nodes:
node1:
network devices:
default:
device: wwnet0
hwaddr: e6:92:39:49:7b:03
ipaddr: 192.168.3.21
netmask: 255.255.255.0
gateway: 192.168.3.1
mtu: 1500
secondary:
device: wwnet1
hwaddr: 9a:77:29:73:14:f1
ipaddr: 192.168.3.22
netmask: 255.255.255.0
gateway: 192.168.3.1
mtu: 9000
tags:
route1: "192.168.1.0/24,192.168.3.254"
ipaddr6: 2001:db8::23
prefixlen6: 64
gateway6: 2001:db8::1

View File

@@ -0,0 +1,137 @@
package systemd_networkd
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"github.com/warewulf/warewulf/internal/app/wwctl/overlay/show"
"github.com/warewulf/warewulf/internal/pkg/testenv"
"github.com/warewulf/warewulf/internal/pkg/wwlog"
)
func Test_systemdNetworkOverlay(t *testing.T) {
env := testenv.New(t)
defer env.RemoveAll()
env.ImportFile("var/lib/warewulf/overlays/systemd.networkd/rootfs/etc/systemd/network/default.network.ww", "../rootfs/etc/systemd/network/default.network.ww")
tests := []struct {
name string
nodes_conf string
args []string
log string
}{
{
name: "systemd.networkd with hwaddr",
nodes_conf: "nodes.conf",
args: []string{"--render", "node1", "systemd.networkd", "etc/systemd/network/default.network.ww"},
log: expected_log_with_hwaddr,
},
{
name: "systemd.networkd without hwaddr",
nodes_conf: "nodes-no-hwaddr.conf",
args: []string{"--render", "node1", "systemd.networkd", "etc/systemd/network/default.network.ww"},
log: expected_log_without_hwaddr,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
env.ImportFile("etc/warewulf/nodes.conf", tt.nodes_conf)
cmd := show.GetCommand()
cmd.SetArgs(tt.args)
stdout := bytes.NewBufferString("")
stderr := bytes.NewBufferString("")
logbuf := bytes.NewBufferString("")
cmd.SetOut(stdout)
cmd.SetErr(stderr)
wwlog.SetLogWriter(logbuf)
err := cmd.Execute()
assert.NoError(t, err)
assert.Empty(t, stdout.String())
assert.Empty(t, stderr.String())
assert.Equal(t, tt.log, logbuf.String())
})
}
}
const expected_log_with_hwaddr string = `backupFile: true
writeFile: true
Filename: 10-ww4-networkd-default.network
# This file is autogenerated by warewulf
[Match]
Name=wwnet0
MACAddress=e6:92:39:49:7b:03
[Network]
DHCP=no
Address=192.168.3.21/24
Gateway=192.168.3.1
[Link]
MTUBytes=1500
backupFile: true
writeFile: true
Filename: 10-ww4-networkd-secondary.network
# This file is autogenerated by warewulf
[Match]
Name=wwnet1
MACAddress=9a:77:29:73:14:f1
[Network]
DHCP=no
Address=192.168.3.22/24
Gateway=192.168.3.1
IPv6PrivacyExtensions=false
Address=2001:db8::23/64
Gateway=2001:db8::1
[Link]
MTUBytes=9000
[Route]
Destination=192.168.1.0/24
Gateway=192.168.3.254
[DHCPv6]
UseAddress=no
`
const expected_log_without_hwaddr string = `backupFile: true
writeFile: true
Filename: 10-ww4-networkd-default.network
# This file is autogenerated by warewulf
[Match]
Name=wwnet0
[Network]
DHCP=no
Address=192.168.3.21/24
Gateway=192.168.3.1
[Link]
MTUBytes=1500
backupFile: true
writeFile: true
Filename: 10-ww4-networkd-secondary.network
# This file is autogenerated by warewulf
[Match]
Name=wwnet1
[Network]
DHCP=no
Address=192.168.3.22/24
Gateway=192.168.3.1
IPv6PrivacyExtensions=false
Address=2001:db8::23/64
Gateway=2001:db8::1
[Link]
MTUBytes=9000
[Route]
Destination=192.168.1.0/24
Gateway=192.168.3.254
[DHCPv6]
UseAddress=no
`

View File

@@ -0,0 +1,55 @@
{{- range $devname, $netdev := .ThisNode.NetDevs }}
{{ file (print "10-ww4-networkd-" $devname ".network") }}
# This file is autogenerated by warewulf
[Match]
{{- if $netdev.Device }}
Name={{ $netdev.Device }}
{{- end }}
{{- if $netdev.Hwaddr }}
MACAddress={{ $netdev.Hwaddr }}
{{- end }}
[Network]
{{- if or $netdev.IpCIDR $netdev.IpCIDR6 }}
DHCP=no
{{- end }}
{{- if $netdev.IpCIDR }}
Address={{ $netdev.IpCIDR }}
{{- end }}
{{- if $netdev.Gateway }}
Gateway={{ $netdev.Gateway }}
{{- end }}
{{- if $netdev.IpCIDR6 }}
IPv6PrivacyExtensions=false
Address={{ $netdev.IpCIDR6 }}
{{- end }}
{{- if $netdev.Gateway6 }}
Gateway={{ $netdev.Gateway6 }}
{{- end }}
{{- range $tk, $tv := $netdev.Tags }}
{{- if regexMatch "^DNS[0-9]*$" $tk }}
DNS={{ $tv }}
{{- end }}
{{- end }}
{{- if $netdev.MTU }}
[Link]
MTUBytes={{ $netdev.MTU }}
{{- end }}
{{- range $tk, $tv := $netdev.Tags }}
{{- if eq (substr 0 5 $tk) "route" }}
{{- $route := splitList "," $tv }}
[Route]
Destination={{ index $route 0 }}
Gateway={{ index $route 1 }}
{{- end }}
{{- end }}
{{- if $netdev.Ipaddr6 }}
[DHCPv6]
UseAddress=no
{{ end -}}
{{ end -}}