def destroy_snapshots(shell: Shell, snapshots: [Snapshot]): for dataset, snapshots in sortedgroupby(snapshots, lambda snapshot: snapshot.dataset): names = {snapshot.name for snapshot in snapshots} logger.info("On %r for dataset %r destroying snapshots %r", shell, dataset, names) while names: chunk = set() sum_len = len(dataset) for name in sorted(names): new_sum_len = sum_len + len(name) + 1 if new_sum_len >= ARG_MAX: break chunk.add(name) sum_len = new_sum_len args = ["zfs", "destroy", f"{dataset}@" + ",".join(sorted(chunk))] try: shell.exec(args) names -= chunk except ExecException as e: if m := re.search(r"cannot destroy snapshot .+?@(.+?): dataset is busy", e.stdout): reason = "busy" name = m.group(1) elif m := re.search(r"cannot destroy '.+?@(.+?)': snapshot has dependent clones", e.stdout): reason = "cloned" name = m.group(1) else: raise logger.info("Snapshot %r on dataset %r is %s, skipping", name, dataset, reason) names.discard(name)
def destroy_snapshots(shell: Shell, snapshots: [Snapshot]): for dataset, snapshots in sortedgroupby(snapshots, lambda snapshot: snapshot.dataset): names = [snapshot.name for snapshot in snapshots] logger.info("On %r for dataset %r destroying snapshots %r", shell, dataset, names) args = ["zfs", "destroy", f"{dataset}@" + "%".join(names)] shell.exec(args)
def destroy_snapshots(shell: Shell, snapshots: [Snapshot]): for dataset, snapshots in sortedgroupby(snapshots, lambda snapshot: snapshot.dataset): names = [snapshot.name for snapshot in snapshots] logger.info("On %r for dataset %r destroying snapshots %r", shell, dataset, names) while names: args = ["zfs", "destroy", f"{dataset}@" + ",".join(names)] try: shell.exec(args) break except ExecException as e: m = re.search( r"cannot destroy snapshot .+?@(.+?): dataset is busy", e.stdout) if m is None: raise name = m.group(1) logger.info("Snapshot %r on dataset %r is busy, skipping", name, dataset) names.remove(name)
def _transport_for_replication_tasks(self, replication_tasks): return sortedgroupby( replication_tasks, lambda replication_task: replication_task.transport, False)