Merge branch 'main' of github.com:ctrl-cmd/warewulf into main

This commit is contained in:
Shannon V. Davidson
2020-11-23 08:28:16 -06:00
60 changed files with 1992 additions and 1141 deletions

View File

@@ -1,34 +1,15 @@
nodegroups:
group_1:
comment: This is the group 1
vnfs: /var/chroots/centos-7
system overlay: default
default:
comment: This is the default group
vnfs: docker://warewulf/centos-8
runtime overlay: default
domain suffix: group1
nodes:
n0000:
hostname: localtest
kernel version: 3.10.0-1127.el7.x86_64
kernel args: crashkernel=no quiet
system overlay: test
netdevs:
eth0:
hwaddr: xx:xx:xx:xx:aa
ipaddr: 192.168.1.1
netmask: 255.255.255.0
gateway: 192.168.1.1
group_2:
comment: This is the group 2
vnfs: docker://warewulf/centos-7
system overlay: default
runtime overlay: default
domain suffix: group2
kernel version: 3.10.0-1127.el7.x86_64
domain suffix: default
kernel version: ""
kernel args: crashkernel=no quiet
nodes:
n0000:
hostname: n0000
ipmi ipaddr: x.x.x.x
kernel args: crashkernel=no
netdevs:
eth0:
hwaddr: 00:0c:29:23:8b:48
@@ -37,21 +18,36 @@ nodegroups:
gateway: 192.168.1.1
type: ethernet
ib0:
hwaddr: xx:xx:xx:xx:xx
ipaddr: x.x.x.x
netmask: x.x.x.x
gateway: x.x.x.x
hwaddr: aa:bb:cc:dd:ee:a0
ipaddr: 192.168.10.100
netmask: 255.255.255.0
type: infiniband
n0001:
hostname: n0001
ipmi ipaddr: x.x.x.x
netdevs:
eth0:
hwaddr: xx:xx:xx:xx:xx
hwaddr: aa:bb:cc:dd:ee:b0
ipaddr: 192.168.1.101
netmask: 255.255.255.0
gateway: 192.168.1.1
ib0:
hwaddr: xx:xx:xx:xx:xx
ipaddr: x.x.x.x
netmask: x.x.x.x
hwaddr: aa:bb:cc:dd:ee:b1
ipaddr: 192.168.10.100
netmask: 255.255.255.0
group_1:
comment: This is the group 1
vnfs: /var/chroots/centos-7
runtime overlay: default
domain suffix: group1
nodes:
n0000:
hostname: localtest
kernel version: 3.10.0-1127.el7.x86_64
system overlay: test
netdevs:
eth0:
hwaddr: aa:bb:cc:dd:ee:c0
ipaddr: 192.168.2.100
netmask: 255.255.255.0
gateway: 192.168.2.1

1
go.mod
View File

@@ -5,6 +5,7 @@ go 1.15
require (
github.com/containers/image/v5 v5.7.0
github.com/kelseyhightower/envconfig v1.4.0
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
github.com/spf13/cobra v1.1.1

13
go.sum
View File

@@ -46,6 +46,10 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/checkpoint-restore/go-criu/v4 v4.0.2/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.0.0-20200507155900-a9f01edf17e3/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
@@ -191,6 +195,8 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
@@ -214,13 +220,19 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
@@ -468,6 +480,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@@ -2,8 +2,8 @@ package response
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"log"
"net/http"
@@ -26,13 +26,20 @@ type iPxeTemplate struct {
func IpxeSend(w http.ResponseWriter, req *http.Request) {
url := strings.Split(req.URL.Path, "/")
nodes, 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)
return
}
hwaddr := strings.ReplaceAll(url[2], "-", ":")
node, err := assets.FindByHwaddr(hwaddr)
node, err := nodes.FindByHwaddr(hwaddr)
if err != nil {
log.Printf("Could not find HW Addr: %s: %s\n", hwaddr, err)
w.WriteHeader(404)

View File

@@ -2,8 +2,8 @@ package response
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"log"
"net/http"
"strconv"
@@ -12,6 +12,12 @@ import (
func RuntimeOverlaySend(w http.ResponseWriter, req *http.Request) {
config := config.New()
nodes, err := node.New()
if err != nil {
log.Printf("Could not read node configuration file: %s\n", err)
w.WriteHeader(503)
return
}
remote := strings.Split(req.RemoteAddr, ":")
port, err := strconv.Atoi(remote[1])
@@ -34,7 +40,7 @@ func RuntimeOverlaySend(w http.ResponseWriter, req *http.Request) {
}
}
node, err := assets.FindByIpaddr(remote[0])
node, err := nodes.FindByIpaddr(remote[0])
if err != nil {
fmt.Printf("Could not find node by IP address: %s\n", remote[0])
w.WriteHeader(404)

View File

@@ -1,7 +1,8 @@
package response
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/errors"
"io"
"log"
@@ -11,23 +12,29 @@ import (
"strings"
)
func getSanity(req *http.Request) (assets.NodeInfo, error) {
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], "-", ":")
node, err := assets.FindByHwaddr(hwaddr)
ret, err = nodes.FindByHwaddr(hwaddr)
if err != nil {
return node, errors.New("Could not find node by HW address")
return ret, errors.New("Could not find node by HW address")
}
if node.Fqdn == "" {
if ret.Fqdn == "" {
log.Printf("UNKNOWN: %15s: %s\n", hwaddr, req.URL.Path)
return node, errors.New("Unknown node HW address: " + hwaddr)
return ret, errors.New("Unknown node HW address: " + hwaddr)
} else {
log.Printf("REQ: %15s: %s\n", node.Fqdn, req.URL.Path)
log.Printf("REQ: %15s: %s\n", ret.Fqdn, req.URL.Path)
}
return node, nil
return ret, nil
}
func sendFile(w http.ResponseWriter, filename string, sendto string) error {

View File

@@ -1,79 +0,0 @@
package build
import (
"github.com/hpcng/warewulf/internal/app/wwctl/build/kernel"
runtime_overlay "github.com/hpcng/warewulf/internal/app/wwctl/build/runtime-overlay"
system_overlay "github.com/hpcng/warewulf/internal/app/wwctl/build/system-overlay"
"github.com/hpcng/warewulf/internal/app/wwctl/build/vnfs"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var nodeList []assets.NodeInfo
if buildAll == true {
wwlog.Printf(wwlog.VERBOSE, "Building all components\n")
buildVnfs = true
buildKernel = true
buildSystemOverlay = true;
buildRuntimeOverlay = true;
}
if len(args) >= 1 {
nodeList, _ = assets.SearchByName(args[0])
} else {
nodeList, _ = assets.FindAllNodes()
}
if len(nodeList) == 0 {
wwlog.Printf(wwlog.ERROR, "No nodes found matching: '%s'\n", args[0])
os.Exit(255)
} else {
wwlog.Printf(wwlog.VERBOSE, "Found matching nodes for build: %d\n", len(nodeList))
}
if buildVnfs == true {
// wwlog.Printf(wwlog.INFO, "===============================================================================\n")
err := vnfs.Build(nodeList, buildForce)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(255)
}
}
if buildKernel == true {
// wwlog.Printf(wwlog.INFO, "===============================================================================\n")
err := kernel.Build(nodeList, buildForce)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(255)
}
}
if buildSystemOverlay == true {
// wwlog.Printf(wwlog.INFO, "===============================================================================\n")
err := system_overlay.Build(nodeList, buildForce)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(255)
}
}
if buildRuntimeOverlay == true {
// wwlog.Printf(wwlog.INFO, "===============================================================================\n")
err := runtime_overlay.Build(nodeList, buildForce)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(255)
}
}
return nil
}

View File

@@ -1,73 +0,0 @@
package kernel
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"os"
"os/exec"
"path"
)
func Build(nodeList []assets.NodeInfo, force bool) error {
config := config.New()
set := make(map[string]int)
wwlog.Printf(wwlog.INFO, "Importing Kernels:\n")
wwlog.SetIndent(4)
for _, node := range nodeList {
if node.KernelVersion != "" {
set[node.KernelVersion] ++
wwlog.Printf(wwlog.DEBUG, "Node '%s' has KernelVersion '%s'\n", node.Fqdn, node.KernelVersion)
}
}
for kernelVersion := range set {
kernelImage := "/boot/vmlinuz-"+kernelVersion
kernelDrivers := "/lib/modules/"+kernelVersion
kernelDestination := config.KernelImage(kernelVersion)
driversDestination := config.KmodsImage(kernelVersion)
// Create the destination paths just in case it doesn't exist
os.MkdirAll(path.Dir(kernelDestination), 0755)
os.MkdirAll(path.Dir(driversDestination), 0755)
if _, err := os.Stat(kernelImage); err == nil {
if util.PathIsNewer(kernelImage, kernelDestination) && force == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, kernel is current\n", "vmlinuz-"+kernelVersion)
} else {
err := util.CopyFile(kernelImage, kernelDestination)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed copying kernel image: %s\n", err)
continue
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", "vmlinuz-"+kernelVersion)
}
}
if _, err := os.Stat(kernelDrivers); err == nil {
if util.PathIsNewer(kernelDrivers, driversDestination) && force == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, drivers are current\n", "kmods-"+kernelVersion+".img")
} else {
cmd := fmt.Sprintf("cd /; find .%s | cpio --quiet -o -H newc -F \"%s\"", kernelDrivers, driversDestination)
err := exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not generate kernel driver overlay: %s\n", err)
continue
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", "kmods-"+kernelVersion+".img")
}
}
}
wwlog.SetIndent(0)
return nil
}

View File

