Merge pull request #781 from anderbubble/config-refactor

Refactor package that handles warewulf.conf
This commit is contained in:
Jonathon Anderson
2023-04-26 13:56:03 -06:00
committed by GitHub
50 changed files with 552 additions and 380 deletions

4
.gitignore vendored
View File

@@ -25,10 +25,10 @@
/etc/bash_completion.d/
warewulf.spec
internal/pkg/buildconfig/setconfigs.go
internal/pkg/warewulfconf/buildconfig.go
internal/pkg/config/buildconfig.go
include/systemd/warewulfd.service
_dist/
config
/config
warewulf-*.tar.gz
Defaults.mk
/etc/wwapid.config

View File

@@ -151,7 +151,7 @@ vet:
go vet ./...
test-it:
go test -v ./... -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=$(shell pwd)/etc/warewulf.conf'"
go test -v ./...
# Generate test coverage
test-cover: ## Run test coverage and generate html report
@@ -219,13 +219,12 @@ init:
wwctl: $(WWCTL_DEPS)
@echo Building "$@"
@cd cmd/wwctl; GOOS=linux go build -mod vendor -tags "$(WW_GO_BUILD_TAGS)" \
-ldflags "-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=$(SYSCONFDIR)/warewulf/warewulf.conf'" \
-o ../../wwctl
wwclient: $(WWCLIENT_DEPS)
@echo Building "$@"
@cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags "-extldflags -static \
-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=/etc/warewulf/warewulf.conf'" -o ../../wwclient
@cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags "-extldflags -static" \
-o ../../wwclient
man_pages: wwctl
@install -d man_pages
@@ -235,7 +234,7 @@ man_pages: wwctl
@cd man_pages; for i in wwctl*1 *.5; do gzip --force $$i; echo -n "$$i "; done; echo
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'\
cd cmd/update_configuration && go build \
-X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\
-mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../update_configuration

View File

