diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 0d4ca49f..8f18ce6e 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -71,6 +71,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":TYPE", netdev.Type.Source(), netdev.Type.Print()) fmt.Printf("%-20s %-18s %-12s %t\n", node.Id.Get(), name+":ONBOOT", netdev.OnBoot.Source(), netdev.OnBoot.PrintB()) fmt.Printf("%-20s %-18s %-12s %t\n", node.Id.Get(), name+":DEFAULT", netdev.Default.Source(), netdev.Default.PrintB()) + for keyname, key := range netdev.Tags { + fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":TAG["+keyname+"]", key.Source(), key.Print()) + } } } diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 1ded9259..c41900d8 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -176,9 +176,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error { if SetNetName != "" { if _, ok := n.NetDevs[SetNetName]; !ok { var nd node.NetDevEntry + nd.Tags = make(map[string]*node.Entry) n.NetDevs[SetNetName] = &nd - if SetNetDev == "" { n.NetDevs[SetNetName].Device.Set(SetNetName) } @@ -341,7 +341,34 @@ func CobraRunE(cmd *cobra.Command, args []string) error { delete(n.Tags, key) } } + if len(SetNetTags) > 0 { + for _, t := range SetNetTags { + keyval := strings.SplitN(t, "=", 2) + key := keyval[0] + val := keyval[1] + if _, ok := n.NetDevs[SetNetName].Tags[key]; !ok { + var nd node.Entry + n.NetDevs[SetNetName].Tags[key] = &nd + } + wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting NETTAG '%s'='%s'\n", n.Id.Get(), SetNetName, key, val) + n.NetDevs[SetNetName].Tags[key].Set(val) + } + + } + if len(SetNetDelTags) > 0 { + for _, t := range SetNetDelTags { + keyval := strings.SplitN(t, "=", 1) + key := keyval[0] + if _, ok := n.NetDevs[SetNetName].Tags[key]; !ok { + wwlog.Printf(wwlog.WARN, "Node: %s:%s Key %s does not exist\n", n.Id.Get(), SetNetName, key) + os.Exit(1) + } + + wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Deleting Tag %s\n", n.Id.Get(), SetNetName, key) + delete(n.NetDevs[SetNetName].Tags, key) + } + } err := nodeDB.NodeUpdate(n) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index bf8dd547..1470cafb 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -72,6 +72,8 @@ var ( SetTags []string SetDelTags []string SetAssetKey string + SetNetTags []string + SetNetDelTags []string ) func init() { @@ -144,6 +146,8 @@ func init() { baseCmd.PersistentFlags().StringVar(&SetNetDefault, "default", "", "Enable/disable device as default (yes/no)") baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "netdel", false, "Delete the node's network device") + baseCmd.PersistentFlags().StringSliceVar(&SetNetTags, "nettag", []string{}, "Define custom tag to network device (key=value)") + baseCmd.PersistentFlags().StringSliceVar(&SetNetDelTags, "netdeltag", []string{}, "Delete tag for network device") baseCmd.PersistentFlags().StringSliceVarP(&SetTags, "tag", "t", []string{}, "Define custom tag (key=value)") baseCmd.PersistentFlags().StringSliceVar(&SetDelTags, "tagdel", []string{}, "Delete tag") diff --git a/internal/app/wwctl/profile/list/main.go b/internal/app/wwctl/profile/list/main.go index b013ae01..72a80dbe 100644 --- a/internal/app/wwctl/profile/list/main.go +++ b/internal/app/wwctl/profile/list/main.go @@ -60,6 +60,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), name+":TYPE", netdev.Hwaddr.Print()) fmt.Printf("%-20s %-18s %t\n", profile.Id.Get(), name+":ONBOOT", netdev.OnBoot.PrintB()) fmt.Printf("%-20s %-18s %t\n", profile.Id.Get(), name+":DEFAULT", netdev.Default.PrintB()) + for keyname, key := range netdev.Tags { + fmt.Printf("%-20s %-18s %-12s %s\n", profile.Id.Get(), name+":TAG["+keyname+"]", key.Source(), key.Print()) + } } } } else { diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index 347d9b6f..f14df079 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -151,7 +151,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { if SetNetName != "" { if _, ok := p.NetDevs[SetNetName]; !ok { var nd node.NetDevEntry - + nd.Tags = make(map[string]*node.Entry) p.NetDevs[SetNetName] = &nd } } @@ -276,6 +276,34 @@ func CobraRunE(cmd *cobra.Command, args []string) error { delete(p.Tags, key) } } + if len(SetNetTags) > 0 { + for _, t := range SetNetTags { + keyval := strings.SplitN(t, "=", 2) + key := keyval[0] + val := keyval[1] + if _, ok := p.NetDevs[SetNetName].Tags[key]; !ok { + var nd node.Entry + p.NetDevs[SetNetName].Tags[key] = &nd + } + + wwlog.Printf(wwlog.VERBOSE, "Profile: %s:%s, Setting NETTAG '%s'='%s'\n", p.Id.Get(), SetNetName, key, val) + p.NetDevs[SetNetName].Tags[key].Set(val) + } + + } + if len(SetNetDelTags) > 0 { + for _, t := range SetNetDelTags { + keyval := strings.SplitN(t, "=", 1) + key := keyval[0] + if _, ok := p.NetDevs[SetNetName].Tags[key]; !ok { + wwlog.Printf(wwlog.WARN, "Profile: %s,%s, Key %s does not exist\n", p.Id.Get(), SetNetName, key) + os.Exit(1) + } + + wwlog.Printf(wwlog.VERBOSE, "Profile: %s,%s Deleting NETTAG: %s\n", p.Id.Get(), SetNetName, key) + delete(p.NetDevs[SetNetName].Tags, key) + } + } err := nodeDB.ProfileUpdate(p) if err != nil { diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index c7d2d4b9..eb2a6b6e 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -67,6 +67,8 @@ var ( SetTags []string SetDelTags []string SetAssetKey string + SetNetTags []string + SetNetDelTags []string ) func init() { @@ -122,6 +124,8 @@ func init() { baseCmd.PersistentFlags().StringVar(&SetNetOnBoot, "onboot", "", "Enable/disable device (yes/no)") baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "netdel", false, "Delete the node's network device") + baseCmd.PersistentFlags().StringSliceVar(&SetNetTags, "nettag", []string{}, "Define custom tag to network device (key=value)") + baseCmd.PersistentFlags().StringSliceVar(&SetNetDelTags, "netdeltag", []string{}, "Delete tag for network device") baseCmd.PersistentFlags().StringSliceVarP(&SetTags, "tag", "t", []string{}, "Define custom tag (key=value)") baseCmd.PersistentFlags().StringSliceVar(&SetDelTags, "tagdel", []string{}, "Delete tag") diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index dea296e7..906e4ed3 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -140,6 +140,15 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { if len(node.NetDevs) == 1 { n.NetDevs[devname].Default.Set("true") } + n.NetDevs[devname].Tags = make(map[string]*Entry) + for keyname, key := range netdev.Tags { + if _, ok := n.Tags[keyname]; !ok { + var keyVar Entry + n.NetDevs[devname].Tags[keyname] = &keyVar + } + n.NetDevs[devname].Tags[keyname].Set(key) + } + } // Merge Keys into Tags for backwards compatibility @@ -201,13 +210,22 @@ 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) <- Ipaddr must be uniq + n.NetDevs[devname].Ipaddr.SetAlt(netdev.Ipaddr, p) //FIXME? <- 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) n.NetDevs[devname].Type.SetAlt(netdev.Type, p) n.NetDevs[devname].OnBoot.SetAlt(netdev.OnBoot, p) n.NetDevs[devname].Default.SetAlt(netdev.Default, p) + if len(netdev.Tags) != 0 { + for keyname, key := range netdev.Tags { + if _, ok := n.Tags[keyname]; !ok { + var keyVar Entry + n.NetDevs[devname].Tags[keyname] = &keyVar + } + n.NetDevs[devname].Tags[keyname].SetAlt(key, p) + } + } } // Merge Keys into Tags for backwards compatibility @@ -302,6 +320,15 @@ func (config *nodeYaml) FindAllProfiles() ([]NodeInfo, error) { if netdev.Hwaddr != "" { wwlog.Printf(wwlog.WARN, "Ignoring hardware address %v in profile %v\n", netdev.Hwaddr, name) } + p.NetDevs[devname].Tags = make(map[string]*Entry) + for keyname, key := range netdev.Tags { + if _, ok := p.Tags[keyname]; !ok { + var keyVar Entry + p.NetDevs[devname].Tags[keyname] = &keyVar + } + p.NetDevs[devname].Tags[keyname].Set(key) + } + } // Merge Keys into Tags for backwards compatibility diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 05012fd9..a6c1ee9f 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -15,6 +15,9 @@ type nodeYaml struct { Nodes map[string]*NodeConf } +/* +NodeConf is the datastructure which is stored on disk. +*/ type NodeConf struct { Comment string `yaml:"comment,omitempty"` ClusterName string `yaml:"cluster name,omitempty"` @@ -51,24 +54,25 @@ type KernelConf struct { } type NetDevs struct { - Type string `yaml:"type,omitempty"` - OnBoot string `yaml:"onboot,omitempty"` - Device string `yaml:"device,omitempty"` - 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"` - Default string `yaml:"default,omitempty"` + Type string `yaml:"type,omitempty"` + OnBoot string `yaml:"onboot,omitempty"` + Device string `yaml:"device,omitempty"` + 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"` + Default string `yaml:"default,omitempty"` + Tags map[string]string `yaml:"tags,omitempty"` } /****** * Internal code data representations ******/ /* -Holds a strtng value, when accessed via Get, its value +Holds string values, when accessed via Get, its value is returned which is the default or if set the value from the profile or if set the value of the node itself */ @@ -79,6 +83,12 @@ type Entry struct { def []string } +/* +NodeInfo is the in memory datastructure, which can containe +a default value, which is overwritten by the overlay from the +overlay (altvalue) which is overwitten by the value of the +node itself, for all values of type Entry. +*/ type NodeInfo struct { Id Entry Cid Entry @@ -129,6 +139,7 @@ type NetDevEntry struct { Netmask Entry Gateway Entry Default Entry + Tags map[string]*Entry } func init() { diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 933b73c6..7f48f8f6 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -91,6 +91,12 @@ func (config *nodeYaml) NodeUpdate(node NodeInfo) error { config.Nodes[nodeID].NetDevs[devname].Type = netdev.Type.GetReal() config.Nodes[nodeID].NetDevs[devname].OnBoot = netdev.OnBoot.GetReal() config.Nodes[nodeID].NetDevs[devname].Default = netdev.Default.GetReal() + config.Nodes[nodeID].NetDevs[devname].Tags = make(map[string]string) + for keyname, key := range netdev.Tags { + if key.GetReal() != "" { + config.Nodes[nodeID].NetDevs[devname].Tags[keyname] = key.GetReal() + } + } } config.Nodes[nodeID].Tags = make(map[string]string) diff --git a/internal/pkg/overlay/overlay.go b/internal/pkg/overlay/overlay.go index 0cee8f04..82eccf6a 100644 --- a/internal/pkg/overlay/overlay.go +++ b/internal/pkg/overlay/overlay.go @@ -254,6 +254,10 @@ func BuildOverlayIndir(nodeInfo node.NodeInfo, overlayNames []string, outputDir tstruct.NetDevs[devname].Prefix = strconv.Itoa(netPrefix) tstruct.NetDevs[devname].IpCIDR = netaddr.String() tstruct.NetDevs[devname].Ipaddr6 = netdev.Ipaddr6.Get() + tstruct.NetDevs[devname].Tags = make(map[string]string) + for key, value := range netdev.Tags { + tstruct.NetDevs[devname].Tags[key] = value.Get() + } } // Backwards compatibility for templates using "Keys" for keyname, key := range nodeInfo.Tags {