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-18 22:40:07 +02:00
|
|
|
@bp.route("/scodoc-installmgr/upload-dump", methods=["POST"])
|
2021-09-18 17:38:52 +02:00
|
|
|
def upload_dump():
|
|
|
|
"""
|
|
|
|
Réception d'un fichier de dump uploadé
|
|
|
|
"""
|
|
|
|
log = open(LOG_FILENAME, "a")
|
2021-09-18 22:36:55 +02:00
|
|
|
log.write("hello\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)
|
|
|
|
|
|
|
|
log.write("{fulltime} request from {remote_addr}\n")
|
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"])
|
|
|
|
the_file = request.files["file"]
|
|
|
|
filename = the_file.filename
|
2021-09-18 22:43:04 +02:00
|
|
|
data = the_file.read()
|
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 = ""
|
|
|
|
|
|
|
|
D = {
|
|
|
|
"dept_name": request.form["dept_name"],
|
|
|
|
"serial": request.form["serial"],
|
|
|
|
"sco_user": request.form["sco_user"],
|
|
|
|
"sent_by": request.form["sent_by"],
|
|
|
|
"sco_version": request.form["sco_version"],
|
|
|
|
"sco_subversion": request.form["sco_subversion"],
|
|
|
|
"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
|
|
|
|
|
|
|
|
cur_size = int(subprocess.check_output(["du", "-skx", REPOSIT_DIR]).split("\t")[0])
|
|
|
|
|
|
|
|
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")
|
|
|
|
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-18 22:36:55 +02:00
|
|
|
log.close()
|
2021-09-18 17:38:52 +02:00
|
|
|
return ("", 204) # ok empty response
|
|
|
|
|
|
|
|
|
|
|
|
# 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-18 22:36:55 +02:00
|
|
|
return serial
|