run.py 5.13 KB
Newer Older
1
2
3
4
#!/bin/sh
''''which python3.8 >/dev/null 2>&1 && exec python3.8 "$0" "$@"     # '''
''''which python3.7  >/dev/null 2>&1 && exec python3.7  "$0" "$@"   # '''
''''exec echo "Error: Snaaakey Python, where are you?"                # '''
5
6

#
David Trattnig's avatar
David Trattnig committed
7
8
9
# Aura Engine (https://gitlab.servus.at/aura/engine)
#
# Copyright (C) 2017-2020 - The Aura Engine Team.
10
11
12
13
14
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
David Trattnig's avatar
David Trattnig committed
15
#
16
17
18
19
# 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 Affero General Public License for more details.
David Trattnig's avatar
David Trattnig committed
20
#
21
22
23
24
25
26
27
28
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import os
import sys
import signal
import logging
29
import subprocess
30

31
32
import time 

33
34
from flask               import Flask
from flask_sqlalchemy    import SQLAlchemy
35

36
37
38
from src.base.logger import AuraLogger
from src.base.config import AuraConfig
from src.base.utils  import SimpleUtil as SU
39
40
41
42
43
44
45
46
47
48
49
50
51


config = AuraConfig()
def configure_flask():
    app.config["SQLALCHEMY_DATABASE_URI"] = config.get_database_uri()
    app.config['BABEL_DEFAULT_LOCALE'] = 'de'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# FIXME Instatiate SQLAlchemy without the need for Flask
app = Flask(__name__)
configure_flask()
DB = SQLAlchemy(app)

52

53
class EngineRunner:
54
    """
55
    EngineRunner is in charge of
56

57
58
    1. Initializing the engine and all dependencies
    3. Starting Liquidsoap in a separate thread, if requested
59
60
61
62

    """
    logger = None
    config = None
David Trattnig's avatar
David Trattnig committed
63
    engine = None
64
    lqs = None
65
66
67
68


    def __init__(self):
        """
69
        Constructor
70
71
        """
        self.config = config
David Trattnig's avatar
David Trattnig committed
72
73
74
        AuraLogger(self.config)
        self.logger = logging.getLogger("AuraEngine")
        
75
76


77
    def run(self, start_lqs, lqs_debug_flags):
78
        """
79
        Starts Engine Core.
David Trattnig's avatar
David Trattnig committed
80
        """                
81
        from src.scheduling.models import AuraDatabaseModel
82
        from src.core.engine import Engine
83

84
        # Check if the database has to be re-) created
85
        if self.config.get("recreate_db") is not None:
86
            AuraDatabaseModel.recreate_db()
87

88
89
90
91
        if start_lqs:
            runner.run_lqs(lqs_debug_flags)        
        else:
            self.logger.info(SU.yellow("Please note, Liquidsoap needs to be started manually."))
92

93
        self.engine = Engine()
94

95
96


97
    def run_lqs(self, lqs_debug_flags):
98
99
100
        """
        Starts Liquidsoap.
        """
101
102
        debug_output = lqs_debug_flags.get("debug_output")
        verbose_output = lqs_debug_flags.get("verbose_output")
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
        lqs_path = self.config.get("liquidsoap_path")
        lqs_cwd = os.getcwd() + "/" + self.config.get("liquidsoap_working_dir")
        lqs_output = ""
        lqs_output = self.get_debug_flags(debug_output, verbose_output)

        self.lqs = subprocess.Popen([lqs_path, lqs_output, "engine.liq"], \
            cwd=lqs_cwd, \
            stdout=subprocess.PIPE, \
            shell=False)



    def get_lqs_cmd(self, debug_output, verbose_output):
        """
        Returns a shell command string to start Liquidsoap
        """
        lqs_path = self.config.get("liquidsoap_path")
        lqs_cwd = os.getcwd() + "/" + self.config.get("liquidsoap_working_dir")
        lqs_output = self.get_debug_flags(debug_output, verbose_output)
        return "(cd %s && %s %s ./engine.liq)" % (lqs_cwd, lqs_path, lqs_output)



    def get_debug_flags(self, debug_output, verbose_output):
        """
David Trattnig's avatar
David Trattnig committed
128
        Build Liquidsoap debug parameters.
129
130
131
132
133
134
135
        """
        output = ""
        if debug_output:
            output += "--debug " 
        if verbose_output:
            output += "--verbose "
        return output
136
137
138
139
140



    def exit_gracefully(self, signum, frame):
        """
141
        Shutdown of the engine. Also terminates the Liquidsoap thread.
142
        """
143
144
145
        if self.engine:
            self.engine.terminate()

146
147
148
149
        if self.lqs:
            self.lqs.terminate()
            self.logger.info("Terminated Liquidsoap")

David Trattnig's avatar
David Trattnig committed
150
        self.logger.info("Gracefully terminated Aura Engine! (signum:%s, frame:%s)" % (signum, frame))
151
        sys.exit(0)        
152
153
154



155
156
157
158
159
#
# START THE ENGINE
#


160
if __name__ == "__main__":        
161
162
    runner = EngineRunner()
    do_start_lqs = True
163
    lqs_cmd = False
164

165
166
    signal.signal(signal.SIGINT, runner.exit_gracefully)
    signal.signal(signal.SIGTERM, runner.exit_gracefully)
167
168

    if len(sys.argv) >= 2:
169
        if "--without-lqs" in sys.argv:
170
            do_start_lqs = False
171
172
        if "--get-lqs-command" in sys.argv:
            lqs_cmd = True
173
        if "--use-test-data" in sys.argv:
174
            runner.config.set("use_test_data", True)
175
        if "--recreate-database" in sys.argv:
176
            runner.config.set("recreate_db", True)
177

178
    if lqs_cmd:
179
180
181
        print(runner.get_lqs_cmd(True, True))
    else:                
        runner.run(do_start_lqs, { "debug_output": False, "verbose_output": False })