mirror of
https://github.com/zrepl/zrepl.git
synced 2025-08-16 01:47:50 +02:00
WIP: Switch to new config format.
Don't use jobrun for daemon, just call JobDo() once, the job must organize stuff itself. Sacrifice all the oneshot commands, they will be reintroduced as client-calls to the daemon.
This commit is contained in:
140
cmd/prune.go
140
cmd/prune.go
@ -1,140 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zrepl/zrepl/util"
|
||||
"github.com/zrepl/zrepl/zfs"
|
||||
)
|
||||
|
||||
var pruneArgs struct {
|
||||
job string
|
||||
dryRun bool
|
||||
}
|
||||
|
||||
var PruneCmd = &cobra.Command{
|
||||
Use: "prune",
|
||||
Short: "perform pruning",
|
||||
Run: cmdPrune,
|
||||
}
|
||||
|
||||
func init() {
|
||||
PruneCmd.Flags().StringVar(&pruneArgs.job, "job", "", "job to run")
|
||||
PruneCmd.Flags().BoolVarP(&pruneArgs.dryRun, "dryrun", "n", false, "dry run")
|
||||
RootCmd.AddCommand(PruneCmd)
|
||||
}
|
||||
|
||||
func cmdPrune(cmd *cobra.Command, args []string) {
|
||||
|
||||
if len(args) < 1 {
|
||||
log.Printf("must specify exactly one job as positional argument")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
job, ok := conf.Prunes[args[0]]
|
||||
if !ok {
|
||||
log.Printf("could not find prune job: %s", args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
log.Printf("Beginning prune job:\n%s", job)
|
||||
ctx := PruneContext{job, time.Now(), pruneArgs.dryRun}
|
||||
err := doPrune(ctx, log)
|
||||
if err != nil {
|
||||
log.Printf("Prune job failed with error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type PruneContext struct {
|
||||
Prune *Prune
|
||||
Now time.Time
|
||||
DryRun bool
|
||||
}
|
||||
|
||||
type retentionGridAdaptor struct {
|
||||
zfs.FilesystemVersion
|
||||
}
|
||||
|
||||
func (a retentionGridAdaptor) Date() time.Time {
|
||||
return a.Creation
|
||||
}
|
||||
|
||||
func (a retentionGridAdaptor) LessThan(b util.RetentionGridEntry) bool {
|
||||
return a.CreateTXG < b.(retentionGridAdaptor).CreateTXG
|
||||
}
|
||||
|
||||
func doPrune(ctx PruneContext, log Logger) error {
|
||||
|
||||
if ctx.DryRun {
|
||||
log.Printf("doing dry run")
|
||||
}
|
||||
|
||||
prune := ctx.Prune
|
||||
|
||||
// ZFSListSnapsFiltered --> todo can extend fsfilter or need new? Have already something per fs
|
||||
// Dedicated snapshot object? Adaptor object to FilesystemVersion?
|
||||
|
||||
filesystems, err := zfs.ZFSListMapping(prune.DatasetFilter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error applying filesystem filter: %s", err)
|
||||
}
|
||||
|
||||
for _, fs := range filesystems {
|
||||
|
||||
fsversions, err := zfs.ZFSListFilesystemVersions(fs, prune.SnapshotFilter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error listing filesytem versions of %s: %s", fs, err)
|
||||
}
|
||||
|
||||
if len(fsversions) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
adaptors := make([]util.RetentionGridEntry, len(fsversions))
|
||||
for fsv := range fsversions {
|
||||
adaptors[fsv] = retentionGridAdaptor{fsversions[fsv]}
|
||||
}
|
||||
|
||||
sort.SliceStable(adaptors, func(i, j int) bool {
|
||||
return adaptors[i].LessThan(adaptors[j])
|
||||
})
|
||||
ctx.Now = adaptors[len(adaptors)-1].Date()
|
||||
|
||||
describe := func(a retentionGridAdaptor) string {
|
||||
timeSince := a.Creation.Sub(ctx.Now)
|
||||
const day time.Duration = 24 * time.Hour
|
||||
days := timeSince / day
|
||||
remainder := timeSince % day
|
||||
return fmt.Sprintf("%s@%dd%s from now", a.ToAbsPath(fs), days, remainder)
|
||||
}
|
||||
|
||||
keep, remove := prune.RetentionPolicy.FitEntries(ctx.Now, adaptors)
|
||||
for _, a := range remove {
|
||||
r := a.(retentionGridAdaptor)
|
||||
log.Printf("remove %s", describe(r))
|
||||
// do echo what we'll do and exec zfs destroy if not dry run
|
||||
// special handling for EBUSY (zfs hold)
|
||||
// error handling for clones? just echo to cli, skip over, and exit with non-zero status code (we're idempotent)
|
||||
if !ctx.DryRun {
|
||||
err := zfs.ZFSDestroyFilesystemVersion(fs, r.FilesystemVersion)
|
||||
if err != nil {
|
||||
// handle
|
||||
log.Printf("error: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, a := range keep {
|
||||
r := a.(retentionGridAdaptor)
|
||||
log.Printf("would keep %s", describe(r))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
Reference in New Issue
Block a user