Skip to content

Commit

Permalink
wip: bookmarks. allow disabling/reenabling bookmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
psy0rz committed Oct 1, 2024
1 parent 5e74c16 commit 9faa9ef
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 5 deletions.
53 changes: 53 additions & 0 deletions tests/test_zfsautobackup34.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,56 @@ def test_select_bookmark_or_snapshot(self):
#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.assertMultiLineEqual(r,"""
test_source1
test_source1/fs1
test_source1/fs1@test-20101111000001
test_source1/fs1#test-20101111000001
test_source1/fs1/sub
test_source1/fs1/sub@test-20101111000001
test_source1/fs1/sub#test-20101111000001
""")

#disable it
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.assertMultiLineEqual(r,"""
test_source1
test_source1/fs1
test_source1/fs1@test-20101111000001
test_source1/fs1@test-20101111000002
test_source1/fs1/sub
test_source1/fs1/sub@test-20101111000001
test_source1/fs1/sub@test-20101111000002
""")

#re-enable
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.assertMultiLineEqual(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-20101111000003
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-20101111000003
""")
14 changes: 13 additions & 1 deletion zfs_autobackup/ZfsAutobackup.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ def get_parser(self):
help='Don\'t transfer snapshots (useful for cleanups, or if you want a separate send-cronjob)')
group.add_argument('--no-holds', action='store_true',
help='Don\'t hold snapshots. (Faster. Allows you to destroy common snapshot.)')
group.add_argument('--no-bookmarks', action='store_true',
help='Don\'t use bookmarks.')

group.add_argument('--clear-refreservation', action='store_true',
help='Filter "refreservation" property. (recommended, saves space. same as '
'--filter-properties refreservation)')
Expand Down Expand Up @@ -395,6 +398,15 @@ def sync_datasets(self, source_node, source_datasets, target_node):
target_features = target_node.get_pool(target_dataset).features
common_features = source_features and target_features

if self.args.no_bookmarks:
use_bookmarks=False
else:
if not 'bookmark_written' in common_features:
source_dataset.warning("Disabling bookmarks, not supported on both pools.")
use_bookmarks=False
else:
use_bookmarks=True

# sync the snapshots of this dataset
source_dataset.sync_snapshots(target_dataset, show_progress=self.args.progress,
features=common_features, filter_properties=self.filter_properties_list(),
Expand All @@ -407,7 +419,7 @@ def sync_datasets(self, source_node, source_datasets, target_node):
send_pipes=send_pipes, recv_pipes=recv_pipes,
decrypt=self.args.decrypt, encrypt=self.args.encrypt,
zfs_compressed=self.args.zfs_compressed, force=self.args.force,
guid_check=not self.args.no_guid_check)
guid_check=not self.args.no_guid_check, use_bookmarks=use_bookmarks)
except Exception as e:

fail_count = fail_count + 1
Expand Down
8 changes: 4 additions & 4 deletions zfs_autobackup/ZfsDataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def filesystem_name(self):

@property
def suffix(self):
"""snapshot or bookmark part of the name"""
"""snapshot or bookmark part of the name (the stuff after the # or @) """
if self.is_snapshot:
(filesystem, snapshot_name) = self.name.split("@")
return snapshot_name
Expand Down Expand Up @@ -1227,7 +1227,7 @@ def handle_incompatible_snapshots(self, incompatible_target_snapshots, destroy_i

def sync_snapshots(self, target_dataset, features, show_progress, filter_properties, set_properties,
ignore_recv_exit_code, holds, rollback, decrypt, encrypt, also_other_snapshots,
no_send, destroy_incompatible, send_pipes, recv_pipes, zfs_compressed, force, guid_check):
no_send, destroy_incompatible, send_pipes, recv_pipes, zfs_compressed, force, guid_check, use_bookmarks):
"""sync this dataset's snapshots to target_dataset, while also thinning
out old snapshots along the way.
Expand Down Expand Up @@ -1334,14 +1334,14 @@ def sync_snapshots(self, target_dataset, features, show_progress, filter_propert

#bookmark common snapshot on source, or use holds if bookmarks are not enabled.
#NOTE: bookmark_written seems to be needed. (only 'bookmarks' was not enough on ubuntu 20)
if 'bookmark_written' in features:
if use_bookmarks:
source_snapshot.bookmark()
#note: destroy source_snapshot when obsolete at this point?
else:
if holds:
source_snapshot.hold()

if prev_source_snapshot:
if prev_source_snapshot and prev_source_snapshot.is_snapshot:
prev_source_snapshot.release()

# we may now destroy the previous source snapshot if its obsolete or an bookmark
Expand Down

0 comments on commit 9faa9ef

Please sign in to comment.