@@ -0,0 +1,90 @@
package build
import (
"github.com/hpcng/warewulf/internal/pkg/kernel"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var nodes []node.NodeInfo
showHelp := true
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if len(args) > 0 {
var err error
nodes, err = n.SearchByName(args[0])
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find nodes for search term: %s\n", args[0])
os.Exit(1)
}
} else {
var err error
nodes, err = n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not get list of nodes: %s\n", err)
os.Exit(1)
}
}
if buildVnfs == true || buildAll == true {
set := make(map[string]int)
showHelp = false
wwlog.Printf(wwlog.INFO, "Building VNFS images...\n")
for _, node := range nodes {
set[node.Vnfs] ++
}
for e := range set {
vnfs.Build(e, buildForce)
}
}
if buildKernel == true || buildAll == true {
set := make(map[string]int)
showHelp = false
wwlog.Printf(wwlog.INFO, "Building Kernel images...\n")
for _, node := range nodes {
set[node.KernelVersion] ++
}
for e := range set {
kernel.Build(e)
}
}
if buildSystemOverlay == true || buildAll == true {
wwlog.Printf(wwlog.INFO, "Building System Overlays...\n")
showHelp = false
overlay.SystemBuild(nodes, buildForce)
}
if buildRuntimeOverlay == true || buildAll == true {
wwlog.Printf(wwlog.INFO, "Building Runtime Overlays...n")
showHelp = false
overlay.RuntimeBuild(nodes, buildForce)
}
if showHelp == true {
cmd.Usage()
os.Exit(1)
}
return nil
}

View File

@@ -13,6 +13,7 @@ var (
"that seems to be needed.",
RunE: CobraRunE,
}
buildVnfs bool
buildKernel bool
buildRuntimeOverlay bool

View File

@@ -1,144 +0,0 @@
package runtime_overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
)
func fileInclude(path string) string {
wwlog.Printf(wwlog.DEBUG, "Including file into template: %s\n", path)
content, err := ioutil.ReadFile(path)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Template include: %s\n", err)
}
return strings.TrimSuffix(string(content), "\n")
}
func Build(nodeList []assets.NodeInfo, force bool) error {
wwlog.Printf(wwlog.INFO, "Building Runtime Overlays:\n")
config := config.New()
wwlog.SetIndent(4)
for _, node := range nodeList {
if node.RuntimeOverlay != "" {
OverlayDir := config.RuntimeOverlaySource(node.RuntimeOverlay)
OverlayFile := config.RuntimeOverlayImage(node.Fqdn)
wwlog.Printf(wwlog.VERBOSE, "Building Runtime Overlay for: %s\n", node.Fqdn)
tmpDir, err := ioutil.TempDir(os.TempDir(), ".wwctl-runtime-overlay-")
if err != nil {
return err
}
if _, err := os.Stat(OverlayDir); err != nil {
return err
}
err = os.MkdirAll(path.Dir(OverlayFile), 0755)
if err != nil {
return err
}
if force == false {
wwlog.Printf(wwlog.DEBUG, "Checking if overlay is required\n")
}
if util.PathIsNewer(OverlayDir, OverlayFile) {
if force == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, overlay is current\n", node.Fqdn)
continue
}
}
wwlog.Printf(wwlog.DEBUG, "Changing directory to OverlayDir: %s\n", OverlayDir)
err = os.Chdir(OverlayDir)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not chdir() to OverlayDir: %s\n", OverlayDir)
continue
}
wwlog.Printf(wwlog.DEBUG, "Walking the file system: %s\n", OverlayDir)
err = filepath.Walk(".", func(location string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
wwlog.Printf(wwlog.DEBUG, "Found directory: %s\n", location)
err := os.MkdirAll(path.Join(tmpDir, location), info.Mode())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
} else if filepath.Ext(location) == ".ww" {
wwlog.Printf(wwlog.DEBUG, "Found template file: %s\n", location)
destFile := strings.TrimSuffix(location, ".ww")
tmpl, err := template.New(path.Base(location)).Funcs(template.FuncMap{"Include": fileInclude}).ParseGlob(path.Join(OverlayDir, destFile + ".ww*"))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
w, err := os.OpenFile(path.Join(tmpDir, destFile), os.O_RDWR|os.O_CREATE, info.Mode())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
defer w.Close()
err = tmpl.Execute(w, node)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
} else if b, _ := regexp.MatchString(`\.ww[a-zA-Z0-9\-\._]*$`, location); b == true {
wwlog.Printf(wwlog.DEBUG, "Ignoring WW template file: %s\n", location)
} else {
wwlog.Printf(wwlog.DEBUG, "Found file: %s\n", location)
err := util.CopyFile(path.Join(OverlayDir, location), path.Join(tmpDir, location))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
}
return nil
})
wwlog.Printf(wwlog.VERBOSE, "Finished generating overlay directory for: %s\n", node.Fqdn)
cmd := fmt.Sprintf("cd \"%s\"; find . | cpio --quiet -o -H newc -F \"%s\"", tmpDir, OverlayFile)
wwlog.Printf(wwlog.DEBUG, "RUNNING: %s\n", cmd)
err = exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not generate runtime image overlay: %s\n", err)
continue
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", node.Fqdn)
wwlog.Printf(wwlog.DEBUG, "Removing temporary directory: %s\n", tmpDir)
os.RemoveAll(tmpDir)
}
}
wwlog.SetIndent(0)
return nil
}

View File

@@ -1,144 +0,0 @@
package system_overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
)
func fileInclude(path string) string {
wwlog.Printf(wwlog.DEBUG, "Including file into template: %s\n", path)
content, err := ioutil.ReadFile(path)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Template include: %s\n", err)
}
return strings.TrimSuffix(string(content), "\n")
}
func Build(nodeList []assets.NodeInfo, force bool) error {
wwlog.Printf(wwlog.INFO, "Building System Overlays:\n")
config := config.New()
wwlog.SetIndent(4)
for _, node := range nodeList {
if node.SystemOverlay != "" {
OverlayDir := config.SystemOverlaySource(node.SystemOverlay)
OverlayFile := config.SystemOverlayImage(node.Fqdn)
wwlog.Printf(wwlog.VERBOSE, "Building System Overlay for: %s\n", node.Fqdn)
tmpDir, err := ioutil.TempDir(os.TempDir(), ".wwctl-system-overlay-")
if err != nil {
return err
}
if _, err := os.Stat(OverlayDir); err != nil {
return err
}
err = os.MkdirAll(path.Dir(OverlayFile), 0755)
if err != nil {
return err
}
if force == false {
wwlog.Printf(wwlog.DEBUG, "Checking if overlay is required\n")
}
if util.PathIsNewer(OverlayDir, OverlayFile) {
if force == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, overlay is current\n", node.Fqdn)
continue
}
}
wwlog.Printf(wwlog.DEBUG, "Changing directory to OverlayDir: %s\n", OverlayDir)
err = os.Chdir(OverlayDir)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not chdir() to OverlayDir: %s\n", OverlayDir)
continue
}
wwlog.Printf(wwlog.DEBUG, "Walking the file system: %s\n", OverlayDir)
err = filepath.Walk(".", func(location string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
wwlog.Printf(wwlog.DEBUG, "Found directory: %s\n", location)
err := os.MkdirAll(path.Join(tmpDir, location), info.Mode())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
} else if filepath.Ext(location) == ".ww" {
wwlog.Printf(wwlog.DEBUG, "Found template file: %s\n", location)
destFile := strings.TrimSuffix(location, ".ww")
tmpl, err := template.New(path.Base(location)).Funcs(template.FuncMap{"Include": fileInclude}).ParseGlob(path.Join(OverlayDir, destFile + ".ww*"))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
w, err := os.OpenFile(path.Join(tmpDir, destFile), os.O_RDWR|os.O_CREATE, info.Mode())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
defer w.Close()
err = tmpl.Execute(w, node)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
} else if b, _ := regexp.MatchString(`\.ww[a-zA-Z0-9\-\._]*$`, location); b == true {
wwlog.Printf(wwlog.DEBUG, "Ignoring WW template file: %s\n", location)
} else {
wwlog.Printf(wwlog.DEBUG, "Found file: %s\n", location)
err := util.CopyFile(path.Join(OverlayDir, location), path.Join(tmpDir, location))
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
return err
}
}
return nil
})
wwlog.Printf(wwlog.VERBOSE, "Finished generating overlay directory for: %s\n", node.Fqdn)
cmd := fmt.Sprintf("cd \"%s\"; find . | cpio --quiet -o -H newc -F \"%s\"", tmpDir, OverlayFile)
wwlog.Printf(wwlog.DEBUG, "RUNNING: %s\n", cmd)
err = exec.Command("/bin/sh", "-c", cmd).Run()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not generate system image overlay: %s\n", err)
continue
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", node.Fqdn)
wwlog.Printf(wwlog.DEBUG, "Removing temporary directory: %s\n", tmpDir)
os.RemoveAll(tmpDir)
}
}
wwlog.SetIndent(0)
return nil
}

View File

