Merge pull request #25 from gmkurtzer/warewulfd_fixes

Warewulfd fixes
This commit is contained in:
Gregory M. Kurtzer
2021-02-12 23:04:45 -08:00
committed by GitHub
17 changed files with 219 additions and 30 deletions

1
go.mod
View File

@@ -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
View File

@@ -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=

View File

@@ -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()
}

View File

@@ -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()
}
}

View File

@@ -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()
}
}

View File

@@ -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 {

View 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()
}

View 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
}

View 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()
}

View 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
}

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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

View 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")
}

View File

@@ -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 {

View File

@@ -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
}