Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc26f8bf

Browse files
committed
fix: avoid forced snapshot cleanup (#231):
Take into account related clones while clean up snapshots.check all snapshots that we are going to delete and skip those that have active dependent clones.
1 parentfc1817c commitc26f8bf

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-3
lines changed

‎pkg/services/provision/thinclones/zfs/zfs.go‎

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strconv"
1111
"strings"
1212
"time"
13+
"unicode"
1314

1415
"github.com/pkg/errors"
1516

@@ -305,12 +306,21 @@ func (m *Manager) DestroySnapshot(snapshotName string) error {
305306
returnnil
306307
}
307308

308-
// CleanupSnapshots destroys old snapshots considering retention limit.
309+
// CleanupSnapshots destroys old snapshots considering retention limit and related clones.
309310
func (m*Manager)CleanupSnapshots(retentionLimitint) ([]string,error) {
311+
clonesCmd:=fmt.Sprintf("zfs list -S clones -o name,origin -H -r %s",m.config.Pool.Name)
312+
313+
clonesOutput,err:=m.runner.Run(clonesCmd)
314+
iferr!=nil {
315+
returnnil,errors.Wrap(err,"failed to list snapshots")
316+
}
317+
318+
busySnapshots:=m.getBusySnapshotList(clonesOutput)
319+
310320
cleanupCmd:=fmt.Sprintf(
311-
"zfs list -t snapshot -H -o name -s %s -s creation -r %s | grep -v clone | head -n -%d "+
321+
"zfs list -t snapshot -H -o name -s %s -s creation -r %s | grep -v clone | head -n -%d%s"+
312322
"| xargs -n1 --no-run-if-empty zfs destroy -R ",
313-
dataStateAtLabel,m.config.Pool.Name,retentionLimit)
323+
dataStateAtLabel,m.config.Pool.Name,retentionLimit,excludeBusySnapshots(busySnapshots))
314324

315325
out,err:=m.runner.Run(cleanupCmd)
316326
iferr!=nil {
@@ -322,6 +332,52 @@ func (m *Manager) CleanupSnapshots(retentionLimit int) ([]string, error) {
322332
returnlines,nil
323333
}
324334

335+
func (m*Manager)getBusySnapshotList(clonesOutputstring) []string {
336+
systemClones,userClones:=make(map[string]string),make(map[string]struct{})
337+
338+
userClonePrefix:=m.config.Pool.Name+"/"+util.ClonePrefix
339+
340+
for_,line:=rangestrings.Split(clonesOutput,"\n") {
341+
cloneLine:=strings.FieldsFunc(line,unicode.IsSpace)
342+
343+
iflen(cloneLine)!=2||cloneLine[1]=="-" {
344+
continue
345+
}
346+
347+
ifstrings.HasPrefix(cloneLine[0],userClonePrefix) {
348+
origin:=cloneLine[1]
349+
350+
ifidx:=strings.Index(origin,"@");idx!=-1 {
351+
origin=origin[:idx]
352+
}
353+
354+
userClones[origin]=struct{}{}
355+
356+
continue
357+
}
358+
359+
systemClones[cloneLine[0]]=cloneLine[1]
360+
}
361+
362+
busySnapshots:=make([]string,0,len(userClones))
363+
364+
foruserClone:=rangeuserClones {
365+
busySnapshots=append(busySnapshots,systemClones[userClone])
366+
}
367+
368+
returnbusySnapshots
369+
}
370+
371+
// excludeBusySnapshots excludes snapshots that match a pattern by name.
372+
// The exclusion logic relies on the fact that snapshots have unique substrings (timestamps).
373+
funcexcludeBusySnapshots(busySnapshots []string)string {
374+
iflen(busySnapshots)==0 {
375+
return""
376+
}
377+
378+
returnfmt.Sprintf("| grep -Ev '%s' ",strings.Join(busySnapshots,"|"))
379+
}
380+
325381
// GetSessionState returns a state of a session.
326382
func (m*Manager)GetSessionState(namestring) (*resources.SessionState,error) {
327383
entries,err:=m.listFilesystems(m.config.Pool.Name)

‎pkg/services/provision/thinclones/zfs/zfs_test.go‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,47 @@ func TestFailedListClones(t *testing.T) {
113113
assert.Nil(t,cloneNames)
114114
assert.EqualError(t,err,"failed to list clones: runner error")
115115
}
116+
117+
funcTestBusySnapshotList(t*testing.T) {
118+
m:=Manager{config:Config{Pool:&resources.Pool{Name:"dblab_pool"}}}
119+
120+
out:=`dblab_pool-
121+
dblab_pool/clone_pre_20210127105215dblab_pool@snapshot_20210127105215_pre
122+
dblab_pool/clone_pre_20210127113000dblab_pool@snapshot_20210127113000_pre
123+
dblab_pool/clone_pre_20210127120000dblab_pool@snapshot_20210127120000_pre
124+
dblab_pool/clone_pre_20210127123000dblab_pool@snapshot_20210127123000_pre
125+
dblab_pool/clone_pre_20210127130000dblab_pool@snapshot_20210127130000_pre
126+
dblab_pool/clone_pre_20210127133000dblab_pool@snapshot_20210127133000_pre
127+
dblab_pool/clone_pre_20210127140000dblab_pool@snapshot_20210127140000_pre
128+
dblab_pool/dblab_clone_6000dblab_pool/clone_pre_20210127133000@snapshot_20210127133008
129+
dblab_pool/dblab_clone_6001dblab_pool/clone_pre_20210127123000@snapshot_20210127133008
130+
`
131+
expected:= []string{"dblab_pool@snapshot_20210127133000_pre","dblab_pool@snapshot_20210127123000_pre"}
132+
133+
list:=m.getBusySnapshotList(out)
134+
assert.Equal(t,expected,list)
135+
}
136+
137+
funcTestExcludingBusySnapshots(t*testing.T) {
138+
testCases:= []struct {
139+
snapshotList []string
140+
resultstring
141+
}{
142+
{
143+
snapshotList: []string{},
144+
result:"",
145+
},
146+
{
147+
snapshotList: []string{"dblab_pool@snapshot_20210127133000_pre"},
148+
result:"| grep -Ev 'dblab_pool@snapshot_20210127133000_pre' ",
149+
},
150+
{
151+
snapshotList: []string{"dblab_pool@snapshot_20210127133000_pre","dblab_pool@snapshot_20210127123000_pre"},
152+
result:"| grep -Ev 'dblab_pool@snapshot_20210127133000_pre|dblab_pool@snapshot_20210127123000_pre' ",
153+
},
154+
}
155+
156+
for_,tc:=rangetestCases {
157+
assert.Equal(t,tc.result,excludeBusySnapshots(tc.snapshotList))
158+
}
159+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp