Lots of cleanups, added vnfs package and utilizing config package for constants

This commit is contained in:
Gregory Kurtzer
2020-11-09 17:24:35 -08:00
parent 76a8b2c135
commit f3ec8ee923
20 changed files with 206 additions and 93 deletions

View File

@@ -12,7 +12,7 @@ import (
"strings"
)
func ipxe(w http.ResponseWriter, req *http.Request) {
func ipxeSend(w http.ResponseWriter, req *http.Request) {
url := strings.Split(req.URL.Path, "/")
if url[2] == "" {
@@ -58,12 +58,10 @@ func ipxe(w http.ResponseWriter, req *http.Request) {
// TODO: Add KernelArgs to nodes.conf
//newLine = strings.ReplaceAll(newLine, "@KERNELARGS@", node.KernelArgs)
fmt.Fprintln(w, newLine)
}
log.Printf("SEND: %15s: %s\n", node.Fqdn, ipxeTemplate)
} else {
log.Printf("ERROR: iPXE request from unknown Node (hwaddr=%s)\n", url[2])
}

View File

@@ -2,11 +2,12 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"log"
"net/http"
)
func kernel(w http.ResponseWriter, req *http.Request) {
func kernelSend(w http.ResponseWriter, req *http.Request) {
node, err := getSanity(req)
if err != nil {
@@ -16,7 +17,7 @@ func kernel(w http.ResponseWriter, req *http.Request) {
}
if node.KernelVersion != "" {
fileName := fmt.Sprintf("%s/provision/kernel/vmlinuz-%s", LocalStateDir, node.KernelVersion)
fileName := fmt.Sprintf("%s/provision/kernel/vmlinuz-%s", config.LocalStateDir, node.KernelVersion)
err := sendFile(w, fileName, node.Fqdn)
if err != nil {

View File

@@ -2,11 +2,12 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"log"
"net/http"
)
func kmods(w http.ResponseWriter, req *http.Request) {
func kmodsSend(w http.ResponseWriter, req *http.Request) {
node, err := getSanity(req)
if err != nil {
@@ -15,7 +16,7 @@ func kmods(w http.ResponseWriter, req *http.Request) {
return
}
if node.KernelVersion != "" {
fileName := fmt.Sprintf("%s/provision/kernel/kmods-%s.img", LocalStateDir, node.KernelVersion)
fileName := fmt.Sprintf("%s/provision/kernel/kmods-%s.img", config.LocalStateDir, node.KernelVersion)
err := sendFile(w, fileName, node.Fqdn)
if err != nil {

View File

@@ -10,7 +10,7 @@ import (
"strings"
)
func runtimeOverlay(w http.ResponseWriter, req *http.Request) {
func runtimeOverlaySend(w http.ResponseWriter, req *http.Request) {
remote := strings.Split(req.RemoteAddr, ":")
port, err := strconv.Atoi(remote[1])
if err != nil {
@@ -49,7 +49,7 @@ func runtimeOverlay(w http.ResponseWriter, req *http.Request) {
}
if node.RuntimeOverlay != "" {
fileName := fmt.Sprintf("%s/provision/overlays/runtime/%s.img", LocalStateDir, node.Fqdn)
fileName := fmt.Sprintf("%s/provision/overlays/runtime/%s.img", config.LocalStateDir, node.Fqdn)
err := sendFile(w, fileName, node.Fqdn)
if err != nil {

View File

@@ -2,11 +2,12 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"log"
"net/http"
)
func systemOverlay(w http.ResponseWriter, req *http.Request) {
func systemOverlaySend(w http.ResponseWriter, req *http.Request) {
node, err := getSanity(req)
if err != nil {
@@ -16,7 +17,7 @@ func systemOverlay(w http.ResponseWriter, req *http.Request) {
}
if node.SystemOverlay != "" {
fileName := fmt.Sprintf("%s/provision/overlays/system/%s.img", LocalStateDir, node.Fqdn)
fileName := fmt.Sprintf("%s/provision/overlays/system/%s.img", config.LocalStateDir, node.Fqdn)
err := sendFile(w, fileName, node.Fqdn)
if err != nil {

View File

@@ -1,13 +1,12 @@
package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"log"
"net/http"
"path"
)
func vnfs(w http.ResponseWriter, req *http.Request) {
func vnfsSend(w http.ResponseWriter, req *http.Request) {
node, err := getSanity(req)
if err != nil {
@@ -17,13 +16,13 @@ func vnfs(w http.ResponseWriter, req *http.Request) {
}
if node.Vnfs != "" {
fileName := fmt.Sprintf("%s/provision/vnfs/%s.img.gz", LocalStateDir, path.Base(node.Vnfs))
v := vnfs.New(node.Vnfs)
err := sendFile(w, fileName, node.Fqdn)
err := sendFile(w, v.Image(), node.Fqdn)
if err != nil {
log.Printf("ERROR: %s\n", err)
} else {
log.Printf("SEND: %15s: %s\n", node.Fqdn, fileName)
log.Printf("SEND: %15s: %s\n", node.Fqdn, v.Image())
}
} else {
w.WriteHeader(503)

View File

@@ -15,7 +15,7 @@ import (
// TODO: https://github.com/danderson/netboot/blob/master/pixiecore/dhcp.go
// TODO: https://github.com/pin/tftp
const LocalStateDir = "/var/warewulf"
//const LocalStateDir = "/var/warewulf"
func getSanity(req *http.Request) (assets.NodeInfo, error) {
url := strings.Split(req.URL.Path, "/")
@@ -62,12 +62,12 @@ func sendFile(w http.ResponseWriter, filename string, sendto string) error {
func main() {
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.HandleFunc("/ipxe/", ipxeSend)
http.HandleFunc("/kernel/", kernelSend)
http.HandleFunc("/kmods/", kmodsSend)
http.HandleFunc("/vnfs/", vnfsSend)
http.HandleFunc("/overlay-system/", systemOverlaySend)
http.HandleFunc("/overlay-runtime", runtimeOverlaySend)
http.ListenAndServe(":9873", nil)
}

View File

@@ -3,6 +3,7 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"os"
"os/exec"
@@ -13,22 +14,22 @@ import (
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.conf")
if err != nil {
fmt.Printf("ERROR: could not find node file: /etc/warewulf/nodes.conf")
os.Exit(1)
}
configModTime := configMod.ModTime()
sourceModTime, _ := util.DirModTime(OverlayDir)
*/
OverlayDir := fmt.Sprintf("%s/overlays/runtime/%s", config.LocalStateDir, node.RuntimeOverlay)
OverlayFile := fmt.Sprintf("%s/provision/overlays/runtime/%s.img", config.LocalStateDir, node.Fqdn)
/*
destModTime := time.Time{}
destMod, err := os.Stat(OverlayFile)
if err == nil {
destModTime = destMod.ModTime()
}
configMod, err := os.Stat("/etc/warewulf/nodes.conf")
if err != nil {
fmt.Printf("ERROR: could not find node file: /etc/warewulf/nodes.conf")
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)
@@ -39,20 +40,20 @@ func overlayRuntime(node assets.NodeInfo, replace map[string]string, wg *sync.Wa
fmt.Printf("ERROR: %s\n", err)
return
}
// if sourceModTime.After(destModTime) || configModTime.After(destModTime) {
fmt.Printf("RUNTIME: %s\n", node.Fqdn)
// if sourceModTime.After(destModTime) || configModTime.After(destModTime) {
fmt.Printf("RUNTIME: %s\n", node.Fqdn)
overlayDest := "/tmp/.overlay-" + util.RandomString(16)
BuildOverlayDir(OverlayDir, overlayDest, replace)
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)
}
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)
// }
os.RemoveAll(overlayDest)
// } else {
// fmt.Printf("RUNTIME: %s (skipped no changes)\n", node.Fqdn)
// }
}

View File

@@ -3,6 +3,7 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"os"
"os/exec"
@@ -14,17 +15,17 @@ import (
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)
OverlayDir := fmt.Sprintf("%s/overlays/system/%s", config.LocalStateDir, node.SystemOverlay)
OverlayFile := fmt.Sprintf("%s/provision/overlays/system/%s.img", config.LocalStateDir, node.Fqdn)
destModTime := time.Time{}
destMod, err := os.Stat(OverlayFile)
if err == nil {
destModTime = destMod.ModTime()
}
configMod, err := os.Stat("/etc/warewulf/nodes.conf")
configMod, err := os.Stat(config.SysConfDir + "nodes.conf")
if err != nil {
fmt.Printf("ERROR: could not find node file: /etc/warewulf/nodes.conf\n")
fmt.Printf("ERROR: could not find node file: nodes.conf\n", config.SysConfDir)
os.Exit(1)
}
configModTime := configMod.ModTime()

View File

@@ -2,6 +2,7 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"os"
"path"
"sync"
@@ -9,22 +10,29 @@ import (
func vnfsLocalBuild(vnfsPath string, wg *sync.WaitGroup) {
defer wg.Done()
v := vnfs.New(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
vnfsDestination := fmt.Sprintf("%s/provision/vnfs/%s.img.gz", LocalStateDir, path.Base(vnfsPath))
//vnfsDestination := fmt.Sprintf("%s/provision/vnfs/%s.img.gz", LocalStateDir, path.Base(vnfsPath))
fmt.Printf("Building local Container: %s\n", vnfsPath)
err := os.MkdirAll(path.Dir(vnfsDestination), 0755)
err := os.MkdirAll(path.Dir(v.Image()), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
err = buildVnfs(vnfsPath, vnfsDestination)
err = buildVnfs(vnfsPath, v.Image())
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
err = buildLinks(v, vnfsPath)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)

View File

@@ -3,75 +3,90 @@ package main
import (
"context"
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/oci"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"log"
"os"
"path"
"sync"
)
const (
OciCacheDir = config.LocalStateDir + "/oci"
VnfsHashDir = config.LocalStateDir + "/oci/vnfs/hash/"
)
func vnfsOciBuild(OciPath string, wg *sync.WaitGroup) {
vnfsDestination := fmt.Sprintf("%s/provision/vnfs/%s.img.gz", LocalStateDir, path.Base(OciPath))
v := vnfs.New(OciPath)
// vnfsDestination := fmt.Sprintf("%s/provision/vnfs/%s.img.gz", LocalStateDir, path.Base(OciPath))
defer wg.Done()
log.Printf("Building OCI Container: %s\n", OciPath)
c, err := oci.NewCache(oci.OptSetCachePath("/var/warewulf/oci"))
c, err := oci.NewCache(oci.OptSetCachePath(OciCacheDir))
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
log.Printf("Downloading OCI container layers\n")
sourcePath, err := c.Pull(context.Background(), OciPath, nil)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
ociDestination := fmt.Sprintf("%s/oci/vnfs/hash/%s", LocalStateDir, path.Base(sourcePath))
hashDestination := VnfsHashDir + path.Base(sourcePath)
name, err := os.Readlink(vnfsDestination)
name, err := os.Readlink(v.Image())
if err == nil {
if name == ociDestination {
log.Printf("Container already built, no changes from upstream\n")
if name == hashDestination {
log.Printf("Container already built, no update available\n")
return
}
}
err = os.MkdirAll(path.Dir(ociDestination), 0755)
err = os.MkdirAll(VnfsHashDir, 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
err = os.MkdirAll(path.Dir(vnfsDestination), 0755)
err = os.MkdirAll(path.Dir(v.Image()), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
err = os.MkdirAll(LocalStateDir+"/oci/vnfs/name", 0755)
err = os.MkdirAll(path.Dir(v.Root()), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
err = buildVnfs(sourcePath, ociDestination)
log.Printf("Building bootable VNFS image\n")
err = buildVnfs(sourcePath, hashDestination)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
err = os.Symlink(ociDestination, vnfsDestination+"-link")
log.Printf("Finalizing Build\n")
_ = os.Remove(v.Image() + "-link")
err = os.Symlink(hashDestination, v.Image()+"-link")
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
err = os.Rename(v.Image()+"-link", v.Image())
err = os.Symlink(sourcePath, LocalStateDir+"/oci/vnfs/name/"+path.Base(OciPath))
err = buildLinks(v, sourcePath)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
err = os.Rename(vnfsDestination+"-link", vnfsDestination)
log.Printf("Completed building VNFS: %s\n", path.Base(OciPath))
return

View File

@@ -2,6 +2,8 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"os"
"os/exec"
)
@@ -12,3 +14,23 @@ func buildVnfs(source string, dest string) error {
return err
}
func buildLinks(v vnfs.VnfsObject, source string) error {
// Just incase the temporary link location is present, remove it if we can
_ = os.Remove(v.Root() + "-link")
// Link to a temporary location so we can atomically move the link into place
err := os.Symlink(source, v.Root()+"-link")
if err != nil {
return err
}
// Atomically move the link into place
err = os.Rename(v.Root()+"-link", v.Root())
if err != nil {
return err
}
return nil
}

View File

@@ -3,6 +3,8 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"os"
"os/exec"
"path"
@@ -11,8 +13,6 @@ import (
"time"
)
const LocalStateDir = "/var/warewulf"
func main() {
if len(os.Args) < 2 {
@@ -80,8 +80,8 @@ func main() {
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)
kernelDestination := fmt.Sprintf("%s/provision/kernel/vmlinuz-%s", config.LocalStateDir, kernelVers)
kmodsDestination := fmt.Sprintf("%s/provision/kernel/kmods-%s.img", config.LocalStateDir, kernelVers)
err := os.MkdirAll(path.Dir(kernelDestination), 0755)
if err != nil {
@@ -123,10 +123,12 @@ func main() {
}
for _, node := range nodeList {
v := vnfs.New(node.Vnfs)
replace := make(map[string]string)
replace["HOSTNAME"] = node.HostName
replace["FQDN"] = node.Fqdn
replace["VNFS"] = node.Vnfs
replace["VNFSDIR"] = v.Root()
replace["KERNELVERSION"] = node.KernelVersion
replace["GROUPNAME"] = node.GroupName
replace["DOMAIN"] = node.DomainName

View File

@@ -18,7 +18,7 @@ nodegroups:
gateway: 192.168.1.1
group_2:
comment: This is the group 2
vnfs: /var/chroots/centos-7
vnfs: docker://warewulf/centos-7
system overlay: default
runtime overlay: default
domain suffix: group2

View File

@@ -64,6 +64,7 @@ type NodeInfo struct {
DomainName string
Fqdn string
Vnfs string
VnfsDir string
Ipxe string
SystemOverlay string
RuntimeOverlay string
@@ -139,7 +140,9 @@ func FindAllNodes() ([]NodeInfo, error) {
if strings.HasPrefix(n.Vnfs, "docker://") {
//TODO: This is a kludge and shouldn't be done here. We need to go back
// and do this from a "vnfs" interface or package
n.Vnfs = LocalStateDir + "/oci/vnfs/name/" + path.Base(n.Vnfs)
n.VnfsDir = LocalStateDir + "/oci/vnfs/name/" + path.Base(n.Vnfs)
} else {
n.VnfsDir = n.Vnfs
}
ret = append(ret, n)

View File

@@ -9,19 +9,22 @@ import (
// THIS IS NOT BEING USED YET AND IS THUS A WORK IN PROGRESS
const ConfigFile = "/etc/warewulf/warewulf.conf"
const SysConfDir = "/etc/warewulf/"
const LocalStateDir = "/var/warewulf"
type Config struct {
Port int `yaml:"warewulfd port", envconfig:"WAREWULFD_PORT"`
Ipaddr string `yaml:"warewulfd ipaddr", envconfig:"WAREWULFD_IPADDR"`
InsecureRuntime bool `yaml:"insecure runtime"`
Debug bool `yaml:"debug"`
Port int `yaml:"warewulfd port", envconfig:"WAREWULFD_PORT"`
Ipaddr string `yaml:"warewulfd ipaddr", envconfig:"WAREWULFD_IPADDR"`
InsecureRuntime bool `yaml:"insecure runtime"`
Debug bool `yaml:"debug"`
SysConfDir string `yaml:"system config dir"`
LocalStateDir string `yaml:"local state dir"`
}
func New() (Config, error) {
var c Config
fd, err := ioutil.ReadFile(ConfigFile)
fd, err := ioutil.ReadFile(SysConfDir + "warewulf.conf")
if err != nil {
return c, err
}
@@ -37,7 +40,14 @@ func New() (Config, error) {
}
if c.Ipaddr == "" {
fmt.Printf("ERROR: 'warewulf ipaddr' has not been set in %s\n", ConfigFile)
fmt.Printf("ERROR: 'warewulf ipaddr' has not been set in %s\n", SysConfDir+"warewulf.conf")
}
if c.SysConfDir == "" {
c.SysConfDir = SysConfDir
}
if c.LocalStateDir == "" {
c.LocalStateDir = LocalStateDir
}
return c, nil

View File

@@ -126,8 +126,8 @@ func (p *puller) pull(ctx context.Context, uri, dst string) (err error) {
// copy to cache location
_, err = copy.Image(ctx, policyCtx, cacheRef, srcRef, &copy.Options{
ReportWriter: os.Stdout,
SourceCtx: p.sysCtx,
//ReportWriter: os.Stdout,
SourceCtx: p.sysCtx,
})
if err != nil {
return err

51
internal/pkg/vnfs/vnfs.go Normal file
View File

@@ -0,0 +1,51 @@
package vnfs
import (
"github.com/hpcng/warewulf/internal/pkg/config"
"path"
"strings"
)
type VnfsObject struct {
Source string
RootPath string
ImagePath string
}
func New(s string) VnfsObject {
var ret VnfsObject
ret.Source = s
return ret
}
func (self *VnfsObject) Name() string {
if self.Source == "" {
return ""
}
if strings.HasPrefix(self.Source, "/") {
return path.Base(self.Source)
}
uri := strings.Split(self.Source, "://")
return strings.ReplaceAll(uri[0]+":"+uri[1], "/", "_")
}
func (self *VnfsObject) Image() string {
if self.Source == "" {
return ""
}
return config.LocalStateDir + "/provision/vnfs/" + self.Name() + ".img.gz"
}
func (self *VnfsObject) Root() string {
if self.Source == "" {
return ""
}
return config.LocalStateDir + "/chroots/" + self.Name()
}

View File

@@ -1,2 +1,2 @@
#WWINCLUDE @VNFS@/etc/group
#WWINCLUDE /etc/group
#WWINCLUDE @VNFSDIR@/etc/group
#WWINCLUDE /etc/group

View File

@@ -1,3 +1,3 @@
root::0:0:root:/root:/bin/bash
#WWINCLUDE @VNFS@/etc/passwd
#WWINCLUDE /etc/passwd
#WWINCLUDE @VNFSDIR@/etc/passwd
#WWINCLUDE /etc/passwd