@@ -1,65 +0,0 @@
package vnfs
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"os"
"path"
)
func BuildContainerdir(v vnfs.VnfsObject) {
config := config.New()
if _, err := os.Stat(v.Source()); err != nil {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping (bad path)\n", v.Name())
return
}
wwlog.Printf(wwlog.DEBUG, "Checking if there have been any updates to the VNFS directory\n")
if util.PathIsNewer(v.Source(), config.VnfsImage(v.NameClean())) {
if buildForce == false {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, VNFS is current\n", v.Name())
return
}
}
wwlog.Printf(wwlog.DEBUG, "Making the directory: %s\n", path.Dir(config.VnfsImage(v.NameClean())))
err := os.MkdirAll(path.Dir(config.VnfsImage(v.NameClean())), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
wwlog.Printf(wwlog.DEBUG, "Making the directory: %s\n", path.Dir(config.VnfsChroot(v.NameClean())))
err = os.MkdirAll(path.Dir(config.VnfsChroot(v.NameClean())), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
wwlog.Printf(wwlog.DEBUG, "Building VNFS image: '%s' -> '%s'\n", v.Source(), config.VnfsImage(v.NameClean()))
err = buildVnfs(v.Source(), config.VnfsImage(v.NameClean()))
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
// Setup links from OCI rootfs to chroot path
_ = os.Remove(config.VnfsChroot(v.NameClean()) + "-link")
err = os.Symlink(v.Source(), config.VnfsChroot(v.NameClean())+"-link")
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Chroot: %s\n", err)
os.Exit(1)
}
err = os.Rename(config.VnfsChroot(v.NameClean())+"-link", config.VnfsChroot(v.NameClean()))
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
os.Exit(1)
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", v.Name())
}

View File

@@ -1,102 +0,0 @@
package vnfs
import (
"context"
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/oci"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"os"
"path"
)
func BuildDocker(v vnfs.VnfsObject) {
wwlog.Printf(wwlog.VERBOSE, "Building OCI Container: %s\n", v.Source())
config := config.New()
OciCacheDir := config.LocalStateDir + "/oci"
VnfsHashDir := config.LocalStateDir + "/oci/vnfs"
c, err := oci.NewCache(oci.OptSetCachePath(OciCacheDir))
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Downloading OCI container layers\n")
sourcePath, err := c.Pull(context.Background(), v.Source(), nil)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
hashDestination := VnfsHashDir + path.Base(sourcePath)
name, err := os.Readlink(config.VnfsImage(v.NameClean()))
if err == nil {
if name == hashDestination {
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, VNFS is current\n", v.Name())
return
}
}
err = os.MkdirAll(VnfsHashDir, 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
err = os.MkdirAll(path.Dir(config.VnfsImage(v.NameClean())), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
err = os.MkdirAll(path.Dir(config.VnfsChroot(v.NameClean())), 0755)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
return
}
wwlog.Printf(wwlog.VERBOSE, "Building bootable VNFS image\n")
err = buildVnfs(sourcePath, hashDestination)
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Finalizing Build\n")
// Setup links from OCI image to provision path
_ = os.Remove(config.VnfsImage(v.NameClean()) + "-link")
err = os.Symlink(hashDestination, config.VnfsImage(v.NameClean())+"-link")
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Image: %s\n", err)
os.Exit(1)
}
err = os.Rename(config.VnfsImage(v.NameClean())+"-link", config.VnfsImage(v.NameClean()))
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
os.Exit(1)
}
// Setup links from OCI rootfs to chroot path
_ = os.Remove(config.VnfsChroot(v.NameClean()) + "-link")
err = os.Symlink(sourcePath, config.VnfsChroot(v.NameClean())+"-link")
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Chroot: %s\n", err)
os.Exit(1)
}
err = os.Rename(config.VnfsChroot(v.NameClean())+"-link", config.VnfsChroot(v.NameClean()))
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
os.Exit(1)
}
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", v.Name())
return
}

View File

@@ -1,14 +0,0 @@
package vnfs
import (
"fmt"
"os/exec"
)
func buildVnfs(source string, dest string) error {
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc | gzip -c > \"%s\"", source, dest)
err := exec.Command("/bin/sh", "-c", cmd).Run()
return err
}

View File

@@ -1,47 +0,0 @@
package vnfs
import (
"strings"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
var buildForce bool
func Build(nodeList []assets.NodeInfo, force bool) error {
set := make(map[string]int)
wwlog.Printf(wwlog.INFO, "Building and Importing VNFS Images:\n")
wwlog.SetIndent(4)
buildForce = force
for _, node := range nodeList {
if node.Vnfs != "" {
set[node.Vnfs]++
wwlog.Printf(wwlog.DEBUG, "Node '%s' has VNFS '%s'\n", node.Fqdn, node.Vnfs)
}
}
for uri := range set {
v := vnfs.New(uri)
wwlog.Printf(wwlog.VERBOSE, "VNFS found: %s (nodes: %d)\n", uri, set[uri])
if strings.HasPrefix(uri, "/") {
if strings.HasSuffix(uri, "tar.gz") {
//wwlog.Printf(wwlog.WARN, "Building VNFS from local tarball: %s\n", uri)
wwlog.Printf(wwlog.WARN, "Building VNFS from local tarball is not supported yet: %s\n", uri)
} else {
BuildContainerdir(v)
}
} else {
BuildDocker(v)
}
}
wwlog.SetIndent(0)
return nil
}

View File

@@ -0,0 +1,29 @@
package add
import (
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed opening node database: %s\n", err)
os.Exit(1)
}
for _, g := range args {
err = nodeDB.AddGroup(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
nodeDB.Persist()
return nil
}

View File

@@ -0,0 +1,25 @@
package add
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "add",
Short: "Add a new node group",
Long: "Add a new node group ",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetVnfs string
SetKernel string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,61 @@
package delete
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var count int
var numNodes int
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed to open node database: %s\n", err)
os.Exit(1)
}
nodes, err := nodeDB. FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not load all nodes: %s\n", err)
os.Exit(1)
}
for _, g := range args {
err := nodeDB.DelGroup(g)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
} else {
for _, n := range nodes {
if n.GroupName == g {
numNodes ++
}
}
count ++
}
}
if count > 0 {
q := fmt.Sprintf("Are you sure you want to delete %d group(s) (%d nodes)", count, numNodes)
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
wwlog.Printf(wwlog.INFO, "No groups found\n")
}
return nil
}

View File

@@ -0,0 +1,25 @@
package delete
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "delete",
Short: "Add a new node group",
Long: "Add a new node group ",
RunE: CobraRunE,
}
SetVnfs string
SetKernel string
// SetGroupLevel bool
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,44 @@
package list
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"reflect"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
groups, err := nodeDB.FindAllGroups()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find all nodes: %s\n", err)
os.Exit(1)
}
if ShowAll == true {
for _, group := range groups {
v := reflect.ValueOf(group)
typeOfS := v.Type()
fmt.Printf("################################################################################\n")
for i := 0; i< v.NumField(); i++ {
fmt.Printf("%-25s %s = %v\n", group.Id, typeOfS.Field(i).Name, v.Field(i).Interface())
}
}
} else {
fmt.Printf("%-22s %-16s %-30s %-30s %-16s\n", "GROUP NAME", "DOMAINNAME", "KERNEL VERSION", "VNFS IMAGE", "RUNTIME OVERLAY")
for _, g := range groups {
fmt.Printf("%-22s %-16s %-30s %-30s %-16s\n", g.GroupName, g.DomainName, g.KernelVersion, g.Vnfs, g.RuntimeOverlay)
}
}
return nil
}

View File

@@ -0,0 +1,23 @@
package list
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "list",
Short: "List group configurations",
Long: "List group configurations ",
RunE: CobraRunE,
}
ShowAll bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&ShowAll, "all", "a", false, "Show all node configurations")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,29 @@
package group
import (
"github.com/hpcng/warewulf/internal/app/wwctl/group/add"
"github.com/hpcng/warewulf/internal/app/wwctl/group/delete"
"github.com/hpcng/warewulf/internal/app/wwctl/group/list"
"github.com/hpcng/warewulf/internal/app/wwctl/group/set"
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
Use: "group",
Short: "Group management",
Long: "Management of group settings and power management",
}
)
func init() {
baseCmd.AddCommand(list.GetCommand())
baseCmd.AddCommand(set.GetCommand())
baseCmd.AddCommand(add.GetCommand())
baseCmd.AddCommand(delete.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,247 @@
package set
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var err error
var groups []node.GroupInfo
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
if len(args) > 0 {
var tmp []node.GroupInfo
tmp, err = nodeDB.FindAllGroups()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, a := range args {
for _, g := range tmp {
if g.Id == a {
groups = append(groups, g)
}
}
}
} else {
cmd.Usage()
os.Exit(1)
}
for _, g := range groups {
if SetVnfs != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting vnfs to: %s\n", g.Id, SetVnfs)
err := nodeDB.SetGroupVal(g.Id, "vnfs", SetVnfs)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "vnfs", "")
}
}
}
if SetKernel != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting kernel to: %s\n", g.Id, SetVnfs)
err := nodeDB.SetGroupVal(g.Id, "kernel", SetKernel)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "kernel", "")
}
}
}
if SetDomainName != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting domain name to: %s\n", g.Id, SetDomainName)
err := nodeDB.SetGroupVal(g.Id, "domain", SetDomainName)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "domain", "")
}
}
}
if SetIpxe != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting iPXE template to: %s\n", g.Id, SetIpxe)
err := nodeDB.SetGroupVal(g.Id, "ipxe", SetIpxe)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "ipxe", "")
}
}
}
if SetRuntimeOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting runtime overlay to: %s\n", g.Id, SetRuntimeOverlay)
err := nodeDB.SetGroupVal(g.Id, "runtimeoverlay", SetRuntimeOverlay)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "runtimeoverlay", "")
}
}
}
if SetSystemOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting system overlay to: %s\n", g.Id, SetSystemOverlay)
err := nodeDB.SetGroupVal(g.Id, "systemoverlay", SetSystemOverlay)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "systemoverlay", "")
}
}
}
if SetIpmiIpaddr != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting IPMI IP address to: %s\n", g.Id, SetIpmiIpaddr)
err := nodeDB.SetGroupVal(g.Id, "ipmiipaddr", SetIpmiIpaddr)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "ipmiipaddr", "")
}
}
}
if SetIpmiUsername != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting IPMI IP username to: %s\n", g.Id, SetIpmiUsername)
err := nodeDB.SetGroupVal(g.Id, "ipmiusername", SetIpmiUsername)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "ipmiusername", "")
}
}
}
if SetIpmiPassword != "" {
wwlog.Printf(wwlog.VERBOSE, "Group: %s, Setting IPMI IP password to: %s\n", g.Id, SetIpmiPassword)
err := nodeDB.SetGroupVal(g.Id, "ipmipassword", SetIpmiPassword)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
if SetClearNodes == true {
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, n := range nodes {
_ = nodeDB.SetNodeVal(g.Id, n.Id, "ipmipassword", "")
}
}
}
}
if len(groups) > 0 {
q := fmt.Sprintf("Are you sure you want to modify %d group(s)", len(groups))
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
fmt.Printf("No groups found\n")
}
return nil
}

