5 Commits

6 changed files with 197 additions and 2 deletions

View File

@@ -1 +1 @@
1.0.0
1.1.0

View File

@@ -21,6 +21,7 @@ from ConfBack.config import DefaultConfig
from ConfBack.auth import auth
from ConfBack.account import account
from ConfBack.params import params
from ConfBack.datetime import dt
from ConfBack.schedule import schedule
from ConfBack.log import log as logs
from ConfBack.infos import info
@@ -135,5 +136,5 @@ def configure_blueprints(app=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)

View File

@@ -9,6 +9,7 @@
import sys, re, os
import logging as log
from datetime import datetime, timezone
import time
from flask import Flask, Blueprint, request, abort, jsonify, current_app
from flask_api import status
@@ -25,6 +26,8 @@ import hashlib
import subprocess
from werkzeug.exceptions import HTTPException
from ConfBack.manager import Sock
#########################################################
# Class et Methods #
@@ -166,6 +169,18 @@ def reboot():
if os.path.exists(userpath):
shutil.rmtree(userpath)
conn = Sock(addr=current_app.config['UNIX_ADDR'], logger=current_app.logger)
if not conn.connect():
current_app.logger.error("impossible de se connecter au serveur")
else:
# send order to KineIntercom process
if not conn.send(b"SHUTDOWN\n"):
conn.disconnect()
current_app.logger.error("impossible de communiquer avec le serveur")
conn.disconnect()
time.sleep(3)
reboot_cmd = ['sudo', '/bin/systemctl', 'reboot']
if not execute_cmd(reboot_cmd):
abort(status.HTTP_500_INTERNAL_SERVER_ERROR,
@@ -186,6 +201,18 @@ def shutdown():
if os.path.exists(userpath):
shutil.rmtree(userpath)
conn = Sock(addr=current_app.config['UNIX_ADDR'], logger=current_app.logger)
if not conn.connect():
current_app.logger.error("impossible de se connecter au serveur")
else:
# send order to KineIntercom process
if not conn.send(b"SHUTDOWN\n"):
conn.disconnect()
current_app.logger.error("impossible de communiquer avec le serveur")
conn.disconnect()
time.sleep(3)
reboot_cmd = ['sudo', '/bin/systemctl', 'poweroff']
if not execute_cmd(reboot_cmd):
abort(status.HTTP_500_INTERNAL_SERVER_ERROR,

View File

@@ -0,0 +1,6 @@
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : datetime views and models
from .views import dt

147
ConfBack/datetime/views.py Normal file
View File

@@ -0,0 +1,147 @@
# -*- 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
import time
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('/datetime', methods=['GET'])
@jwt_required()
def retreive_datetime():
''' recuperation de la date et heure du système
'''
current_user = get_jwt_identity()
today = datetime.now().strftime("%d/%m/%Y %H:%M")
content = jsonify({'today':today})
return content, status.HTTP_200_OK
@dt.route('/update_datetime', methods=['POST'])
@jwt_required()
def update_datetime():
''' Mise a jour de la date et heure du système
'''
current_app.logger.info("Mise a 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 a l\'heure du système impossible')
if os.path.exists("/dev/rtc0"):
setdate_cmd = ['sudo', '/sbin/hwclock', '-w']
if not execute_cmd(setdate_cmd):
abort(status.HTTP_500_INTERNAL_SERVER_ERROR,
description='Mise a l\'heure de l\horloge materielle impossible')
else:
current_app.logger.warning("horloge materielle non presente ...")
current_app.logger.warning("On doit recréer un token JWT ....")
access_token = create_access_token(identity=current_user)
# 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.
content = jsonify({'message':'maj date and time successful!'})
set_access_cookies(content, access_token)
return content, status.HTTP_200_OK

View File

@@ -146,3 +146,17 @@ def is_alive():
content = {'alive':ret}
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