-
Notifications
You must be signed in to change notification settings - Fork 11
/
backup.py
151 lines (120 loc) · 5.41 KB
/
backup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/python3
import os, logging, subprocess, ast, smtplib
from time import strftime, localtime
from socket import gaierror
def envBool(env):
return (os.environ.get(env) or "").casefold() == 'true'
BACKUP_NAME=os.environ.get("BACKUP_NAME")
BACKUP_ENCRYPTION_KEY=os.environ.get("BACKUP_ENCRYPTION_KEY")
BACKUP_SCHEDULE=os.environ.get("BACKUP_SCHEDULE")
BACKUP_LOCATION=os.environ.get("BACKUP_LOCATION")
BACKUP_PRUNE=envBool("BACKUP_PRUNE")
BACKUP_NOW=envBool("BACKUP_NOW")
BACKUP_VERBOSE=envBool("BACKUP_VERBOSE")
BORG_CUSTOM_ARGS=os.environ.get("BORG_CUSTOM_ARGS")
EMAIL_HOST=os.environ.get("EMAIL_HOST")
EMAIL_USER=os.environ.get("EMAIL_USER")
EMAIL_PASS=os.environ.get("EMAIL_PASS")
EMAIL_USE_TLS=envBool("EMAIL_USE_TLS")
EMAIL_PORT=os.environ.get("EMAIL_PORT")
EMAIL_FROM=os.environ.get("EMAIL_FROM")
EMAIL_TO=os.environ.get("EMAIL_TO")
EMAIL_TEST=envBool("EMAIL_TEST")
EMAIL_ENABLED=envBool("EMAIL_ENABLED")
B2_ID=os.environ.get("B2_ID")
B2_KEY=os.environ.get("B2_KEY")
BORG_REPO="/backups/"+BACKUP_NAME
def sendEmail(message=str,subject_tag="success"):
if not EMAIL_ENABLED: return
email = f"Subject: Backup alerts - {subject_tag}\n\n{message}"
try:
#send your message with credentials specified above
if EMAIL_USE_TLS:
logging.debug("Using SMTP-TLS")
server = smtplib.SMTP(EMAIL_HOST,int(EMAIL_PORT))
server.starttls()
server.ehlo()
else:
logging.debug("Using SMTP-SSL")
server = smtplib.SMTP_SSL(EMAIL_HOST,int(EMAIL_PORT))
server.login(EMAIL_USER, EMAIL_PASS)
server.sendmail(EMAIL_FROM, EMAIL_TO, email)
server.close()
logging.debug("Email sent successfully")
except (gaierror, ConnectionRefusedError):
logging.error('Error while sending email: the SMTP server refused the connection')
except smtplib.SMTPServerDisconnected:
logging.error('Error while sending email, check login credentials')
except smtplib.SMTPException as e:
logging.error('Error whiel sending email: General SMTP error: ' + str(e))
os.environ["BORG_PASSPHRASE"]=BACKUP_ENCRYPTION_KEY
os.environ["BORG_HOST_ID"]=BACKUP_NAME
os.environ["BORG_REPO"]=BORG_REPO
if BACKUP_VERBOSE:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
if EMAIL_TEST:
logging.info("Sending test email")
sendEmail("Test email",subject_tag="TEST")
exit(0)
if BORG_CUSTOM_ARGS:
try:
BORG_CUSTOM_ARGS = ast.literal_eval(BORG_CUSTOM_ARGS)
except:
raise Exception("Error while evaluating the BORG_CUSTOM_ARGS env variable, ensure it is a valid python list")
logging.debug("Starting Borg Backup")
if not os.path.isdir(BORG_REPO):
logging.debug("Starting Repository Initialization")
os.mkdir(BORG_REPO)
command = ['borg', 'init', '--encryption=repokey']
logging.debug("Executing command: " + str(command))
try:
output = subprocess.run(command, shell=False,capture_output=True, check=True)
except subprocess.CalledProcessError as error:
logging.fatal("There was a problem initializing the repository")
sendEmail("Error during repository initialization, borg said: " + str(error.stderr), subject_tag="ERROR_BORG")
raise Exception("Error running command: " + str(error.stderr))
logging.debug("Ending Repository Initialization")
borg_pid = subprocess.run(['pidof','borg'],shell=False,capture_output=True)
if not borg_pid.stdout:
logging.debug("Clearing Locks; Borg Not Running")
subprocess.run(['borg','break-lock'],shell=False,check=True)
logging.debug("Starting Daily Archive")
timestamp = strftime("%Y-%m-%d-%s", localtime())
command = ['borg','create','::'+timestamp,'/data']
if BORG_CUSTOM_ARGS:
command[2:0] = BORG_CUSTOM_ARGS
logging.debug("Executing command: " + str(command))
try:
output = subprocess.run(command,shell=False,check=True,capture_output=True)
except subprocess.CalledProcessError as error:
logging.fatal("There was a problem creating the daily archive")
sendEmail("Error during archive creation, borg said: " + str(error.stderr), subject_tag="ERROR_BORG")
raise Exception("Error running command: " + str(error.stderr))
if BACKUP_PRUNE:
logging.debug("Starting Prune")
BACKUP_PRUNE=BACKUP_PRUNE.split()
command = ['borg','prune']
command+=BACKUP_PRUNE
try:
output = subprocess.run(command,shell=False,check=True,capture_output=True)
except subprocess.CalledProcessError as error:
logging.warning("There was a problem pruning the daily archive")
sendEmail("Error during archive prune: " + str(error.stderr), subject_tag="ERROR_PRUNE")
raise Exception("Error running command: " + str(error.stderr))
logging.debug("Ending Prune")
logging.debug("Ending Daily Archive")
logging.debug("Ending Borg Backup")
logging.debug("Starting Rclone")
command = ['rclone','sync','--transfers','16',BORG_REPO,BACKUP_LOCATION]
logging.debug("Executing command: " + str(command))
try:
output = subprocess.run(command,shell=False,capture_output=True,check=True)
except subprocess.CalledProcessError as error:
logging.fatal("There was a problem syncing the backup")
sendEmail("Error during rclone sync, rclone said: " + str(error.stderr), subject_tag="ERROR_RCLONE")
raise Exception("Error running command: " + str(error.stderr))
logging.debug("Ending Rclone")
logging.debug("Ending Backup")
sendEmail("Backup was successful")