added Changelog

Signed-off-by: Christian Goll <cgoll@suse.de>
This commit is contained in:
Christian Goll
2023-03-06 15:51:34 +01:00
parent ce43dfa0b7
commit a422a1617c
4 changed files with 93 additions and 44 deletions

View File

@@ -16,7 +16,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The primary hostname and warewulf server fqdn are now the canonical name in
`/etc/hosts`
- 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

View File

@@ -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 "$@"

View File

@@ -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
}

View File

@@ -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,61 @@ 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
fmt.Println(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 +144,7 @@ func (ret *ControllerConf) setDynamicDefaults() (err error) {
return errors.New("invalid ipv6 network size")
}
}
cachedConf = *conf
cachedConf.current = true
return
}