Added controllers, services, and lots of various optimizations and fixes

This commit is contained in:
Gregory Kurtzer
2020-11-30 23:07:42 -08:00
parent 210d0044a5
commit 4d752a67db
35 changed files with 1147 additions and 365 deletions

View File

@@ -22,6 +22,8 @@ sudo make install
```
sudo ./wwctl profile set -K $(uname -r) -V docker://warewulf/centos-8 default
sudo ./wwctl node add [node name]
sudo ./wwctl node set --netdev eth0 -I 192.168.1.10 -M 255.255.255.0 -G 192.168.1.1 -H aa:bb:cc:dd:ee:ff
```

View File

@@ -1,4 +1,3 @@
allow booting;
allow bootp;
ddns-update-style interim;
@@ -13,8 +12,6 @@ option ipxe.no-pxedhcp 1;
option architecture-type code 93 = unsigned integer 16;
if exists user-class and option user-class = "iPXE" {
#filename "http://192.168.1.1/WW4/ipxe/${mac:hexhyp}";
#filename "http://192.168.1.1:9873/ipxe?hwaddr=${mac:hexhyp}";
filename "http://192.168.1.1:9873/ipxe/${mac:hexhyp}";
} else {
if option architecture-type = 00:0B {
@@ -32,23 +29,14 @@ if exists user-class and option user-class = "iPXE" {
}
}
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.10 192.168.1.99;
subnet {{.Ipaddr}} netmask {{.Netmask}} {
range {{.RangeStart}} {{.RangeEnd}};
next-server 192.168.1.1;
}
}
#subnet 192.168.1.0 netmask 255.255.255.0 {
# not authoritative;
# option subnet-mask 255.255.255.0;
#}
#group {
# host n0000_localdomain-eth0 {
# option host-name n0000;
# option domain-name "localdomain";
# hardware ethernet 00:0c:29:c3:bf:42;
# fixed-address 192.168.1.100;
# next-server 192.168.1.1;
# }
{{range .Nodes}}
#host {{.Fqdn}} {
# hardware ethernet {{.NetDevs.eth0.Hwaddr}}
# filed-address {{.NetDevs.eth0.Ipaddr}}
#}
{{end}}

View File

@@ -1,52 +1,87 @@
nodeprofiles:
default:
comment: ""
vnfs: ""
kernel version: ""
kernel args: crashkernel=no quiet
nodegroups:
default:
comment: This is the default group
domain name: cluster01
profiles:
- default
nodes:
n0000:
hostname: n0000
netdevs:
eth0:
type: ethernet
hwaddr: 00:0c:29:23:8b:48
ipaddr: 192.168.1.100
netmask: 255.255.255.0
gateway: 192.168.1.1
ib0:
type: infiniband
hwaddr: aa:bb:cc:dd:ee:a0
ipaddr: 192.168.10.100
netmask: 255.255.255.0
n0001:
hostname: n0001
ipmi ipaddr: x.x.x.x
netdevs:
eth0:
hwaddr: aa:bb:cc:dd:ee:b0
ipaddr: 192.168.1.101
netmask: 255.255.255.0
gateway: 192.168.1.1
ib0:
hwaddr: aa:bb:cc:dd:ee:b1
ipaddr: 192.168.10.100
netmask: 255.255.255.0
group_1:
comment: This is the group 1
domain name: group1
profiles:
- default
nodes:
n0000:
hostname: n0000
netdevs:
eth0:
hwaddr: aa:bb:cc:dd:ee:c0
ipaddr: 192.168.2.100
netmask: 255.255.255.0
gateway: 192.168.2.1
control:
headnode01:
comment: This is the first control system
ipaddr: 192.168.1.1
services:
warewulfd:
port: 9873
secure: true
dhcp:
enabled: true
range start: 192.168.1.100
range end: 192.168.1.250
assign static: false
config file: /etc/dhcp/dhcpd.conf
start command: service dhcp start
restart command: killall dhcpd -HUP
enable command: chkconfig dhcp on
tftp:
enabled: true
tftproot: /var/lib/tftproot
start command: service tftp start
restart command: service tftp restart
enable command: chkconfig tftp on
nfs:
enabled: true
config file: /etc/exports
exports:
- /var/warewulf 192.168.1.1/255.255.255.0(ro,no_root_squash)
- /home 192.168.1.1/255.255.255.0(rw,no_root_squash)
start command: service nfs start
restart command: service nfs restart
enable command: chkconfig nfs on
nodegroups:
default:
comment: This is the default group
domain name: cluster01
profiles:
- default
nodes:
n0000:
hostname: n0000
netdevs:
eth0:
type: ethernet
hwaddr: 00:0c:29:23:8b:48
ipaddr: 192.168.1.100
netmask: 255.255.255.0
gateway: 192.168.1.1
ib0:
type: infiniband
hwaddr: aa:bb:cc:dd:ee:a0
ipaddr: 192.168.10.100
netmask: 255.255.255.0
n0001:
hostname: n0001
ipmi ipaddr: x.x.x.x
netdevs:
eth0:
hwaddr: aa:bb:cc:dd:ee:b0
ipaddr: 192.168.1.101
netmask: 255.255.255.0
gateway: 192.168.1.1
ib0:
hwaddr: aa:bb:cc:dd:ee:b1
ipaddr: 192.168.10.100
netmask: 255.255.255.0
group_1:
comment: This is the group 1
domain name: group1
profiles:
- default
nodes:
n0000:
hostname: n0000
netdevs:
eth0:
hwaddr: aa:bb:cc:dd:ee:c0
ipaddr: 192.168.2.100
netmask: 255.255.255.0
gateway: 192.168.2.1

View File

@@ -0,0 +1,29 @@
package add
import (
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed opening node database: %s\n", err)
os.Exit(1)
}
for _, c := range args {
err = nodeDB.AddController(c)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
nodeDB.Persist()
return nil
}

View File

@@ -0,0 +1,23 @@
package add
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "add",
Short: "Add",
Long: "Add",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetController string
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,61 @@
package delete
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var count int
var numNodes int
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed to open node database: %s\n", err)
os.Exit(1)
}
nodes, err := nodeDB. FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not load all nodes: %s\n", err)
os.Exit(1)
}
for _, c := range args {
err := nodeDB.DelController(c)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
} else {
for _, n := range nodes {
if n.Cid.Get() == c {
numNodes ++
}
}
count ++
}
}
if count > 0 {
q := fmt.Sprintf("Are you sure you want to delete %d controllers(s) (%d nodes)", count, numNodes)
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
wwlog.Printf(wwlog.INFO, "No controllers found\n")
}
return nil
}

