Commit cd9bc5fb authored by Gottfried Gaisbauer's avatar Gottfried Gaisbauer
Browse files

greater commit than expected. informations from tank now stored into database;...

greater commit than expected. informations from tank now stored into database; introduced a new switch "--recreate-database"
parent 7d81e7b6
......@@ -27,27 +27,75 @@
import os
import sys
import signal
import logging
import unittest
from modules.scheduling.scheduler import AuraScheduler
from modules.communication.liquidsoap.communicator import LiquidSoapCommunicator
from modules.communication.redis.adapter import ServerRedisAdapter
from modules.web.routes import Routes
from flask import request, render_template, Flask, Response
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.ext.declarative import declarative_base
#from modules.web.routes import Routes
from modules.monitoring.diskspace_watcher import DiskSpaceWatcher
from libraries.base.logger import AuraLogger
from libraries.base.config import AuraConfig
def get_config_file():
if len(sys.argv) >= 3 and "--config-file" in sys.argv:
idx = sys.argv.index("--config-file")
return sys.argv[idx + 1]
else:
return "/etc/aura/engine.ini"
def get_database_uri():
db_name = config.get("db_name")
db_user = config.get("db_user")
db_pass = config.get("db_pass")
db_host = config.get("db_host")
db_charset = config.get("db_charset", "utf8")
#### return created database uri ####
return "mysql://" + db_user + ":" + db_pass + "@" + db_host + "/" + db_name + "?charset=" + db_charset
from testing.test import TestConfig, TestLogger
def configure_flask():
app.config["SQLALCHEMY_DATABASE_URI"] = get_database_uri()
app.config['BABEL_DEFAULT_LOCALE'] = 'de'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
class Aura(AuraLogger):
config = AuraConfig(get_config_file())
app = Flask(__name__, template_folder=config.get("install_dir") + "/modules/web/templates")
configure_flask()
DB = SQLAlchemy(app)
Base = declarative_base()
class Aura:
logger = None
config = None
server = None
messenger = None
controller = None
# ------------------------------------------------------------------------------------------ #
def __init__(self):
super(Aura, self).__init__()
# set config
self.config = config
# init logger
AuraLogger(self.config)
# use logger
self.logger = logging.getLogger("AuraEngine")
def startup(self):
from modules.scheduling.scheduler import AuraScheduler
from modules.communication.liquidsoap.communicator import LiquidSoapCommunicator
from modules.communication.redis.adapter import ServerRedisAdapter
if self.config.get("recreate_db") is not None:
AuraScheduler(self.config) # handles recreate and exits program
# self.controller = AuraController(self.config)
# create scheduler and ls_communicator
......@@ -55,12 +103,12 @@ class Aura(AuraLogger):
self.scheduler = AuraScheduler(self.config)
# give both a reference of each other
self.liquidsoapcommunicator.scheduler = self.scheduler
self.scheduler.liquidsoapcommunicator = self.liquidsoapcommunicator
# self.liquidsoapcommunicator.scheduler = self.scheduler
# self.scheduler.liquidsoapcommunicator = self.liquidsoapcommunicator
# create the redis adapter
self.messenger = ServerRedisAdapter(self.config)
self.messenger.scheduler = self.scheduler
# self.messenger.scheduler = self.scheduler
self.messenger.liquidsoapcommunicator = self.liquidsoapcommunicator
#self.diskspace_watcher = DiskSpaceWatcher(self.config, self.logger, self.liquidsoapcommunicator)
......@@ -80,7 +128,7 @@ class Aura(AuraLogger):
def start_web_service(self):
try:
self.logger.info("Listening on Port 5000 for API or Webcalls")
Routes(self.scheduler, self.liquidsoapcommunicator, self.messenger, self.config)
# Routes(self.scheduler, self.liquidsoapcommunicator, self.messenger, self.config)
except OSError as e:
self.messenger.halt()
self.logger.critical("AuraEngine already running? Exception: " + e.strerror + ". Exiting...")
......@@ -93,8 +141,14 @@ class Aura(AuraLogger):
def main():
aura = Aura()
if len(sys.argv) >= 2 and "--use-test-data" in sys.argv:
aura.config.set("use_test_data", True)
aura.logger.critical("MAKE THE STARTTIME OF A SCHEDULE TO ITS PK")
if len(sys.argv) >= 2:
if "--use-test-data" in sys.argv:
aura.config.set("use_test_data", True)
if "--recreate-database" in sys.argv:
aura.config.set("recreate_db", True);
aura.startup()
......
......@@ -7,6 +7,7 @@ db_user="engine"
db_name="engine"
db_pass="engine"
db_host="localhost"
db_charset="utf8"
[redis]
redis_host="localhost"
......@@ -38,9 +39,9 @@ mailsubject_prefix="[AURA]"
[dataurls]
# the url of pv/steering
calendarurl="http://localhost:8000/api/v1/playout"
calendarurl="http://localhost:8001/api/v1/playout"
# the url of tank
importerurl="http://localhost:8008/api/v1/groups/_public/playlists/"
importerurl="http://localhost:8040/api/v1/shows/"
# how often should the calendar be fetched in seconds (This determines the time of the last change before a specific show)
fetching_frequency=3600
......@@ -70,6 +71,10 @@ logdir="/var/log/aura"
# possible values: debug, info, warning, error, critical
loglevel="info"
[audiofolder]
audiofolder="/var/audio"
[fallback]
# track_sensitive => fallback_folder track sensitivity
# max_blank => maximum time of blank from source (float)
# min_noise => minimum duration of noise on source to switch back over (float)
......@@ -282,4 +287,4 @@ stream_4_password="source"
stream_4_url="http://www.fro.at"
stream_4_name="AURA Test Stream 3"
stream_4_genre="mixed"
stream_4_description="Test Stream 3"
\ No newline at end of file
stream_4_description="Test Stream 3"
......@@ -22,23 +22,96 @@
# along with engine. If not, see <http://www.gnu.org/licenses/>.
#
from modules.base.config import ConfigReader
import os
import sys
import logging
from configparser import ConfigParser
class AuraConfig:
"""
AuraCommon handles logger, reads and stores config
"""
config = None
ini_path = ""
logger = None
def __init__(self, ini_path): # = "/etc/aura/engine.ini"):
self.ini_path = ini_path
self.logger = logging.getLogger("AuraEngine")
self.load_config()
def set(self, key, value):
"""
Set a property
@type key: string
@param key: The Key
@type value: mixed
@param value: Beliebiger Wert
"""
try:
self.__dict__[key] = int(value)
except:
self.__dict__[key] = str(value)
# ------------------------------------------------------------------------------------------ #
def get(self, key, default=None):
"""
get a loaded property
@type key: string
@param key: Der Key
@type default: mixed
@param default: Beliebiger Wert
"""
def __init__(self):
super(AuraConfig, self).__init__()
self.config = ConfigReader()
self.read_config()
if key not in self.__dict__:
if default:
self.set(key, default)
else:
self.logger.warning("Key " + key + " not found in configfile " + self.ini_path + "!")
return None
def read_config(self):
if key == "loglevel":
loglvl = self.__dict__[key]
if loglvl == "debug":
return logging.DEBUG
elif loglvl == "info":
return logging.INFO
elif loglvl == "warning":
return logging.WARNING
elif loglvl == "error":
return logging.ERROR
else:
return logging.CRITICAL
if key == "debug":
return self.__dict__[key].count("y")
return self.__dict__[key]
# ------------------------------------------------------------------------------------------ #
def load_config(self):
"""
reads aura.ini
Set config defaults and load settings from file
:return:
"""
self.config.load_config()
if not os.path.isfile(self.ini_path):
self.logger.critical(self.ini_path + " not found :(")
sys.exit(1)
# INI einlesen
f = open(self.ini_path, 'r')
ini_str = f.read()
f.close()
config_parser = ConfigParser()
try:
config_parser.read_string(ini_str)
except Exception as e:
self.logger.critical("Cannot read " + self.ini_path + "! Reason: " + str(e))
sys.exit(0)
for section in config_parser.sections():
for key, value in config_parser.items(section):
v = config_parser.get(section, key).replace('"', '').strip()
self.set(key, v)
self.set("install_dir", os.path.realpath(__file__ + "../../../.."))
......@@ -27,11 +27,13 @@ import logging
from libraries.base.config import AuraConfig
class AuraLogger(AuraConfig):
class AuraLogger():
config = None
logger = None
def __init__(self):
super(AuraLogger, self).__init__()
def __init__(self, config):
self.config = config
self.__create_logger("AuraEngine")
def __create_logger(self, name):
......
This diff is collapsed.
#
# engine
#
# Playout Daemon for autoradio project
#
#
# Copyright (C) 2017-2018 Gottfried Gaisbauer <gottfried.gaisbauer@servus.at>
#
# This file is part of engine.
#
# engine is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# engine is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with engine. If not, see <http://www.gnu.org/licenses/>.
#
from sqlalchemy.ext.declarative import declarative_base
from flask_sqlalchemy import SQLAlchemy
# from flask_babel import Babel
from flask import Flask
from modules.base.config import ConfigReader # pylint: disable=import-error
def create_app(install_dir, uri):
"""
creates flask app context
:param install_dir: Installdir of Aura
:param uri: Database connection uri
:return: Flask object
"""
app = Flask(__name__, template_folder=install_dir + '/modules/web/templates')
app.config["SQLALCHEMY_DATABASE_URI"] = uri
app.config['BABEL_DEFAULT_LOCALE'] = 'de'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
return app
def create_database():
"""
creates sqlalchemy database connection
:return: SQLAlchemy object
"""
#### load config ####
config = ConfigReader()
config.load_config()
#### read config ####
install_dir = config.get(str("install_dir"))
db_name = config.get(str("db_name"))
db_user = config.get(str("db_user"))
db_pass = config.get(str("db_pass"))
db_host = config.get(str("db_host"))
#### create database conn ####
uri = "mysql://"+db_user+":"+db_pass+"@"+db_host+"/"+db_name+"?charset=utf8"
app = create_app(install_dir, uri)
database = SQLAlchemy(app)
# babel = Babel(app)
return app, database
Base = declarative_base()
APP, DB = create_database()
#
# engine
#
# Playout Daemon for autoradio project
#
# Copyright 2014 BFR <info@freie-radios.de>
# Copyright (C) 2017-2018 Gottfried Gaisbauer <gottfried.gaisbauer@servus.at>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; Version 3 of the License
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, the license can be downloaded here:
#
# http://www.gnu.org/licenses/gpl.html
# Meta
__version__ = '0.1.1'
__license__ = "GNU General Public License (GPL) Version 3"
__version_info__ = (0, 1, 1)
__author__ = 'Michael Liebler <michael-liebler@radio-z.net>'
"""
Aura Config Reader
"""
import os
import sys
import socket
import logging
from configparser import ConfigParser
class ConfigReader(object):
ini_path = ""
logger = None
def __init__(self):
self.logger = logging.getLogger("AuraEngine")
def set(self, key, value):
"""
Set a property
@type key: string
@param key: The Key
@type value: mixed
@param value: Beliebiger Wert
"""
try:
self.__dict__[key] = int(value)
except:
self.__dict__[key] = str(value)
# ------------------------------------------------------------------------------------------ #
def get(self, key, default=None):
"""
get a loaded property
@type key: string
@param key: Der Key
@type default: mixed
@param default: Beliebiger Wert
"""
if key not in self.__dict__:
if default:
self.set(key, default)
else:
self.logger.warning("Key " + key + " not found in configfile " + self.ini_path + "!")
return None
if key == "loglevel":
loglvl = self.__dict__[key]
if loglvl == "debug":
return logging.DEBUG
elif loglvl == "info":
return logging.INFO
elif loglvl == "warning":
return logging.WARNING
elif loglvl == "error":
return logging.ERROR
else:
return logging.CRITICAL
if key == "debug":
return self.__dict__[key].count("y")
return self.__dict__[key]
# ------------------------------------------------------------------------------------------ #
def load_config(self):
"""
Set config defaults and load settings from file
:return:
"""
self.ini_path = self.get('configpath', '/etc/aura/engine.ini')
if not os.path.isfile(self.ini_path):
self.logger.critical(self.ini_path + " not found :(")
sys.exit(1)
# INI einlesen
f = open(self.ini_path, 'r')
ini_str = f.read()
f.close()
config_parser = ConfigParser()
try:
config_parser.read_string(ini_str)
except Exception as e:
self.logger.critical("Cannot read " + self.ini_path + "! Reason: " + str(e))
sys.exit(0)
for section in config_parser.sections():
for key, value in config_parser.items(section):
v = config_parser.get(section, key).replace('"', '').strip()
self.set(key, v)
self.set("install_dir", os.path.realpath(__file__ + "../../../.."))
......@@ -27,7 +27,7 @@ import logging
import json
from modules.communication.liquidsoap.communicator import LiquidSoapCommunicator
from libraries.database.broadcasts import ScheduleEntry
#from libraries.database.broadcasts import ScheduleEntry
from libraries.base.config import AuraConfig
......@@ -41,7 +41,7 @@ class ConnectionTester(AuraConfig):
# ------------------------------------------------------------------------------------------ #
def get_connection_status(self):
status = dict()
status["db"] = self.test_db_conn()
status["db"] = False # self.test_db_conn()
status["pv"] = self.test_pv_conn()
status["lqs"] = self.test_lqs_conn()
status["lqsr"] = False # self.test_lqsr_conn()
......@@ -51,13 +51,13 @@ class ConnectionTester(AuraConfig):
return json.dumps(status)
# ------------------------------------------------------------------------------------------ #
def test_db_conn(self):
try:
ScheduleEntry.select_all()
except:
return False
return True
# def test_db_conn(self):
# try:
# ScheduleEntry.select_all()
# except:
# return False
#
# return True
# ------------------------------------------------------------------------------------------ #
def test_lqs_conn(self):
......
......@@ -33,7 +33,7 @@ from modules.communication.mail.mail import AuraMailer
from libraries.enum.auraenumerations import TerminalColors, ScheduleEntryType
from libraries.exceptions.auraexceptions import LQConnectionError
from libraries.database.broadcasts import TrackService
#from libraries.database.broadcasts import TrackService
from libraries.exceptions.exception_logger import ExceptionLogger
"""
......@@ -306,7 +306,8 @@ class LiquidSoapCommunicator(ExceptionLogger):
self.disable_transaction()
# insert playlist entry
self.insert_track_service_entry(new_entry)
self.logger.critical("Trackservice entry not written here anymore")
# self.insert_track_service_entry(new_entry)
except LQConnectionError as e:
# we already caught and handled this error in __send_lqc_command__, but we do not want to execute this function further and pass the exception
pass
......
......@@ -32,7 +32,7 @@ from datetime import datetime
from threading import Event
from modules.communication.redis.messenger import RedisMessenger
from modules.communication.connection_tester import ConnectionTester
# from modules.communication.connection_tester import ConnectionTester
from libraries.database.statestore import RedisStateStore
from libraries.exceptions.auraexceptions import RedisConnectionException
from libraries.enum.auraenumerations import RedisChannel, TerminalColors, FallbackType
......@@ -47,7 +47,7 @@ class ServerRedisAdapter(threading.Thread, RedisMessenger):
channel = ""
scheduler = None
redisclient = None
connection_tester = None
# connection_tester = None
liquidsoapcommunicator = None
# ------------------------------------------------------------------------------------------ #
......@@ -69,7 +69,7 @@ class ServerRedisAdapter(threading.Thread, RedisMessenger):
self.adminMails = ''
self.redisclient = ClientRedisAdapter(config)
self.connection_tester = ConnectionTester()
# self.connection_tester = ConnectionTester()
# ------------------------------------------------------------------------------------------ #
def run(self):
......@@ -157,8 +157,8 @@ class ServerRedisAdapter(threading.Thread, RedisMessenger):
elif item["data"] == "get_act_programme":
self.execute(RedisChannel.GAP_REPLY.value, self.scheduler.get_act_programme_as_string)
elif item["data"] == "get_connection_status":
self.execute(RedisChannel.GCS_REPLY.value, self.connection_tester.get_connection_status)
# elif item["data"] == "get_connection_status":
# self.execute(RedisChannel.GCS_REPLY.value, self.connection_tester.get_connection_status)
elif item["data"] == "print_message_queue":
self.execute(RedisChannel.PMQ_REPLY.value, self.scheduler.print_message_queue)
......
......@@ -107,7 +107,7 @@ class RedisMessenger():
@param section: Globale Sektion überschreiben
"""
section = self.section if section == '' else section
self.time = str(datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S:%f'))
self.time = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S:%f'))
self.utime = time.time()
state = {'message':message.strip().replace("'","\\'"), 'code':self.errnr + str(code),'job':job,'value':value}
self.rstore.set_section(section)
......
This diff is collapsed.
import os
import sys
import urllib
import logging
import simplejson
from datetime import datetime, timedelta
#from modules.models.schedule import Schedule
class CalendarFetcher:
url = dict()
url_parameter = dict()
config = None
logging = None
has_already_fetched = False
fetched_schedule_data = None
# another crutch because of the missing TANK
used_random_playlist_ids = list()