diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go
index 39d43b95..43eae0b3 100644
--- a/internal/app/wwctl/node/add/main.go
+++ b/internal/app/wwctl/node/add/main.go
@@ -1,6 +1,9 @@
package add
import (
+ "fmt"
+ "net"
+
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
@@ -123,7 +126,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
n.NetDevs[SetNetName].Type.Set(SetType)
}
+ if SetIpaddr6 != "" {
+ if SetNetName == "" {
+ return errors.New("you must include the '--netname' option")
+ }
+ if _, ok := n.NetDevs[SetNetName]; !ok {
+ return errors.New("network device does not exist: " + SetNetName)
+ }
+ // just check if address is a valid ipv6 CIDR address
+ if _, _, err := net.ParseCIDR(SetIpaddr6); err != nil {
+ return errors.New(fmt.Sprintf("%s is not a valid ipv6 address in CIDR notation\n", SetIpaddr6))
+ }
+ }
if SetDiscoverable {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting node to discoverable\n", n.Id.Get())
diff --git a/internal/app/wwctl/node/add/root.go b/internal/app/wwctl/node/add/root.go
index a3081965..a08caaf8 100644
--- a/internal/app/wwctl/node/add/root.go
+++ b/internal/app/wwctl/node/add/root.go
@@ -5,16 +5,17 @@ import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
- Use: "add [OPTIONS] NODENAME",
- Short: "Add new node to Warewulf",
- Long: "This command will add a new node named NODENAME to Warewulf.",
- RunE: CobraRunE,
- Args: cobra.MinimumNArgs(1),
+ Use: "add [OPTIONS] NODENAME",
+ Short: "Add new node to Warewulf",
+ Long: "This command will add a new node named NODENAME to Warewulf.",
+ RunE: CobraRunE,
+ Args: cobra.MinimumNArgs(1),
}
SetClusterName string
SetNetName string
SetNetDev string
SetIpaddr string
+ SetIpaddr6 string
SetNetmask string
SetGateway string
SetHwaddr string
@@ -27,6 +28,7 @@ func init() {
baseCmd.PersistentFlags().StringVarP(&SetNetName, "netname", "n", "default", "Define the network name to configure")
baseCmd.PersistentFlags().StringVarP(&SetNetDev, "netdev", "N", "", "Define the network device to configure")
baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "I", "", "Set the node's network device IP address")
+ baseCmd.PersistentFlags().StringVarP(&SetIpaddr6, "ipaddr6", "6", "", "Set the node's network device IPv6 address")
baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask")
baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway")
baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "H", "", "Set the node's network device HW address")
diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go
index 4fe66890..bb661b4e 100644
--- a/internal/app/wwctl/node/list/main.go
+++ b/internal/app/wwctl/node/list/main.go
@@ -65,6 +65,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":DEVICE", netdev.Device.Source(), netdev.Device.Print())
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":HWADDR", netdev.Hwaddr.Source(), netdev.Hwaddr.Print())
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":IPADDR", netdev.Ipaddr.Source(), netdev.Ipaddr.Print())
+ fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":IPADDR6", netdev.Ipaddr.Source(), netdev.Ipaddr6.Print())
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":NETMASK", netdev.Netmask.Source(), netdev.Netmask.Print())
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":GATEWAY", netdev.Gateway.Source(), netdev.Gateway.Print())
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":TYPE", netdev.Type.Source(), netdev.Type.Print())
@@ -75,16 +76,17 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
} else if ShowNet {
- fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", "NODE NAME", "DEVICE", "HWADDR", "IPADDR", "GATEWAY")
+ fmt.Printf("%-22s %-6s %-18s %-15s %-15s %-15s\n", "NODE NAME", "DEVICE", "HWADDR", "IPADDR", "GATEWAY", "IPADDR6")
fmt.Println(strings.Repeat("=", 80))
for _, node := range node.FilterByName(nodes, args) {
if len(node.NetDevs) > 0 {
for name, dev := range node.NetDevs {
- fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", node.Id.Get(), name, dev.Hwaddr.Print(), dev.Ipaddr.Print(), dev.Gateway.Print())
+ fmt.Printf("%-22s %-6s %-18s %-15s %-15s %-15s\n",
+ node.Id.Get(), name, dev.Hwaddr.Print(), dev.Ipaddr.Print(), dev.Gateway.Print(), dev.Ipaddr6.Print())
}
} else {
- fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", node.Id.Get(), "--", "--", "--", "--")
+ fmt.Printf("%-22s %-6s %-18s %-15s %-15s %-15s\n", node.Id.Get(), "--", "--", "--", "--", "--")
}
}
diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go
index ed445901..789bc9d4 100644
--- a/internal/pkg/node/constructors.go
+++ b/internal/pkg/node/constructors.go
@@ -2,12 +2,15 @@ package node
import (
"errors"
+ "fmt"
"io/ioutil"
+ "net"
"path"
"sort"
"strings"
"github.com/hpcng/warewulf/internal/pkg/buildconfig"
+ "github.com/hpcng/warewulf/internal/pkg/warewulfconf"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
@@ -43,7 +46,10 @@ func New() (nodeYaml, error) {
func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
var ret []NodeInfo
-
+ wwconfig, err := warewulfconf.New()
+ if err != nil {
+ return ret, err
+ }
wwlog.Printf(wwlog.DEBUG, "Finding all nodes...\n")
for nodename, node := range config.Nodes {
var n NodeInfo
@@ -103,13 +109,28 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
}
n.NetDevs[devname].Device.Set(netdev.Device)
n.NetDevs[devname].Ipaddr.Set(netdev.Ipaddr)
+ n.NetDevs[devname].Ipaddr6.Set(netdev.Ipaddr6)
+
+ // Derive value of ipv6 address from ipv4 if not explicitly set
+ if wwconfig.Ipaddr6 != "" {
+ ipv4Arr := strings.Split(netdev.Ipaddr, ".")
+ // error can be ignored as check was done at init
+ _, ipv6Net, _ := net.ParseCIDR(wwconfig.Ipaddr6)
+ mSize, _ := ipv6Net.Mask.Size()
+ ipv6str := fmt.Sprintf("%s%s:%s:%s:%s/%v",
+ ipv6Net.IP.String(), ipv4Arr[0], ipv4Arr[1], ipv4Arr[2], ipv4Arr[3], mSize)
+ if strings.Count(ipv6Net.IP.String(), ":") == 5 {
+ ipv6str = strings.Replace(ipv6str, "::", ":", -1)
+ }
+ n.NetDevs[devname].Ipaddr6.SetDefault(ipv6str)
+ }
n.NetDevs[devname].Netmask.Set(netdev.Netmask)
n.NetDevs[devname].Hwaddr.Set(netdev.Hwaddr)
n.NetDevs[devname].Gateway.Set(netdev.Gateway)
n.NetDevs[devname].Type.Set(netdev.Type)
n.NetDevs[devname].OnBoot.Set(netdev.OnBoot)
n.NetDevs[devname].Default.Set(netdev.Default)
- // for just one netdeve, it is always the default
+ // for just one netdev, it is always the default
if len(node.NetDevs) == 1 {
n.NetDevs[devname].Default.Set("true")
}
@@ -174,7 +195,7 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
wwlog.Printf(wwlog.DEBUG, "Updating profile (%s) netdev: %s\n", p, devname)
n.NetDevs[devname].Device.SetAlt(netdev.Device, p)
- n.NetDevs[devname].Ipaddr.SetAlt(netdev.Ipaddr, p)
+ //n.NetDevs[devname].Ipaddr.SetAlt(netdev.Ipaddr, p) <- Ipaddr must be uniq
n.NetDevs[devname].Netmask.SetAlt(netdev.Netmask, p)
n.NetDevs[devname].Hwaddr.SetAlt(netdev.Hwaddr, p)
n.NetDevs[devname].Gateway.SetAlt(netdev.Gateway, p)
diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go
index b2e0e343..20610dfd 100644
--- a/internal/pkg/node/datastructure.go
+++ b/internal/pkg/node/datastructure.go
@@ -49,6 +49,7 @@ type NetDevs struct {
Hwaddr string `yaml:"hwaddr,omitempty"`
Ipaddr string `yaml:"ipaddr,omitempty"`
IpCIDR string `yaml:"ipcidr,omitempty"`
+ Ipaddr6 string `yaml:"ip6addr,omitempty"`
Prefix string `yaml:"prefix,omitempty"`
Netmask string `yaml:"netmask,omitempty"`
Gateway string `yaml:"gateway,omitempty"`
@@ -101,6 +102,7 @@ type NetDevEntry struct {
Device Entry
Hwaddr Entry
Ipaddr Entry
+ Ipaddr6 Entry
IpCIDR Entry
Prefix Entry
Netmask Entry
diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go
index 5f1f04e9..e0697883 100644
--- a/internal/pkg/overlay/datastructure.go
+++ b/internal/pkg/overlay/datastructure.go
@@ -33,8 +33,10 @@ type TemplateStruct struct {
BuildTime string
BuildSource string
Ipaddr string
+ Ipaddr6 string
Netmask string
Network string
+ Ipv6 bool
Dhcp warewulfconf.DhcpConf
Nfs warewulfconf.NfsConf
Warewulf warewulfconf.WarewulfConf
diff --git a/internal/pkg/overlay/overlay.go b/internal/pkg/overlay/overlay.go
index 388e76e0..2538547f 100644
--- a/internal/pkg/overlay/overlay.go
+++ b/internal/pkg/overlay/overlay.go
@@ -253,7 +253,7 @@ func BuildOverlayIndir(nodeInfo node.NodeInfo, overlayNames []string, outputDir
netPrefix, _ := net.IPMask(net.ParseIP(netdev.Netmask.Get()).To4()).Size()
tstruct.NetDevs[devname].Prefix = strconv.Itoa(netPrefix)
tstruct.NetDevs[devname].IpCIDR = netaddr.String()
-
+ tstruct.NetDevs[devname].Ipaddr6 = netdev.Ipaddr6.Get()
}
// Backwards compatibility for templates using "Keys"
for keyname, key := range nodeInfo.Tags {
@@ -267,8 +267,14 @@ func BuildOverlayIndir(nodeInfo node.NodeInfo, overlayNames []string, outputDir
tstruct.Dhcp = *controller.Dhcp
tstruct.Warewulf = *controller.Warewulf
tstruct.Ipaddr = controller.Ipaddr
+ tstruct.Ipaddr6 = controller.Ipaddr6
tstruct.Netmask = controller.Netmask
tstruct.Network = controller.Network
+ if controller.Ipaddr6 != "" {
+ tstruct.Ipv6 = true
+ } else {
+ tstruct.Ipv6 = false
+ }
hostname, _ := os.Hostname()
tstruct.BuildHost = hostname
dt := time.Now()
diff --git a/internal/pkg/warewulfconf/constructors.go b/internal/pkg/warewulfconf/constructors.go
index 932a3433..b3d91d1f 100644
--- a/internal/pkg/warewulfconf/constructors.go
+++ b/internal/pkg/warewulfconf/constructors.go
@@ -62,7 +62,18 @@ func New() (ControllerConf, error) {
ret.Network = sub.GetNetworkPortion()
}
-
+ // check validity of ipv6 net
+ if ret.Ipaddr6 != "" {
+ _, ipv6net, err := net.ParseCIDR(ret.Ipaddr6)
+ if err != nil {
+ wwlog.Printf(wwlog.ERROR, "Invalid ipv6 address specified, mut be CIDR notation: %s\n", ret.Ipaddr6)
+ return ret, errors.New("invalid ipv6 network")
+ }
+ if msize, _ := ipv6net.Mask.Size(); msize > 64 {
+ wwlog.Printf(wwlog.ERROR, "ipv6 mask size must be smaller than 64\n")
+ return ret, errors.New("invalid ipv6 network size")
+ }
+ }
if ret.Warewulf.Port == 0 {
ret.Warewulf.Port = defaultPort
}
diff --git a/internal/pkg/warewulfconf/datastructure.go b/internal/pkg/warewulfconf/datastructure.go
index 0ef1481e..a8a65ef3 100644
--- a/internal/pkg/warewulfconf/datastructure.go
+++ b/internal/pkg/warewulfconf/datastructure.go
@@ -9,8 +9,10 @@ import (
type ControllerConf struct {
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"`
diff --git a/overlays/wwinit/etc/issue.ww b/overlays/wwinit/etc/issue.ww
index 134e8994..57ff1fc2 100644
--- a/overlays/wwinit/etc/issue.ww
+++ b/overlays/wwinit/etc/issue.ww
@@ -7,7 +7,6 @@ Network:
{{- range $devname, $netdev := .NetDevs}}
{{$devname}}: {{$netdev.Device}}
{{$devname}}: {{$netdev.IpCIDR}}
-{{if $netdev.Hwaddr }}
- {{$devname}}: {{$netdev.Hwaddr}}
-{{ end -}}
-{{end}}
\ No newline at end of file
+{{if $netdev.Ipaddr6 }} {{$devname}}: {{$netdev.Ipaddr6}}{{ end }}
+{{if $netdev.Hwaddr }} {{$devname}}: {{$netdev.Hwaddr}}{{ end }}
+{{end}}
diff --git a/overlays/wwinit/etc/sysconfig/network-scripts/ifcfg.ww b/overlays/wwinit/etc/sysconfig/network-scripts/ifcfg.ww
index 7449adab..363b2f5f 100644
--- a/overlays/wwinit/etc/sysconfig/network-scripts/ifcfg.ww
+++ b/overlays/wwinit/etc/sysconfig/network-scripts/ifcfg.ww
@@ -21,4 +21,11 @@ GATEWAY={{ $netdev.Gateway }}
HWADDR={{ $netdev.Hwaddr }}
{{ end -}}
ONBOOT=yes
+IPV6INIT=yes
+IPV6_AUTOCONF=yes
+IPV6_DEFROUTE=yes
+IPV6_FAILURE_FATAL=no
+{{ if $.NetDevs.default.Ipaddr6 -}}
+IPV6ADDR="{{ $.NetDevs.default.Ipaddr6 }}"
+{{ end -}}
{{ end -}}
diff --git a/overlays/wwinit/etc/wicked/ifconfig/ifcfg.xml.ww b/overlays/wwinit/etc/wicked/ifconfig/ifcfg.xml.ww
index cadb45b5..29277012 100644
--- a/overlays/wwinit/etc/wicked/ifconfig/ifcfg.xml.ww
+++ b/overlays/wwinit/etc/wicked/ifconfig/ifcfg.xml.ww
@@ -38,5 +38,12 @@ Source: {{ $source }}
prefer-public
false
+{{ if $.NetDevs.default.Ipaddr6 -}}
+
+
+ {{ $.NetDevs.default.Ipaddr6 }}
+
+
+{{ end -}}
{{ end -}}