Skip to content

Commit

Permalink
bookmarks now use target dataset guid as tag, to allow sending to mul…
Browse files Browse the repository at this point in the history
…tiple destinations
  • Loading branch information
psy0rz committed Oct 7, 2024
1 parent 4e7679c commit 49069dd
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 16 deletions.
62 changes: 57 additions & 5 deletions tests/test_zfsautobackup34.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,25 +190,77 @@ def test_double_send_bookmark(self):
with mocktime("20101111000001"):
self.assertFalse(
ZfsAutobackup(
"test test_target1/a --no-progress --verbose --allow-empty --debug --tag tag1".split(" ")).run())
"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 tag1".split(" ")).run())
"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 --no-snapshot --allow-empty".split(
"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.assertMultiLineEqual(r, """
...
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
""")
26 changes: 15 additions & 11 deletions zfs_autobackup/ZfsDataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class ZfsDataset:
"""a zfs dataset (filesystem/volume/snapshot/clone) Note that a dataset
doesn't have to actually exist (yet/anymore) Also most properties are cached
for performance-reasons, but also to allow --test to function correctly.
A dataset 'name' is the full name as you would use it with zfs list.
Internally we use it in 3 parts: the prefix, suffix and tag.
(see respective properties below)
"""

# illegal properties per dataset type. these will be removed from --set-properties and --filter-properties
Expand Down Expand Up @@ -122,7 +126,7 @@ def rstrip_path(self, count):
return "/".join(self.split_path()[:-count])

@property
def filesystem_name(self):
def prefix(self):
"""filesystem part of the name (before the @)"""
if self.is_snapshot:
(filesystem, snapshot) = self.name.split("@")
Expand Down Expand Up @@ -286,7 +290,7 @@ def parent(self):
:rtype: ZfsDataset | None
"""
if self.is_snapshot:
return self.zfs_node.get_dataset(self.filesystem_name)
return self.zfs_node.get_dataset(self.prefix)
else:
stripped = self.rstrip_path(1)
if stripped:
Expand Down Expand Up @@ -683,7 +687,7 @@ def bookmark(self, tag):

self.debug("Bookmarking")

bookmark_name = "#" + self.tagless_suffix + self.zfs_node.tag_seperator + tag
bookmark_name = self.prefix + "#" + self.tagless_suffix + self.zfs_node.tag_seperator + tag
cmd = [
"zfs", "bookmark", self.name, bookmark_name
]
Expand Down Expand Up @@ -802,7 +806,6 @@ def send_pipe(self, features, prev_snapshot, resume_token, show_progress, raw, s

cmd.extend(send_pipes)

self.error(cmd)
output_pipe = self.zfs_node.run(cmd, pipe=True, readonly=True)

return output_pipe
Expand Down Expand Up @@ -857,7 +860,7 @@ def recv_pipe(self, pipe, features, recv_pipes, filter_properties=None, set_prop
self.debug("Enabled resume support")
cmd.append("-s")

cmd.append(self.filesystem_name)
cmd.append(self.prefix)

if ignore_exit_code:
valid_exitcodes = []
Expand Down Expand Up @@ -935,17 +938,17 @@ def transfer_snapshot(self, target_snapshot, features, prev_snapshot, show_progr
if filter_properties is None:
filter_properties = []

self.debug("Transfer snapshot to {}".format(target_snapshot.filesystem_name))
self.debug("Transfer snapshot to {}".format(target_snapshot.prefix))

if resume_token:
self.verbose("resuming")

# initial or increment
if not prev_snapshot:
self.verbose("-> {} (new)".format(target_snapshot.filesystem_name))
self.verbose("-> {} (new)".format(target_snapshot.prefix))
else:
# incremental
self.verbose("-> {}".format(target_snapshot.filesystem_name))
self.verbose("-> {}".format(target_snapshot.prefix))

# do it
pipe = self.send_pipe(features=features, show_progress=show_progress, prev_snapshot=prev_snapshot,
Expand Down Expand Up @@ -994,7 +997,7 @@ def get_resume_snapshot(self, resume_token):
matches = re.findall("toname = .*@(.*)", line)
if matches:
snapshot_name = matches[0]
snapshot = self.zfs_node.get_dataset(self.filesystem_name + "@" + snapshot_name)
snapshot = self.zfs_node.get_dataset(self.prefix + "@" + snapshot_name)
snapshot.debug("resume token belongs to this snapshot")
return snapshot

Expand Down Expand Up @@ -1230,7 +1233,7 @@ def _plan_sync(self, target_dataset, also_other_snapshots, guid_check, raw, book
if (also_other_snapshots or source_snapshot.is_ours) and not source_snapshot.is_snapshot_excluded:
# create virtual target snapshot
target_snapshot = target_dataset.zfs_node.get_dataset(
target_dataset.filesystem_name + source_snapshot.typed_suffix, force_exists=False)
target_dataset.prefix + source_snapshot.typed_suffix, force_exists=False)
possible_target_snapshots.append(target_snapshot)
source_snapshot = self.find_next_snapshot(source_snapshot)

Expand Down Expand Up @@ -1401,7 +1404,8 @@ def sync_snapshots(self, target_dataset, features, show_progress, filter_propert
# FIXME: met bookmarks kan de huidige snapshot na send ook meteen weg
# FIXME: klopt niet, nu haalt ie altijd bookmark weg? wat als we naar andere target willen senden (zoals in test_encryption.py)
if prev_source_snapshot_bookmark and (
prev_source_snapshot_bookmark in source_obsoletes or prev_source_snapshot_bookmark.is_bookmark):
prev_source_snapshot_bookmark in source_obsoletes or (
prev_source_snapshot_bookmark.is_bookmark and prev_source_snapshot_bookmark.tag == bookmark_tag)):
prev_source_snapshot_bookmark.destroy()

# destroy the previous target snapshot if obsolete (usually this is only the common_snapshot,
Expand Down

0 comments on commit 49069dd

Please sign in to comment.