run.py 5.04 KB
Newer Older
1
#!/bin/sh
2
3
''''which python3.9 >/dev/null 2>&1 && exec python3.9 "$0" "$@"     # '''
''''which python3.8  >/dev/null 2>&1 && exec python3.8  "$0" "$@"   # '''
4
''''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
from flask               import Flask
from flask_sqlalchemy    import SQLAlchemy
33

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


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)

50

51
class EngineRunner:
52
    """
53
    EngineRunner is in charge of
54

55
    1. Initializing the engine and all dependencies
David Trattnig's avatar
David Trattnig committed
56
    3. Starting Liquidsoap in a sub-process, if requested
57
58
59
60

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


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


75
    def run(self, start_lqs, lqs_debug_flags):
76
        """
77
        Starts Engine Core.
78
        """                        
79
        from src.core.engine import Engine
80

81
82
83
84
        if start_lqs:
            runner.run_lqs(lqs_debug_flags)        
        else:
            self.logger.info(SU.yellow("Please note, Liquidsoap needs to be started manually."))
85

86
        self.engine = Engine()
87

88
89


90
    def run_lqs(self, lqs_debug_flags):
91
92
93
        """
        Starts Liquidsoap.
        """
94
95
        debug_output = lqs_debug_flags.get("debug_output")
        verbose_output = lqs_debug_flags.get("verbose_output")
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
        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
121
        Build Liquidsoap debug parameters.
122
123
124
125
126
127
128
        """
        output = ""
        if debug_output:
            output += "--debug " 
        if verbose_output:
            output += "--verbose "
        return output
129
130
131



132
133
134
135
136
137
138
139
140
    def recreate_db(self):
        """
        Initializes the database and deletes any existing content.
        """
        from src.scheduling.models import AuraDatabaseModel
        AuraDatabaseModel.recreate_db()



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

148
149
150
151
        if self.lqs:
            self.lqs.terminate()
            self.logger.info("Terminated Liquidsoap")

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



157
158
159
160
161
#
# START THE ENGINE
#


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

167
168
    signal.signal(signal.SIGINT, runner.exit_gracefully)
    signal.signal(signal.SIGTERM, runner.exit_gracefully)
169
170

    if len(sys.argv) >= 2:
171
        if "--without-lqs" in sys.argv:
172
            do_start_lqs = False
173
174
        if "--get-lqs-command" in sys.argv:
            lqs_cmd = True
175
        if "--recreate-database" in sys.argv:
176
177
            runner.recreate_db()
            sys.exit(0)
178

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