From 872e531ef5fd037fb00d5169903129f66b7bc179 Mon Sep 17 00:00:00 2001 From: Tobias Kurze Date: Wed, 13 Nov 2019 08:19:39 +0100 Subject: [PATCH] added logging conf and now checking recording status with simple script ; notifications are missing --- backend/__init__.py | 70 +++- backend/config.py | 158 ++++----- backend/models/initial_recorders.json | 344 ++++++++++---------- backend/recorder_adapters/epiphan_base.py | 17 +- backend/recorder_adapters/extron_smp.py | 24 +- backend/tools/import_excel_recorder_list.py | 1 + backend/tools/simple_state_checker.py | 87 ++++- 7 files changed, 436 insertions(+), 265 deletions(-) diff --git a/backend/__init__.py b/backend/__init__.py index 97f8753..217b2b3 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -2,7 +2,9 @@ """ Backend base module """ - +import logging +from logging.config import dictConfig +import coloredlogs as coloredlogs import jwt import requests from flask import Flask, jsonify @@ -11,6 +13,72 @@ from flask_jwt_extended import JWTManager, decode_token from flask_login import LoginManager from flask_sqlalchemy import SQLAlchemy from flask_cors import CORS +from backend.config import Config + +__author__ = "Tobias Kurze" +__copyright__ = "Copyright 2019, Tobias Kurze, KIT" +__credits__ = ["Tobias Kurze"] +__license__ = "" +__version__ = "0.9.0" +__maintainer__ = "Tobias Kurze" +__email__ = "it@t-kurze.de" +# __status__ = "Production" +__status__ = "Development" + + +dictConfig({ + 'version': 1, + 'formatters': { + 'default': { + 'format': '[%(asctime)s] {%(threadName)s} %(levelname)s in %(module)s, line %(lineno)d: %(message)s', + } + }, + 'handlers': { + 'wsgi': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://flask.logging.wsgi_errors_stream', + 'formatter': 'default' + }, + 'root_file': { + 'class': 'logging.handlers.TimedRotatingFileHandler', + 'filename': Config.ROOT_LOG_FILE, + 'when': 'd', + 'interval': 1, + 'backupCount': 3, + 'formatter': 'default', + }, + 'file': { + 'class': 'logging.handlers.TimedRotatingFileHandler', + 'filename': Config.LOG_FILE, + 'when': 'd', + 'interval': 1, + 'backupCount': 5, + 'formatter': 'default', + }, + 'errors_file': { + 'class': 'logging.handlers.TimedRotatingFileHandler', + 'filename': Config.ERROR_LOG_FILE, + 'when': 'd', + 'interval': 1, + 'backupCount': 5, + 'level': 'ERROR', + 'formatter': 'default', + }, + }, + 'loggers': { + 'mal': { + 'level': Config.LOG_LEVEL, + 'handlers': ['wsgi', 'file', 'errors_file'] + } + }, + 'root': { + 'level': 'ERROR', + 'handlers': ['root_file', 'errors_file'] + } +}) + +main_logger = logging.getLogger("lrc") +coloredlogs.install(level='DEBUG', logger=main_logger) class LrcException(Exception): diff --git a/backend/config.py b/backend/config.py index 755a6ba..d191a36 100644 --- a/backend/config.py +++ b/backend/config.py @@ -1,75 +1,85 @@ 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 diff --git a/backend/models/initial_recorders.json b/backend/models/initial_recorders.json index 8610b8c..6d24a36 100644 --- a/backend/models/initial_recorders.json +++ b/backend/models/initial_recorders.json @@ -1,63 +1,63 @@ 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 @@ -87,118 +87,118 @@ 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 diff --git a/backend/recorder_adapters/epiphan_base.py b/backend/recorder_adapters/epiphan_base.py index 4e62347..8d90515 100644 --- a/backend/recorder_adapters/epiphan_base.py +++ b/backend/recorder_adapters/epiphan_base.py @@ -19,7 +19,10 @@ PW = "lrgrashof+-" class EpiphanV1(RecorderAdapter): - def __init__(self, admin_user: str, admin_pw: str): + def __init__(self, url: str, admin_user: str, admin_pw: str): + if not url.startswith('http'): + url = 'http://' + url + self.url = url self.user = admin_user self.password = admin_pw self.session = requests.Session() @@ -32,13 +35,13 @@ class EpiphanV1(RecorderAdapter): pass def get_status(self) -> dict: - res = self.session.get(BASE_URL + "/admin/ajax/recorder_status.cgi") + res = self.session.get(self.url + "/admin/ajax/recorder_status.cgi") if res.ok: return res.json() raise LrcException(res.text, res.status_code) def get_sysinfo(self) -> dict: - res = self.session.get(BASE_URL + "/ajax/sysinfo.cgi") + res = self.session.get(self.url + "/ajax/sysinfo.cgi") if res.ok: return res.json() raise LrcException(res.text, res.status_code) @@ -55,13 +58,13 @@ class EpiphanV1(RecorderAdapter): return self.get_status().get('seconds', None) def start_recording(self): - res = self.session.get(BASE_URL + "/admin/ajax/start_recorder.cgi") + res = self.session.get(self.url + "/admin/ajax/start_recorder.cgi") if not res.ok: raise LrcException(res.text, res.status_code) time.sleep(2) # just a little bit of waiting time -> it takes a bit for the Epiphan to update its state def stop_recording(self): - res = self.session.get(BASE_URL + "/admin/ajax/stop_recorder.cgi") + res = self.session.get(self.url + "/admin/ajax/stop_recorder.cgi") if not res.ok: raise LrcException(res.text, res.status_code) time.sleep(4) # just a little bit of waiting time -> it takes a bit for the Epiphan to update its state @@ -106,7 +109,7 @@ class EpiphanV1(RecorderAdapter): raise LrcException(str(err)) def get_screenshot(self): - ret = self.session.get(BASE_URL + "/admin/grab_frame.cgi?size=256x192&device=DAV93133.vga&_t=1573471990578", + ret = self.session.get(self.url + "/admin/grab_frame.cgi?size=256x192&device=DAV93133.vga&_t=1573471990578", stream=True) print(ret) @@ -117,7 +120,7 @@ class EpiphanV1(RecorderAdapter): if __name__ == '__main__': - e = EpiphanV1(USER, PW) + e = EpiphanV1(BASE_URL, USER, PW) try: # print(e.is_recording()) """ diff --git a/backend/recorder_adapters/extron_smp.py b/backend/recorder_adapters/extron_smp.py index a736545..ec87e89 100644 --- a/backend/recorder_adapters/extron_smp.py +++ b/backend/recorder_adapters/extron_smp.py @@ -1,5 +1,10 @@ +import logging + +from backend import LrcException from backend.recorder_adapters import telnetlib, TelnetAdapter, RecorderAdapter +logger = logging.getLogger() + RECORDER_MODEL_NAME = "SMP 351 / 352" VERSION = "0.9.0" REQUIRES_USER = False @@ -16,26 +21,34 @@ PW = "123mzsmp" class SMP(TelnetAdapter, RecorderAdapter): - def __init__(self, address, password, **kwargs): + def __init__(self, address, password, auto_login=True, **kwargs): super().__init__(address) self.admin_pw = password + if auto_login: + self._login() def _login(self): - self.tn = telnetlib.Telnet(HOST) + print("Connecting to {} ...".format(self.address)) + try: + self.tn = telnetlib.Telnet(self.address) + except TimeoutError as e: + raise LrcException(str(e)) self.tn.read_until("\r\nPassword:") # password = getpass.getpass() password = self.admin_pw self.tn.write(password + "\n\r") out = self.tn.assert_string_in_output("Login Administrator") + print(out) if not out[0]: print(out[1]) if "Password:" in out[1]: # TODO: loop until logged in... print("re-enter pw") - self.tn.write("123mzsmp\n\r") + self.tn.write(self.admin_pw+"\n\r") print(self.tn.assert_string_in_output("Login Administrator")) print("WRONG (admin) password!! Exiting!") + print(self.admin_pw) self.tn = None raise Exception("Could not login as administrator with given pw!") print("OK, we have admin rights!") @@ -369,6 +382,9 @@ class SMP(TelnetAdapter, RecorderAdapter): self.tn.write("{}YRCDR\n".format(self.esc_char)) return TelnetAdapter._get_response_str(self.tn.read_until_non_empty_line()) + def is_recording(self): + return self.get_recording_status() == 1 + def extent_recording_time(self, extension_time: int): """ Extends a scheduled recording by extension_time minutes @@ -764,7 +780,7 @@ class SMP(TelnetAdapter, RecorderAdapter): def main(): - smp = SMP(HOST, PW) + smp = SMP(HOST, PW, False) print(smp) smp._login() print(smp.get_version(verbose_info=False)) diff --git a/backend/tools/import_excel_recorder_list.py b/backend/tools/import_excel_recorder_list.py index db78551..b03cefc 100644 --- a/backend/tools/import_excel_recorder_list.py +++ b/backend/tools/import_excel_recorder_list.py @@ -48,6 +48,7 @@ for r in recorders: 'type': 'SMP 351' if 'SMP 351' in r['Rekorder-Typ'] else r['Rekorder-Typ'], 'additional_camera': r['Zus. Kamera'] == 'Ja', 'firmware_version': r['FW – Vers.'], + 'network_name': r['DNS'], 'description': json.dumps( {'comment': r['Bemerkung'], 'network_port': r['Dosennummer'], 'rsync_name': r['Rsync-Name']})} nicely_formatted_recorders.append(rec) diff --git a/backend/tools/simple_state_checker.py b/backend/tools/simple_state_checker.py index 5aabfd0..222449a 100644 --- a/backend/tools/simple_state_checker.py +++ b/backend/tools/simple_state_checker.py @@ -1,3 +1,8 @@ +import json +import os +import logging +from multiprocessing.pool import ThreadPool + from pprint import pprint import requests @@ -5,6 +10,14 @@ from requests.auth import HTTPBasicAuth from ics import Calendar from backend.config import Config +from backend.recorder_adapters.epiphan_base import EpiphanV1 +from backend.recorder_adapters.extron_smp import SMP + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +stream_handler = logging.StreamHandler() +stream_handler.setLevel(logging.DEBUG) +logger.addHandler(stream_handler) base_url = "https://opencast.bibliothek.kit.edu" @@ -13,6 +26,8 @@ session.auth = HTTPBasicAuth(Config.OPENCAST_USER, Config.OPENCAST_PW) config = {'service_urls': {}} +recorders = None + def get_service_url(service_type: str): if service_type in config['service_urls']: @@ -24,7 +39,7 @@ def get_service_url(service_type: str): service = res.json()["services"]["service"] config["service_urls"][service_type] = service["host"] + \ service["path"] - return service["host"] +service["path"] + return service["host"] + service["path"] return None @@ -43,13 +58,71 @@ def get_capture_agents(): if res.ok: return res.json()["agents"]["agent"] + +def get_recorder_details(): + """Temporary implementation using initial_recorders.json. Should be replaced by DB layer later!""" + global recorders + if recorders is None: + f = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, 'models', 'initial_recorders.json')) + with open(f, 'r') as json_file: + recorders = json.load(json_file)['recorders'] + return recorders + + +def get_recorder_by_name(name: str): + for r in get_recorder_details(): + if r["name"] == name: + return r + return None + + +def notify_users_of_problem(msg: str): + pass + + +def check_capture_agent_state(a: dict): + logger.debug("Checking Agent {}".format(a['name'])) + c = get_calender(a['name']) + is_recording_in_calendar = len(list(c.timeline.now())) >= 1 + if is_recording_in_calendar: + if a['state'] == "capturing": + print( + "{} is in capturing state, so there should be an entry in the calendar of the recorder, right? -> {}".format( + a['name'], is_recording_in_calendar + )) + rec = get_recorder_by_name(a['name']) + print(rec) + if "SMP" in rec["type"]: + print("using SMP adapter") + rec = SMP(rec['ip'], rec['password']) + else: + rec = EpiphanV1(rec['ip'], rec["username"], rec["password"]) + if rec.is_recording(): + print("OK – recorder is recording :)") + else: + logger.info(rec.get_recording_status()) + logger.error("FATAL - recorder {} must be recording!!!!".format(a['name'])) + else: + print("FATAL: {} is not in capturing state...but should be!!".format(a['name'])) + else: + rec = get_recorder_by_name(a['name']) + if "SMP" in rec["type"]: + logger.debug("using SMP adapter") + rec = SMP(rec['ip'], rec['password']) + else: + rec = EpiphanV1(rec['ip'], rec["username"], rec["password"]) + if rec.is_recording(): + logger.error("FATAL - recorder must not be recording!!!!") + else: + logger.info("OK – recorder is not recording :)") + + agents = get_capture_agents() -for a in agents: - print(a['name']) - print(a['state']) - if a['state'] == "capturing": - c = get_calender(a['name']) - print(list(c.timeline.now())) +logger.info("Got {} capture agents that will be checked...".format(len(agents))) + +pool = ThreadPool(5) +pool.map(check_capture_agent_state, agents) + exit() c = get_calender('CS 30.46 Chemie Neuer Hoersaal')