forked from open-eats/OpenEats
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackup.py
130 lines (103 loc) · 4.54 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
#!/usr/bin/env python3
# Creates a backup for the OpenEats database and images
#
# See docs/Taking_and_Restoring_Backups.md for directions on using this script
import errno
import os
import shutil
import subprocess
import sys
from datetime import datetime
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from google.oauth2 import service_account
# Other Variables
OPENEATS_DIR = "/home/pi/OpenEats"
TMP_DIR = "/tmp"
ENV_FILE = "env_prod.list"
SQL_DUMP_FILE_NAME = "openeats_dump.sql"
IMAGES_DIR_NAME = "images"
def mkdir(dir):
try:
os.mkdir(dir)
except OSError as e:
print(f"Problem creating directory at {dir}: {e}", file=sys.stderr)
exit(1)
def run_process(cmd, shell=False):
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell)
out, err = process.communicate()
if len(out) > 0:
print(out)
if len(err) > 0:
print(err, file=sys.stderr)
if process.returncode != 0:
cmd_string = " ".join(cmd)
print(f"process ({cmd_string}) exited with code {process.returncode}")
exit(1)
# Script Start
os.chdir(OPENEATS_DIR)
try:
with open(ENV_FILE, 'r') as fh:
vars_dict = dict(
tuple(line.strip().split('='))
for line in fh.readlines() if not line.startswith('#') and line.strip()
)
except Exception as e:
print(f"Unable to load vars from {ENV_FILE}: {e}", file=sys.stderr)
exit(1)
try:
DATABASE_PASSWORD = vars_dict['MYSQL_ROOT_PASSWORD']
DATABASE_NAME = vars_dict['MYSQL_DATABASE'] if 'MYSQL_DATABASE' in vars_dict else "openeats"
DATABASE_USER = vars_dict['MYSQL_USER'] if 'MYSQL_USER' in vars_dict else "openeats"
BACKUP_GOOGLE_DRIVE = vars_dict['BACKUP_GOOGLE_DRIVE'].lower() == 'true' if 'BACKUP_GOOGLE_DRIVE' in vars_dict else False
if BACKUP_GOOGLE_DRIVE:
GOOGLE_DRIVE_CREDENTIALS_FILE = vars_dict['GOOGLE_DRIVE_CREDENTIALS_FILE']
GOOGLE_DRIVE_BACKUP_FOLDER_ID = vars_dict['GOOGLE_DRIVE_BACKUP_FOLDER_ID']
DATABASE_HOSTED_IN_DOCKER = vars_dict['DATABASE_HOSTED_IN_DOCKER'].lower() == 'true' if 'DATABASE_HOSTED_IN_DOCKER' in vars_dict else True
except KeyError as e:
print(f"MYSQL_ROOT_PASSWORD or GOOGLE_API_KEY missing from {ENV_FILE}: {e}", file=sys.stderr)
exit(1)
backup_name = datetime.now().strftime("openeats-%Y-%m-%d_%H_%M")
backup_dir = os.path.join(TMP_DIR, backup_name)
mkdir(backup_dir)
# Get a SQL dump from the MySQL Database.
# Note that my Fork hosts the database on the RPi, not Docker for me the command is:
# mysqldump openeats -u openeats -p"<PASSWORD>" > dump.sql
if DATABASE_HOSTED_IN_DOCKER:
dump_cmd = f"docker exec openeats_db_1 sh -c 'exec mysqldump {DATABASE_NAME} -u {DATABASE_USER} --password=\"{DATABASE_PASSWORD}\"' > {os.path.join(backup_dir, SQL_DUMP_FILE_NAME)}"
else:
dump_cmd = f"mysqldump {DATABASE_NAME} -u {DATABASE_USER} --password='{DATABASE_PASSWORD}' > {os.path.join(backup_dir, SQL_DUMP_FILE_NAME)}"
run_process(dump_cmd, shell=True)
# Backup the images
images_dir = os.path.join(backup_dir, IMAGES_DIR_NAME)
mkdir(images_dir)
img_cp_cmd = ["docker", "cp", "openeats_api_1:/code/site-media/", images_dir]
run_process(img_cp_cmd)
# Zip the folder
backup_zip = shutil.make_archive(backup_dir, 'zip', backup_dir)
shutil.rmtree(backup_dir)
drive_backup_failure = False
if BACKUP_GOOGLE_DRIVE:
try:
if not os.path.exists(GOOGLE_DRIVE_CREDENTIALS_FILE):
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), GOOGLE_DRIVE_CREDENTIALS_FILE)
# Load the creds and create the service
SCOPES = ['https://www.googleapis.com/auth/drive.file']
creds = service_account.Credentials.from_service_account_file(GOOGLE_DRIVE_CREDENTIALS_FILE, scopes=SCOPES)
service = build('drive', 'v3', credentials=creds)
print(f"Uploading file {backup_zip} to Google Drive...")
_, drive_file_name = os.path.split(backup_zip)
# Create and send the file creation request
body = {
'name': drive_file_name,
'parents': [GOOGLE_DRIVE_BACKUP_FOLDER_ID]
}
media = MediaFileUpload(backup_zip, mimetype='application/zip')
drive_file = service.files().create(body=body, media_body=media).execute()
print(f"Created file {drive_file.get('name')} id {drive_file.get('id')}.")
except Exception as e:
print(f"Unable to upload {backup_zip} to Google Drive: {e}")
drive_backup_failure = True
if BACKUP_GOOGLE_DRIVE:
os.remove(backup_zip)
exit(drive_backup_failure)