Refactor and document config/datastructure

Also adjusted case for initialisms (e.g., DHCP, TFTP, NFS).

Signed-off-by: Jonathon Anderson <janderson@ciq.co>
This commit is contained in:
Jonathon Anderson
2023-04-14 19:21:29 -06:00
parent cfdf179e16
commit 8321193645
15 changed files with 122 additions and 100 deletions

3
.gitignore vendored
View File

@@ -28,8 +28,7 @@ internal/pkg/buildconfig/setconfigs.go
internal/pkg/config/buildconfig.go internal/pkg/config/buildconfig.go
include/systemd/warewulfd.service include/systemd/warewulfd.service
_dist/ _dist/
config /config
!internal/pkg/config
warewulf-*.tar.gz warewulf-*.tar.gz
Defaults.mk Defaults.mk
/etc/wwapid.config /etc/wwapid.config

View File

@@ -6,5 +6,5 @@ import (
) )
func CobraRunE(cmd *cobra.Command, args []string) error { func CobraRunE(cmd *cobra.Command, args []string) error {
return configure.Dhcp() return configure.DHCP()
} }

View File

@@ -11,7 +11,7 @@ import (
func CobraRunE(cmd *cobra.Command, args []string) error { func CobraRunE(cmd *cobra.Command, args []string) error {
var err error var err error
if allFunctions { if allFunctions {
err = configure.Dhcp() err = configure.DHCP()
if err != nil { if err != nil {
wwlog.Error("%s", err) wwlog.Error("%s", err)
os.Exit(1) os.Exit(1)

View File

@@ -8,7 +8,7 @@ type BuildConfig struct {
Datadir string `default:"@DATADIR@"` Datadir string `default:"@DATADIR@"`
Localstatedir string `default:"@LOCALSTATEDIR@"` Localstatedir string `default:"@LOCALSTATEDIR@"`
Srvdir string `default:"@SRVDIR@"` Srvdir string `default:"@SRVDIR@"`
Tftpdir string `default:"@TFTPDIR@"` TFTPdir string `default:"@TFTPDIR@"`
Firewallddir string `default:"@FIREWALLDDIR@"` Firewallddir string `default:"@FIREWALLDDIR@"`
Systemddir string `default:"@SYSTEMDDIR@"` Systemddir string `default:"@SYSTEMDDIR@"`
WWOverlaydir string `default:"@WWOVERLAYDIR@"` WWOverlaydir string `default:"@WWOVERLAYDIR@"`

View File

@@ -1,61 +0,0 @@
package config
import (
"github.com/creasty/defaults"
)
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"`
}
type DhcpConf struct {
Enabled bool `yaml:"enabled" default:"true"`
Template string `yaml:"template" default:"default"`
RangeStart string `yaml:"range start,omitempty"`
RangeEnd string `yaml:"range end,omitempty"`
SystemdName string `yaml:"systemd name" default:"dhcpd"`
}
type TftpConf struct {
Enabled bool `yaml:"enabled" default:"true"`
TftpRoot string `yaml:"tftproot" default:"/var/lib/tftpboot"`
SystemdName string `yaml:"systemd name" default:"tftp"`
// Path is relative to buildconfig.DATADIR()
IpxeBinaries map[string]string `yaml:"ipxe" default:"{\"00:09\": \"x86_64.efi\",\"00:00\": \"x86_64.kpxe\",\"00:0B\": \"arm64.efi\",\"00:07\": \"x86_64.efi\"}"`
}
type NfsConf struct {
Enabled bool `yaml:"enabled" default:"true"`
ExportsExtended []*NfsExportConf `yaml:"export paths" default:"[]"`
SystemdName string `yaml:"systemd name" default:"nfsd"`
}
type NfsExportConf struct {
Path string `yaml:"path" default:"/dev/null"`
ExportOptions string `default:"rw,sync,no_subtree_check" yaml:"export options"`
MountOptions string `default:"defaults" yaml:"mount options"`
Mount bool `default:"true" yaml:"mount"`
}
/*
Describe a mount point for a container exec
*/
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"`
Options string `yaml:"options,omitempty"` // ignored at the moment
}
func (s *NfsConf) Unmarshal(unmarshal func(interface{}) error) error {
if err := defaults.Set(s); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,12 @@
package config
// DHCPConf represents the configuration for the DHCP service that
// Warewulf will configure.
type DHCPConf struct {
Enabled bool `yaml:"enabled" default:"true"`
Template string `yaml:"template" default:"default"`
RangeStart string `yaml:"range start,omitempty"`
RangeEnd string `yaml:"range end,omitempty"`
SystemdName string `yaml:"systemd name" default:"dhcpd"`
}

View File

@@ -0,0 +1,10 @@
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"`
Options string `yaml:"options,omitempty"` // ignored at the moment
}

View File

@@ -0,0 +1,35 @@
package config
import (
"github.com/creasty/defaults"
)
// NFSConf represents the NFS configuration that will be used by
// Warewulf to generate exports on the server and mounts on compute
// nodes.
type NFSConf struct {
Enabled bool `yaml:"enabled" default:"true"`
ExportsExtended []*NFSExportConf `yaml:"export paths" default:"[]"`
SystemdName string `yaml:"systemd name" default:"nfsd"`
}
// An NFSExportConf reprents a single NFS export / mount.
type NFSExportConf struct {
Path string `yaml:"path" default:"/dev/null"`
ExportOptions string `default:"rw,sync,no_subtree_check" yaml:"export options"`
MountOptions string `default:"defaults" yaml:"mount options"`
Mount bool `default:"true" yaml:"mount"`
}
// Implements the Unmarshal interface for NFSConf to set default
// values.
func (conf *NFSConf) Unmarshal(unmarshal func(interface{}) error) error {
if err := defaults.Set(conf); err != nil {
return err
}
return nil
}

View File

@@ -26,7 +26,7 @@ var cachedConf RootConf
// RootConf is the main Warewulf configuration structure. It stores // RootConf is the main Warewulf configuration structure. It stores
// some information about the Warewulf server locally, and has // some information about the Warewulf server locally, and has
// [WarewulfConf], [DhcpConf], [TftpConf], and [NfsConf] sub-sections. // [WarewulfConf], [DHCPConf], [TFTPConf], and [NFSConf] sub-sections.
type RootConf struct { type RootConf struct {
WWInternal int `yaml:"WW_INTERNAL"` WWInternal int `yaml:"WW_INTERNAL"`
Comment string `yaml:"comment,omitempty"` Comment string `yaml:"comment,omitempty"`
@@ -37,9 +37,9 @@ type RootConf struct {
Ipv6net string `yaml:"ipv6net,omitempty"` Ipv6net string `yaml:"ipv6net,omitempty"`
Fqdn string `yaml:"fqdn,omitempty"` Fqdn string `yaml:"fqdn,omitempty"`
Warewulf *WarewulfConf `yaml:"warewulf"` Warewulf *WarewulfConf `yaml:"warewulf"`
Dhcp *DhcpConf `yaml:"dhcp"` DHCP *DHCPConf `yaml:"dhcp"`
Tftp *TftpConf `yaml:"tftp"` TFTP *TFTPConf `yaml:"tftp"`
Nfs *NfsConf `yaml:"nfs"` NFS *NFSConf `yaml:"nfs"`
MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"` MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"`
Paths *BuildConfig `yaml:"paths"` Paths *BuildConfig `yaml:"paths"`
@@ -53,9 +53,9 @@ func New() (*RootConf) {
cachedConf = RootConf{} cachedConf = RootConf{}
cachedConf.fromFile = false cachedConf.fromFile = false
cachedConf.Warewulf = new(WarewulfConf) cachedConf.Warewulf = new(WarewulfConf)
cachedConf.Dhcp = new(DhcpConf) cachedConf.DHCP = new(DHCPConf)
cachedConf.Tftp = new(TftpConf) cachedConf.TFTP = new(TFTPConf)
cachedConf.Nfs = new(NfsConf) cachedConf.NFS = new(NFSConf)
cachedConf.Paths = new(BuildConfig) cachedConf.Paths = new(BuildConfig)
if err := defaults.Set(&cachedConf); err != nil { if err := defaults.Set(&cachedConf); err != nil {
panic(err) panic(err)
@@ -95,15 +95,15 @@ func (conf *RootConf) Read(confFileName string) (error) {
func (conf *RootConf) Parse(data []byte) (error) { func (conf *RootConf) Parse(data []byte) (error) {
// ipxe binaries are merged not overwritten, store defaults separate // ipxe binaries are merged not overwritten, store defaults separate
defIpxe := make(map[string]string) defIpxe := make(map[string]string)
for k, v := range conf.Tftp.IpxeBinaries { for k, v := range conf.TFTP.IPXEBinaries {
defIpxe[k] = v defIpxe[k] = v
delete(conf.Tftp.IpxeBinaries, k) delete(conf.TFTP.IPXEBinaries, k)
} }
if err := yaml.Unmarshal(data, &conf); err != nil { if err := yaml.Unmarshal(data, &conf); err != nil {
return err return err
} }
if len(conf.Tftp.IpxeBinaries) == 0 { if len(conf.TFTP.IPXEBinaries) == 0 {
conf.Tftp.IpxeBinaries = defIpxe conf.TFTP.IPXEBinaries = defIpxe
} }
return nil return nil
} }
@@ -141,14 +141,14 @@ func (conf *RootConf) SetDynamicDefaults() (err error) {
wwlog.Verbose("Network is not configured in warewulf.conf, using %s", conf.Network) wwlog.Verbose("Network is not configured in warewulf.conf, using %s", conf.Network)
} }
} }
if conf.Dhcp.RangeStart == "" && conf.Dhcp.RangeEnd == "" { if conf.DHCP.RangeStart == "" && conf.DHCP.RangeEnd == "" {
start := net.ParseIP(conf.Network).To4() start := net.ParseIP(conf.Network).To4()
start[3] += 1 start[3] += 1
if start.Equal(net.ParseIP(conf.Ipaddr)) { if start.Equal(net.ParseIP(conf.Ipaddr)) {
start[3] += 1 start[3] += 1
} }
conf.Dhcp.RangeStart = start.String() conf.DHCP.RangeStart = start.String()
wwlog.Verbose("dhpd start is not configured in warewulf.conf, using %s", conf.Dhcp.RangeStart) wwlog.Verbose("dhpd start is not configured in warewulf.conf, using %s", conf.DHCP.RangeStart)
sz, _ := net.IPMask(net.ParseIP(conf.Netmask).To4()).Size() sz, _ := net.IPMask(net.ParseIP(conf.Netmask).To4()).Size()
range_end := (1 << (32 - sz)) / 8 range_end := (1 << (32 - sz)) / 8
if range_end > 127 { if range_end > 127 {
@@ -156,8 +156,8 @@ func (conf *RootConf) SetDynamicDefaults() (err error) {
} }
end := net.ParseIP(conf.Network).To4() end := net.ParseIP(conf.Network).To4()
end[3] += byte(range_end) end[3] += byte(range_end)
conf.Dhcp.RangeEnd = end.String() conf.DHCP.RangeEnd = end.String()
wwlog.Verbose("dhpd end is not configured in warewulf.conf, using %s", conf.Dhcp.RangeEnd) wwlog.Verbose("dhpd end is not configured in warewulf.conf, using %s", conf.DHCP.RangeEnd)
} }
// check validity of ipv6 net // check validity of ipv6 net

View File

@@ -0,0 +1,13 @@
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"`
// Path is relative to buildconfig.DATADIR()
IPXEBinaries map[string]string `yaml:"ipxe" default:"{\"00:09\": \"x86_64.efi\",\"00:00\": \"x86_64.kpxe\",\"00:0B\": \"arm64.efi\",\"00:07\": \"x86_64.efi\"}"`
}

View File

@@ -0,0 +1,14 @@
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"`
}

View File

@@ -15,21 +15,21 @@ import (
Configures the dhcpd server, when show is set to false, else the Configures the dhcpd server, when show is set to false, else the
dhcp configuration is checked. dhcp configuration is checked.
*/ */
func Dhcp() (err error) { func DHCP() (err error) {
controller := warewulfconf.Get() controller := warewulfconf.Get()
if !controller.Dhcp.Enabled { if !controller.DHCP.Enabled {
wwlog.Info("This system is not configured as a Warewulf DHCP controller") wwlog.Info("This system is not configured as a Warewulf DHCP controller")
os.Exit(1) os.Exit(1)
} }
if controller.Dhcp.RangeStart == "" { if controller.DHCP.RangeStart == "" {
wwlog.Error("Configuration is not defined: `dhcpd range start`") wwlog.Error("Configuration is not defined: `dhcpd range start`")
os.Exit(1) os.Exit(1)
} }
if controller.Dhcp.RangeEnd == "" { if controller.DHCP.RangeEnd == "" {
wwlog.Error("Configuration is not defined: `dhcpd range end`") wwlog.Error("Configuration is not defined: `dhcpd range end`")
os.Exit(1) os.Exit(1)
} }
@@ -42,7 +42,7 @@ func Dhcp() (err error) {
wwlog.Info("host overlays are disabled, did not modify/create dhcpd configuration") wwlog.Info("host overlays are disabled, did not modify/create dhcpd configuration")
} }
fmt.Printf("Enabling and restarting the DHCP services\n") fmt.Printf("Enabling and restarting the DHCP services\n")
err = util.SystemdStart(controller.Dhcp.SystemdName) err = util.SystemdStart(controller.DHCP.SystemdName)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to start") return errors.Wrap(err, "failed to start")
} }

View File

@@ -18,7 +18,7 @@ func NFS() error {
controller := warewulfconf.Get() controller := warewulfconf.Get()
if controller.Nfs.Enabled { if controller.NFS.Enabled {
if controller.Warewulf.EnableHostOverlay { if controller.Warewulf.EnableHostOverlay {
err := overlay.BuildHostOverlay() err := overlay.BuildHostOverlay()
if err != nil { if err != nil {
@@ -28,13 +28,13 @@ func NFS() error {
wwlog.Info("host overlays are disabled, did not modify exports") wwlog.Info("host overlays are disabled, did not modify exports")
} }
fmt.Printf("Enabling and restarting the NFS services\n") fmt.Printf("Enabling and restarting the NFS services\n")
if controller.Nfs.SystemdName == "" { if controller.NFS.SystemdName == "" {
err := util.SystemdStart("nfs-server") err := util.SystemdStart("nfs-server")
if err != nil { if err != nil {
return errors.Wrap(err, "failed to start nfs-server") return errors.Wrap(err, "failed to start nfs-server")
} }
} else { } else {
err := util.SystemdStart(controller.Nfs.SystemdName) err := util.SystemdStart(controller.NFS.SystemdName)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to start") return errors.Wrap(err, "failed to start")
} }

View File

@@ -12,7 +12,7 @@ import (
func TFTP() error { func TFTP() error {
controller := warewulfconf.Get() controller := warewulfconf.Get()
var tftpdir string = path.Join(controller.Paths.Tftpdir, "warewulf") var tftpdir string = path.Join(controller.Paths.TFTPdir, "warewulf")
err := os.MkdirAll(tftpdir, 0755) err := os.MkdirAll(tftpdir, 0755)
if err != nil { if err != nil {
@@ -22,7 +22,7 @@ func TFTP() error {
fmt.Printf("Writing PXE files to: %s\n", tftpdir) fmt.Printf("Writing PXE files to: %s\n", tftpdir)
copyCheck := make(map[string]bool) copyCheck := make(map[string]bool)
for _, f := range controller.Tftp.IpxeBinaries { for _, f := range controller.TFTP.IPXEBinaries {
if copyCheck[f] { if copyCheck[f] {
continue continue
} }
@@ -33,13 +33,13 @@ func TFTP() error {
} }
} }
if !controller.Tftp.Enabled { if !controller.TFTP.Enabled {
wwlog.Info("Warewulf does not auto start TFTP services due to disable by warewulf.conf") wwlog.Info("Warewulf does not auto start TFTP services due to disable by warewulf.conf")
os.Exit(0) os.Exit(0)
} }
fmt.Printf("Enabling and restarting the TFTP services\n") fmt.Printf("Enabling and restarting the TFTP services\n")
err = util.SystemdStart(controller.Tftp.SystemdName) err = util.SystemdStart(controller.TFTP.SystemdName)
if err != nil { if err != nil {
wwlog.Error("%s", err) wwlog.Error("%s", err)
return err return err

View File

@@ -28,10 +28,10 @@ type TemplateStruct struct {
Network string Network string
NetworkCIDR string NetworkCIDR string
Ipv6 bool Ipv6 bool
Dhcp warewulfconf.DhcpConf Dhcp warewulfconf.DHCPConf
Nfs warewulfconf.NfsConf Nfs warewulfconf.NFSConf
Warewulf warewulfconf.WarewulfConf Warewulf warewulfconf.WarewulfConf
Tftp warewulfconf.TftpConf Tftp warewulfconf.TFTPConf
Paths warewulfconf.BuildConfig Paths warewulfconf.BuildConfig
AllNodes []node.NodeInfo AllNodes []node.NodeInfo
node.NodeConf node.NodeConf
@@ -60,9 +60,9 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct {
tstruct.Hostname = nodeInfo.Id.Get() tstruct.Hostname = nodeInfo.Id.Get()
// Backwards compatibility for templates using "Keys" // Backwards compatibility for templates using "Keys"
tstruct.AllNodes = allNodes tstruct.AllNodes = allNodes
tstruct.Nfs = *controller.Nfs tstruct.Nfs = *controller.NFS
tstruct.Dhcp = *controller.Dhcp tstruct.Dhcp = *controller.DHCP
tstruct.Tftp = *controller.Tftp tstruct.Tftp = *controller.TFTP
tstruct.Warewulf = *controller.Warewulf tstruct.Warewulf = *controller.Warewulf
tstruct.Ipaddr = controller.Ipaddr tstruct.Ipaddr = controller.Ipaddr
tstruct.Ipaddr6 = controller.Ipaddr6 tstruct.Ipaddr6 = controller.Ipaddr6