View File

@@ -0,0 +1,43 @@
package set
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "set",
Short: "Set group configurations",
Long: "Set group configurations ",
RunE: CobraRunE,
}
SetVnfs string
SetKernel string
SetDomainName string
SetIpxe string
SetRuntimeOverlay string
SetSystemOverlay string
SetHostname string
SetClearNodes bool
SetIpmiIpaddr string
SetIpmiUsername string
SetIpmiPassword string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
baseCmd.PersistentFlags().StringVarP(&SetDomainName, "domain", "D", "", "Set the node's domain name")
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system overlay")
baseCmd.PersistentFlags().StringVar(&SetIpmiIpaddr, "ipmi", "", "Set the node's IPMI address")
baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username")
baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password")
baseCmd.PersistentFlags().BoolVarP(&SetClearNodes, "clear", "c", false, "Clear node configurations when setting parent group")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -1,20 +1,26 @@
package build
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/kernel"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var nodes []assets.NodeInfo
var nodes []node.NodeInfo
set := make(map[string]int)
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if len(args) == 1 && ByNode == true {
var err error
nodes, err = assets.SearchByName(args[0])
nodes, err = n.SearchByName(args[0])
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find nodes for search term: %s\n", args[0])
os.Exit(1)
@@ -26,7 +32,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
} else if BuildAll == true {
var err error
nodes, err = assets.FindAllNodes()
nodes, err = n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not get list of nodes: %s\n", err)
os.Exit(1)

View File

@@ -0,0 +1,28 @@
package add
import (
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed to open node database: %s\n", err)
os.Exit(1)
}
for _, a := range args {
err = nodeDB.AddNode(SetGroup, a)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
nodeDB.Persist()
return nil
}

View File

@@ -0,0 +1,23 @@
package add
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "add",
Short: "Add new node",
Long: "Add new node ",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(1),
}
SetGroup string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetGroup, "group", "g", "default", "Set group to add nodes to")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,55 @@
package delete
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var count int
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Failed to open node database: %s\n", err)
os.Exit(1)
}
nodeList, err := nodeDB.SearchByNameList(args)
for _, n := range nodeList {
if SetGroup != "" && SetGroup != n.GroupName {
wwlog.Printf(wwlog.DEBUG, "skipping node of different group: %s/%s\n", n.GroupName, n.Id)
continue
}
err := nodeDB.DelNode(n.GroupName, n.Id)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
} else {
count++
}
}
if count > 0 {
q := fmt.Sprintf("Are you sure you want to delete %d nodes(s)", count)
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
fmt.Printf("No nodes found\n")
}
return nil
}

View File

@@ -0,0 +1,25 @@
package delete
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "delete",
Short: "Set node configurations",
Long: "Set node configurations ",
RunE: CobraRunE,
}
SetForce string
SetGroup string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetForce, "force", "f", "", "Force node delete")
baseCmd.PersistentFlags().StringVarP(&SetGroup, "group", "g", "default", "Set group to delete nodes from")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -0,0 +1,71 @@
package list
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"os"
"reflect"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var err error
var nodes []node.NodeInfo
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if len(args) > 0 {
nodes, err = n.SearchByNameList(args)
} else {
nodes, err = n.FindAllNodes()
}
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
if ShowAll == true {
for _, node := range nodes {
v := reflect.ValueOf(node)
typeOfS := v.Type()
fmt.Printf("################################################################################\n")
for i := 0; i< v.NumField(); i++ {
fmt.Printf("%-25s %s = %v\n", node.Fqdn, typeOfS.Field(i).Name, v.Field(i).Interface())
}
}
} else if ShowNet == true {
fmt.Printf("%-22s %-10s %-20s %-16s %-16s %-16s %s\n", "NODE NAME", "DEVICE", "HWADDR", "IPADDR", "NETMASK", "GATEWAY", "TYPE")
for _, node := range nodes {
for name, dev := range node.NetDevs {
fmt.Printf("%-22s %-10s %-20s %-16s %-16s %-16s %s\n", node.Fqdn, name, dev.Hwaddr, dev.Ipaddr, dev.Netmask, dev.Gateway, dev.Type)
}
}
} else if ShowIpmi == true {
fmt.Printf("%-22s %-16s %-20s %-20s\n", "NODE NAME", "IPMI IPADDR", "IPMI USERNAME", "IPMI PASSWORD")
for _, node := range nodes {
fmt.Printf("%-22s %-16s %-20s %-20s\n", node.Fqdn, node.IpmiIpaddr, node.IpmiUserName, node.IpmiPassword)
}
} else {
fmt.Printf("%-22s %-16s %-30s %-30s %-16s\n", "NODE NAME", "GROUP NAME", "KERNEL VERSION", "VNFS IMAGE", "RUNTIME OVERLAY")
for _, node := range nodes {
fmt.Printf("%-22s %-16s %-30s %-30s %-16s\n", node.Fqdn, node.GroupName, node.KernelVersion, node.Vnfs, node.RuntimeOverlay)
}
}
return nil
}

View File

