From a6878e1037716ac66db087ab0d947e264e3acf68 Mon Sep 17 00:00:00 2001 From: Edwin Eefting Date: Mon, 28 Oct 2019 20:54:01 +0100 Subject: [PATCH] filter illegal properties per dataset type. change clear-options to filtering instead of setting --- zfs_autobackup | 63 +++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/zfs_autobackup b/zfs_autobackup index 539231c..55d1ab1 100755 --- a/zfs_autobackup +++ b/zfs_autobackup @@ -476,6 +476,12 @@ class ZfsDataset(): """ + # illegal properties per dataset type. these will be filtered from --set-properties and --filter-properties + ILLEGAL_PROPERTIES={ + 'filesystem': [ ], + 'volume': [ "canmount" ], + } + def __init__(self, zfs_node, name, force_exists=None): """name: full path of the zfs dataset exists: specifiy if you already know a dataset exists or not. for performance reasons. (othewise it will have to check with zfs list when needed) @@ -974,18 +980,28 @@ class ZfsDataset(): return(snapshot) + def get_allowed_properties(self, filter_properties, set_properties): + """only returns lists of allowed properties for this dataset type""" + + allowed_filter_properties=[] + allowed_set_properties=[] + illegal_properties=self.ILLEGAL_PROPERTIES[self.properties['type']] + for set_property in set_properties: + (property, value) = set_property.split("=") + if property not in illegal_properties: + allowed_set_properties.append(set_property) + + for filter_property in filter_properties: + if filter_property not in illegal_properties: + allowed_filter_properties.append(filter_property) + + return ( ( allowed_filter_properties, allowed_set_properties ) ) + def sync_snapshots(self, target_dataset, show_progress=False, resume=True, filter_properties=[], set_properties=[], ignore_recv_exit_code=False, source_holds=True, rollback=False): - """sync our snapshots to target_dataset""" + """sync this dataset's snapshots to target_dataset,""" - #resume something first? - # resumed=self.resume_transfer(target_dataset, show_progress=show_progress, filter_properties=filter_properties, set_properties=set_properties, ignore_recv_exit_code=ignore_recv_exit_code) - # if resumed: - # #running in readonly mode and no snapshots yet? assume initial snapshot (otherwise we cant find common snapshot in next step) - # if self.zfs_node.readonly and not target_dataset.our_snapshots: - # target_dataset.snapshots.append(ZfsDataset(target_dataset.zfs_node, target_dataset.name + "@" + self.our_snapshots[0].snapshot_name)) - #determine start snapshot (the first snapshot after the common snapshot) target_dataset.debug("Determining start snapshot") common_snapshot=self.find_common_snapshot(target_dataset) @@ -1010,24 +1026,6 @@ class ZfsDataset(): resume_token=None - - - # #if something is resumed, fix the holds at this point - # if resumed: - # #hold the current commons, relase the previous ones - # if common_snapshot: - # common_snapshot.hold() - # target_dataset.find_snapshot(common_snapshot).hold() - # - # prev_target_snapshot=target_dataset.find_our_prev_snapshot(common_snapshot) - # if prev_target_snapshot: - # prev_target_snapshot.release() - # - # prev_source_snapshot=self.find_snapshot(prev_target_snapshot) - # if prev_source_snapshot: - # prev_source_snapshot.release() - - #create virtual target snapshots target_dataset.debug("Creating virtual target snapshots") source_snapshot=start_snapshot @@ -1066,7 +1064,8 @@ class ZfsDataset(): #does target actually want it? if target_snapshot in target_keeps: - source_snapshot.transfer_snapshot(target_snapshot, prev_snapshot=prev_source_snapshot, show_progress=show_progress, resume=resume, filter_properties=filter_properties, set_properties=set_properties, ignore_recv_exit_code=ignore_recv_exit_code, resume_token=resume_token) + ( allowed_filter_properties, allowed_set_properties ) = self.get_allowed_properties(filter_properties, set_properties) + source_snapshot.transfer_snapshot(target_snapshot, prev_snapshot=prev_source_snapshot, show_progress=show_progress, resume=resume, filter_properties=allowed_filter_properties, set_properties=allowed_set_properties, ignore_recv_exit_code=ignore_recv_exit_code, resume_token=resume_token) resume_token=None #hold the new common snapshots and release the previous ones @@ -1289,8 +1288,8 @@ class ZfsAutobackup: # parser.add_argument('--destroy-stale', action='store_true', help='Destroy stale backups that have no more snapshots. Be sure to verify the output before using this! ') - parser.add_argument('--clear-refreservation', action='store_true', help='Set refreservation property to none for new filesystems. Usefull when backupping SmartOS volumes. (recommended. same as --set-properties refreservation=none)') - parser.add_argument('--clear-mountpoint', action='store_true', help='Sets canmount=noauto property, to prevent the received filesystem from mounting over existing filesystems. (recommended. same as --set-properties canmount=noauto)') + parser.add_argument('--clear-refreservation', action='store_true', help='Filter "refreservation" property. (recommended, safes space. same as --filter-properties refreservation)') + parser.add_argument('--clear-mountpoint', action='store_true', help='Filter "canmount" property (recommended, prevents mount conflicts. same as --filter-properties canmount)') parser.add_argument('--filter-properties', type=str, help='List of propererties to "filter" when receiving filesystems. (you can still restore them with zfs inherit -S)') parser.add_argument('--set-properties', type=str, help='List of propererties to override when receiving filesystems. (you can still restore them with zfs inherit -S)') parser.add_argument('--rollback', action='store_true', help='Rollback changes on the target before starting a backup. (normally you can prevent changes by setting the readonly property on the target_path to on)') @@ -1377,10 +1376,10 @@ class ZfsAutobackup: set_properties=[] if self.args.clear_refreservation: - set_properties.append("refreservation=none") + filter_properties.append("refreservation") if self.args.clear_mountpoint: - set_properties.append("canmount=noauto") + filter_properties.append("canmount") fail_count=0 for source_dataset in source_datasets: @@ -1402,7 +1401,7 @@ class ZfsAutobackup: raise if not fail_count: - set_title("All backups completed succesfully") + self.set_title("All backups completed succesfully") else: self.error("{} datasets failed!".format(fail_count))