Compare commits
2 Commits
3eca803f08
...
7cd6eb8821
Author | SHA1 | Date | |
---|---|---|---|
7cd6eb8821 | |||
0bb783aca4 |
34
src/check_success.py
Normal file
34
src/check_success.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
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)
|
@ -7,4 +7,6 @@ REMOTE_LOCATION = "192.168.1.5"
|
|||||||
REMOTE_USER = "myuser"
|
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/...."
|
117
src/main.py
117
src/main.py
@ -1,6 +1,7 @@
|
|||||||
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
|
||||||
@ -9,9 +10,19 @@ 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)
|
||||||
@ -20,61 +31,77 @@ ssh_key_passwd = requests.get(config.SSH_KEY_PWD_URL).text.strip()
|
|||||||
log("Got password :", ssh_key_passwd)
|
log("Got password :", ssh_key_passwd)
|
||||||
|
|
||||||
|
|
||||||
subprocess.run([
|
class Drive():
|
||||||
"cryptsetup", "luksOpen",
|
def __init__(self, disk, passwd, mount_location):
|
||||||
config.DISK, "backup"
|
self.disk = disk
|
||||||
], input=passwd, text=True)
|
self.passwd = passwd
|
||||||
|
self.mount_location = mount_location
|
||||||
|
|
||||||
subprocess.call([
|
def __enter__(self):
|
||||||
"mount", "/dev/mapper/backup",
|
subprocess.run([
|
||||||
config.MNT_LOCATION
|
"cryptsetup", "luksOpen",
|
||||||
])
|
self.disk, "backup"
|
||||||
|
], input=self.passwd, text=True)
|
||||||
|
|
||||||
log("Successfully mounted, doing the backup stuff")
|
subprocess.call([
|
||||||
|
"mount", "/dev/mapper/backup",
|
||||||
|
self.mount_location
|
||||||
|
])
|
||||||
|
return self
|
||||||
|
|
||||||
os.makedirs(
|
def __exit__(self, exception_type, exception_value, exception_traceback):
|
||||||
os.path.join(config.MNT_LOCATION, "latest"),
|
subprocess.call([
|
||||||
exist_ok=True
|
"umount", self.mount_location
|
||||||
)
|
])
|
||||||
|
|
||||||
for src, dest in config.BACKUP_MAP:
|
subprocess.call([
|
||||||
# We could also use a rsync daemon on the remote machine for pwd(-less) auth
|
"cryptsetup", "luksClose",
|
||||||
subprocess.call(
|
"/dev/mapper/backup"
|
||||||
[
|
])
|
||||||
"sshpass", "-P", "passphrase", "-e",
|
|
||||||
"rsync",
|
|
||||||
"-ahz",
|
with Drive(config.DISK, passwd, config.MNT_LOCATION) as backup_drive:
|
||||||
"--partial",
|
log("Successfully mounted, doing the backup stuff")
|
||||||
"--delete",
|
|
||||||
"--stats",
|
os.makedirs(
|
||||||
f"{config.REMOTE_USER}@{config.REMOTE_LOCATION}:{src}",
|
os.path.join(config.MNT_LOCATION, "latest"),
|
||||||
os.path.join(config.MNT_LOCATION, "latest", dest),
|
exist_ok=True
|
||||||
],
|
|
||||||
env={**os.environ, "SSHPASS":ssh_key_passwd}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
log("Rsync ok. Creating snapshot.")
|
for src, dest in config.BACKUP_MAP:
|
||||||
|
# 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}")
|
||||||
|
|
||||||
subprocess.call([
|
log("Rsync ok. Creating snapshot.")
|
||||||
"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'))
|
|
||||||
])
|
|
||||||
|
|
||||||
log("Snapshot ok. Deleting unneeded backups.")
|
ret = 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'))
|
||||||
|
])
|
||||||
|
check_return_code(ret, f"Error when creating snapshot")
|
||||||
|
|
||||||
#TODO
|
log("Snapshot ok. Deleting unneeded backups.")
|
||||||
|
|
||||||
log("Unmounting.")
|
#TODO
|
||||||
|
|
||||||
subprocess.call([
|
log("Unmounting.")
|
||||||
"umount", config.MNT_LOCATION
|
|
||||||
])
|
|
||||||
|
|
||||||
subprocess.call([
|
log("Everything okay, done !")
|
||||||
"cryptsetup", "luksClose",
|
|
||||||
"/dev/mapper/backup"
|
|
||||||
])
|
|
||||||
|
|
||||||
log("Done !")
|
with open("latest-success", "w") as f:
|
||||||
|
f.write(datetime.today().strftime('%Y-%m-%d'))
|
Loading…
x
Reference in New Issue
Block a user