From 6d267d38e6cdd57e76851e1c5ea7d29b7e5ba846 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 29 Jul 2021 09:24:58 +0200 Subject: [PATCH 1/6] added IpCIDR entry for the nodes --- internal/pkg/node/datastructure.go | 4 ++++ internal/pkg/overlay/overlay.go | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 406c656d..a04102ea 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -44,6 +44,8 @@ type NetDevs struct { Default bool `yaml:"default"` Hwaddr string Ipaddr string + IpCIDR string + Prefix string Netmask string Gateway string `yaml:"gateway,omitempty"` } @@ -91,6 +93,8 @@ type NetDevEntry struct { Default Entry `yaml:"default"` Hwaddr Entry Ipaddr Entry + IpCIDR Entry + Prefix Entry Netmask Entry Gateway Entry `yaml:"gateway,omitempty"` } diff --git a/internal/pkg/overlay/overlay.go b/internal/pkg/overlay/overlay.go index 7936e534..fc9c64a5 100644 --- a/internal/pkg/overlay/overlay.go +++ b/internal/pkg/overlay/overlay.go @@ -3,11 +3,13 @@ package overlay import ( "fmt" "io/ioutil" + "net" "os" "os/exec" "path" "path/filepath" "regexp" + "strconv" "strings" "text/template" @@ -160,6 +162,13 @@ func buildOverlay(nodeList []node.NodeInfo, overlayType string) error { t.NetDevs[devname].Gateway = netdev.Gateway.Get() t.NetDevs[devname].Type = netdev.Type.Get() t.NetDevs[devname].Default = netdev.Default.GetB() + 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() + t.NetDevs[devname].Prefix = strconv.Itoa(netPrefix) + t.NetDevs[devname].IpCIDR = netaddr.String() + } for keyname, key := range n.Keys { t.Keys[keyname] = key.Get() From 49300a513d5957be5dd247771093b4494ee54587 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 29 Jul 2021 09:27:37 +0200 Subject: [PATCH 2/6] added wicked xml configuration --- .../etc/wicked/ifconfig/ifcfg-eth0.xml.ww | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 overlays/system/default/etc/wicked/ifconfig/ifcfg-eth0.xml.ww diff --git a/overlays/system/default/etc/wicked/ifconfig/ifcfg-eth0.xml.ww b/overlays/system/default/etc/wicked/ifconfig/ifcfg-eth0.xml.ww new file mode 100644 index 00000000..6e7f7600 --- /dev/null +++ b/overlays/system/default/etc/wicked/ifconfig/ifcfg-eth0.xml.ww @@ -0,0 +1,27 @@ + + eth0 + + boot + + + + + true + true + + +
+ {{$.NetDevs.eth0.IpCIDR}} +
+ + + {{$.NetDevs.eth0.Gateway}} + + +
+ + true + prefer-public + false + +
From c6b2fc579595b97201dda559a354c39f98037679 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 3 Aug 2021 11:30:26 +0200 Subject: [PATCH 3/6] added configureable ipmiinterface used by ipmitool ipmitool is now searched from $PATH, so that self compiled ipmitool can be used --- internal/app/wwctl/node/list/main.go | 6 ++++-- internal/app/wwctl/node/sensors/power.go | 14 ++++++++----- internal/app/wwctl/node/set/main.go | 5 +++++ internal/app/wwctl/node/set/root.go | 2 ++ internal/app/wwctl/power/cycle/power.go | 14 ++++++++----- internal/app/wwctl/power/on/power.go | 14 ++++++++----- internal/app/wwctl/power/status/power.go | 14 ++++++++----- internal/app/wwctl/profile/set/main.go | 5 +++++ internal/app/wwctl/profile/set/root.go | 2 ++ internal/pkg/node/constructors.go | 3 +++ internal/pkg/node/datastructure.go | 2 ++ internal/pkg/node/modifiers.go | 2 ++ internal/pkg/overlay/overlay.go | 24 ++++++++++++---------- internal/pkg/power/ipmitool.go | 26 ++++++++++++++++-------- 14 files changed, 91 insertions(+), 42 deletions(-) diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 16954318..a11063e8 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -49,6 +49,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error { fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiNetmask", node.IpmiNetmask.Source(), node.IpmiNetmask.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiGateway", node.IpmiGateway.Source(), node.IpmiGateway.Print()) fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiUserName", node.IpmiUserName.Source(), node.IpmiUserName.Print()) + fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiInterface", node.IpmiInterface.Source(), node.IpmiInterface.Print()) + for name, netdev := range node.NetDevs { fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), name+":HWADDR", netdev.Hwaddr.Source(), netdev.Hwaddr.Print()) @@ -79,11 +81,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } else if ShowIpmi { - fmt.Printf("%-22s %-16s %-20s %-20s\n", "NODE NAME", "IPMI IPADDR", "IPMI USERNAME", "IPMI PASSWORD") + fmt.Printf("%-22s %-16s %-20s %-20s\n", "NODE NAME", "IPMI IPADDR", "IPMI USERNAME", "IPMI PASSWORD IPMI INTERFACE") fmt.Println(strings.Repeat("=", 80)) for _, node := range node.FilterByName(nodes, args) { - fmt.Printf("%-22s %-16s %-20s %-20s\n", node.Id.Get(), node.IpmiIpaddr.Print(), node.IpmiUserName.Print(), node.IpmiPassword.Print()) + fmt.Printf("%-22s %-16s %-20s %-20s\n", node.Id.Get(), node.IpmiIpaddr.Print(), node.IpmiUserName.Print(), node.IpmiPassword.Print(), node.IpmiInterface.Print()) } } else if ShowLong { diff --git a/internal/app/wwctl/node/sensors/power.go b/internal/app/wwctl/node/sensors/power.go index b0379dce..3f1dad88 100644 --- a/internal/app/wwctl/node/sensors/power.go +++ b/internal/app/wwctl/node/sensors/power.go @@ -48,12 +48,16 @@ func CobraRunE(cmd *cobra.Command, args []string) error { wwlog.Printf(wwlog.ERROR, "%s: No IPMI IP address\n", node.Id.Get()) continue } - + var ipmiInterface = "lan" + if node.IpmiInterface.Get() != "" { + ipmiInterface = node.IpmiInterface.Get() + } ipmiCmd := power.IPMI{ - NodeName: node.Id.Get(), - HostName: node.IpmiIpaddr.Get(), - User: node.IpmiUserName.Get(), - Password: node.IpmiPassword.Get(), + NodeName: node.Id.Get(), + HostName: node.IpmiIpaddr.Get(), + User: node.IpmiUserName.Get(), + Password: node.IpmiPassword.Get(), + Interface: ipmiInterface, AuthType: "MD5", } diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 76973c86..fc16ba3d 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -175,6 +175,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { n.IpmiPassword.Set(SetIpmiPassword) } + if SetIpmiInterface != "" { + wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP interface to: %s\n", n.Id.Get(), SetIpmiInterface) + n.IpmiInterface.Set(SetIpmiInterface) + } + if SetDiscoverable == true { wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting node to discoverable\n", n.Id.Get()) n.Discoverable.SetB(true) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 48c1531d..fe41253a 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -31,6 +31,7 @@ var ( SetIpmiGateway string SetIpmiUsername string SetIpmiPassword string + SetIpmiInterface string SetNodeAll bool SetYes bool SetProfile string @@ -63,6 +64,7 @@ func init() { baseCmd.PersistentFlags().StringVar(&SetIpmiGateway, "ipmigateway", "", "Set the node's IPMI gateway") baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username") baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password") + baseCmd.PersistentFlags().StringVar(&SetIpmiInterface, "ipmiinterface", "", "Set the node's IPMI interface (defaults to lan if empty)") baseCmd.PersistentFlags().StringSliceVar(&SetAddProfile, "addprofile", []string{}, "Add Profile(s) to node") baseCmd.PersistentFlags().StringSliceVar(&SetDelProfile, "delprofile", []string{}, "Remove Profile(s) to node") diff --git a/internal/app/wwctl/power/cycle/power.go b/internal/app/wwctl/power/cycle/power.go index c3aa7c80..b76aebc9 100644 --- a/internal/app/wwctl/power/cycle/power.go +++ b/internal/app/wwctl/power/cycle/power.go @@ -48,12 +48,16 @@ func CobraRunE(cmd *cobra.Command, args []string) error { wwlog.Printf(wwlog.ERROR, "%s: No IPMI IP address\n", node.Id.Get()) continue } - + var ipmiInterface = "lan" + if node.IpmiInterface.Get() != "" { + ipmiInterface = node.IpmiInterface.Get() + } ipmiCmd := power.IPMI{ - NodeName: node.Id.Get(), - HostName: node.IpmiIpaddr.Get(), - User: node.IpmiUserName.Get(), - Password: node.IpmiPassword.Get(), + NodeName: node.Id.Get(), + HostName: node.IpmiIpaddr.Get(), + User: node.IpmiUserName.Get(), + Password: node.IpmiPassword.Get(), + Interface: ipmiInterface, AuthType: "MD5", } diff --git a/internal/app/wwctl/power/on/power.go b/internal/app/wwctl/power/on/power.go index 2dad58ea..013d1dbc 100644 --- a/internal/app/wwctl/power/on/power.go +++ b/internal/app/wwctl/power/on/power.go @@ -48,12 +48,16 @@ func CobraRunE(cmd *cobra.Command, args []string) error { wwlog.Printf(wwlog.ERROR, "%s: No IPMI IP address\n", node.Id.Get()) continue } - + var ipmiInterface = "lan" + if node.IpmiInterface.Get() != "" { + ipmiInterface = node.IpmiInterface.Get() + } ipmiCmd := power.IPMI{ - NodeName: node.Id.Get(), - HostName: node.IpmiIpaddr.Get(), - User: node.IpmiUserName.Get(), - Password: node.IpmiPassword.Get(), + NodeName: node.Id.Get(), + HostName: node.IpmiIpaddr.Get(), + User: node.IpmiUserName.Get(), + Password: node.IpmiPassword.Get(), + Interface: ipmiInterface, AuthType: "MD5", } diff --git a/internal/app/wwctl/power/status/power.go b/internal/app/wwctl/power/status/power.go index 35f815b1..98ecdf37 100644 --- a/internal/app/wwctl/power/status/power.go +++ b/internal/app/wwctl/power/status/power.go @@ -48,12 +48,16 @@ func CobraRunE(cmd *cobra.Command, args []string) error { wwlog.Printf(wwlog.ERROR, "%s: No IPMI IP address\n", node.Id.Get()) continue } - + var ipmiInterface = "lan" + if node.IpmiInterface.Get() != "" { + ipmiInterface = node.IpmiInterface.Get() + } ipmiCmd := power.IPMI{ - NodeName: node.Id.Get(), - HostName: node.IpmiIpaddr.Get(), - User: node.IpmiUserName.Get(), - Password: node.IpmiPassword.Get(), + NodeName: node.Id.Get(), + HostName: node.IpmiIpaddr.Get(), + User: node.IpmiUserName.Get(), + Password: node.IpmiPassword.Get(), + Interface: ipmiInterface, AuthType: "MD5", } diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index b7a2eda6..1a2b700b 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -132,6 +132,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { p.IpmiPassword.Set(SetIpmiPassword) } + if SetIpmiInterface != "" { + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI username to: %s\n", p.Id, SetIpmiInterface) + p.IpmiInterface.Set(SetIpmiInterface) + } + if SetNetDevDel == true { if SetNetDev == "" { wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n") diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index 2bc4b6e2..cf152aa8 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -25,6 +25,7 @@ var ( SetIpmiGateway string SetIpmiUsername string SetIpmiPassword string + SetIpmiInterface string SetNetDev string SetIpaddr string SetNetmask string @@ -56,6 +57,7 @@ func init() { baseCmd.PersistentFlags().StringVar(&SetIpmiGateway, "ipmigateway", "", "Set the node's IPMI gateway") baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username") baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password") + baseCmd.PersistentFlags().StringVar(&SetIpmiInterface, "ipmiinterface", "", "Set the node's IPMI interface (defaults to lan if empty)") 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") diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 7f90342c..f17ea167 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -75,6 +75,7 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.IpmiGateway.Set(node.IpmiGateway) n.IpmiUserName.Set(node.IpmiUserName) n.IpmiPassword.Set(node.IpmiPassword) + n.IpmiInterface.Set(node.IpmiInterface) n.SystemOverlay.Set(node.SystemOverlay) n.RuntimeOverlay.Set(node.RuntimeOverlay) n.Root.Set(node.Root) @@ -123,6 +124,7 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) { n.IpmiGateway.SetAlt(config.NodeProfiles[p].IpmiGateway, p) n.IpmiUserName.SetAlt(config.NodeProfiles[p].IpmiUserName, p) n.IpmiPassword.SetAlt(config.NodeProfiles[p].IpmiPassword, p) + n.IpmiInterface.SetAlt(config.NodeProfiles[p].IpmiInterface, p) n.SystemOverlay.SetAlt(config.NodeProfiles[p].SystemOverlay, p) n.RuntimeOverlay.SetAlt(config.NodeProfiles[p].RuntimeOverlay, p) n.Root.SetAlt(config.NodeProfiles[p].Root, p) @@ -190,6 +192,7 @@ func (config *nodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.IpmiGateway.Set(profile.IpmiGateway) p.IpmiUserName.Set(profile.IpmiUserName) p.IpmiPassword.Set(profile.IpmiPassword) + p.IpmiInterface.Set(profile.IpmiInterface) p.RuntimeOverlay.Set(profile.RuntimeOverlay) p.SystemOverlay.Set(profile.SystemOverlay) p.Root.Set(profile.Root) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 406c656d..079434b5 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -29,6 +29,7 @@ type NodeConf struct { IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"` IpmiNetmask string `yaml:"ipmi netmask,omitempty"` IpmiGateway string `yaml:"ipmi gateway,omitempty"` + IpmiInterface string `yaml:"ipmi interface,omitempty"` RuntimeOverlay string `yaml:"runtime overlay,omitempty"` SystemOverlay string `yaml:"system overlay,omitempty"` Init string `yaml:"init,omitempty"` @@ -75,6 +76,7 @@ type NodeInfo struct { IpmiGateway Entry IpmiUserName Entry IpmiPassword Entry + IpmiInterface Entry RuntimeOverlay Entry SystemOverlay Entry Root Entry diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index ce22dea1..1c6e42ac 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -66,6 +66,7 @@ func (config *nodeYaml) NodeUpdate(node NodeInfo) error { config.Nodes[nodeID].IpmiGateway = node.IpmiGateway.GetReal() config.Nodes[nodeID].IpmiUserName = node.IpmiUserName.GetReal() config.Nodes[nodeID].IpmiPassword = node.IpmiPassword.GetReal() + config.Nodes[nodeID].IpmiInterface = node.IpmiInterface.GetReal() config.Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal() config.Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal() config.Nodes[nodeID].Root = node.Root.GetReal() @@ -149,6 +150,7 @@ func (config *nodeYaml) ProfileUpdate(profile NodeInfo) error { config.NodeProfiles[profileID].IpmiGateway = profile.IpmiGateway.GetReal() config.NodeProfiles[profileID].IpmiUserName = profile.IpmiUserName.GetReal() config.NodeProfiles[profileID].IpmiPassword = profile.IpmiPassword.GetReal() + config.NodeProfiles[profileID].IpmiInterface = profile.IpmiInterface.GetReal() config.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay.GetReal() config.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay.GetReal() config.NodeProfiles[profileID].Root = profile.Root.GetReal() diff --git a/internal/pkg/overlay/overlay.go b/internal/pkg/overlay/overlay.go index 7936e534..5ec7cd3c 100644 --- a/internal/pkg/overlay/overlay.go +++ b/internal/pkg/overlay/overlay.go @@ -19,17 +19,18 @@ import ( ) type TemplateStruct struct { - Id string - Hostname string - ClusterName string - Container string - Init string - Root string - IpmiIpaddr string - IpmiNetmask string - IpmiGateway string - IpmiUserName string - IpmiPassword string + Id string + Hostname string + ClusterName string + Container string + Init string + Root string + IpmiIpaddr string + IpmiNetmask string + IpmiGateway string + IpmiUserName string + IpmiPassword string + IpmiInterface string NetDevs map[string]*node.NetDevs Keys map[string]string AllNodes []node.NodeInfo @@ -149,6 +150,7 @@ func buildOverlay(nodeList []node.NodeInfo, overlayType string) error { t.IpmiGateway = n.IpmiGateway.Get() t.IpmiUserName = n.IpmiUserName.Get() t.IpmiPassword = n.IpmiPassword.Get() + t.IpmiInterface = n.IpmiInterface.Get() t.NetDevs = make(map[string]*node.NetDevs) t.Keys = make(map[string]string) for devname, netdev := range n.NetDevs { diff --git a/internal/pkg/power/ipmitool.go b/internal/pkg/power/ipmitool.go index aac1ca66..4ef21882 100644 --- a/internal/pkg/power/ipmitool.go +++ b/internal/pkg/power/ipmitool.go @@ -11,11 +11,12 @@ type IPMIResult struct { } type IPMI struct { - NodeName string - HostName string - User string - Password string - AuthType string + NodeName string + HostName string + User string + Password string + AuthType string + Interface string result IPMIResult } @@ -27,9 +28,12 @@ func (ipmi *IPMI) Command(ipmiArgs []string) ([]byte, error) { var args []string - args = append(args, "-I", "lan", "-H", ipmi.HostName, "-U", ipmi.User, "-P", ipmi.Password) + if ipmi.Interface == "" { + ipmi.Interface = "lanplus" + } + args = append(args, "-I", ipmi.Interface, "-H", ipmi.HostName, "-U", ipmi.User, "-P", ipmi.Password) args = append(args, ipmiArgs...) - ipmiCmd := exec.Command("/usr/bin/ipmitool", args...) + ipmiCmd := exec.Command("ipmitool", args...) return ipmiCmd.CombinedOutput() } @@ -37,9 +41,13 @@ func (ipmi *IPMI) InteractiveCommand(ipmiArgs []string) error { var args []string - args = append(args, "-I", "lanplus", "-H", ipmi.HostName, "-U", ipmi.User, "-P", ipmi.Password) + if ipmi.Interface == "" { + ipmi.Interface = "lan" + } + + args = append(args, "-I", ipmi.Interface, "-H", ipmi.HostName, "-U", ipmi.User, "-P", ipmi.Password) args = append(args, ipmiArgs...) - ipmiCmd := exec.Command("/usr/bin/ipmitool", args...) + ipmiCmd := exec.Command("ipmitool", args...) ipmiCmd.Stdout = os.Stdout ipmiCmd.Stdin = os.Stdin ipmiCmd.Stderr = os.Stderr From b27951b59f9b3282516628b41ab79b0ddfedc947 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 16 Jul 2021 14:32:39 +0200 Subject: [PATCH 4/6] added binary to create bash completion also do not bail out, when configs can't be read, still the --- Makefile | 7 ++++++- cmd/bash_completion/bash_completion.go | 23 ++++++++++++++++++++++ cmd/wwctl/main.go | 1 + internal/app/wwctl/root.go | 8 ++++++++ internal/pkg/node/datastructure.go | 3 ++- internal/pkg/warewulfconf/datastructure.go | 4 ++-- 6 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 cmd/bash_completion/bash_completion.go diff --git a/Makefile b/Makefile index 0ba63bb8..b041f180 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ GOLANGCI_LINT_VERSION := v1.31.0 # built tags needed for wwbuild binary WW_BUILD_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree -all: setup_tools vendor wwctl wwclient +all: setup_tools vendor wwctl wwclient bash_completion # set the go tools into the tools bin. setup_tools: $(GO_TOOLS_BIN) $(GOLANGCI_LINT) @@ -53,6 +53,8 @@ files: all install -d -m 0755 $(DESTDIR)/etc/warewulf/ install -d -m 0755 $(DESTDIR)/etc/warewulf/ipxe install -d -m 0755 $(DESTDIR)/var/lib/tftpboot/warewulf/ipxe/ + install -d -m 0755 $(DESTDIR)/etc/bash_completion.d/ + ./bash_completion $(DESTDIR)/etc/bash_completion.d/warewulf test -f $(DESTDIR)/etc/warewulf/warewulf.conf || install -m 644 etc/warewulf.conf $(DESTDIR)/etc/warewulf/ test -f $(DESTDIR)/etc/warewulf/hosts.tmpl || install -m 644 etc/hosts.tmpl $(DESTDIR)/etc/warewulf/ cp -r etc/dhcp $(DESTDIR)/etc/warewulf/ @@ -84,6 +86,9 @@ wwctl: wwclient: cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags '-extldflags -static' -o ../../wwclient +bash_completion: + cd cmd/bash_completion; go build -mod vendor -tags "$(WW_BUILD_GO_BUILD_TAGS)" -o ../../bash_completion + dist: vendor rm -rf _dist/warewulf-$(VERSION) mkdir -p _dist/warewulf-$(VERSION) diff --git a/cmd/bash_completion/bash_completion.go b/cmd/bash_completion/bash_completion.go new file mode 100644 index 00000000..2a300c87 --- /dev/null +++ b/cmd/bash_completion/bash_completion.go @@ -0,0 +1,23 @@ +// usage: ./bash_completion +package main + +import ( + "fmt" + "os" + "github.com/hpcng/warewulf/internal/app/wwctl" +) + +func main() { + fh, err := os.Create(os.Args[1]) + if err != nil { + fmt.Println(err) + return + } + + defer fh.Close() + + if err := wwctl.GenBashCompletion(fh); err != nil { + fmt.Println(err) + return + } +} diff --git a/cmd/wwctl/main.go b/cmd/wwctl/main.go index 0676131e..e1e0f479 100644 --- a/cmd/wwctl/main.go +++ b/cmd/wwctl/main.go @@ -9,3 +9,4 @@ func main() { root.Execute() } + diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index e355cd37..7e810b13 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -1,6 +1,7 @@ package wwctl import ( + "io" "github.com/hpcng/warewulf/internal/app/wwctl/configure" "github.com/hpcng/warewulf/internal/app/wwctl/container" "github.com/hpcng/warewulf/internal/app/wwctl/kernel" @@ -59,3 +60,10 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) error { } return nil } + +// GenBashCompletionFile +func GenBashCompletion(w io.Writer) error { + return rootCmd.GenBashCompletion(w) +} + + diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 406c656d..8d7527c9 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -101,7 +101,8 @@ func init() { c, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE, 0644) if err != nil { wwlog.Printf(wwlog.ERROR, "Could not create new configuration file: %s\n", err) - os.Exit(1) + // just return silently, as init is also called for bash_completion + return } fmt.Fprintf(c, "nodeprofiles:\n") diff --git a/internal/pkg/warewulfconf/datastructure.go b/internal/pkg/warewulfconf/datastructure.go index da2dc0ad..c47a08d8 100644 --- a/internal/pkg/warewulfconf/datastructure.go +++ b/internal/pkg/warewulfconf/datastructure.go @@ -1,7 +1,6 @@ package warewulfconf import ( - "os" "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" @@ -52,6 +51,7 @@ func init() { //TODO: Check to make sure nodes.conf is found if util.IsFile(ConfigFile) == false { wwlog.Printf(wwlog.ERROR, "Configuration file not found: %s\n", ConfigFile) - os.Exit(1) + // fail silently as this also called by bash_completion + return } } From 8d5162f88a6868e5750f5095768c16e9570fe4df Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 22 Jul 2021 11:53:58 +0200 Subject: [PATCH 5/6] automatic man page generation --- Makefile | 10 +++++++++- cmd/man_page/man_page.go | 16 ++++++++++++++++ internal/app/wwctl/root.go | 11 +++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 cmd/man_page/man_page.go diff --git a/Makefile b/Makefile index b041f180..a8cb43ce 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ GOLANGCI_LINT_VERSION := v1.31.0 # built tags needed for wwbuild binary WW_BUILD_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree -all: setup_tools vendor wwctl wwclient bash_completion +all: setup_tools vendor wwctl wwclient bash_completion man_page # set the go tools into the tools bin. setup_tools: $(GO_TOOLS_BIN) $(GOLANGCI_LINT) @@ -54,7 +54,10 @@ files: all install -d -m 0755 $(DESTDIR)/etc/warewulf/ipxe install -d -m 0755 $(DESTDIR)/var/lib/tftpboot/warewulf/ipxe/ install -d -m 0755 $(DESTDIR)/etc/bash_completion.d/ + install -d -m 0755 $(DESTDIR)/usr/share/man/man1 ./bash_completion $(DESTDIR)/etc/bash_completion.d/warewulf + ./man_page $(DESTDIR)/usr/share/man/man1 + gzip $(DESTDIR)/usr/share/man/man1/wwctl*1 test -f $(DESTDIR)/etc/warewulf/warewulf.conf || install -m 644 etc/warewulf.conf $(DESTDIR)/etc/warewulf/ test -f $(DESTDIR)/etc/warewulf/hosts.tmpl || install -m 644 etc/hosts.tmpl $(DESTDIR)/etc/warewulf/ cp -r etc/dhcp $(DESTDIR)/etc/warewulf/ @@ -89,6 +92,9 @@ wwclient: bash_completion: cd cmd/bash_completion; go build -mod vendor -tags "$(WW_BUILD_GO_BUILD_TAGS)" -o ../../bash_completion +man_page: + cd cmd/man_page; go build -mod vendor -tags "$(WW_BUILD_GO_BUILD_TAGS)" -o ../../man_page + dist: vendor rm -rf _dist/warewulf-$(VERSION) mkdir -p _dist/warewulf-$(VERSION) @@ -102,6 +108,8 @@ clean: rm -f wwctl rm -rf _dist rm -f warewulf-$(VERSION).tar.gz + rm -f bash_completion + rm -f man_page install: files diff --git a/cmd/man_page/man_page.go b/cmd/man_page/man_page.go new file mode 100644 index 00000000..45d42416 --- /dev/null +++ b/cmd/man_page/man_page.go @@ -0,0 +1,16 @@ +// usage: ./bash_completion +package main + +import ( + "fmt" + "os" + "github.com/hpcng/warewulf/internal/app/wwctl" +) + +func main() { + + if err := wwctl.GenManTree(os.Args[1]); err != nil { + fmt.Println(err) + return + } +} diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index 7e810b13..c6d9023c 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -1,7 +1,7 @@ package wwctl import ( - "io" + "io" "github.com/hpcng/warewulf/internal/app/wwctl/configure" "github.com/hpcng/warewulf/internal/app/wwctl/container" "github.com/hpcng/warewulf/internal/app/wwctl/kernel" @@ -13,6 +13,7 @@ import ( "github.com/hpcng/warewulf/internal/app/wwctl/server" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" ) var ( @@ -66,4 +67,10 @@ func GenBashCompletion(w io.Writer) error { return rootCmd.GenBashCompletion(w) } - +func GenManTree(fileName string) error{ + header := &doc.GenManHeader{ + Title: "MINE", + Section: "1", + } + return doc.GenManTree(rootCmd,header,fileName) +} From aae843287007a1692d561a5bbde07f09fced25f0 Mon Sep 17 00:00:00 2001 From: "Michael L. Young" Date: Thu, 19 Aug 2021 22:41:10 -0400 Subject: [PATCH 6/6] Use Module Mirror For Downloads - By using the module mirror, we get around the issue of using an older git client such as that which comes with CentOS 7. - Using a module mirror helps to speed up module downloads. Fixes #89 --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index d2fc0b91..e25436a7 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,10 @@ GO_TOOLS_VENDOR := $(addprefix vendor/, $(GO_TOOLS)) GOLANGCI_LINT := $(TOOLS_BIN)/golangci-lint GOLANGCI_LINT_VERSION := v1.31.0 +# use GOPROXY for older git clients and speed up downloads +GOPROXY ?= https://proxy.golang.org +export GOPROXY + # built tags needed for wwbuild binary WW_BUILD_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree