From 4e836e61d310a0297eb8cb963304073bf418a60e Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Mon, 30 Aug 2021 11:03:24 +0200 Subject: [PATCH] Debian postinst restart services postgresql and scodoc9. Enhanced error page when DB unavailable. --- app/__init__.py | 34 +++++++++++++++++++++++++++++----- app/scodoc/notesdb.py | 10 ++++++++-- app/templates/error_500.html | 4 +++- app/templates/error_503.html | 34 ++++++++++++++++++++++++++++++++++ sco_version.py | 2 +- tools/debian/postinst | 6 +++++- tools/etc/scodoc9.nginx | 4 ++-- 7 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 app/templates/error_503.html diff --git a/app/__init__.py b/app/__init__.py index 311578b3..a883f89a 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -10,11 +10,9 @@ import traceback import logging from logging.handlers import SMTPHandler, WatchedFileHandler -from flask import request +from flask import current_app, g, request from flask import Flask -from flask import current_app -from flask import g -from flask import has_request_context +from flask import abort, has_request_context from flask import render_template from flask.logging import default_handler from flask_sqlalchemy import SQLAlchemy @@ -24,6 +22,7 @@ from flask_mail import Mail from flask_bootstrap import Bootstrap from flask_moment import Moment from flask_caching import Cache +import sqlalchemy from app.scodoc.sco_exceptions import ScoValueError from config import DevConfig @@ -52,10 +51,31 @@ def handle_sco_value_error(exc): def internal_server_error(e): + """Bugs scodoc, erreurs 500""" # note that we set the 500 status explicitly return render_template("error_500.html", SCOVERSION=sco_version.SCOVERSION), 500 +def render_raw_html(template_filename: str, **args) -> str: + """Load and render an HTML file _without_ using Flask + Necessary for 503 error mesage, when DB is down and Flask may be broken. + """ + template_path = os.path.join( + current_app.config["SCODOC_DIR"], + "app", + current_app.template_folder, + template_filename, + ) + with open(template_path) as f: + txt = f.read().format(**args) + return txt + + +def postgresql_server_error(e): + """Erreur de connection au serveur postgresql (voir notesdb.open_db_connection)""" + return render_raw_html("error_503.html", SCOVERSION=sco_version.SCOVERSION), 503 + + class RequestFormatter(logging.Formatter): """Ajoute URL et remote_addr for logging""" @@ -86,6 +106,7 @@ def create_app(config_class=DevConfig): app.register_error_handler(ScoValueError, handle_sco_value_error) app.register_error_handler(500, internal_server_error) + app.register_error_handler(503, postgresql_server_error) from app.auth import bp as auth_bp @@ -178,7 +199,10 @@ def create_app(config_class=DevConfig): def set_sco_dept(scodoc_dept: str): """Set global g object to given dept and open db connection if needed""" # Check that dept exists - dept = Departement.query.filter_by(acronym=scodoc_dept).first() + try: + dept = Departement.query.filter_by(acronym=scodoc_dept).first() + except sqlalchemy.exc.OperationalError: + abort(503) if not dept: raise ScoValueError(f"Invalid dept: {scodoc_dept}") g.scodoc_dept = scodoc_dept # l'acronyme diff --git a/app/scodoc/notesdb.py b/app/scodoc/notesdb.py index e9fdaf02..135675cc 100644 --- a/app/scodoc/notesdb.py +++ b/app/scodoc/notesdb.py @@ -7,7 +7,7 @@ import psycopg2 import psycopg2.pool import psycopg2.extras -from flask import g, current_app +from flask import g, current_app, abort import app import app.scodoc.sco_utils as scu @@ -36,7 +36,13 @@ def unquote(s): def open_db_connection(): """Open a connection to the database""" - g.db_conn = psycopg2.connect(current_app.config["SQLALCHEMY_DATABASE_URI"]) + try: + g.db_conn = psycopg2.connect(current_app.config["SQLALCHEMY_DATABASE_URI"]) + except psycopg2.OperationalError: + # Dans la majorité des cas, cela signifie que le serveur postgres + # n'est pas lancé. + log("open_db_connection: psycopg2.OperationalError") + abort(503) # HTTP 503 Service Unavailable def close_db_connection(): diff --git a/app/templates/error_500.html b/app/templates/error_500.html index ba960d7a..e093a6af 100644 --- a/app/templates/error_500.html +++ b/app/templates/error_500.html @@ -10,7 +10,9 @@

Si le problème persiste, contacter l'administrateur de votre site, ou écrire la liste "notes" notes@listes.univ-paris13.fr en indiquant la version du logiciel - (plus d'informations sur les listes de diffusion). +
+ (plus d'informations sur les listes de diffusionvoir + cette page).

retour à la page d'accueil

diff --git a/app/templates/error_503.html b/app/templates/error_503.html new file mode 100644 index 00000000..ba0ef9e0 --- /dev/null +++ b/app/templates/error_503.html @@ -0,0 +1,34 @@ + + + + + + Service ScoDoc indisponible ! + + + +
+

Service ScoDoc indisponible !

+
+

+ +

ScoDoc ne parvient pas à charger ses données.

+ +

Le plus souvent, ce problème indique que le serveur de base de données n'est pas lancé + ou ne fonctionne pas correctement: prévenir l'administrateur système ou le service + concerné de votre établissement. +

+ +

retour à la page d'accueil

+ + +

Si le problème persiste après intervention de votre équipe locale, + contacter la liste "notes" notes@listes.univ-paris13.fr en + indiquant la version du logiciel (ScoDoc {SCOVERSION}) +
(pour plus d'informations sur les listes de diffusion voir cette page). +

+ + + + \ No newline at end of file diff --git a/sco_version.py b/sco_version.py index 2ac0ac77..ae606040 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.0.5" +SCOVERSION = "9.0.6" SCONAME = "ScoDoc" diff --git a/tools/debian/postinst b/tools/debian/postinst index c2a3d89f..73167c38 100644 --- a/tools/debian/postinst +++ b/tools/debian/postinst @@ -27,9 +27,11 @@ do echo adding $locname echo "$locname ${locname##*.}" >> /etc/locale.gen /usr/sbin/locale-gen --keep-existing - systemctl restart postgresql fi done +echo "debian postinst: scodoc9 is $(systemctl is-active scodoc9)" +# On a besoin d'un postgresql lancé pour la mise à jour +systemctl restart postgresql # Le numero de version complet, genre 9.0.0 SCODOC_RELEASE=$(grep SCOVERSION $SCODOC_DIR/sco_version.py | awk '{ print substr($3, 2, length($3)-2) }') @@ -123,3 +125,5 @@ systemctl start scodoc-updater.timer systemctl daemon-reload systemctl enable scodoc9 +# --- RESTART SCODOC +systemctl restart scodoc9 diff --git a/tools/etc/scodoc9.nginx b/tools/etc/scodoc9.nginx index ab80d3a4..dbc31caf 100644 --- a/tools/etc/scodoc9.nginx +++ b/tools/etc/scodoc9.nginx @@ -18,8 +18,8 @@ server { ssl_certificate /opt/scodoc-data/certs/cert.pem; ssl_certificate_key /opt/scodoc-data/certs/key.pem; # write access and error logs to /var/log - access_log /var/log/scodoc_access.log; - error_log /var/log/scodoc_error.log; + access_log /var/log/nginx/scodoc_access.log; + error_log /var/log/nginx/scodoc_error.log; location / { # forward application requests to the gunicorn server proxy_pass http://localhost:8000;