From 18eb531d4b884a8d660404ec3e0540829eaf5ffe Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 1 Sep 2022 10:08:31 +0200 Subject: [PATCH] fixed deletion of network and deletion of tags --- internal/app/wwctl/node/set/main.go | 8 +- internal/app/wwctl/node/set/root.go | 2 +- internal/app/wwctl/profile/list/main.go | 2 +- internal/app/wwctl/profile/set/main.go | 6 +- internal/app/wwctl/profile/set/root.go | 2 +- internal/pkg/api/node/list.go | 4 +- internal/pkg/api/node/node.go | 15 ++- internal/pkg/api/profile/profile.go | 20 ++-- internal/pkg/node/constructors.go | 10 ++ internal/pkg/node/transformers.go | 130 ++++++++++++++++++------ 10 files changed, 144 insertions(+), 55 deletions(-) diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index e71a5d10..63dad15f 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -15,15 +15,13 @@ import ( func CobraRunE(cmd *cobra.Command, args []string) (err error) { // remove the default network as the all network values are assigned // to this network - if NetName != "" { - netDev := *NodeConf.NetDevs["default"] - NodeConf.NetDevs[NetName] = &netDev + if NetName != "default" { + NodeConf.NetDevs[NetName] = NodeConf.NetDevs["default"] delete(NodeConf.NetDevs, "default") - } buffer, err := yaml.Marshal(NodeConf) if err != nil { - wwlog.Error("Cant marshall nodeInfo", err) + wwlog.Error("Can't marshall nodeInfo", err) os.Exit(1) } set := wwapiv1.NodeSetParameter{ diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index b3087897..0e5e81cf 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -44,7 +44,7 @@ func init() { NodeConf = node.NewConf() NodeConf.CreateFlags(baseCmd, []string{}) baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") - baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") + baseCmd.PersistentFlags().StringVar(&NetName, "netname", "default", "Set network name for network options") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") baseCmd.PersistentFlags().BoolVarP(&SetForce, "force", "f", false, "Force configuration (even on error)") diff --git a/internal/app/wwctl/profile/list/main.go b/internal/app/wwctl/profile/list/main.go index 7e8d7163..2c9782ef 100644 --- a/internal/app/wwctl/profile/list/main.go +++ b/internal/app/wwctl/profile/list/main.go @@ -70,7 +70,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } else { fmt.Printf("%-20s %s\n", "PROFILE NAME", "COMMENT/DESCRIPTION") - fmt.Println(strings.Repeat("=", 80)) + fmt.Printf(strings.Repeat("=", 80) + "\n") for _, profile := range node.FilterByName(profiles, args) { fmt.Printf("%-20s %s\n", profile.Id.Print(), profile.Comment.Print()) diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index d0d8dcfd..f905f2a9 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -16,11 +16,9 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { // remove the default network as the all network values are assigned // to this network - if NetName != "" { - netDev := *ProfileConf.NetDevs["default"] - ProfileConf.NetDevs[NetName] = &netDev + if NetName != "default" { + ProfileConf.NetDevs[NetName] = ProfileConf.NetDevs["default"] delete(ProfileConf.NetDevs, "default") - } buffer, err := yaml.Marshal(ProfileConf) if err != nil { diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index 807d2367..f95cbb6c 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -44,7 +44,7 @@ func init() { ProfileConf = node.NewConf() ProfileConf.CreateFlags(baseCmd, []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) - baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") + baseCmd.PersistentFlags().StringVar(&NetName, "netname", "default", "Set network name for network options") baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") diff --git a/internal/pkg/api/node/list.go b/internal/pkg/api/node/list.go index f31b8604..f8f995eb 100644 --- a/internal/pkg/api/node/list.go +++ b/internal/pkg/api/node/list.go @@ -131,11 +131,11 @@ func NodeList(nodeGet *wwapiv1.GetNodeList) (nodeList wwapiv1.NodeList, err erro } } else if netInfoType.Field(j).Type == reflect.TypeOf(map[string]*node.Entry{}) { for key, val := range netInfoVal.Field(j).Interface().(map[string]*node.Entry) { - fieldName = fieldName + ":" + key + keyfieldName := fieldName + ":" + key fieldSource = val.Source() fieldVal = val.Print() nodeList.Output = append(nodeList.Output, - fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), fieldName, fieldSource, fieldVal)) + fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), keyfieldName, fieldSource, fieldVal)) } } diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index e3c7d890..e34169b8 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -238,7 +238,6 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB } n.SetFrom(&nodeConf) if set.NetdevDelete != "" { - if _, ok := n.NetDevs[set.NetdevDelete]; !ok { err = fmt.Errorf("network device name doesn't exist: %s", set.NetdevDelete) wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) @@ -248,7 +247,19 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", n.Id.Get(), set.NetdevDelete) delete(n.NetDevs, set.NetdevDelete) } - + for _, key := range nodeConf.TagsDel { + delete(n.Tags, key) + } + for _, key := range nodeConf.Ipmi.TagsDel { + delete(n.Ipmi.Tags, key) + } + for net := range nodeConf.NetDevs { + for _, key := range nodeConf.NetDevs[net].TagsDel { + if _, ok := n.NetDevs[net]; ok { + delete(n.NetDevs[net].Tags, key) + } + } + } err := nodeDB.NodeUpdate(n) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) diff --git a/internal/pkg/api/profile/profile.go b/internal/pkg/api/profile/profile.go index 1f25b897..48c53a73 100644 --- a/internal/pkg/api/profile/profile.go +++ b/internal/pkg/api/profile/profile.go @@ -33,7 +33,6 @@ func ProfileSet(set *wwapiv1.NodeSetParameter) (err error) { // TODO: Determine if the console switch does wwlog or not. // - console may end up being textOutput? func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB node.NodeYaml, profileCount uint, err error) { - if set == nil { err = fmt.Errorf("profile set parameter is nil") if console { @@ -87,19 +86,28 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node if util.InSlice(set.NodeNames, p.Id.Get()) { wwlog.Printf(wwlog.VERBOSE, "Evaluating profile: %s\n", p.Id.Get()) p.SetFrom(&pConf) - if set.NetdevDelete != "" { - if _, ok := p.NetDevs[set.NetdevDelete]; !ok { - err = fmt.Errorf("Network device name doesn't exist: %s", set.NetdevDelete) + err = fmt.Errorf("network device name doesn't exist: %s", set.NetdevDelete) wwlog.Error(fmt.Sprintf("%v\n", err.Error())) return } - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Deleting network device: %s\n", p.Id.Get(), set.NetdevDelete) delete(p.NetDevs, set.NetdevDelete) } - + for _, key := range pConf.TagsDel { + delete(p.Tags, key) + } + for _, key := range pConf.Ipmi.TagsDel { + delete(p.Ipmi.Tags, key) + } + for net := range pConf.NetDevs { + for _, key := range pConf.NetDevs[net].TagsDel { + if _, ok := p.NetDevs[net]; ok { + delete(p.NetDevs[net].Tags, key) + } + } + } err := nodeDB.ProfileUpdate(p) if err != nil { wwlog.Error("%s\n", err) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 9afabd2c..428145ec 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -157,11 +157,16 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { for name, profile := range config.NodeProfiles { var p NodeInfo + p.NetDevs = make(map[string]*NetDevEntry) + p.Tags = make(map[string]*Entry) + p.Kernel = new(KernelEntry) + p.Ipmi = new(IpmiEntry) p.Id.Set(name) for keyname, key := range profile.Keys { profile.Tags[keyname] = key delete(profile.Keys, keyname) } + p.SetFrom(profile) p.Ipmi.Ipaddr.Set(profile.IpmiIpaddr) p.Ipmi.Netmask.Set(profile.IpmiNetmask) @@ -185,6 +190,11 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { profile.KernelArgs = "" profile.KernelOverride = "" profile.KernelVersion = "" + // Merge Keys into Tags for backwards compatibility + if len(profile.Tags) == 0 { + profile.Tags = make(map[string]string) + } + ret = append(ret, p) } sort.Slice(ret, func(i, j int) bool { diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index 4a2369f9..a50ca263 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -52,8 +52,23 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, } } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*Entry{}) { entryMap := nodeInfoVal.Field(i).Interface().(map[string]*Entry) + confMap := confField.Interface().(map[string]string) + + if len(confMap) > len(entryMap) { + for confKey := range confMap { + foundKey := false + for entrKey := range entryMap { + if confKey == entrKey { + foundKey = true + } + } + if !foundKey { + delete(confMap, confKey) + } + } + } for key, val := range entryMap { - confField.Interface().(map[string]string)[key] = getter(val) + confMap[key] = getter(val) } } else if nodeInfoVal.Field(i).Type().Kind() == reflect.Ptr { if confField.Addr().Elem().IsZero() { @@ -90,11 +105,24 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, *mapPtr = make(map[string]string) } entryMap := nestedInfoVal.Elem().Field(j).Interface().(map[string]*Entry) + confMap := nestedVal.Interface().(map[string]string) + if len(confMap) > len(entryMap) { + for confKey := range confMap { + foundKey := false + for entrKey := range entryMap { + if confKey == entrKey { + foundKey = true + } + } + if !foundKey { + delete(confMap, confKey) + } + } + } for key, val := range entryMap { - nestedVal.Interface().(map[string]string)[key] = getter(val) + confMap[key] = getter(val) } } - //} } } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) { @@ -103,36 +131,59 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, *netMapPtr = make(map[string](*NetDevs)) } nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry) + netMap := confField.Interface().(map[string](*NetDevs)) + // check if a network was deleted + if len(netMap) > len(nestedMap) { + for netMapKey := range netMap { + foundKey := false + for nestedMapKey := range nestedMap { + if netMapKey == nestedMapKey { + foundKey = true + } + } + if !foundKey { + delete(netMap, netMapKey) + } + } + } for netName, netVal := range nestedMap { netValsType := reflect.ValueOf(netVal) - netMap := confField.Interface().(map[string](*NetDevs)) - var newNet NetDevs - newNet.Tags = make(map[string]string) - netMap[netName] = &newNet - netConfType := reflect.TypeOf(newNet) - netConfVal := reflect.ValueOf(&newNet) + if _, ok := netMap[netName]; !ok { + netMap[netName] = new(NetDevs) + } + netConfType := reflect.TypeOf(*netMap[netName]) + netConfVal := reflect.ValueOf(netMap[netName]) for j := 0; j < netConfType.NumField(); j++ { netVal := netValsType.Elem().FieldByName(netConfType.Field(j).Name) if netVal.IsValid() { if netVal.Type() == reflect.TypeOf(Entry{}) { newVal := netConfVal.Elem().Field(j).Addr().Interface().((*string)) *newVal = getter((netVal.Addr().Interface()).(*Entry)) - } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - for key, val := range (netVal.Interface()).(map[string]*string) { - *val = getter(netConfVal.Elem().Field(j).Interface().((map[string](*Entry)))[key]) + } else if netVal.Type() == reflect.TypeOf(map[string]*Entry{}) { + entryMap := netVal.Interface().(map[string](*Entry)) + confMap := netConfVal.Elem().Field(j).Interface().(map[string]string) + if len(confMap) > len(entryMap) { + for confMapKey := range confMap { + foundKey := false + for entryMapKey := range entryMap { + if confMapKey == entryMapKey { + foundKey = true + } + } + if !foundKey { + delete(netConfVal.Elem().Field(j).Interface().(map[string]string), confMapKey) + } + } + } + for key, val := range entryMap { + netConfVal.Elem().Field(j).Interface().(map[string]string)[key] = getter(val) } } } - } } } } - /* else { - // NodeInfo has the Id field, nodeConf not - fmt.Println("INVALID", nodeInfoType.Field(i).Name) - } - */ } } func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) { @@ -154,9 +205,17 @@ func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []stri } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string]*NetDevs(nil)) { netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string]*NetDevs) // add a default network so that it can hold values - netMap["default"] = new(NetDevs) - netType := reflect.TypeOf(netMap["default"]) - netVal := reflect.ValueOf(netMap["default"]) + key := "default" + if len(netMap) == 0 { + netMap[key] = new(NetDevs) + } else { + for keyIt := range netMap { + key = keyIt + break + } + } + netType := reflect.TypeOf(netMap[key]) + netVal := reflect.ValueOf(netMap[key]) for j := 0; j < netType.Elem().NumField(); j++ { field := netVal.Elem().Field(j) createFlags(baseCmd, excludeList, netType.Elem().Field(j), &field) @@ -304,27 +363,32 @@ func (node *NodeInfo) setterFrom(n *NodeConf, nameArg string, (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = entr } } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { - nestedMap := valField.Interface().(map[string](*NetDevs)) - for netName, netVals := range nestedMap { + netValMap := valField.Interface().(map[string](*NetDevs)) + for netName, netVals := range netValMap { netValsType := reflect.ValueOf(netVals) netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) - var newNet NetDevEntry - newNet.Tags = make(map[string]*Entry) - // This should be done a bit down, but didn't know how to do it - netMap[netName] = &newNet - netInfoType := reflect.TypeOf(newNet) - netInfoVal := reflect.ValueOf(&newNet) + if nodeInfoVal.Elem().Field(i).IsNil() { + netMap = make(map[string]*NetDevEntry) + } + if _, ok := netMap[netName]; !ok { + var newNet NetDevEntry + newNet.Tags = make(map[string]*Entry) + netMap[netName] = &newNet + } + netInfoType := reflect.TypeOf(*netMap[netName]) + netInfoVal := reflect.ValueOf(netMap[netName]) for j := 0; j < netInfoType.NumField(); j++ { netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) if netVal.IsValid() { if netVal.Type().Kind() == reflect.String { setter(netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)), netVal.String(), nameArg) } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normaly the map should be created here, but did not manage it for key, val := range (netVal.Interface()).(map[string]string) { - entr := new(Entry) - setter(entr, val, nameArg) - netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = entr + //netTagMap := netInfoVal.Elem().Field(j).Interface().((map[string](*Entry))) + if _, ok := netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key]; !ok { + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = new(Entry) + } + setter(netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key], val, nameArg) } } }