btrfs snapshot gc

This commit is contained in:
bigeagle 2014-10-18 23:24:08 +08:00
parent 61c408c8e4
commit 8ddac716d5
7 changed files with 83 additions and 11 deletions

View File

@ -13,7 +13,7 @@ max_retry = 2
[btrfs]
service_dir = {mirror_root}/{mirror_name}/_current
working_dir = {mirror_root}/{mirror_name}/_working
tmp_dir = {mirror_root}/{mirror_name}/_tmp
gc_dir = {mirror_root}/{mirror_name}/_gc_{timestamp}
# rmirror:archlinux]

View File

@ -0,0 +1,11 @@
[Unit]
Description=Delete garbage subvolumes generated by tunasync
Requires = network.target
After = network.target
[Service]
Type=simple
ExecStart=/home/tuna/.virtualenvs/tunasync/bin/python -u /home/tuna/tunasync/tunasync_snapshot_gc.py %i
[Install]
WantedBy = multi-user.target

View File

@ -0,0 +1,9 @@
[Unit]
Description=TUNAsync GC every 10 minutes
[Timer]
OnUnitActiveSec=10min
Unit=tunasync-snapshot-gc@%i.service
[Install]
WantedBy=multi-user.target

13
systemd/tunasync.service Normal file
View File

@ -0,0 +1,13 @@
[Unit]
Description = TUNA mirrors sync daemon
Requires = network.target
After = network.target
[Service]
ExecStart = /home/tuna/.virtualenvs/tunasync/bin/python -u /home/tuna/tunasync/tunasync.py -c /etc/tunasync.ini
KillSignal = SIGTERM
ExecReload = /bin/kill -SIGUSR1 $MAINPID
Environment = "HOME=/home/tuna"
[Install]
WantedBy = multi-user.target

View File

@ -2,6 +2,7 @@
# -*- coding:utf-8 -*-
import sh
import os
from datetime import datetime
from .hook import JobHook
@ -11,10 +12,10 @@ class BtrfsVolumeError(Exception):
class BtrfsHook(JobHook):
def __init__(self, service_dir, working_dir, tmp_dir):
def __init__(self, service_dir, working_dir, gc_dir):
self.service_dir = service_dir
self.working_dir = working_dir
self.tmp_dir = tmp_dir
self.gc_dir = gc_dir
def before_job(self):
self._create_working_snapshot()
@ -44,13 +45,15 @@ class BtrfsHook(JobHook):
def _commit_changes(self):
self._ensure_subvolume()
self._ensure_subvolume()
out = sh.mv(self.service_dir, self.tmp_dir)
gc_dir = self.gc_dir.format(timestamp=datetime.now().strftime("%s"))
out = sh.mv(self.service_dir, gc_dir)
assert out.exit_code == 0 and out.stderr == ""
out = sh.mv(self.working_dir, self.service_dir)
assert out.exit_code == 0 and out.stderr == ""
# print("btrfs subvolume delete {}".format(self.tmp_dir))
sh.sleep(3)
out = sh.btrfs("subvolume", "delete", self.tmp_dir)
assert out.exit_code == 0 and out.stderr == ""
# sh.sleep(3)
# out = sh.btrfs("subvolume", "delete", self.tmp_dir)
# assert out.exit_code == 0 and out.stderr == ""
# vim: ts=4 sw=4 sts=4 expandtab

View File

@ -113,11 +113,11 @@ class MirrorConfig(object):
mirror_root=parent.mirror_root,
mirror_name=self.name
)
tmp_dir = parent.btrfs_tmp_dir_tmpl.format(
gc_dir = parent.btrfs_gc_dir_tmpl.format(
mirror_root=parent.mirror_root,
mirror_name=self.name
)
hooks.append(BtrfsHook(service_dir, working_dir, tmp_dir))
hooks.append(BtrfsHook(service_dir, working_dir, gc_dir))
return hooks
@ -152,8 +152,8 @@ class TUNASync(object):
"btrfs", "service_dir")
self.btrfs_working_dir_tmpl = self._settings.get(
"btrfs", "working_dir")
self.btrfs_tmp_dir_tmpl = self._settings.get(
"btrfs", "tmp_dir")
self.btrfs_gc_dir_tmpl = self._settings.get(
"btrfs", "gc_dir")
def hooks(self):
return []

36
tunasync_snapshot_gc.py Normal file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env python2
# -*- coding:utf-8 -*-
import re
import sh
import os
import argparse
if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="tunasync_snapshot_gc")
parser.add_argument("--max-level", type=int, default=2, help="max walk level to find garbage snapshots")
parser.add_argument("--pattern", default=r"^_gc_\d+", help="pattern to match garbage snapshots")
parser.add_argument("mirror_root", help="tunasync mirror root")
args = parser.parse_args()
pattern = re.compile(args.pattern)
def walk(_dir, level=1):
if level > 2:
return
for fname in os.listdir(_dir):
abs_fname = os.path.join(_dir, fname)
if os.path.isdir(abs_fname):
if pattern.match(fname):
print("GC: {}".format(abs_fname))
try:
ret = sh.btrfs("subvolume", "delete", abs_fname)
except sh.ErrorReturnCode:
print("Error: {}".format(ret.stderr))
else:
walk(abs_fname, level+1)
walk(args.mirror_root)
# vim: ts=4 sw=4 sts=4 expandtab