49 lines
2.0 KiB
Django/Jinja
49 lines
2.0 KiB
Django/Jinja
#!/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)
|