Skip to content

Commit f3dc9bb

Browse files
authored
Merge pull request #119 from gman0/localcache-hostpath
mount local cache as hostPath; clean it on startup
2 parents 888821a + 1bd7244 commit f3dc9bb

File tree

3 files changed

+123
-2
lines changed

3 files changed

+123
-2
lines changed

deployments/helm/cvmfs-csi/values.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ extraConfigMaps:
3636
cache:
3737
local:
3838
volumeSpec:
39-
emptyDir: {}
39+
hostPath:
40+
path: /var/lib/cvmfs.csi.cern.ch/cache
41+
type: DirectoryOrCreate
4042
# Maximum size of local cache in MiB.
4143
# CVMFS client will garbage collect the exceeding amount.
4244
cvmfsQuotaLimit: 1000

deployments/kubernetes/nodeplugin-daemonset.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ spec:
171171
- name: runtime-metadata
172172
emptyDir: {}
173173
- name: cvmfs-localcache
174-
emptyDir: {}
174+
hostPath:
175+
path: /var/lib/cvmfs.csi.cern.ch/cache
176+
type: DirectoryOrCreate
175177
- configMap:
176178
name: cvmfs-csi-default-local
177179
name: etc-cvmfs-default-conf

internal/cvmfs/automount/automount.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"os"
2424
goexec "os/exec"
2525
"os/signal"
26+
"path"
2627
"syscall"
2728

2829
"github.com/cvmfs-contrib/cvmfs-csi/internal/exec"
@@ -32,6 +33,7 @@ import (
3233
const (
3334
AutofsCvmfsRoot = "/cvmfs"
3435
AlienCachePath = "/cvmfs-aliencache"
36+
LocalCachePath = "/cvmfs-localcache"
3537
)
3638

3739
type Opts struct {
@@ -54,6 +56,100 @@ func cvmfsVersion() (string, error) {
5456
return string(bytes.TrimSpace(out)), nil
5557
}
5658

59+
func removeDirContents(dirName string) error {
60+
contents, err := os.ReadDir(dirName)
61+
if err != nil {
62+
// Ignore ENOENT.
63+
if os.IsNotExist(err) {
64+
return nil
65+
}
66+
67+
return err
68+
}
69+
70+
for i := range contents {
71+
if err = os.RemoveAll(path.Join(dirName, contents[i].Name())); err != nil {
72+
return err
73+
}
74+
}
75+
76+
return nil
77+
}
78+
79+
func readEffectiveDefaultCvmfsConfig() (map[string]string, error) {
80+
out, err := exec.Output(goexec.Command(
81+
"cvmfs_config",
82+
"showconfig",
83+
// Show only non-empty config parameters.
84+
"-s",
85+
// Repository name. We use "x" as a dummy value,
86+
// as we don't care at this point, and need only
87+
// the default, not repository-specific values.
88+
"x",
89+
))
90+
91+
if err != nil {
92+
execErr, ok := err.(*goexec.ExitError)
93+
if !ok {
94+
return nil, err
95+
}
96+
97+
// The command normally exits with code 1, because
98+
// the repository "x" does not exist. The output is
99+
// still valid.
100+
if execErr.ExitCode() != 1 {
101+
return nil, err
102+
}
103+
}
104+
105+
var (
106+
buf = bytes.NewBuffer(out)
107+
sc = bufio.NewScanner(buf)
108+
config = make(map[string]string)
109+
)
110+
111+
for sc.Scan() {
112+
// Each line is expected to be in the following format:
113+
//
114+
// <Key>=<Value>
115+
//
116+
// when there is no comment, or
117+
//
118+
// <Key>=<Value> # from <Source filepath>
119+
//
120+
// when there is a comment.
121+
line := sc.Bytes()
122+
123+
// Find the equal sign '=' where the Key is separated from the Value.
124+
125+
eqTok := bytes.IndexByte(line, '=')
126+
if eqTok == -1 {
127+
log.Debugf("Read unexpected CVMFS config parameter \"%s\", missing '='", line)
128+
continue
129+
}
130+
131+
// Cut the comment from the Value, if any.
132+
133+
valEndIdx := len(line)
134+
const commentPrefix = " #"
135+
136+
if commentTok := bytes.LastIndexByte(line, '#'); commentTok != -1 {
137+
if bytes.HasSuffix(line[:commentTok+1], []byte(commentPrefix)) {
138+
valEndIdx = commentTok - len(commentPrefix) + 1
139+
}
140+
}
141+
142+
// Add to the map.
143+
144+
key := string(line[:eqTok])
145+
value := string(line[eqTok+1 : valEndIdx])
146+
147+
config[key] = value
148+
}
149+
150+
return config, nil
151+
}
152+
57153
func setupCvmfs(o *Opts) error {
58154
if o.HasAlienCache {
59155
// Make sure the volume is writable by CVMFS processes.
@@ -62,7 +158,28 @@ func setupCvmfs(o *Opts) error {
62158
}
63159
}
64160

161+
// Clean up local cache. It may be dirty after previous nodeplugin Pod runs.
162+
163+
log.Debugf("Cleaning up local cache directory %s...", LocalCachePath)
164+
165+
cvmfsConfig, err := readEffectiveDefaultCvmfsConfig()
166+
if err != nil {
167+
return fmt.Errorf("failed to read CVMFS config: %v", err)
168+
}
169+
170+
cacheDir := cvmfsConfig["CVMFS_CACHE_BASE"]
171+
if cacheDir == "" {
172+
cacheDir = LocalCachePath
173+
}
174+
175+
if err := removeDirContents(cacheDir); err != nil {
176+
return fmt.Errorf("failed to clean up local cache directory %s: %v", cacheDir, err)
177+
}
178+
179+
log.Debugf("Finished cleaning up local cache directory %s", cacheDir)
180+
65181
// Set up configuration required for autofs with CVMFS to work properly.
182+
66183
if _, err := exec.CombinedOutput(goexec.Command("cvmfs_config", "setup", "nocfgmod", "nostart", "noautofs")); err != nil {
67184
return fmt.Errorf("failed to setup CVMFS config: %v", err)
68185
}

0 commit comments

Comments
 (0)