mirror of
https://github.com/psy0rz/zfs_autobackup.git
synced 2025-04-23 23:00:53 +03:00
423 lines
17 KiB
Python
423 lines
17 KiB
Python
from basetest import *
|
|
|
|
|
|
class TestZfsAutobackup40(unittest2.TestCase):
|
|
"""various new 4.0 features"""
|
|
|
|
def setUp(self):
|
|
prepare_zpools()
|
|
self.longMessage = True
|
|
|
|
def test_no_bookmark_source_support(self):
|
|
"""test if everything is fine when source has no bookmark support (has no features at all even)"""
|
|
|
|
subprocess.check_call("zpool destroy test_source1", shell=True)
|
|
subprocess.check_call("zpool create -d test_source1 /dev/ram0", shell=True)
|
|
shelltest("zpool get all test_source1")
|
|
subprocess.check_call("zfs create -p test_source1/fs1/sub", shell=True) # recreate with no features at all
|
|
subprocess.check_call("zfs set autobackup:test=true test_source1/fs1", shell=True)
|
|
|
|
with mocktime("20101111000001"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty".split(" ")).run())
|
|
|
|
# should fallback on holds on the source snapshot
|
|
r = shelltest("zfs holds test_source1/fs1@test-20101111000001")
|
|
self.assertIn("zfs_autobackup:test", r)
|
|
|
|
def test_no_bookmark_target_support(self):
|
|
"""test if everything is fine when target has no bookmark support (has no features at all even)"""
|
|
# NOTE: not sure if its ok if only the source supports bookmarks, so currently zfs-autobackup requires both sides to support bookmarks to enable it.
|
|
|
|
subprocess.check_call("zpool destroy test_target1", shell=True)
|
|
subprocess.check_call("zpool create -d test_target1 /dev/ram2", shell=True)
|
|
|
|
with mocktime("20101111000001"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty".split(" ")).run())
|
|
|
|
# should fallback on holds on the source snapshot
|
|
r = shelltest("zfs holds test_source1/fs1@test-20101111000001")
|
|
self.assertIn("zfs_autobackup:test", r)
|
|
|
|
def test_select_bookmark_or_snapshot(self):
|
|
"""test if zfs autobackup chooses the most recent common matching dataset when there are both bookmarks and snapshots, some with the wrong GUID"""
|
|
|
|
with mocktime("20101111000001"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty".split(" ")).run())
|
|
|
|
target_guid = shelltest("zfs get -H -o value guid test_target1").strip()
|
|
|
|
# destroy stuff and see if it still selects the correct ones
|
|
shelltest("zfs destroy test_source2/fs2/sub@test-20101111000001")
|
|
shelltest("zfs destroy test_source1/fs1/sub#test-20101111000001_" + target_guid)
|
|
|
|
# replace bookmark with incorrect GUID, should fallback to snapshot
|
|
# NOTE: the incorrect bookmark should be ignored and not destroyed.
|
|
shelltest("zfs destroy test_source1/fs1#test-20101111000001_" + target_guid)
|
|
shelltest("zfs snapshot test_source1/fs1@wrong")
|
|
shelltest("zfs bookmark test_source1/fs1@wrong \#test-20101111000001_" + target_guid)
|
|
shelltest("zfs destroy test_source1/fs1@wrong")
|
|
|
|
with mocktime("20101111000002"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty".split(" ")).run())
|
|
|
|
r = shelltest("zfs list -H -o name -r -t all " + TEST_POOLS)
|
|
self.assertRegexpMatches(r, """
|
|
test_source1
|
|
test_source1/fs1
|
|
test_source1/fs1@test-20101111000001
|
|
test_source1/fs1@test-20101111000002
|
|
test_source1/fs1#test-20101111000001_[0-9]*
|
|
test_source1/fs1#test-20101111000002_[0-9]*
|
|
test_source1/fs1/sub
|
|
test_source1/fs1/sub@test-20101111000001
|
|
test_source1/fs1/sub@test-20101111000002
|
|
test_source1/fs1/sub#test-20101111000002_[0-9]*
|
|
test_source2
|
|
test_source2/fs2
|
|
test_source2/fs2/sub
|
|
test_source2/fs2/sub@test-20101111000002
|
|
test_source2/fs2/sub#test-20101111000002_[0-9]*
|
|
test_source2/fs3
|
|
test_source2/fs3/sub
|
|
test_target1
|
|
test_target1/test_source1
|
|
test_target1/test_source1/fs1
|
|
test_target1/test_source1/fs1@test-20101111000001
|
|
test_target1/test_source1/fs1@test-20101111000002
|
|
test_target1/test_source1/fs1/sub
|
|
test_target1/test_source1/fs1/sub@test-20101111000001
|
|
test_target1/test_source1/fs1/sub@test-20101111000002
|
|
test_target1/test_source2
|
|
test_target1/test_source2/fs2
|
|
test_target1/test_source2/fs2/sub
|
|
test_target1/test_source2/fs2/sub@test-20101111000001
|
|
test_target1/test_source2/fs2/sub@test-20101111000002
|
|
""")
|
|
|
|
# while we're here, check that there are no holds on source common snapshot (since bookmarks replace holds on source side)
|
|
r = shelltest("zfs holds test_source2/fs2/sub@test-20101111000002")
|
|
self.assertNotIn("zfs_autobackup:test", r)
|
|
|
|
def test_disable_bookmarks(self):
|
|
"""test if we can disable it on an existing backup with bookmarks, with --no-bookmarks and get the old behaviour (holds on source)"""
|
|
|
|
# first with bookmarks enabled
|
|
with mocktime("20101111000001"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty".split(" ")).run())
|
|
|
|
r = shelltest("zfs list -H -o name -r -t all test_source1")
|
|
self.assertRegexpMatches(r, """
|
|
test_source1
|
|
test_source1/fs1
|
|
test_source1/fs1@test-20101111000001
|
|
test_source1/fs1#test-20101111000001_[0-9]*
|
|
test_source1/fs1/sub
|
|
test_source1/fs1/sub@test-20101111000001
|
|
test_source1/fs1/sub#test-20101111000001_[0-9]*
|
|
""")
|
|
|
|
# disable it (this should not touch the old bookmark)
|
|
with mocktime("20101111000002"):
|
|
self.assertFalse(ZfsAutobackup(
|
|
"test test_target1 --no-progress --verbose --allow-empty --no-bookmarks".split(" ")).run())
|
|
|
|
r = shelltest("zfs list -H -o name -r -t all test_source1")
|
|
self.assertRegexpMatches(r, """
|
|
test_source1
|
|
test_source1/fs1
|
|
test_source1/fs1@test-20101111000001
|
|
test_source1/fs1@test-20101111000002
|
|
test_source1/fs1#test-20101111000001_[0-9]*
|
|
test_source1/fs1/sub
|
|
test_source1/fs1/sub@test-20101111000001
|
|
test_source1/fs1/sub@test-20101111000002
|
|
test_source1/fs1/sub#test-20101111000001_[0-9]*
|
|
""")
|
|
|
|
# re-enable (now the old bookmark should be still left alone)
|
|
with mocktime("20101111000003"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty".split(" ")).run())
|
|
|
|
r = shelltest("zfs list -H -o name -r -t all test_source1")
|
|
self.assertRegexpMatches(r, """
|
|
test_source1
|
|
test_source1/fs1
|
|
test_source1/fs1@test-20101111000001
|
|
test_source1/fs1@test-20101111000002
|
|
test_source1/fs1@test-20101111000003
|
|
test_source1/fs1#test-20101111000001_[0-9]*
|
|
test_source1/fs1#test-20101111000003_[0-9]*
|
|
test_source1/fs1/sub
|
|
test_source1/fs1/sub@test-20101111000001
|
|
test_source1/fs1/sub@test-20101111000002
|
|
test_source1/fs1/sub@test-20101111000003
|
|
test_source1/fs1/sub#test-20101111000001_[0-9]*
|
|
test_source1/fs1/sub#test-20101111000003_[0-9]*
|
|
""")
|
|
|
|
def test_tags(self):
|
|
with mocktime("20101111000001"):
|
|
self.assertFalse(
|
|
ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty --tag test1".split(" ")).run())
|
|
|
|
with mocktime("20101111000002"):
|
|
self.assertFalse(
|
|
ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty --tag test2".split(" ")).run())
|
|
|
|
with mocktime("20101111000003"):
|
|
# make sure the thinner sees and cleans up the old snaphots that have a tag
|
|
self.assertFalse(ZfsAutobackup(
|
|
"test test_target1 --no-progress --verbose --allow-empty --keep-source=2 --keep-target=2".split(
|
|
" ")).run())
|
|
|
|
r = shelltest("zfs list -H -r -t snapshot -o name " + TEST_POOLS)
|
|
|
|
self.assertMultiLineEqual(r, """
|
|
test_source1/fs1@test-20101111000002_test2
|
|
test_source1/fs1@test-20101111000003
|
|
test_source1/fs1/sub@test-20101111000002_test2
|
|
test_source1/fs1/sub@test-20101111000003
|
|
test_source2/fs2/sub@test-20101111000002_test2
|
|
test_source2/fs2/sub@test-20101111000003
|
|
test_target1/test_source1/fs1@test-20101111000002_test2
|
|
test_target1/test_source1/fs1@test-20101111000003
|
|
test_target1/test_source1/fs1/sub@test-20101111000002_test2
|
|
test_target1/test_source1/fs1/sub@test-20101111000003
|
|
test_target1/test_source2/fs2/sub@test-20101111000002_test2
|
|
test_target1/test_source2/fs2/sub@test-20101111000003
|
|
""")
|
|
|
|
def test_double_send_bookmark(self):
|
|
"""test sending the same snaphots to 2 targets, and check if they each use their own bookmark and delete them correctly."""
|
|
|
|
shelltest("zfs create test_target1/a")
|
|
shelltest("zfs create test_target1/b")
|
|
|
|
# full
|
|
with mocktime("20101111000001"):
|
|
self.assertFalse(
|
|
ZfsAutobackup(
|
|
"test test_target1/a --no-progress --verbose --allow-empty --debug --tag tagA".split(" ")).run())
|
|
|
|
# increment, should be from bookmark
|
|
with mocktime("20101111000002"):
|
|
self.assertFalse(
|
|
ZfsAutobackup(
|
|
"test test_target1/a --no-progress --verbose --allow-empty --tag tagB".split(" ")).run())
|
|
|
|
# to target b, now each has one full + two incrementals, which should be from their own bookmarks.
|
|
with mocktime("20101111000003"):
|
|
self.assertFalse(
|
|
ZfsAutobackup(
|
|
"test test_target1/b --no-progress --verbose --allow-empty".split(
|
|
" ")).run())
|
|
|
|
# result:
|
|
# for target a the bookmarks should be at 20101111000002, for target b the bookmarks should be at 20101111000003
|
|
r = shelltest("zfs list -H -r -t all -o name " + TEST_POOLS)
|
|
|
|
self.assertRegexpMatches(r, """
|
|
test_source1
|
|
test_source1/fs1
|
|
test_source1/fs1@test-20101111000001_tagA
|
|
test_source1/fs1@test-20101111000002_tagB
|
|
test_source1/fs1@test-20101111000003
|
|
test_source1/fs1#test-20101111000002_[0-9]*
|
|
test_source1/fs1#test-20101111000003_[0-9]*
|
|
test_source1/fs1/sub
|
|
test_source1/fs1/sub@test-20101111000001_tagA
|
|
test_source1/fs1/sub@test-20101111000002_tagB
|
|
test_source1/fs1/sub@test-20101111000003
|
|
test_source1/fs1/sub#test-20101111000002_[0-9]*
|
|
test_source1/fs1/sub#test-20101111000003_[0-9]*
|
|
test_source2
|
|
test_source2/fs2
|
|
test_source2/fs2/sub
|
|
test_source2/fs2/sub@test-20101111000001_tagA
|
|
test_source2/fs2/sub@test-20101111000002_tagB
|
|
test_source2/fs2/sub@test-20101111000003
|
|
test_source2/fs2/sub#test-20101111000002_[0-9]*
|
|
test_source2/fs2/sub#test-20101111000003_[0-9]*
|
|
test_source2/fs3
|
|
test_source2/fs3/sub
|
|
test_target1
|
|
test_target1/a
|
|
test_target1/a/test_source1
|
|
test_target1/a/test_source1/fs1
|
|
test_target1/a/test_source1/fs1@test-20101111000001_tagA
|
|
test_target1/a/test_source1/fs1@test-20101111000002_tagB
|
|
test_target1/a/test_source1/fs1/sub
|
|
test_target1/a/test_source1/fs1/sub@test-20101111000001_tagA
|
|
test_target1/a/test_source1/fs1/sub@test-20101111000002_tagB
|
|
test_target1/a/test_source2
|
|
test_target1/a/test_source2/fs2
|
|
test_target1/a/test_source2/fs2/sub
|
|
test_target1/a/test_source2/fs2/sub@test-20101111000001_tagA
|
|
test_target1/a/test_source2/fs2/sub@test-20101111000002_tagB
|
|
test_target1/b
|
|
test_target1/b/test_source1
|
|
test_target1/b/test_source1/fs1
|
|
test_target1/b/test_source1/fs1@test-20101111000001_tagA
|
|
test_target1/b/test_source1/fs1@test-20101111000002_tagB
|
|
test_target1/b/test_source1/fs1@test-20101111000003
|
|
test_target1/b/test_source1/fs1/sub
|
|
test_target1/b/test_source1/fs1/sub@test-20101111000001_tagA
|
|
test_target1/b/test_source1/fs1/sub@test-20101111000002_tagB
|
|
test_target1/b/test_source1/fs1/sub@test-20101111000003
|
|
test_target1/b/test_source2
|
|
test_target1/b/test_source2/fs2
|
|
test_target1/b/test_source2/fs2/sub
|
|
test_target1/b/test_source2/fs2/sub@test-20101111000001_tagA
|
|
test_target1/b/test_source2/fs2/sub@test-20101111000002_tagB
|
|
test_target1/b/test_source2/fs2/sub@test-20101111000003
|
|
""")
|
|
|
|
def test_missing_common_bookmark(self):
|
|
with mocktime("20101111000000"):
|
|
self.assertFalse(ZfsAutobackup(
|
|
"test test_target1 --no-progress --verbose --allow-empty --no-holds".split(" ")).run())
|
|
|
|
# remove common bookmark
|
|
bookmark = shelltest("zfs list -H -o name -t bookmark test_source1/fs1").strip()
|
|
shelltest("zfs destroy " + bookmark)
|
|
|
|
with mocktime("20101111000001"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty".split(" ")).run())
|
|
|
|
def test_keepsource0target10queuedsend_bookmarks(self):
|
|
"""Test if thinner doesnt destroy too much early on if there are no common snapshots YET. Issue #84"""
|
|
# new behavior, with bookmarks. (will delete common snapshot, since there is a bookmark)
|
|
|
|
with mocktime("20101111000000"):
|
|
self.assertFalse(ZfsAutobackup(
|
|
"test test_target1 --no-progress --verbose --keep-source=0 --keep-target=10 --allow-empty --no-send".split(
|
|
" ")).run())
|
|
|
|
with mocktime("20101111000001"):
|
|
self.assertFalse(ZfsAutobackup(
|
|
"test test_target1 --no-progress --verbose --keep-source=0 --keep-target=10 --allow-empty --no-send".split(
|
|
" ")).run())
|
|
|
|
with mocktime("20101111000002"):
|
|
self.assertFalse(ZfsAutobackup(
|
|
"test test_target1 --no-progress --verbose --keep-source=0 --keep-target=10 --allow-empty".split(
|
|
" ")).run())
|
|
|
|
r = shelltest("zfs list -H -o name -r -t snapshot,filesystem " + TEST_POOLS)
|
|
self.assertMultiLineEqual(r, """
|
|
test_source1
|
|
test_source1/fs1
|
|
test_source1/fs1/sub
|
|
test_source2
|
|
test_source2/fs2
|
|
test_source2/fs2/sub
|
|
test_source2/fs3
|
|
test_source2/fs3/sub
|
|
test_target1
|
|
test_target1/test_source1
|
|
test_target1/test_source1/fs1
|
|
test_target1/test_source1/fs1@test-20101111000000
|
|
test_target1/test_source1/fs1@test-20101111000001
|
|
test_target1/test_source1/fs1@test-20101111000002
|
|
test_target1/test_source1/fs1/sub
|
|
test_target1/test_source1/fs1/sub@test-20101111000000
|
|
test_target1/test_source1/fs1/sub@test-20101111000001
|
|
test_target1/test_source1/fs1/sub@test-20101111000002
|
|
test_target1/test_source2
|
|
test_target1/test_source2/fs2
|
|
test_target1/test_source2/fs2/sub
|
|
test_target1/test_source2/fs2/sub@test-20101111000000
|
|
test_target1/test_source2/fs2/sub@test-20101111000001
|
|
test_target1/test_source2/fs2/sub@test-20101111000002
|
|
""")
|
|
|
|
def test_migrate_from_mismatching_bookmarkname(self):
|
|
"""test migration from a bookmark with a mismatching name."""
|
|
|
|
shelltest("zfs snapshot test_source1/fs1@migrate1")
|
|
shelltest("zfs create test_target1/test_source1")
|
|
shelltest("zfs send test_source1/fs1@migrate1| zfs recv test_target1/test_source1/fs1")
|
|
|
|
# make it so there is only the bookmark to migrate from, which a random non-matching name
|
|
shelltest("zfs bookmark test_source1/fs1@migrate1 \#randombookmarkname")
|
|
shelltest("zfs destroy test_source1/fs1@migrate1")
|
|
|
|
with mocktime("20101111000000"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --test".split(" ")).run())
|
|
|
|
with mocktime("20101111000000"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose".split(" ")).run())
|
|
|
|
r = shelltest("zfs list -H -o name -r -t snapshot,filesystem " + TEST_POOLS)
|
|
self.assertMultiLineEqual(r, """
|
|
test_source1
|
|
test_source1/fs1
|
|
test_source1/fs1@test-20101111000000
|
|
test_source1/fs1/sub
|
|
test_source1/fs1/sub@test-20101111000000
|
|
test_source2
|
|
test_source2/fs2
|
|
test_source2/fs2/sub
|
|
test_source2/fs2/sub@test-20101111000000
|
|
test_source2/fs3
|
|
test_source2/fs3/sub
|
|
test_target1
|
|
test_target1/test_source1
|
|
test_target1/test_source1/fs1
|
|
test_target1/test_source1/fs1@migrate1
|
|
test_target1/test_source1/fs1@test-20101111000000
|
|
test_target1/test_source1/fs1/sub
|
|
test_target1/test_source1/fs1/sub@test-20101111000000
|
|
test_target1/test_source2
|
|
test_target1/test_source2/fs2
|
|
test_target1/test_source2/fs2/sub
|
|
test_target1/test_source2/fs2/sub@test-20101111000000
|
|
""")
|
|
|
|
def test_migrate_from_mismatching_snapshotname(self):
|
|
"""test migration from a snapshot with a mismatching name."""
|
|
|
|
shelltest("zfs snapshot test_source1/fs1@migrate1")
|
|
shelltest("zfs create test_target1/test_source1")
|
|
shelltest("zfs send test_source1/fs1@migrate1| zfs recv test_target1/test_source1/fs1")
|
|
|
|
# rename it so the names mismatch and guid matching is needed to resolve it
|
|
shelltest("zfs rename test_source1/fs1@migrate1 test_source1/fs1@randomsnapshotname")
|
|
|
|
# testmode
|
|
with mocktime("20101111000000"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --test".split(" ")).run())
|
|
|
|
with mocktime("20101111000000"):
|
|
self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose".split(" ")).run())
|
|
|
|
r = shelltest("zfs list -H -o name -r -t snapshot,filesystem " + TEST_POOLS)
|
|
self.assertMultiLineEqual(r, """
|
|
test_source1
|
|
test_source1/fs1
|
|
test_source1/fs1@randomsnapshotname
|
|
test_source1/fs1@test-20101111000000
|
|
test_source1/fs1/sub
|
|
test_source1/fs1/sub@test-20101111000000
|
|
test_source2
|
|
test_source2/fs2
|
|
test_source2/fs2/sub
|
|
test_source2/fs2/sub@test-20101111000000
|
|
test_source2/fs3
|
|
test_source2/fs3/sub
|
|
test_target1
|
|
test_target1/test_source1
|
|
test_target1/test_source1/fs1
|
|
test_target1/test_source1/fs1@migrate1
|
|
test_target1/test_source1/fs1@test-20101111000000
|
|
test_target1/test_source1/fs1/sub
|
|
test_target1/test_source1/fs1/sub@test-20101111000000
|
|
test_target1/test_source2
|
|
test_target1/test_source2/fs2
|
|
test_target1/test_source2/fs2/sub
|
|
test_target1/test_source2/fs2/sub@test-20101111000000
|
|
""")
|
|
|
|
# TODO
|
|
# - check if holds and no-holds function ok when bookmarks are enabled
|