View File

@@ -0,0 +1,23 @@
package delete
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "delete",
Short: "Delete",
Long: "Delete",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetController string
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,45 @@
package list
import "C"
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"reflect"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
controllers, err := nodeDB.FindAllControllers()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find all nodes: %s\n", err)
os.Exit(1)
}
if ShowAll == true {
for _, controller := range controllers {
v := reflect.ValueOf(controller)
typeOfS := v.Type()
fmt.Printf("################################################################################\n")
for i := 0; i< v.NumField(); i++ {
fmt.Printf("%-25s %s = %v\n", controller.Id, typeOfS.Field(i).Name, v.Field(i).Interface())
}
}
} else {
fmt.Printf("%-22s\n", "CONTROLLER NAME")
for _, c := range controllers {
fmt.Printf("%-22s\n", c.Id)
}
}
return nil
}

View File

@@ -0,0 +1,23 @@
package list
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "list",
Short: "List",
Long: "List",
RunE: CobraRunE,
}
ShowAll bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&ShowAll, "all", "a", false, "Show all node configurations")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,30 @@
package controller
import (
"github.com/spf13/cobra"
"github.com/hpcng/warewulf/internal/app/wwctl/controller/add"
"github.com/hpcng/warewulf/internal/app/wwctl/controller/delete"
"github.com/hpcng/warewulf/internal/app/wwctl/controller/list"
"github.com/hpcng/warewulf/internal/app/wwctl/controller/set"
)
var (
baseCmd = &cobra.Command{
Use: "controller",
Short: "Controller management",
Long: "Management of group settings and power management",
}
)
func init() {
baseCmd.AddCommand(list.GetCommand())
baseCmd.AddCommand(set.GetCommand())
baseCmd.AddCommand(add.GetCommand())
baseCmd.AddCommand(delete.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,94 @@
package set
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var err error
var controllers []node.ControllerInfo
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
if SetAll == true {
var tmp []node.ControllerInfo
tmp, err = nodeDB.FindAllControllers()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, c := range tmp {
controllers = append(controllers, c)
}
} else if len(args) > 0 {
var tmp []node.ControllerInfo
tmp, err = nodeDB.FindAllControllers()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, a := range args {
for _, c := range tmp {
if c.Id == a {
controllers = append(controllers, c)
}
}
}
} else {
cmd.Usage()
os.Exit(1)
}
for _, c := range controllers {
if SetIpaddr != "" {
wwlog.Printf(wwlog.VERBOSE, "Controller: %s, Setting IP Addr to: %s\n", c.Id, SetIpaddr)
c.Ipaddr = SetIpaddr
err := nodeDB.ControllerUpdate(c)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
}
if len(controllers) > 0 {
q := fmt.Sprintf("Are you sure you want to modify %d group(s)", len(controllers))
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
fmt.Printf("No controllers found\n")
}
return nil
}

View File

@@ -0,0 +1,26 @@
package set
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "set",
Short: "Set",
Long: "Set",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetAll bool
SetIpaddr string
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SetAll, "all", "a", false, "Set all controllers")
baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "i", "", "Set the controller's IP address")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -15,7 +15,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, g := range args {
err = nodeDB.AddGroup(g)
err = nodeDB.AddGroup(SetController, g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)

View File

@@ -10,13 +10,12 @@ var (
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetVnfs string
SetKernel string
SetController string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add group to")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -26,12 +26,12 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, g := range args {
err := nodeDB.DelGroup(g)
err := nodeDB.DelGroup(SetController, g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
} else {
for _, n := range nodes {
if n.GroupName.String() == g {
if n.Gid.Get() == g {
numNodes ++
}
}

View File

@@ -9,14 +9,11 @@ var (
Long: "Add a new node group ",
RunE: CobraRunE,
}
SetVnfs string
SetKernel string
// SetGroupLevel bool
SetController string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add group to")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -34,9 +34,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
}
} else {
fmt.Printf("%-22s %-16s %s\n", "GROUP NAME", "DOMAINNAME", "PROFILES")
fmt.Printf("%-22s %-16s %-16s %s\n", "GROUP NAME", "DOMAINNAME", "CONTROLLER", "PROFILES")
for _, g := range groups {
fmt.Printf("%-22s %-16s %s\n", g.Id, g.DomainName, strings.Join(g.Profiles, ","))
fmt.Printf("%-22s %-16s %-16s %s\n", g.Id, g.DomainName, g.Cid, strings.Join(g.Profiles, ","))
}
}

View File

@@ -16,7 +16,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
for _, a := range args {
err = nodeDB.AddNode(SetGroup, a)
err = nodeDB.AddNode(SetController, SetGroup, a)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)

View File

@@ -11,10 +11,12 @@ var (
Args: cobra.MinimumNArgs(1),
}
SetGroup string
SetController string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetGroup, "group", "g", "default", "Set group to add nodes to")
baseCmd.PersistentFlags().StringVarP(&SetGroup, "group", "g", "default", "Group to add nodes to")
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add nodes to")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -21,11 +21,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
nodeList, err := nodeDB.SearchByNameList(args)
for _, n := range nodeList {
if SetGroup != "" && SetGroup != n.GroupName.String() {
wwlog.Printf(wwlog.DEBUG, "skipping node of different group: %s/%s\n", n.GroupName, n.Id)
if SetGroup != "" && SetGroup != n.Gid.String() {
wwlog.Printf(wwlog.DEBUG, "skipping node of different group: %s/%s\n", n.Gid, n.Id)
continue
}
err := nodeDB.DelNode(n.GroupName.String(), n.Id.String())
err := nodeDB.DelNode(n.Cid.Get(), n.Gid.Get(), n.Id.Get())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
} else {

View File

@@ -11,11 +11,13 @@ var (
}
SetForce string
SetGroup string
SetController string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetForce, "force", "f", "", "Force node delete")
baseCmd.PersistentFlags().StringVarP(&SetGroup, "group", "g", "default", "Set group to delete nodes from")
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add nodes to")
}

View File

@@ -37,7 +37,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Printf("################################################################################\n")
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Id", node.Id.Source(), node.Id.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Comment", node.Comment.Source(), node.Comment.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "GroupName", node.GroupName.Source(), node.GroupName.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "GroupName", node.Gid.Source(), node.Gid.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "DomainName", node.DomainName.Source(), node.DomainName.String())
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Profiles (Group)", "group", strings.Join(node.GroupProfiles, ","))
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Profiles (Node)", "node", strings.Join(node.Profiles, ","))
@@ -93,7 +93,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Println(strings.Repeat("=", 120))
for _, node := range nodes {
fmt.Printf("%-22s %-12s %-26s %-35s %s\n", node.Fqdn.Get(), node.GroupName.String(), node.KernelVersion.String(), node.Vnfs.String(), node.SystemOverlay.String() +"/"+ node.RuntimeOverlay.String())
fmt.Printf("%-22s %-12s %-26s %-35s %s\n", node.Fqdn.Get(), node.Gid.String(), node.KernelVersion.String(), node.Vnfs.String(), node.SystemOverlay.String() +"/"+ node.RuntimeOverlay.String())
}
} else {

View File

@@ -38,7 +38,7 @@ func init() {
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system overlay")
baseCmd.PersistentFlags().StringVarP(&SetHostname, "hostname", "H", "", "Set the node's hostname")
baseCmd.PersistentFlags().StringVarP(&SetHostname, "hostname", "N", "", "Set the node's hostname")
baseCmd.PersistentFlags().StringVar(&SetIpmiIpaddr, "ipmi", "", "Set the node's IPMI address")
baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username")
baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password")
@@ -50,7 +50,7 @@ func init() {
baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "I", "", "Set the node's network device IP address")
baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask")
baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway")
baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "N", "", "Set the node's network device HW address")
baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "H", "", "Set the node's network device HW address")
baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "delete", false, "Delete the node's network device")
baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes")