@@ -12,7 +12,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/api/apiconfig"
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@@ -24,7 +24,7 @@ import (
func main() {
log.Println("Client running")
conf := warewulfconf.New()
conf := warewulfconf.Get()
// Read the config file.
config, err := apiconfig.NewClient(path.Join(conf.Paths.Sysconfdir, "warewulf/wwapic.conf"))

View File

@@ -16,7 +16,7 @@ import (
apinode "github.com/hpcng/warewulf/internal/pkg/api/node"
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/version"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
@@ -34,7 +34,7 @@ var apiVersion string
func main() {
log.Println("Server running")
conf := warewulfconf.New()
conf := warewulfconf.Get()
// Read the config file.
config, err := apiconfig.NewServer(path.Join(conf.Paths.Sysconfdir, "warewulf/wwapid.conf"))
if err != nil {

View File

@@ -18,7 +18,7 @@ import (
"google.golang.org/grpc/credentials/insecure"
"github.com/hpcng/warewulf/internal/pkg/api/apiconfig"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
gw "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
@@ -29,7 +29,7 @@ func run() error {
log.Println("test0")
conf := warewulfconf.New()
conf := warewulfconf.Get()
// Read the config file.
config, err := apiconfig.NewClientServer(path.Join(conf.Paths.Sysconfdir, "warewulf/wwapird.conf"))
if err != nil {

View File

@@ -17,7 +17,7 @@ import (
"github.com/coreos/go-systemd/daemon"
"github.com/google/uuid"
"github.com/hpcng/warewulf/internal/pkg/pidfile"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"github.com/talos-systems/go-smbios/smbios"
@@ -49,7 +49,7 @@ func GetRootCommand() *cobra.Command {
}
func CobraRunE(cmd *cobra.Command, args []string) error {
conf := warewulfconf.New()
conf := warewulfconf.Get()
pid, err := pidfile.Write(PIDFile)
if err != nil && pid == -1 {

View File

@@ -6,5 +6,5 @@ import (
)
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 {
var err error
if allFunctions {
err = configure.Dhcp()
err = configure.DHCP()
if err != nil {
wwlog.Error("%s", err)
os.Exit(1)

View File

@@ -15,7 +15,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -33,7 +33,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
wwlog.Error("Unknown Warewulf container: %s", containerName)
os.Exit(1)
}
conf := warewulfconf.New()
conf := warewulfconf.Get()
mountPts := conf.MountsContainer
mountPts = append(container.InitMountPnts(binds), mountPts...)
// check for valid mount points

View File

@@ -10,7 +10,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/stretchr/testify/assert"
)
@@ -55,8 +55,8 @@ nodes:
WW_INTERNAL: 0
`
conf := warewulfconf.New()
err := conf.Read([]byte(conf_yml))
conf := warewulfconf.Get()
err := conf.Parse([]byte(conf_yml))
assert.NoError(t, err)
warewulfd.SetNoDaemon()
for _, tt := range tests {

View File

@@ -3,13 +3,13 @@ package print
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
)
func CobraRunE(cmd *cobra.Command, args []string) (err error) {
conf := warewulfconf.New()
conf := warewulfconf.Get()
buffer, err := yaml.Marshal(&conf)
if err != nil {
return

View File

@@ -6,7 +6,7 @@ import (
"testing"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/stretchr/testify/assert"
)
@@ -243,7 +243,7 @@ nodes:
_, warewulfConfErr = tempWarewulfConf.Write([]byte(conf_yml))
assert.NoError(t, warewulfConfErr)
assert.NoError(t, tempWarewulfConf.Sync())
warewulfconf.ConfigFile = tempWarewulfConf.Name()
assert.NoError(t, warewulfconf.New().Read(tempWarewulfConf.Name()))
nodes_yml := `WW_INTERNAL: 43`
tempNodeConf, nodesConfErr := os.CreateTemp("", "nodes.conf-")

View File

@@ -7,7 +7,7 @@ import (
"testing"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/stretchr/testify/assert"
)
@@ -42,7 +42,7 @@ nodes:
_, warewulfConfErr = tempWarewulfConf.Write([]byte(conf_yml))
assert.NoError(t, warewulfConfErr)
assert.NoError(t, tempWarewulfConf.Sync())
warewulfconf.ConfigFile = tempWarewulfConf.Name()
assert.NoError(t, warewulfconf.New().Read(tempWarewulfConf.Name()))
tempNodeConf, nodesConfErr := os.CreateTemp("", "nodes.conf-")
assert.NoError(t, nodesConfErr)

View File

@@ -9,7 +9,7 @@ import (
"github.com/fatih/color"
apinode "github.com/hpcng/warewulf/internal/pkg/api/node"
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/pkg/hostlist"
"github.com/spf13/cobra"
@@ -18,7 +18,7 @@ import (
func CobraRunE(cmd *cobra.Command, args []string) (err error) {
controller := warewulfconf.New()
controller := warewulfconf.Get()
if controller.Ipaddr == "" {
return fmt.Errorf("warewulf Server IP Address is not properly configured")

View File

@@ -7,14 +7,14 @@ import (
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/pkg/hostlist"
"github.com/spf13/cobra"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
controller := warewulfconf.New()
controller := warewulfconf.Get()
nodeDB, err := node.New()
if err != nil {
wwlog.Error("Could not open node configuration: %s", err)

View File

@@ -6,7 +6,7 @@ import (
"testing"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/stretchr/testify/assert"
)

View File

@@ -8,7 +8,7 @@ import (
"testing"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/stretchr/testify/assert"
)
@@ -43,7 +43,7 @@ nodes:
_, warewulfConfErr = tempWarewulfConf.Write([]byte(conf_yml))
assert.NoError(t, warewulfConfErr)
assert.NoError(t, tempWarewulfConf.Sync())
warewulfconf.ConfigFile = tempWarewulfConf.Name()
assert.NoError(t, warewulfconf.New().Read(tempWarewulfConf.Name()))
tempNodeConf, nodesConfErr := os.CreateTemp("", "nodes.conf-")
assert.NoError(t, nodesConfErr)

View File

@@ -15,7 +15,7 @@ import (
"github.com/hpcng/warewulf/internal/app/wwctl/ssh"
"github.com/hpcng/warewulf/internal/app/wwctl/version"
"github.com/hpcng/warewulf/internal/pkg/help"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
)
@@ -76,17 +76,19 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) (err error) {
if LogLevel != wwlog.INFO {
wwlog.SetLogLevel(LogLevel)
}
conf := warewulfconf.New()
if !AllowEmptyConf && !conf.Initialized() {
conf := warewulfconf.Get()
if !AllowEmptyConf && !conf.InitializedFromFile() {
if WarewulfConfArg != "" {
err = conf.ReadConf(WarewulfConfArg)
err = conf.Read(WarewulfConfArg)
} else if os.Getenv("WAREWULFCONF") != "" {
err = conf.ReadConf(os.Getenv("WAREWULFCONF"))
err = conf.Read(os.Getenv("WAREWULFCONF"))
} else {
err = conf.ReadConf(warewulfconf.ConfigFile)
err = conf.Read(warewulfconf.ConfigFile)
}
} else {
err = conf.SetDynamicDefaults()
}
if err != nil {
return
}
err = conf.SetDynamicDefaults()
return
}

View File

@@ -1,7 +1,7 @@
package start
import (
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -10,7 +10,7 @@ import (
func CobraRunE(cmd *cobra.Command, args []string) error {
if SetForeground {
conf := warewulfconf.New()
conf := warewulfconf.Get()
conf.Warewulf.Syslog = false
return errors.Wrap(warewulfd.RunServer(), "failed to start Warewulf server")
} else {

View File

@@ -10,7 +10,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/pkg/hostlist"
"github.com/pkg/errors"
@@ -317,7 +317,7 @@ func NodeStatus(nodeNames []string) (nodeStatusResponse *wwapiv1.NodeStatusRespo
Nodes map[string]*nodeStatusInternal `json:"nodes"`
}
controller := warewulfconf.New()
controller := warewulfconf.Get()
if controller.Ipaddr == "" {
err = fmt.Errorf("the Warewulf Server IP Address is not properly configured")

View File

@@ -1,4 +1,6 @@
package warewulfconf
package config
var ConfigFile = "@SYSCONFDIR@/warewulf/warewulf.conf"
type BuildConfig struct {
Bindir string `default:"@BINDIR@"`

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
}

183
internal/pkg/config/root.go Normal file
View File

@@ -0,0 +1,183 @@
// Package config reads, parses, and represents the warewulf.conf
// config file.
//
// warewulf.conf is a yaml-formatted configuration file that includes
// configuration for the Warewulf daemon and commands, as well as the
// DHCP, TFTP and NFS services that Warewulf manages.
package config
import (
"fmt"
"net"
"os"
"reflect"
"github.com/pkg/errors"
"github.com/creasty/defaults"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
)
var cachedConf RootConf
// RootConf is the main Warewulf configuration structure. It stores
// some information about the Warewulf server locally, and has
// [WarewulfConf], [DHCPConf], [TFTPConf], and [NFSConf] sub-sections.
type RootConf struct {
WWInternal int `yaml:"WW_INTERNAL"`
Comment string `yaml:"comment,omitempty"`
Ipaddr string `yaml:"ipaddr"`
Ipaddr6 string `yaml:"ipaddr6,omitempty"`
Netmask string `yaml:"netmask"`
Network string `yaml:"network,omitempty"`
Ipv6net string `yaml:"ipv6net,omitempty"`
Fqdn string `yaml:"fqdn,omitempty"`
Warewulf *WarewulfConf `yaml:"warewulf"`
DHCP *DHCPConf `yaml:"dhcp"`
TFTP *TFTPConf `yaml:"tftp"`
NFS *NFSConf `yaml:"nfs"`
MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"`
Paths *BuildConfig `yaml:"paths"`
fromFile bool
}
// New caches and returns a new [RootConf] initialized with empty
// values, clearing replacing any previously cached value.
func New() (*RootConf) {
cachedConf = RootConf{}
cachedConf.fromFile = false
cachedConf.Warewulf = new(WarewulfConf)
cachedConf.DHCP = new(DHCPConf)
cachedConf.TFTP = new(TFTPConf)
cachedConf.NFS = new(NFSConf)
cachedConf.Paths = new(BuildConfig)
if err := defaults.Set(&cachedConf); err != nil {
panic(err)
}
return &cachedConf
}
// Get returns a previously cached [RootConf] if it exists, or returns
// a new RootConf.
func Get() (*RootConf) {
// NOTE: This function can be called before any log level is set
// so using wwlog.Verbose or wwlog.Debug won't work
if reflect.ValueOf(cachedConf).IsZero() {
cachedConf = *New()
}
return &cachedConf
}
// Read populates [RootConf] with the values from a configuration
// file.
func (conf *RootConf) Read(confFileName string) (error) {
wwlog.Debug("Reading warewulf.conf from: %s", confFileName)
if data, err := os.ReadFile(confFileName); err != nil {
return err
} else if err := conf.Parse(data); err != nil {
return err
} else {
conf.fromFile = true
return nil
}
}
// Parse populates [RootConf] with the values from a yaml document.
func (conf *RootConf) Parse(data []byte) (error) {
// ipxe binaries are merged not overwritten, store defaults separate
defIpxe := make(map[string]string)
for k, v := range conf.TFTP.IpxeBinaries {
defIpxe[k] = v
delete(conf.TFTP.IpxeBinaries, k)
}
if err := yaml.Unmarshal(data, &conf); err != nil {
return err
}
if len(conf.TFTP.IpxeBinaries) == 0 {
conf.TFTP.IpxeBinaries = defIpxe
}
return nil
}
// SetDynamicDefaults populates [RootConf] with plausible defaults for
// the runtime environment.
func (conf *RootConf) SetDynamicDefaults() (err error) {
if conf.Ipaddr == "" || conf.Netmask == "" || conf.Network == "" {
var mask net.IPMask
var network *net.IPNet
var ipaddr net.IP
if conf.Ipaddr == "" {
wwlog.Verbose("Configuration has no valid network, going to dynamic values")
conn, _ := net.Dial("udp", "8.8.8.8:80")
defer conn.Close()
ipaddr = conn.LocalAddr().(*net.UDPAddr).IP
mask = ipaddr.DefaultMask()
sz, _ := mask.Size()
conf.Ipaddr = ipaddr.String() + fmt.Sprintf("/%d", sz)
}
_, network, err = net.ParseCIDR(conf.Ipaddr)
if err == nil {
mask = network.Mask
} else {
return errors.Wrap(err, "Couldn't parse IP address")
}
if conf.Netmask == "" {
conf.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
wwlog.Verbose("Netmask address is not configured in warewulf.conf, using %s", conf.Netmask)
}
if conf.Network == "" {
conf.Network = network.IP.String()
wwlog.Verbose("Network is not configured in warewulf.conf, using %s", conf.Network)
}
}
if conf.DHCP.RangeStart == "" && conf.DHCP.RangeEnd == "" {
start := net.ParseIP(conf.Network).To4()
start[3] += 1
if start.Equal(net.ParseIP(conf.Ipaddr)) {
start[3] += 1
}
conf.DHCP.RangeStart = start.String()
wwlog.Verbose("dhpd start is not configured in warewulf.conf, using %s", conf.DHCP.RangeStart)
sz, _ := net.IPMask(net.ParseIP(conf.Netmask).To4()).Size()
range_end := (1 << (32 - sz)) / 8
if range_end > 127 {
range_end = 127
}
end := net.ParseIP(conf.Network).To4()
end[3] += byte(range_end)
conf.DHCP.RangeEnd = end.String()
wwlog.Verbose("dhpd end is not configured in warewulf.conf, using %s", conf.DHCP.RangeEnd)
}
// check validity of ipv6 net
if conf.Ipaddr6 != "" {
_, ipv6net, err := net.ParseCIDR(conf.Ipaddr6)
if err != nil {
wwlog.Error("Invalid ipv6 address specified, mut be CIDR notation: %s", conf.Ipaddr6)
return errors.New("invalid ipv6 network")
}
if msize, _ := ipv6net.Mask.Size(); msize > 64 {
wwlog.Error("ipv6 mask size must be smaller than 64")
return errors.New("invalid ipv6 network size")
}
}
return
}
// InitializedFromFile returns true if [RootConf] memory was read from
// a file, or false otherwise.
func (conf *RootConf) InitializedFromFile() bool {
return conf.fromFile
}

View File

@@ -0,0 +1,174 @@
package config
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestDefaultRootConf(t *testing.T) {
conf := New()
assert.Equal(t, 9983, conf.Warewulf.Port)
assert.True(t, conf.Warewulf.Secure)
assert.Equal(t, 60, conf.Warewulf.UpdateInterval)
assert.True(t, conf.Warewulf.AutobuildOverlays)
assert.True(t, conf.Warewulf.EnableHostOverlay)
assert.False(t, conf.Warewulf.Syslog)
assert.NotEmpty(t, conf.Warewulf.DataStore)
assert.True(t, conf.DHCP.Enabled)
assert.Equal(t, "default", conf.DHCP.Template)
assert.Empty(t, conf.DHCP.RangeStart)
assert.Empty(t, conf.DHCP.RangeEnd)
assert.Equal(t, "dhcpd", conf.DHCP.SystemdName)
assert.True(t, conf.TFTP.Enabled)
assert.NotEmpty(t, conf.TFTP.TftpRoot)
assert.Equal(t, "tftp", conf.TFTP.SystemdName)
assert.NotEmpty(t, conf.TFTP.IpxeBinaries["00:00"])
assert.NotEmpty(t, conf.TFTP.IpxeBinaries["00:07"])
assert.NotEmpty(t, conf.TFTP.IpxeBinaries["00:09"])
assert.NotEmpty(t, conf.TFTP.IpxeBinaries["00:0B"])
assert.True(t, conf.NFS.Enabled)
assert.Empty(t, conf.NFS.ExportsExtended)
assert.Equal(t, "nfsd", conf.NFS.SystemdName)
assert.Equal(t, "/etc/resolv.conf", conf.MountsContainer[0].Source)
assert.Equal(t, "/etc/resolv.conf", conf.MountsContainer[0].Dest)
assert.False(t, conf.MountsContainer[0].ReadOnly)
assert.Empty(t, conf.MountsContainer[0].Options)
assert.NotEmpty(t, conf.Paths.Bindir)
assert.NotEmpty(t, conf.Paths.Sysconfdir)
assert.NotEmpty(t, conf.Paths.Datadir)
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)
assert.NotEmpty(t, conf.Paths.WWChrootdir)
assert.NotEmpty(t, conf.Paths.WWProvisiondir)
assert.NotEmpty(t, conf.Paths.Version)
assert.NotEmpty(t, conf.Paths.Release)
assert.NotEmpty(t, conf.Paths.WWClientdir)
}
func TestInitializedFromFile(t *testing.T) {
example_warewulf_conf := "WW_INTERNAL: 43"
tempWarewulfConf, warewulfConfErr := os.CreateTemp("", "warewulf.conf-")
assert.NoError(t, warewulfConfErr)
defer os.Remove(tempWarewulfConf.Name())
_, warewulfConfErr = tempWarewulfConf.Write([]byte(example_warewulf_conf))
assert.NoError(t, warewulfConfErr)
assert.NoError(t, tempWarewulfConf.Sync())
conf := New()
assert.False(t, conf.InitializedFromFile())
assert.NoError(t, conf.Read(tempWarewulfConf.Name()))
assert.True(t, conf.InitializedFromFile())
}
func TestExampleRootConf(t *testing.T) {
example_warewulf_conf := `WW_INTERNAL: 43
ipaddr: 192.168.200.1
netmask: 255.255.255.0
network: 192.168.200.0
warewulf:
port: 9873
secure: false
update interval: 60
autobuild overlays: true
host overlay: true
syslog: false
dhcp:
enabled: true
range start: 192.168.200.50
range end: 192.168.200.99
systemd name: dhcpd
tftp:
enabled: true
systemd name: tftp
nfs:
enabled: true
export paths:
- path: /home
export options: rw,sync
mount options: defaults
mount: true
- path: /opt
export options: ro,sync,no_root_squash
mount options: defaults
mount: false
systemd name: nfs-server
container mounts:
- source: /etc/resolv.conf
dest: /etc/resolv.conf
readonly: true`
tempWarewulfConf, warewulfConfErr := os.CreateTemp("", "warewulf.conf-")
assert.NoError(t, warewulfConfErr)
defer os.Remove(tempWarewulfConf.Name())
_, warewulfConfErr = tempWarewulfConf.Write([]byte(example_warewulf_conf))
assert.NoError(t, warewulfConfErr)
assert.NoError(t, tempWarewulfConf.Sync())
conf := New()
assert.NoError(t, conf.Read(tempWarewulfConf.Name()))
assert.Equal(t, "192.168.200.1", conf.Ipaddr)
assert.Equal(t, "255.255.255.0", conf.Netmask)
assert.Equal(t, "192.168.200.0", conf.Network)
assert.Equal(t, 9873, conf.Warewulf.Port)
assert.False(t, conf.Warewulf.Secure)
assert.Equal(t, 60, conf.Warewulf.UpdateInterval)
assert.True(t, conf.Warewulf.AutobuildOverlays)
assert.True(t, conf.Warewulf.EnableHostOverlay)
assert.False(t, conf.Warewulf.Syslog)
assert.True(t, conf.DHCP.Enabled)
assert.Equal(t, "192.168.200.50", conf.DHCP.RangeStart)
assert.Equal(t, "192.168.200.99", conf.DHCP.RangeEnd)
assert.Equal(t, "dhcpd", conf.DHCP.SystemdName)
assert.True(t, conf.TFTP.Enabled)
assert.Equal(t, "tftp", conf.TFTP.SystemdName)
assert.True(t, conf.NFS.Enabled)
assert.Equal(t, "/home", conf.NFS.ExportsExtended[0].Path)
assert.Equal(t, "rw,sync", conf.NFS.ExportsExtended[0].ExportOptions)
assert.Equal(t, "defaults", conf.NFS.ExportsExtended[0].MountOptions)
assert.True(t, conf.NFS.ExportsExtended[0].Mount)
assert.Equal(t, "/opt", conf.NFS.ExportsExtended[1].Path)
assert.Equal(t, "ro,sync,no_root_squash", conf.NFS.ExportsExtended[1].ExportOptions)
assert.Equal(t, "defaults", conf.NFS.ExportsExtended[1].MountOptions)
assert.False(t, conf.NFS.ExportsExtended[1].Mount)
assert.Equal(t, "nfs-server", conf.NFS.SystemdName)
assert.Equal(t, "/etc/resolv.conf", conf.MountsContainer[0].Source)
assert.Equal(t, "/etc/resolv.conf", conf.MountsContainer[0].Dest)
assert.True(t, conf.MountsContainer[0].ReadOnly)
}
func TestCache(t *testing.T) {
confOrig := New()
confCached := Get()
assert.Equal(t, 9983, confOrig.Warewulf.Port)
assert.Equal(t, 9983, confCached.Warewulf.Port)
confOrig.Warewulf.Port = 9999
assert.Equal(t, 9999, confCached.Warewulf.Port)
assert.Equal(t, 9999, Get().Warewulf.Port)
New()
assert.NotEqual(t, 9999, Get().Warewulf.Port)
}

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\": \"ipxe/ipxe-snponly-x86_64.efi\",\"00:00\": \"ipxe/undionly.kpxe\",\"00:0B\": \"ipxe/arm64-efi/snponly.efi\",\"00:07\": \"ipxe/ipxe-snponly-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

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

View File

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

View File

@@ -6,7 +6,7 @@ import (
"path"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/pkg/errors"
)
@@ -14,7 +14,7 @@ import (
func SSH() error {
if os.Getuid() == 0 {
fmt.Printf("Updating system keys\n")
conf := warewulfconf.New()
conf := warewulfconf.Get()
wwkeydir := path.Join(conf.Paths.Sysconfdir, "warewulf/keys") + "/"
err := os.MkdirAll(path.Join(conf.Paths.Sysconfdir, "warewulf/keys"), 0755)

View File

@@ -6,12 +6,12 @@ import (
"path"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
func TFTP() error {
controller := warewulfconf.New()
controller := warewulfconf.Get()
var tftpdir string = path.Join(controller.Paths.Tftpdir, "warewulf")
err := os.MkdirAll(tftpdir, 0755)
@@ -22,24 +22,24 @@ func TFTP() error {
fmt.Printf("Writing PXE files to: %s\n", tftpdir)
copyCheck := make(map[string]bool)
for _, f := range controller.Tftp.IpxeBinaries {
for _, f := range controller.TFTP.IpxeBinaries {
if copyCheck[f] {
continue
}
copyCheck[f] = true
err = util.SafeCopyFile(path.Join(controller.Paths.Datadir, f), path.Join(tftpdir, f))
err = util.SafeCopyFile(path.Join(controller.Paths.Datadir, f), path.Join(tftpdir, path.Base(f)))
if err != nil {
wwlog.Warn("ipxe binary could not be copied, booting may not work: %s", err)
}
}
if !controller.Tftp.Enabled {
if !controller.TFTP.Enabled {
wwlog.Info("Warewulf does not auto start TFTP services due to disable by warewulf.conf")
os.Exit(0)
}
fmt.Printf("Enabling and restarting the TFTP services\n")
err = util.SystemdStart(controller.Tftp.SystemdName)
err = util.SystemdStart(controller.TFTP.SystemdName)
if err != nil {
wwlog.Error("%s", err)
return err

View File

@@ -3,11 +3,11 @@ package container
import (
"path"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
)
func SourceParentDir() string {
conf := warewulfconf.New()
conf := warewulfconf.Get()
return conf.Paths.WWChrootdir
}
@@ -20,7 +20,7 @@ func RootFsDir(name string) string {
}
func ImageParentDir() string {
conf := warewulfconf.New()
conf := warewulfconf.Get()
return path.Join(conf.Paths.WWProvisiondir, "container/")
}

View File

@@ -9,13 +9,13 @@ import (
"github.com/containers/storage/drivers/copy"
"github.com/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/oci"
"github.com/hpcng/warewulf/internal/pkg/util"
)
func ImportDocker(uri string, name string, sCtx *types.SystemContext) error {
OciBlobCacheDir := warewulfconf.DataStore() + "/oci"
OciBlobCacheDir := warewulfconf.Get().Warewulf.DataStore + "/oci"
err := os.MkdirAll(OciBlobCacheDir, 0755)
if err != nil {

View File

@@ -3,7 +3,7 @@ package container
import (
"strings"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)

View File

@@ -12,7 +12,7 @@ import (
"github.com/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
@@ -28,7 +28,7 @@ var (
)
func KernelImageTopDir() string {
conf := warewulfconf.New()
conf := warewulfconf.Get()
return path.Join(conf.Paths.WWProvisiondir, "kernel")
}

View File

@@ -8,7 +8,7 @@ import (
"sort"
"strings"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
@@ -41,7 +41,7 @@ defaultnode:
onboot: true`
func init() {
conf := warewulfconf.New()
conf := warewulfconf.Get()
if ConfigFile == "" {
ConfigFile = path.Join(conf.Paths.Sysconfdir, "warewulf/nodes.conf")
}

View File

@@ -1,11 +1,13 @@
package oci
import "github.com/hpcng/warewulf/internal/pkg/warewulfconf"
import "path/filepath"
import (
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"path/filepath"
)
var defaultCachePath = filepath.Join(warewulfconf.DataStore(), "/container-cache/oci/")
var defaultCachePath = filepath.Join(warewulfconf.Get().Warewulf.DataStore, "/container-cache/oci/")
const (
blobPrefix = "blobs"
rootfsPrefix = "rootfs"
)
)

View File

@@ -5,11 +5,11 @@ import (
"path"
"strings"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
)
func OverlaySourceTopDir() string {
conf := warewulfconf.New()
conf := warewulfconf.Get()
return conf.Paths.WWOverlaydir
}
@@ -31,6 +31,6 @@ func OverlaySourceDir(overlayName string) string {
Returns the overlay name of the image for a given node
*/
func OverlayImage(nodeName string, overlayName []string) string {
conf := warewulfconf.New()
conf := warewulfconf.Get()
return path.Join(conf.Paths.WWProvisiondir, "overlays/", nodeName, strings.Join(overlayName, "-")+".img")
}

View File

@@ -7,7 +7,7 @@ import (
"time"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
@@ -28,10 +28,10 @@ type TemplateStruct struct {
Network string
NetworkCIDR string
Ipv6 bool
Dhcp warewulfconf.DhcpConf
Nfs warewulfconf.NfsConf
Dhcp warewulfconf.DHCPConf
Nfs warewulfconf.NFSConf
Warewulf warewulfconf.WarewulfConf
Tftp warewulfconf.TftpConf
Tftp warewulfconf.TFTPConf
Paths warewulfconf.BuildConfig
AllNodes []node.NodeInfo
node.NodeConf
@@ -44,7 +44,7 @@ Initialize an TemplateStruct with the given node.NodeInfo
*/
func InitStruct(nodeInfo node.NodeInfo) TemplateStruct {
var tstruct TemplateStruct
controller := warewulfconf.New()
controller := warewulfconf.Get()
nodeDB, err := node.New()
if err != nil {
wwlog.Error("%s", err)
@@ -60,9 +60,9 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct {
tstruct.Hostname = nodeInfo.Id.Get()
// Backwards compatibility for templates using "Keys"
tstruct.AllNodes = allNodes
tstruct.Nfs = *controller.Nfs
tstruct.Dhcp = *controller.Dhcp
tstruct.Tftp = *controller.Tftp
tstruct.Nfs = *controller.NFS
tstruct.Dhcp = *controller.DHCP
tstruct.Tftp = *controller.TFTP
tstruct.Warewulf = *controller.Warewulf
tstruct.Ipaddr = controller.Ipaddr
tstruct.Ipaddr6 = controller.Ipaddr6

View File

@@ -8,7 +8,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/container"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
@@ -17,7 +17,7 @@ Reads a file file from the host fs. If the file has nor '/' prefix
the path is relative to Paths.SysconfdirTemplates in the file are no evaluated.
*/
func templateFileInclude(inc string) string {
conf := warewulfconf.New()
conf := warewulfconf.Get()
if !strings.HasPrefix(inc, "/") {
inc = path.Join(conf.Paths.Sysconfdir, "warewulf", inc)
}
@@ -35,7 +35,7 @@ is the file to read, the second the abort string
Templates in the file are no evaluated.
*/
func templateFileBlock(inc string, abortStr string) (string, error) {
conf := warewulfconf.New()
conf := warewulfconf.Get()
if !strings.HasPrefix(inc, "/") {
inc = path.Join(conf.Paths.Sysconfdir, "warewulf", inc)
}

View File

@@ -371,6 +371,7 @@ func RenderTemplateFile(fileName string, data TemplateStruct) (
"Include": templateFileInclude,
"IncludeFrom": templateContainerFileInclude,
"IncludeBlock": templateFileBlock,
"basename": path.Base,
"inc": func(i int) int { return i + 1 },
"dec": func(i int) int { return i - 1 },
"file": func(str string) string { return fmt.Sprintf("{{ /* file \"%s\" */ }}", str) },

View File

@@ -4,14 +4,14 @@ import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
)
/*
Return the version of wwctl
*/
func GetVersion() string {
conf := warewulfconf.New()
conf := warewulfconf.Get()
return fmt.Sprintf("%s-%s", conf.Paths.Version, conf.Paths.Release)
}

View File

@@ -1,156 +0,0 @@
package warewulfconf
import (
"fmt"
"net"
"os"
"github.com/pkg/errors"
"github.com/creasty/defaults"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
)
var cachedConf ControllerConf
var ConfigFile string
/*
Creates a new empty ControllerConf object, returns a cached
one if called in a nother context.
*/
func New() (conf ControllerConf) {
// NOTE: This function can be called before any log level is set
// so using wwlog.Verbose or wwlog.Debug won't work
if !cachedConf.current {
conf.Warewulf = new(WarewulfConf)
conf.Dhcp = new(DhcpConf)
conf.Tftp = new(TftpConf)
conf.Nfs = new(NfsConf)
conf.Paths = new(BuildConfig)
_ = defaults.Set(&conf)
cachedConf = conf
cachedConf.readConf = false
cachedConf.current = true
} else {
// If cached struct isn't empty, use it as the return value
conf = cachedConf
}
return conf
}
/*
Populate the configuration with the values from the configuration file.
*/
func (conf *ControllerConf) ReadConf(confFileName string) (err error) {
wwlog.Debug("Reading warewulf.conf from: %s", confFileName)
fileHandle, err := os.ReadFile(confFileName)
if err != nil {
return err
}
return conf.Read(fileHandle)
}
/*
Populate the configuration with the values from the given yaml information
*/
func (conf *ControllerConf) Read(data []byte) (err error) {
// ipxe binaries are merged not overwritten, store defaults separate
defIpxe := make(map[string]string)
for k, v := range conf.Tftp.IpxeBinaries {
defIpxe[k] = v
delete(conf.Tftp.IpxeBinaries, k)
}
err = yaml.Unmarshal(data, &conf)
if err != nil {
return
}
err = conf.SetDynamicDefaults()
if err != nil {
return
}
if len(conf.Tftp.IpxeBinaries) == 0 {
conf.Tftp.IpxeBinaries = defIpxe
}
cachedConf = *conf
cachedConf.current = true
cachedConf.readConf = true
return
}
/*
Set the runtime defaults like IP address of running system to the config
*/
func (conf *ControllerConf) SetDynamicDefaults() (err error) {
if conf.Ipaddr == "" || conf.Netmask == "" || conf.Network == "" {
var mask net.IPMask
var network *net.IPNet
var ipaddr net.IP
if conf.Ipaddr == "" {
wwlog.Verbose("Configuration has no valid network, going to dynamic values")
conn, _ := net.Dial("udp", "8.8.8.8:80")
defer conn.Close()
ipaddr = conn.LocalAddr().(*net.UDPAddr).IP
mask = ipaddr.DefaultMask()
sz, _ := mask.Size()
conf.Ipaddr = ipaddr.String() + fmt.Sprintf("/%d", sz)
}
_, network, err = net.ParseCIDR(conf.Ipaddr)
if err == nil {
mask = network.Mask
} else {
return errors.Wrap(err, "Couldn't parse IP address")
}
if conf.Netmask == "" {
conf.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
wwlog.Verbose("Netmask address is not configured in warewulf.conf, using %s", conf.Netmask)
}
if conf.Network == "" {
conf.Network = network.IP.String()
wwlog.Verbose("Network is not configured in warewulf.conf, using %s", conf.Network)
}
}
if conf.Dhcp.RangeStart == "" && conf.Dhcp.RangeEnd == "" {
start := net.ParseIP(conf.Network).To4()
start[3] += 1
if start.Equal(net.ParseIP(conf.Ipaddr)) {
start[3] += 1
}
conf.Dhcp.RangeStart = start.String()
wwlog.Verbose("dhpd start is not configured in warewulf.conf, using %s", conf.Dhcp.RangeStart)
sz, _ := net.IPMask(net.ParseIP(conf.Netmask).To4()).Size()
range_end := (1 << (32 - sz)) / 8
if range_end > 127 {
range_end = 127
}
end := net.ParseIP(conf.Network).To4()
end[3] += byte(range_end)
conf.Dhcp.RangeEnd = end.String()
wwlog.Verbose("dhpd end is not configured in warewulf.conf, using %s", conf.Dhcp.RangeEnd)
}
// check validity of ipv6 net
if conf.Ipaddr6 != "" {
_, ipv6net, err := net.ParseCIDR(conf.Ipaddr6)
if err != nil {
wwlog.Error("Invalid ipv6 address specified, mut be CIDR notation: %s", conf.Ipaddr6)
return errors.New("invalid ipv6 network")
}
if msize, _ := ipv6net.Mask.Size(); msize > 64 {
wwlog.Error("ipv6 mask size must be smaller than 64")
return errors.New("invalid ipv6 network size")
}
}
cachedConf = *conf
cachedConf.current = true
return
}
/*
Return if configuration was read from disk
*/
func (conf *ControllerConf) Initialized() bool {
return conf.readConf
}

View File

@@ -1,87 +0,0 @@
package warewulfconf
import (
"github.com/creasty/defaults"
)
type ControllerConf struct {
WWInternal int `yaml:"WW_INTERNAL"`
Comment string `yaml:"comment,omitempty"`
Ipaddr string `yaml:"ipaddr"`
Ipaddr6 string `yaml:"ipaddr6,omitempty"`
Netmask string `yaml:"netmask"`
Network string `yaml:"network,omitempty"`
Ipv6net string `yaml:"ipv6net,omitempty"`
Fqdn string `yaml:"fqdn,omitempty"`
Warewulf *WarewulfConf `yaml:"warewulf"`
Dhcp *DhcpConf `yaml:"dhcp"`
Tftp *TftpConf `yaml:"tftp"`
Nfs *NfsConf `yaml:"nfs"`
MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"`
Paths *BuildConfig `yaml:"paths"`
current bool
readConf bool
}
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
}
// Waste processor cycles to make code more readable
func DataStore() string {
_ = New()
return cachedConf.Warewulf.DataStore
}

View File

@@ -1,32 +0,0 @@
package warewulfconf
import (
"os"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
)
func (controller *ControllerConf) Persist() error {
out, err := yaml.Marshal(controller)
if err != nil {
return err
}
file, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
wwlog.Error("%s", err)
os.Exit(1)
}
defer file.Close()
_, err = file.WriteString(string(out)+"\n")
if err != nil {
wwlog.Error("Unable to write to warewulf.conf")
return err
}
return nil
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/version"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/pkg/errors"
)
@@ -61,7 +61,7 @@ func DaemonInitLogging() error {
wwlog.SetLogLevel(wwlog.SERV)
}
conf := warewulfconf.New()
conf := warewulfconf.Get()
if conf.Warewulf.Syslog {

View File

@@ -10,7 +10,7 @@ import (
"github.com/hpcng/warewulf/internal/pkg/container"
"github.com/hpcng/warewulf/internal/pkg/kernel"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
@@ -30,7 +30,7 @@ type iPxeTemplate struct {
}
func ProvisionSend(w http.ResponseWriter, req *http.Request) {
conf := warewulfconf.New()
conf := warewulfconf.Get()
rinfo, err := parseReq(req)
if err != nil {

View File

@@ -7,7 +7,7 @@ import (
"strconv"
"syscall"
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
warewulfconf "github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/pkg/errors"
)
@@ -58,7 +58,7 @@ func RunServer() error {
http.HandleFunc("/overlay-runtime/", ProvisionSend)
http.HandleFunc("/status", StatusSend)
conf := warewulfconf.New()
conf := warewulfconf.Get()
daemonPort := conf.Warewulf.Port
wwlog.Serv("Starting HTTPD REST service on port %d", daemonPort)

View File

@@ -22,7 +22,7 @@ if exists user-class and option user-class = "iPXE" {
} else {
{{range $type,$name := $.Tftp.IpxeBinaries }}
if option architecture-type = {{ $type }} {
filename "/warewulf/{{ $name }}";
filename "/warewulf/{{ basename $name }}";
}
{{ end }}
}