diff options
Diffstat (limited to 'modules/zfssnap')
| -rw-r--r-- | modules/zfssnap/zfssnap.py | 45 |
1 files changed, 21 insertions, 24 deletions
diff --git a/modules/zfssnap/zfssnap.py b/modules/zfssnap/zfssnap.py index 4e7188f9..9a536258 100644 --- a/modules/zfssnap/zfssnap.py +++ b/modules/zfssnap/zfssnap.py | |||
| @@ -46,10 +46,9 @@ def _get_items(): | |||
| 46 | with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: | 46 | with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: |
| 47 | text_stdout = io.TextIOWrapper(proc.stdout) | 47 | text_stdout = io.TextIOWrapper(proc.stdout) |
| 48 | reader = csv.reader(text_stdout, delimiter='\t', quoting=csv.QUOTE_NONE) | 48 | reader = csv.reader(text_stdout, delimiter='\t', quoting=csv.QUOTE_NONE) |
| 49 | for row in reader: | 49 | Row = namedtuple('Row', ['name', 'setting']) |
| 50 | name = row[0] | 50 | for row in map(Row._make, reader): |
| 51 | setting = bool(strtobool(row[1])) | 51 | items[row.name] = bool(strtobool(row.setting)) |
| 52 | items[name] = setting | ||
| 53 | 52 | ||
| 54 | return items | 53 | return items |
| 55 | 54 | ||
| @@ -62,16 +61,15 @@ def prune(config, dry_run, keep_newest): | |||
| 62 | with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: | 61 | with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: |
| 63 | text_stdout = io.TextIOWrapper(proc.stdout) | 62 | text_stdout = io.TextIOWrapper(proc.stdout) |
| 64 | reader = csv.reader(text_stdout, delimiter='\t', quoting=csv.QUOTE_NONE) | 63 | reader = csv.reader(text_stdout, delimiter='\t', quoting=csv.QUOTE_NONE) |
| 65 | for row in reader: | 64 | Row = namedtuple('Row', ['name', 'timestamp']) |
| 66 | name = row[0] | 65 | for row in map(Row._make, reader): |
| 67 | timestamp = int(row[1]) | 66 | creation = datetime.fromtimestamp(int(row.timestamp), timezone.utc) |
| 68 | creation = datetime.fromtimestamp(timestamp, timezone.utc) | 67 | base_name, _, _ = row.name.rpartition('@') |
| 69 | base_name, _, _ = name.rpartition('@') | ||
| 70 | expected_name = _snap_name(base_name, time=creation) | 68 | expected_name = _snap_name(base_name, time=creation) |
| 71 | if expected_name != name: | 69 | if expected_name != row.name: |
| 72 | # logger.debug(f'Skipping ‘{name}’ since it does not conform to naming scheme') | 70 | # logger.debug(f'Skipping ‘{row.name}’ since it does not conform to naming scheme') |
| 73 | continue | 71 | continue |
| 74 | items[base_name].append(Snap(name=name, creation=creation)) | 72 | items[base_name].append(Snap(name=row.name, creation=creation)) |
| 75 | 73 | ||
| 76 | keep = set() | 74 | keep = set() |
| 77 | kept_count = defaultdict(lambda: defaultdict(lambda: 0)) | 75 | kept_count = defaultdict(lambda: defaultdict(lambda: 0)) |
| @@ -162,29 +160,28 @@ def rename(snapshots, destroy=False): | |||
| 162 | with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: | 160 | with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: |
| 163 | text_stdout = io.TextIOWrapper(proc.stdout) | 161 | text_stdout = io.TextIOWrapper(proc.stdout) |
| 164 | reader = csv.reader(text_stdout, delimiter='\t', quoting=csv.QUOTE_NONE) | 162 | reader = csv.reader(text_stdout, delimiter='\t', quoting=csv.QUOTE_NONE) |
| 165 | for row in reader: | 163 | Row = namedtuple('Row', ['name', 'timestamp']) |
| 166 | name = row[0] | 164 | for row in map(Row._make, reader): |
| 167 | timestamp = int(row[1]) | 165 | creation = datetime.fromtimestamp(int(row.timestamp), timezone.utc) |
| 168 | creation = datetime.fromtimestamp(timestamp, timezone.utc) | 166 | base_name, _, _ = row.name.rpartition('@') |
| 169 | base_name, _, _ = name.rpartition('@') | ||
| 170 | new_name = _snap_name(base_name, time=creation) | 167 | new_name = _snap_name(base_name, time=creation) |
| 171 | if new_name == name: | 168 | if new_name == row.name: |
| 172 | logger.debug(f'Not renaming ‘{name}’ since name is already correct') | 169 | logger.debug(f'Not renaming ‘{row.name}’ since name is already correct') |
| 173 | continue | 170 | continue |
| 174 | 171 | ||
| 175 | if new_name in renamed_to: | 172 | if new_name in renamed_to: |
| 176 | if destroy: | 173 | if destroy: |
| 177 | logger.warning(f'Destroying ‘{name}’ since ‘{new_name}’ was already renamed to') | 174 | logger.warning(f'Destroying ‘{row.name}’ since ‘{new_name}’ was already renamed to') |
| 178 | args = ['zfs', 'destroy', name] | 175 | args = ['zfs', 'destroy', row.name] |
| 179 | _log_cmd(*args) | 176 | _log_cmd(*args) |
| 180 | subprocess.run(args, check=True) | 177 | subprocess.run(args, check=True) |
| 181 | else: | 178 | else: |
| 182 | logger.info(f'Skipping ‘{name}’ since ‘{new_name}’ was already renamed to') | 179 | logger.info(f'Skipping ‘{row.name}’ since ‘{new_name}’ was already renamed to') |
| 183 | 180 | ||
| 184 | continue | 181 | continue |
| 185 | 182 | ||
| 186 | logger.info(f'Renaming ‘{name}’ to ‘{new_name}’') | 183 | logger.info(f'Renaming ‘{row.name}’ to ‘{new_name}’') |
| 187 | args = ['zfs', 'rename', name, new_name] | 184 | args = ['zfs', 'rename', row.name, new_name] |
| 188 | _log_cmd(*args) | 185 | _log_cmd(*args) |
| 189 | subprocess.run(args, check=True) | 186 | subprocess.run(args, check=True) |
| 190 | renamed_to.add(new_name) | 187 | renamed_to.add(new_name) |