View File

@@ -69,7 +69,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Fprintf(w, "\n")
}
shasum1, err := util.ShaSumFile(overlayFile)
if err != nil {
wwlog.Printf(wwlog.WARN, "Could not open overlay file for checksum: %s\n", err)
@@ -80,7 +79,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
wwlog.Printf(wwlog.ERROR, "Editor process existed with non-zero\n")
os.Exit(1)
}
wwlog.Printf(wwlog.INFO, "Updated: %s %s\n", args[0], args[1] )
wwlog.Printf(wwlog.INFO, "Updated: %s %s\n", args[0], args[1])
shasum2, err := util.ShaSumFile(overlayFile)
if err != nil {
@@ -126,4 +125,3 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
return nil
}

View File

@@ -143,7 +143,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if len(profiles) > 0 {
q := fmt.Sprintf("Are you sure you want to modify %d group(s)", len(profiles))
q := fmt.Sprintf("Are you sure you want to modify %d profile(s)", len(profiles))
prompt := promptui.Prompt{
Label: q,

View File

@@ -1,11 +1,13 @@
package wwctl
import (
"github.com/hpcng/warewulf/internal/app/wwctl/controller"
"github.com/hpcng/warewulf/internal/app/wwctl/group"
"github.com/hpcng/warewulf/internal/app/wwctl/kernel"
"github.com/hpcng/warewulf/internal/app/wwctl/node"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay"
"github.com/hpcng/warewulf/internal/app/wwctl/profile"
"github.com/hpcng/warewulf/internal/app/wwctl/services"
"github.com/hpcng/warewulf/internal/app/wwctl/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
@@ -14,26 +16,29 @@ import (
var (
rootCmd = &cobra.Command{
Use: "wwctl",
Short: "Warewulf Control",
Long: "Control interface to the Cluster Warewulf Provisioning System.",
PersistentPreRunE: rootPersistentPreRunE,
Use: "wwctl",
Short: "Warewulf Control",
Long: "Control interface to the Cluster Warewulf Provisioning System.",
PersistentPreRunE: rootPersistentPreRunE,
}
verboseArg bool
debugArg bool
debugArg bool
)
func init() {
rootCmd.PersistentFlags().BoolVarP(&verboseArg, "verbose", "v", false, "Run with increased verbosity.")
rootCmd.PersistentFlags().BoolVarP(&debugArg, "debug", "d", false, "Run with debugging messages enabled.")
rootCmd.AddCommand(overlay.GetCommand())
//rootCmd.AddCommand(build.GetCommand())
rootCmd.AddCommand(overlay.GetCommand())
rootCmd.AddCommand(controller.GetCommand())
rootCmd.AddCommand(vnfs.GetCommand())
rootCmd.AddCommand(node.GetCommand())
rootCmd.AddCommand(kernel.GetCommand())
rootCmd.AddCommand(group.GetCommand())
rootCmd.AddCommand(profile.GetCommand())
rootCmd.AddCommand(services.GetCommand())
}
@@ -51,4 +56,4 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) error {
wwlog.SetLevel(wwlog.INFO)
}
return nil
}
}

View File

@@ -0,0 +1,109 @@
package dhcp
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"net"
"os"
"text/template"
)
type dhcpTemplate struct {
Ipaddr string
RangeStart string
RangeEnd string
Netmask string
Nodes []node.NodeInfo
}
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
controllers, err := nodeDB.FindAllControllers()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find all controllers: %s\n", err)
os.Exit(1)
}
for _, controller := range controllers {
var d dhcpTemplate
var configured bool
addrs, err := net.InterfaceAddrs()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not get network interfaces: %s\n", err)
os.Exit(1)
}
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.String() == controller.Ipaddr {
mask := ipnet.IP.DefaultMask()
d.Ipaddr = ipnet.IP.String()
d.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
d.RangeStart = controller.Services.Dhcp.RangeStart
d.RangeEnd = controller.Services.Dhcp.RangeEnd
configured = true
fmt.Printf("%#v\n", d)
break
}
}
}
if configured == false {
wwlog.Printf(wwlog.ERROR, "Could not identify this system in the Warewulf configuration by it's IP address\n")
os.Exit(1)
}
if controller.Services.Dhcp.ConfigFile == "" {
wwlog.Printf(wwlog.ERROR, "Could not locate the DHCP configuration file for this controller\n")
os.Exit(1)
}
if _, ok := nodeDB.Controllers[controller.Id]; !ok {
wwlog.Printf(wwlog.ERROR, "We should never get here, but since we did, Hello! %s\n", err)
os.Exit(1)
}
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find all controllers: %s\n", err)
os.Exit(1)
}
for _, node := range nodes {
d.Nodes = append(d.Nodes, node)
}
tmpl, err := template.New("default-dhcpd.conf").ParseFiles("/etc/warewulf/dhcp/default-dhcpd.conf")
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
// w, err := os.OpenFile(controller.Services.Dhcp.ConfigFile, os.O_RDWR|os.O_CREATE, 0640)
// if err != nil {
// wwlog.Printf(wwlog.ERROR, "%s\n", err)
// os.Exit(1)
// }
// defer w.Close()
err = tmpl.Execute(os.Stdout, d)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
// Just in case we get here, we've now finished the loop
break
}
return nil
}

