Lots of updates...
This commit is contained in:
@@ -12,7 +12,7 @@ func ipxe(w http.ResponseWriter, req *http.Request) {
|
||||
url := strings.Split(req.URL.Path, "/")
|
||||
|
||||
if url[2] == "" {
|
||||
fmt.Printf("ERROR: Bad iPXE request from %s\n", req.RemoteAddr)
|
||||
log.Printf("ERROR: Bad iPXE request from %s\n", req.RemoteAddr)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func ipxe(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
if node.HostName != "" {
|
||||
fmt.Printf("IPXE: %15s: hwaddr=%s\n", node.Fqdn, hwaddr)
|
||||
log.Printf("IPXE: %15s: hwaddr=%s\n", node.Fqdn, hwaddr)
|
||||
|
||||
fmt.Fprintf(w, "#!ipxe\n")
|
||||
|
||||
@@ -34,10 +34,10 @@ func ipxe(w http.ResponseWriter, req *http.Request) {
|
||||
fmt.Fprintf(w, "kernel ${base}/kernel/%s crashkernel=no quiet\n", url[2])
|
||||
fmt.Fprintf(w, "initrd ${base}/vnfs/%s\n", url[2])
|
||||
fmt.Fprintf(w, "initrd ${base}/kmods/%s\n", url[2])
|
||||
fmt.Fprintf(w, "initrd ${base}/overlay/%s\n", url[2])
|
||||
fmt.Fprintf(w, "initrd ${base}/overlay-system/%s\n", url[2])
|
||||
fmt.Fprintf(w, "boot\n")
|
||||
} else {
|
||||
fmt.Printf("ERROR: iPXE request from unknown Node (hwaddr=%s)\n", url[2])
|
||||
log.Printf("ERROR: iPXE request from unknown Node (hwaddr=%s)\n", url[2])
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,17 +16,19 @@ func kernel(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
if node.KernelVersion != "" {
|
||||
fileName := fmt.Sprintf("%s/provision/kernels/vmlinuz-%s", LocalStateDir, node.KernelVersion)
|
||||
fileName := fmt.Sprintf("%s/provision/kernel/vmlinuz-%s", LocalStateDir, node.KernelVersion)
|
||||
|
||||
err := sendFile(w, fileName, node.Fqdn)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Printf("ERROR: %s\n", err)
|
||||
} else {
|
||||
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
|
||||
}
|
||||
|
||||
} else {
|
||||
w.WriteHeader(503)
|
||||
log.Printf("No kernel version set for node %s\n", node.Fqdn)
|
||||
log.Printf("ERROR: No 'kernel version' set for node %s\n", node.Fqdn)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,19 @@ func kmods(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
if node.KernelVersion != "" {
|
||||
fileName := fmt.Sprintf("%s/provision/kernels/kmods-%s.img", LocalStateDir, node.KernelVersion)
|
||||
fileName := fmt.Sprintf("%s/provision/kernel/kmods-%s.img", LocalStateDir, node.KernelVersion)
|
||||
|
||||
err := sendFile(w, fileName, node.Fqdn)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Printf("ERROR: %s\n", err)
|
||||
} else {
|
||||
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
|
||||
}
|
||||
|
||||
} else {
|
||||
w.WriteHeader(503)
|
||||
log.Printf("No kernel version set for node %s\n", node.Fqdn)
|
||||
log.Printf("ERROR: No 'kernel version' set for node %s\n", node.Fqdn)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func overlay(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
node, err := getSanity(req)
|
||||
if err != nil {
|
||||
w.WriteHeader(404)
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if node.Overlay!= "" {
|
||||
fileName := fmt.Sprintf("%s/provision/overlays/%s.img", LocalStateDir, node.Fqdn)
|
||||
|
||||
err := sendFile(w, fileName, node.Fqdn)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
} else {
|
||||
w.WriteHeader(503)
|
||||
log.Printf("No Overlay set for node %s\n", node.Fqdn)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -2,45 +2,57 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func runtime(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
node, err := getSanity(req)
|
||||
if err != nil {
|
||||
w.WriteHeader(404)
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
func runtimeOverlay(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
remote := strings.Split(req.RemoteAddr, ":")
|
||||
port, err := strconv.Atoi(remote[1])
|
||||
if err != nil {
|
||||
w.WriteHeader(404)
|
||||
log.Printf("Could not convert port to integer: %s\n", remote[1])
|
||||
w.WriteHeader(503)
|
||||
return
|
||||
}
|
||||
|
||||
if port >= 1024 {
|
||||
log.Panicf("DENIED: Connection coming from non-privledged port: %s\n", req.RemoteAddr)
|
||||
w.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
if node.Overlay!= "" {
|
||||
fileName := fmt.Sprintf("%s/provision/runtime/%s.img", LocalStateDir, node.Fqdn)
|
||||
node, err := assets.FindByIpaddr(remote[0])
|
||||
if err != nil {
|
||||
fmt.Printf("Could not find node by IP address: %s\n", remote[0])
|
||||
w.WriteHeader(404)
|
||||
return
|
||||
}
|
||||
|
||||
if node.Fqdn == "" {
|
||||
log.Printf("UNKNOWN: %15s: %s\n", remote[0], req.URL.Path)
|
||||
w.WriteHeader(404)
|
||||
return
|
||||
} else {
|
||||
log.Printf("REQ: %15s: %s\n", node.Fqdn, req.URL.Path)
|
||||
}
|
||||
|
||||
if node.RuntimeOverlay != "" {
|
||||
fileName := fmt.Sprintf("%s/provision/overlays/runtime/%s.img", LocalStateDir, node.Fqdn)
|
||||
|
||||
err := sendFile(w, fileName, node.Fqdn)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Printf("ERROR: %s\n", err)
|
||||
} else {
|
||||
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
|
||||
}
|
||||
} else {
|
||||
w.WriteHeader(503)
|
||||
log.Printf("No Overlay set for node %s\n", node.Fqdn)
|
||||
log.Printf("ERROR: No 'runtime overlay' set for node %s\n", node.Fqdn)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
33
cmd/warewulfd/system.go
Normal file
33
cmd/warewulfd/system.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func systemOverlay(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
node, err := getSanity(req)
|
||||
if err != nil {
|
||||
w.WriteHeader(404)
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if node.SystemOverlay != "" {
|
||||
fileName := fmt.Sprintf("%s/provision/overlays/system/%s.img", LocalStateDir, node.Fqdn)
|
||||
|
||||
err := sendFile(w, fileName, node.Fqdn)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: %s\n", err)
|
||||
} else {
|
||||
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
|
||||
}
|
||||
} else {
|
||||
w.WriteHeader(503)
|
||||
log.Printf("ERROR: No 'system overlay' set for node %s\n", node.Fqdn)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -17,16 +17,18 @@ func vnfs(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
if node.Vnfs != "" {
|
||||
fileName := fmt.Sprintf("%s/provision/bases/%s.img.gz", LocalStateDir, path.Base(node.Vnfs))
|
||||
fileName := fmt.Sprintf("%s/provision/vnfs/%s.img.gz", LocalStateDir, path.Base(node.Vnfs))
|
||||
|
||||
err := sendFile(w, fileName, node.Fqdn)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Printf("ERROR: %s\n", err)
|
||||
} else {
|
||||
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
|
||||
}
|
||||
} else {
|
||||
w.WriteHeader(503)
|
||||
log.Printf("No VNFS set for node %s\n", node.Fqdn)
|
||||
log.Printf("ERROR: No VNFS set for node %s\n", node.Fqdn)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,136 +1,73 @@
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
"github.com/hpcng/warewulf/internal/pkg/errors"
|
||||
"net/http"
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
"github.com/hpcng/warewulf/internal/pkg/errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// TODO: https://github.com/danderson/netboot/blob/master/pixiecore/dhcp.go
|
||||
// TODO: https://github.com/pin/tftp
|
||||
|
||||
|
||||
const LocalStateDir = "/var/warewulf"
|
||||
|
||||
func getSanity(req *http.Request) (assets.NodeInfo, error) {
|
||||
url := strings.Split(req.URL.Path, "/")
|
||||
url := strings.Split(req.URL.Path, "/")
|
||||
|
||||
hwaddr := strings.ReplaceAll(url[2], "-", ":")
|
||||
node, err := assets.FindByHwaddr(hwaddr)
|
||||
log.Printf("REQ: %s: %s\n", hwaddr, req.URL.Path)
|
||||
if err != nil {
|
||||
return node, errors.New("Could not find HW address")
|
||||
}
|
||||
hwaddr := strings.ReplaceAll(url[2], "-", ":")
|
||||
node, err := assets.FindByHwaddr(hwaddr)
|
||||
if err != nil {
|
||||
return node, errors.New("Could not find node by HW address")
|
||||
}
|
||||
|
||||
if node.Fqdn == "" {
|
||||
fmt.Printf("UNKNOWN: %15s: %s\n", node.Fqdn, req.URL.Path)
|
||||
return node, errors.New("Unknown Node: "+ hwaddr)
|
||||
}
|
||||
fmt.Printf("GET: %15s: %s\n", node.Fqdn, req.URL.Path)
|
||||
if node.Fqdn == "" {
|
||||
log.Printf("UNKNOWN: %15s: %s\n", hwaddr, req.URL.Path)
|
||||
return node, errors.New("Unknown node HW address: " + hwaddr)
|
||||
} else {
|
||||
log.Printf("REQ: %15s: %s\n", node.Fqdn, req.URL.Path)
|
||||
}
|
||||
|
||||
return node, nil
|
||||
return node, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func files(w http.ResponseWriter, req *http.Request) {
|
||||
url := strings.Split(req.URL.Path, "/")
|
||||
|
||||
node := assets.FindByHwaddr(strings.ReplaceAll(url[3], "-", ":"))
|
||||
|
||||
if node.Fqdn == "" {
|
||||
fmt.Printf("UNKNOWN: %15s: %s\n", node.Fqdn, req.URL.Path)
|
||||
}
|
||||
fmt.Printf("GET: %15s: %s\n", node.Fqdn, req.URL.Path)
|
||||
|
||||
if url[2] == "kernel" {
|
||||
if node.KernelVersion != "" {
|
||||
kernelFile := fmt.Sprintf("%s/provision/kernels/vmlinuz-%s", LocalStateDir, node.KernelVersion)
|
||||
|
||||
sendFile(w, kernelFile, node.Fqdn)
|
||||
}
|
||||
} else if url[2] == "kmods" {
|
||||
if node.KernelVersion != "" {
|
||||
kmodsFile := fmt.Sprintf("%s/provision/kernels/kmods-%s.img", LocalStateDir, node.KernelVersion)
|
||||
|
||||
sendFile(w, kmodsFile, node.Fqdn)
|
||||
}
|
||||
} else if url[2] == "vnfs" {
|
||||
if node.Vnfs != "" {
|
||||
vnfsFile := fmt.Sprintf("%s/provision/bases/%s.img.gz", LocalStateDir, path.Base(node.Vnfs))
|
||||
|
||||
sendFile(w, vnfsFile, node.Fqdn)
|
||||
}
|
||||
} else if url[2] == "overlay" {
|
||||
if node.Overlay!= "" {
|
||||
overlayFile := fmt.Sprintf("%s/provision/overlays/%s.img", LocalStateDir, node.Fqdn)
|
||||
|
||||
sendFile(w, overlayFile, node.Fqdn)
|
||||
}
|
||||
} else if url[2] == "runtime" {
|
||||
fmt.Printf("FROM: %s\n", req.RemoteAddr)
|
||||
|
||||
remote := strings.Split(req.RemoteAddr, ":")
|
||||
port, _ := strconv.Atoi(remote[1])
|
||||
|
||||
if port >= 1024 {
|
||||
fmt.Printf("DENIED: Connection coming from non-privledged port: %s\n", req.RemoteAddr)
|
||||
return
|
||||
}
|
||||
|
||||
if node.Overlay!= "" {
|
||||
overlayFile := fmt.Sprintf("%s/provision/runtime/%s.img", LocalStateDir, node.Fqdn)
|
||||
|
||||
sendFile(w, overlayFile, node.Fqdn)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
func sendFile(w http.ResponseWriter, filename string, sendto string) error {
|
||||
|
||||
fmt.Printf("SEND: %15s: %s\n", sendto, filename)
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return err
|
||||
}
|
||||
FileHeader := make([]byte, 512)
|
||||
fd.Read(FileHeader)
|
||||
FileContentType := http.DetectContentType(FileHeader)
|
||||
FileStat, _ := fd.Stat()
|
||||
FileSize := strconv.FormatInt(FileStat.Size(), 10)
|
||||
|
||||
FileHeader := make([]byte, 512)
|
||||
fd.Read(FileHeader)
|
||||
FileContentType := http.DetectContentType(FileHeader)
|
||||
FileStat, _ := fd.Stat()
|
||||
FileSize := strconv.FormatInt(FileStat.Size(), 10)
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=kernel")
|
||||
w.Header().Set("Content-Type", FileContentType)
|
||||
w.Header().Set("Content-Length", FileSize)
|
||||
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=kernel")
|
||||
w.Header().Set("Content-Type", FileContentType)
|
||||
w.Header().Set("Content-Length", FileSize)
|
||||
fd.Seek(0, 0)
|
||||
io.Copy(w, fd)
|
||||
|
||||
fd.Seek(0, 0)
|
||||
io.Copy(w, fd)
|
||||
|
||||
fd.Close()
|
||||
return nil
|
||||
fd.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
|
||||
http.HandleFunc("/ipxe/", ipxe)
|
||||
http.HandleFunc("/kernel/", kernel)
|
||||
http.HandleFunc("/kmods/", kmods)
|
||||
http.HandleFunc("/vnfs/", vnfs)
|
||||
http.HandleFunc("/overlay/", overlay)
|
||||
http.HandleFunc("/runtime/", runtime)
|
||||
http.HandleFunc("/ipxe/", ipxe)
|
||||
http.HandleFunc("/kernel/", kernel)
|
||||
http.HandleFunc("/kmods/", kmods)
|
||||
http.HandleFunc("/vnfs/", vnfs)
|
||||
http.HandleFunc("/overlay-system/", systemOverlay)
|
||||
http.HandleFunc("/overlay-runtime", runtimeOverlay)
|
||||
|
||||
http.ListenAndServe(":9873", nil)
|
||||
http.ListenAndServe(":9873", nil)
|
||||
}
|
||||
|
||||
58
cmd/wwbuild/overlay-runtime.go
Normal file
58
cmd/wwbuild/overlay-runtime.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func overlayRuntime(node assets.NodeInfo, replace map[string]string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
OverlayDir := fmt.Sprintf("%s/overlays/runtime/%s", LocalStateDir, node.RuntimeOverlay)
|
||||
OverlayFile := fmt.Sprintf("%s/provision/overlays/runtime/%s.img", LocalStateDir, node.Fqdn)
|
||||
/*
|
||||
destModTime := time.Time{}
|
||||
destMod, err := os.Stat(OverlayFile)
|
||||
if err == nil {
|
||||
destModTime = destMod.ModTime()
|
||||
}
|
||||
configMod, err := os.Stat("/etc/warewulf/nodes.yaml")
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: could not find node file: /etc/warewulf/nodes.yaml")
|
||||
os.Exit(1)
|
||||
}
|
||||
configModTime := configMod.ModTime()
|
||||
sourceModTime, _ := util.DirModTime(OverlayDir)
|
||||
*/
|
||||
err := os.MkdirAll(path.Dir(OverlayFile), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
err = os.MkdirAll(OverlayDir, 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
// if sourceModTime.After(destModTime) || configModTime.After(destModTime) {
|
||||
fmt.Printf("RUNTIME: %s\n", node.Fqdn)
|
||||
|
||||
overlayDest := "/tmp/.overlay-" + util.RandomString(16)
|
||||
BuildOverlayDir(OverlayDir, overlayDest, replace)
|
||||
|
||||
cmd := fmt.Sprintf("cd %s && find . | cpio --quiet -o -H newc -F \"%s\"", overlayDest, OverlayFile)
|
||||
err = exec.Command("/bin/sh", "-c", cmd).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
|
||||
os.RemoveAll(overlayDest)
|
||||
// } else {
|
||||
// fmt.Printf("RUNTIME: %s (skipped no changes)\n", node.Fqdn)
|
||||
// }
|
||||
}
|
||||
60
cmd/wwbuild/overlay-system.go
Normal file
60
cmd/wwbuild/overlay-system.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func overlaySystem(node assets.NodeInfo, replace map[string]string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
OverlayDir := fmt.Sprintf("%s/overlays/system/%s", LocalStateDir, node.SystemOverlay)
|
||||
OverlayFile := fmt.Sprintf("%s/provision/overlays/system/%s.img", LocalStateDir, node.Fqdn)
|
||||
/*
|
||||
destModTime := time.Time{}
|
||||
destMod, err := os.Stat(OverlayFile)
|
||||
if err == nil {
|
||||
destModTime = destMod.ModTime()
|
||||
}
|
||||
configMod, err := os.Stat("/etc/warewulf/nodes.yaml")
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: could not find node file: /etc/warewulf/nodes.yaml")
|
||||
os.Exit(1)
|
||||
}
|
||||
configModTime := configMod.ModTime()
|
||||
sourceModTime, _ := util.DirModTime(OverlayDir)
|
||||
*/
|
||||
err := os.MkdirAll(path.Dir(OverlayFile), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
err = os.MkdirAll(OverlayDir, 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// if sourceModTime.After(destModTime) || configModTime.After(destModTime) {
|
||||
fmt.Printf("SYSTEM: %s\n", node.Fqdn)
|
||||
|
||||
overlayDest := "/tmp/.overlay-" + util.RandomString(16)
|
||||
BuildOverlayDir(OverlayDir, overlayDest, replace)
|
||||
|
||||
cmd := fmt.Sprintf("cd %s && find . | cpio --quiet -o -H newc -F \"%s\"", overlayDest, OverlayFile)
|
||||
err = exec.Command("/bin/sh", "-c", cmd).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
|
||||
os.RemoveAll(overlayDest)
|
||||
|
||||
// } else {
|
||||
// fmt.Printf("SYSTEM: %s (skipped no changes)\n", node.Fqdn)
|
||||
// }
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
||||
func BuildOverlayDir(sourceDir string, destDir string, replace map[string]string) error {
|
||||
err := os.Chdir(sourceDir)
|
||||
if err != nil {
|
||||
@@ -23,7 +22,7 @@ func BuildOverlayDir(sourceDir string, destDir string, replace map[string]string
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
err := os.MkdirAll(destDir + "/" + path, info.Mode())
|
||||
err := os.MkdirAll(destDir+"/"+path, info.Mode())
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -36,7 +35,7 @@ func BuildOverlayDir(sourceDir string, destDir string, replace map[string]string
|
||||
return err
|
||||
}
|
||||
|
||||
destFD, err :=os.OpenFile(destDir + "/" + destFile, os.O_RDWR|os.O_CREATE, info.Mode())
|
||||
destFD, err := os.OpenFile(destDir+"/"+destFile, os.O_RDWR|os.O_CREATE, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -60,7 +59,7 @@ func BuildOverlayDir(sourceDir string, destDir string, replace map[string]string
|
||||
sourceFD.Close()
|
||||
destFD.Close()
|
||||
} else {
|
||||
err := util.CopyFile(sourceDir + "/" + path, destDir + "/" + path)
|
||||
err := util.CopyFile(sourceDir+"/"+path, destDir+"/"+path)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -76,4 +75,4 @@ func BuildOverlayDir(sourceDir string, destDir string, replace map[string]string
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -1,151 +1,183 @@
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
||||
const LocalStateDir = "/var/warewulf"
|
||||
|
||||
func vnfsBuild(vnfsPath string) {
|
||||
fmt.Printf("BUILDING VNFS: %s\n", vnfsPath)
|
||||
if _, err := os.Stat(vnfsPath); err == nil {
|
||||
// TODO: Build VNFS to temporary file and move to real location when complete atomically
|
||||
// TODO: Check time stamps of sourcedir and build file to see if we need to rebuild or skip
|
||||
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc | gzip -c > \"%s/provision/bases/%s.img.gz\"", vnfsPath, LocalStateDir, path.Base(vnfsPath))
|
||||
err := exec.Command("/bin/sh", "-c", cmd).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("SKIPPING VNFS: (bad path) %s\n", vnfsPath)
|
||||
}
|
||||
func vnfsBuild(vnfsPath string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
if _, err := os.Stat(vnfsPath); err == nil {
|
||||
// TODO: Build VNFS to temporary file and move to real location when complete atomically
|
||||
// TODO: Check time stamps of sourcedir and build file to see if we need to rebuild or skip
|
||||
vnfsDestination := fmt.Sprintf("%s/provision/vnfs/%s.img.gz", LocalStateDir, path.Base(vnfsPath))
|
||||
|
||||
err := os.MkdirAll(path.Dir(vnfsDestination), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("BUILDING VNFS: %s\n", vnfsPath)
|
||||
|
||||
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc | gzip -c > \"%s\"", vnfsPath, vnfsDestination)
|
||||
err = exec.Command("/bin/sh", "-c", cmd).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("BUILD DONE: %s\n", vnfsPath)
|
||||
|
||||
} else {
|
||||
fmt.Printf("SKIPPING VNFS: (bad path) %s\n", vnfsPath)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Printf("USAGE: %s [vnfs/kernel/overlay/all]\n", os.Args[0])
|
||||
return
|
||||
}
|
||||
|
||||
func main(){
|
||||
if os.Args[1] == "vnfs" {
|
||||
var nodeList []assets.NodeInfo
|
||||
set := make(map[string]bool)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Printf("USAGE: %s [vnfs/kernel/overlays/all]\n", os.Args[0])
|
||||
return
|
||||
}
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Printf("USAGE: %s vnfs [node name pattern/ALL]\n", os.Args[0])
|
||||
return
|
||||
}
|
||||
|
||||
if os.Args[2] == "ALL" {
|
||||
nodeList, _ = assets.FindAllNodes()
|
||||
} else {
|
||||
nodeList, _ = assets.SearchByName(os.Args[2])
|
||||
}
|
||||
|
||||
if os.Args[1] == "vnfs" {
|
||||
if len(os.Args) >= 3 {
|
||||
vnfsBuild(os.Args[3])
|
||||
} else {
|
||||
nodeList, err := assets.FindAllVnfs()
|
||||
if err != nil {
|
||||
log.Panicf("Could not locate VNFS images: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if len(nodeList) == 0 {
|
||||
fmt.Printf("ERROR: No nodes found\n")
|
||||
return
|
||||
}
|
||||
|
||||
for _, vnfs := range nodeList {
|
||||
vnfsBuild(vnfs)
|
||||
}
|
||||
}
|
||||
} else if os.Args[1] == "kernel" {
|
||||
nodeList, err := assets.FindAllKernels()
|
||||
if err != nil {
|
||||
log.Panicf("Could not locate Kernel Versions: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
for _, node := range nodeList {
|
||||
if node.Vnfs != "" {
|
||||
set[node.Vnfs] = true
|
||||
}
|
||||
}
|
||||
for entry := range set {
|
||||
wg.Add(1)
|
||||
go vnfsBuild(entry, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for _, kernelVers := range nodeList {
|
||||
kernelSource := fmt.Sprintf("/boot/vmlinuz-%s", kernelVers)
|
||||
// TODO: Check time stamps of source and dests to see if we need to rebuild or skip
|
||||
if _, err := os.Stat(kernelSource); err == nil {
|
||||
kernelDestination := fmt.Sprintf("%s/provision/kernels/vmlinuz-%s", LocalStateDir, kernelVers)
|
||||
fmt.Printf("SETUP KERNEL: %s (%s)\n", kernelSource, kernelDestination)
|
||||
err := exec.Command("cp", kernelSource, kernelDestination).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
} else if os.Args[1] == "kernel" {
|
||||
var nodeList []assets.NodeInfo
|
||||
set := make(map[string]bool)
|
||||
|
||||
kernelMods := fmt.Sprintf("/lib/modules/%s", kernelVers)
|
||||
if _, err := os.Stat(kernelMods); err == nil {
|
||||
fmt.Printf("BUILDING MODS: %s\n", kernelMods)
|
||||
cmd := fmt.Sprintf("find %s | cpio --quiet -o -H newc -F \"%s/provision/kernels/kmods-%s.img\"", kernelMods, LocalStateDir, kernelVers)
|
||||
err := exec.Command("/bin/sh", "-c", cmd).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("OUTPUT: %s", err)
|
||||
}
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Printf("USAGE: %s vnfs [node name pattern/ALL]\n", os.Args[0])
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if os.Args[1] == "overlay" {
|
||||
//TODO: Move this all to warewulfd and generate on demand when needed
|
||||
nodeList, err := assets.FindAllNodes()
|
||||
if err != nil {
|
||||
log.Panicf("Could not identify nodes: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if os.Args[2] == "ALL" {
|
||||
nodeList, _ = assets.FindAllNodes()
|
||||
} else {
|
||||
nodeList, _ = assets.SearchByName(os.Args[2])
|
||||
}
|
||||
|
||||
for _, node := range nodeList {
|
||||
if len(nodeList) == 0 {
|
||||
fmt.Printf("ERROR: No nodes found\n")
|
||||
return
|
||||
}
|
||||
|
||||
overlayDir := fmt.Sprintf("/etc/warewulf/overlays/%s", node.Overlay)
|
||||
for _, node := range nodeList {
|
||||
if node.KernelVersion != "" {
|
||||
set[node.KernelVersion] = true
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Move this all to the Asset package
|
||||
replace := make(map[string]string)
|
||||
replace["HOSTNAME"] = node.HostName
|
||||
replace["FQDN"] = node.Fqdn
|
||||
replace["VNFS"] = node.Vnfs
|
||||
replace["KERNELVERSION"] = node.KernelVersion
|
||||
replace["GROUPNAME"] = node.GroupName
|
||||
replace["DOMAIN"] = node.DomainName
|
||||
for key, dev := range node.NetDevs {
|
||||
replace[fmt.Sprintf("%s:NAME", key)] = key
|
||||
replace[fmt.Sprintf("%s:HWADDR", key)] = strings.ReplaceAll(dev.Hwaddr, "-", ":")
|
||||
replace[fmt.Sprintf("%s:IPADDR", key)] = dev.Ipaddr
|
||||
replace[fmt.Sprintf("%s:NETMASK", key)] = dev.Netmask
|
||||
replace[fmt.Sprintf("%s:GATEWAY", key)] = dev.Gateway
|
||||
}
|
||||
for kernelVers := range set {
|
||||
kernelSource := fmt.Sprintf("/boot/vmlinuz-%s", kernelVers)
|
||||
// TODO: Check time stamps of source and dests to see if we need to rebuild or skip
|
||||
if _, err := os.Stat(kernelSource); err == nil {
|
||||
kernelDestination := fmt.Sprintf("%s/provision/kernel/vmlinuz-%s", LocalStateDir, kernelVers)
|
||||
kmodsDestination := fmt.Sprintf("%s/provision/kernel/kmods-%s.img", LocalStateDir, kernelVers)
|
||||
|
||||
destFile := fmt.Sprintf("%s/provision/overlays/%s.img", LocalStateDir, node.Fqdn)
|
||||
err := os.MkdirAll(path.Dir(kernelDestination), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
destModTime := time.Time{}
|
||||
destMod, err := os.Stat(destFile)
|
||||
if err == nil {
|
||||
destModTime = destMod.ModTime()
|
||||
}
|
||||
fmt.Printf("SETUP KERNEL: %s (%s)\n", kernelSource, kernelDestination)
|
||||
err = exec.Command("cp", kernelSource, kernelDestination).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
|
||||
configMod, err := os.Stat("/etc/warewulf/nodes.yaml")
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: could not find node file: /etc/warewulf/nodes.yaml")
|
||||
os.Exit(1)
|
||||
}
|
||||
configModTime := configMod.ModTime()
|
||||
kernelMods := fmt.Sprintf("./lib/modules/%s", kernelVers)
|
||||
if _, err := os.Stat(kernelMods); err == nil {
|
||||
fmt.Printf("BUILDING MODS: %s\n", kernelMods)
|
||||
cmd := fmt.Sprintf("cd /; find %s | cpio --quiet -o -H newc -F \"%s\"", kernelMods, kmodsDestination)
|
||||
err := exec.Command("/bin/sh", "-c", cmd).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("OUTPUT: %s", err)
|
||||
}
|
||||
|
||||
sourceModTime, _ := util.DirModTime(overlayDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if os.Args[1] == "overlay" {
|
||||
var nodeList []assets.NodeInfo
|
||||
var wg sync.WaitGroup
|
||||
|
||||
if sourceModTime.After(destModTime) || configModTime.After(destModTime) {
|
||||
fmt.Printf("BUILDING OVERLAY: %s\n", node.Fqdn)
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Printf("USAGE: %s vnfs [node name pattern/ALL]\n", os.Args[0])
|
||||
return
|
||||
}
|
||||
|
||||
overlayDest := "/tmp/.overlay-" + util.RandomString(16)
|
||||
BuildOverlayDir(overlayDir, overlayDest, replace)
|
||||
if os.Args[2] == "ALL" {
|
||||
nodeList, _ = assets.FindAllNodes()
|
||||
} else {
|
||||
nodeList, _ = assets.SearchByName(os.Args[2])
|
||||
}
|
||||
|
||||
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc -F \"%s\"", overlayDest, destFile)
|
||||
err := exec.Command("/bin/sh", "-c", cmd).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
if len(nodeList) == 0 {
|
||||
fmt.Printf("ERROR: No nodes found\n")
|
||||
return
|
||||
}
|
||||
|
||||
for _, node := range nodeList {
|
||||
|
||||
replace := make(map[string]string)
|
||||
replace["HOSTNAME"] = node.HostName
|
||||
replace["FQDN"] = node.Fqdn
|
||||
replace["VNFS"] = node.Vnfs
|
||||
replace["KERNELVERSION"] = node.KernelVersion
|
||||
replace["GROUPNAME"] = node.GroupName
|
||||
replace["DOMAIN"] = node.DomainName
|
||||
for key, dev := range node.NetDevs {
|
||||
replace[fmt.Sprintf("%s:NAME", key)] = key
|
||||
replace[fmt.Sprintf("%s:HWADDR", key)] = strings.ReplaceAll(dev.Hwaddr, "-", ":")
|
||||
replace[fmt.Sprintf("%s:IPADDR", key)] = dev.Ipaddr
|
||||
replace[fmt.Sprintf("%s:NETMASK", key)] = dev.Netmask
|
||||
replace[fmt.Sprintf("%s:GATEWAY", key)] = dev.Gateway
|
||||
}
|
||||
|
||||
wg.Add(2)
|
||||
overlayRuntime(node, replace, &wg)
|
||||
overlaySystem(node, replace, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
os.RemoveAll(overlayDest)
|
||||
} else {
|
||||
fmt.Printf("Skipping overlay (nothing changed): %s\n", node.Fqdn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,20 +11,20 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
func main() {
|
||||
os.Chdir("/")
|
||||
|
||||
// Setting up the connection manually so we can ensure a low port
|
||||
localAddr, err := net.ResolveIPAddr("ip", "localhost")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
if os.Args[0] == "/warewulf/bin/wwclient" {
|
||||
os.Chdir("/")
|
||||
log.Printf("Updating live file system LIVE, cancel now if this is in error")
|
||||
time.Sleep(5000 * time.Millisecond)
|
||||
} else {
|
||||
fmt.Printf("Called via: %s\n", os.Args[0])
|
||||
fmt.Printf("Runtime overlay is being put in '/warewulf/wwclient-test' rather than '/'\n")
|
||||
os.MkdirAll("/warewulf/wwclient-test", 0755)
|
||||
os.Chdir("/warewulf/wwclient-test")
|
||||
}
|
||||
|
||||
// Setup local port to 987
|
||||
localTCPAddr := net.TCPAddr{
|
||||
IP: localAddr.IP,
|
||||
Port: 987,
|
||||
}
|
||||
|
||||
@@ -46,34 +46,57 @@ func main() {
|
||||
|
||||
for true {
|
||||
var resp *http.Response
|
||||
counter := 0
|
||||
|
||||
for true {
|
||||
var err error
|
||||
fmt.Printf("Connecting ....\n")
|
||||
resp, err = webclient.Get("http://192.168.1.1:9873/runtime/xx-xx-xx-xx-xx")
|
||||
|
||||
resp, err = webclient.Get("http://192.168.1.1:9873/overlay-runtime")
|
||||
if err == nil {
|
||||
break
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
if counter > 60 {
|
||||
counter = 0
|
||||
}
|
||||
if counter == 0 {
|
||||
log.Println(err)
|
||||
}
|
||||
counter++
|
||||
}
|
||||
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
}
|
||||
|
||||
fmt.Printf("Connection accepted to remote host\n")
|
||||
command := exec.Command("cpio", "-i")
|
||||
stdin, err := command.StdinPipe()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
log.Printf("Not updating runtime overlay, got status code: %d\n", resp.StatusCode)
|
||||
time.Sleep(60000 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
||||
command := exec.Command("cpio", "-i")
|
||||
command.Wait()
|
||||
stdin, err := command.StdinPipe()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
defer stdin.Close()
|
||||
|
||||
go func() {
|
||||
defer stdin.Close()
|
||||
io.Copy(stdin, resp.Body)
|
||||
bytes, err := io.Copy(stdin, resp.Body)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: io.Copy() failed: %s\n", err)
|
||||
} else {
|
||||
log.Printf("Updated the runtime overlay (recv: %d)\n", bytes)
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
command.Run()
|
||||
resp.Body.Close()
|
||||
|
||||
time.Sleep(5000 * time.Millisecond)
|
||||
// defer webclient.CloseIdleConnections()
|
||||
|
||||
|
||||
time.Sleep(30000 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user