66 lines
2.3 KiB
Python
Executable File
66 lines
2.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import subprocess
|
|
import pathlib
|
|
import os
|
|
import logging
|
|
import asyncio
|
|
|
|
|
|
async def notify(level, message):
|
|
# notify = desktop_notify.aio.Notify(level, message)
|
|
# await notify.show()
|
|
notify_cmd = ["backup/notify.sh", level, message]
|
|
notify = subprocess.run(notify_cmd, capture_output=True)
|
|
|
|
def is_mountpoint(path):
|
|
mountpoint_cmd = ["mountpoint", str(path)]
|
|
logging.info(' '.join(mountpoint_cmd))
|
|
check = subprocess.run(mountpoint_cmd, capture_output=True)
|
|
if check.returncode != 0: # not a mountpoint
|
|
logging.error(check.stdout.decode().strip())
|
|
return False
|
|
else:
|
|
logging.info(check.stdout.decode().strip())
|
|
return True
|
|
|
|
|
|
async def main():
|
|
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.DEBUG)
|
|
|
|
subvolumes_to_backup = ["home", "root"]
|
|
logging.info(f"Backing up {', '.join(subvolumes_to_backup)}")
|
|
btrfs_subvolume = "/btrfs"
|
|
snapshot_subvolume = f"{btrfs_subvolume}/snapshots"
|
|
snapshot_path = pathlib.Path(snapshot_subvolume)
|
|
old_snapshots = os.listdir(snapshot_path)
|
|
|
|
for snapshot in old_snapshots:
|
|
delete_cmd = ["btrfs", "sub", "del", f"{snapshot_path}/{snapshot}"]
|
|
logging.info(' '.join(delete_cmd))
|
|
delete = subprocess.run(delete_cmd, capture_output=True)
|
|
|
|
for subvolume in subvolumes_to_backup:
|
|
snapshot_cmd = [
|
|
"btrfs", "sub", "snap", "-r", f"{btrfs_subvolume}/{subvolume}", f"{snapshot_path}"]
|
|
logging.info(' '.join(snapshot_cmd))
|
|
create_new_snap = subprocess.run(snapshot_cmd, capture_output=True)
|
|
|
|
backup_mountpoint = pathlib.Path("/mnt/53de8433-6394-408c-a856-5f3b9908f21f")
|
|
snapshots = os.listdir(snapshot_path)
|
|
|
|
if is_mountpoint(backup_mountpoint):
|
|
for new_snapshot in snapshots:
|
|
backup_cmd = ["rsync", "-av", "--delete",
|
|
f"{snapshot_path}/{new_snapshot}/",
|
|
f"{backup_mountpoint}/{new_snapshot}/"]
|
|
logging.info(' '.join(backup_cmd))
|
|
rsync = subprocess.run(backup_cmd, capture_output=True)
|
|
await notify(f"{new_snapshot} backup successful", ' '.join(backup_cmd))
|
|
else:
|
|
await notify(f"{new_snapshot} backup failed", f"{backup_mountpoint} is not mounted")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|