Files
warewulf/internal/pkg/overlay/config.go
Jonathon Anderson a2c7caa4ba Rebuild overlays for discovered nodes
- Fixes: #1468

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
2025-07-09 14:29:38 -06:00

124 lines
4.0 KiB
Go

package overlay
import (
"fmt"
"os"
"path"
"path/filepath"
"strings"
"github.com/containers/storage/drivers/copy"
"github.com/warewulf/warewulf/internal/pkg/config"
"github.com/warewulf/warewulf/internal/pkg/util"
"github.com/warewulf/warewulf/internal/pkg/wwlog"
)
// GetOverlay returns the filesystem path of an overlay identified by its name,
// along with a boolean indicating whether the returned overlayPath corresponds
// to a site-specific overlay.
func GetOverlay(name string) (overlay Overlay) {
overlay = GetSiteOverlay(name)
if overlay.Exists() {
return overlay
}
overlay = GetDistributionOverlay(name)
if overlay.Exists() {
return overlay
}
return GetSiteOverlay(name)
}
// GetDistributionOverlay returns the filesystem path of a distribution overlay
// identified by the given name.
func GetDistributionOverlay(name string) (overlay Overlay) {
return getOverlay(config.Get().Paths.DistributionOverlaydir(), name)
}
// GetSiteOverlay returns the filesystem path of a site-specific overlay
// identified by the given name.
func GetSiteOverlay(name string) (overlay Overlay) {
return getOverlay(config.Get().Paths.SiteOverlaydir(), name)
}
// getOverlay constructs an overlay based on the given overlay directory and
// overlay name. The overlay does not necessarily exist.
func getOverlay(overlaydir, name string) (overlay Overlay) {
return Overlay(path.Join(overlaydir, name))
}
// Create creates a new overlay directory for the given overlay
//
// Returns an error if the overlay already exists or if directory creation fails.
func (overlay Overlay) Create() error {
if util.IsDir(overlay.Path()) {
return fmt.Errorf("overlay already exists: %s", overlay)
}
return os.MkdirAll(overlay.Rootfs(), 0755)
}
// Creates a site overlay from an existing distribution overlay.
//
// If the distribution overlay doesn't exist, return an error.
func (overlay Overlay) CloneSiteOverlay() (siteOverlay Overlay, err error) {
siteOverlay = GetSiteOverlay(overlay.Name())
if !util.IsDir(overlay.Path()) {
return siteOverlay, fmt.Errorf("source overlay does not exist: %s", overlay.Name())
}
if siteOverlay.Exists() {
return siteOverlay, fmt.Errorf("site overlay already exists: %s", siteOverlay.Name())
}
if !util.IsDir(filepath.Dir(overlay.Path())) {
if err := os.MkdirAll(filepath.Dir(overlay.Path()), 0755); err != nil {
return siteOverlay, err
}
}
err = copy.DirCopy(overlay.Path(), siteOverlay.Path(), copy.Content, true)
return siteOverlay, err
}
// OverlayImage returns the full path to an overlay image based on the
// context and the overlays contained in it.
//
// If a context is provided, the image file name is based on that
// context name, in the form __{CONTEXT}__.
//
// If the context is empty ("") the image file name is a concatenated
// list of the contained overlays joined by "-".
//
// If the context is empty and no overlays are specified, the empty
// string is returned.
func OverlayImage(nodeName string, context string, overlayNames []string) string {
var name string
if context != "" {
if len(overlayNames) > 0 {
wwlog.Debug("context(%v) and overlays(%v) specified: prioritizing context(%v)",
context, overlayNames, context)
}
name = "__" + strings.ToUpper(context) + "__.img"
} else if len(overlayNames) > 0 {
name = strings.Join(overlayNames, "-") + ".img"
} else {
wwlog.Warn("unable to generate overlay image path: no context or overlays specified")
return ""
}
return path.Join(config.Get().Paths.OverlayProvisiondir(), nodeName, name)
}
func ClearOverlayImage(nodeName string, context string, overlayNames []string) error {
imagePath := OverlayImage(nodeName, context, overlayNames)
if util.IsFile(imagePath) {
if err := os.Remove(imagePath); err != nil {
return fmt.Errorf("failed to remove overlay image: %w", err)
}
}
compressedImagePath := imagePath + ".gz"
if util.IsFile(compressedImagePath) {
if err := os.Remove(compressedImagePath); err != nil {
return fmt.Errorf("failed to remove compressed overlay image: %w", err)
}
}
return nil
}