1
go.mod
1
go.mod
@@ -5,6 +5,7 @@ go 1.15
|
||||
require (
|
||||
github.com/brotherpowers/ipsubnet v0.0.0-20170914094241-30bc98f0a5b1
|
||||
github.com/containers/image/v5 v5.7.0
|
||||
github.com/fsnotify/fsnotify v1.4.7 // indirect
|
||||
github.com/manifoldco/promptui v0.8.0
|
||||
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
|
||||
github.com/opencontainers/umoci v0.4.6
|
||||
|
||||
1
go.sum
1
go.sum
@@ -110,6 +110,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/container"
|
||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
@@ -79,6 +80,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
nodeDB.Persist()
|
||||
fmt.Printf("Set default profile to container: %s\n", name)
|
||||
warewulfd.DaemonReload()
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/kernel"
|
||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
@@ -43,6 +44,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
nodeDB.Persist()
|
||||
fmt.Printf("Set default kernel version to: %s\n", args[0])
|
||||
|
||||
warewulfd.DaemonReload()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/container"
|
||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -274,6 +275,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if result == "y" || result == "yes" {
|
||||
nodeDB.Persist()
|
||||
warewulfd.DaemonReload()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/container"
|
||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -251,6 +252,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if result == "y" || result == "yes" {
|
||||
nodeDB.Persist()
|
||||
warewulfd.DaemonReload()
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
10
internal/app/wwctl/server/reload/main.go
Normal file
10
internal/app/wwctl/server/reload/main.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package reload
|
||||
|
||||
import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
return warewulfd.DaemonReload()
|
||||
}
|
||||
19
internal/app/wwctl/server/reload/root.go
Normal file
19
internal/app/wwctl/server/reload/root.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package reload
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
var (
|
||||
baseCmd = &cobra.Command{
|
||||
Use: "reload",
|
||||
Short: "Reload the Warewulf server configuration",
|
||||
RunE: CobraRunE,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
func GetCommand() *cobra.Command {
|
||||
return baseCmd
|
||||
}
|
||||
11
internal/app/wwctl/server/restart/main.go
Normal file
11
internal/app/wwctl/server/restart/main.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package restart
|
||||
|
||||
import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
warewulfd.DaemonStop()
|
||||
return warewulfd.DaemonStart()
|
||||
}
|
||||
19
internal/app/wwctl/server/restart/root.go
Normal file
19
internal/app/wwctl/server/restart/root.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package restart
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
var (
|
||||
baseCmd = &cobra.Command{
|
||||
Use: "restart",
|
||||
Short: "Restart the Warewulf server",
|
||||
RunE: CobraRunE,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
func GetCommand() *cobra.Command {
|
||||
return baseCmd
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/hpcng/warewulf/internal/app/wwctl/server/reload"
|
||||
"github.com/hpcng/warewulf/internal/app/wwctl/server/restart"
|
||||
"github.com/hpcng/warewulf/internal/app/wwctl/server/start"
|
||||
"github.com/hpcng/warewulf/internal/app/wwctl/server/status"
|
||||
"github.com/hpcng/warewulf/internal/app/wwctl/server/stop"
|
||||
@@ -20,6 +22,9 @@ func init() {
|
||||
baseCmd.AddCommand(start.GetCommand())
|
||||
baseCmd.AddCommand(status.GetCommand())
|
||||
baseCmd.AddCommand(stop.GetCommand())
|
||||
baseCmd.AddCommand(restart.GetCommand())
|
||||
baseCmd.AddCommand(reload.GetCommand())
|
||||
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
|
||||
@@ -15,7 +15,7 @@ func New() (ControllerConf, error) {
|
||||
wwlog.Printf(wwlog.DEBUG, "Opening Warewulf configuration file: %s\n", ConfigFile)
|
||||
data, err := ioutil.ReadFile(ConfigFile)
|
||||
if err != nil {
|
||||
fmt.Printf("error reading node configuration file\n")
|
||||
fmt.Printf("error reading Warewulf configuration file\n")
|
||||
return ret, err
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,34 @@ func DaemonStatus() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func DaemonReload() error {
|
||||
if util.IsFile(WAREWULFD_PIDFILE) == false {
|
||||
wwlog.Printf(wwlog.INFO, "Warewulf daemon process not running (%s)\n", WAREWULFD_PIDFILE)
|
||||
return nil
|
||||
}
|
||||
|
||||
dat, err := ioutil.ReadFile(WAREWULFD_PIDFILE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pid, _ := strconv.Atoi(string(dat))
|
||||
process, err := os.FindProcess(pid)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to find process: %s\n", err)
|
||||
return err
|
||||
} else {
|
||||
err := process.Signal(syscall.Signal(syscall.SIGHUP))
|
||||
if err != nil {
|
||||
fmt.Printf("SIGCONT on pid %d returned: %v\n", pid, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DaemonStop() error {
|
||||
|
||||
if util.IsFile(WAREWULFD_PIDFILE) == false {
|
||||
|
||||
@@ -30,19 +30,14 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
||||
url := strings.Split(req.URL.Path, "/")
|
||||
var unconfiguredNode bool
|
||||
|
||||
nodeDB, err := node.New()
|
||||
if err != nil {
|
||||
log.Printf("Could not read node configuration file: %s\n", err)
|
||||
w.WriteHeader(503)
|
||||
return
|
||||
}
|
||||
|
||||
if url[2] == "" {
|
||||
log.Printf("ERROR: Bad iPXE request from %s\n", req.RemoteAddr)
|
||||
w.WriteHeader(404)
|
||||
return
|
||||
}
|
||||
|
||||
hwaddr := strings.ReplaceAll(url[2], "-", ":")
|
||||
|
||||
conf, err := warewulfconf.New()
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||
@@ -50,16 +45,22 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
hwaddr := strings.ReplaceAll(url[2], "-", ":")
|
||||
nodeobj, err := GetNode(hwaddr)
|
||||
|
||||
n, err := nodeDB.FindByHwaddr(hwaddr)
|
||||
if err != nil {
|
||||
// If we failed to find a node, let's see if we can add one...
|
||||
var netdev string
|
||||
|
||||
nodeDB, err := node.New()
|
||||
if err != nil {
|
||||
log.Printf("Could not read node configuration file: %s\n", err)
|
||||
w.WriteHeader(503)
|
||||
return
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.VERBOSE, "Node was not found, looking for discoverable nodes...\n")
|
||||
|
||||
n, netdev, err = nodeDB.FindDiscoverableNode()
|
||||
n, netdev, err := nodeDB.FindDiscoverableNode()
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.WARN, "No nodes are set as discoverable...\n")
|
||||
unconfiguredNode = true
|
||||
@@ -79,6 +80,7 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not persist new node configuration while adding node: %s\n", n.Id.Get())
|
||||
unconfiguredNode = true
|
||||
} else {
|
||||
nodeobj = n
|
||||
wwlog.Printf(wwlog.INFO, "Building System Overlay:\n")
|
||||
_ = overlay.BuildSystemOverlay([]node.NodeInfo{n})
|
||||
wwlog.Printf(wwlog.INFO, "Building Runtime Overlay:\n")
|
||||
@@ -110,9 +112,10 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
|
||||
} else {
|
||||
log.Printf("IPXE: %15s: %s\n", n.Id.Get(), req.URL.Path)
|
||||
|
||||
ipxeTemplate := fmt.Sprintf("/etc/warewulf/ipxe/%s.ipxe", n.Ipxe.Get())
|
||||
log.Printf("IPXE: %15s: %s\n", nodeobj.Id.Get(), req.URL.Path)
|
||||
|
||||
ipxeTemplate := fmt.Sprintf("/etc/warewulf/ipxe/%s.ipxe", nodeobj.Ipxe.Get())
|
||||
|
||||
tmpl, err := template.ParseFiles(ipxeTemplate)
|
||||
if err != nil {
|
||||
@@ -122,14 +125,14 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
var replace iPxeTemplate
|
||||
|
||||
replace.Fqdn = n.Id.Get()
|
||||
replace.Fqdn = nodeobj.Id.Get()
|
||||
replace.Ipaddr = conf.Ipaddr
|
||||
replace.Port = strconv.Itoa(conf.Warewulf.Port)
|
||||
replace.Hostname = n.Id.Get()
|
||||
replace.Hostname = nodeobj.Id.Get()
|
||||
replace.Hwaddr = url[2]
|
||||
replace.ContainerName = n.ContainerName.Get()
|
||||
replace.KernelArgs = n.KernelArgs.Get()
|
||||
replace.KernelVersion = n.KernelVersion.Get()
|
||||
replace.ContainerName = nodeobj.ContainerName.Get()
|
||||
replace.KernelArgs = nodeobj.KernelArgs.Get()
|
||||
replace.KernelVersion = nodeobj.KernelVersion.Get()
|
||||
|
||||
err = tmpl.Execute(w, replace)
|
||||
if err != nil {
|
||||
@@ -137,7 +140,7 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("SEND: %15s: %s\n", n.Id.Get(), ipxeTemplate)
|
||||
log.Printf("SEND: %15s: %s\n", nodeobj.Id.Get(), ipxeTemplate)
|
||||
|
||||
}
|
||||
return
|
||||
|
||||
64
internal/pkg/warewulfd/nodedb.go
Normal file
64
internal/pkg/warewulfd/nodedb.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package warewulfd
|
||||
|
||||
import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/errors"
|
||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type nodeDB struct {
|
||||
lock sync.RWMutex
|
||||
NodeInfo map[string]node.NodeInfo
|
||||
}
|
||||
|
||||
var (
|
||||
db nodeDB
|
||||
)
|
||||
|
||||
func LoadNodeDB() error {
|
||||
|
||||
var TmpMap map[string]node.NodeInfo
|
||||
TmpMap = make(map[string]node.NodeInfo)
|
||||
|
||||
wwlog.Printf(wwlog.INFO, "Loading the node Database\n")
|
||||
|
||||
DB, err := node.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodes, err := DB.FindAllNodes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, n := range nodes {
|
||||
for _, netdev := range n.NetDevs {
|
||||
wwlog.Printf(wwlog.DEBUG, "Caching node entry: '%s' -> %s\n", netdev.Hwaddr.Get(), n.Id.Get())
|
||||
|
||||
TmpMap[netdev.Hwaddr.Get()] = n
|
||||
}
|
||||
}
|
||||
|
||||
db.lock.Lock()
|
||||
defer db.lock.Unlock()
|
||||
db.NodeInfo = TmpMap
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetNode(val string) (node.NodeInfo, error) {
|
||||
db.lock.RLock()
|
||||
defer db.lock.RUnlock()
|
||||
|
||||
if _, ok := db.NodeInfo[val]; ok {
|
||||
wwlog.Printf(wwlog.DEBUG, "Found node:\n%+v\n", db.NodeInfo[val])
|
||||
|
||||
return db.NodeInfo[val], nil
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.VERBOSE, "Node not found in DB: %s\n", val)
|
||||
var empty node.NodeInfo
|
||||
return empty, errors.New("No node found")
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package warewulfd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/errors"
|
||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
||||
"io"
|
||||
@@ -14,22 +13,18 @@ import (
|
||||
|
||||
func getSanity(req *http.Request) (node.NodeInfo, error) {
|
||||
url := strings.Split(req.URL.Path, "/")
|
||||
var ret node.NodeInfo
|
||||
|
||||
nodes, err := node.New()
|
||||
if err != nil {
|
||||
return ret, errors.New(fmt.Sprintf("%s", err))
|
||||
}
|
||||
|
||||
hwaddr := strings.ReplaceAll(url[2], "-", ":")
|
||||
ret, err = nodes.FindByHwaddr(hwaddr)
|
||||
|
||||
nodeobj, err := GetNode(hwaddr)
|
||||
if err != nil {
|
||||
var ret node.NodeInfo
|
||||
return ret, errors.New("Could not find node by HW address")
|
||||
}
|
||||
|
||||
log.Printf("REQ: %15s: %s\n", ret.Id.Get(), req.URL.Path)
|
||||
log.Printf("REQ: %15s: %s\n", nodeobj.Id.Get(), req.URL.Path)
|
||||
|
||||
return ret, nil
|
||||
return nodeobj, nil
|
||||
}
|
||||
|
||||
func sendFile(w http.ResponseWriter, filename string, sendto string) error {
|
||||
|
||||
@@ -3,6 +3,9 @@ package warewulfd
|
||||
import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// TODO: https://github.com/danderson/netboot/blob/master/pixiecore/dhcp.go
|
||||
@@ -10,6 +13,23 @@ import (
|
||||
|
||||
func RunServer() error {
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP)
|
||||
|
||||
go func() {
|
||||
for _ = range c {
|
||||
err := LoadNodeDB()
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.WARN, "Could not load database: %s\n", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err := LoadNodeDB()
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.WARN, "Could not load database: %s\n", err)
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.DEBUG, "Registering handlers for the web service\n")
|
||||
|
||||
http.HandleFunc("/ipxe/", IpxeSend)
|
||||
@@ -21,7 +41,11 @@ func RunServer() error {
|
||||
|
||||
wwlog.Printf(wwlog.VERBOSE, "Starting HTTPD REST service\n")
|
||||
|
||||
http.ListenAndServe(":9873", nil)
|
||||
err = http.ListenAndServe(":9873", nil)
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not start listening service: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user