Merge pull request #1459 from mslacken/ChangeOCIDir
Make cache directory configureable and add clean command
This commit is contained in:
@@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Add support to render template using `host` or `$(uname -n)` as the value of `overlay show --render`. #623
|
||||
- Added command line parameters for credentials of a container registry
|
||||
- Add flag `--build` to `wwctl container copy`. #1378
|
||||
- Add `wwctl clean` to remove OCI cache and overlays from deleted nodes
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -38,6 +39,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Remove NodeInfo (in-memory-only) data structure, consolidating onto NodeConf. #916
|
||||
- Replace `defaults.conf` with settings on the default profile. #917
|
||||
- Switched from yaml.v2 to yaml.v3 #1462
|
||||
- Make OCIBlobCache a seperate path and point it to `/var/cache` #1459
|
||||
|
||||
|
||||
### Removed
|
||||
|
||||
@@ -27,7 +27,7 @@ ifdef PREFIX
|
||||
endif
|
||||
|
||||
# System directory paths
|
||||
VARLIST += PREFIX BINDIR SYSCONFDIR SRVDIR DATADIR MANDIR DOCDIR LOCALSTATEDIR RELEASE
|
||||
VARLIST += PREFIX BINDIR SYSCONFDIR SRVDIR DATADIR MANDIR DOCDIR LOCALSTATEDIR RELEASE CACHEDIR
|
||||
PREFIX ?= /usr/local
|
||||
BINDIR ?= $(PREFIX)/bin
|
||||
SYSCONFDIR ?= $(PREFIX)/etc
|
||||
@@ -42,6 +42,7 @@ else
|
||||
SRVDIR ?= $(PREFIX)/srv
|
||||
LOCALSTATEDIR ?= $(PREFIX)/var
|
||||
endif
|
||||
CACHEDIR ?= $(LOCALSTATEDIR)/cache
|
||||
|
||||
# OS-Specific Service Locations
|
||||
VARLIST += TFTPDIR FIREWALLDDIR SYSTEMDDIR BASHCOMPDIR LOGROTATEDIR DRACUTMODDIR
|
||||
|
||||
19
internal/app/wwctl/clean/main.go
Normal file
19
internal/app/wwctl/clean/main.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package clean
|
||||
|
||||
import (
|
||||
"github.com/warewulf/warewulf/internal/pkg/clean"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) {
|
||||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
if err = clean.CleanOciBlobCacheDir(); err != nil {
|
||||
return err
|
||||
} else if err = clean.CleanOverlays(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
29
internal/app/wwctl/clean/main_test.go
Normal file
29
internal/app/wwctl/clean/main_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package clean
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/warewulf/warewulf/internal/pkg/testenv"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
func Test_Clean(t *testing.T) {
|
||||
wwlog.SetLogLevel(wwlog.DEBUG)
|
||||
env := testenv.New(t)
|
||||
env.WriteFile(t, "etc/warewulf/nodes.conf",
|
||||
`WW_INTERNAL: 45
|
||||
nodeprofiles: {}
|
||||
nodes:
|
||||
node1: {}
|
||||
`)
|
||||
env.WriteFile(t, "srv/warewulf/overlays/node1/__SYSTEM__.img", "Fake System")
|
||||
env.WriteFile(t, "srv/warewulf/overlays/node2/__SYSTEM__.img", "Fake System")
|
||||
env.WriteFile(t, "var/cache/warewulf/test", "Nothing to see here")
|
||||
baseCmd := GetCommand()
|
||||
err := baseCmd.Execute()
|
||||
assert.NoError(t, err)
|
||||
assert.FileExists(t, env.GetPath("srv/warewulf/overlays/node1/__SYSTEM__.img"))
|
||||
assert.NoFileExists(t, env.GetPath("srv/warewulf/overlays/node2/__SYSTEM__.img"))
|
||||
assert.NoFileExists(t, env.GetPath("/var/cache/warewulf/test"))
|
||||
}
|
||||
20
internal/app/wwctl/clean/root.go
Normal file
20
internal/app/wwctl/clean/root.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package clean
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type variables struct {
|
||||
}
|
||||
|
||||
func GetCommand() *cobra.Command {
|
||||
vars := variables{}
|
||||
baseCmd := &cobra.Command{
|
||||
DisableFlagsInUseLine: true,
|
||||
Use: "clean",
|
||||
Short: "Clean up",
|
||||
Long: "This command cleans the OCI cache and removes leftovers from deleted nodes",
|
||||
RunE: CobraRunE(&vars),
|
||||
}
|
||||
return baseCmd
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/clean"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/configure"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/container"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/genconf"
|
||||
@@ -58,6 +59,7 @@ func init() {
|
||||
rootCmd.AddCommand(version.GetCommand())
|
||||
rootCmd.AddCommand(ssh.GetCommand())
|
||||
rootCmd.AddCommand(genconf.GetCommand())
|
||||
rootCmd.AddCommand(clean.GetCommand())
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
|
||||
46
internal/pkg/clean/clean.go
Normal file
46
internal/pkg/clean/clean.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package clean
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
warewulfconf "github.com/warewulf/warewulf/internal/pkg/config"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/util"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
/*
|
||||
Cleans up the OCI cache and remains of deleted nodes
|
||||
*/
|
||||
func CleanOciBlobCacheDir() error {
|
||||
warewulfconf := warewulfconf.Get()
|
||||
wwlog.Verbose("removing oci cache dir: %s", warewulfconf.Paths.OciBlobCachedir())
|
||||
return os.RemoveAll(warewulfconf.Paths.OciBlobCachedir())
|
||||
}
|
||||
|
||||
func CleanOverlays() error {
|
||||
warewulfconf := warewulfconf.Get()
|
||||
nodeDB, err := node.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nodes := nodeDB.ListAllNodes()
|
||||
dirList, err := os.ReadDir(warewulfconf.Paths.OverlayProvisiondir())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, item := range dirList {
|
||||
if !item.IsDir() {
|
||||
continue
|
||||
}
|
||||
if !util.InSlice(nodes, item.Name()) {
|
||||
wwlog.Verbose("removing overlays of delete node: %s", item.Name())
|
||||
err = os.RemoveAll(path.Join(warewulfconf.Paths.OverlayProvisiondir(), item.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"path"
|
||||
)
|
||||
|
||||
var ConfigFile = "@SYSCONFDIR@/warewulf/warewulf.conf"
|
||||
|
||||
type BuildConfig struct {
|
||||
Bindir string `default:"@BINDIR@"`
|
||||
Sysconfdir string `default:"@SYSCONFDIR@"`
|
||||
Localstatedir string `default:"@LOCALSTATEDIR@"`
|
||||
Cachedir string `default:"@CACHEDIR@"`
|
||||
Ipxesource string `default:"@IPXESOURCE@"`
|
||||
Srvdir string `default:"@SRVDIR@"`
|
||||
Firewallddir string `default:"@FIREWALLDDIR@"`
|
||||
@@ -42,3 +47,11 @@ type WarewulfConf struct {
|
||||
DataStore string `yaml:"datastore" default:"@DATADIR@"`
|
||||
GrubBoot bool `yaml:"grubboot" default:"false"`
|
||||
}
|
||||
|
||||
func (paths BuildConfig) OciBlobCachedir() string {
|
||||
return path.Join(paths.Cachedir, "warewulf")
|
||||
}
|
||||
|
||||
func (paths BuildConfig) OverlayProvisiondir() string {
|
||||
return path.Join(paths.WWProvisiondir, "overlays")
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ func TestDefaultRootConf(t *testing.T) {
|
||||
assert.True(t, conf.Warewulf.AutobuildOverlays)
|
||||
assert.True(t, conf.Warewulf.EnableHostOverlay)
|
||||
assert.False(t, conf.Warewulf.Syslog)
|
||||
assert.NotEmpty(t, conf.Warewulf.DataStore)
|
||||
|
||||
assert.True(t, conf.DHCP.Enabled)
|
||||
assert.Equal(t, "default", conf.DHCP.Template)
|
||||
@@ -43,7 +42,6 @@ func TestDefaultRootConf(t *testing.T) {
|
||||
|
||||
assert.NotEmpty(t, conf.Paths.Bindir)
|
||||
assert.NotEmpty(t, conf.Paths.Sysconfdir)
|
||||
assert.NotEmpty(t, conf.Warewulf.DataStore)
|
||||
assert.NotEmpty(t, conf.Paths.Localstatedir)
|
||||
assert.NotEmpty(t, conf.Paths.Srvdir)
|
||||
assert.NotEmpty(t, conf.Paths.Firewallddir)
|
||||
@@ -52,6 +50,7 @@ func TestDefaultRootConf(t *testing.T) {
|
||||
assert.NotEmpty(t, conf.Paths.WWChrootdir)
|
||||
assert.NotEmpty(t, conf.Paths.WWProvisiondir)
|
||||
assert.NotEmpty(t, conf.Paths.WWClientdir)
|
||||
assert.NotEmpty(t, conf.Paths.Cachedir)
|
||||
}
|
||||
|
||||
func TestInitializedFromFile(t *testing.T) {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
func ImportDocker(uri string, name string, sCtx *types.SystemContext) error {
|
||||
OciBlobCacheDir := warewulfconf.Get().Warewulf.DataStore + "/oci"
|
||||
OciBlobCacheDir := warewulfconf.Get().Paths.OciBlobCachedir()
|
||||
|
||||
err := os.MkdirAll(OciBlobCacheDir, 0755)
|
||||
if err != nil {
|
||||
|
||||
@@ -55,5 +55,5 @@ func OverlayImage(nodeName string, context string, overlayNames []string) string
|
||||
}
|
||||
|
||||
conf := warewulfconf.Get()
|
||||
return path.Join(conf.Paths.WWProvisiondir, "overlays/", nodeName, name)
|
||||
return path.Join(conf.Paths.OverlayProvisiondir(), nodeName, name)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ const Systemddir = "usr/lib/systemd/system"
|
||||
const WWOverlaydir = "var/lib/warewulf/overlays"
|
||||
const WWChrootdir = "var/lib/warewulf/chroots"
|
||||
const WWProvisiondir = "srv/warewulf"
|
||||
const Cachedir = "var/cache"
|
||||
|
||||
// New creates a test environment in a temporary directory and configures
|
||||
// Warewulf to use it.
|
||||
@@ -76,6 +77,7 @@ func New(t *testing.T) (env *TestEnv) {
|
||||
conf.Paths.WWOverlaydir = env.GetPath(WWOverlaydir)
|
||||
conf.Paths.WWChrootdir = env.GetPath(WWChrootdir)
|
||||
conf.Paths.WWProvisiondir = env.GetPath(WWProvisiondir)
|
||||
conf.Paths.Cachedir = env.GetPath(Cachedir)
|
||||
conf.Paths.WWClientdir = "/warewulf"
|
||||
|
||||
for _, confPath := range []string{
|
||||
|
||||
@@ -103,10 +103,10 @@ nodes:
|
||||
assert.NoError(t, dbErr)
|
||||
|
||||
conf.Warewulf.Secure = false
|
||||
assert.NoError(t, os.MkdirAll(path.Join(conf.Paths.WWProvisiondir, "overlays", "n1"), 0700))
|
||||
assert.NoError(t, os.WriteFile(path.Join(conf.Paths.WWProvisiondir, "overlays", "n1", "__SYSTEM__.img"), []byte("system overlay"), 0600))
|
||||
assert.NoError(t, os.WriteFile(path.Join(conf.Paths.WWProvisiondir, "overlays", "n1", "__RUNTIME__.img"), []byte("runtime overlay"), 0600))
|
||||
assert.NoError(t, os.WriteFile(path.Join(conf.Paths.WWProvisiondir, "overlays", "n1", "o1.img"), []byte("specific overlay"), 0600))
|
||||
assert.NoError(t, os.MkdirAll(path.Join(conf.Paths.OverlayProvisiondir(), "n1"), 0700))
|
||||
assert.NoError(t, os.WriteFile(path.Join(conf.Paths.OverlayProvisiondir(), "n1", "__SYSTEM__.img"), []byte("system overlay"), 0600))
|
||||
assert.NoError(t, os.WriteFile(path.Join(conf.Paths.OverlayProvisiondir(), "n1", "__RUNTIME__.img"), []byte("runtime overlay"), 0600))
|
||||
assert.NoError(t, os.WriteFile(path.Join(conf.Paths.OverlayProvisiondir(), "n1", "o1.img"), []byte("specific overlay"), 0600))
|
||||
|
||||
wwlog.SetLogLevel(wwlog.DEBUG)
|
||||
for _, tt := range provisionSendTests {
|
||||
|
||||
@@ -37,42 +37,42 @@ var getOverlayFileTests = []struct {
|
||||
node: "",
|
||||
context: "",
|
||||
overlays: []string{"o1", "o2"},
|
||||
result: "overlays/node1/o1-o2.img",
|
||||
result: "node1/o1-o2.img",
|
||||
},
|
||||
{
|
||||
description: "system overlay for a node points to the node's system overlay image",
|
||||
node: "node1",
|
||||
context: "system",
|
||||
overlays: []string{"o1"},
|
||||
result: "overlays/node1/__SYSTEM__.img",
|
||||
result: "node1/__SYSTEM__.img",
|
||||
},
|
||||
{
|
||||
description: "runtime overlay for a node points to the node's runtime overlay image",
|
||||
node: "node1",
|
||||
context: "runtime",
|
||||
overlays: nil,
|
||||
result: "overlays/node1/__RUNTIME__.img",
|
||||
result: "node1/__RUNTIME__.img",
|
||||
},
|
||||
{
|
||||
description: "a specific overlay for a node points to that specific overlay image for that node",
|
||||
node: "node1",
|
||||
context: "",
|
||||
overlays: []string{"o1"},
|
||||
result: "overlays/node1/o1.img",
|
||||
result: "node1/o1.img",
|
||||
},
|
||||
{
|
||||
description: "a specific set of overlays for a node points to a combined overlay image for that node",
|
||||
node: "node1",
|
||||
context: "",
|
||||
overlays: []string{"o1", "o2"},
|
||||
result: "overlays/node1/o1-o2.img",
|
||||
result: "node1/o1-o2.img",
|
||||
},
|
||||
{
|
||||
description: "a specific set of overlays for a node while also specifying a context points to the contextual overlay image for that node",
|
||||
node: "node1",
|
||||
context: "system",
|
||||
overlays: []string{"o1", "o2"},
|
||||
result: "overlays/node1/__SYSTEM__.img",
|
||||
result: "node1/__SYSTEM__.img",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ nodes:
|
||||
result, err := getOverlayFile(nodeInfo, tt.context, tt.overlays, false)
|
||||
assert.NoError(t, err)
|
||||
if tt.result != "" {
|
||||
tt.result = path.Join(conf.Paths.WWProvisiondir, tt.result)
|
||||
tt.result = path.Join(conf.Paths.OverlayProvisiondir(), tt.result)
|
||||
}
|
||||
assert.Equal(t, tt.result, result)
|
||||
})
|
||||
|
||||
@@ -128,7 +128,8 @@ make defaults \
|
||||
FIREWALLDDIR=/usr/lib/firewalld/services \
|
||||
WWCLIENTDIR=/warewulf \
|
||||
IPXESOURCE=/usr/share/ipxe \
|
||||
DRACUTMODDIR=/usr/lib/dracut/modules.d
|
||||
DRACUTMODDIR=/usr/lib/dracut/modules.d \
|
||||
CACHEDIR=%{_localstatedir}/cache
|
||||
make
|
||||
%if %{api}
|
||||
make api
|
||||
|
||||
Reference in New Issue
Block a user