ajout des routes pour l'affichage de l'état de la rtc ou de la mise à jour de la date et heure du système
This commit is contained in:
+2
-1
@@ -21,6 +21,7 @@ from ConfBack.config import DefaultConfig
|
|||||||
from ConfBack.auth import auth
|
from ConfBack.auth import auth
|
||||||
from ConfBack.account import account
|
from ConfBack.account import account
|
||||||
from ConfBack.params import params
|
from ConfBack.params import params
|
||||||
|
from ConfBack.datetime import dt
|
||||||
from ConfBack.schedule import schedule
|
from ConfBack.schedule import schedule
|
||||||
from ConfBack.log import log as logs
|
from ConfBack.log import log as logs
|
||||||
from ConfBack.infos import info
|
from ConfBack.infos import info
|
||||||
@@ -135,5 +136,5 @@ def configure_blueprints(app=None):
|
|||||||
|
|
||||||
:return None:
|
:return None:
|
||||||
'''
|
'''
|
||||||
for bp in [auth, logs, account, params, schedule, info]:
|
for bp in [auth, logs, account, params, dt, schedule, info]:
|
||||||
app.register_blueprint(bp)
|
app.register_blueprint(bp)
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# @author : vincent.benoit@benserv.fr
|
||||||
|
# @brief : datetime views and models
|
||||||
|
|
||||||
|
from .views import dt
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# @author : vincent.benoit@benserv.fr
|
||||||
|
# @brief : Datetime routes
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# Importation de modules externes #
|
||||||
|
|
||||||
|
import sys, re, os
|
||||||
|
import logging as log
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
from flask import Flask, Blueprint, request, abort, jsonify, current_app
|
||||||
|
from flask_api import status
|
||||||
|
from flask_jwt_extended import create_access_token
|
||||||
|
from flask_jwt_extended import get_jwt
|
||||||
|
from flask_jwt_extended import set_access_cookies
|
||||||
|
from flask_jwt_extended import unset_jwt_cookies
|
||||||
|
from flask_jwt_extended import get_jwt_identity
|
||||||
|
from flask_jwt_extended import jwt_required
|
||||||
|
|
||||||
|
import json
|
||||||
|
import shutil
|
||||||
|
import hashlib
|
||||||
|
import subprocess
|
||||||
|
from werkzeug.exceptions import HTTPException
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# Class et Methods #
|
||||||
|
|
||||||
|
dt = Blueprint('datetime', __name__, url_prefix='/api/configurateur')
|
||||||
|
|
||||||
|
@dt.errorhandler(HTTPException)
|
||||||
|
def handle_exception(e):
|
||||||
|
''' return JSON instead of HTML for HTTP errors '''
|
||||||
|
response = e.get_response()
|
||||||
|
# replace the body with JSON
|
||||||
|
response.data = json.dumps({
|
||||||
|
'code': e.code,
|
||||||
|
'name': e.name,
|
||||||
|
'description': e.description,
|
||||||
|
})
|
||||||
|
response.content_type = "application/json"
|
||||||
|
return response
|
||||||
|
|
||||||
|
@dt.after_request
|
||||||
|
def refresh_expiring_tokens(response):
|
||||||
|
''' Using an 'after_request' callback, we refresh any token that is within
|
||||||
|
30 minutes of expiring.'''
|
||||||
|
try:
|
||||||
|
exp_timestamp = get_jwt()['exp']
|
||||||
|
now = datetime.now(timezone.utc)
|
||||||
|
target_timestamp = datetime.timestamp(now + current_app.config['DELTA'])
|
||||||
|
if target_timestamp > exp_timestamp:
|
||||||
|
current_app.logger.warning("On doit recréer un token JWT ....")
|
||||||
|
access_token = create_access_token(identity=get_jwt_identity())
|
||||||
|
# refresh token in storage place
|
||||||
|
if os.path.exists(os.path.join("/tmp", current_app.config['PROJECT'])):
|
||||||
|
with open(os.path.join("/tmp", current_app.config['PROJECT'], get_jwt_identity()['id']), 'w') as f:
|
||||||
|
f.write(access_token)
|
||||||
|
# Modifiy a Flask Response to set a cookie containing the access JWT.
|
||||||
|
set_access_cookies(response, access_token)
|
||||||
|
return response
|
||||||
|
except (RuntimeError, KeyError):
|
||||||
|
return response
|
||||||
|
|
||||||
|
def execute_cmd(args=""):
|
||||||
|
''' Execute system command
|
||||||
|
'''
|
||||||
|
out = None
|
||||||
|
err = None
|
||||||
|
if len(args) == 0:
|
||||||
|
current_app.logger.error("Paramètre d'entrée invalide")
|
||||||
|
return False
|
||||||
|
|
||||||
|
current_app.logger.debug("La commande système executée est : {}".format(args))
|
||||||
|
try:
|
||||||
|
cmd = subprocess.Popen(args,
|
||||||
|
shell=False,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
(out, err) = cmd.communicate(timeout=10)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
current_app.logger.error("Error executing system command : {} - {}".format(e.output, e.returncode))
|
||||||
|
return False
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
cmd.kill()
|
||||||
|
current_app.logger.error("Timeout when executing system command")
|
||||||
|
return False
|
||||||
|
except FileNotFoundError:
|
||||||
|
current_app.logger.error("System command not found")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if cmd.returncode != 0:
|
||||||
|
current_app.logger.error('Error executing system command ({})'.format(cmd.returncode))
|
||||||
|
current_app.logger.error('{}'.format(err))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@dt.route('/update_datetime', methods=['POST'])
|
||||||
|
@jwt_required()
|
||||||
|
def update_datetime():
|
||||||
|
''' Mise à jour de la date et heure du système
|
||||||
|
'''
|
||||||
|
current_app.logger.info("Mise à jour de la date et heure du système")
|
||||||
|
current_user = get_jwt_identity()
|
||||||
|
# recuperation des attributs JSON de la requete
|
||||||
|
data_req = request.get_json()
|
||||||
|
current_app.logger.debug("Nouvelle date et heure: {}".format(data_req['datetime']))
|
||||||
|
setdate_cmd = ['sudo', '/bin/date', '-s', data_req['datetime']]
|
||||||
|
if not execute_cmd(setdate_cmd):
|
||||||
|
abort(status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
description='Mise à l\'heure du système impossible')
|
||||||
|
|
||||||
|
setdate_cmd = ['sudo', '/sbin/hwclock', '-w']
|
||||||
|
if not execute_cmd(setdate_cmd):
|
||||||
|
abort(status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
description='Mise à l\'heure de l\horloge matérielle impossible')
|
||||||
|
|
||||||
|
content = {'message':'maj date and time successful!'}
|
||||||
|
return content, status.HTTP_200_OK
|
||||||
|
|
||||||
@@ -146,3 +146,17 @@ def is_alive():
|
|||||||
|
|
||||||
content = {'alive':ret}
|
content = {'alive':ret}
|
||||||
return jsonify(content), status.HTTP_200_OK
|
return jsonify(content), status.HTTP_200_OK
|
||||||
|
|
||||||
|
@info.route('/rtc_alive', methods=['GET'])
|
||||||
|
@jwt_required()
|
||||||
|
def rtc_alive():
|
||||||
|
''' RTC is alive ? '''
|
||||||
|
ret = False
|
||||||
|
if os.path.exists("/dev/rtc0"):
|
||||||
|
current_app.logger.info("L'horloge matérielle est présente ...")
|
||||||
|
ret = True
|
||||||
|
else:
|
||||||
|
current_app.logger.warning("L'horloge matérielle n'est pas présente ...")
|
||||||
|
|
||||||
|
content = {'RTCalive':ret}
|
||||||
|
return jsonify(content), status.HTTP_200_OK
|
||||||
|
|||||||
Reference in New Issue
Block a user