diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2022-02-19 15:24:38 +0100 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2022-02-19 15:24:38 +0100 |
| commit | 4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7 (patch) | |
| tree | 50f5f9acb456a49a4181417c6c3bdc86824d3781 | |
| parent | fa4031277173dec7077489f87506a56c0c9e1f04 (diff) | |
| download | nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.tar nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.tar.gz nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.tar.bz2 nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.tar.xz nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.zip | |
vidhar: ...
| -rw-r--r-- | modules/zfssnap/zfssnap.py | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/modules/zfssnap/zfssnap.py b/modules/zfssnap/zfssnap.py index 7daa2935..57b0e95f 100644 --- a/modules/zfssnap/zfssnap.py +++ b/modules/zfssnap/zfssnap.py | |||
| @@ -126,13 +126,13 @@ def prune(config, dry_run): | |||
| 126 | logger.debug(f'Missing {to_keep} to fulfill {rule}={desired_count} for ‘{base}’') | 126 | logger.debug(f'Missing {to_keep} to fulfill {rule}={desired_count} for ‘{base}’') |
| 127 | 127 | ||
| 128 | all_snaps = {snap['name'] for _, snaps in items.items() for snap in snaps} | 128 | all_snaps = {snap['name'] for _, snaps in items.items() for snap in snaps} |
| 129 | to_delete = all_snaps - keep | 129 | to_destroy = all_snaps - keep |
| 130 | if to_delete: | 130 | if to_destroy: |
| 131 | logger.info(f'Will prune: %s', ', '.join(map(lambda snap: f'‘{snap}’', to_delete))) | 131 | logger.info(f'Will prune: %s', ', '.join(map(lambda snap: f'‘{snap}’', to_destroy))) |
| 132 | else: | 132 | else: |
| 133 | logger.info('Nothing to prune') | 133 | logger.info('Nothing to prune') |
| 134 | 134 | ||
| 135 | for snap in to_delete: | 135 | for snap in to_destroy: |
| 136 | args = ['zfs', 'destroy'] | 136 | args = ['zfs', 'destroy'] |
| 137 | if dry_run: | 137 | if dry_run: |
| 138 | args += ['-n'] | 138 | args += ['-n'] |
| @@ -140,9 +140,10 @@ def prune(config, dry_run): | |||
| 140 | _log_cmd(*args) | 140 | _log_cmd(*args) |
| 141 | subprocess.run(args, check=True) | 141 | subprocess.run(args, check=True) |
| 142 | 142 | ||
| 143 | def rename(snapshots, check=False): | 143 | def rename(snapshots, destroy=False): |
| 144 | args = ['zfs', 'get', '-H', '-p', '-o', 'name,value', 'creation', *snapshots] | 144 | args = ['zfs', 'get', '-H', '-p', '-o', 'name,value', 'creation', *snapshots] |
| 145 | _log_cmd(*args) | 145 | _log_cmd(*args) |
| 146 | renamed_to = set() | ||
| 146 | with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: | 147 | with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: |
| 147 | text_stdout = io.TextIOWrapper(proc.stdout) | 148 | text_stdout = io.TextIOWrapper(proc.stdout) |
| 148 | reader = csv.reader(text_stdout, delimiter='\t', quoting=csv.QUOTE_NONE) | 149 | reader = csv.reader(text_stdout, delimiter='\t', quoting=csv.QUOTE_NONE) |
| @@ -155,11 +156,23 @@ def rename(snapshots, check=False): | |||
| 155 | if new_name == name: | 156 | if new_name == name: |
| 156 | logger.debug(f'Not renaming ‘{name}’ since name is already correct') | 157 | logger.debug(f'Not renaming ‘{name}’ since name is already correct') |
| 157 | continue | 158 | continue |
| 158 | logger.info(f'Renaming ‘{name}’ to ‘{new_name}’') | ||
| 159 | 159 | ||
| 160 | if new_name in renamed_to: | ||
| 161 | if destroy: | ||
| 162 | logger.warning(f'Destroying ‘{name}’ since ‘{new_name}’ was already renamed to') | ||
| 163 | args = ['zfs', 'destroy', name] | ||
| 164 | _log_cmd(*args) | ||
| 165 | subprocess.run(args, check=True) | ||
| 166 | else: | ||
| 167 | logger.info(f'Skipping ‘{name}’ since ‘{new_name}’ was already renamed to') | ||
| 168 | |||
| 169 | continue | ||
| 170 | |||
| 171 | logger.info(f'Renaming ‘{name}’ to ‘{new_name}’') | ||
| 160 | args = ['zfs', 'rename', name, new_name] | 172 | args = ['zfs', 'rename', name, new_name] |
| 161 | _log_cmd(*args) | 173 | _log_cmd(*args) |
| 162 | subprocess.run(args, check=check) | 174 | subprocess.run(args, check=True) |
| 175 | renamed_to.add(new_name) | ||
| 163 | 176 | ||
| 164 | def autosnap(): | 177 | def autosnap(): |
| 165 | items = _get_items() | 178 | items = _get_items() |
| @@ -207,7 +220,7 @@ def autosnap(): | |||
| 207 | 220 | ||
| 208 | _log_cmd(*args) | 221 | _log_cmd(*args) |
| 209 | subprocess.run(args, check=True) | 222 | subprocess.run(args, check=True) |
| 210 | rename(snapshots=all_snap_names, check=True) | 223 | rename(snapshots=all_snap_names) |
| 211 | 224 | ||
| 212 | do_snapshot(*single) | 225 | do_snapshot(*single) |
| 213 | do_snapshot(*recursive, recursive=True) | 226 | do_snapshot(*recursive, recursive=True) |
| @@ -236,6 +249,7 @@ def main(): | |||
| 236 | parser.set_defaults(cmd=autosnap) | 249 | parser.set_defaults(cmd=autosnap) |
| 237 | rename_parser = subparsers.add_parser('rename') | 250 | rename_parser = subparsers.add_parser('rename') |
| 238 | rename_parser.add_argument('snapshots', nargs='+') | 251 | rename_parser.add_argument('snapshots', nargs='+') |
| 252 | rename_parser.add_argument('--destroy', action='store_true', default=False) | ||
| 239 | rename_parser.set_defaults(cmd=rename) | 253 | rename_parser.set_defaults(cmd=rename) |
| 240 | prune_parser = subparsers.add_parser('prune') | 254 | prune_parser = subparsers.add_parser('prune') |
| 241 | prune_parser.add_argument('--config', '-c', dest='config_files', nargs='*', default=list()) | 255 | prune_parser.add_argument('--config', '-c', dest='config_files', nargs='*', default=list()) |
| @@ -251,7 +265,7 @@ def main(): | |||
| 251 | logger.setLevel(logging.DEBUG) | 265 | logger.setLevel(logging.DEBUG) |
| 252 | 266 | ||
| 253 | cmdArgs = {} | 267 | cmdArgs = {} |
| 254 | for copy in {'snapshots', 'dry_run'}: | 268 | for copy in {'snapshots', 'dry_run', 'destroy'}: |
| 255 | if copy in vars(args): | 269 | if copy in vars(args): |
| 256 | cmdArgs[copy] = vars(args)[copy] | 270 | cmdArgs[copy] = vars(args)[copy] |
| 257 | if 'config_files' in vars(args): | 271 | if 'config_files' in vars(args): |
