Added configuration pkg, iPXE templating, clean up, etc.

This commit is contained in:
Gregory Kurtzer
2020-11-04 18:45:36 -08:00
parent 260315cccd
commit d2ed5766cd
13 changed files with 127 additions and 85 deletions

View File

@@ -5,10 +5,12 @@ all: warewulfd wwbuild wwclient
files: all
install -d -m 0755 /var/warewulf/
install -d -m 0755 /etc/warewulf/
install -d -m 0755 /var/lib/tftpboot/warewulf/ipxe/
install -d -m 0755 /etc/warewulf/ipxe
install -d -m 0755 /var/lib/tftpboot/warewulf/pxe/
install -m 0640 etc/dhcpd.conf /etc/dhcp/dhcpd.conf
install -m 0640 etc/nodes.conf /etc/warewulf/nodes.conf
install -m 0640 etc/warewulf.conf /etc/warewulf/warewulf.conf
install -m 0644 etc/nodes.conf /etc/warewulf/nodes.conf
install -m 0644 etc/warewulf.conf /etc/warewulf/warewulf.conf
install -m 0644 etc/ipxe/default.ipxe /etc/warewulf/ipxe/default.ipxe
cp -r tftpboot/* /var/lib/tftpboot/warewulf/ipxe/
cp -r overlays /var/warewulf/
chmod +x /var/warewulf/overlays/system/default/init

View File

@@ -1,17 +1,18 @@
# warewulf
# warewulf v4 WIP
This is built on CentOS-7. More needs to be done to make it work on other
distributions and versions specifically with the system service
compoenents.
components.
In a nutshell, to use:
In a nutshell, to install and start provisioning nodes, do the following:
1. make install
2. build VNFS `sudo singularity build --sandbox /var/chroots/centos-7 centos-7.def`
3. Edit `/etc/warewulf/nodes.yaml`
4. Run the following commands:
a. `./wwbuild vnfs`
b. `./wwbuild kernel`
c. `./wwbuild overlay`
c. `./warewulfd`
5. Boot your node and watch the console and the output of the Warewulfd process
1. `make`
2. `sudo make install`
3. `vi /etc/warewulf/warewulf.conf`
4. `vi /etc/warewulf/nodes.conf`
5. `sudo singularity build --sandbox /var/chroots/centos-7 centos-7.def`
6. `sudo ./wwbuild vnfs`
7. `sudo ./wwbuild kernel`
8. `sudo ./wwbuild overlay`
9. `./warewulfd`
10. Boot your compute node

View File

@@ -1,10 +1,14 @@
package main
import (
"bufio"
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"log"
"net/http"
"os"
"strconv"
"strings"
)
@@ -25,17 +29,35 @@ func ipxe(w http.ResponseWriter, req *http.Request) {
}
if node.HostName != "" {
log.Printf("IPXE: %15s: hwaddr=%s\n", node.Fqdn, hwaddr)
replace := make(map[string]string)
fmt.Fprintf(w, "#!ipxe\n")
conf, err := config.New()
if err != nil {
log.Printf("Could not get config: %s\n", err)
return
}
ipxeTemplate := fmt.Sprintf("/etc/warewulf/ipxe/%s.ipxe", node.Ipxe)
sourceFD, err := os.Open(ipxeTemplate)
if err != nil {
log.Printf("ERROR: Could not open iPXE Template: %s\n", err)
w.WriteHeader(404)
return
}
scanner := bufio.NewScanner(sourceFD)
for scanner.Scan() {
newLine := scanner.Text()
newLine = strings.ReplaceAll(newLine, "@HWADDR@", url[2])
newLine = strings.ReplaceAll(newLine, "@IPADDR@", conf.Ipaddr)
newLine = strings.ReplaceAll(newLine, "@HOSTNAME@", node.HostName)
newLine = strings.ReplaceAll(newLine, "@PORT@", strconv.Itoa(conf.Port))
fmt.Fprintln(w, newLine)
}
fmt.Fprintf(w, "echo Now booting Warewulf - v4 Proof of Concept\n")
fmt.Fprintf(w, "set base http://192.168.1.1:9873/\n")
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-system/%s\n", url[2])
fmt.Fprintf(w, "boot\n")
} else {
log.Printf("ERROR: iPXE request from unknown Node (hwaddr=%s)\n", url[2])
}

View File

@@ -3,6 +3,7 @@ package main
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"log"
"net/http"
"strconv"
@@ -10,7 +11,6 @@ import (
)
func runtimeOverlay(w http.ResponseWriter, req *http.Request) {
remote := strings.Split(req.RemoteAddr, ":")
port, err := strconv.Atoi(remote[1])
if err != nil {
@@ -19,12 +19,20 @@ func runtimeOverlay(w http.ResponseWriter, req *http.Request) {
return
}
if port >= 1024 {
log.Panicf("DENIED: Connection coming from non-privledged port: %s\n", req.RemoteAddr)
w.WriteHeader(401)
config, err := config.New()
if err != nil {
fmt.Printf("ERROR: Could not load configuration file: %s\n", err)
return
}
if config.InsecureRuntime == false {
if port >= 1024 {
log.Panicf("DENIED: Connection coming from non-privledged port: %s\n", req.RemoteAddr)
w.WriteHeader(401)
return
}
}
node, err := assets.FindByIpaddr(remote[0])
if err != nil {
fmt.Printf("Could not find node by IP address: %s\n", remote[0])

View File

@@ -99,6 +99,9 @@ func BuildOverlayDir(sourceDir string, destDir string, replace map[string]string
return err
}
includeFD.Close()
} else if strings.HasPrefix(newLine, "#WW") {
// Anything else is a comment or to be ignored
continue
} else {
_, err := w.WriteString(newLine + "\n")
if err != nil {

View File

@@ -7,9 +7,9 @@ import (
"net/http"
"os"
"os/exec"
// "os/exec"
"time"
"github.com/hpcng/warewulf/internal/pkg/config"
)
func main() {
@@ -24,9 +24,18 @@ func main() {
os.Chdir("/warewulf/wwclient-test")
}
// Setup local port to 987
localTCPAddr := net.TCPAddr{
Port: 987,
config, err := config.New()
if err != nil {
fmt.Printf("ERROR: Could not load configuration file: %s\n", err)
return
}
localTCPAddr := net.TCPAddr{}
if config.InsecureRuntime == false {
// Setup local port to something privileged (<1024)
localTCPAddr.Port = 987
} else {
fmt.Printf("INFO: Running from an insecure port\n")
}
webclient := &http.Client{
@@ -52,7 +61,8 @@ func main() {
for true {
var err error
resp, err = webclient.Get("http://192.168.1.1:9873/overlay-runtime")
getString := fmt.Sprintf("http://%s:%d/overlay-runtime", config.Ipaddr, config.Port)
resp, err = webclient.Get(getString)
if err == nil {
break
} else {
@@ -79,25 +89,7 @@ func main() {
continue
}
/*
// TODO: Turn all of this into a pipe instead of having to use a tmpfile which
// I tried to get working, but when running on a node, it always gave a
// trying to write on closed file descriptor... This maybe ugly, but it
// works.
tmpfile := fmt.Sprintf("/tmp/.wwclient-%s", util.RandomString(14))
tmpFD, _ := os.Create(tmpfile)
defer tmpFD.Close()
io.Copy(tmpFD, resp.Body)
tmpFD.Close()
err := exec.Command("cpio", "-i", "-F", tmpfile).Run()
if err != nil {
fmt.Printf("%s", err)
}
os.Remove(tmpfile)
*/
log.Printf("Updating runtime system\n")
command := exec.Command("/bin/cpio", "-iu")
command.Stdin = resp.Body
@@ -105,27 +97,6 @@ func main() {
if err != nil {
log.Printf("ERROR: Failed running CPIO: %s\n", err)
}
/*
command.Wait()
stdin, err := command.StdinPipe()
if err != nil {
log.Println(err)
}
defer stdin.Close()
go func() {
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()
*/
// defer webclient.CloseIdleConnections()
time.Sleep(30000 * time.Millisecond)
}

