installmgr/app/routes.py

181 lines
5.5 KiB
Python
Raw Normal View History

2021-09-18 17:38:52 +02:00
import json, datetime, fcntl, os, re, socket, subprocess, time
from flask import request, abort
from flask import Blueprint
from app import email
bp = Blueprint("routes", __name__)
# --------------------------------------------------------------
DIR = "/opt/installmgr/"
REPOSIT_DIR = "/opt/installmgr/incoming_dumps"
MAX_REPOSIT_SIZE = 100 * 20 * 1024 # kB (here, max 100 dumps of 20MB)
ALERT_MAIL_FROM = "root@scodoc.iutv.univ-paris13.fr"
ALERT_MAIL_TO = "emmanuel.viennet@gmail.com"
LOG_FILENAME = os.path.join(DIR, "upload-dump-errors.log")
UPLOAD_LOG_FILENAME = os.path.join(DIR, "upload-dump-log.json")
DEBUG = False # if false, don't publish error messages
2021-09-18 21:19:01 +02:00
@bp.route("/scodoc-installmgr/last_stable_version")
2021-09-18 17:38:52 +02:00
def last_stable_version():
# LAST_RELEASE_TAG=$(curl "$GITEA_RELEASE_URL" | jq ".[].tag_name" | tr -d -c "0-9.\n" | sort --version-sort | tail -1)
return "9.0.30"
2021-09-19 18:00:22 +02:00
2021-09-18 22:40:07 +02:00
@bp.route("/scodoc-installmgr/upload-dump", methods=["POST"])
2021-09-19 16:01:18 +02:00
def upload_scodoc9():
"""Réception d'un fichier de dump"""
2021-09-18 17:38:52 +02:00
log = open(LOG_FILENAME, "a")
2021-09-19 16:01:18 +02:00
log.write("haallo\n")
2021-09-18 17:38:52 +02:00
now = datetime.datetime.now()
fulltime = now.isoformat()
2021-09-18 21:27:30 +02:00
# client addr:
2021-09-18 22:36:55 +02:00
remote_addr = request.environ.get("HTTP_X_REAL_IP", request.remote_addr)
2021-09-19 16:01:18 +02:00
log.write(f"{fulltime} request from {remote_addr}\n")
log.flush()
2021-09-18 17:38:52 +02:00
# Avec seulement alphanum et tiret:
clean_deptname = re.sub(r"[^A-Za-z-]", "", request.form["dept_name"])
2021-09-19 16:01:18 +02:00
if not clean_deptname:
abort(400, "missing argument: dept_name")
2021-09-18 17:38:52 +02:00
try:
remote_host = socket.gethostbyaddr(remote_addr)[0]
except:
log.write("reverse DNS lookup failed for {}".format(remote_addr))
remote_host = ""
2021-09-19 16:01:18 +02:00
the_file = request.files["file"]
filename = the_file.filename
data = the_file.read()
2021-09-18 17:38:52 +02:00
D = {
"dept_name": request.form["dept_name"],
"serial": request.form["serial"],
"sco_user": request.form["sco_user"],
"sent_by": request.form["sent_by"],
2021-09-19 18:00:22 +02:00
"sco_version": request.form.get("sco_version", ""), # release
2021-09-19 16:01:18 +02:00
"sco_subversion": request.form.get("sco_subversion", ""),
2021-09-18 17:38:52 +02:00
"dump_filename": fulltime + "_" + clean_deptname + ".gz",
"dump_size": len(data),
"remote_addr": remote_addr,
"remote_host": remote_host,
}
log.write("received data ({} bytes)\n".format(D["dump_size"]))
json_descr = json.dumps(D, sort_keys=True, indent=4)
# --- Check disk space
2021-09-19 18:00:22 +02:00
cur_size = int(
subprocess.check_output(["du", "-skx", REPOSIT_DIR])
.decode("utf-8")
.split("\t")[0]
)
2021-09-18 17:38:52 +02:00
if (cur_size + len(data) / 1024) > MAX_REPOSIT_SIZE:
# out of space !
log.write(
"Out of space: cur_size={}kB, limit={}\n".format(cur_size, MAX_REPOSIT_SIZE)
)
# Send alert
try:
email.send_email(
"[upload-dump] Out of space !",
ALERT_MAIL_FROM,
[ALERT_MAIL_TO],
"Out space !\nNew upload was canceled:\n" + json_descr,
)
except:
log.write("exception while sending email !\n")
2021-09-19 16:01:18 +02:00
log.close()
2021-09-18 17:38:52 +02:00
abort(507, "Insufficient Storage")
else:
log.write("writing dump to {}\n".format(D["dump_filename"]))
# dump:
f = open(os.path.join(REPOSIT_DIR, D["dump_filename"]), "wb")
f.write(data)
f.close()
uplog = open(UPLOAD_LOG_FILENAME, "a")
uplog.write(json_descr)
uplog.write("\n,\n") # separator
uplog.close()
# Send notification
try:
log.write("sending notification to {}\n".format(ALERT_MAIL_TO))
email.send_email(
f"[upload-dump] new dump {D['dept_name']} from {D['remote_addr']} ({D['remote_host']})",
ALERT_MAIL_FROM,
[ALERT_MAIL_TO],
"New upload:\n" + json_descr,
)
except:
log.write("exception while sending email !\n")
2021-09-19 16:01:18 +02:00
2021-09-18 22:36:55 +02:00
log.close()
2021-09-19 16:10:24 +02:00
return "Données envoyées."
2021-09-18 17:38:52 +02:00
2021-09-19 16:01:18 +02:00
@bp.route("/scodoc-installmgr/scodoc9")
def scodoc9():
"""
Réception d'un fichier de dump uploadé
"""
log = open(LOG_FILENAME, "a")
log.write("hello\n")
2021-09-18 17:38:52 +02:00
# Lock for counter
class Lock:
def acquire(self):
self.f = open("lock", "w")
fcntl.flock(self.f.fileno(), fcntl.LOCK_EX)
def release(self):
self.f.close()
def increment():
L = Lock()
L.acquire()
try:
try:
val = int(open(DIR + "/counter").read())
except:
val = 0
val += 1
open("counter", "w").write("%d" % val)
finally:
L.release()
return val
2021-09-18 21:19:01 +02:00
@bp.route("/scodoc-installmgr/version", methods=["GET"])
2021-09-18 17:38:52 +02:00
def version():
"""
2021-09-18 17:52:33 +02:00
echo -e "DATE\tIP\tSVN\tSERIAL\tOP" > installs.log; chown scodoc installs.log
2021-09-18 17:38:52 +02:00
"""
2021-09-18 21:35:52 +02:00
remote_addr = request.environ.get("HTTP_X_REAL_IP", request.remote_addr)
2021-09-18 17:38:52 +02:00
mode = request.args.get("mode", "?")
2021-09-18 17:52:33 +02:00
sn = request.args.get("sn", "-1") # serial number
2021-09-18 21:40:49 +02:00
svn = request.args.get("svn", "") # installed subversion (ScoDoc 7)
2021-09-18 21:35:52 +02:00
release = request.args.get("release", "") # ScoDoc 9 prod installs
commit = request.args.get("commit", "") # installed git commit (devs)
2021-09-18 17:38:52 +02:00
if mode == "install" or not sn:
serial = increment()
else:
serial = sn
f = open(DIR + "installs.log", "a")
f.write(
2021-09-18 21:40:49 +02:00
"%s\t%s\t%s\t%s\t%s\n"
2021-09-18 17:38:52 +02:00
% (
time.strftime("%Y-%m-%d %H:%M:%S"),
2021-09-18 21:32:52 +02:00
remote_addr,
2021-09-18 21:35:52 +02:00
svn or commit or release or "-",
2021-09-18 17:38:52 +02:00
serial,
mode,
)
)
f.close()
2021-09-19 18:00:22 +02:00
return str(serial)