-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
185 lines (143 loc) · 5.13 KB
/
app.py
File metadata and controls
185 lines (143 loc) · 5.13 KB
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import logging
import os
import sys
from flask import Flask, g, redirect, render_template, request, send_file
from redis import Redis
from rq import Queue
from rq.exceptions import NoSuchJobError
from rq.job import Job
from rq.registry import StartedJobRegistry
from jobs import initialize_and_start_benches, start_backup
from utils.setup_prerequisite import (
BENCHES_DIRECTORY,
SITE_BACKUP_JOB_ID,
START_BENCHES_JOB_ID,
check_server_status,
)
from utils.site_mapping import get_nginx_config, get_sites_with_available_backups
def configure_logging(level: int = logging.INFO) -> None:
"""Configure global logging for the Flask app."""
logging.basicConfig(
level=level,
format="%(asctime)s | %(levelname)-8s | %(name)s:%(lineno)d - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
stream=sys.stdout,
force=True,
)
configure_logging()
app = Flask(__name__)
queue = Queue(connection=Redis.from_url("redis://localhost:6379/0"))
@app.before_request
def check_setup_status():
s = check_server_status()
g.server_state = s
@app.errorhandler(404)
def page_not_found(_):
return redirect("/")
@app.route("/")
def index():
return render_template(
"index.html",
overall_status=g.server_state.status,
)
# Route for the main page that shows the setup status
@app.route("/setup-status")
def failover_setup_status():
return render_template(
"setup_status.html",
status=g.server_state.status,
services=g.server_state.services,
bench_dir=BENCHES_DIRECTORY,
bench_ok=g.server_state.bench_ok,
benches=g.server_state.benches,
malformed_benches=g.server_state.malformed_benches,
), 200 if g.server_state.status == "ok" else 503
# Skipping the start benches page, the button on status page should all the api
@app.route("/site-mapping")
def site_mapping_page():
try:
job = Job.fetch(START_BENCHES_JOB_ID, connection=queue.connection)
bench_job_status = job.get_status().value
except NoSuchJobError:
bench_job_status = "not started"
nginx_config = get_nginx_config(bench_job_status)
backup_available = get_sites_with_available_backups(nginx_config, queue=queue)
return render_template(
"site_mapping.html",
status=g.server_state.status,
benches=g.server_state.benches,
bench_job_status=bench_job_status,
backup_available=backup_available,
nginx_config=nginx_config,
)
@app.route("/api/job-status")
def job_status_api():
try:
job = Job.fetch(START_BENCHES_JOB_ID, connection=queue.connection)
bench_job_status = job.get_status().value
except NoSuchJobError:
bench_job_status = "not started"
nginx_config = get_nginx_config(bench_job_status)
backup_available = get_sites_with_available_backups(nginx_config, queue=queue)
return {"status": bench_job_status, "backup_available": backup_available}
@app.route("/api/start-benches", methods=["POST"])
def start_benches_api():
try:
existing_job = Job.fetch(START_BENCHES_JOB_ID, connection=queue.connection)
if existing_job.get_status().value in ("queued", "started"):
return {"status": "already running"}, 202
except NoSuchJobError:
pass
queue.enqueue(
initialize_and_start_benches,
benches=g.server_state.benches,
job_id=START_BENCHES_JOB_ID,
)
return {
"status": "queued",
"benches": list(g.server_state.benches.keys()),
"job_id": START_BENCHES_JOB_ID,
}, 202
@app.route("/api/site-backup/download")
def site_backup_download_api():
site = request.args.get("site")
bench_name = request.args.get("bench_name")
if not site or not bench_name:
return {"error": "Site name and bench name is required"}, 400
backup_path = os.path.join(
f"{BENCHES_DIRECTORY}/{bench_name}/sites/{site}/private/backup.tar.gz"
)
if not os.path.exists(backup_path):
return {"error": "No backups found"}
return send_file(backup_path, as_attachment=True, mimetype="application/zip")
@app.route("/api/site-backup", methods=["POST"])
def site_backup_api():
data = request.get_json()
site = data.get("site")
bench_name = data.get("bench_name")
if not site or not bench_name:
return {"error": "Site name and bench name is required"}, 400
try:
existing_job = Job.fetch(
SITE_BACKUP_JOB_ID.format(site), connection=queue.connection
)
if existing_job.get_status().value in ("queued", "started"):
return {"status": "already running"}, 202
except NoSuchJobError:
pass
registry = StartedJobRegistry(queue=queue)
for job in registry.get_job_ids():
if SITE_BACKUP_JOB_ID.replace("-{}", "") in job:
return {"error": "Only one backup can run at a time"}, 400
queue.enqueue(
start_backup,
site=site,
bench_name=bench_name,
job_id=SITE_BACKUP_JOB_ID.format(site),
)
return {
"status": "queued",
"job_id": SITE_BACKUP_JOB_ID.format(site),
}, 202
if __name__ == "__main__":
app.run(debug=True)