Added controllers, services, and lots of various optimizations and fixes
This commit is contained in:
@@ -22,6 +22,8 @@ sudo make install
|
|||||||
|
|
||||||
```
|
```
|
||||||
sudo ./wwctl profile set -K $(uname -r) -V docker://warewulf/centos-8 default
|
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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
allow booting;
|
allow booting;
|
||||||
allow bootp;
|
allow bootp;
|
||||||
ddns-update-style interim;
|
ddns-update-style interim;
|
||||||
@@ -13,8 +12,6 @@ option ipxe.no-pxedhcp 1;
|
|||||||
option architecture-type code 93 = unsigned integer 16;
|
option architecture-type code 93 = unsigned integer 16;
|
||||||
|
|
||||||
if exists user-class and option user-class = "iPXE" {
|
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}";
|
filename "http://192.168.1.1:9873/ipxe/${mac:hexhyp}";
|
||||||
} else {
|
} else {
|
||||||
if option architecture-type = 00:0B {
|
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 {
|
subnet {{.Ipaddr}} netmask {{.Netmask}} {
|
||||||
range 192.168.1.10 192.168.1.99;
|
range {{.RangeStart}} {{.RangeEnd}};
|
||||||
next-server 192.168.1.1;
|
next-server 192.168.1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{{range .Nodes}}
|
||||||
#subnet 192.168.1.0 netmask 255.255.255.0 {
|
#host {{.Fqdn}} {
|
||||||
# not authoritative;
|
# hardware ethernet {{.NetDevs.eth0.Hwaddr}}
|
||||||
# option subnet-mask 255.255.255.0;
|
# filed-address {{.NetDevs.eth0.Ipaddr}}
|
||||||
#}
|
|
||||||
|
|
||||||
#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;
|
|
||||||
# }
|
|
||||||
#}
|
#}
|
||||||
|
{{end}}
|
||||||
131
etc/nodes.conf
131
etc/nodes.conf
@@ -1,52 +1,87 @@
|
|||||||
nodeprofiles:
|
nodeprofiles:
|
||||||
default:
|
default:
|
||||||
comment: ""
|
comment: ""
|
||||||
|
vnfs: ""
|
||||||
|
kernel version: ""
|
||||||
kernel args: crashkernel=no quiet
|
kernel args: crashkernel=no quiet
|
||||||
nodegroups:
|
|
||||||
default:
|
control:
|
||||||
comment: This is the default group
|
headnode01:
|
||||||
domain name: cluster01
|
comment: This is the first control system
|
||||||
profiles:
|
ipaddr: 192.168.1.1
|
||||||
- default
|
services:
|
||||||
nodes:
|
warewulfd:
|
||||||
n0000:
|
port: 9873
|
||||||
hostname: n0000
|
secure: true
|
||||||
netdevs:
|
dhcp:
|
||||||
eth0:
|
enabled: true
|
||||||
type: ethernet
|
range start: 192.168.1.100
|
||||||
hwaddr: 00:0c:29:23:8b:48
|
range end: 192.168.1.250
|
||||||
ipaddr: 192.168.1.100
|
assign static: false
|
||||||
netmask: 255.255.255.0
|
config file: /etc/dhcp/dhcpd.conf
|
||||||
gateway: 192.168.1.1
|
start command: service dhcp start
|
||||||
ib0:
|
restart command: killall dhcpd -HUP
|
||||||
type: infiniband
|
enable command: chkconfig dhcp on
|
||||||
hwaddr: aa:bb:cc:dd:ee:a0
|
tftp:
|
||||||
ipaddr: 192.168.10.100
|
enabled: true
|
||||||
netmask: 255.255.255.0
|
tftproot: /var/lib/tftproot
|
||||||
n0001:
|
start command: service tftp start
|
||||||
hostname: n0001
|
restart command: service tftp restart
|
||||||
ipmi ipaddr: x.x.x.x
|
enable command: chkconfig tftp on
|
||||||
netdevs:
|
nfs:
|
||||||
eth0:
|
enabled: true
|
||||||
hwaddr: aa:bb:cc:dd:ee:b0
|
config file: /etc/exports
|
||||||
ipaddr: 192.168.1.101
|
exports:
|
||||||
netmask: 255.255.255.0
|
- /var/warewulf 192.168.1.1/255.255.255.0(ro,no_root_squash)
|
||||||
gateway: 192.168.1.1
|
- /home 192.168.1.1/255.255.255.0(rw,no_root_squash)
|
||||||
ib0:
|
start command: service nfs start
|
||||||
hwaddr: aa:bb:cc:dd:ee:b1
|
restart command: service nfs restart
|
||||||
ipaddr: 192.168.10.100
|
enable command: chkconfig nfs on
|
||||||
netmask: 255.255.255.0
|
nodegroups:
|
||||||
group_1:
|
default:
|
||||||
comment: This is the group 1
|
comment: This is the default group
|
||||||
domain name: group1
|
domain name: cluster01
|
||||||
profiles:
|
profiles:
|
||||||
- default
|
- default
|
||||||
nodes:
|
nodes:
|
||||||
n0000:
|
n0000:
|
||||||
hostname: n0000
|
hostname: n0000
|
||||||
netdevs:
|
netdevs:
|
||||||
eth0:
|
eth0:
|
||||||
hwaddr: aa:bb:cc:dd:ee:c0
|
type: ethernet
|
||||||
ipaddr: 192.168.2.100
|
hwaddr: 00:0c:29:23:8b:48
|
||||||
netmask: 255.255.255.0
|
ipaddr: 192.168.1.100
|
||||||
gateway: 192.168.2.1
|
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
|
||||||
|
|||||||
29
internal/app/wwctl/controller/add/main.go
Normal file
29
internal/app/wwctl/controller/add/main.go
Normal 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
|
||||||
|
}
|
||||||
23
internal/app/wwctl/controller/add/root.go
Normal file
23
internal/app/wwctl/controller/add/root.go
Normal 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
|
||||||
|
}
|
||||||
61
internal/app/wwctl/controller/delete/main.go
Normal file
61
internal/app/wwctl/controller/delete/main.go
Normal 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
|
||||||
|
}
|
||||||
23
internal/app/wwctl/controller/delete/root.go
Normal file
23
internal/app/wwctl/controller/delete/root.go
Normal 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
|
||||||
|
}
|
||||||
45
internal/app/wwctl/controller/list/main.go
Normal file
45
internal/app/wwctl/controller/list/main.go
Normal 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
|
||||||
|
}
|
||||||
23
internal/app/wwctl/controller/list/root.go
Normal file
23
internal/app/wwctl/controller/list/root.go
Normal 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
|
||||||
|
}
|
||||||
30
internal/app/wwctl/controller/root.go
Normal file
30
internal/app/wwctl/controller/root.go
Normal 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
|
||||||
|
}
|
||||||
94
internal/app/wwctl/controller/set/main.go
Normal file
94
internal/app/wwctl/controller/set/main.go
Normal 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
|
||||||
|
}
|
||||||
26
internal/app/wwctl/controller/set/root.go
Normal file
26
internal/app/wwctl/controller/set/root.go
Normal 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
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, g := range args {
|
for _, g := range args {
|
||||||
err = nodeDB.AddGroup(g)
|
err = nodeDB.AddGroup(SetController, g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -10,13 +10,12 @@ var (
|
|||||||
RunE: CobraRunE,
|
RunE: CobraRunE,
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
}
|
}
|
||||||
SetVnfs string
|
SetController string
|
||||||
SetKernel string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
|
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add group to")
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootCommand returns the root cobra.Command for the application.
|
// GetRootCommand returns the root cobra.Command for the application.
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, g := range args {
|
for _, g := range args {
|
||||||
err := nodeDB.DelGroup(g)
|
err := nodeDB.DelGroup(SetController, g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
} else {
|
} else {
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
if n.GroupName.String() == g {
|
if n.Gid.Get() == g {
|
||||||
numNodes ++
|
numNodes ++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,11 @@ var (
|
|||||||
Long: "Add a new node group ",
|
Long: "Add a new node group ",
|
||||||
RunE: CobraRunE,
|
RunE: CobraRunE,
|
||||||
}
|
}
|
||||||
SetVnfs string
|
SetController string
|
||||||
SetKernel string
|
|
||||||
// SetGroupLevel bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
|
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add group to")
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootCommand returns the root cobra.Command for the application.
|
// GetRootCommand returns the root cobra.Command for the application.
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
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, ","))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
err = nodeDB.AddNode(SetGroup, a)
|
err = nodeDB.AddNode(SetController, SetGroup, a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ var (
|
|||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
}
|
}
|
||||||
SetGroup string
|
SetGroup string
|
||||||
|
SetController string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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.
|
// GetRootCommand returns the root cobra.Command for the application.
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
nodeList, err := nodeDB.SearchByNameList(args)
|
nodeList, err := nodeDB.SearchByNameList(args)
|
||||||
|
|
||||||
for _, n := range nodeList {
|
for _, n := range nodeList {
|
||||||
if SetGroup != "" && SetGroup != n.GroupName.String() {
|
if SetGroup != "" && SetGroup != n.Gid.String() {
|
||||||
wwlog.Printf(wwlog.DEBUG, "skipping node of different group: %s/%s\n", n.GroupName, n.Id)
|
wwlog.Printf(wwlog.DEBUG, "skipping node of different group: %s/%s\n", n.Gid, n.Id)
|
||||||
continue
|
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 {
|
if err != nil {
|
||||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ var (
|
|||||||
}
|
}
|
||||||
SetForce string
|
SetForce string
|
||||||
SetGroup string
|
SetGroup string
|
||||||
|
SetController string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetForce, "force", "f", "", "Force node delete")
|
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(&SetGroup, "group", "g", "default", "Set group to delete nodes from")
|
||||||
|
baseCmd.PersistentFlags().StringVarP(&SetController, "controller", "c", "default", "Controller to add nodes to")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
fmt.Printf("################################################################################\n")
|
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(), "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(), "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(), "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 (Group)", "group", strings.Join(node.GroupProfiles, ","))
|
||||||
fmt.Printf("%-20s %-18s %8s: %s\n", node.Fqdn.Get(), "Profiles (Node)", "node", strings.Join(node.Profiles, ","))
|
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))
|
fmt.Println(strings.Repeat("=", 120))
|
||||||
|
|
||||||
for _, node := range nodes {
|
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 {
|
} else {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func init() {
|
|||||||
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
|
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(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system 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(&SetIpmiIpaddr, "ipmi", "", "Set the node's IPMI address")
|
||||||
baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username")
|
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(&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(&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(&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(&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().BoolVar(&SetNetDevDel, "delete", false, "Delete the node's network device")
|
||||||
baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes")
|
baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes")
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
shasum1, err := util.ShaSumFile(overlayFile)
|
shasum1, err := util.ShaSumFile(overlayFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wwlog.Printf(wwlog.WARN, "Could not open overlay file for checksum: %s\n", err)
|
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")
|
wwlog.Printf(wwlog.ERROR, "Editor process existed with non-zero\n")
|
||||||
os.Exit(1)
|
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)
|
shasum2, err := util.ShaSumFile(overlayFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -126,4 +125,3 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(profiles) > 0 {
|
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{
|
prompt := promptui.Prompt{
|
||||||
Label: q,
|
Label: q,
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package wwctl
|
package wwctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hpcng/warewulf/internal/app/wwctl/controller"
|
||||||
"github.com/hpcng/warewulf/internal/app/wwctl/group"
|
"github.com/hpcng/warewulf/internal/app/wwctl/group"
|
||||||
"github.com/hpcng/warewulf/internal/app/wwctl/kernel"
|
"github.com/hpcng/warewulf/internal/app/wwctl/kernel"
|
||||||
"github.com/hpcng/warewulf/internal/app/wwctl/node"
|
"github.com/hpcng/warewulf/internal/app/wwctl/node"
|
||||||
"github.com/hpcng/warewulf/internal/app/wwctl/overlay"
|
"github.com/hpcng/warewulf/internal/app/wwctl/overlay"
|
||||||
"github.com/hpcng/warewulf/internal/app/wwctl/profile"
|
"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/app/wwctl/vnfs"
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||||
@@ -14,26 +16,29 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
rootCmd = &cobra.Command{
|
rootCmd = &cobra.Command{
|
||||||
Use: "wwctl",
|
Use: "wwctl",
|
||||||
Short: "Warewulf Control",
|
Short: "Warewulf Control",
|
||||||
Long: "Control interface to the Cluster Warewulf Provisioning System.",
|
Long: "Control interface to the Cluster Warewulf Provisioning System.",
|
||||||
PersistentPreRunE: rootPersistentPreRunE,
|
PersistentPreRunE: rootPersistentPreRunE,
|
||||||
}
|
}
|
||||||
verboseArg bool
|
verboseArg bool
|
||||||
debugArg bool
|
debugArg bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.PersistentFlags().BoolVarP(&verboseArg, "verbose", "v", false, "Run with increased verbosity.")
|
rootCmd.PersistentFlags().BoolVarP(&verboseArg, "verbose", "v", false, "Run with increased verbosity.")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&debugArg, "debug", "d", false, "Run with debugging messages enabled.")
|
rootCmd.PersistentFlags().BoolVarP(&debugArg, "debug", "d", false, "Run with debugging messages enabled.")
|
||||||
|
|
||||||
rootCmd.AddCommand(overlay.GetCommand())
|
|
||||||
//rootCmd.AddCommand(build.GetCommand())
|
//rootCmd.AddCommand(build.GetCommand())
|
||||||
|
|
||||||
|
rootCmd.AddCommand(overlay.GetCommand())
|
||||||
|
rootCmd.AddCommand(controller.GetCommand())
|
||||||
rootCmd.AddCommand(vnfs.GetCommand())
|
rootCmd.AddCommand(vnfs.GetCommand())
|
||||||
rootCmd.AddCommand(node.GetCommand())
|
rootCmd.AddCommand(node.GetCommand())
|
||||||
rootCmd.AddCommand(kernel.GetCommand())
|
rootCmd.AddCommand(kernel.GetCommand())
|
||||||
rootCmd.AddCommand(group.GetCommand())
|
rootCmd.AddCommand(group.GetCommand())
|
||||||
rootCmd.AddCommand(profile.GetCommand())
|
rootCmd.AddCommand(profile.GetCommand())
|
||||||
|
rootCmd.AddCommand(services.GetCommand())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
109
internal/app/wwctl/services/dhcp/main.go
Normal file
109
internal/app/wwctl/services/dhcp/main.go
Normal 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
|
||||||
|
}
|
||||||
23
internal/app/wwctl/services/dhcp/root.go
Normal file
23
internal/app/wwctl/services/dhcp/root.go
Normal 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
|
||||||
|
}
|
||||||
23
internal/app/wwctl/services/root.go
Normal file
23
internal/app/wwctl/services/root.go
Normal 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
|
||||||
|
}
|
||||||
@@ -30,78 +30,80 @@ func New() (nodeYaml, error) {
|
|||||||
func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
||||||
var ret []NodeInfo
|
var ret []NodeInfo
|
||||||
|
|
||||||
for groupname, group := range self.NodeGroups {
|
for controllername, controller := range self.Controllers {
|
||||||
for nodename, node := range group.Nodes {
|
for groupname, group := range controller.NodeGroups {
|
||||||
var n NodeInfo
|
for nodename, node := range group.Nodes {
|
||||||
var allProfiles []string
|
var n NodeInfo
|
||||||
|
var allProfiles []string
|
||||||
|
|
||||||
if node.Disabled == true || group.Disabled == true {
|
if node.Disabled == true || group.Disabled == true {
|
||||||
wwlog.Printf(wwlog.VERBOSE, "Skipping disabled node: %s/%s\n", groupname, nodename)
|
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)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
n.DomainName.SetProfile(self.NodeProfiles[p].DomainName)
|
n.Id.Set(nodename)
|
||||||
n.Vnfs.SetProfile(self.NodeProfiles[p].Vnfs)
|
n.Gid.Set(groupname)
|
||||||
n.KernelVersion.SetProfile(self.NodeProfiles[p].KernelVersion)
|
n.Cid.Set(controllername)
|
||||||
n.KernelArgs.SetProfile(self.NodeProfiles[p].KernelArgs)
|
n.HostName.Set(node.Hostname)
|
||||||
n.Ipxe.SetProfile(self.NodeProfiles[p].Ipxe)
|
n.IpmiIpaddr.Set(node.IpmiIpaddr)
|
||||||
n.IpmiUserName.SetProfile(self.NodeProfiles[p].IpmiUserName)
|
n.DomainName.Set(node.DomainName)
|
||||||
n.IpmiPassword.SetProfile(self.NodeProfiles[p].IpmiPassword)
|
n.Vnfs.Set(node.Vnfs)
|
||||||
n.SystemOverlay.SetProfile(self.NodeProfiles[p].SystemOverlay)
|
n.KernelVersion.Set(node.KernelVersion)
|
||||||
n.RuntimeOverlay.SetProfile(self.NodeProfiles[p].RuntimeOverlay)
|
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) {
|
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
|
||||||
var ret []GroupInfo
|
var ret []GroupInfo
|
||||||
|
|
||||||
for groupname, group := range self.NodeGroups {
|
for controllername, controller := range self.Controllers {
|
||||||
var g GroupInfo
|
for groupname, group := range controller.NodeGroups {
|
||||||
|
var g GroupInfo
|
||||||
|
|
||||||
g.Id = groupname
|
g.Id = groupname
|
||||||
g.DomainName = group.DomainName
|
g.Cid = controllername
|
||||||
g.Comment = group.Comment
|
g.DomainName = group.DomainName
|
||||||
g.Vnfs = group.Vnfs
|
g.Comment = group.Comment
|
||||||
g.KernelVersion = group.KernelVersion
|
g.Vnfs = group.Vnfs
|
||||||
g.KernelArgs = group.KernelArgs
|
g.KernelVersion = group.KernelVersion
|
||||||
g.IpmiPassword = group.IpmiPassword
|
g.KernelArgs = group.KernelArgs
|
||||||
g.IpmiUserName = group.IpmiUserName
|
g.IpmiPassword = group.IpmiPassword
|
||||||
g.SystemOverlay = group.SystemOverlay
|
g.IpmiUserName = group.IpmiUserName
|
||||||
g.RuntimeOverlay = group.RuntimeOverlay
|
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
|
// TODO: Validate or die on all inputs
|
||||||
|
|
||||||
ret = append(ret, g)
|
ret = append(ret, c)
|
||||||
}
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
@@ -159,8 +212,6 @@ func (self *nodeYaml) FindAllProfiles() ([]ProfileInfo, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (self *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
|
func (self *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
|
||||||
var ret NodeInfo
|
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)
|
return ret, errors.New("No nodes found with IP Addr: " + ipaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) {
|
func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) {
|
||||||
var ret []NodeInfo
|
var ret []NodeInfo
|
||||||
|
|
||||||
|
|||||||
@@ -6,127 +6,212 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/******
|
||||||
|
* YAML data representations
|
||||||
|
******/
|
||||||
|
|
||||||
type nodeYaml struct {
|
type nodeYaml struct {
|
||||||
NodeProfiles map[string]*ProfileConf
|
NodeProfiles map[string]*ProfileConf
|
||||||
NodeGroups map[string]*GroupConf
|
Controllers map[string]*ControllerConf `yaml:"control"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProfileConf struct {
|
type ProfileConf struct {
|
||||||
Comment string `yaml:"comment"`
|
Comment string `yaml:"comment"`
|
||||||
Vnfs string `yaml:"vnfs,omitempty"`
|
Vnfs string `yaml:"vnfs,omitempty"`
|
||||||
Ipxe string `yaml:"ipxe template,omitempty"`
|
Ipxe string `yaml:"ipxe template,omitempty"`
|
||||||
KernelVersion string `yaml:"kernel version,omitempty"`
|
KernelVersion string `yaml:"kernel version,omitempty"`
|
||||||
KernelArgs string `yaml:"kernel args,omitempty"`
|
KernelArgs string `yaml:"kernel args,omitempty"`
|
||||||
IpmiUserName string `yaml:"ipmi username,omitempty"`
|
IpmiUserName string `yaml:"ipmi username,omitempty"`
|
||||||
IpmiPassword string `yaml:"ipmi password,omitempty"`
|
IpmiPassword string `yaml:"ipmi password,omitempty"`
|
||||||
DomainName string `yaml:"domain name,omitempty"`
|
DomainName string `yaml:"domain name,omitempty"`
|
||||||
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
|
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
|
||||||
SystemOverlay string `yaml:"system 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 {
|
type GroupConf struct {
|
||||||
Comment string `yaml:"comment"`
|
Comment string `yaml:"comment"`
|
||||||
Disabled bool `yaml:"disabled,omitempty"`
|
Disabled bool `yaml:"disabled,omitempty"`
|
||||||
DomainName string `yaml:"domain name"`
|
DomainName string `yaml:"domain name"`
|
||||||
Vnfs string `yaml:"vnfs,omitempty"`
|
Vnfs string `yaml:"vnfs,omitempty"`
|
||||||
Ipxe string `yaml:"ipxe template,omitempty"`
|
Ipxe string `yaml:"ipxe template,omitempty"`
|
||||||
KernelVersion string `yaml:"kernel version,omitempty"`
|
KernelVersion string `yaml:"kernel version,omitempty"`
|
||||||
KernelArgs string `yaml:"kernel args,omitempty"`
|
KernelArgs string `yaml:"kernel args,omitempty"`
|
||||||
IpmiUserName string `yaml:"ipmi username,omitempty"`
|
IpmiUserName string `yaml:"ipmi username,omitempty"`
|
||||||
IpmiPassword string `yaml:"ipmi password,omitempty"`
|
IpmiPassword string `yaml:"ipmi password,omitempty"`
|
||||||
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
|
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
|
||||||
SystemOverlay string `yaml:"system overlay files,omitempty"`
|
SystemOverlay string `yaml:"system overlay files,omitempty"`
|
||||||
Profiles []string `yaml:"profiles,omitempty"`
|
Profiles []string `yaml:"profiles,omitempty"`
|
||||||
Nodes map[string]*NodeConf
|
Nodes map[string]*NodeConf
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeConf struct {
|
type NodeConf struct {
|
||||||
Comment string `yaml:"comment,omitempty"`
|
Comment string `yaml:"comment,omitempty"`
|
||||||
Disabled bool `yaml:"disabled,omitempty"`
|
Disabled bool `yaml:"disabled,omitempty"`
|
||||||
Hostname string `yaml:"hostname,omitempty"`
|
Hostname string `yaml:"hostname,omitempty"`
|
||||||
DomainName string `yaml:"domain name,omitempty"`
|
DomainName string `yaml:"domain name,omitempty"`
|
||||||
Vnfs string `yaml:"vnfs,omitempty"`
|
Vnfs string `yaml:"vnfs,omitempty"`
|
||||||
Ipxe string `yaml:"ipxe template,omitempty"`
|
Ipxe string `yaml:"ipxe template,omitempty"`
|
||||||
KernelVersion string `yaml:"kernel version,omitempty"`
|
KernelVersion string `yaml:"kernel version,omitempty"`
|
||||||
KernelArgs string `yaml:"kernel args,omitempty"`
|
KernelArgs string `yaml:"kernel args,omitempty"`
|
||||||
IpmiUserName string `yaml:"ipmi username,omitempty"`
|
IpmiUserName string `yaml:"ipmi username,omitempty"`
|
||||||
IpmiPassword string `yaml:"ipmi password,omitempty"`
|
IpmiPassword string `yaml:"ipmi password,omitempty"`
|
||||||
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
|
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
|
||||||
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
|
RuntimeOverlay string `yaml:"runtime overlay files,omitempty"`
|
||||||
SystemOverlay string `yaml:"system overlay files,omitempty"`
|
SystemOverlay string `yaml:"system overlay files,omitempty"`
|
||||||
Profiles []string `yaml:"profiles,omitempty"`
|
Profiles []string `yaml:"profiles,omitempty"`
|
||||||
NetDevs map[string]*NetDevs
|
NetDevs map[string]*NetDevs
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetDevs struct {
|
type NetDevs struct {
|
||||||
Type string `yaml:"type,omitempty"`
|
Type string `yaml:"type,omitempty"`
|
||||||
Hwaddr string
|
Hwaddr string
|
||||||
Ipaddr string
|
Ipaddr string
|
||||||
Netmask string
|
Netmask string
|
||||||
Gateway string `yaml:"gateway,omitempty"`
|
Gateway string `yaml:"gateway,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******
|
||||||
|
* Code internal data representations
|
||||||
|
******/
|
||||||
|
|
||||||
type NodeInfoEntry struct {
|
type NodeInfoEntry struct {
|
||||||
value string
|
value string
|
||||||
profile string
|
profile string
|
||||||
group string
|
group string
|
||||||
def string
|
controller string
|
||||||
|
def string
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeInfo struct {
|
type NodeInfo struct {
|
||||||
Id NodeInfoEntry
|
Id NodeInfoEntry
|
||||||
Gid NodeInfoEntry
|
Gid NodeInfoEntry
|
||||||
Uid NodeInfoEntry
|
Cid NodeInfoEntry
|
||||||
Comment NodeInfoEntry
|
Comment NodeInfoEntry
|
||||||
GroupName NodeInfoEntry
|
HostName NodeInfoEntry
|
||||||
HostName NodeInfoEntry
|
Fqdn NodeInfoEntry
|
||||||
Fqdn NodeInfoEntry
|
DomainName NodeInfoEntry
|
||||||
DomainName NodeInfoEntry
|
Vnfs NodeInfoEntry
|
||||||
Vnfs NodeInfoEntry
|
Ipxe NodeInfoEntry
|
||||||
Ipxe NodeInfoEntry
|
KernelVersion NodeInfoEntry
|
||||||
KernelVersion NodeInfoEntry
|
KernelArgs NodeInfoEntry
|
||||||
KernelArgs NodeInfoEntry
|
IpmiIpaddr NodeInfoEntry
|
||||||
IpmiIpaddr NodeInfoEntry
|
IpmiUserName NodeInfoEntry
|
||||||
IpmiUserName NodeInfoEntry
|
IpmiPassword NodeInfoEntry
|
||||||
IpmiPassword NodeInfoEntry
|
RuntimeOverlay NodeInfoEntry
|
||||||
RuntimeOverlay NodeInfoEntry
|
SystemOverlay NodeInfoEntry
|
||||||
SystemOverlay NodeInfoEntry
|
Profiles []string
|
||||||
Profiles []string
|
GroupProfiles []string
|
||||||
GroupProfiles []string
|
NetDevs map[string]*NetDevs
|
||||||
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 {
|
type GroupInfo struct {
|
||||||
Id string
|
Id string
|
||||||
Comment string
|
Cid string
|
||||||
Vnfs string
|
Comment string
|
||||||
Ipxe string
|
Vnfs string
|
||||||
KernelVersion string
|
Ipxe string
|
||||||
KernelArgs string
|
KernelVersion string
|
||||||
IpmiUserName string
|
KernelArgs string
|
||||||
IpmiPassword string
|
IpmiUserName string
|
||||||
DomainName string
|
IpmiPassword string
|
||||||
RuntimeOverlay string
|
DomainName string
|
||||||
SystemOverlay string
|
RuntimeOverlay string
|
||||||
Profiles []string
|
SystemOverlay string
|
||||||
|
Profiles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProfileInfo struct {
|
type ProfileInfo struct {
|
||||||
Id string
|
Id string
|
||||||
Comment string
|
Comment string
|
||||||
Vnfs string
|
Vnfs string
|
||||||
Ipxe string
|
Ipxe string
|
||||||
KernelVersion string
|
KernelVersion string
|
||||||
KernelArgs string
|
KernelArgs string
|
||||||
IpmiUserName string
|
IpmiUserName string
|
||||||
IpmiPassword string
|
IpmiPassword string
|
||||||
DomainName string
|
DomainName string
|
||||||
RuntimeOverlay string
|
RuntimeOverlay string
|
||||||
SystemOverlay string
|
SystemOverlay string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const ConfigFile = "/etc/warewulf/nodes.conf"
|
const ConfigFile = "/etc/warewulf/nodes.conf"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ func (self *NodeInfoEntry) String() string {
|
|||||||
if self.profile != "" {
|
if self.profile != "" {
|
||||||
return self.profile
|
return self.profile
|
||||||
}
|
}
|
||||||
|
if self.controller != "" {
|
||||||
|
return self.controller
|
||||||
|
}
|
||||||
if self.def != "" {
|
if self.def != "" {
|
||||||
return self.def
|
return self.def
|
||||||
}
|
}
|
||||||
@@ -30,6 +33,9 @@ func (self *NodeInfoEntry) Source() string {
|
|||||||
if self.profile != "" {
|
if self.profile != "" {
|
||||||
return "profile"
|
return "profile"
|
||||||
}
|
}
|
||||||
|
if self.controller != "" {
|
||||||
|
return "controller"
|
||||||
|
}
|
||||||
if self.def != "" {
|
if self.def != "" {
|
||||||
return "default"
|
return "default"
|
||||||
}
|
}
|
||||||
@@ -46,6 +52,9 @@ func (self *NodeInfoEntry) Get() string {
|
|||||||
if self.profile != "" {
|
if self.profile != "" {
|
||||||
return self.profile
|
return self.profile
|
||||||
}
|
}
|
||||||
|
if self.controller != "" {
|
||||||
|
return self.controller
|
||||||
|
}
|
||||||
if self.def != "" {
|
if self.def != "" {
|
||||||
return self.def
|
return self.def
|
||||||
}
|
}
|
||||||
@@ -81,6 +90,13 @@ func (self *NodeInfoEntry) SetProfile(value string) {
|
|||||||
self.profile = value
|
self.profile = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *NodeInfoEntry) SetController(value string) {
|
||||||
|
if value == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.controller = value
|
||||||
|
}
|
||||||
|
|
||||||
func (self *NodeInfoEntry) Set(value string) {
|
func (self *NodeInfoEntry) Set(value string) {
|
||||||
if value == "" {
|
if value == "" {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -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
|
var node NodeConf
|
||||||
|
|
||||||
wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID)
|
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)
|
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)
|
return errors.New("Nodename already exists in group: " + nodeID)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.NodeGroups[groupID].Nodes[nodeID] = &node
|
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID] = &node
|
||||||
self.NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
|
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
|
||||||
|
|
||||||
return nil
|
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 {
|
if _, ok := self.Controllers[controllerID]; ! ok {
|
||||||
return errors.New("Group '" + groupID + "' was not found")
|
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)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func(self *nodeYaml) NodeUpdate(node NodeInfo) error {
|
func(self *nodeYaml) NodeUpdate(node NodeInfo) error {
|
||||||
|
controllerID := node.Cid.Get()
|
||||||
groupID := node.Gid.Get()
|
groupID := node.Gid.Get()
|
||||||
nodeID := node.Id.Get()
|
nodeID := node.Id.Get()
|
||||||
|
|
||||||
if _, ok := self.NodeGroups[groupID]; !ok {
|
if _, ok := self.Controllers[controllerID]; ! ok {
|
||||||
return errors.New("Group '" + groupID + "' was not found")
|
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 + "'")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName.GetReal()
|
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
|
||||||
self.NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal()
|
return errors.New("Group does not exist: " + groupID)
|
||||||
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()
|
if _, ok := self.Controllers[controllerID].NodeGroups[groupID].Nodes[groupID]; ! ok {
|
||||||
self.NodeGroups[groupID].Nodes[nodeID].KernelArgs = node.KernelArgs.GetReal()
|
return errors.New("Nodename does not exist in group: " + nodeID)
|
||||||
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.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Hostname = node.HostName.GetReal()
|
||||||
self.NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal()
|
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Vnfs = node.Vnfs.GetReal()
|
||||||
self.NodeGroups[groupID].Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal()
|
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].DomainName = node.DomainName.GetReal()
|
||||||
self.NodeGroups[groupID].Nodes[nodeID].Profiles = node.Profiles
|
self.Controllers[controllerID].NodeGroups[groupID].Nodes[nodeID].Ipxe = node.Ipxe.GetReal()
|
||||||
self.NodeGroups[groupID].Nodes[nodeID].NetDevs = node.NetDevs
|
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
|
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
|
var group GroupConf
|
||||||
|
|
||||||
wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID)
|
wwlog.Printf(wwlog.VERBOSE, "Adding new group: %s/%s\n", groupID)
|
||||||
|
|
||||||
if _, ok := self.NodeGroups[groupID]; ok {
|
if _, ok := self.Controllers[controllerID]; ! ok {
|
||||||
return errors.New("Group name already exists: " + groupID)
|
return errors.New("Controller does not exist: " + controllerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.NodeGroups[groupID] = &group
|
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ok {
|
||||||
self.NodeGroups[groupID].DomainName = groupID
|
return errors.New("Group already exists: " + groupID)
|
||||||
self.NodeGroups[groupID].Profiles = []string{"default"}
|
}
|
||||||
|
|
||||||
|
self.Controllers[controllerID].NodeGroups[groupID] = &group
|
||||||
|
self.Controllers[controllerID].NodeGroups[groupID].DomainName = groupID
|
||||||
|
self.Controllers[controllerID].NodeGroups[groupID].Profiles = []string{"default"}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *nodeYaml) DelGroup(groupID string) error {
|
func (self *nodeYaml) DelGroup(controllerID string, groupID 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.Controllers[controllerID].NodeGroups[groupID]; ! ok {
|
||||||
|
return errors.New("Group does not exist: " + groupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
wwlog.Printf(wwlog.VERBOSE, "Deleting group: %s\n", groupID)
|
wwlog.Printf(wwlog.VERBOSE, "Deleting group: %s\n", groupID)
|
||||||
delete(self.NodeGroups, groupID)
|
delete(self.Controllers[controllerID].NodeGroups, groupID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func(self *nodeYaml) GroupUpdate(group GroupInfo) error {
|
func(self *nodeYaml) GroupUpdate(group GroupInfo) error {
|
||||||
|
controllerID := group.Cid
|
||||||
groupID := group.Id
|
groupID := group.Id
|
||||||
|
|
||||||
if _, ok := self.NodeGroups[groupID]; !ok {
|
if _, ok := self.Controllers[controllerID]; ! ok {
|
||||||
return errors.New("Group '" + groupID + "' was not found")
|
return errors.New("Controller does not exist: " + controllerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.NodeGroups[groupID].DomainName = group.DomainName
|
if _, ok := self.Controllers[controllerID].NodeGroups[groupID]; ! ok {
|
||||||
self.NodeGroups[groupID].Vnfs = group.Vnfs
|
return errors.New("Group does not exist: " + groupID)
|
||||||
self.NodeGroups[groupID].KernelVersion = group.KernelVersion
|
}
|
||||||
self.NodeGroups[groupID].KernelArgs = group.KernelArgs
|
|
||||||
self.NodeGroups[groupID].Ipxe = group.Ipxe
|
self.Controllers[controllerID].NodeGroups[groupID].DomainName = group.DomainName
|
||||||
self.NodeGroups[groupID].IpmiUserName = group.IpmiUserName
|
self.Controllers[controllerID].NodeGroups[groupID].Vnfs = group.Vnfs
|
||||||
self.NodeGroups[groupID].IpmiPassword = group.IpmiPassword
|
self.Controllers[controllerID].NodeGroups[groupID].KernelVersion = group.KernelVersion
|
||||||
self.NodeGroups[groupID].RuntimeOverlay = group.RuntimeOverlay
|
self.Controllers[controllerID].NodeGroups[groupID].KernelArgs = group.KernelArgs
|
||||||
self.NodeGroups[groupID].SystemOverlay = group.SystemOverlay
|
self.Controllers[controllerID].NodeGroups[groupID].Ipxe = group.Ipxe
|
||||||
self.NodeGroups[groupID].Profiles = group.Profiles
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type TemplateStruct struct {
|
type TemplateStruct struct {
|
||||||
Fqdn string
|
Self struct {
|
||||||
Hostname string
|
Fqdn string
|
||||||
Groupname string
|
Hostname string
|
||||||
Vnfs string
|
GroupName string
|
||||||
Netdev map[string]*node.NetDevs
|
Vnfs string
|
||||||
|
NetDevs map[string]*node.NetDevs
|
||||||
|
}
|
||||||
|
AllNodes []node.NodeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildSystemOverlay(nodeList []node.NodeInfo) error {
|
func BuildSystemOverlay(nodeList []node.NodeInfo) error {
|
||||||
@@ -49,9 +52,6 @@ func RuntimeOverlayInit(name string) error {
|
|||||||
return overlayInit(name, "runtime")
|
return overlayInit(name, "runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func findAllOverlays(overlayType string) ([]string, error) {
|
func findAllOverlays(overlayType string) ([]string, error) {
|
||||||
config := config.New()
|
config := config.New()
|
||||||
var ret []string
|
var ret []string
|
||||||
@@ -83,7 +83,6 @@ func findAllOverlays(overlayType string) ([]string, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func overlayInit(name string, overlayType string) error {
|
func overlayInit(name string, overlayType string) error {
|
||||||
var path string
|
var path string
|
||||||
config := config.New()
|
config := config.New()
|
||||||
@@ -100,7 +99,7 @@ func overlayInit(name string, overlayType string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if util.IsDir(path) == true {
|
if util.IsDir(path) == true {
|
||||||
return errors.New("Overlay already exists: "+name)
|
return errors.New("Overlay already exists: " + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := os.MkdirAll(path, 0755)
|
err := os.MkdirAll(path, 0755)
|
||||||
@@ -108,13 +107,10 @@ func overlayInit(name string, overlayType string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
|
func buildOverlay(nodeList []node.NodeInfo, overlayType string) error {
|
||||||
config := config.New()
|
config := config.New()
|
||||||
|
nodeDB, _ := node.New()
|
||||||
|
allNodes, _ := nodeDB.FindAllNodes()
|
||||||
|
|
||||||
for _, node := range nodeList {
|
for _, node := range nodeList {
|
||||||
var t TemplateStruct
|
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())
|
wwlog.Printf(wwlog.DEBUG, "Processing overlay for node: %s\n", node.Fqdn.Get())
|
||||||
|
|
||||||
t.Fqdn = node.Fqdn.Get()
|
t.Self.Fqdn = node.Fqdn.Get()
|
||||||
t.Hostname = node.HostName.Get()
|
t.Self.Hostname = node.HostName.Get()
|
||||||
t.Groupname = node.GroupName.Get()
|
t.Self.GroupName = node.Gid.Get()
|
||||||
t.Vnfs = node.Vnfs.Get()
|
t.Self.Vnfs = node.Vnfs.Get()
|
||||||
t.Netdev = node.NetDevs
|
t.Self.NetDevs = node.NetDevs
|
||||||
|
t.AllNodes = allNodes
|
||||||
|
|
||||||
if overlayType == "runtime" && node.RuntimeOverlay.Defined() == false {
|
if overlayType == "runtime" && node.RuntimeOverlay.Defined() == false {
|
||||||
wwlog.Printf(wwlog.WARN, "Undefined runtime overlay, skipping node: %s\n", node.Fqdn.Get())
|
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
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
wwlog.Printf(wwlog.VERBOSE, "Finished generating overlay directory for: %s\n", node.Fqdn.Get())
|
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)
|
cmd := fmt.Sprintf("cd \"%s\"; find . | cpio --quiet -o -H newc -F \"%s\"", tmpDir, OverlayFile)
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ func CleanName(source string) string {
|
|||||||
tmp = source
|
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
|
return tmp
|
||||||
}
|
}
|
||||||
@@ -75,6 +75,10 @@ func New(source string) (VnfsObject, error) {
|
|||||||
return ret, errors.New("Called vnfs.Load() without a VNFS name")
|
return ret, errors.New("Called vnfs.Load() without a VNFS name")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if util.IsFile(ret.Config) {
|
||||||
|
return Load(source)
|
||||||
|
}
|
||||||
|
|
||||||
pathFriendlyName := CleanName(source)
|
pathFriendlyName := CleanName(source)
|
||||||
|
|
||||||
if strings.HasPrefix(source, "/") == true {
|
if strings.HasPrefix(source, "/") == true {
|
||||||
@@ -92,10 +96,6 @@ func New(source string) (VnfsObject, error) {
|
|||||||
ret.Image = config.VnfsImage(pathFriendlyName)
|
ret.Image = config.VnfsImage(pathFriendlyName)
|
||||||
ret.Config = path.Join(config.VnfsImageDir(pathFriendlyName), "config.yaml")
|
ret.Config = path.Join(config.VnfsImageDir(pathFriendlyName), "config.yaml")
|
||||||
|
|
||||||
if util.IsFile(ret.Config) {
|
|
||||||
return Load(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user