SHA256
1
0
forked from pool/warewulf4

Accepting request 1139432 from home:mslacken:pr

- added documentation for replacing dhcpd and tftp with dnsmasq
  as README.dnsmasq (jira#HPC-65)
- added following patches:
  * clean-warewulf-conf.patch
  * dnsmasq-template-move.patch

OBS-URL: https://build.opensuse.org/request/show/1139432
OBS-URL: https://build.opensuse.org/package/show/network:cluster/warewulf4?expand=0&rev=50
This commit is contained in:
Christian Goll 2024-01-17 13:10:53 +00:00 committed by Git OBS Bridge
parent 9480ecd563
commit b9cf0a703d
7 changed files with 573 additions and 374 deletions

52
README.dnsmasq Normal file
View File

@ -0,0 +1,52 @@
Replace dhcpd and tftp with dnsmasq
===================================
The isc `dhcpd` server and `tftp` service can be replaced by `dnsmasq` as
singe service, which has also the benefit that dns entries for the
wwarewulf cluster will then also be provided.
Installation
-----------
Before the installation, make sure that `dhcpd` and `tftp` are disabled.
You can do that with the commands:
```
systemctl disable dhcpd
systemctl stop dhcpd
systemctl disable tftp
systemctl stop tftp
```
Now you can install `dnsmasq` with command
```
zypper install dnsmasq
```
After the installation you have to instruct `warewulf` to use `dnsmasq` as
`dhcpd` and `tftp` service, `dnsmasq` has to be specified in the configuration
file `/etc/warewulf/warewulf.conf`. There you have to change the two following
values:
```
tftp:
systemd name: dnsmasq
dhcp:
systemd name: dnsmasq
```
The configuration of `dnsmasq` doesn't need to be changed, as the default configuration
includes all files with following pattern `/etc/dnsmasq.d/*conf` into its configuration.
This configuration is created by the template `overlays/host/etc/dnsmasq.d/ww4-hosts.conf.ww`.
In order to build this template run
```
wwctl overlay build -H
```
After that the `dnsmasq` service has to be enabled with either
```
systemctl enable --now dnsmasq
```
or by (re)configuring warewulf with
```
wwctl configure dhcp
wwctl configure tftp
```

238
clean-warewulf-conf.patch Normal file
View File

@ -0,0 +1,238 @@
diff --git a/Makefile b/Makefile
index e85ac05b..466faf19 100644
--- a/Makefile
+++ b/Makefile
@@ -106,7 +106,8 @@ install: build docs
install -d -m 0755 $(DESTDIR)$(SYSTEMDDIR)
install -d -m 0755 $(DESTDIR)$(IPXESOURCE)
install -d -m 0755 $(DESTDIR)$(DATADIR)/warewulf
- test -f $(DESTDIR)$(WWCONFIGDIR)/warewulf.conf || install -m 0644 etc/warewulf.conf $(DESTDIR)$(WWCONFIGDIR)
+ # wwctl genconfig to get the compiled in paths to warewulf.conf
+ test -f $(DESTDIR)$(WWCONFIGDIR)/warewulf.conf || ./wwctl --warewulfconf etc/warewulf.conf genconfig warewulfconf print> $(DESTDIR)$(WWCONFIGDIR)/warewulf.conf
test -f $(DESTDIR)$(WWCONFIGDIR)/nodes.conf || install -m 0644 etc/nodes.conf $(DESTDIR)$(WWCONFIGDIR)
test -f $(DESTDIR)$(WWCONFIGDIR)/wwapic.conf || install -m 0644 etc/wwapic.conf $(DESTDIR)$(WWCONFIGDIR)
test -f $(DESTDIR)$(WWCONFIGDIR)/wwapid.conf || install -m 0644 etc/wwapid.conf $(DESTDIR)$(WWCONFIGDIR)
diff --git a/internal/pkg/config/buildconfig.go.in b/internal/pkg/config/buildconfig.go.in
index 125f192f..6f761cc1 100644
--- a/internal/pkg/config/buildconfig.go.in
+++ b/internal/pkg/config/buildconfig.go.in
@@ -5,17 +5,44 @@ var ConfigFile = "@SYSCONFDIR@/warewulf/warewulf.conf"
type BuildConfig struct {
Bindir string `default:"@BINDIR@"`
Sysconfdir string `default:"@SYSCONFDIR@"`
- Datadir string `default:"@DATADIR@"`
Localstatedir string `default:"@LOCALSTATEDIR@"`
Ipxesource string `default:"@IPXESOURCE@"`
Srvdir string `default:"@SRVDIR@"`
- Tftpdir string `default:"@TFTPDIR@"`
Firewallddir string `default:"@FIREWALLDDIR@"`
Systemddir string `default:"@SYSTEMDDIR@"`
WWOverlaydir string `default:"@WWOVERLAYDIR@"`
WWChrootdir string `default:"@WWCHROOTDIR@"`
WWProvisiondir string `default:"@WWPROVISIONDIR@"`
- Version string `default:"@VERSION@"`
- Release string `default:"@RELEASE@"`
WWClientdir string `default:"@WWCLIENTDIR@"`
+ version string `default:"@VERSION@"`
+ release string `default:"@RELEASE@"`
+}
+
+func (conf BuildConfig) Version() string {
+ return conf.version
+}
+
+func (conf BuildConfig) Release() string {
+ return conf.release
+}
+
+type TFTPConf struct {
+ Enabled bool `yaml:"enabled" default:"true"`
+ TftpRoot string `yaml:"tftproot" default:"@TFTPDIR@"`
+ SystemdName string `yaml:"systemd name" default:"tftp"`
+
+ IpxeBinaries map[string]string `yaml:"ipxe" default:"{\"00:09\": \"ipxe-snponly-x86_64.efi\",\"00:00\": \"undionly.kpxe\",\"00:0B\": \"arm64-efi/snponly.efi\",\"00:07\": \"ipxe-snponly-x86_64.efi\"}"`
+}
+
+// WarewulfConf adds additional Warewulf-specific configuration to
+// BaseConf.
+type WarewulfConf struct {
+ Port int `yaml:"port" default:"9983"`
+ Secure bool `yaml:"secure" default:"true"`
+ UpdateInterval int `yaml:"update interval" default:"60"`
+ AutobuildOverlays bool `yaml:"autobuild overlays" default:"true"`
+ EnableHostOverlay bool `yaml:"host overlay" default:"true"`
+ Syslog bool `yaml:"syslog" default:"false"`
+ DataStore string `yaml:"datastore" default:"@DATADIR@"`
+ GrubBoot bool `yaml:"grubboot" default:"false"`
}
diff --git a/internal/pkg/config/mounts.go b/internal/pkg/config/mounts.go
index daf38c0a..2eb5060b 100644
--- a/internal/pkg/config/mounts.go
+++ b/internal/pkg/config/mounts.go
@@ -3,8 +3,8 @@ package config
// A MountEntry represents a bind mount that is applied to a container
// during exec and shell.
type MountEntry struct {
- Source string `yaml:"source" default:"/etc/resolv.conf"`
- Dest string `yaml:"dest,omitempty" default:"/etc/resolv.conf"`
- ReadOnly bool `yaml:"readonly,omitempty" default:"false"`
+ Source string `yaml:"source"`
+ Dest string `yaml:"dest,omitempty"`
+ ReadOnly bool `yaml:"readonly,omitempty"`
Options string `yaml:"options,omitempty"` // ignored at the moment
}
diff --git a/internal/pkg/config/root_test.go b/internal/pkg/config/root_test.go
index f8c9a697..d57d1557 100644
--- a/internal/pkg/config/root_test.go
+++ b/internal/pkg/config/root_test.go
@@ -43,10 +43,9 @@ func TestDefaultRootConf(t *testing.T) {
assert.NotEmpty(t, conf.Paths.Bindir)
assert.NotEmpty(t, conf.Paths.Sysconfdir)
- assert.NotEmpty(t, conf.Paths.Datadir)
+ assert.NotEmpty(t, conf.Warewulf.DataStore)
assert.NotEmpty(t, conf.Paths.Localstatedir)
assert.NotEmpty(t, conf.Paths.Srvdir)
- assert.NotEmpty(t, conf.Paths.Tftpdir)
assert.NotEmpty(t, conf.Paths.Firewallddir)
assert.NotEmpty(t, conf.Paths.Systemddir)
assert.NotEmpty(t, conf.Paths.WWOverlaydir)
diff --git a/internal/pkg/config/tftp.go b/internal/pkg/config/tftp.go
deleted file mode 100644
index cd5260df..00000000
--- a/internal/pkg/config/tftp.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package config
-
-// TFTPConf represents that configuration for the TFTP service that
-// Warewulf will configure.
-type TFTPConf struct {
- Enabled bool `yaml:"enabled" default:"true"`
- TftpRoot string `yaml:"tftproot" default:"/var/lib/tftpboot"`
- SystemdName string `yaml:"systemd name" default:"tftp"`
-
- IpxeBinaries map[string]string `yaml:"ipxe" default:"{\"00:09\": \"ipxe-snponly-x86_64.efi\",\"00:00\": \"undionly.kpxe\",\"00:0B\": \"arm64-efi/snponly.efi\",\"00:07\": \"ipxe-snponly-x86_64.efi\"}"`
-}
diff --git a/internal/pkg/config/warewulf.go b/internal/pkg/config/warewulf.go
deleted file mode 100644
index 9a0dc3f4..00000000
--- a/internal/pkg/config/warewulf.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package config
-
-// WarewulfConf adds additional Warewulf-specific configuration to
-// BaseConf.
-type WarewulfConf struct {
- Port int `yaml:"port" default:"9983"`
- Secure bool `yaml:"secure" default:"true"`
- UpdateInterval int `yaml:"update interval" default:"60"`
- AutobuildOverlays bool `yaml:"autobuild overlays" default:"true"`
- EnableHostOverlay bool `yaml:"host overlay" default:"true"`
- Syslog bool `yaml:"syslog" default:"false"`
- DataStore string `yaml:"datastore" default:"/var/lib/warewulf"`
- GrubBoot bool `yaml:"grubboot" default:"false"`
-}
diff --git a/internal/pkg/configure/tftp.go b/internal/pkg/configure/tftp.go
index 058ca059..ab71429d 100644
--- a/internal/pkg/configure/tftp.go
+++ b/internal/pkg/configure/tftp.go
@@ -12,7 +12,7 @@ import (
func TFTP() error {
controller := warewulfconf.Get()
- var tftpdir string = path.Join(controller.Paths.Tftpdir, "warewulf")
+ var tftpdir string = path.Join(controller.TFTP.TftpRoot, "warewulf")
err := os.MkdirAll(tftpdir, 0755)
if err != nil {
diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go
index 857f93cf..1ddf9274 100644
--- a/internal/pkg/node/constructors.go
+++ b/internal/pkg/node/constructors.go
@@ -49,7 +49,7 @@ func New() (NodeYaml, error) {
ConfigFile = path.Join(conf.Paths.Sysconfdir, "warewulf/nodes.conf")
}
if DefaultConfig == "" {
- DefaultConfig = path.Join(conf.Paths.Datadir, "warewulf/defaults.conf")
+ DefaultConfig = path.Join(conf.Warewulf.DataStore, "warewulf/defaults.conf")
}
wwlog.Verbose("Opening node configuration file: %s", ConfigFile)
data, err := os.ReadFile(ConfigFile)
diff --git a/internal/pkg/testenv/testenv.go b/internal/pkg/testenv/testenv.go
index 7303d326..6ddbeeca 100644
--- a/internal/pkg/testenv/testenv.go
+++ b/internal/pkg/testenv/testenv.go
@@ -68,10 +68,10 @@ func New(t *testing.T) (env *TestEnv) {
conf.Paths.Sysconfdir = env.GetPath(Sysconfdir)
conf.Paths.Bindir = env.GetPath(Bindir)
- conf.Paths.Datadir = env.GetPath(Datadir)
+ conf.Warewulf.DataStore = env.GetPath(Datadir)
conf.Paths.Localstatedir = env.GetPath(Localstatedir)
conf.Paths.Srvdir = env.GetPath(Srvdir)
- conf.Paths.Tftpdir = env.GetPath(Tftpdir)
+ conf.TFTP.TftpRoot = env.GetPath(Tftpdir)
conf.Paths.Firewallddir = env.GetPath(Firewallddir)
conf.Paths.Systemddir = env.GetPath(Systemddir)
conf.Paths.WWOverlaydir = env.GetPath(WWOverlaydir)
@@ -82,10 +82,10 @@ func New(t *testing.T) (env *TestEnv) {
for _, confPath := range []string{
conf.Paths.Sysconfdir,
conf.Paths.Bindir,
- conf.Paths.Datadir,
+ conf.Warewulf.DataStore,
conf.Paths.Localstatedir,
conf.Paths.Srvdir,
- conf.Paths.Tftpdir,
+ conf.TFTP.TftpRoot,
conf.Paths.Firewallddir,
conf.Paths.Systemddir,
conf.Paths.WWOverlaydir,
diff --git a/internal/pkg/version/version.go b/internal/pkg/version/version.go
index d4b5fb85..6231e4fc 100644
--- a/internal/pkg/version/version.go
+++ b/internal/pkg/version/version.go
@@ -12,7 +12,7 @@ Return the version of wwctl
*/
func GetVersion() string {
conf := warewulfconf.Get()
- return fmt.Sprintf("%s-%s", conf.Paths.Version, conf.Paths.Release)
+ return fmt.Sprintf("%s-%s", conf.Paths.Version(), conf.Paths.Release())
}
/*
diff --git a/internal/pkg/warewulfd/copyshim.go b/internal/pkg/warewulfd/copyshim.go
index 44ea45f4..0b295175 100644
--- a/internal/pkg/warewulfd/copyshim.go
+++ b/internal/pkg/warewulfd/copyshim.go
@@ -24,22 +24,22 @@ func CopyShimGrub() (err error) {
if shimPath == "" {
return fmt.Errorf("no shim found on the host os")
}
- err = util.CopyFile(shimPath, path.Join(conf.Paths.Tftpdir, "warewulf", "shim.efi"))
+ err = util.CopyFile(shimPath, path.Join(conf.TFTP.TftpRoot, "warewulf", "shim.efi"))
if err != nil {
return err
}
- _ = os.Chmod(path.Join(conf.Paths.Tftpdir, "warewulf", "shim.efi"), 0o755)
+ _ = os.Chmod(path.Join(conf.TFTP.TftpRoot, "warewulf", "shim.efi"), 0o755)
grubPath := container.GrubFind("")
if grubPath == "" {
return fmt.Errorf("no grub found on host os")
}
- err = util.CopyFile(grubPath, path.Join(conf.Paths.Tftpdir, "warewulf", "grub.efi"))
+ err = util.CopyFile(grubPath, path.Join(conf.TFTP.TftpRoot, "warewulf", "grub.efi"))
if err != nil {
return err
}
- _ = os.Chmod(path.Join(conf.Paths.Tftpdir, "warewulf", "grub.efi"), 0o755)
- err = util.CopyFile(grubPath, path.Join(conf.Paths.Tftpdir, "warewulf", "grubx64.efi"))
- _ = os.Chmod(path.Join(conf.Paths.Tftpdir, "warewulf", "grubx64.efi"), 0o755)
+ _ = os.Chmod(path.Join(conf.TFTP.TftpRoot, "warewulf", "grub.efi"), 0o755)
+ err = util.CopyFile(grubPath, path.Join(conf.TFTP.TftpRoot, "warewulf", "grubx64.efi"))
+ _ = os.Chmod(path.Join(conf.TFTP.TftpRoot, "warewulf", "grubx64.efi"), 0o755)
return
}

View File

@ -0,0 +1,53 @@
diff --git a/overlays/host/dnsmasq.d/ww4-hosts.conf.ww b/overlays/host/etc/dnsmasq.d/ww4-hosts.conf.ww
similarity index 57%
rename from overlays/host/dnsmasq.d/ww4-hosts.conf.ww
rename to overlays/host/etc/dnsmasq.d/ww4-hosts.conf.ww
index a9d6d66f..951a1596 100644
--- a/overlays/host/dnsmasq.d/ww4-hosts.conf.ww
+++ b/overlays/host/etc/dnsmasq.d/ww4-hosts.conf.ww
@@ -4,14 +4,30 @@
# Source {{.BuildSource}}
{{ nobackup }}
# 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
-{{ with (index $.Tftp.IpxeBinaries "00:07" ) }}dhcp-boot=tag:x86PC,"/warewulf/{{ index $.Tftp.IpxeBinaries "00:07" }}"{{ end }}
-dhcp-no-override
-# iPXE binary will get the following configuration file
+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://{{$.Ipaddr}}:{{$.Warewulf.Port}}/efiboot/shim.efi"
+# iPXE binary will get the following configuration file
dhcp-boot=tag:iPXE,"http://{{$.Ipaddr}}:{{$.Warewulf.Port}}/ipxe/${mac:hexhyp}"
+{{- if $.Warewulf.GrubBoot }}
+dhcp-boot=tag:x86PC,"warewulf/shim.efi"
+{{- else }}
+{{- with (index $.Tftp.IpxeBinaries "00:07" ) }}
+dhcp-boot=tag:x86PC,"/warewulf/{{ index $.Tftp.IpxeBinaries "00:07" }}"
+{{- end }}
+{{- with (index $.Tftp.IpxeBinaries "00:0B" ) }}
+dhcp-boot=tag:aarch64,"/warewulf/{{ index $.Tftp.IpxeBinaries "00:0B" }}"
+{{- end }}
+{{- end }}
+dhcp-no-override
{{- if $.Tftp.Enabled }}
# also act as tftp server
tftp-root={{ $.Tftp.TftpRoot }}
@@ -24,7 +40,7 @@ dhcp-range={{$.Dhcp.RangeStart}},{{$.Dhcp.RangeEnd}},{{$.Netmask}},6h
{{- if $netdev.Ipaddr.Defined}} {{/* if we have an ip address on this network device */}}
{{- if $netdev.Hwaddr.Defined }}
dhcp-host={{$netdev.Hwaddr.Get}},set:warewulf,{{$node.Id.Get}},{{$netdev.Ipaddr.Get}},infinite
-{{- end}} {{/* end if Hwaddr */}}
-{{- end}} {{/* end if ip */}}
-{{- end}} {{/* end for each network device */}}
-{{- end}} {{/* end for each node */}}
+{{- end}}{{/* end if Hwaddr */}}
+{{- end}}{{/* end if ip */}}
+{{- end}}{{/* end for each network device */}}
+{{- end}}{{/* end for each node */}}

View File

@ -1,24 +1,3 @@
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 70280717..93304050 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -124,6 +124,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support importing containers with symlinked `/bin/sh` #797
- Don't panic on malformed passwd #527
+- first container imported container is added to the default profile
+- grub in combination can now be set as boot method with `warewulf.grubboot: true` in
+ `warewulf.conf`. For unknown nodes `grub.efi` and `shim.efi` will be extracted from
+ the host running warewulf. If node has container it will get these binaries from the
+ container image.
+
+- Added support for booting nodes with grub. Enable this behavior using
+ warewulf.grubboot: true in warewulf.conf. For unknown nodes, grub.efi
+ and shim.efi are extracted from the Warewulf host. If the booted node
+ has a container these binaries are extracted from the container image.
## [4.4.0] 2023-01-18
### Added
diff --git a/Makefile b/Makefile diff --git a/Makefile b/Makefile
index 4ef5a5bf..e85ac05b 100644 index 4ef5a5bf..e85ac05b 100644
--- a/Makefile --- a/Makefile
@ -45,43 +24,60 @@ index 4ef5a5bf..e85ac05b 100644
(cd overlays && find * -type l -exec cp -av {} $(DESTDIR)$(WWOVERLAYDIR)/{} \;) (cd overlays && find * -type l -exec cp -av {} $(DESTDIR)$(WWOVERLAYDIR)/{} \;)
diff --git a/etc/grub/chainload.ww b/etc/grub/chainload.ww diff --git a/etc/grub/chainload.ww b/etc/grub/chainload.ww
new file mode 100644 new file mode 100644
index 00000000..916aff84 index 00000000..dc3c51d8
--- /dev/null --- /dev/null
+++ b/etc/grub/chainload.ww +++ b/etc/grub/chainload.ww
@@ -0,0 +1,18 @@ @@ -0,0 +1,28 @@
+# This file is autogenerated by warewulf +# This file is autogenerated by warewulf
+# Host: {{ .BuildHost }} +# Host: {{ .BuildHost }}
+# Time: {{ .BuildTime }} +# Time: {{ .BuildTime }}
+# Source: {{ .BuildSource }} +# Source: {{ .BuildSource }}
+echo "================================================================================" +echo "================================================================================"
+echo "Warewulf v4 now booting with grub" +echo "Warewulf v4 now iXPE booting with grub"
+echo +echo "================================================================================"
+echo "Warewulf Controller: {{.Ipaddr}}" +set timeout=2
+echo "Chain loading specific grub.cfg" +# Must chainload in order to get kernel args for specific node
+uri="(http,{{.Ipaddr}}:{{.Warewulf.Port}})/efiboot/grub.cfg" +menuentry "Load specific configfile" {
+echo $uri + conf="(http,{{.Ipaddr}}:{{.Warewulf.Port}})/efiboot/grub.cfg"
+configfile $uri + configfile $conf
+echo "MESSAGE: This node is unconfigured. Please have your system administrator add a" +}
+echo " configuration for this node with HW address: ${net_default_mac}" +menuentry "Chainload shim of container" {
+echo "" + shim="(http,{{.Ipaddr}}:{{.Warewulf.Port}})/efiboot/shim.efi"
+echo "Rebooting in 1 minute..." + chainloader ${shim}
+sleep 60 +}
+menuentry "UEFI Firmware Settings" --id "uefi-firmware" {
+ fwsetup
+}
+menuentry "System restart" {
+ echo "System rebooting..."
+ reboot + reboot
+}
+menuentry "System shutdown" {
+ echo "System shutting down..."
+ halt
+}
diff --git a/etc/grub/grub.cfg.ww b/etc/grub/grub.cfg.ww diff --git a/etc/grub/grub.cfg.ww b/etc/grub/grub.cfg.ww
new file mode 100644 new file mode 100644
index 00000000..79357fae index 00000000..7efbbe0a
--- /dev/null --- /dev/null
+++ b/etc/grub/grub.cfg.ww +++ b/etc/grub/grub.cfg.ww
@@ -0,0 +1,29 @@ @@ -0,0 +1,51 @@
+echo "================================================================================" +echo "================================================================================"
+echo "Warewulf v4 now booting with grub: {{.Fqdn}} ({{.Hwaddr}})" +echo "Warewulf v4 now http booting grub: {{.Fqdn}} ({{.Hwaddr}})"
+echo "================================================================================" +echo "================================================================================"
+uri="(http,{{.Ipaddr}}:9873)/provision/${net_default_mac}?assetkey=" +echo
+echo "Warewulf Controller: {{.Ipaddr}}"
+echo
+sleep 1
+smbios --type1 --get-string 8 --set assetkey
+uri="(http,{{.Ipaddr}}:{{.Port}})/provision/${net_default_mac}?assetkey=${assetkey}"
+kernel="${uri}&stage=kernel" +kernel="${uri}&stage=kernel"
+container="${uri}&stage=container&compress=gz" +container="${uri}&stage=container&compress=gz"
+system="${uri}&stage=system&compress=gz" +system="${uri}&stage=system&compress=gz"
+runtime="${uri}&stage=runtime&compress=gz" +runtime="${uri}&stage=runtime&compress=gz"
+echo "Warewulf Controller: {{.Ipaddr}}" +set default=ww4
+set timeout=5
+menuentry "Network boot node: {{.Id}}" --id ww4 {
+ {{if .KernelOverride }} + {{if .KernelOverride }}
+ echo "Kernel: {{.KernelOverride}}" + echo "Kernel: {{.KernelOverride}}"
+ {{else}} + {{else}}
@ -92,16 +88,32 @@ index 00000000..79357fae
+ if [ x$? = x0 ] ; then + if [ x$? = x0 ] ; then
+ echo "Loading Container: {{.ContainerName}}" + echo "Loading Container: {{.ContainerName}}"
+ initrd $container $system $runtime + initrd $container $system $runtime
+echo
+ boot + boot
+ else + else
+echo "MESSAGE: This node is unconfigured. Please have your system administrator add a" + echo "MESSAGE: This node seems to be unconfigured. Please have your system administrator add a"
+ echo " configuration for this node with HW address: ${net_default_mac}" + echo " configuration for this node with HW address: ${net_default_mac}"
+ echo "" + echo ""
+ echo "Rebooting in 1 minute..." + echo "Rebooting in 1 minute..."
+ sleep 60 + sleep 60
+ reboot + reboot
+ fi + fi
+}
+menuentry "Chainload specific configfile" {
+ conf="(http,{{.Ipaddr}}:{{.Port}})/efiboot/grub.cfg"
+ configfile $conf
+}
+menuentry "UEFI Firmware Settings" --id "uefi-firmware" {
+ fwsetup
+}
+menuentry "System restart" {
+ echo "System rebooting..."
+ reboot
+}
+menuentry "System shutdown" {
+ echo "System shutting down..."
+ halt
+}
\ No newline at end of file
diff --git a/go.mod b/go.mod diff --git a/go.mod b/go.mod
index c9e07d29..4d304414 100644 index c9e07d29..4d304414 100644
--- a/go.mod --- a/go.mod
@ -407,7 +419,7 @@ index 00000000..a590690f
+ return "" + return ""
+} +}
diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go
index 08c27b19..053d3a63 100644 index fe7eb87a..857f93cf 100644
--- a/internal/pkg/node/constructors.go --- a/internal/pkg/node/constructors.go
+++ b/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go
@@ -31,6 +31,7 @@ defaultnode: @@ -31,6 +31,7 @@ defaultnode:
@ -418,7 +430,7 @@ index 08c27b19..053d3a63 100644
profiles: profiles:
- default - default
network devices: network devices:
@@ -306,6 +307,36 @@ func (config *NodeYaml) ListAllProfiles() []string { @@ -305,6 +306,36 @@ func (config *NodeYaml) ListAllProfiles() []string {
return ret return ret
} }
@ -640,20 +652,18 @@ index 1e62dd0f..063d10b4 100644
if ret.ipaddr == "" { if ret.ipaddr == "" {
return ret, errors.New("could not obtain ipaddr from HTTP request") return ret, errors.New("could not obtain ipaddr from HTTP request")
diff --git a/internal/pkg/warewulfd/provision.go b/internal/pkg/warewulfd/provision.go diff --git a/internal/pkg/warewulfd/provision.go b/internal/pkg/warewulfd/provision.go
index f2851a26..b04a8a91 100644 index f2851a26..bdca8a34 100644
--- a/internal/pkg/warewulfd/provision.go --- a/internal/pkg/warewulfd/provision.go
+++ b/internal/pkg/warewulfd/provision.go +++ b/internal/pkg/warewulfd/provision.go
@@ -3,7 +3,9 @@ package warewulfd @@ -3,6 +3,7 @@ package warewulfd
import ( import (
"bytes" "bytes"
"errors" "errors"
+ "fmt" + "fmt"
"net/http" "net/http"
+ "os"
"path" "path"
"strconv" "strconv"
"strings" @@ -17,7 +18,7 @@ import (
@@ -17,7 +19,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/hpcng/warewulf/internal/pkg/wwlog"
) )
@ -662,7 +672,7 @@ index f2851a26..b04a8a91 100644
Message string Message string
WaitTime string WaitTime string
Hostname string Hostname string
@@ -32,13 +34,10 @@ type iPxeTemplate struct { @@ -32,20 +33,13 @@ type iPxeTemplate struct {
KernelOverride string KernelOverride string
} }
@ -673,14 +683,19 @@ index f2851a26..b04a8a91 100644
- "system": "SYSTEM_OVERLAY", - "system": "SYSTEM_OVERLAY",
- "runtime": "RUNTIME_OVERLAY"} - "runtime": "RUNTIME_OVERLAY"}
- -
+/*
+Handles all the http request for warewulfd, different stages are encoded
+in the GET request.
+*/
func ProvisionSend(w http.ResponseWriter, req *http.Request) { func ProvisionSend(w http.ResponseWriter, req *http.Request) {
+ wwlog.Debug("Requested URL: %s", req.URL.String())
conf := warewulfconf.Get() conf := warewulfconf.Get()
-
rinfo, err := parseReq(req)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
- wwlog.ErrorExc(err, "")
+ wwlog.ErrorExc(err, "Bad status")
return
}
@@ -59,8 +58,17 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { @@ -59,6 +53,14 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
} }
} }
@ -693,13 +708,9 @@ index f2851a26..b04a8a91 100644
+ "runtime": "RUNTIME_OVERLAY"} + "runtime": "RUNTIME_OVERLAY"}
+ +
status_stage := status_stages[rinfo.stage] status_stage := status_stages[rinfo.stage]
- var stage_file string var stage_file string
+ var stage_file string = ""
+ updateSentDB := true
// TODO: when module version is upgraded to go1.18, should be 'any' type @@ -83,13 +85,13 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
var tmpl_data interface{}
@@ -83,13 +91,13 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
wwlog.Error("%s (unknown/unconfigured node)", rinfo.hwaddr) wwlog.Error("%s (unknown/unconfigured node)", rinfo.hwaddr)
if rinfo.stage == "ipxe" { if rinfo.stage == "ipxe" {
stage_file = path.Join(conf.Paths.Sysconfdir, "/warewulf/ipxe/unconfigured.ipxe") stage_file = path.Join(conf.Paths.Sysconfdir, "/warewulf/ipxe/unconfigured.ipxe")
@ -715,29 +726,15 @@ index f2851a26..b04a8a91 100644
Id: node.Id.Get(), Id: node.Id.Get(),
Cluster: node.ClusterName.Get(), Cluster: node.ClusterName.Get(),
Fqdn: node.Id.Get(), Fqdn: node.Id.Get(),
@@ -100,8 +108,20 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { @@ -100,7 +102,6 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
ContainerName: node.ContainerName.Get(), ContainerName: node.ContainerName.Get(),
KernelArgs: node.Kernel.Args.Get(), KernelArgs: node.Kernel.Args.Get(),
KernelOverride: node.Kernel.Override.Get()} KernelOverride: node.Kernel.Override.Get()}
- -
} else if rinfo.stage == "kernel" { } else if rinfo.stage == "kernel" {
+ if DBGetWWinit(node.Id.Get()) {
+ DBReset(node.Id.Get())
+ }
+ if DBSize(node.Id.Get()) == 0 {
+ fd, err := os.Open(path.Join(path.Join(conf.Paths.Tftpdir, "warewulf", "grub.cfg")))
+ if err != nil {
+ wwlog.Warn("no grub.cfg detected for potential tftp boot node: %s", node)
+ } else {
+ defer fd.Close()
+ DBAddImage(node.Id.Get(), "grub.cfg", fd)
+ }
+
+ }
if node.Kernel.Override.Defined() { if node.Kernel.Override.Defined() {
stage_file = kernel.KernelImage(node.Kernel.Override.Get()) stage_file = kernel.KernelImage(node.Kernel.Override.Get())
} else if node.ContainerName.Defined() { @@ -137,7 +138,6 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
@@ -137,7 +157,6 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
} else { } else {
context = rinfo.stage context = rinfo.stage
} }
@ -745,7 +742,7 @@ index f2851a26..b04a8a91 100644
stage_file, err = getOverlayFile( stage_file, err = getOverlayFile(
node, node,
context, context,
@@ -154,6 +173,64 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { @@ -154,6 +154,64 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
wwlog.ErrorExc(err, "") wwlog.ErrorExc(err, "")
return return
} }
@ -810,29 +807,6 @@ index f2851a26..b04a8a91 100644
} }
wwlog.Serv("stage_file '%s'", stage_file) wwlog.Serv("stage_file '%s'", stage_file)
@@ -187,11 +264,12 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text")
w.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
+ reader := bytes.NewReader(buf.Bytes())
+ DBAddImage(node.Id.Get(), stage_file, reader)
_, err = buf.WriteTo(w)
if err != nil {
wwlog.ErrorExc(err, "")
}
-
wwlog.Send("%15s: %s", node.Id.Get(), stage_file)
} else {
@@ -210,7 +288,7 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusNotFound)
}
- err = sendFile(w, req, stage_file, node.Id.Get())
+ err = sendFile(w, req, stage_file, node.Id.Get(), updateSentDB)
if err != nil {
wwlog.ErrorExc(err, "")
return
diff --git a/internal/pkg/warewulfd/provision_test.go b/internal/pkg/warewulfd/provision_test.go diff --git a/internal/pkg/warewulfd/provision_test.go b/internal/pkg/warewulfd/provision_test.go
index 870e1de0..5ec8d72e 100644 index 870e1de0..5ec8d72e 100644
--- a/internal/pkg/warewulfd/provision_test.go --- a/internal/pkg/warewulfd/provision_test.go
@ -965,267 +939,31 @@ index 870e1de0..5ec8d72e 100644
assert.NoError(t, readErr) assert.NoError(t, readErr)
assert.Equal(t, tt.body, string(data)) assert.Equal(t, tt.body, string(data))
assert.Equal(t, tt.status, res.StatusCode) assert.Equal(t, tt.status, res.StatusCode)
diff --git a/internal/pkg/warewulfd/sentDB.go b/internal/pkg/warewulfd/sentDB.go
new file mode 100644
index 00000000..ee64e4c5
--- /dev/null
+++ b/internal/pkg/warewulfd/sentDB.go
@@ -0,0 +1,144 @@
+package warewulfd
+
+import (
+ "crypto/sha256"
+ "fmt"
+ "io"
+ "path"
+ "sync"
+
+ "github.com/hpcng/warewulf/internal/pkg/wwlog"
+)
+
+/*
+store the sent files name and its checksum
+*/
+type SentFiles struct {
+ Files []File `json:"files:"`
+ sha256sum [32]byte
+ Sha256hex string `json:"sha256"`
+ wwinit bool
+}
+
+type File struct {
+ FileName string `json:"file name"`
+ sha256sum [32]byte
+ Sha256hex string `json:"sha256"`
+}
+
+/*
+Database for the checksum of sent files, this
+values can be used for measured boot in combination with
+TPM devicces
+*/
+var sentDB map[string]*SentFiles
+
+// mutex for locking the map
+var mu sync.Mutex
+
+func init() {
+ sentDB = map[string]*SentFiles{}
+}
+
+/*
+Adds the image with the name to the database
+*/
+func DBAddImage(node string, fileName string, content io.ReadSeeker) {
+ wwlog.Debug("adding file %s for node %s to sentDB", node, fileName)
+ hasher := sha256.New()
+ sent := File{
+ FileName: path.Base(fileName),
+ }
+ if _, err := io.Copy(hasher, content); err != nil {
+ wwlog.SecWarn("couldn't create hash of %s for %s", fileName, node)
+ return
+ }
+ copy(sent.sha256sum[:], hasher.Sum(nil))
+ sent.Sha256hex = fmt.Sprintf("%x", sent.sha256sum)
+ mu.Lock()
+ if _, ok := sentDB[node]; !ok {
+ sentDB[node] = new(SentFiles)
+ }
+ sentDB[node].Files = append(sentDB[node].Files, sent)
+ for i := 0; i < sha256.Size; i++ {
+ sentDB[node].sha256sum[i] = 1
+ }
+ for _, sntFile := range sentDB[node].Files {
+ sentDB[node].sha256sum = sha256.Sum256(append(sentDB[node].sha256sum[:], sntFile.sha256sum[:]...))
+ }
+ sentDB[node].Sha256hex = fmt.Sprintf("%x", sentDB[node].sha256sum)
+ mu.Unlock()
+ hasher.Reset()
+}
+
+/*
+Get the final sum of all the hashed files
+*/
+func DBGetSum(node string) (ret [sha256.Size]byte) {
+ mu.Lock()
+ defer mu.Unlock()
+ if sentNode, ok := sentDB[node]; ok {
+ ret = sentNode.sha256sum
+ return
+ }
+ ret = [sha256.Size]byte{0}
+ return
+}
+
+/*
+Reset the database for a single node
+*/
+func DBReset(node string) {
+ mu.Lock()
+ if _, ok := sentDB[node]; !ok {
+ sentDB[node] = new(SentFiles)
+ }
+ sentDB[node] = new(SentFiles)
+ mu.Unlock()
+}
+
+/*
+Reset the database
+*/
+func DBResetAll() {
+ sentDB = make(map[string]*SentFiles)
+}
+
+/*
+Get the size of the DB
+*/
+func DBSize(node string) int {
+ mu.Lock()
+ if _, ok := sentDB[node]; !ok {
+ sentDB[node] = new(SentFiles)
+ }
+ size := len(sentDB[node].Files)
+ mu.Unlock()
+ return size
+}
+
+/*
+Check if wwinit was sent
+*/
+func DBGetWWinit(node string) bool {
+ mu.Lock()
+ if _, ok := sentDB[node]; !ok {
+ sentDB[node] = new(SentFiles)
+ }
+ ret := sentDB[node].wwinit
+ mu.Unlock()
+ return ret
+}
+
+/*
+Mark that wwinit was sent
+*/
+
+func DBWWinitSent(node string) {
+ mu.Lock()
+ if _, ok := sentDB[node]; !ok {
+ sentDB[node] = new(SentFiles)
+ }
+ sentDB[node].wwinit = true
+ mu.Unlock()
+}
diff --git a/internal/pkg/warewulfd/sentstatus.go b/internal/pkg/warewulfd/sentstatus.go
new file mode 100644
index 00000000..36350367
--- /dev/null
+++ b/internal/pkg/warewulfd/sentstatus.go
@@ -0,0 +1,34 @@
+package warewulfd
+
+import (
+ "encoding/json"
+ "net/http"
+
+ "github.com/hpcng/warewulf/internal/pkg/wwlog"
+ "github.com/pkg/errors"
+)
+
+func sentStatusJSON() ([]byte, error) {
+ wwlog.Debug("Request for node sent status data...")
+
+ ret, err := json.MarshalIndent(sentDB, "", " ")
+ if err != nil {
+ return ret, errors.Wrap(err, "could not marshal JSON data from status structure")
+ }
+
+ return ret, nil
+
+}
+
+func SentStatus(w http.ResponseWriter, req *http.Request) {
+ status, err := sentStatusJSON()
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ _, err = w.Write(status)
+ if err != nil {
+ wwlog.Warn("Could not send sent status JSON: %s", err)
+ }
+}
diff --git a/internal/pkg/warewulfd/sentsums_test.go b/internal/pkg/warewulfd/sentsums_test.go
new file mode 100644
index 00000000..41fcfe00
--- /dev/null
+++ b/internal/pkg/warewulfd/sentsums_test.go
@@ -0,0 +1,23 @@
+package warewulfd
+
+import (
+ "bytes"
+ "testing"
+)
+
+func Test_SumOne(t *testing.T) {
+ firstText := `Scalable. Flexible. Today, Warewulf unites the ecosystem with the ability to provision containers directly to the bare metal hardware at massive scale, simplistically while retaining massive flexibility.`
+ secondText := `Being open source for over two-decades, and pioneering the concept of stateless node management, Warewulf is among the most successful HPC cluster platforms in the industry with support from OpenHPC, contributors around the world, and usage from every industry.`
+ DBAddImage("n01", "firstText", bytes.NewReader([]byte(firstText)))
+ DBAddImage("n01", "secondText", bytes.NewReader([]byte(secondText)))
+ if sum_n02 := DBGetSum("n02"); sum_n02 != [32]byte{} {
+ t.Errorf("Sum of second entry must be zero")
+ }
+ if sum_n01 := DBGetSum("n01"); sum_n01 == [32]byte{} {
+ t.Errorf("Sum of entry must not be zero")
+ }
+ DBResetAll()
+ if sum_n01 := DBGetSum("n01"); sum_n01 != [32]byte{} {
+ t.Errorf("Sum after reset must be zero")
+ }
+}
diff --git a/internal/pkg/warewulfd/util.go b/internal/pkg/warewulfd/util.go diff --git a/internal/pkg/warewulfd/util.go b/internal/pkg/warewulfd/util.go
index 3290a678..cefa1cab 100644 index 3290a678..caaf22ae 100644
--- a/internal/pkg/warewulfd/util.go --- a/internal/pkg/warewulfd/util.go
+++ b/internal/pkg/warewulfd/util.go +++ b/internal/pkg/warewulfd/util.go
@@ -1,8 +1,11 @@ @@ -1,8 +1,10 @@
package warewulfd package warewulfd
import ( import (
+ "bufio" + "bufio"
+ "io"
"net/http" "net/http"
"os" "os"
+ "strings" + "strings"
"github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/node"
nodepkg "github.com/hpcng/warewulf/internal/pkg/node" nodepkg "github.com/hpcng/warewulf/internal/pkg/node"
@@ -15,7 +18,7 @@ func sendFile( @@ -38,7 +40,7 @@ func sendFile(
w http.ResponseWriter,
req *http.Request,
filename string,
- sendto string) error {
+ sendto string, updateSentDB bool) error {
fd, err := os.Open(filename)
if err != nil {
@@ -36,7 +39,14 @@ func sendFile(
filename,
stat.ModTime(),
fd) fd)
-
+ // seek back
+ _, err = fd.Seek(0, io.SeekStart)
+ if err != nil {
+ wwlog.Warn("couldn't seek in file: %s", filename)
+ }
+ if updateSentDB {
+ DBAddImage(sendto, filename, fd)
+ }
wwlog.Send("%15s: %s", sendto, filename)
wwlog.Send("%15s: %s", sendto, filename)
-
+ req.Body.Close()
return nil return nil
@@ -70,3 +80,34 @@ func getOverlayFile( }
@@ -70,3 +72,34 @@ func getOverlayFile(
return return
} }
@ -1261,7 +999,7 @@ index 3290a678..cefa1cab 100644
+ return + return
+} +}
diff --git a/internal/pkg/warewulfd/warewulfd.go b/internal/pkg/warewulfd/warewulfd.go diff --git a/internal/pkg/warewulfd/warewulfd.go b/internal/pkg/warewulfd/warewulfd.go
index 796054b0..4c480ebe 100644 index 796054b0..c9376634 100644
--- a/internal/pkg/warewulfd/warewulfd.go --- a/internal/pkg/warewulfd/warewulfd.go
+++ b/internal/pkg/warewulfd/warewulfd.go +++ b/internal/pkg/warewulfd/warewulfd.go
@@ -5,6 +5,7 @@ import ( @@ -5,6 +5,7 @@ import (
@ -1296,7 +1034,7 @@ index 796054b0..4c480ebe 100644
func RunServer() error { func RunServer() error {
err := DaemonInitLogging() err := DaemonInitLogging()
@@ -49,21 +67,27 @@ func RunServer() error { @@ -49,21 +67,36 @@ func RunServer() error {
wwlog.Error("Could not prepopulate node status DB: %s", err) wwlog.Error("Could not prepopulate node status DB: %s", err)
} }
@ -1321,18 +1059,122 @@ index 796054b0..4c480ebe 100644
+ wwHandler.HandleFunc("/overlay-system/", ProvisionSend) + wwHandler.HandleFunc("/overlay-system/", ProvisionSend)
+ wwHandler.HandleFunc("/overlay-runtime/", ProvisionSend) + wwHandler.HandleFunc("/overlay-runtime/", ProvisionSend)
+ wwHandler.HandleFunc("/status", StatusSend) + wwHandler.HandleFunc("/status", StatusSend)
+ wwHandler.HandleFunc("/sentstatus", SentStatus)
conf := warewulfconf.Get() conf := warewulfconf.Get()
daemonPort := conf.Warewulf.Port daemonPort := conf.Warewulf.Port
wwlog.Serv("Starting HTTPD REST service on port %d", daemonPort) - wwlog.Serv("Starting HTTPD REST service on port %d", daemonPort)
+ /*
+ wwlog.Serv("Starting HTTPD REST service on port %d", daemonPort)
+ s := &http.Server{
+ Addr: ":" + strconv.Itoa(daemonPort),
+ Handler: &slashFix{&wwHandler},
+ ReadTimeout: 10 * time.Second,
+ IdleTimeout: 10 * time.Second,
+ WriteTimeout: 10 * time.Second,
+ }
+ err = s.ListenAndServe()
+ */
+ err = http.ListenAndServe(":"+strconv.Itoa(daemonPort), &slashFix{&wwHandler})
- err = http.ListenAndServe(":"+strconv.Itoa(daemonPort), nil) - err = http.ListenAndServe(":"+strconv.Itoa(daemonPort), nil)
+ err = http.ListenAndServe(":"+strconv.Itoa(daemonPort), &slashFix{&wwHandler})
if err != nil { if err != nil {
return errors.Wrap(err, "Could not start listening service") return errors.Wrap(err, "Could not start listening service")
} }
diff --git a/internal/pkg/wwlog/wwlog.go b/internal/pkg/wwlog/wwlog.go
index 98f67f2a..0b8ee5ca 100644
--- a/internal/pkg/wwlog/wwlog.go
+++ b/internal/pkg/wwlog/wwlog.go
@@ -36,9 +36,11 @@ var (
ERROR = SetLevelName(40, "ERROR")
SECWARN = SetLevelName(31, "SECWARN")
WARN = SetLevelName(30, "WARN")
+ ERROUT = SetLevelName(29, "ERROUT")
SEND = SetLevelName(27, "SEND")
RECV = SetLevelName(26, "RECV")
SERV = SetLevelName(25, "SERV")
+ OUT = SetLevelName(22, "OUT")
SECINFO = SetLevelName(21, "SECINFO")
INFO = SetLevelName(20, "INFO")
SECVERBOSE = SetLevelName(16, "SECVERBOSE")
@@ -52,6 +54,7 @@ var (
levelNames = []string{"NOTSET"}
logLevel = INFO
logErr io.Writer = os.Stderr
+ logOut io.Writer = os.Stdout
logFormatter LogFormatter = DefaultFormatter
)
@@ -153,11 +156,30 @@ func GetLogLevel() int {
Set the log output writer
By default they are set to output writer
*/
-func SetLogWriter(err io.Writer) {
- logErr = err
+func SetLogWriter(newOut io.Writer) {
+ logErr = newOut
+ logOut = newOut
}
-func GetLogWriter() io.Writer {
+/*
+Set the log ofr info only
+*/
+func SetLogWriterInfo(newOut io.Writer) {
+ logOut = newOut
+}
+
+/*
+Set the log ofr info only
+*/
+func SetLogWriterErr(newOut io.Writer) {
+ logOut = newOut
+}
+
+func GetLogWriterInfo() io.Writer {
+ return logOut
+}
+
+func GetLogWriterErr() io.Writer {
return logErr
}
@@ -196,8 +218,12 @@ func LogCaller(level int, skip int, err error, message string, a ...interface{})
}
message = logFormatter(logLevel, &rec)
+ if level == INFO || level == RECV || level == SEND || level == OUT {
+ fmt.Fprint(logOut, message)
+ } else {
+ fmt.Fprint(logErr, message)
- fmt.Fprint(logErr, message)
+ }
}
}
@@ -249,6 +275,10 @@ func Info(message string, a ...interface{}) {
LogCaller(INFO, 1, nil, message, a...)
}
+func Output(message string, a ...interface{}) {
+ LogCaller(OUT, 1, nil, message, a...)
+}
+
func InfoExc(err error, message string, a ...interface{}) {
LogCaller(INFO, 1, err, message, a...)
}
@@ -281,6 +311,10 @@ func SecWarn(message string, a ...interface{}) {
LogCaller(SECWARN, 1, nil, message, a...)
}
+func ErrOut(message string, a ...interface{}) {
+ LogCaller(ERROUT, 1, nil, message, a...)
+}
+
func Error(message string, a ...interface{}) {
LogCaller(ERROR, 1, nil, message, a...)
}
diff --git a/overlays/host/etc/dhcp/dhcpd.conf.ww b/overlays/host/etc/dhcp/dhcpd.conf.ww diff --git a/overlays/host/etc/dhcp/dhcpd.conf.ww b/overlays/host/etc/dhcp/dhcpd.conf.ww
index 4a9637f7..03fe54cb 100644 index 4a9637f7..03fe54cb 100644
--- a/overlays/host/etc/dhcp/dhcpd.conf.ww --- a/overlays/host/etc/dhcp/dhcpd.conf.ww

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:e0bb66935b1e4b11e542ef521284389a6e492fc775adfe8a9384fcc8efff76f2 oid sha256:23b80008f251cf1abfa23bede22168d503cb7abc0e71b79703de425e4c835d7f
size 16927353 size 16928203

View File

@ -1,3 +1,12 @@
-------------------------------------------------------------------
Wed Jan 17 11:16:59 UTC 2024 - Christian Goll <cgoll@suse.com>
- added documentation for replacing dhcpd and tftp with dnsmasq
as README.dnsmasq (jira#HPC-65)
- added following patches:
* clean-warewulf-conf.patch
* dnsmasq-template-move.patch
------------------------------------------------------------------- -------------------------------------------------------------------
Thu Dec 21 14:48:08 UTC 2023 - Christian Goll <cgoll@suse.com> Thu Dec 21 14:48:08 UTC 2023 - Christian Goll <cgoll@suse.com>

View File

@ -1,7 +1,7 @@
# #
# spec file for package warewulf4 # spec file for package warewulf4
# #
# Copyright (c) 2023 SUSE LLC # Copyright (c) 2024 SUSE LLC
# #
# All modifications and additions to the file contributed by third parties # All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed # remain the property of their copyright owners, unless otherwise agreed
@ -33,7 +33,10 @@ URL: https://warewulf.org
Source0: https://github.com/hpcng/warewulf/releases/download/nightly/warewulf-4.5.x.tar.gz#/warewulf4-v%{version}.tar.gz Source0: https://github.com/hpcng/warewulf/releases/download/nightly/warewulf-4.5.x.tar.gz#/warewulf4-v%{version}.tar.gz
Source5: warewulf4-rpmlintrc Source5: warewulf4-rpmlintrc
Source10: config-ww4.sh Source10: config-ww4.sh
Source20: README.dnsmasq
Patch10: grub-boot.patch Patch10: grub-boot.patch
Patch12: clean-warewulf-conf.patch
Patch15: dnsmasq-template-move.patch
# no firewalld in sle12 # no firewalld in sle12
%if 0%{?sle_version} >= 150000 || 0%{?suse_version} > 1500 %if 0%{?sle_version} >= 150000 || 0%{?suse_version} > 1500
@ -163,6 +166,7 @@ mv -v %{buildroot}%{_sysconfdir}/bash_completion.d/wwctl \
#rm -r %{buildroot}%{_datadir}/doc/warewulf #rm -r %{buildroot}%{_datadir}/doc/warewulf
# copy the LICESNSE.md via %%doc # copy the LICESNSE.md via %%doc
rm -f %{buildroot}/usr/share/doc/packages/warewulf/LICENSE.md rm -f %{buildroot}/usr/share/doc/packages/warewulf/LICENSE.md
cp %{S:20} .
# use ipxe-bootimgs images from distribution # use ipxe-bootimgs images from distribution
yq e ' yq e '
@ -173,7 +177,7 @@ yq e '
.["container mounts"] += {"source": "/etc/SUSEConnect", "dest": "/etc/SUSEConnect", "readonly": true} | .["container mounts"] += {"source": "/etc/SUSEConnect", "dest": "/etc/SUSEConnect", "readonly": true} |
.["container mounts"] += {"source": "/etc/zypp/credentials.d/SCCcredentials", "dest": "/etc/zypp/credentials.d/SCCcredentials", "readonly": true}' \ .["container mounts"] += {"source": "/etc/zypp/credentials.d/SCCcredentials", "dest": "/etc/zypp/credentials.d/SCCcredentials", "readonly": true}' \
-i %{buildroot}%{_sysconfdir}/warewulf/warewulf.conf -i %{buildroot}%{_sysconfdir}/warewulf/warewulf.conf
sed -i 's@\(^\s*\)\(.*:.*\):@\1"\2":@' %{buildroot}%{_sysconfdir}/warewulf/warewulf.conf #sed -i -e 's@\(^\s*\)\(.*:.*\):@\1"\2":@' %{buildroot}%{_sysconfdir}/warewulf/warewulf.conf
# fix dhcp for SUSE # fix dhcp for SUSE
mv %{buildroot}%{_localstatedir}/lib/warewulf/overlays/host/etc/dhcp/dhcpd.conf.ww %{buildroot}%{_localstatedir}/lib/warewulf/overlays/host/etc/dhcpd.conf.ww mv %{buildroot}%{_localstatedir}/lib/warewulf/overlays/host/etc/dhcp/dhcpd.conf.ww %{buildroot}%{_localstatedir}/lib/warewulf/overlays/host/etc/dhcpd.conf.ww
rmdir %{buildroot}%{_localstatedir}/lib/warewulf/overlays/host/etc/dhcp rmdir %{buildroot}%{_localstatedir}/lib/warewulf/overlays/host/etc/dhcp
@ -214,6 +218,7 @@ EOF
%files %files
%defattr(-,root,root) %defattr(-,root,root)
%doc README.md %doc README.md
%doc README.dnsmasq
%license LICENSE.md %license LICENSE.md
%{_datadir}/bash-completion/completions/wwctl %{_datadir}/bash-completion/completions/wwctl
%attr(0755, root, warewulf) %dir %{_sysconfdir}/warewulf %attr(0755, root, warewulf) %dir %{_sysconfdir}/warewulf