@@ -0,0 +1,26 @@
package list
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "list",
Short: "List all nodes",
Long: "List all nodes",
RunE: CobraRunE,
}
ShowNet bool
ShowIpmi bool
ShowAll bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&ShowNet, "net", "n", false, "Show node network configurations")
baseCmd.PersistentFlags().BoolVarP(&ShowIpmi, "ipmi", "i", false, "Show node IPMI configurations")
baseCmd.PersistentFlags().BoolVarP(&ShowAll, "all", "a", false, "Show all node configurations")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -1,7 +1,7 @@
package poweroff
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/power"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
@@ -9,14 +9,17 @@ import (
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var returnErr error = nil
var nodeList []node.NodeInfo
var nodeList []assets.NodeInfo
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if len(args) >= 1 {
//nodeList, _ = assets.SearchByName(args[0])
nodeList, _ = assets.SearchByNameList(args)
nodeList, _ = n.SearchByNameList(args)
} else {
wwlog.Printf(wwlog.ERROR, "No requested nodes\n")
os.Exit(255)

View File

@@ -1,7 +1,7 @@
package poweron
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/power"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
@@ -9,14 +9,17 @@ import (
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var returnErr error = nil
var nodeList []node.NodeInfo
var nodeList []assets.NodeInfo
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if len(args) >= 1 {
//nodeList, _ = assets.SearchByName(args[0])
nodeList, _ = assets.SearchByNameList(args)
nodeList, _ = n.SearchByNameList(args)
} else {
wwlog.Printf(wwlog.ERROR, "No requested nodes\n")
os.Exit(255)

View File

@@ -1,7 +1,7 @@
package powerstatus
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/power"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
@@ -9,14 +9,17 @@ import (
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var returnErr error = nil
var nodeList []node.NodeInfo
var nodeList []assets.NodeInfo
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if len(args) >= 1 {
//nodeList, _ = assets.SearchByName(args[0])
nodeList, _ = assets.SearchByNameList(args)
nodeList, _ = n.SearchByNameList(args)
} else {
wwlog.Printf(wwlog.ERROR, "No requested nodes\n")
os.Exit(255)

View File

@@ -1,9 +1,13 @@
package node
import (
"github.com/hpcng/warewulf/internal/app/wwctl/node/add"
"github.com/hpcng/warewulf/internal/app/wwctl/node/delete"
"github.com/hpcng/warewulf/internal/app/wwctl/node/list"
"github.com/hpcng/warewulf/internal/app/wwctl/node/poweron"
"github.com/hpcng/warewulf/internal/app/wwctl/node/poweroff"
"github.com/hpcng/warewulf/internal/app/wwctl/node/powerstatus"
"github.com/hpcng/warewulf/internal/app/wwctl/node/set"
"github.com/spf13/cobra"
)
@@ -19,6 +23,10 @@ func init() {
baseCmd.AddCommand(poweron.GetCommand())
baseCmd.AddCommand(poweroff.GetCommand())
baseCmd.AddCommand(powerstatus.GetCommand())
baseCmd.AddCommand(list.GetCommand())
baseCmd.AddCommand(set.GetCommand())
baseCmd.AddCommand(add.GetCommand())
baseCmd.AddCommand(delete.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -0,0 +1,206 @@
package set
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var err error
var nodes []node.NodeInfo
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
if len(args) > 0 {
nodes, err = nodeDB.SearchByNameList(args)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
} else {
cmd.Usage()
os.Exit(1)
}
for _, n := range nodes {
wwlog.Printf(wwlog.VERBOSE, "Evaluating node: %s\n", n.Fqdn)
if SetVnfs != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting vnfs to: %s\n", n.Fqdn, SetVnfs)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "vnfs", SetVnfs)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetKernel != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel to: %s\n", n.Fqdn, SetVnfs)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "kernel", SetKernel)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetDomainName != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting domain name to: %s\n", n.Fqdn, SetDomainName)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "domain", SetDomainName)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpxe != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting iPXE template to: %s\n", n.Fqdn, SetIpxe)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "ipxe", SetIpxe)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetRuntimeOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting runtime overlay to: %s\n", n.Fqdn, SetRuntimeOverlay)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "runtimeoverlay", SetRuntimeOverlay)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetSystemOverlay != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting system overlay to: %s\n", n.Fqdn, SetSystemOverlay)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "systemoverlay", SetSystemOverlay)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetHostname != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting hostname to: %s\n", n.Fqdn, SetHostname)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "hostname", SetHostname)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpmiIpaddr != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP address to: %s\n", n.Fqdn, SetIpmiIpaddr)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "ipmiipaddr", SetIpmiIpaddr)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpmiUsername != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP username to: %s\n", n.Fqdn, SetIpmiUsername)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "ipmiusername", SetIpmiUsername)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpmiPassword != "" {
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP password to: %s\n", n.Fqdn, SetIpmiPassword)
err := nodeDB.SetNodeVal(n.Gid, n.Id, "ipmipassword", SetIpmiPassword)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetNetDevDel == true {
if SetNetDev == "" {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", n.Fqdn, SetNetDev)
err := nodeDB.DelNodeNet(n.Gid, n.Id, SetNetDev)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetIpaddr != "" {
if SetNetDev == "" {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Ipaddr to: %s\n", n.Fqdn, SetNetDev, SetIpaddr)
err := nodeDB.SetNodeNet(n.Gid, n.Id, SetNetDev, "ipaddr", SetIpaddr)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetNetmask != "" {
if SetNetDev == "" {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting netmask to: %s\n", n.Fqdn, SetNetDev, SetNetmask)
err := nodeDB.SetNodeNet(n.Gid, n.Id, SetNetDev, "netmask", SetNetmask)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetGateway != "" {
if SetNetDev == "" {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting gateway to: %s\n", n.Fqdn, SetNetDev, SetGateway)
err := nodeDB.SetNodeNet(n.Gid, n.Id, SetNetDev, "gateway", SetGateway)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
if SetHwaddr != "" {
if SetNetDev == "" {
wwlog.Printf(wwlog.ERROR, "You must include the '--netdev' option\n")
os.Exit(1)
}
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting HW address to: %s\n", n.Fqdn, SetNetDev, SetHwaddr)
err := nodeDB.SetNodeNet(n.Gid, n.Id, SetNetDev, "hwaddr", SetHwaddr)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
}
}
if len(nodes) > 0 {
q := fmt.Sprintf("Are you sure you want to modify %d nodes(s)", len(nodes))
prompt := promptui.Prompt{
Label: q,
IsConfirm: true,
}
result, _ := prompt.Run()
if result == "y" || result == "yes" {
nodeDB.Persist()
}
} else {
fmt.Printf("No nodes found\n")
}
return nil
}

View File

@@ -0,0 +1,55 @@
package set
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "set",
Short: "Set node configurations",
Long: "Set node configurations ",
RunE: CobraRunE,
}
SetVnfs string
SetKernel string
SetNetDev string
SetIpaddr string
SetNetmask string
SetGateway string
SetHwaddr string
SetNetDevDel bool
SetDomainName string
SetIpxe string
SetRuntimeOverlay string
SetSystemOverlay string
SetHostname string
SetIpmiIpaddr string
SetIpmiUsername string
SetIpmiPassword string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&SetVnfs, "vnfs", "V", "", "Set node Virtual Node File System (VNFS)")
baseCmd.PersistentFlags().StringVarP(&SetKernel, "kernel", "K", "", "Set Kernel version for nodes")
baseCmd.PersistentFlags().StringVarP(&SetDomainName, "domain", "D", "", "Set the node's domain name")
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
baseCmd.PersistentFlags().StringVarP(&SetSystemOverlay, "system", "S", "", "Set the node's system overlay")
baseCmd.PersistentFlags().StringVarP(&SetHostname, "hostname", "H", "", "Set the node's hostname")
baseCmd.PersistentFlags().StringVar(&SetIpmiIpaddr, "ipmi", "", "Set the node's IPMI address")
baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username")
baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password")
baseCmd.PersistentFlags().StringVarP(&SetNetDev, "netdev", "n", "", "Define the network device to configure")
baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "I", "", "Set the node's network device IP address")
baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask")
baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway")
baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "N", "", "Set the node's network device HW address")
baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "delete", false, "Delete the node's network device")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -1,7 +1,7 @@
package build
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
@@ -9,10 +9,16 @@ import (
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var updateNodes []assets.NodeInfo
var updateNodes []node.NodeInfo
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if len(args) > 0 && BuildAll == false {
nodes, err := assets.FindAllNodes()
nodes, err := n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
@@ -27,7 +33,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
} else {
var err error
updateNodes, err = assets.FindAllNodes()
updateNodes, err = n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)

View File

@@ -1,8 +1,8 @@
package chmod
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
@@ -49,13 +49,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if NoOverlayUpdate == false {
nodes, err := assets.FindAllNodes()
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
nodes, err := n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
var updateNodes []assets.NodeInfo
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == overlayName {

View File

@@ -1,7 +1,7 @@
package create
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
@@ -11,7 +11,6 @@ import (
func CobraRunE(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
cmd.Help()
os.Exit(1)
@@ -34,13 +33,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if NoOverlayUpdate == false {
nodes, err := assets.FindAllNodes()
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
nodes, err := n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
var updateNodes []assets.NodeInfo
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {

View File

@@ -2,8 +2,8 @@ package delete
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
@@ -95,13 +95,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if NoOverlayUpdate == false {
nodes, err := assets.FindAllNodes()
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
nodes, err := n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
var updateNodes []assets.NodeInfo
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {

View File

@@ -2,8 +2,8 @@ package edit
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
@@ -93,13 +93,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if NoOverlayUpdate == false {
nodes, err := assets.FindAllNodes()
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
nodes, err := n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
var updateNodes []assets.NodeInfo
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {

View File

@@ -1,8 +1,8 @@
package imprt
import (
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
@@ -45,13 +45,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
}
if NoOverlayUpdate == false {
nodes, err := assets.FindAllNodes()
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
nodes, err := n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
var updateNodes []assets.NodeInfo
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == overlayName {

View File

@@ -2,8 +2,8 @@ package list
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
@@ -17,7 +17,13 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
set := make(map[string]int)
var o []string
var err error
var nodeList []assets.NodeInfo
var nodeList []node.NodeInfo
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if SystemOverlay == true {
if ListLong == false {
@@ -39,7 +45,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
return err
}
nodeList, err = assets.FindAllNodes()
nodeList, err = n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not get node configuration: %s\n", err)
return err

View File

@@ -2,8 +2,8 @@ package mkdir
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
@@ -42,13 +42,19 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Printf("Created directory within overlay: %s:%s\n", args[0], args[1])
if NoOverlayUpdate == false {
nodes, err := assets.FindAllNodes()
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
nodes, err := n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Cloud not get nodeList: %s\n", err)
os.Exit(1)
}
var updateNodes []assets.NodeInfo
var updateNodes []node.NodeInfo
for _, node := range nodes {
if SystemOverlay == true && node.SystemOverlay == args[0] {

View File

@@ -0,0 +1,47 @@
package show
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"io/ioutil"
"os"
"path"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
config := config.New()
var overlaySourceDir string
overlayName := args[0]
fileName := args[1]
if SystemOverlay == true {
overlaySourceDir = config.SystemOverlaySource(overlayName)
} else {
overlaySourceDir = config.RuntimeOverlaySource(overlayName)
}
if util.IsDir(overlaySourceDir) == false {
wwlog.Printf(wwlog.ERROR, "Overlay does not exist: %s\n", overlayName)
os.Exit(1)
}
overlayFile := path.Join(overlaySourceDir, fileName)
if util.IsFile(overlayFile) == false {
wwlog.Printf(wwlog.ERROR, "File does not exist within overlay: %s:%s\n", overlayName, fileName)
os.Exit(1)
}
f, err := ioutil.ReadFile(overlayFile)
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not read file: %s\n", err)
os.Exit(1)
}
fmt.Print(string(f))
return nil
}

View File

@@ -1,7 +1,6 @@
package show
import (
"fmt"
"github.com/spf13/cobra"
)
@@ -11,21 +10,17 @@ var (
Short: "Show Warewulf Overlay objects",
Long: "Warewulf show overlay objects",
RunE: CobraRunE,
Aliases: []string{"cat"},
Args: cobra.ExactArgs(2),
}
SystemOverlay bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SystemOverlay, "system", "s", false, "Show System Overlays as well")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}
func CobraRunE(cmd *cobra.Command, args []string) error {
fmt.Printf("Show: Hello World\n")
return nil
}

View File

@@ -2,6 +2,7 @@ package wwctl
import (
"github.com/hpcng/warewulf/internal/app/wwctl/build"
"github.com/hpcng/warewulf/internal/app/wwctl/group"
"github.com/hpcng/warewulf/internal/app/wwctl/kernel"
"github.com/hpcng/warewulf/internal/app/wwctl/node"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay"
@@ -30,6 +31,8 @@ func init() {
rootCmd.AddCommand(vnfs.GetCommand())
rootCmd.AddCommand(node.GetCommand())
rootCmd.AddCommand(kernel.GetCommand())
rootCmd.AddCommand(group.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -2,7 +2,7 @@ package build
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
@@ -10,12 +10,18 @@ import (
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var nodes []assets.NodeInfo
var nodes []node.NodeInfo
set := make(map[string]int)
n, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
if len(args) == 1 && ByNode == true {
var err error
nodes, err = assets.SearchByName(args[0])
nodes, err = n.SearchByName(args[0])
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not find nodes for search term: %s\n", args[0])
os.Exit(1)
@@ -27,7 +33,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
} else if BuildAll == true {
var err error
nodes, err = assets.FindAllNodes()
nodes, err = n.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not get list of nodes: %s\n", err)
os.Exit(1)

View File

@@ -0,0 +1,27 @@
package list
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
"io/ioutil"
"os"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
config := config.New()
files, err := ioutil.ReadDir(config.VnfsImageParentDir())
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
for _, f := range files {
fmt.Println(f.Name())
}
fmt.Printf("VNFS LIST: work in progress: %s\n", config.VnfsImageParentDir())
return nil
}

View File

@@ -0,0 +1,25 @@
package list
import "github.com/spf13/cobra"
var (
baseCmd = &cobra.Command{
Use: "list",
Short: "List VNFS images",
Long: "List VNFS images ",
RunE: CobraRunE,
}
SystemOverlay bool
BuildAll bool
)
func init() {
baseCmd.PersistentFlags().BoolVarP(&SystemOverlay, "system", "s", false, "Show System Overlays as well")
baseCmd.PersistentFlags().BoolVarP(&BuildAll, "all", "a", false, "Build all overlays (runtime and system)")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -2,6 +2,7 @@ package vnfs
import (
"github.com/hpcng/warewulf/internal/app/wwctl/vnfs/build"
"github.com/hpcng/warewulf/internal/app/wwctl/vnfs/list"
"github.com/spf13/cobra"
)
@@ -16,7 +17,7 @@ var (
func init() {
baseCmd.AddCommand(build.GetCommand())
baseCmd.AddCommand(list.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -1,337 +0,0 @@
package assets
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"io/ioutil"
// "os"
// "os"
"regexp"
"github.com/hpcng/warewulf/internal/pkg/errors"
)
const ConfigFile = "/etc/warewulf/nodes.conf"
const LocalStateDir = "/var/warewulf"
func init() {
//TODO: Check to make sure nodes.conf is found
}
type nodeYaml struct {
NodeGroups map[string]nodeGroup //`yaml:"nodegroups"`
}
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"`
KernelVersion string `yaml:"kernel version"`
KernelArgs string `yaml:"kernel args"`
Nodes map[string]nodeEntry
}
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"`
KernelVersion string `yaml:"kernel version"`
KernelArgs string `yaml:"kernel args"`
IpmiIpaddr string `yaml:"ipmi ipaddr"`
NetDevs map[string]netDevs
}
type netDevs struct {
Type string
Hwaddr string
Ipaddr string
Netmask string
Gateway string
}
type NodeInfo struct {
GroupName string
HostName string
DomainName string
Fqdn string
Vnfs string
VnfsDir string
Ipxe string
SystemOverlay string
RuntimeOverlay string
KernelVersion string
KernelArgs string
IpmiIpaddr string
NetDevs map[string]netDevs
}
func FindAllNodes() ([]NodeInfo, error) {
var c nodeYaml
var ret []NodeInfo
config := config.New()
wwlog.Printf(wwlog.DEBUG, "Opening configuration file: %s\n", ConfigFile)
data, err := ioutil.ReadFile(ConfigFile)
if err != nil {
fmt.Printf("error reading node configuration file\n")
return nil, err
}
err = yaml.Unmarshal(data, &c)
if err != nil {
return nil, err
}
for groupname, group := range c.NodeGroups {
for _, node := range group.Nodes {
var n NodeInfo
n.GroupName = groupname
n.HostName = node.Hostname
n.IpmiIpaddr = node.IpmiIpaddr
n.Vnfs = group.Vnfs
n.SystemOverlay = group.SystemOverlay
n.RuntimeOverlay = group.RuntimeOverlay
n.KernelVersion = group.KernelVersion
n.KernelArgs = group.KernelArgs
n.DomainName = group.DomainSuffix
n.Ipxe = group.Ipxe
n.NetDevs = node.NetDevs
if node.KernelVersion != "" {
n.KernelVersion = node.KernelVersion
}
if node.Vnfs != "" {
n.Vnfs = node.Vnfs
}
if node.SystemOverlay != "" {
n.SystemOverlay = node.SystemOverlay
}
if node.RuntimeOverlay != "" {
n.RuntimeOverlay = node.RuntimeOverlay
}
if node.DomainSuffix != "" {
n.DomainName = node.DomainSuffix
}
if node.Ipxe != "" {
n.Ipxe = node.Ipxe
}
if node.KernelArgs != "" {
n.KernelArgs = node.KernelArgs
}
if n.RuntimeOverlay == "" {
n.RuntimeOverlay = "default"
}
if n.SystemOverlay == "" {
n.SystemOverlay = "default"
}
if n.Ipxe == "" {
n.Ipxe = "default"
}
if n.DomainName != "" {
n.Fqdn = node.Hostname + "." + n.DomainName
} else {
n.Fqdn = node.Hostname
}
util.ValidateOrDie(n.Fqdn, "group name", n.GroupName, "^[a-zA-Z0-9-._]+$")
util.ValidateOrDie(n.Fqdn, "vnfs", n.Vnfs, "^[a-zA-Z0-9-._:/]+$")
util.ValidateOrDie(n.Fqdn, "system overlay", n.SystemOverlay, "^[a-zA-Z0-9-._]+$")
util.ValidateOrDie(n.Fqdn, "runtime overlay", n.RuntimeOverlay, "^[a-zA-Z0-9-._]+$")
util.ValidateOrDie(n.Fqdn, "domain suffix", n.DomainName, "^[a-zA-Z0-9-._]+$")
util.ValidateOrDie(n.Fqdn, "hostname", n.HostName, "^[a-zA-Z0-9-_]+$")
util.ValidateOrDie(n.Fqdn, "kernel version", n.KernelVersion, "^[a-zA-Z0-9-._]+$")
v := vnfs.New(n.Vnfs)
n.VnfsDir = config.VnfsChroot(v.NameClean())
ret = append(ret, n)
}
}
return ret, nil
}
func FindByHwaddr(hwa string) (NodeInfo, error) {
var ret NodeInfo
nodeList, err := FindAllNodes()
if err != nil {
return ret, err
}
for _, node := range nodeList {
for _, dev := range node.NetDevs {
if dev.Hwaddr == hwa {
return node, nil
}
}
}
return ret, errors.New("No nodes found with HW Addr: " + hwa)
}
func FindByIpaddr(ipaddr string) (NodeInfo, error) {
var ret NodeInfo
nodeList, err := FindAllNodes()
if err != nil {
return ret, err
}
for _, node := range nodeList {
for _, dev := range node.NetDevs {
if dev.Ipaddr == ipaddr {
return node, nil
}
}
}
return ret, errors.New("No nodes found with IP Addr: " + ipaddr)
}
func SearchByName(search string) ([]NodeInfo, error) {
var ret []NodeInfo
nodeList, err := FindAllNodes()
if err != nil {
return ret, err
}
for _, node := range nodeList {
b, _ := regexp.MatchString(search, node.Fqdn)
if b == true {
ret = append(ret, node)
}
}
return ret, nil
}
func SearchByNameList(searchList []string) ([]NodeInfo, error) {
var ret []NodeInfo
nodeList, err := FindAllNodes()
if err != nil {
return ret, err
}
for _, search := range searchList {
for _, node := range nodeList {
b, _ := regexp.MatchString(search, node.Fqdn)
if b == true {
ret = append(ret, node)
}
}
}
return ret, nil
}
/*
func FindAllVnfs() ([]string, error) {
var ret []string
set := make(map[string]bool)
nodeList, err := FindAllNodes()
if err != nil {
return ret, err
}
for _, node := range nodeList {
if node.Vnfs != "" {
set[node.Vnfs] = true
}
}
for entry := range set {
ret = append(ret, entry)
}
return ret, nil
}
func FindAllKernels() ([]string, error) {
var ret []string
set := make(map[string]bool)
nodeList, err := FindAllNodes()
if err != nil {
return ret, err
}
for _, node := range nodeList {
if node.KernelVersion != "" {
set[node.KernelVersion] = true
}
}
for entry := range set {
ret = append(ret, entry)
}
return ret, nil
}
func ListSystemOverlays() ([]string, error) {
var ret []string
set := make(map[string]bool)
nodeList, err := FindAllNodes()
if err != nil {
return ret, err
}
for _, node := range nodeList {
if node.SystemOverlay != "" {
set[node.SystemOverlay] = true
}
}
for entry := range set {
ret = append(ret, entry)
}
return ret, nil
}
func ListRuntimeOverlays() ([]string, error) {
var ret []string
set := make(map[string]bool)
nodeList, err := FindAllNodes()
if err != nil {
return ret, err
}
for _, node := range nodeList {
if node.RuntimeOverlay != "" {
set[node.RuntimeOverlay] = true
}
}
for entry := range set {
ret = append(ret, entry)
}
return ret, nil
}
*/

View File

@@ -57,10 +57,10 @@ func init() {
c.Editor = "vi"
}
util.ValidateOrDie("warewulf.conf", "warewulfd ipaddr", c.Ipaddr, "^[0-9]+.[0-9]+.[0-9]+.[0-9]+$")
util.ValidateOrDie("warewulf.conf", "system config dir", c.SysConfDir, "^[a-zA-Z0-9-._:/]+$")
util.ValidateOrDie("warewulf.conf", "local state dir", c.LocalStateDir, "^[a-zA-Z0-9-._:/]+$")
util.ValidateOrDie("warewulf.conf", "default editor", c.LocalStateDir, "^[a-zA-Z0-9-._:/]+$")
util.ValidateOrDie("warewulfd ipaddr", c.Ipaddr, "^[0-9]+.[0-9]+.[0-9]+.[0-9]+$")
util.ValidateOrDie("system config dir", c.SysConfDir, "^[a-zA-Z0-9-._:/]+$")
util.ValidateOrDie("local state dir", c.LocalStateDir, "^[a-zA-Z0-9-._:/]+$")
util.ValidateOrDie("default editor", c.LocalStateDir, "^[a-zA-Z0-9-._:/]+$")
}
@@ -84,6 +84,14 @@ func (self *Config) RuntimeOverlayDir() string {
return path.Join(self.OverlayDir(), "/runtime")
}
func (self *Config) VnfsImageParentDir() string {
return fmt.Sprintf("%s/provision/vnfs/", self.LocalStateDir)
}
func (self *Config) VnfsChrootParentDir() string {
return fmt.Sprintf("%s/chroot/", self.LocalStateDir)
}
func (self *Config) SystemOverlaySource(overlayName string) string {
if overlayName == "" {
wwlog.Printf(wwlog.ERROR, "System overlay name is not defined\n")
@@ -141,20 +149,6 @@ func (self *Config) KmodsImage(kernelVersion string) string {
return fmt.Sprintf("%s/provision/kernel/kmods-%s.img", self.LocalStateDir, kernelVersion)
}
func (self *Config) VnfsImage(vnfsNameClean string) string {
if vnfsNameClean == "" {
wwlog.Printf(wwlog.ERROR, "VNFS name is not defined\n")
return ""
}
if util.TaintCheck(vnfsNameClean, "^[a-zA-Z0-9-._:]+$") == false {
wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", vnfsNameClean)
return ""
}
return fmt.Sprintf("%s/provision/vnfs/%s.img.gz", self.LocalStateDir, vnfsNameClean)
}
func (self *Config) SystemOverlayImage(nodeName string) string {
if nodeName == "" {
wwlog.Printf(wwlog.ERROR, "Node name is not defined\n")
@@ -183,6 +177,21 @@ func (self *Config) RuntimeOverlayImage(nodeName string) string {
return fmt.Sprintf("%s/provision/overlays/runtime/%s.img", self.LocalStateDir, nodeName)
}
func (self *Config) VnfsImage(vnfsNameClean string) string {
if vnfsNameClean == "" {
wwlog.Printf(wwlog.ERROR, "VNFS name is not defined\n")
return ""
}
if util.TaintCheck(vnfsNameClean, "^[a-zA-Z0-9-._:]+$") == false {
wwlog.Printf(wwlog.ERROR, "Runtime overlay name contains illegal characters: %s\n", vnfsNameClean)
return ""
}
return path.Join(self.VnfsImageParentDir(), vnfsNameClean)
}
func (self *Config) VnfsChroot(vnfsNameClean string) string {
if vnfsNameClean == "" {
wwlog.Printf(wwlog.ERROR, "VNFS name is not defined\n")
@@ -194,6 +203,6 @@ func (self *Config) VnfsChroot(vnfsNameClean string) string {
return ""
}
return fmt.Sprintf("%s/chroot/%s.img", self.LocalStateDir, vnfsNameClean)
return path.Join(self.VnfsChrootParentDir(), vnfsNameClean)
}

530
internal/pkg/node/node.go Normal file
View File

@@ -0,0 +1,530 @@
package node
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"gopkg.in/yaml.v2"
"io/ioutil"
"os"
"regexp"
"strings"
)
const ConfigFile = "/etc/warewulf/nodes.conf"
const LocalStateDir = "/var/warewulf"
func init() {
//TODO: Check to make sure nodes.conf is found
}
type nodeYaml struct {
NodeGroups map[string]*nodeGroup //`yaml:"nodegroups"`
}
type nodeGroup struct {
Comment string
Vnfs string `yaml:"vnfs"`
Ipxe string `yaml:"ipxe template,omitempty"`
SystemOverlay string `yaml:"system overlay,omitempty""`
RuntimeOverlay string `yaml:"runtime overlay""`
DomainSuffix string `yaml:"domain suffix"`
KernelVersion string `yaml:"kernel version"`
KernelArgs string `yaml:"kernel args"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
Nodes map[string]*nodeEntry
}
type nodeEntry struct {
Hostname string `yaml:"hostname,omitempty"`
Vnfs string `yaml:"vnfs,omitempty"`
Ipxe string `yaml:"ipxe template,omitempty"`
SystemOverlay string `yaml:"system overlay,omitempty"`
RuntimeOverlay string `yaml:"runtime overlay,omitempty"`
DomainSuffix string `yaml:"domain suffix,omitempty"`
KernelVersion string `yaml:"kernel version,omitempty"`
KernelArgs string `yaml:"kernel args,omitempty"`
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
IpmiUserName string `yaml:"ipmi username,omitempty"`
IpmiPassword string `yaml:"ipmi password,omitempty"`
NetDevs map[string]*netDevs
}
type netDevs struct {
Type string `yaml:"type,omitempty"`
Hwaddr string
Ipaddr string
Netmask string
Gateway string`yaml:"gateway,omitempty"`
}
type NodeInfo struct {
Id string
Gid string
Uid string
GroupName string
HostName string
DomainName string
Fqdn string
Vnfs string
Ipxe string
SystemOverlay string
RuntimeOverlay string
KernelVersion string
KernelArgs string
IpmiIpaddr string
IpmiUserName string
IpmiPassword string
NetDevs map[string]*netDevs
}
type GroupInfo struct {
Id string
GroupName string
DomainName string
Vnfs string
Ipxe string
SystemOverlay string
RuntimeOverlay string
KernelVersion string
KernelArgs string
IpmiUserName string
IpmiPassword string
}
func New() (nodeYaml, error) {
var ret nodeYaml
wwlog.Printf(wwlog.DEBUG, "Opening node configuration file: %s\n", ConfigFile)
data, err := ioutil.ReadFile(ConfigFile)
if err != nil {
fmt.Printf("error reading node configuration file\n")
return ret, err
}
err = yaml.Unmarshal(data, &ret)
if err != nil {
return ret, err
}
return ret, nil
}
func (self *nodeYaml) AddGroup(groupID string) error {
var group nodeGroup
if _, ok := self.NodeGroups[groupID]; ok {
return errors.New("Group name already exists: " + groupID)
}
self.NodeGroups[groupID] = &group
self.NodeGroups[groupID].DomainSuffix = groupID
return nil
}
func (self *nodeYaml) AddNode(groupID string, nodeID string) error {
var node nodeEntry
wwlog.Printf(wwlog.VERBOSE, "Adding new node: %s/%s\n", groupID, nodeID)
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
return errors.New("Nodename already exists in group: " + nodeID)
}
} else {
return errors.New("Group does not exist: "+groupID)
}
self.NodeGroups[groupID].Nodes[nodeID] = &node
self.NodeGroups[groupID].Nodes[nodeID].Hostname = nodeID
return nil
}
func (self *nodeYaml) DelNode(groupID string, nodeID string) error {
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
delete(self.NodeGroups[groupID].Nodes, nodeID)
wwlog.Printf(wwlog.VERBOSE, "Deleting node: %s/%s\n", groupID, nodeID)
} else {
return errors.New("Node '"+nodeID+"' was not found in group '"+groupID+"'")
}
} else {
return errors.New("Group '"+groupID+"' was not found")
}
return nil
}
func (self *nodeYaml) DelNodeNet(groupID string, nodeID string, netDev string) error {
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev]; ok {
wwlog.Printf(wwlog.VERBOSE, "Deleting node network device: %s/%s:%s\n", groupID, nodeID, netDev)
delete(self.NodeGroups[groupID].Nodes[nodeID].NetDevs, netDev)
} else {
return errors.New("Network device '"+netDev+"' was not found in node '"+groupID+"/"+nodeID+"'")
}
} else {
return errors.New("Node '"+nodeID+"' was not found in group '"+groupID+"'")
}
} else {
return errors.New("Group '"+groupID+"' was not found")
}
return nil
}
func (self *nodeYaml) DelGroup(groupname string) error {
if _, ok := self.NodeGroups[groupname]; ok {
delete(self.NodeGroups, groupname)
} else {
return errors.New("Node group undefined: " + groupname)
}
return nil
}
func (self *nodeYaml) SetGroupVal(groupID string, entry string, value string) error {
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
value = ""
}
if _, ok := self.NodeGroups[groupID]; ok {
wwlog.Printf(wwlog.VERBOSE, "Setting group %s to: %s = '%s'\n", groupID, entry, value )
switch strings.ToUpper(entry) {
case "VNFS":
util.ValidateOrDie("VNFS", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Vnfs = value
case "KERNEL":
util.ValidateOrDie("Kernel Version", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].KernelVersion = value
case "DOMAINSUFFIX":
util.ValidateOrDie("Domain", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].DomainSuffix = value
case "IPXE":
util.ValidateOrDie("iPXE Template", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Ipxe = value
case "SYSTEMOVERLAY":
util.ValidateOrDie("System Overlay", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].SystemOverlay = value
case "RUNTIMEOVERLAY":
util.ValidateOrDie("Runtime Overlay", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].RuntimeOverlay = value
case "IPMIUSERNAME":
util.ValidateOrDie("IPMI Username", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].IpmiUserName = value
case "IPMIPASSWORD":
util.ValidateOrDie("IPMI Password", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].IpmiPassword = value
}
} else {
return errors.New("Group does not exist: " +groupID)
}
return nil
}
func (self *nodeYaml) SetNodeVal(groupID string, nodeID string, entry string, value string) error {
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
value = ""
}
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
wwlog.Printf(wwlog.VERBOSE, "Setting node %s/%s to: %s = '%s'\n", groupID, nodeID, entry, value )
switch strings.ToUpper(entry) {
case "VNFS":
util.ValidateOrDie("VNFS", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].Vnfs = value
case "KERNEL":
util.ValidateOrDie("Kernel Version", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].KernelVersion = value
case "DOMAINSUFFIX":
util.ValidateOrDie("Domain", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].DomainSuffix = value
case "IPXE":
util.ValidateOrDie("iPXE Template", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].Ipxe = value
case "SYSTEMOVERLAY":
util.ValidateOrDie("System Overlay", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].SystemOverlay = value
case "RUNTIMEOVERLAY":
util.ValidateOrDie("Runtime Overlay", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].RuntimeOverlay = value
case "HOSTNAME":
util.ValidateOrDie("Hostname", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].Hostname = value
case "IPMIIPADDR":
util.ValidateOrDie("IPMI IP Address", entry, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].IpmiIpaddr = value
case "IPMIUSERNAME":
util.ValidateOrDie("IPMI Username", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].IpmiUserName = value
case "IPMIPASSWORD":
util.ValidateOrDie("IPMI Password", entry, "^[a-zA-Z0-9-._]*$")
self.NodeGroups[groupID].Nodes[nodeID].IpmiPassword = value
}
} else {
return errors.New("Node does not exist: " +groupID+ "/" +nodeID)
}
} else {
return errors.New("Group does not exist: " +groupID)
}
return nil
}
func (self *nodeYaml) SetNodeNet(groupID string, nodeID string, netDev string, entry string, value string) error {
if strings.ToUpper(value) == "UNDEF" || strings.ToUpper(value) == "NIL" || strings.ToUpper(value) == "DEL" {
value = ""
}
if _, ok := self.NodeGroups[groupID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID]; ok {
if _, ok := self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev]; ok {
wwlog.Printf(wwlog.VERBOSE, "Editing existing node NetDev entry for node: %s/%s\n", groupID, nodeID)
} else {
var nd netDevs
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev] = &nd
}
} else {
return errors.New("Node does not exist: "+groupID+"/"+nodeID)
}
} else {
return errors.New("Group does not exist: "+groupID)
}
switch strings.ToUpper(entry) {
case "IPADDR":
util.ValidateOrDie("IP address", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Ipaddr = value
case "NETMASK":
util.ValidateOrDie("Netmask", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Netmask = value
case "GATEWAY":
util.ValidateOrDie("Gateway", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Gateway = value
case "TYPE":
util.ValidateOrDie("Network device type", value, "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Type = value
case "HWADDR":
util.ValidateOrDie("HW address", value, "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")
self.NodeGroups[groupID].Nodes[nodeID].NetDevs[netDev].Hwaddr = value
}
return nil
}
func (self *nodeYaml) Persist() error {
out, err := yaml.Marshal(self)
if err != nil {
return err
}
file, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
wwlog.Printf(wwlog.ERROR, "%s\n", err)
os.Exit(1)
}
defer file.Close()
_, err = file.WriteString(string(out))
if err != nil {
return err
}
return nil
}
func (self *nodeYaml) FindAllGroups() ([]GroupInfo, error) {
var ret []GroupInfo
for groupname, group := range self.NodeGroups {
var g GroupInfo
g.Id = groupname
g.GroupName = groupname
g.RuntimeOverlay = group.RuntimeOverlay
g.SystemOverlay = group.SystemOverlay
g.Ipxe = group.Ipxe
g.KernelVersion = group.KernelVersion
g.KernelArgs = group.KernelArgs
g.Vnfs = group.Vnfs
g.IpmiUserName = group.IpmiUserName
g.IpmiPassword = group.IpmiPassword
g.DomainName = group.DomainSuffix
// TODO: Validate or die on all inputs
ret = append(ret, g)
}
return ret, nil
}
func (self *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
var ret []NodeInfo
for groupname, group := range self.NodeGroups {
for nodename, node := range group.Nodes {
var n NodeInfo
n.Id = nodename
n.Gid = groupname
// n.Uid = groupname + ":" + nodename
n.GroupName = groupname
n.HostName = node.Hostname
n.IpmiIpaddr = node.IpmiIpaddr
n.Vnfs = group.Vnfs
n.SystemOverlay = group.SystemOverlay
n.RuntimeOverlay = group.RuntimeOverlay
n.KernelVersion = group.KernelVersion
n.KernelArgs = group.KernelArgs
n.DomainName = group.DomainSuffix
n.Ipxe = group.Ipxe
n.IpmiUserName = group.IpmiUserName
n.IpmiPassword = group.IpmiPassword
n.NetDevs = node.NetDevs
if node.IpmiUserName != "" {
n.IpmiUserName = node.IpmiUserName
}
if node.IpmiPassword != "" {
n.IpmiPassword = node.IpmiPassword
}
if node.KernelVersion != "" {
n.KernelVersion = node.KernelVersion
}
if node.Vnfs != "" {
n.Vnfs = node.Vnfs
}
if node.SystemOverlay != "" {
n.SystemOverlay = node.SystemOverlay
}
if node.RuntimeOverlay != "" {
n.RuntimeOverlay = node.RuntimeOverlay
}
if node.DomainSuffix != "" {
n.DomainName = node.DomainSuffix
}
if node.Ipxe != "" {
n.Ipxe = node.Ipxe
}
if node.KernelArgs != "" {
n.KernelArgs = node.KernelArgs
}
if n.RuntimeOverlay == "" {
n.RuntimeOverlay = "default"
}
if n.SystemOverlay == "" {
n.SystemOverlay = "default"
}
if n.Ipxe == "" {
n.Ipxe = "default"
}
if n.HostName == "" {
n.HostName = nodename
}
if n.DomainName != "" {
n.Fqdn = node.Hostname + "." + n.DomainName
} else {
n.Fqdn = node.Hostname
}
util.ValidateOrDie(n.Fqdn +":group name", n.GroupName, "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn +":vnfs", n.Vnfs, "^[a-zA-Z0-9-._:/]*$")
util.ValidateOrDie(n.Fqdn +":system overlay", n.SystemOverlay, "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn +":runtime overlay", n.RuntimeOverlay, "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn +":domain suffix", n.DomainName, "^[a-zA-Z0-9-._]*$")
util.ValidateOrDie(n.Fqdn +":hostname", n.HostName, "^[a-zA-Z0-9-_]*$")
util.ValidateOrDie(n.Fqdn +":kernel version", n.KernelVersion, "^[a-zA-Z0-9-._]*$")
ret = append(ret, n)
}
}
return ret, nil
}
func (nodes *nodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
var ret NodeInfo
n, _ := nodes.FindAllNodes()
for _, node := range n {
for _, dev := range node.NetDevs {
if dev.Hwaddr == hwa {
return node, nil
}
}
}
return ret, errors.New("No nodes found with HW Addr: " + hwa)
}
func (nodes *nodeYaml) FindByIpaddr(ipaddr string) (NodeInfo, error) {
var ret NodeInfo
n, _ := nodes.FindAllNodes()
for _, node := range n {
for _, dev := range node.NetDevs {
if dev.Ipaddr == ipaddr {
return node, nil
}
}
}
return ret, errors.New("No nodes found with IP Addr: " + ipaddr)
}
func (nodes *nodeYaml) SearchByName(search string) ([]NodeInfo, error) {
var ret []NodeInfo
n, _ := nodes.FindAllNodes()
for _, node := range n {
b, _ := regexp.MatchString(search, node.Fqdn)
if b == true {
ret = append(ret, node)
}
}
return ret, nil
}
func (nodes *nodeYaml) SearchByNameList(searchList []string) ([]NodeInfo, error) {
var ret []NodeInfo
n, _ := nodes.FindAllNodes()
for _, search := range searchList {
for _, node := range n {
b, _ := regexp.MatchString(search, node.Fqdn)
if b == true {
ret = append(ret, node)
}
}
}
return ret, nil
}

View File

@@ -3,14 +3,13 @@ package overlay
import (
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"io/ioutil"
"path"
"strings"
)
func templateFileInclude(path string) string {
wwlog.Printf(wwlog.DEBUG, "Including file into template: %s\n", path)
content, err := ioutil.ReadFile(path)

View File

@@ -2,10 +2,11 @@ package overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"io/ioutil"
"os"
@@ -53,7 +54,7 @@ func RuntimeOverlayInit(name string) error {
}
func RuntimeBuild(nodeList []assets.NodeInfo, force bool) error {
func RuntimeBuild(nodeList []node.NodeInfo, force bool) error {
config := config.New()
wwlog.SetIndent(4)
@@ -62,6 +63,9 @@ func RuntimeBuild(nodeList []assets.NodeInfo, force bool) error {
if node.RuntimeOverlay != "" {
OverlayDir := config.RuntimeOverlaySource(node.RuntimeOverlay)
OverlayFile := config.RuntimeOverlayImage(node.Fqdn)
vnfs := vnfs.New(node.Vnfs)
vnfsDir := config.VnfsChroot(vnfs.NameClean())
wwlog.Printf(wwlog.VERBOSE, "Building Runtime Overlay for: %s\n", node.Fqdn)
@@ -71,11 +75,11 @@ func RuntimeBuild(nodeList []assets.NodeInfo, force bool) error {
}
if util.IsDir(OverlayDir) == false {
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (unknown runtime overlay)\n", node.Fqdn)
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (runtime overlay template not found)\n", node.Fqdn)
continue
}
if util.IsDir(node.VnfsDir) == false {
if util.IsDir(vnfsDir) == false {
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (VNFS not imported)\n", node.Fqdn)
continue
}

View File

@@ -2,10 +2,11 @@ package overlay
import (
"fmt"
"github.com/hpcng/warewulf/internal/pkg/assets"
"github.com/hpcng/warewulf/internal/pkg/config"
"github.com/hpcng/warewulf/internal/pkg/errors"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/vnfs"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"io/ioutil"
"os"
@@ -53,7 +54,7 @@ func SystemOverlayInit(name string) error {
}
func SystemBuild(nodeList []assets.NodeInfo, force bool) error {
func SystemBuild(nodeList []node.NodeInfo, force bool) error {
config := config.New()
wwlog.SetIndent(4)
@@ -62,6 +63,9 @@ func SystemBuild(nodeList []assets.NodeInfo, force bool) error {
if node.SystemOverlay != "" {
OverlayDir := config.SystemOverlaySource(node.SystemOverlay)
OverlayFile := config.SystemOverlayImage(node.Fqdn)
vnfs := vnfs.New(node.Vnfs)
vnfsDir := config.VnfsChroot(vnfs.NameClean())
wwlog.Printf(wwlog.VERBOSE, "Building System Overlay for: %s\n", node.Fqdn)
@@ -71,11 +75,11 @@ func SystemBuild(nodeList []assets.NodeInfo, force bool) error {
}
if util.IsDir(OverlayDir) == false {
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (unknown system overlay)\n", node.Fqdn)
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (system overlay template not found)\n", node.Fqdn)
continue
}
if util.IsDir(node.VnfsDir) == false {
if util.IsDir(vnfsDir) == false {
wwlog.Printf(wwlog.WARN, "%-35s: Skipped (VNFS not imported)\n", node.Fqdn)
continue
}

View File

@@ -111,9 +111,9 @@ func TaintCheck(pattern string, expr string) bool {
return false
}
func ValidateOrDie(hostname string, name string, pattern string, expr string) {
func ValidateOrDie(message string, pattern string, expr string) {
if TaintCheck(pattern, expr) == false {
wwlog.Printf(wwlog.ERROR, "Entry '%s:%s' contains illegal characters: '%s'\n", hostname, name, pattern)
wwlog.Printf(wwlog.ERROR, "%s does not validate: '%s'\n", message, pattern)
os.Exit(1)
}
}