13
etc/ipxe/default.ipxe Normal file
View File

@@ -0,0 +1,13 @@
#!ipxe
echo
echo Now booting Warewulf - v4 Proof of Concept
echo
set base http://@IPADDR@:@PORT@/
kernel ${base}/kernel/@HWADDR@ crashkernel=no quiet
initrd ${base}/vnfs/@HWADDR@
initrd ${base}/kmods/@HWADDR@
initrd ${base}/overlay-system/@HWADDR@
boot

View File

@@ -1,4 +1,4 @@
Port: 9873
Ipaddr: 192.168.1.1
Secure: true
Debug: false
warewulfd ipaddr: 192.168.1.1
warewulfd port: 9873
insecure runtime: false
debug: false

View File

@@ -26,6 +26,7 @@ type nodeYaml struct {
type nodeGroup struct {
Comment string
Vnfs string
Ipxe string `yaml:"ipxe template"`
SystemOverlay string `yaml:"system overlay""`
RuntimeOverlay string `yaml:"runtime overlay""`
DomainSuffix string `yaml:"domain suffix"`
@@ -36,6 +37,7 @@ type nodeGroup struct {
type nodeEntry struct {
Hostname string
Vnfs string
Ipxe string `yaml:"ipxe template"`
SystemOverlay string `yaml:"system overlay"`
RuntimeOverlay string `yaml:"runtime overlay"`
DomainSuffix string `yaml:"domain suffix"`
@@ -58,6 +60,7 @@ type NodeInfo struct {
DomainName string
Fqdn string
Vnfs string
Ipxe string
SystemOverlay string
RuntimeOverlay string
KernelVersion string
@@ -91,6 +94,7 @@ func FindAllNodes() ([]NodeInfo, error) {
n.RuntimeOverlay = group.RuntimeOverlay
n.KernelVersion = group.KernelVersion
n.DomainName = group.DomainSuffix
n.Ipxe = group.Ipxe
n.NetDevs = node.NetDevs
@@ -109,6 +113,9 @@ func FindAllNodes() ([]NodeInfo, error) {
if node.DomainSuffix != "" {
n.DomainName = node.DomainSuffix
}
if node.Ipxe != "" {
n.Ipxe = node.Ipxe
}
if n.RuntimeOverlay == "" {
@@ -117,6 +124,9 @@ func FindAllNodes() ([]NodeInfo, error) {
if n.SystemOverlay == "" {
n.SystemOverlay = "default"
}
if n.Ipxe == "" {
n.Ipxe = "default"
}
if n.DomainName != "" {
n.Fqdn = node.Hostname + "." + n.DomainName

View File

@@ -1,22 +1,27 @@
package config
import (
"gopkg.in/yaml.v2"
"fmt"
"github.com/kelseyhightower/envconfig"
"gopkg.in/yaml.v2"
"io/ioutil"
)
// THIS IS NOT BEING USED YET AND IS THUS A WORK IN PROGRESS
const ConfigFile = "/etc/warewulf/warewulf.conf"
type Config struct {
Port int `yaml:"port", envconfig:"WAREWULFD_PORT"`
Ipaddr string `yaml:"ipaddr", envconfig:"WAREWULFD_IPADDR"`
Secure bool `yaml:"secure port"`
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"`
}
func New() (Config, error) {
var c Config
fd, err := ioutil.ReadFile("/etc/warewulf/warewulf.conf")
fd, err := ioutil.ReadFile(ConfigFile)
if err != nil {
return c, err
}
@@ -31,5 +36,9 @@ func New() (Config, error) {
return c, err
}
if c.Ipaddr == "" {
fmt.Printf("ERROR: 'warewulf ipaddr' has not been set in %s\n", ConfigFile)
}
return c, nil
}

View File

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

View File

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

View File

@@ -0,0 +1 @@
#WWINCLUDE /etc/warewulf/warewulf.conf