use reflect on overlays
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
|
||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||
@@ -177,7 +178,7 @@ func NodeList(nodeNames []string) (nodeInfo []*wwapiv1.NodeInfo, err error) {
|
||||
}
|
||||
|
||||
nodeNames = hostlist.Expand(nodeNames)
|
||||
|
||||
sort.Strings(nodeNames)
|
||||
// Translate to the protobuf structure so wwapiv1 can use this across the wire.
|
||||
// This is the same logic as was in wwctl.
|
||||
for _, n := range node.FilterByName(nodes, nodeNames) {
|
||||
|
||||
@@ -87,7 +87,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
||||
node.Tags[keyname] = key
|
||||
delete(node.Keys, keyname)
|
||||
}
|
||||
n.setFrom(node)
|
||||
n.SetFrom(node)
|
||||
// backward compatibility
|
||||
n.Ipmi.Ipaddr.Set(node.IpmiIpaddr)
|
||||
n.Ipmi.Netmask.Set(node.IpmiNetmask)
|
||||
@@ -123,7 +123,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
||||
}
|
||||
// can't call setFrom() as we have to use SetAlt instead of Set for an Entry
|
||||
wwlog.Printf(wwlog.VERBOSE, "Merging profile into node: %s <- %s\n", nodename, profileName)
|
||||
config.NodeProfiles[profileName].setAltFrom(n, profileName)
|
||||
config.NodeProfiles[profileName].SetAltFrom(n, profileName)
|
||||
}
|
||||
ret = append(ret, n)
|
||||
}
|
||||
@@ -155,7 +155,7 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) {
|
||||
profile.Tags[keyname] = key
|
||||
delete(profile.Keys, keyname)
|
||||
}
|
||||
p.setFrom(profile)
|
||||
p.SetFrom(profile)
|
||||
p.Ipmi.Ipaddr.Set(profile.IpmiIpaddr)
|
||||
p.Ipmi.Netmask.Set(profile.IpmiNetmask)
|
||||
p.Ipmi.Port.Set(profile.IpmiPort)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
* Filters
|
||||
*
|
||||
*********/
|
||||
|
||||
/*
|
||||
Filter a given slice of NodeInfo against a given
|
||||
regular expression
|
||||
|
||||
@@ -55,7 +55,7 @@ func (config *NodeYaml) NodeUpdate(node NodeInfo) error {
|
||||
if _, ok := config.Nodes[nodeID]; !ok {
|
||||
return errors.New("Nodename does not exist: " + nodeID)
|
||||
}
|
||||
config.Nodes[nodeID].getRealFrom(node)
|
||||
config.Nodes[nodeID].GetRealFrom(node)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func (config *NodeYaml) ProfileUpdate(profile NodeInfo) error {
|
||||
if _, ok := config.NodeProfiles[profileID]; !ok {
|
||||
return errors.New("Profile name does not exist: " + profileID)
|
||||
}
|
||||
config.NodeProfiles[profileID].getRealFrom(profile)
|
||||
config.NodeProfiles[profileID].GetRealFrom(profile)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package node
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
/*
|
||||
Populates a NodeConf struct (the one which goes to disk) from a
|
||||
@@ -8,7 +10,7 @@ NodeInfo (which just lives in memory), with the values from all
|
||||
the underlying entries using GetReal, so just the explicit values
|
||||
go do disk.
|
||||
*/
|
||||
func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) {
|
||||
func (nodeConf *NodeConf) GetRealFrom(nodeInfo NodeInfo) {
|
||||
nodeInfoType := reflect.TypeOf(nodeInfo)
|
||||
nodeInfoVal := reflect.ValueOf(nodeInfo)
|
||||
configVal := reflect.ValueOf(nodeConf)
|
||||
@@ -45,7 +47,6 @@ func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) {
|
||||
*newConfPtr = &newConf
|
||||
}
|
||||
}
|
||||
needNestedStruct := false
|
||||
nestedInfoType := reflect.TypeOf(nodeInfoVal.Field(i).Interface())
|
||||
nestedInfoVal := reflect.ValueOf(nodeInfoVal.Field(i).Interface())
|
||||
nestedConfVal := reflect.ValueOf(confField.Interface())
|
||||
@@ -56,12 +57,10 @@ func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) {
|
||||
newValue := (nestedVal.Addr().Interface()).(*string)
|
||||
entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry)
|
||||
*newValue = entryVal.GetReal()
|
||||
needNestedStruct = needNestedStruct || entryVal.GotReal()
|
||||
} else if nestedVal.Type() == reflect.TypeOf([]string{}) {
|
||||
newValue := (nestedVal.Addr().Interface()).(*[]string)
|
||||
entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry)
|
||||
*newValue = entryVal.GetRealSlice()
|
||||
needNestedStruct = needNestedStruct || entryVal.GotReal()
|
||||
|
||||
}
|
||||
} else if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(map[string]*Entry{}) {
|
||||
@@ -76,18 +75,7 @@ func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) {
|
||||
}
|
||||
//}
|
||||
}
|
||||
// Check if the nested struct has any values, if not replace it with a nil pointer so
|
||||
// that it does not get unmarshalled to someting like ipmi: {}
|
||||
if !needNestedStruct {
|
||||
switch confField.Type() {
|
||||
case reflect.TypeOf((*IpmiConf)(nil)):
|
||||
newConf := (confField.Addr().Interface()).(**IpmiConf)
|
||||
*newConf = (*IpmiConf)(nil)
|
||||
case reflect.TypeOf((*KernelConf)(nil)):
|
||||
newConf := (confField.Addr().Interface()).(**KernelConf)
|
||||
*newConf = (*KernelConf)(nil)
|
||||
}
|
||||
}
|
||||
|
||||
} else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) {
|
||||
nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry)
|
||||
for netName, netVal := range nestedMap {
|
||||
@@ -126,11 +114,130 @@ func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Populates a NodeConf struct from a NodeInfo, with the combined
|
||||
values from the underlying entries using Get.
|
||||
*/
|
||||
func (nodeConf *NodeConf) GetFrom(nodeInfo NodeInfo) {
|
||||
nodeInfoType := reflect.TypeOf(nodeInfo)
|
||||
nodeInfoVal := reflect.ValueOf(nodeInfo)
|
||||
configVal := reflect.ValueOf(nodeConf)
|
||||
// now iterate of every field
|
||||
for i := 0; i < nodeInfoType.NumField(); i++ {
|
||||
// found field with same name for Conf and Info
|
||||
confField := configVal.Elem().FieldByName(nodeInfoType.Field(i).Name)
|
||||
if confField.IsValid() {
|
||||
if nodeInfoVal.Field(i).Type() == reflect.TypeOf(Entry{}) {
|
||||
if confField.Type().Kind() == reflect.String {
|
||||
newValue := (confField.Addr().Interface()).(*string)
|
||||
entryVal := nodeInfoVal.Field(i).Interface().(Entry)
|
||||
*newValue = entryVal.Get()
|
||||
} else if confField.Type() == reflect.TypeOf([]string{}) {
|
||||
newValue := (confField.Addr().Interface()).(*[]string)
|
||||
entryVal := nodeInfoVal.Field(i).Interface().(Entry)
|
||||
*newValue = entryVal.GetSlice()
|
||||
}
|
||||
} else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*Entry{}) {
|
||||
if confField.IsNil() {
|
||||
confFieldPtr := confField.Addr().Interface().(*map[string]string)
|
||||
*confFieldPtr = make(map[string]string)
|
||||
}
|
||||
entryMap := nodeInfoVal.Field(i).Interface().(map[string]*Entry)
|
||||
for key, val := range entryMap {
|
||||
confField.Interface().(map[string]string)[key] = val.Get()
|
||||
}
|
||||
} else if nodeInfoVal.Field(i).Type().Kind() == reflect.Ptr {
|
||||
if confField.Addr().Elem().IsZero() {
|
||||
switch confField.Addr().Elem().Type() {
|
||||
case reflect.TypeOf((*KernelConf)(nil)):
|
||||
var newConf KernelConf
|
||||
newConfPtr := (confField.Addr().Elem().Addr().Interface()).(**KernelConf)
|
||||
*newConfPtr = &newConf
|
||||
case reflect.TypeOf((*IpmiConf)(nil)):
|
||||
var newConf IpmiConf
|
||||
newConfPtr := (confField.Addr().Elem().Addr().Interface()).(**IpmiConf)
|
||||
*newConfPtr = &newConf
|
||||
}
|
||||
}
|
||||
nestedInfoType := reflect.TypeOf(nodeInfoVal.Field(i).Interface())
|
||||
nestedInfoVal := reflect.ValueOf(nodeInfoVal.Field(i).Interface())
|
||||
nestedConfVal := reflect.ValueOf(confField.Interface())
|
||||
for j := 0; j < nestedInfoType.Elem().NumField(); j++ {
|
||||
nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name)
|
||||
if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) {
|
||||
if nestedVal.Type().Kind() == reflect.String {
|
||||
newValue := (nestedVal.Addr().Interface()).(*string)
|
||||
entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry)
|
||||
*newValue = entryVal.Get()
|
||||
} else if nestedVal.Type() == reflect.TypeOf([]string{}) {
|
||||
newValue := (nestedVal.Addr().Interface()).(*[]string)
|
||||
entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry)
|
||||
*newValue = entryVal.GetSlice()
|
||||
|
||||
}
|
||||
} else if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(map[string]*Entry{}) {
|
||||
if nestedVal.IsNil() {
|
||||
mapPtr := nestedVal.Addr().Interface().(*map[string]string)
|
||||
*mapPtr = make(map[string]string)
|
||||
}
|
||||
entryMap := nestedInfoVal.Elem().Field(j).Interface().(map[string]*Entry)
|
||||
for key, val := range entryMap {
|
||||
nestedVal.Interface().(map[string]string)[key] = val.Get()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) {
|
||||
nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry)
|
||||
for netName, netVal := range nestedMap {
|
||||
netValsType := reflect.ValueOf(netVal)
|
||||
if confField.IsNil() {
|
||||
netMapPtr := confField.Addr().Interface().(*map[string](*NetDevs))
|
||||
*netMapPtr = make(map[string](*NetDevs))
|
||||
}
|
||||
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)
|
||||
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 = (netVal.Addr().Interface()).(*Entry).Get()
|
||||
} 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)
|
||||
netConfVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} /*else {
|
||||
// NodeInfo has the Id field, nodeConf not
|
||||
fmt.Println("INVALID", nodeInfoType.Field(i).Name)
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Populates all fields of NodeInfo with Set from the
|
||||
values of NodeConf.
|
||||
*/
|
||||
func (node *NodeInfo) setFrom(n *NodeConf) {
|
||||
func (node *NodeInfo) SetFrom(n *NodeConf) {
|
||||
// get the full memory, taking the shortcut and init Ipmi and Kernel directly
|
||||
if node.Kernel == nil {
|
||||
node.Kernel = new(KernelEntry)
|
||||
}
|
||||
if node.Ipmi == nil {
|
||||
node.Ipmi = new(IpmiEntry)
|
||||
}
|
||||
nodeInfoVal := reflect.ValueOf(node)
|
||||
nodeInfoType := reflect.TypeOf(node)
|
||||
nodeConfVal := reflect.ValueOf(n)
|
||||
@@ -217,7 +324,7 @@ values of NodeConf. The string profileName is used to
|
||||
destermine from which source/NodeInfo the entry came
|
||||
from.
|
||||
*/
|
||||
func (node *NodeConf) setAltFrom(nodeInfo NodeInfo, profileName string) {
|
||||
func (node *NodeConf) SetAltFrom(nodeInfo NodeInfo, profileName string) {
|
||||
nodeInfoVal := reflect.ValueOf(&nodeInfo)
|
||||
nodeInfoType := reflect.TypeOf(&nodeInfo)
|
||||
profileConfVal := reflect.ValueOf(node)
|
||||
|
||||
@@ -16,33 +16,25 @@ struct which contains the variables to which are available in
|
||||
the templates.
|
||||
*/
|
||||
type TemplateStruct struct {
|
||||
Id string
|
||||
Hostname string
|
||||
ClusterName string
|
||||
Container string
|
||||
Kernel *node.KernelConf
|
||||
Init string
|
||||
Root string
|
||||
Ipmi *node.IpmiConf
|
||||
RuntimeOverlay string
|
||||
SystemOverlay string
|
||||
NetDevs map[string]*node.NetDevs
|
||||
Tags map[string]string
|
||||
Keys map[string]string
|
||||
AllNodes []node.NodeInfo
|
||||
BuildHost string
|
||||
BuildTime string
|
||||
BuildTimeUnix string
|
||||
BuildSource string
|
||||
Ipaddr string
|
||||
Ipaddr6 string
|
||||
Netmask string
|
||||
Network string
|
||||
NetworkCIDR string
|
||||
Ipv6 bool
|
||||
Dhcp warewulfconf.DhcpConf
|
||||
Nfs warewulfconf.NfsConf
|
||||
Warewulf warewulfconf.WarewulfConf
|
||||
Id string
|
||||
Hostname string
|
||||
BuildHost string
|
||||
BuildTime string
|
||||
BuildTimeUnix string
|
||||
BuildSource string
|
||||
Ipaddr string
|
||||
Ipaddr6 string
|
||||
Netmask string
|
||||
Network string
|
||||
NetworkCIDR string
|
||||
Ipv6 bool
|
||||
Dhcp warewulfconf.DhcpConf
|
||||
Nfs warewulfconf.NfsConf
|
||||
Warewulf warewulfconf.WarewulfConf
|
||||
AllNodes []node.NodeInfo
|
||||
node.NodeConf
|
||||
// backward compatiblity
|
||||
Container string
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -65,63 +57,12 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct {
|
||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
tstruct.Kernel = new(node.KernelConf)
|
||||
tstruct.Ipmi = new(node.IpmiConf)
|
||||
// init some convininence vars
|
||||
tstruct.Id = nodeInfo.Id.Get()
|
||||
tstruct.Hostname = nodeInfo.Id.Get()
|
||||
tstruct.Id = nodeInfo.Id.Get()
|
||||
tstruct.Hostname = nodeInfo.Id.Get()
|
||||
tstruct.ClusterName = nodeInfo.ClusterName.Get()
|
||||
tstruct.Container = nodeInfo.ContainerName.Get()
|
||||
tstruct.Kernel.Version = nodeInfo.Kernel.Override.Get()
|
||||
tstruct.Kernel.Override = nodeInfo.Kernel.Override.Get()
|
||||
tstruct.Kernel.Args = nodeInfo.Kernel.Args.Get()
|
||||
tstruct.Init = nodeInfo.Init.Get()
|
||||
tstruct.Root = nodeInfo.Root.Get()
|
||||
tstruct.Ipmi.Ipaddr = nodeInfo.Ipmi.Ipaddr.Get()
|
||||
tstruct.Ipmi.Netmask = nodeInfo.Ipmi.Netmask.Get()
|
||||
tstruct.Ipmi.Port = nodeInfo.Ipmi.Port.Get()
|
||||
tstruct.Ipmi.Gateway = nodeInfo.Ipmi.Gateway.Get()
|
||||
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.Get()
|
||||
tstruct.RuntimeOverlay = nodeInfo.RuntimeOverlay.Print()
|
||||
tstruct.SystemOverlay = nodeInfo.SystemOverlay.Print()
|
||||
tstruct.NetDevs = make(map[string]*node.NetDevs)
|
||||
tstruct.Keys = make(map[string]string)
|
||||
tstruct.Tags = make(map[string]string)
|
||||
for devname, netdev := range nodeInfo.NetDevs {
|
||||
var nd node.NetDevs
|
||||
tstruct.NetDevs[devname] = &nd
|
||||
tstruct.NetDevs[devname].Device = netdev.Device.Get()
|
||||
tstruct.NetDevs[devname].Hwaddr = netdev.Hwaddr.Get()
|
||||
tstruct.NetDevs[devname].Ipaddr = netdev.Ipaddr.Get()
|
||||
tstruct.NetDevs[devname].Netmask = netdev.Netmask.Get()
|
||||
tstruct.NetDevs[devname].Gateway = netdev.Gateway.Get()
|
||||
tstruct.NetDevs[devname].Type = netdev.Type.Get()
|
||||
tstruct.NetDevs[devname].OnBoot = netdev.OnBoot.Get()
|
||||
tstruct.NetDevs[devname].Primary = netdev.Primary.Get()
|
||||
mask := net.IPMask(net.ParseIP(netdev.Netmask.Get()).To4())
|
||||
ipaddr := net.ParseIP(netdev.Ipaddr.Get()).To4()
|
||||
netaddr := net.IPNet{IP: ipaddr, Mask: mask}
|
||||
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()
|
||||
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 {
|
||||
tstruct.Keys[keyname] = key.Get()
|
||||
}
|
||||
for keyname, key := range nodeInfo.Tags {
|
||||
tstruct.Tags[keyname] = key.Get()
|
||||
}
|
||||
tstruct.AllNodes = allNodes
|
||||
tstruct.Nfs = *controller.Nfs
|
||||
tstruct.Dhcp = *controller.Dhcp
|
||||
@@ -142,6 +83,9 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct {
|
||||
dt := time.Now()
|
||||
tstruct.BuildTime = dt.Format("01-02-2006 15:04:05 MST")
|
||||
tstruct.BuildTimeUnix = strconv.FormatInt(dt.Unix(), 10)
|
||||
tstruct.NodeConf.GetFrom(nodeInfo)
|
||||
// backward compatibilty
|
||||
tstruct.Container = tstruct.ContainerName
|
||||
|
||||
return tstruct
|
||||
|
||||
|
||||
Reference in New Issue
Block a user