#!/usr/bin/env python3 import argparse import os import subprocess def get_service_data_paths(data_root): dirs = os.listdir(data_root) return { d: os.path.join(data_root, d) for d in dirs } def get_last_daily_snapshot_name(dataset_path): dataset = ''.join(["rpool", dataset_path]) snapshots = subprocess.getoutput( f"zfs list -t snapshot -H -r {dataset} -o name -s creation" ) daily_snapshots = filter(lambda s: s.endswith("_daily"), snapshots.split('\n')) return list(daily_snapshots)[-1] def get_snapshot_mount_path(snapshot): return snapshot.replace("rpool/", "/", 1).replace("@", "/.zfs/snapshot/", 1) if __name__ == "__main__": parser = argparse.ArgumentParser(description="Backup service data using restic") parser.add_argument("--data-root", type=str, required=True, help="Service data root") parser.add_argument("--bucket-endpoint", type=str, required=True, help="S3 bucket endpoint") parser.add_argument("--password-file", type=str, required=True, help="Password file for restic repo") args = parser.parse_args() snapshots_for_backup = {} for service, service_data_root in get_service_data_paths(args.data_root).items(): last_daily_snapshot = get_last_daily_snapshot_name(service_data_root) snapshots_for_backup[service] = get_snapshot_mount_path(last_daily_snapshot) for service, snapshot_path in snapshots_for_backup.items(): print(f"Backing up {service} @ {snapshot_path}") restic_cmd_base = "restic " \ f"--password-file {args.password_file} " \ f"--repo s3:https://{args.bucket_endpoint}/{{ ansible_hostname }}-{service}" subprocess.run(f"{restic_cmd_base} snapshots || {restic_cmd_base} init", shell=True, check=True) subprocess.run(f"{restic_cmd_base} backup -o s3.storage-class=ONEZONE_IA {snapshot_path}", shell=True, check=True)