Compare commits

..

No commits in common. "7cd6eb88211f48e41861bd52e089296ff49fe945" and "3eca803f0810fd25f15355dc286986f69352f65c" have entirely different histories.

3 changed files with 46 additions and 109 deletions

View File

@ -1,34 +0,0 @@
from datetime import datetime
import requests
import os
import config
def raiseWebhook(message, file=None):
data = {
"username": "Backup script",
"embeds":
[{
"title": "Erreur lors de la sauvegarde",
"description": message,
"color": color_red,
"fields": []
}]
}
if file is not None:
data[files]={"file": open(file, "rb")}
requests.post(config.ERROR_WEBHOOK, json=data)
with open("latest-success", "r") as f:
latest_success = f.read().strip()
today = datetime.today().strftime('%Y-%m-%d')
if latest_success != today:
log_file = None
if os.path.exists(f"logs/{today}.txt"):
log_file = f"logs/{today}.txt"
raiseWebhook(f"No successful backup today", file=log_file)

View File

@ -8,5 +8,3 @@ REMOTE_USER = "myuser"
BACKUP_MAP = [ BACKUP_MAP = [
("/home/remote/MyData", "backup-it-here") # myuser@192.168.1.5:/home/remote/MyData will be backed up to /mnt/{backup-date and "latest"}/backup-it-here ("/home/remote/MyData", "backup-it-here") # myuser@192.168.1.5:/home/remote/MyData will be backed up to /mnt/{backup-date and "latest"}/backup-it-here
] ]
ERROR_WEBHOOK = "https://discord.com/api/webhooks/...."

View File

@ -1,7 +1,6 @@
from datetime import datetime from datetime import datetime
import subprocess import subprocess
import requests import requests
import sys
import os import os
import config import config
@ -10,19 +9,9 @@ def log(*args, **kwargs):
date = datetime.now().strftime('%d-%b-%Y %H:%M:%S') date = datetime.now().strftime('%d-%b-%Y %H:%M:%S')
print(f"[{date}]", *args, **kwargs) print(f"[{date}]", *args, **kwargs)
def log_error(*args, **kwargs):
date = datetime.now().strftime('%d-%b-%Y %H:%M:%S')
print(f"[{date}]", *args, **kwargs, file=sys.stderr)
def check_return_code(ret, *args, **kwargs):
if ret != 0:
log_error(*args, **kwargs)
exit(1)
if not os.path.exists(config.DISK): if not os.path.exists(config.DISK):
log_error(f"Drive {config.DISK} not present on the system") log_error(f"Drive {config.DISK} not present on the system")
exit(1)
passwd = requests.get(config.PWD_URL).text.strip() passwd = requests.get(config.PWD_URL).text.strip()
log("Got password :", passwd) log("Got password :", passwd)
@ -31,77 +20,61 @@ ssh_key_passwd = requests.get(config.SSH_KEY_PWD_URL).text.strip()
log("Got password :", ssh_key_passwd) log("Got password :", ssh_key_passwd)
class Drive(): subprocess.run([
def __init__(self, disk, passwd, mount_location): "cryptsetup", "luksOpen",
self.disk = disk config.DISK, "backup"
self.passwd = passwd ], input=passwd, text=True)
self.mount_location = mount_location
def __enter__(self): subprocess.call([
subprocess.run([ "mount", "/dev/mapper/backup",
"cryptsetup", "luksOpen", config.MNT_LOCATION
self.disk, "backup" ])
], input=self.passwd, text=True)
subprocess.call([ log("Successfully mounted, doing the backup stuff")
"mount", "/dev/mapper/backup",
self.mount_location
])
return self
def __exit__(self, exception_type, exception_value, exception_traceback): os.makedirs(
subprocess.call([ os.path.join(config.MNT_LOCATION, "latest"),
"umount", self.mount_location exist_ok=True
]) )
subprocess.call([ for src, dest in config.BACKUP_MAP:
"cryptsetup", "luksClose", # We could also use a rsync daemon on the remote machine for pwd(-less) auth
"/dev/mapper/backup" subprocess.call(
]) [
"sshpass", "-P", "passphrase", "-e",
"rsync",
with Drive(config.DISK, passwd, config.MNT_LOCATION) as backup_drive: "-ahz",
log("Successfully mounted, doing the backup stuff") "--partial",
"--delete",
os.makedirs( "--stats",
os.path.join(config.MNT_LOCATION, "latest"), f"{config.REMOTE_USER}@{config.REMOTE_LOCATION}:{src}",
exist_ok=True os.path.join(config.MNT_LOCATION, "latest", dest),
],
env={**os.environ, "SSHPASS":ssh_key_passwd}
) )
for src, dest in config.BACKUP_MAP: log("Rsync ok. Creating snapshot.")
# We could also use a rsync daemon on the remote machine for pwd(-less) auth
ret = subprocess.call(
[
"sshpass", "-P", "passphrase", "-e",
"rsync",
"-ahz",
"--partial",
"--delete",
"--stats",
f"{config.REMOTE_USER}@{config.REMOTE_LOCATION}:{src}",
os.path.join(config.MNT_LOCATION, "latest", dest),
],
env={**os.environ, "SSHPASS":ssh_key_passwd}
)
check_return_code(ret, f"Error when syncing {config.REMOTE_LOCATION}")
log("Rsync ok. Creating snapshot.") subprocess.call([
"cp", "-a",
"--reflink=always", #! The partition must be Btrfs or XFS
os.path.join(config.MNT_LOCATION, "latest"),
os.path.join(config.MNT_LOCATION, datetime.today().strftime('%Y-%m-%d'))
])
ret = subprocess.call([ log("Snapshot ok. Deleting unneeded backups.")
"cp", "-a",
"--reflink=always", #! The partition must be Btrfs or XFS
os.path.join(config.MNT_LOCATION, "latest"),
os.path.join(config.MNT_LOCATION, datetime.today().strftime('%Y-%m-%d'))
])
check_return_code(ret, f"Error when creating snapshot")
log("Snapshot ok. Deleting unneeded backups.") #TODO
#TODO log("Unmounting.")
log("Unmounting.") subprocess.call([
"umount", config.MNT_LOCATION
])
log("Everything okay, done !") subprocess.call([
"cryptsetup", "luksClose",
"/dev/mapper/backup"
])
with open("latest-success", "w") as f: log("Done !")
f.write(datetime.today().strftime('%Y-%m-%d'))