summaryrefslogtreecommitdiff
path: root/modules/zfssnap
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2022-02-19 15:24:38 +0100
committerGregor Kleen <gkleen@yggdrasil.li>2022-02-19 15:24:38 +0100
commit4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7 (patch)
tree50f5f9acb456a49a4181417c6c3bdc86824d3781 /modules/zfssnap
parentfa4031277173dec7077489f87506a56c0c9e1f04 (diff)
downloadnixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.tar
nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.tar.gz
nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.tar.bz2
nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.tar.xz
nixos-4ec3abc5a5e0c0f5a5790d9713201023b26d3bc7.zip
vidhar: ...
Diffstat (limited to 'modules/zfssnap')
-rw-r--r--modules/zfssnap/zfssnap.py32
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
143def rename(snapshots, check=False): 143def 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
164def autosnap(): 177def 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):