Rebuild overlays for discovered nodes

- Fixes: #1468

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2025-07-09 14:29:38 -06:00
parent 4f63790896
commit a2c7caa4ba
5 changed files with 69 additions and 11 deletions

View File

@@ -6,6 +6,7 @@ import (
"sync"
"github.com/warewulf/warewulf/internal/pkg/node"
"github.com/warewulf/warewulf/internal/pkg/overlay"
"github.com/warewulf/warewulf/internal/pkg/wwlog"
)
@@ -53,7 +54,7 @@ func loadNodeDB() (err error) {
return nil
}
func GetNodeOrSetDiscoverable(hwaddr string) (node.Node, error) {
func GetNodeOrSetDiscoverable(hwaddr string, autobuildOverlays bool) (node.Node, error) {
db.lock.RLock()
defer db.lock.RUnlock()
// NOTE: since discoverable nodes will write an updated DB to file and then
@@ -97,9 +98,14 @@ func GetNodeOrSetDiscoverable(hwaddr string) (node.Node, error) {
if err != nil {
return nodeFound, fmt.Errorf("%s (failed to reload configuration) %w", hwaddr, err)
}
// NOTE: previously all overlays were built here, but that will also
// be done automatically when attempting to serve an overlay that
// hasn't been built (without blocking the database).
if autobuildOverlays {
if err := overlay.ClearOverlayImage(nodeFound.Id(), "system", []string{}); err != nil {
wwlog.Warn("Failed to clear system overlay image: %s: %s", nodeFound.Id(), err)
}
if err := overlay.ClearOverlayImage(nodeFound.Id(), "runtime", []string{}); err != nil {
wwlog.Warn("Failed to clear runtime overlay image: %s: %s", nodeFound.Id(), err)
}
}
wwlog.Serv("%s (node %s automatically configured)", hwaddr, nodeFound.Id())

View File

@@ -10,10 +10,12 @@ import (
func Test_GetNodeOrSetDiscoverable(t *testing.T) {
var tests = map[string]struct {
nodesConf string
hwaddr string
node string
err bool
nodesConf string
hwaddr string
node string
err bool
initFiles []string
removedFiles []string
}{
"empty": {
nodesConf: `
@@ -40,6 +42,29 @@ nodes:
discoverable: true
network devices:
default: {}
`,
hwaddr: "00:00:00:00:00:01",
node: "n1",
},
"discoverable autobuild": {
initFiles: []string{
"/srv/warewulf/overlays/n1/__SYSTEM__.img",
"/srv/warewulf/overlays/n1/__SYSTEM__.img.gz",
"/srv/warewulf/overlays/n1/__RUNTIME__.img",
"/srv/warewulf/overlays/n1/__RUNTIME__.img.gz",
},
removedFiles: []string{
"/srv/warewulf/overlays/n1/__SYSTEM__.img",
"/srv/warewulf/overlays/n1/__SYSTEM__.img.gz",
"/srv/warewulf/overlays/n1/__RUNTIME__.img",
"/srv/warewulf/overlays/n1/__RUNTIME__.img.gz",
},
nodesConf: `
nodes:
n1:
discoverable: true
network devices:
default: {}
`,
hwaddr: "00:00:00:00:00:01",
node: "n1",
@@ -77,20 +102,25 @@ nodes:
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
env := testenv.New(t)
for _, file := range tt.initFiles {
env.CreateFile(file)
}
defer env.RemoveAll()
env.WriteFile("/etc/warewulf/nodes.conf", tt.nodesConf)
err := LoadNodeDB()
assert.NoError(t, err)
node, err := GetNodeOrSetDiscoverable(tt.hwaddr)
node, err := GetNodeOrSetDiscoverable(tt.hwaddr, true)
if tt.err {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.node, node.Id())
}
for _, file := range tt.removedFiles {
assert.NoFileExists(t, env.GetPath(file), "File should not exist: %s", file)
}
})
}
}

View File

@@ -76,7 +76,7 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) {
// TODO: when module version is upgraded to go1.18, should be 'any' type
var tmpl_data *templateVars
remoteNode, err := GetNodeOrSetDiscoverable(rinfo.hwaddr)
remoteNode, err := GetNodeOrSetDiscoverable(rinfo.hwaddr, conf.Warewulf.AutobuildOverlays())
if err != nil && err != node.ErrNoUnconfigured {
wwlog.ErrorExc(err, "")
w.WriteHeader(http.StatusServiceUnavailable)