From b548d8583d5ecc9777be22e645f572a441d376a4 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 29 Jul 2022 14:55:51 +0200 Subject: [PATCH] reflection on constructor --- internal/pkg/node/constructors.go | 270 ++++++++++++++++---------- internal/pkg/node/datastructure.go | 2 +- internal/pkg/node/modifiers.go | 4 +- internal/pkg/overlay/datastructure.go | 2 +- 4 files changed, 174 insertions(+), 104 deletions(-) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 5002a32a..fb3d17ce 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -4,13 +4,12 @@ import ( "errors" "fmt" "io/ioutil" - "net" "path" + "reflect" "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" @@ -51,10 +50,12 @@ for every node */ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { var ret []NodeInfo - wwconfig, err := warewulfconf.New() - if err != nil { - return ret, err - } + /* + 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 @@ -75,29 +76,98 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { if len(fullname) > 1 { n.ClusterName.SetDefault(fullname[1]) } - + // special handling for profile to get the default one if len(node.Profiles) == 0 { n.Profiles = []string{"default"} } else { n.Profiles = node.Profiles } - + // node explciti nodename field in NodeConf n.Id.Set(nodename) - n.Comment.Set(node.Comment) - n.ContainerName.Set(node.ContainerName) - n.ClusterName.Set(node.ClusterName) - n.Ipxe.Set(node.Ipxe) - n.Init.Set(node.Init) - // backward compatibility for old Ipmi config - n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) - n.Ipmi.Netmask.Set(node.IpmiNetmask) - n.Ipmi.Port.Set(node.IpmiPort) - n.Ipmi.Gateway.Set(node.IpmiGateway) - n.Ipmi.UserName.Set(node.IpmiUserName) - n.Ipmi.Password.Set(node.IpmiPassword) - n.Ipmi.Interface.Set(node.IpmiInterface) - n.Ipmi.Write.Set(node.IpmiWrite) - // delete deprectated structures so that they do not get unmarshalled + /* + n.Comment.Set(node.Comment) + n.ContainerName.Set(node.ContainerName) + n.ClusterName.Set(node.ClusterName) + n.Ipxe.Set(node.Ipxe) + n.Init.Set(node.Init) + // backward compatibility for old Ipmi config + n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) + n.Ipmi.Netmask.Set(node.IpmiNetmask) + n.Ipmi.Port.Set(node.IpmiPort) + n.Ipmi.Gateway.Set(node.IpmiGateway) + n.Ipmi.UserName.Set(node.IpmiUserName) + n.Ipmi.Password.Set(node.IpmiPassword) + n.Ipmi.Interface.Set(node.IpmiInterface) + n.Ipmi.Write.Set(node.IpmiWrite) + */ + nodeInfoType := reflect.TypeOf(&n) + nodeInfoVal := reflect.ValueOf(&n) + nodeConfVal := reflect.ValueOf(node) + // now iterate of every field + for i := 0; i < nodeInfoType.Elem().NumField(); i++ { + valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) + if valField.IsValid() { + // found field with same name + if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { + if valField.Type().Kind() == reflect.String { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).Set(valField.String()) + } else if valField.Type() == reflect.TypeOf([]string{}) { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetSlice(valField.Interface().([]string)) + } + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr { + nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) + netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) + nestedConfVal := reflect.ValueOf(valField.Interface()) + for j := 0; j < nestedInfoType.Elem().NumField(); j++ { + nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) + if nestedVal.IsValid() { + if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { + netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).Set(nestedVal.String()) + } + } + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { + fmt.Println("Found map") + confMap := valField.Interface().(map[string]string) + for key, val := range confMap { + var entr Entry + entr.Set(val) + (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 { + 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'tknow how to do it + netMap[netName] = &newNet + netInfoType := reflect.TypeOf(newNet) + netInfoVal := reflect.ValueOf(&newNet) + for j := 0; j < netInfoType.NumField(); j++ { + netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) + if netVal.IsValid() { + if netVal.Type().Kind() == reflect.String { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).Set(netVal.String()) + if netInfoType.Field(j).Name == "Netmask" { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetDefault("255.255.255.0") + } + } 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) { + var entr Entry + entr.Set(val) + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + } + } + } + } + } + } + } + } + // delete deprecated structures so that they do not get unmarshalled node.IpmiIpaddr = "" node.IpmiNetmask = "" node.IpmiGateway = "" @@ -105,22 +175,23 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.IpmiPassword = "" node.IpmiInterface = "" node.IpmiWrite = "" - - if node.Ipmi != nil { - n.Ipmi.Ipaddr.Set(node.Ipmi.Ipaddr) - n.Ipmi.Netmask.Set(node.Ipmi.Netmask) - n.Ipmi.Port.Set(node.Ipmi.Port) - n.Ipmi.Gateway.Set(node.Ipmi.Gateway) - n.Ipmi.UserName.Set(node.Ipmi.UserName) - n.Ipmi.Password.Set(node.Ipmi.Password) - n.Ipmi.Interface.Set(node.Ipmi.Interface) - n.Ipmi.Write.SetB(node.Ipmi.Write) - } - n.SystemOverlay.SetSlice(node.SystemOverlay) - n.RuntimeOverlay.SetSlice(node.RuntimeOverlay) - n.Root.Set(node.Root) - n.AssetKey.Set(node.AssetKey) - n.Discoverable.Set(node.Discoverable) + /* + if node.Ipmi != nil { + n.Ipmi.Ipaddr.Set(node.Ipmi.Ipaddr) + n.Ipmi.Netmask.Set(node.Ipmi.Netmask) + n.Ipmi.Port.Set(node.Ipmi.Port) + n.Ipmi.Gateway.Set(node.Ipmi.Gateway) + n.Ipmi.UserName.Set(node.Ipmi.UserName) + n.Ipmi.Password.Set(node.Ipmi.Password) + n.Ipmi.Interface.Set(node.Ipmi.Interface) + n.Ipmi.Write.SetB(node.Ipmi.Write) + } + n.SystemOverlay.SetSlice(node.SystemOverlay) + n.RuntimeOverlay.SetSlice(node.RuntimeOverlay) + n.Root.Set(node.Root) + n.AssetKey.Set(node.AssetKey) + n.Discoverable.Set(node.Discoverable) + */ // backward compatibility n.Kernel.Args.Set(node.KernelArgs) n.Kernel.Override.Set(node.KernelOverride) @@ -128,68 +199,67 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.KernelArgs = "" node.KernelOverride = "" node.KernelVersion = "" - - if node.Kernel != nil { - n.Kernel.Args.Set(node.Kernel.Args) - if node.Kernel.Override != "" { - n.Kernel.Override.Set(node.Kernel.Override) - } else if node.Kernel.Version != "" { - n.Kernel.Override.Set(node.Kernel.Version) - } - } - - for devname, netdev := range node.NetDevs { - if _, ok := n.NetDevs[devname]; !ok { - var netdev NetDevEntry - n.NetDevs[devname] = &netdev - } - 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 != "" && netdev.Ipaddr != "" { - 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) + /* + if node.Kernel != nil { + n.Kernel.Args.Set(node.Kernel.Args) + if node.Kernel.Override != "" { + n.Kernel.Override.Set(node.Kernel.Override) + } else if node.Kernel.Version != "" { + n.Kernel.Override.Set(node.Kernel.Version) + } } - n.NetDevs[devname].Ipaddr6.SetDefault(ipv6str) - } - n.NetDevs[devname].Netmask.Set(netdev.Netmask) - n.NetDevs[devname].Netmask.SetDefault("255.255.255.0") - n.NetDevs[devname].Hwaddr.Set(strings.ToLower(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].Primary.Set(netdev.Primary) - n.NetDevs[devname].Primary.Set(netdev.Default) // backwards compatibility - // for just one netdev, it is always the primary - if len(node.NetDevs) == 1 { - n.NetDevs[devname].Primary.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 + for devname, netdev := range node.NetDevs { + if _, ok := n.NetDevs[devname]; !ok { + var netdev NetDevEntry + n.NetDevs[devname] = &netdev } - n.NetDevs[devname].Tags[keyname].Set(key) - } - 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) - } - } + 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 != "" && netdev.Ipaddr != "" { + 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].Netmask.SetDefault("255.255.255.0") + n.NetDevs[devname].Hwaddr.Set(strings.ToLower(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].Primary.Set(netdev.Primary) + n.NetDevs[devname].Primary.Set(netdev.Default) // backwards compatibility + // for just one netdev, it is always the primary + if len(node.NetDevs) == 1 { + n.NetDevs[devname].Primary.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) + } + 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 if len(node.Tags) == 0 { node.Tags = make(map[string]string) @@ -231,7 +301,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Ipmi.UserName.SetAlt(config.NodeProfiles[p].Ipmi.UserName, p) n.Ipmi.Password.SetAlt(config.NodeProfiles[p].Ipmi.Password, p) n.Ipmi.Interface.SetAlt(config.NodeProfiles[p].Ipmi.Interface, p) - n.Ipmi.Write.SetAltB(config.NodeProfiles[p].Ipmi.Write, p) + n.Ipmi.Write.SetAlt(config.NodeProfiles[p].Ipmi.Write, p) } n.SystemOverlay.SetAltSlice(config.NodeProfiles[p].SystemOverlay, p) n.RuntimeOverlay.SetAltSlice(config.NodeProfiles[p].RuntimeOverlay, p) @@ -369,7 +439,7 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.Ipmi.UserName.Set(profile.Ipmi.UserName) p.Ipmi.Password.Set(profile.Ipmi.Password) p.Ipmi.Interface.Set(profile.Ipmi.Interface) - p.Ipmi.Write.SetB(profile.Ipmi.Write) + p.Ipmi.Write.Set(profile.Ipmi.Write) } p.RuntimeOverlay.SetSlice(profile.RuntimeOverlay) p.SystemOverlay.SetSlice(profile.SystemOverlay) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index b8ffed07..8521122a 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -60,7 +60,7 @@ type IpmiConf struct { Port string `yaml:"port,omitempty" lopt:"ipmiport" comment:"Set the IPMI port"` Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway"` Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` - Write bool `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` + Write string `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` Tags map[string]string `yaml:"tags,omitempty" lopt:"impitag" comment:"ipmi keys"` } type KernelConf struct { diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 44c3b10c..4d094dc6 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -79,7 +79,7 @@ func (config *NodeYaml) NodeUpdate(node NodeInfo) error { config.Nodes[nodeID].Ipmi.UserName = node.Ipmi.UserName.GetReal() config.Nodes[nodeID].Ipmi.Password = node.Ipmi.Password.GetReal() config.Nodes[nodeID].Ipmi.Interface = node.Ipmi.Interface.GetReal() - config.Nodes[nodeID].Ipmi.Write = node.Ipmi.Write.GetB() + config.Nodes[nodeID].Ipmi.Write = node.Ipmi.Write.Get() } config.Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetRealSlice() config.Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetRealSlice() @@ -185,7 +185,7 @@ func (config *NodeYaml) ProfileUpdate(profile NodeInfo) error { config.NodeProfiles[profileID].Ipmi.UserName = profile.Ipmi.UserName.GetReal() config.NodeProfiles[profileID].Ipmi.Password = profile.Ipmi.Password.GetReal() config.NodeProfiles[profileID].Ipmi.Interface = profile.Ipmi.Interface.GetReal() - config.NodeProfiles[profileID].Ipmi.Write = profile.Ipmi.Interface.GetB() + config.NodeProfiles[profileID].Ipmi.Write = profile.Ipmi.Interface.Get() } config.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay.GetRealSlice() config.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay.GetRealSlice() diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go index 8d5dd534..4a0575af 100644 --- a/internal/pkg/overlay/datastructure.go +++ b/internal/pkg/overlay/datastructure.go @@ -86,7 +86,7 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct { tstruct.Ipmi.UserName = nodeInfo.Ipmi.UserName.Get() tstruct.Ipmi.Password = nodeInfo.Ipmi.Password.Get() tstruct.Ipmi.Interface = nodeInfo.Ipmi.Interface.Get() - tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.GetB() + tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.Get() tstruct.RuntimeOverlay = nodeInfo.RuntimeOverlay.Print() tstruct.SystemOverlay = nodeInfo.SystemOverlay.Print() tstruct.NetDevs = make(map[string]*node.NetDevs)