Files
warewulf/overlays/host/internal/host_test.go
Timothy Middelkoop e4a721d87e Remove debian.interfaces from nodes.conf
Signed-off-by: Timothy Middelkoop <tmiddelkoop@internet2.edu>
2024-11-12 14:46:12 +01:00

361 lines
11 KiB
Go

package host
import (
"bytes"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/warewulf/warewulf/internal/app/wwctl/overlay/show"
"github.com/warewulf/warewulf/internal/pkg/config"
"github.com/warewulf/warewulf/internal/pkg/testenv"
"github.com/warewulf/warewulf/internal/pkg/wwlog"
)
func Test_hostOverlay(t *testing.T) {
hostname, _ := os.Hostname()
env := testenv.New(t)
defer env.RemoveAll(t)
env.ImportFile(t, "etc/warewulf/nodes.conf", "nodes.conf")
env.ImportFile(t, "var/lib/warewulf/overlays/host/rootfs/etc/dhcp/dhcpd.conf.ww", "../rootfs/etc/dhcp/dhcpd.conf.ww")
env.ImportFile(t, "var/lib/warewulf/overlays/host/rootfs/etc/dnsmasq.d/ww4-hosts.conf.ww", "../rootfs/etc/dnsmasq.d/ww4-hosts.conf.ww")
env.ImportFile(t, "var/lib/warewulf/overlays/host/rootfs/etc/exports.ww", "../rootfs/etc/exports.ww")
env.ImportFile(t, "var/lib/warewulf/overlays/host/rootfs/etc/hosts.ww", "../rootfs/etc/hosts.ww")
env.ImportFile(t, "var/lib/warewulf/overlays/host/rootfs/etc/profile.d/ssh_setup.csh.ww", "../rootfs/etc/profile.d/ssh_setup.csh.ww")
env.ImportFile(t, "var/lib/warewulf/overlays/host/rootfs/etc/profile.d/ssh_setup.sh.ww", "../rootfs/etc/profile.d/ssh_setup.sh.ww")
tests := []struct {
name string
conf string
args []string
log string
header string
}{
{
name: "host:dhcp",
conf: "warewulf.conf",
args: []string{"--render", "host", "host", "etc/dhcp/dhcpd.conf.ww"},
log: host_dhcp,
header: "",
},
{
name: "host:dhcp(static)",
conf: "warewulf.conf-static",
args: []string{"--render", "host", "host", "etc/dhcp/dhcpd.conf.ww"},
log: host_dhcp_static,
header: "",
},
{
name: "host:dnsmasq",
conf: "warewulf.conf",
args: []string{"--render", "host", "host", "etc/dnsmasq.d/ww4-hosts.conf.ww"},
log: host_dnsmasq,
header: "",
},
{
name: "host:/etc/exports",
conf: "",
args: []string{"--render", "host", "host", "etc/exports.ww"},
log: host_exports,
header: "",
},
{
name: "host:/etc/hosts",
args: []string{"--render", "host", "host", "etc/hosts.ww"},
log: host_hosts,
header: "# Do not edit after this line",
},
{
name: "host:ssh_setup.csh",
conf: "",
args: []string{"--render", "host", "host", "etc/profile.d/ssh_setup.csh.ww"},
log: host_ssh_setup_csh,
header: "",
},
{
name: "host:ssh_setup.sh",
conf: "",
args: []string{"--render", "host", "host", "etc/profile.d/ssh_setup.sh.ww"},
log: host_ssh_setup_sh,
header: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.conf != "" {
env.ImportFile(t, "etc/warewulf/warewulf.conf", tt.conf)
assert.NoError(t, config.Get().Read(env.GetPath("etc/warewulf/warewulf.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())
var log string
if tt.header != "" {
log = skipHeader(t, logbuf.String(), tt.header)
} else {
log = logbuf.String()
}
assert.Equal(t, strings.Replace(tt.log, "%HOSTNAME%", hostname, -1), log)
})
}
}
func skipHeader(t *testing.T, log string, header string) (newlog string) {
newlog = ""
found := false
for _, line := range strings.SplitAfter(log, "\n") {
if strings.Contains(line, header) {
found = true
}
if found || strings.HasPrefix(line, "backupFile:") || strings.HasPrefix(line, "writeFile:") || strings.HasPrefix(line, "Filename:") {
newlog = newlog + line
}
}
return
}
const host_dhcp string = `backupFile: true
writeFile: true
Filename: etc/dhcp/dhcpd.conf
# This file is autogenerated by warewulf
allow booting;
allow bootp;
ddns-update-style interim;
authoritative;
option space ipxe;
# Tell iPXE to not wait for ProxyDHCP requests to speed up boot.
option ipxe.no-pxedhcp code 176 = unsigned integer 8;
option ipxe.no-pxedhcp 1;
option space PXE;
option PXE.mtftp-ip code 1 = ip-address;
option PXE.mtftp-cport code 2 = unsigned integer 16;
option PXE.mtftp-sport code 3 = unsigned integer 16;
option PXE.mtftp-tmout code 4 = unsigned integer 8;
option PXE.mtftp-delay code 5 = unsigned integer 8;
option architecture-type code 93 = unsigned integer 16;
if exists user-class and option user-class = "iPXE" {
filename "http://192.168.0.1:9873/ipxe/${mac:hexhyp}?assetkey=${asset}&uuid=${uuid}";
} else {
if option architecture-type = 00:00 {
filename "/warewulf/undionly.kpxe";
}
if option architecture-type = 00:07 {
filename "/warewulf/ipxe-snponly-x86_64.efi";
}
if option architecture-type = 00:09 {
filename "/warewulf/ipxe-snponly-x86_64.efi";
}
if option architecture-type = 00:0B {
filename "/warewulf/snponly.efi";
}
}
subnet 192.168.0.0 netmask 255.255.255.0 {
max-lease-time 120;
range 192.168.0.100 192.168.0.199;
next-server 192.168.0.1;
}
`
const host_dhcp_static string = `backupFile: true
writeFile: true
Filename: etc/dhcp/dhcpd.conf
# This file is autogenerated by warewulf
allow booting;
allow bootp;
ddns-update-style interim;
authoritative;
option space ipxe;
# Tell iPXE to not wait for ProxyDHCP requests to speed up boot.
option ipxe.no-pxedhcp code 176 = unsigned integer 8;
option ipxe.no-pxedhcp 1;
option space PXE;
option PXE.mtftp-ip code 1 = ip-address;
option PXE.mtftp-cport code 2 = unsigned integer 16;
option PXE.mtftp-sport code 3 = unsigned integer 16;
option PXE.mtftp-tmout code 4 = unsigned integer 8;
option PXE.mtftp-delay code 5 = unsigned integer 8;
option architecture-type code 93 = unsigned integer 16;
if exists user-class and option user-class = "iPXE" {
filename "http://192.168.0.1:9873/ipxe/${mac:hexhyp}?assetkey=${asset}&uuid=${uuid}";
} else {
if option architecture-type = 00:00 {
filename "/warewulf/undionly.kpxe";
}
if option architecture-type = 00:07 {
filename "/warewulf/ipxe-snponly-x86_64.efi";
}
if option architecture-type = 00:09 {
filename "/warewulf/ipxe-snponly-x86_64.efi";
}
if option architecture-type = 00:0B {
filename "/warewulf/snponly.efi";
}
}
subnet 192.168.0.0 netmask 255.255.255.0 {
max-lease-time 120;
range 192.168.0.100 192.168.0.199;
next-server 192.168.0.1;
}
host node1-default
{
hardware ethernet e6:92:39:49:7b:03;
fixed-address 192.168.3.21;
option host-name "node1";
}
host node1-secondary
{
hardware ethernet 9a:77:29:73:14:f1;
fixed-address 192.168.3.22;
}
host node2-default
{
hardware ethernet e6:92:39:49:7b:04;
fixed-address 192.168.3.23;
option host-name "node2";
}
`
const host_dnsmasq string = `backupFile: false
writeFile: true
Filename: etc/dnsmasq.d/ww4-hosts.conf
# This file was autgenerated by warewulf
# select the x86 hosts which will get the iXPE binary
dhcp-match=set:bios,option:client-arch,0 #legacy boot
dhcp-match=set:x86PC,option:client-arch, 7 #EFI x86-64
dhcp-match=set:x86PC,option:client-arch, 6 #EFI x86-64
dhcp-match=set:x86PC,option:client-arch, 9 #EFI x86-64
dhcp-match=set:aarch64,option:client-arch, 11 #EFI aarch64
dhcp-match=set:iPXE,77,"iPXE"
dhcp-userclass=set:iPXE,iPXE
dhcp-vendorclass=set:efi-http,HTTPClient:Arch:00016
dhcp-option-force=tag:efi-http,60,HTTPClient
# for http boot always use shim/grub
dhcp-boot=tag:efi-http,"http://192.168.0.1:9873/efiboot/shim.efi"
dhcp-boot=tag:x86PC,"/warewulf/ipxe-snponly-x86_64.efi"
dhcp-boot=tag:aarch64,"/warewulf/arm64-efi/snponly.efi"
# iPXE binary will get the following configuration file
dhcp-boot=tag:iPXE,"http://192.168.0.1:9873/ipxe/${mac:hexhyp}?assetkey=${asset}&uuid=${uuid}"
dhcp-no-override
# define the the range
dhcp-range=192.168.0.100,192.168.0.199,255.255.255.0,6h
dhcp-host=e6:92:39:49:7b:03,set:warewulf,node1,192.168.3.21,infinite
dhcp-host=9a:77:29:73:14:f1,set:warewulf,node1,192.168.3.22,infinite
dhcp-host=e6:92:39:49:7b:04,set:warewulf,node2,192.168.3.23,infinite
`
const host_exports string = `backupFile: true
writeFile: true
Filename: etc/exports
# This file is autogenerated by warewulf
/home 192.168.0.0/255.255.255.0(rw,sync)
/opt 192.168.0.0/255.255.255.0(ro,sync,no_root_squash)
`
const host_hosts string = `backupFile: true
writeFile: true
Filename: etc/hosts
# Do not edit after this line
# This block is autogenerated by warewulf
# Warewulf Server
192.168.0.1 %HOSTNAME% warewulf
# Entry for node1
192.168.3.21 node1 node1-default node1-wwnet0
192.168.3.22 node1-secondary node1-wwnet1
# Entry for node2
192.168.3.23 node2 node2-default node2-wwnet0
`
const host_ssh_setup_csh = `backupFile: true
writeFile: true
Filename: etc/profile.d/ssh_setup.csh
#!/bin/csh
## Automatically configure SSH keys for a user on C SHell login
## Copy this file to /etc/profile.d along with ssh_setup.sh
` + "set _UID=`id -u`" + `
if ( ( $_UID > 500 || $_UID == 0 ) && ( ! -f "$HOME/.ssh/config" && ! -f "$HOME/.ssh/cluster" ) ) then
echo "Configuring SSH for cluster access"
install -d -m 700 $HOME/.ssh
ssh-keygen -t rsa -f $HOME/.ssh/cluster -N '' -C "Warewulf Cluster key" >& /dev/null
cat $HOME/.ssh/cluster.pub >>! $HOME/.ssh/authorized_keys
chmod 0600 $HOME/.ssh/authorized_keys
touch $HOME/.ssh/config
echo -n "# Added by Warewulf " >>! $HOME/.ssh/config
(date +%Y-%m-%d >> $HOME/.ssh/config) >& /dev/null
echo "Host *" >> $HOME/.ssh/config
echo " IdentityFile ~/.ssh/cluster" >> $HOME/.ssh/config
echo " StrictHostKeyChecking=no" >> $HOME/.ssh/config
chmod 0600 $HOME/.ssh/config
endif
`
const host_ssh_setup_sh = `backupFile: true
writeFile: true
Filename: etc/profile.d/ssh_setup.sh
#!/bin/sh
##
## Copyright (c) 2001-2003 Gregory M. Kurtzer
##
## Copyright (c) 2003-2012, The Regents of the University of California,
## through Lawrence Berkeley National Laboratory (subject to receipt of any
## required approvals from the U.S. Dept. of Energy). All rights reserved.
##
## Copied from https://github.com/warewulf/warewulf3/blob/master/cluster/bin/cluster-env
## Automatically configure SSH keys for a user on login
## Copy this file to /etc/profile.d
` + "_UID=`id -u`" + `
if [ $_UID -ge 500 -o $_UID -eq 0 ] && [ ! -f "$HOME/.ssh/config" -a ! -f "$HOME/.ssh/cluster" ]; then
echo "Configuring SSH for cluster access"
install -d -m 700 $HOME/.ssh
ssh-keygen -t rsa -f $HOME/.ssh/cluster -N '' -C "Warewulf Cluster key" > /dev/null 2>&1
cat $HOME/.ssh/cluster.pub >> $HOME/.ssh/authorized_keys
chmod 0600 $HOME/.ssh/authorized_keys
echo "# Added by Warewulf ` + "`date +%Y-%m-%d 2>/dev/null`" + `" >> $HOME/.ssh/config
echo "Host *" >> $HOME/.ssh/config
echo " IdentityFile ~/.ssh/cluster" >> $HOME/.ssh/config
echo " StrictHostKeyChecking=no" >> $HOME/.ssh/config
chmod 0600 $HOME/.ssh/config
fi
`