View File

@@ -0,0 +1,23 @@
package dhcp
import (
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
Use: "dhcp",
Short: "DHCP configuration",
Long: "DHCP Config",
RunE: CobraRunE,
}
test bool
)
func init() {
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,23 @@
package services
import (
"github.com/hpcng/warewulf/internal/app/wwctl/services/dhcp"
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
Use: "services",
Short: "Initialize Warewulf services",
Long: "Warewulf Initialization",
}
)
func init() {
baseCmd.AddCommand(dhcp.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -30,78 +30,80 @@ func New() (nodeYaml, error) {
func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
var ret []NodeInfo
for groupname, group := range self.NodeGroups {
for nodename, node := range group.Nodes {
var n NodeInfo
var allProfiles []string
for controllername, controller := range self.Controllers {
for groupname, group := range controller.NodeGroups {
for nodename, node := range group.Nodes {
var n NodeInfo
var allProfiles []string
if node.Disabled == true || group.Disabled == true {
wwlog.Printf(wwlog.VERBOSE, "Skipping disabled node: %s/%s\n", groupname, nodename)
continue
}
n.Id.Set(nodename)
n.Gid.Set(groupname)
n.GroupName.Set(groupname)
n.HostName.Set(node.Hostname)
n.IpmiIpaddr.Set(node.IpmiIpaddr)
n.DomainName.Set(node.DomainName)
n.Vnfs.Set(node.Vnfs)
n.KernelVersion.Set(node.KernelVersion)
n.KernelArgs.Set(node.KernelArgs)
n.Ipxe.Set(node.Ipxe)
n.IpmiUserName.Set(node.IpmiUserName)
n.IpmiPassword.Set(node.IpmiPassword)
n.SystemOverlay.Set(node.SystemOverlay)
n.RuntimeOverlay.Set(node.RuntimeOverlay)
n.DomainName.SetGroup(group.DomainName)
n.Vnfs.SetGroup(group.Vnfs)
n.KernelVersion.SetGroup(group.KernelVersion)
n.KernelArgs.SetGroup(group.KernelArgs)
n.Ipxe.SetGroup(group.Ipxe)
n.IpmiUserName.SetGroup(group.IpmiUserName)
n.IpmiPassword.SetGroup(group.IpmiPassword)
n.SystemOverlay.SetGroup(group.SystemOverlay)
n.RuntimeOverlay.SetGroup(group.RuntimeOverlay)
n.RuntimeOverlay.SetDefault("default")
n.SystemOverlay.SetDefault("default")
n.Ipxe.SetDefault("default")
n.KernelArgs.SetDefault("crashkernel=no quiet")
n.GroupProfiles = group.Profiles
n.Profiles = node.Profiles
allProfiles = append(allProfiles, group.Profiles...)
allProfiles = append(allProfiles, node.Profiles...)
for _, p := range allProfiles {
if _, ok := self.NodeProfiles[p]; !ok {
wwlog.Printf(wwlog.WARN, "Profile not found for node '%s': %s\n", nodename, p)
if node.Disabled == true || group.Disabled == true {
wwlog.Printf(wwlog.VERBOSE, "Skipping disabled node: %s/%s\n", groupname, nodename)
continue
}
n.DomainName.SetProfile(self.NodeProfiles[p].DomainName)
n.Vnfs.SetProfile(self.NodeProfiles[p].Vnfs)
n.KernelVersion.SetProfile(self.NodeProfiles[p].KernelVersion)
n.KernelArgs.SetProfile(self.NodeProfiles[p].KernelArgs)
n.Ipxe.SetProfile(self.NodeProfiles[p].Ipxe)
n.IpmiUserName.SetProfile(self.NodeProfiles[p].IpmiUserName)
n.IpmiPassword.SetProfile(self.NodeProfiles[p].IpmiPassword)
n.SystemOverlay.SetProfile(self.NodeProfiles[p].SystemOverlay)
n.RuntimeOverlay.SetProfile(self.NodeProfiles[p].RuntimeOverlay)
n.Id.Set(nodename)
n.Gid.Set(groupname)
n.Cid.Set(controllername)
n.HostName.Set(node.Hostname)
n.IpmiIpaddr.Set(node.IpmiIpaddr)
n.DomainName.Set(node.DomainName)
n.Vnfs.Set(node.Vnfs)
n.KernelVersion.Set(node.KernelVersion)
n.KernelArgs.Set(node.KernelArgs)
n.Ipxe.Set(node.Ipxe)
n.IpmiUserName.Set(node.IpmiUserName)
n.IpmiPassword.Set(node.IpmiPassword)
n.SystemOverlay.Set(node.SystemOverlay)
n.RuntimeOverlay.Set(node.RuntimeOverlay)
n.DomainName.SetGroup(group.DomainName)
n.Vnfs.SetGroup(group.Vnfs)
n.KernelVersion.SetGroup(group.KernelVersion)
n.KernelArgs.SetGroup(group.KernelArgs)
n.Ipxe.SetGroup(group.Ipxe)
n.IpmiUserName.SetGroup(group.IpmiUserName)
n.IpmiPassword.SetGroup(group.IpmiPassword)
n.SystemOverlay.SetGroup(group.SystemOverlay)
n.RuntimeOverlay.SetGroup(group.RuntimeOverlay)
n.RuntimeOverlay.SetDefault("default")
n.SystemOverlay.SetDefault("default")
n.Ipxe.SetDefault("default")
n.KernelArgs.SetDefault("crashkernel=no quiet")
n.GroupProfiles = group.Profiles
n.Profiles = node.Profiles
allProfiles = append(allProfiles, group.Profiles...)
allProfiles = append(allProfiles, node.Profiles...)
for _, p := range allProfiles {
if _, ok := self.NodeProfiles[p]; !ok {
wwlog.Printf(wwlog.WARN, "Profile not found for node '%s': %s\n", nodename, p)
continue
}
n.DomainName.SetProfile(self.NodeProfiles[p].DomainName)
n.Vnfs.SetProfile(self.NodeProfiles[p].Vnfs)
n.KernelVersion.SetProfile(self.NodeProfiles[p].KernelVersion)
n.KernelArgs.SetProfile(self.NodeProfiles[p].KernelArgs)
n.Ipxe.SetProfile(self.NodeProfiles[p].Ipxe)
n.IpmiUserName.SetProfile(self.NodeProfiles[p].IpmiUserName)
n.IpmiPassword.SetProfile(self.NodeProfiles[p].IpmiPassword)
n.SystemOverlay.SetProfile(self.NodeProfiles[p].SystemOverlay)
n.RuntimeOverlay.SetProfile(self.NodeProfiles[p].RuntimeOverlay)
}
if n.DomainName.Defined() == true {
n.Fqdn.Set(node.Hostname + "." + n.DomainName.Get())
} else {
n.Fqdn.Set(node.Hostname)
}
n.NetDevs = node.NetDevs
ret = append(ret, n)
}
if n.DomainName.Defined() == true {
n.Fqdn.Set(node.Hostname +"."+ n.DomainName.Get())
} else {
n.Fqdn.Set(node.Hostname)
}
n.NetDevs = node.NetDevs
ret = append(ret, n)
}
}
@@ -111,25 +113,76 @@ func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
var ret []GroupInfo
for groupname, group := range self.NodeGroups {
var g GroupInfo
for controllername, controller := range self.Controllers {
for groupname, group := range controller.NodeGroups {
var g GroupInfo
g.Id = groupname
g.DomainName = group.DomainName
g.Comment = group.Comment
g.Vnfs = group.Vnfs
g.KernelVersion = group.KernelVersion
g.KernelArgs = group.KernelArgs
g.IpmiPassword = group.IpmiPassword
g.IpmiUserName = group.IpmiUserName
g.SystemOverlay = group.SystemOverlay
g.RuntimeOverlay = group.RuntimeOverlay
g.Id = groupname
g.Cid = controllername
g.DomainName = group.DomainName
g.Comment = group.Comment
g.Vnfs = group.Vnfs
g.KernelVersion = group.KernelVersion
g.KernelArgs = group.KernelArgs
g.IpmiPassword = group.IpmiPassword
g.IpmiUserName = group.IpmiUserName
g.SystemOverlay = group.SystemOverlay
g.RuntimeOverlay = group.RuntimeOverlay
g.Profiles = group.Profiles
g.Profiles = group.Profiles
// TODO: Validate or die on all inputs
ret = append(ret, g)
}
}
return ret, nil
}
func (self *nodeYaml) FindAllControllers() ([]ControllerInfo, error) {
var ret []ControllerInfo
for controllername, controller := range self.Controllers {
var c ControllerInfo
c.Id = controllername
c.Ipaddr = controller.Ipaddr
c.Services = struct {
Warewulfd struct {
Port string
Secure string
StartCmd string
RestartCmd string
EnableCmd string
}
Dhcp struct {
Enabled bool
RangeStart string
RangeEnd string
ConfigFile string
StartCmd string
RestartCmd string
EnableCmd string
}
Tftp struct {
Enabled bool
TftpRoot string
StartCmd string
RestartCmd string
EnableCmd string
}
Nfs struct {
Enabled bool
Exports []string
StartCmd string
RestartCmd string
EnableCmd string
}
}(controller.Services)
// TODO: Validate or die on all inputs
ret = append(ret, g)
ret = append(ret, c)
}
return ret, nil
}
@@ -159,8 +212,6 @@ func (self *nodeYaml) FindAllProfiles() ([]ProfileInfo, error) {
return ret, nil
}
func (self *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
var ret NodeInfo
@@ -193,13 +244,6 @@ func (self *nodeYaml) FindByIpaddr(ipaddr string) (NodeInfo, error) {
return ret, errors.New("No nodes found with IP Addr: " + ipaddr)
}
func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) {
var ret []NodeInfo

View File

@@ -6,127 +6,212 @@ import (
"os"
)
/******
* YAML data representations
******/
type nodeYaml struct {
NodeProfiles map[string]*ProfileConf
NodeGroups map[string]*GroupConf
NodeProfiles map[string]*ProfileConf
Controllers map[string]*ControllerConf `yaml:"control"`
}
type ProfileConf struct {
Comment string `yaml:"comment"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
DomainName string `yaml:"domain name,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
Comment string `yaml:"comment"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
DomainName string `yaml:"domain name,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
}
type ControllerConf struct {
Comment string `yaml:"comment"`
Ipaddr string `yaml:"ipaddr"`
Services struct {
Warewulfd struct {
Port string `yaml:"port"`
Secure string `yaml:"secure,omitempty"`
StartCmd string `yaml:"start command,omitempty"`
RestartCmd string `yaml:"restart command,omitempty"`
EnableCmd string `yaml:"enable command,omitempty"`
} `yaml:"warewulf"`
Dhcp struct {
Enabled bool `yaml:"enabled,omitempty"`
RangeStart string `yaml:"range start,omitempty"`
RangeEnd string `yaml:"range end,omitempty"`
ConfigFile string `yaml:"config file,omitempty"`
StartCmd string `yaml:"start command,omitempty"`
RestartCmd string `yaml:"restart command,omitempty"`
EnableCmd string `yaml:"enable command,omitempty"`
} `yaml:"dhcp,omitempty"`
Tftp struct {
Enabled bool `yaml:"enabled,omitempty"`
TftpRoot string `yaml:"tftp root,omitempty"`
StartCmd string `yaml:"start command,omitempty"`
RestartCmd string `yaml:"restart command,omitempty"`
EnableCmd string `yaml:"enable command,omitempty"`
} `yaml:"tftp,omitempty"`
Nfs struct {
Enabled bool `yaml:"enabled,omitempty"`
Exports []string `yaml:"exports,omitempty"`
StartCmd string `yaml:"start command,omitempty"`
RestartCmd string `yaml:"restart command,omitempty"`
EnableCmd string `yaml:"enable command,omitempty"`
} `yaml:"nfs,omitempty"`
} `yaml:"services"`
NodeGroups map[string]*GroupConf
}
type GroupConf struct {
Comment string `yaml:"comment"`
Disabled bool `yaml:"disabled,omitempty"`
DomainName string `yaml:"domain name"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,omitempty"`
Nodes map[string]*NodeConf
Comment string `yaml:"comment"`
Disabled bool `yaml:"disabled,omitempty"`
DomainName string `yaml:"domain name"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,omitempty"`
Nodes map[string]*NodeConf
}
type NodeConf struct {
Comment string `yaml:"comment,omitempty"`
Disabled bool `yaml:"disabled,omitempty"`
Hostname string `yaml:"hostname,omitempty"`
DomainName string `yaml:"domain name,omitempty"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,omitempty"`
NetDevs map[string]*NetDevs
Comment string `yaml:"comment,omitempty"`
Disabled bool `yaml:"disabled,omitempty"`
Hostname string `yaml:"hostname,omitempty"`
DomainName string `yaml:"domain name,omitempty"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
SystemOverlay string `yaml:"system overlay files,omitempty"`
Profiles []string `yaml:"profiles,omitempty"`
NetDevs map[string]*NetDevs
}
type NetDevs struct {
Type string `yaml:"type,omitempty"`
Hwaddr string
Ipaddr string
Netmask string
Gateway string `yaml:"gateway,omitempty"`
Type string `yaml:"type,omitempty"`
Hwaddr string
Ipaddr string
Netmask string
Gateway string `yaml:"gateway,omitempty"`
}
/******
* Code internal data representations
******/
type NodeInfoEntry struct {
value string
profile string
group string
def string
value string
profile string
group string
controller string
def string
}
type NodeInfo struct {
Id NodeInfoEntry
Gid NodeInfoEntry
Uid NodeInfoEntry
Comment NodeInfoEntry
GroupName NodeInfoEntry
HostName NodeInfoEntry
Fqdn NodeInfoEntry
DomainName NodeInfoEntry
Vnfs NodeInfoEntry
Ipxe NodeInfoEntry
KernelVersion NodeInfoEntry
KernelArgs NodeInfoEntry
IpmiIpaddr NodeInfoEntry
IpmiUserName NodeInfoEntry
IpmiPassword NodeInfoEntry
RuntimeOverlay NodeInfoEntry
SystemOverlay NodeInfoEntry
Profiles []string
GroupProfiles []string
NetDevs map[string]*NetDevs
Id NodeInfoEntry
Gid NodeInfoEntry
Cid NodeInfoEntry
Comment NodeInfoEntry
HostName NodeInfoEntry
Fqdn NodeInfoEntry
DomainName NodeInfoEntry
Vnfs NodeInfoEntry
Ipxe NodeInfoEntry
KernelVersion NodeInfoEntry
KernelArgs NodeInfoEntry
IpmiIpaddr NodeInfoEntry
IpmiUserName NodeInfoEntry
IpmiPassword NodeInfoEntry
RuntimeOverlay NodeInfoEntry
SystemOverlay NodeInfoEntry
Profiles []string
GroupProfiles []string
NetDevs map[string]*NetDevs
}
type ControllerInfo struct {
Id string
Comment string
Ipaddr string
Fqdn string
DomainName string
Services struct {
Warewulfd struct {
Port string
Secure string
StartCmd string
RestartCmd string
EnableCmd string
}
Dhcp struct {
Enabled bool
RangeStart string
RangeEnd string
ConfigFile string
StartCmd string
RestartCmd string
EnableCmd string
}
Tftp struct {
Enabled bool
TftpRoot string
StartCmd string
RestartCmd string
EnableCmd string
}
Nfs struct {
Enabled bool
Exports []string
StartCmd string
RestartCmd string
EnableCmd string
}
}
}
type GroupInfo struct {
Id string
Comment string
Vnfs string
Ipxe string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
DomainName string
RuntimeOverlay string
SystemOverlay string
Profiles []string
Id string
Cid string
Comment string
Vnfs string
Ipxe string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
DomainName string
RuntimeOverlay string
SystemOverlay string
Profiles []string
}
type ProfileInfo struct {
Id string
Comment string
Vnfs string
Ipxe string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
DomainName string
RuntimeOverlay string
SystemOverlay string
Id string
Comment string
Vnfs string
Ipxe string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
DomainName string
RuntimeOverlay string
SystemOverlay string
}
const ConfigFile = "/etc/warewulf/nodes.conf"
func init() {

View File

@@ -14,6 +14,9 @@ func (self *NodeInfoEntry) String() string {
if self.profile != "" {
return self.profile
}
if self.controller != "" {
return self.controller
}
if self.def != "" {
return self.def
}
@@ -30,6 +33,9 @@ func (self *NodeInfoEntry) Source() string {
if self.profile != "" {
return "profile"
}
if self.controller != "" {
return "controller"
}
if self.def != "" {
return "default"
}
@@ -46,6 +52,9 @@ func (self *NodeInfoEntry) Get() string {
if self.profile != "" {
return self.profile
}
if self.controller != "" {
return self.controller
}
if self.def != "" {
return self.def
}
@@ -81,6 +90,13 @@ func (self *NodeInfoEntry) SetProfile(value string) {
self.profile = value
}
func (self *NodeInfoEntry) SetController(value string) {
if value == "" {
return
}
self.controller = value
}
func (self *NodeInfoEntry) Set(value string) {
if value == "" {
return

View File

@@ -14,64 +14,79 @@ import (
*
****/
func (self *nodeYaml) AddNode(groupID string, nodeID string) error {
func (self *nodeYaml) AddNode(controllerID string, groupID string, nodeID string) error {
var node NodeConf
wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID)
if _, ok := self.NodeGroups[groupID]; !ok {
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
if _, ok := self.NodeGroups[groupID].Nodes[groupID]; ok {
if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ok {
return errors.New("Nodename already exists in group: " + nodeID)
}
self.NodeGroups[groupID].Nodes[nodeID] = &node
self.NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID] = &node
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
return nil
}
func (self *nodeYaml) DelNode(groupID string, nodeID string) error {
func (self *nodeYaml) DelNode(controllerID string, groupID string, nodeID string) error {
if _, ok := self.NodeGroups[groupID]; !ok {
return errors.New("Group '" + groupID + "' was not found")
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; !ok {
return errors.New("Node '" + nodeID + "' was not found in group '" + groupID + "'")
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ok {
return errors.New("Nodename does not exist in group: " + nodeID)
}
wwlog.Printf(wwlog.VERBOSE, "Deleting node network device: %s/%s\n", groupID, nodeID)
delete(self.NodeGroups[groupID].Nodes, nodeID)
delete(self.Controllers[controllerID].NodeGroups[groupID].Nodes, nodeID)
return nil
}
func(self *nodeYaml) NodeUpdate(node NodeInfo) error {
controllerID := node.Cid.Get()
groupID := node.Gid.Get()
nodeID := node.Id.Get()
if _, ok := self.NodeGroups[groupID]; !ok {
return errors.New("Group '" + groupID + "' was not found")
}
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; !ok {
return errors.New("Node '" + nodeID + "' was not found in group '" + groupID + "'")
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
self.NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].DomainName = node.DomainName.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].Ipxe = node.Ipxe.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].KernelVersion = node.KernelVersion.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].IpmiIpaddr = node.IpmiIpaddr.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].IpmiUserName = node.IpmiUserName.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].IpmiPassword = node.IpmiPassword.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal()
self.NodeGroups[groupID].Nodes[nodeID].Profiles = node.Profiles
self.NodeGroups[groupID].Nodes[nodeID].NetDevs = node.NetDevs
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ! ok {
return errors.New("Nodename does not exist in group: " + nodeID)
}
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].DomainName = node.DomainName.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Ipxe = node.Ipxe.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].KernelVersion = node.KernelVersion.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].IpmiIpaddr = node.IpmiIpaddr.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].IpmiUserName = node.IpmiUserName.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].IpmiPassword = node.IpmiPassword.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal()
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Profiles = node.Profiles
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].NetDevs = node.NetDevs
return nil
}
@@ -84,51 +99,140 @@ func(self *nodeYaml) NodeUpdate(node NodeInfo) error {
*
****/
func (self *nodeYaml) AddGroup(groupID string) error {
func (self *nodeYaml) AddGroup(controllerID string, groupID string) error {
var group GroupConf
wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID)
if _, ok := self.NodeGroups[groupID]; ok {
return errors.New("Group name already exists: " + groupID)
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
self.NodeGroups[groupID] = &group
self.NodeGroups[groupID].DomainName = groupID
self.NodeGroups[groupID].Profiles = []string{"default"}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ok {
return errors.New("Group already exists: " + groupID)
}
self.Controllers[controllerID].NodeGroups[groupID] = &group
self.Controllers[controllerID].NodeGroups[groupID].DomainName = groupID
self.Controllers[controllerID].NodeGroups[groupID].Profiles = []string{"default"}
return nil
}
func (self *nodeYaml) DelGroup(groupID string) error {
if _, ok := self.NodeGroups[groupID]; !ok {
func (self *nodeYaml) DelGroup(controllerID string, groupID string) error {
return errors.New("Group '" + groupID + "' was not found")
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
wwlog.Printf(wwlog.VERBOSE, "Deleting group: %s\n", groupID)
delete(self.NodeGroups, groupID)
delete(self.Controllers[controllerID].NodeGroups, groupID)
return nil
}
func(self *nodeYaml) GroupUpdate(group GroupInfo) error {
controllerID := group.Cid
groupID := group.Id
if _, ok := self.NodeGroups[groupID]; !ok {
return errors.New("Group '" + groupID + "' was not found")
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
self.NodeGroups[groupID].DomainName = group.DomainName
self.NodeGroups[groupID].Vnfs = group.Vnfs
self.NodeGroups[groupID].KernelVersion = group.KernelVersion
self.NodeGroups[groupID].KernelArgs = group.KernelArgs
self.NodeGroups[groupID].Ipxe = group.Ipxe
self.NodeGroups[groupID].IpmiUserName = group.IpmiUserName
self.NodeGroups[groupID].IpmiPassword = group.IpmiPassword
self.NodeGroups[groupID].RuntimeOverlay = group.RuntimeOverlay
self.NodeGroups[groupID].SystemOverlay = group.SystemOverlay
self.NodeGroups[groupID].Profiles = group.Profiles
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
return errors.New("Group does not exist: " + groupID)
}
self.Controllers[controllerID].NodeGroups[groupID].DomainName = group.DomainName
self.Controllers[controllerID].NodeGroups[groupID].Vnfs = group.Vnfs
self.Controllers[controllerID].NodeGroups[groupID].KernelVersion = group.KernelVersion
self.Controllers[controllerID].NodeGroups[groupID].KernelArgs = group.KernelArgs
self.Controllers[controllerID].NodeGroups[groupID].Ipxe = group.Ipxe
self.Controllers[controllerID].NodeGroups[groupID].IpmiUserName = group.IpmiUserName
self.Controllers[controllerID].NodeGroups[groupID].IpmiPassword = group.IpmiPassword
self.Controllers[controllerID].NodeGroups[groupID].RuntimeOverlay = group.RuntimeOverlay
self.Controllers[controllerID].NodeGroups[groupID].SystemOverlay = group.SystemOverlay
self.Controllers[controllerID].NodeGroups[groupID].Profiles = group.Profiles
return nil
}
/****
*
* CONTROLLER MODIFIERS
*
****/
func (self *nodeYaml) AddController(controllerID string) error {
var controller ControllerConf
var group GroupConf
wwlog.Printf(wwlog.VERBOSE, "Adding new controller: %s/%s\n", controllerID)
if _, ok := self.Controllers[controllerID]; ok {
return errors.New("Controller already exists: " + controllerID)
}
self.Controllers[controllerID] = &controller
self.Controllers[controllerID].NodeGroups = make(map[string]*GroupConf)
self.Controllers[controllerID].NodeGroups["default"] = &group
return nil
}
func (self *nodeYaml) DelController(controllerID string) error {
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
wwlog.Printf(wwlog.VERBOSE, "Deleting controller: %s\n", controllerID)
delete(self.Controllers, controllerID)
return nil
}
func(self *nodeYaml) ControllerUpdate(controller ControllerInfo) error {
controllerID := controller.Id
if _, ok := self.Controllers[controllerID]; ! ok {
return errors.New("Controller does not exist: " + controllerID)
}
self.Controllers[controllerID].Ipaddr = controller.Ipaddr
self.Controllers[controllerID].Comment = controller.Comment
self.Controllers[controllerID].Services.Warewulfd.Port = controller.Services.Warewulfd.Port
self.Controllers[controllerID].Services.Warewulfd.Secure = controller.Services.Warewulfd.Secure
self.Controllers[controllerID].Services.Warewulfd.StartCmd = controller.Services.Warewulfd.StartCmd
self.Controllers[controllerID].Services.Warewulfd.RestartCmd = controller.Services.Warewulfd.RestartCmd
self.Controllers[controllerID].Services.Warewulfd.EnableCmd = controller.Services.Warewulfd.EnableCmd
self.Controllers[controllerID].Services.Dhcp.Enabled = controller.Services.Dhcp.Enabled
self.Controllers[controllerID].Services.Dhcp.ConfigFile = controller.Services.Dhcp.ConfigFile
self.Controllers[controllerID].Services.Dhcp.RangeStart = controller.Services.Dhcp.RangeStart
self.Controllers[controllerID].Services.Dhcp.RangeEnd = controller.Services.Dhcp.RangeEnd
self.Controllers[controllerID].Services.Dhcp.StartCmd = controller.Services.Dhcp.StartCmd
self.Controllers[controllerID].Services.Dhcp.RestartCmd = controller.Services.Dhcp.RestartCmd
self.Controllers[controllerID].Services.Dhcp.EnableCmd = controller.Services.Dhcp.EnableCmd
self.Controllers[controllerID].Services.Nfs.Enabled = controller.Services.Nfs.Enabled
self.Controllers[controllerID].Services.Nfs.Exports = controller.Services.Nfs.Exports
self.Controllers[controllerID].Services.Nfs.StartCmd = controller.Services.Nfs.StartCmd
self.Controllers[controllerID].Services.Nfs.RestartCmd = controller.Services.Nfs.RestartCmd
self.Controllers[controllerID].Services.Nfs.EnableCmd = controller.Services.Nfs.EnableCmd
self.Controllers[controllerID].Services.Tftp.Enabled = controller.Services.Tftp.Enabled
self.Controllers[controllerID].Services.Tftp.TftpRoot = controller.Services.Tftp.TftpRoot
self.Controllers[controllerID].Services.Tftp.StartCmd = controller.Services.Tftp.StartCmd
self.Controllers[controllerID].Services.Tftp.RestartCmd = controller.Services.Tftp.RestartCmd
self.Controllers[controllerID].Services.Tftp.EnableCmd = controller.Services.Tftp.EnableCmd
return nil
}

View File

@@ -18,11 +18,14 @@ import (
)
type TemplateStruct struct {
Fqdn string
Hostname string
Groupname string
Vnfs string
Netdev map[string]*node.NetDevs
Self struct {
Fqdn string
Hostname string
GroupName string
Vnfs string
NetDevs map[string]*node.NetDevs
}
AllNodes []node.NodeInfo
}
func BuildSystemOverlay(nodeList []node.NodeInfo) error {
@@ -49,9 +52,6 @@ func RuntimeOverlayInit(name string) error {
return overlayInit(name, "runtime")
}
func findAllOverlays(overlayType string) ([]string, error) {
config := config.New()
var ret []string
@@ -83,7 +83,6 @@ func findAllOverlays(overlayType string) ([]string, error) {
return ret, nil
}
func overlayInit(name string, overlayType string) error {
var path string
config := config.New()
@@ -100,7 +99,7 @@ func overlayInit(name string, overlayType string) error {
}
if util.IsDir(path) == true {
return errors.New("Overlay already exists: "+name)
return errors.New("Overlay already exists: " + name)
}
err := os.MkdirAll(path, 0755)
@@ -108,13 +107,10 @@ func overlayInit(name string, overlayType string) error {
return err
}
func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
config := config.New()
nodeDB, _ := node.New()
allNodes, _ := nodeDB.FindAllNodes()
for _, node := range nodeList {
var t TemplateStruct
@@ -134,11 +130,12 @@ func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
wwlog.Printf(wwlog.DEBUG, "Processing overlay for node: %s\n", node.Fqdn.Get())
t.Fqdn = node.Fqdn.Get()
t.Hostname = node.HostName.Get()
t.Groupname = node.GroupName.Get()
t.Vnfs = node.Vnfs.Get()
t.Netdev = node.NetDevs
t.Self.Fqdn = node.Fqdn.Get()
t.Self.Hostname = node.HostName.Get()
t.Self.GroupName = node.Gid.Get()
t.Self.Vnfs = node.Vnfs.Get()
t.Self.NetDevs = node.NetDevs
t.AllNodes = allNodes
if overlayType == "runtime" && node.RuntimeOverlay.Defined() == false {
wwlog.Printf(wwlog.WARN, "Undefined runtime overlay, skipping node: %s\n", node.Fqdn.Get())
@@ -230,7 +227,6 @@ func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
return nil
})
wwlog.Printf(wwlog.VERBOSE, "Finished generating overlay directory for: %s\n", node.Fqdn.Get())
cmd := fmt.Sprintf("cd \"%s\"; find . | cpio --quiet -o -H newc -F \"%s\"", tmpDir, OverlayFile)

View File

@@ -59,9 +59,9 @@ func CleanName(source string) string {
tmp = source
}
tmp = strings.ReplaceAll(tmp, "://", "-")
tmp = strings.ReplaceAll(tmp, "/", ".")
tmp = strings.ReplaceAll(tmp, ":", "-")
tmp = strings.ReplaceAll(tmp, "://", ":")
tmp = strings.ReplaceAll(tmp, "/", "-")
tmp = strings.ReplaceAll(tmp, ":", ":")
return tmp
}
@@ -75,6 +75,10 @@ func New(source string) (VnfsObject, error) {
return ret, errors.New("Called vnfs.Load() without a VNFS name")
}
if util.IsFile(ret.Config) {
return Load(source)
}
pathFriendlyName := CleanName(source)
if strings.HasPrefix(source, "/") == true {
@@ -92,10 +96,6 @@ func New(source string) (VnfsObject, error) {
ret.Image = config.VnfsImage(pathFriendlyName)
ret.Config = path.Join(config.VnfsImageDir(pathFriendlyName), "config.yaml")
if util.IsFile(ret.Config) {
return Load(source)
}
return ret, nil
}