11
CHANGELOG.md
11
CHANGELOG.md
@@ -22,6 +22,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
`/etc/hosts`
|
||||
- Added experimental dnsmasq support.
|
||||
|
||||
- new subcommand `wwctl genconf` is available with following subcommands:
|
||||
* `completions` which will create the files used for bash-completion. Also
|
||||
fish an zsh completions can be generated
|
||||
* `defaults` which will generate a valid `defaults.conf`
|
||||
* `man` which will generate the man pages in the specified directory
|
||||
* `reference` which will generate a reference documentation for the wwctl commands
|
||||
* `warwulfconf print` which will print the used `warewulf.conf`. If there is no valid
|
||||
`warewulf.conf` a valid configuration is provided, prefilled with default values
|
||||
and an IP configuration derived from the network configuration of the host
|
||||
- All paths can now be configured in `warewulf.conf`, check the paths section of of
|
||||
`wwctl --emptyconf genconfig warewulfconf print` for the available paths.
|
||||
## [4.4.0] 2023-01-18
|
||||
|
||||
### Added
|
||||
|
||||
13
Makefile
13
Makefile
@@ -218,7 +218,9 @@ init:
|
||||
|
||||
wwctl: $(WWCTL_DEPS)
|
||||
@echo Building "$@"
|
||||
@cd cmd/wwctl; GOOS=linux go build -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../wwctl
|
||||
@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 "$@"
|
||||
@@ -226,10 +228,11 @@ wwclient: $(WWCLIENT_DEPS)
|
||||
-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=/etc/warewulf/warewulf.conf'" -o ../../wwclient
|
||||
|
||||
man_pages: wwctl
|
||||
install -d man_pages
|
||||
./wwctl genconfig man man_pages
|
||||
cp docs/man/man5/*.5 ./man_pages/
|
||||
cd man_pages; for i in wwctl*1 *.5; do echo "Compressing manpage: $$i"; gzip --force $$i; done
|
||||
@install -d man_pages
|
||||
@./wwctl --emptyconf genconfig man man_pages
|
||||
@cp docs/man/man5/*.5 ./man_pages/
|
||||
@echo -n "Compressing manpage: "
|
||||
@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'\
|
||||
|
||||
@@ -34,6 +34,7 @@ var (
|
||||
DebugFlag bool
|
||||
LogLevel int
|
||||
WarewulfConfArg string
|
||||
AllowEmptyConf bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -42,9 +43,10 @@ func init() {
|
||||
rootCmd.PersistentFlags().IntVar(&LogLevel, "loglevel", wwlog.INFO, "Set log level to given string")
|
||||
_ = rootCmd.PersistentFlags().MarkHidden("loglevel")
|
||||
rootCmd.PersistentFlags().StringVar(&WarewulfConfArg, "warewulfconf", "", "Set the warewulf configuration file")
|
||||
rootCmd.PersistentFlags().BoolVar(&AllowEmptyConf, "emptyconf", false, "Allow empty configuration")
|
||||
_ = rootCmd.PersistentFlags().MarkHidden("emptyconf")
|
||||
rootCmd.SetUsageTemplate(help.UsageTemplate)
|
||||
rootCmd.SetHelpTemplate(help.HelpTemplate)
|
||||
|
||||
rootCmd.AddCommand(overlay.GetCommand())
|
||||
rootCmd.AddCommand(container.GetCommand())
|
||||
rootCmd.AddCommand(node.GetCommand())
|
||||
@@ -75,10 +77,16 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
wwlog.SetLogLevel(LogLevel)
|
||||
}
|
||||
conf := warewulfconf.New()
|
||||
if WarewulfConfArg != "" {
|
||||
err = conf.ReadConf(WarewulfConfArg)
|
||||
} else if os.Getenv("WAREWULFCONF") != "" {
|
||||
err = conf.ReadConf(os.Getenv("WAREWULFCONF"))
|
||||
if !AllowEmptyConf {
|
||||
if WarewulfConfArg != "" {
|
||||
err = conf.ReadConf(WarewulfConfArg)
|
||||
} else if os.Getenv("WAREWULFCONF") != "" {
|
||||
err = conf.ReadConf(os.Getenv("WAREWULFCONF"))
|
||||
} else {
|
||||
err = conf.ReadConf(warewulfconf.ConfigFile)
|
||||
}
|
||||
} else {
|
||||
conf.SetDynamicDefaults()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package warewulfconf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/brotherpowers/ipsubnet"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/creasty/defaults"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"gopkg.in/yaml.v2"
|
||||
@@ -20,32 +20,32 @@ var ConfigFile string
|
||||
Creates a new empty ControllerConf object, returns a cached
|
||||
one if called in a nother context.
|
||||
*/
|
||||
func New() (ret ControllerConf) {
|
||||
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 {
|
||||
ret.Warewulf = new(WarewulfConf)
|
||||
ret.Dhcp = new(DhcpConf)
|
||||
ret.Tftp = new(TftpConf)
|
||||
ret.Nfs = new(NfsConf)
|
||||
ret.Paths = new(BuildConfig)
|
||||
_ = defaults.Set(&ret)
|
||||
_ = ret.setDynamicDefaults()
|
||||
conf.Warewulf = new(WarewulfConf)
|
||||
conf.Dhcp = new(DhcpConf)
|
||||
conf.Tftp = new(TftpConf)
|
||||
conf.Nfs = new(NfsConf)
|
||||
conf.Paths = new(BuildConfig)
|
||||
_ = defaults.Set(&conf)
|
||||
|
||||
cachedConf = ret
|
||||
cachedConf = conf
|
||||
cachedConf.current = true
|
||||
|
||||
} else {
|
||||
// If cached struct isn't empty, use it as the return value
|
||||
ret = cachedConf
|
||||
conf = cachedConf
|
||||
}
|
||||
return ret
|
||||
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
|
||||
@@ -67,6 +67,10 @@ func (conf *ControllerConf) Read(data []byte) (err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = conf.SetDynamicDefaults()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(conf.Tftp.IpxeBinaries) == 0 {
|
||||
conf.Tftp.IpxeBinaries = defIpxe
|
||||
}
|
||||
@@ -78,38 +82,60 @@ func (conf *ControllerConf) Read(data []byte) (err error) {
|
||||
/*
|
||||
Set the runtime defaults like IP address of running system to the config
|
||||
*/
|
||||
func (ret *ControllerConf) setDynamicDefaults() (err error) {
|
||||
if ret.Ipaddr == "" || ret.Netmask == "" {
|
||||
conn, error := net.Dial("udp", "8.8.8.8:80")
|
||||
if error != nil {
|
||||
return err
|
||||
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)
|
||||
}
|
||||
defer conn.Close()
|
||||
localIp := conn.LocalAddr().(*net.UDPAddr)
|
||||
if ret.Ipaddr == "" {
|
||||
ret.Ipaddr = localIp.IP.String()
|
||||
wwlog.Verbose("IP address is not configured in warewulfd.conf, using %s", ret.Ipaddr)
|
||||
_, network, err = net.ParseCIDR(conf.Ipaddr)
|
||||
if err == nil {
|
||||
mask = network.Mask
|
||||
} else {
|
||||
return errors.Wrap(err, "Couldn't parse IP address")
|
||||
}
|
||||
if ret.Netmask == "" {
|
||||
mask := localIp.IP.DefaultMask()
|
||||
ret.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
|
||||
wwlog.Verbose("Netmask address is not configured in warewulfd.conf, using %s", ret.Netmask)
|
||||
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)
|
||||
|
||||
if ret.Network == "" {
|
||||
mask := net.IPMask(net.ParseIP(ret.Netmask).To4())
|
||||
size, _ := mask.Size()
|
||||
|
||||
sub := ipsubnet.SubnetCalculator(ret.Ipaddr, size)
|
||||
|
||||
ret.Network = sub.GetNetworkPortion()
|
||||
}
|
||||
// check validity of ipv6 net
|
||||
if ret.Ipaddr6 != "" {
|
||||
_, ipv6net, err := net.ParseCIDR(ret.Ipaddr6)
|
||||
if conf.Ipaddr6 != "" {
|
||||
_, ipv6net, err := net.ParseCIDR(conf.Ipaddr6)
|
||||
if err != nil {
|
||||
wwlog.Error("Invalid ipv6 address specified, mut be CIDR notation: %s", ret.Ipaddr6)
|
||||
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 {
|
||||
@@ -117,5 +143,7 @@ func (ret *ControllerConf) setDynamicDefaults() (err error) {
|
||||
return errors.New("invalid ipv6 network size")
|
||||
}
|
||||
}
|
||||
cachedConf = *conf
|
||||
cachedConf.current = true
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user