added logging conf and now checking recording status with simple script ; notifications are missing

This commit is contained in:
Tobias Kurze
2019-11-13 08:19:39 +01:00
parent 4563e16137
commit 872e531ef5
7 changed files with 436 additions and 265 deletions

View File

@@ -2,7 +2,9 @@
""" """
Backend base module Backend base module
""" """
import logging
from logging.config import dictConfig
import coloredlogs as coloredlogs
import jwt import jwt
import requests import requests
from flask import Flask, jsonify from flask import Flask, jsonify
@@ -11,6 +13,72 @@ from flask_jwt_extended import JWTManager, decode_token
from flask_login import LoginManager from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS 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): class LrcException(Exception):

View File

@@ -1,75 +1,85 @@
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

View File

@@ -1,63 +1,63 @@
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
@@ -87,118 +87,118 @@ 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

View File

@@ -19,7 +19,10 @@ PW = "lrgrashof+-"
class EpiphanV1(RecorderAdapter): 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.user = admin_user
self.password = admin_pw self.password = admin_pw
self.session = requests.Session() self.session = requests.Session()
@@ -32,13 +35,13 @@ class EpiphanV1(RecorderAdapter):
pass pass
def get_status(self) -> dict: 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: if res.ok:
return res.json() return res.json()
raise LrcException(res.text, res.status_code) raise LrcException(res.text, res.status_code)
def get_sysinfo(self) -> dict: 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: if res.ok:
return res.json() return res.json()
raise LrcException(res.text, res.status_code) raise LrcException(res.text, res.status_code)
@@ -55,13 +58,13 @@ class EpiphanV1(RecorderAdapter):
return self.get_status().get('seconds', None) return self.get_status().get('seconds', None)
def start_recording(self): 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: if not res.ok:
raise LrcException(res.text, res.status_code) 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 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): 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: if not res.ok:
raise LrcException(res.text, res.status_code) 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 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)) raise LrcException(str(err))
def get_screenshot(self): 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) stream=True)
print(ret) print(ret)
@@ -117,7 +120,7 @@ class EpiphanV1(RecorderAdapter):
if __name__ == '__main__': if __name__ == '__main__':
e = EpiphanV1(USER, PW) e = EpiphanV1(BASE_URL, USER, PW)
try: try:
# print(e.is_recording()) # print(e.is_recording())
""" """

View File

@@ -1,5 +1,10 @@
import logging
from backend import LrcException
from backend.recorder_adapters import telnetlib, TelnetAdapter, RecorderAdapter from backend.recorder_adapters import telnetlib, TelnetAdapter, RecorderAdapter
logger = logging.getLogger()
RECORDER_MODEL_NAME = "SMP 351 / 352" RECORDER_MODEL_NAME = "SMP 351 / 352"
VERSION = "0.9.0" VERSION = "0.9.0"
REQUIRES_USER = False REQUIRES_USER = False
@@ -16,26 +21,34 @@ PW = "123mzsmp"
class SMP(TelnetAdapter, RecorderAdapter): class SMP(TelnetAdapter, RecorderAdapter):
def __init__(self, address, password, **kwargs): def __init__(self, address, password, auto_login=True, **kwargs):
super().__init__(address) super().__init__(address)
self.admin_pw = password self.admin_pw = password
if auto_login:
self._login()
def _login(self): 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:") self.tn.read_until("\r\nPassword:")
# password = getpass.getpass() # password = getpass.getpass()
password = self.admin_pw password = self.admin_pw
self.tn.write(password + "\n\r") self.tn.write(password + "\n\r")
out = self.tn.assert_string_in_output("Login Administrator") out = self.tn.assert_string_in_output("Login Administrator")
print(out)
if not out[0]: if not out[0]:
print(out[1]) print(out[1])
if "Password:" in out[1]: if "Password:" in out[1]:
# TODO: loop until logged in... # TODO: loop until logged in...
print("re-enter pw") 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(self.tn.assert_string_in_output("Login Administrator"))
print("WRONG (admin) password!! Exiting!") print("WRONG (admin) password!! Exiting!")
print(self.admin_pw)
self.tn = None self.tn = None
raise Exception("Could not login as administrator with given pw!") raise Exception("Could not login as administrator with given pw!")
print("OK, we have admin rights!") print("OK, we have admin rights!")
@@ -369,6 +382,9 @@ class SMP(TelnetAdapter, RecorderAdapter):
self.tn.write("{}YRCDR\n".format(self.esc_char)) self.tn.write("{}YRCDR\n".format(self.esc_char))
return TelnetAdapter._get_response_str(self.tn.read_until_non_empty_line()) 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): def extent_recording_time(self, extension_time: int):
""" """
Extends a scheduled recording by extension_time minutes Extends a scheduled recording by extension_time minutes
@@ -764,7 +780,7 @@ class SMP(TelnetAdapter, RecorderAdapter):
def main(): def main():
smp = SMP(HOST, PW) smp = SMP(HOST, PW, False)
print(smp) print(smp)
smp._login() smp._login()
print(smp.get_version(verbose_info=False)) print(smp.get_version(verbose_info=False))

