btrfs_snapshot.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. #!/usr/bin/env python2
  2. # -*- coding:utf-8 -*-
  3. import sh
  4. import os
  5. class BtrfsVolumeError(Exception):
  6. pass
  7. class BtrfsHook(object):
  8. def __init__(self, service_dir, working_dir, tmp_dir):
  9. self.service_dir = service_dir
  10. self.working_dir = working_dir
  11. self.tmp_dir = tmp_dir
  12. def before_job(self):
  13. self._create_working_snapshot()
  14. def after_job(self):
  15. self._commit_changes()
  16. def _ensure_subvolume(self):
  17. # print(self.service_dir)
  18. try:
  19. ret = sh.btrfs("subvolume", "show", self.service_dir)
  20. except Exception, e:
  21. print(e)
  22. raise BtrfsVolumeError("Invalid subvolume")
  23. if ret.stderr != '':
  24. raise BtrfsVolumeError("Invalid subvolume")
  25. def _create_working_snapshot(self):
  26. self._ensure_subvolume()
  27. if os.path.exists(self.working_dir):
  28. print("Warning: working dir existed, are you sure no rsync job is running?")
  29. else:
  30. # print("btrfs subvolume snapshot {} {}".format(self.service_dir, self.working_dir))
  31. sh.btrfs("subvolume", "snapshot", self.service_dir, self.working_dir)
  32. def _commit_changes(self):
  33. self._ensure_subvolume()
  34. self._ensure_subvolume()
  35. out = sh.mv(self.service_dir, self.tmp_dir)
  36. assert out.exit_code == 0 and out.stderr == ""
  37. out = sh.mv(self.working_dir, self.service_dir)
  38. assert out.exit_code == 0 and out.stderr == ""
  39. # print("btrfs subvolume delete {}".format(self.tmp_dir))
  40. out = sh.btrfs("subvolume", "delete", self.tmp_dir)
  41. assert out.exit_code == 0 and out.stderr == ""
  42. # vim: ts=4 sw=4 sts=4 expandtab