View File

@@ -48,6 +48,7 @@ for r in recorders:
'type': 'SMP 351' if 'SMP 351' in r['Rekorder-Typ'] else r['Rekorder-Typ'], 'type': 'SMP 351' if 'SMP 351' in r['Rekorder-Typ'] else r['Rekorder-Typ'],
'additional_camera': r['Zus. Kamera'] == 'Ja', 'additional_camera': r['Zus. Kamera'] == 'Ja',
'firmware_version': r['FW Vers.'], 'firmware_version': r['FW Vers.'],
'network_name': r['DNS'],
'description': json.dumps( 'description': json.dumps(
{'comment': r['Bemerkung'], 'network_port': r['Dosennummer'], 'rsync_name': r['Rsync-Name']})} {'comment': r['Bemerkung'], 'network_port': r['Dosennummer'], 'rsync_name': r['Rsync-Name']})}
nicely_formatted_recorders.append(rec) nicely_formatted_recorders.append(rec)

View File

@@ -1,3 +1,8 @@
import json
import os
import logging
from multiprocessing.pool import ThreadPool
from pprint import pprint from pprint import pprint
import requests import requests
@@ -5,6 +10,14 @@ from requests.auth import HTTPBasicAuth
from ics import Calendar from ics import Calendar
from backend.config import Config 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" base_url = "https://opencast.bibliothek.kit.edu"
@@ -13,6 +26,8 @@ session.auth = HTTPBasicAuth(Config.OPENCAST_USER, Config.OPENCAST_PW)
config = {'service_urls': {}} config = {'service_urls': {}}
recorders = None
def get_service_url(service_type: str): def get_service_url(service_type: str):
if service_type in config['service_urls']: if service_type in config['service_urls']:
@@ -24,7 +39,7 @@ def get_service_url(service_type: str):
service = res.json()["services"]["service"] service = res.json()["services"]["service"]
config["service_urls"][service_type] = service["host"] + \ config["service_urls"][service_type] = service["host"] + \
service["path"] service["path"]
return service["host"] +service["path"] return service["host"] + service["path"]
return None return None
@@ -43,13 +58,71 @@ def get_capture_agents():
if res.ok: if res.ok:
return res.json()["agents"]["agent"] return res.json()["agents"]["agent"]
agents = get_capture_agents()
for a in agents: def get_recorder_details():
print(a['name']) """Temporary implementation using initial_recorders.json. Should be replaced by DB layer later!"""
print(a['state']) global recorders
if a['state'] == "capturing": 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']) c = get_calender(a['name'])
print(list(c.timeline.now())) 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()
logger.info("Got {} capture agents that will be checked...".format(len(agents)))
pool = ThreadPool(5)
pool.map(check_capture_agent_state, agents)
exit() exit()
c = get_calender('CS 30.46 Chemie Neuer Hoersaal') c = get_calender('CS 30.46 Chemie Neuer Hoersaal')