Skip to content
Snippets Groups Projects
README.md 11.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • David Trattnig's avatar
    David Trattnig committed
    # Engine API Server
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    David Trattnig's avatar
    David Trattnig committed
    <!-- TOC -->
    
    - [Engine API Server](#engine-api-server)
        - [Overview](#overview)
        - [Deployment Modes](#deployment-modes)
            - [Single Deployment](#single-deployment)
            - [Redundant Deployment](#redundant-deployment)
                - [Managing Active Engine State](#managing-active-engine-state)
                - [High Availability Playlog Synchronization](#high-availability-playlog-synchronization)
        - [Getting started](#getting-started)
            - [Requirements](#requirements)
            - [Installation](#installation)
            - [Configuration](#configuration)
                - [Engine 1 Node](#engine-1-node)
                - [Engine 2 Node](#engine-2-node)
                - [Synchronization Node](#synchronization-node)
        - [Running the Server](#running-the-server)
            - [Development](#development)
            - [Production](#production)
            - [Running with Systemd](#running-with-systemd)
            - [Running with Supervisor](#running-with-supervisor)
            - [Running with Docker](#running-with-docker)
        - [Using the API](#using-the-api)
    - [About](#about)
    
    <!-- /TOC -->
    
    
    David Trattnig's avatar
    David Trattnig committed
    ## Overview
    
    
    The Project serves the Engine API and handles state management of multiple [Engine](https://gitlab.servus.at/aura/engine) instances.
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    The Engine API stores and provides following information:
    
    
    - **Playlogs**: A history of all audio titles being played by the Engine. This is used for example to generate detailed reports for regulartory purposes.
    - **Track Service**: Same as track service, but stripped-down information. Used for implementing a track service feature on the radio's website.
    - **Active Source**: In redundant deployment scenarios the API stores and shares information on which engine instance is currently active. This could be extended to other audio sources.
    - **Health Information**: In case of some critical issue affecting the functionality of AURA Engine, the history of health status records of the respective engine is stored.
    - **Studio Clock**: Information on the current and next show to be used in a *Studio Clock* application.
    
    
    You can find details on the available API endpoints here: https://app.swaggerhub.com/apis/AURA-Engine/engine-api/1.0.0
    
    ## Deployment Modes
    
    
    David Trattnig's avatar
    David Trattnig committed
    AURA Engine allows single and redundant deployments for high availability scenarios.
    
    Engine can be deployed and run manually, using [Systemd](#running-with-systemd), [Supervisor](#running-with-supervisor) or [Docker](#running-with-docker).
    
    
    ### Single Deployment
    
    This is the most simple case. In that scenario the Engine API is deployed on the same host as the [Engine](https://gitlab.servus.at/aura/engine) itself.
    
    
    David Trattnig's avatar
    David Trattnig committed
    > In your live deployment you might not want to expose the API directly on the web. For security reasons it's highly recommended to guard it using something like NGINX,
    acting as a reverse proxy.
    
    David Trattnig's avatar
    David Trattnig committed
    <img src="docs/engine-api_single.png" width="550" />
    
    
    ### Redundant Deployment
    
    
    David Trattnig's avatar
    David Trattnig committed
    In this scenario there are two Engine instances involved. Here you will need to deploy one Engine API on the host of each Engine instance. Additionally you'll have to set up
    a third, so-called "Syncronization Node" of the Engine API. This sync instance of Engine API is in charge of synchronizing playlogs and managing the active engine state.
    
    <img src="docs/engine-api_redundancy.png" />
    
    David Trattnig's avatar
    David Trattnig committed
    #### Managing Active Engine State
    
    In order to avoid duplicate playlog storage, the Synchronization Node requires to know what the currently active Engine is. This can be achieved by some external *Status Monitor*
    component which tracks the heartbeat of both engines. In case the Status Monitor identifies one Engine as dysfunctional, it sends a REST request to the Sync Node, informing it
    about the second, functional Engine instance being activated.
    
    The history of active Engine instances is stored in the database of the Sync Node. It is not only used for playlog syncing, but is also handy as an audit log.
    
    > At the moment AURA doesn't provide its own *Status Monitor* solution. You'll need to integrate your self knitted component which tracks the heartbeat of the engines and posts
    the active engine state to the Sync Node.
    
    #### High Availability Playlog Synchronization
    
    Usually when some new audio source starts playing, AURA Engine logs it to its local Engine API instance via some REST call. Now, the local API server stores this information in its
    local database. Next, it also performs a request to the Synchronization API Serve. The Sync Server checks if this request is coming from the currently active engine instance.
    If yes, it stores this information in the playlog database.
    
    During the synchronization process between some Engine Node and the Synchronization Node, there might be the case, that the latter is not available e.g. due to network outage,
    maintenance etc. In this situation the playlog obviously can not be synced. That means the local playlog is marked as "not synced". Whenever the Sync Node is up- and running again,
    some automated job on the Sync Node is continuously checking for "unsynced" records on remote nodes. If there are such records pending to be synced, this job reads them as batches
    from that Engine Node. To avoid this sync causing high traffic on any engine instance, these batches are read with some configured delay time (see `sync_interval`, `sync_batch_size`,
    and `sync_step_sleep` in the Sync Node configuration; all values are in seconds).
    
    > In your live deployment you might not want to expose the API directly on the web. For security reasons it's highly recommended to guard it using something like NGINX,
    acting as a reverse proxy.
    
    
    ## Getting started
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    ### Requirements
    
    If you are not planning to go with Docker or just want to setup a local development environment, then you'll need:
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    David Trattnig's avatar
    David Trattnig committed
    Python 3.7+
    
    MariaDB
    Virtualenv
    
    ### Installation
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    Create a virtual environment for your Python dependencies:
    
    ```bash
    virtualenv -p python3.7 python
    ```
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    David Trattnig's avatar
    David Trattnig committed
    Install the required dependencies:
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    David Trattnig's avatar
    David Trattnig committed
    ```bash
    pip3 install -r requirements.txt
    # Additional requirements for the chosen database
    pip3 install -r contrib/mariadb-requirements.txt
    # Create database and user (change password in script)
    sudo mysql -u root -p < contrib/mariadb-database.sql
    
    David Trattnig's avatar
    David Trattnig committed
    ```
    
    ### Configuration
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    David Trattnig's avatar
    David Trattnig committed
    Copy the sample configuration file in `./config/sample/sample-production.engine-api` to `config` and edit the file.
    
    First update the main configuration and then configure the type of federation. Depending on how you want to run your
    Engine API node and where it is deployed, you'll needed to uncomment one of these federation sections:
    
    > To avoid any malfunction it is important that any other node-type configurations are commented out.
    
    #### Engine 1 Node
    
    Use this section if you are running [AURA Engine](https://gitlab.servus.at/aura/engine) standalone or if this is the first API node in a redundant deployment.
    
    
    David Trattnig's avatar
    David Trattnig committed
    Replace `api.sync.local` with the actual host name or IP of your sync node.
    
    David Trattnig's avatar
    David Trattnig committed
    sync_host="http://api.sync.local:8008"
    
    #### Engine 2 Node
    
    In case this is the second API node in a redundant deployment.
    
    
    David Trattnig's avatar
    David Trattnig committed
    Replace `api.sync.local` with the actual host name or IP of your sync node.
    
    David Trattnig's avatar
    David Trattnig committed
    sync_host="http://api.sync.local:8008"
    
    ```
    
    #### Synchronization Node
    
    
    David Trattnig's avatar
    David Trattnig committed
    This is the synchronization instance in a redundant setup. This instance combines all valid information coming from Engine API 1 and 2.
    
    David Trattnig's avatar
    David Trattnig committed
    Replace `engine1.local` and `engine2.local` with the actual details of your main nodes.
    
    
    ```ini
    # NODE SYNC
    host_id=0
    
    David Trattnig's avatar
    David Trattnig committed
    main_host_1="http://engine1.local:8008"
    main_host_2="http://engine2.local:8008"
    
    # The Engine which is seen as "active" as long no other information is received from the status monitor
    
    default_source=1
    
    David Trattnig's avatar
    David Trattnig committed
    # How often the Engine 1 and 2 nodes should be checked for unsynced records (in seconds)
    
    sync_interval=3600
    
    David Trattnig's avatar
    David Trattnig committed
    # How many unsynced records should be retrieved at once (in seconds)
    
    sync_batch_size=100
    
    David Trattnig's avatar
    David Trattnig committed
    # How long to wait until the next batch is requested (in seconds)
    sync_step_sleep=2
    
    ```
    
    ## Running the Server
    
    ### Development
    
    
    David Trattnig's avatar
    David Trattnig committed
    To run the API in an local development server execute:
    
    
    David Trattnig's avatar
    David Trattnig committed
    ```bash
    
    David Trattnig's avatar
    David Trattnig committed
    ./run.sh api-dev
    ```
    
    
    For convenience running a plain `./run.sh` also starts the development server.
    
    When you'll need to run all three nodes to do testing during development you can run:
    
    ```bash
    ./run.sh api-test-0 # Sync Node
    ./run.sh api-test-1 # Node 1
    ./run.sh api-test-2 # Node 2
    ```
    
    Here the run script uses the configurations located in `./test/config`.
    
    ### Production
    
    To run the server for production using Gunicorn, you first need to create the Gunicorn configuration
    by copying the sample `./config/sample/gunicorn/sample-production.gunicorn.conf.py`
    to your `config` directory.
    
    Then run this from the root directory:
    
    ```bash
    ./run.sh api
    ```
    
    
    ### Running with Systemd
    
    **tbd**
    
    ### Running with Supervisor
    
    Alternatively to Systemd you can start Engine API using [Supervisor](http://supervisord.org/). In `./config/sample/supervisor/aura-engine-api.conf` you can find a example.
    Supervisor configuration file.
    
    
    ### Running with Docker
    
    David Trattnig's avatar
    David Trattnig committed
    
    To run the server on a Docker container, please execute the following from the root directory:
    
    ```bash
    # Building the image
    ./run.sh docker:build
    
    # Push the current image to dockerhub.com
    ./run.sh docker:push
    
    # Starting up a container
    ./run.sh docker:api
    ```
    
    ## Using the API
    
    
    You can find details on the available API endpoints here: https://app.swaggerhub.com/apis/AURA-Engine/engine-api/1.0.0
    
    
    David Trattnig's avatar
    David Trattnig committed
    Adding some entry to the playlog:
    
    ```bash
    
    David Trattnig's avatar
    David Trattnig committed
    curl -d '{ "track_start": "2020-06-27 19:14:00", "track_artist": "Mazzie Star", "track_title": "Fade Into You", "log_source": 1 }' -H "Content-Type: application/json" -X POST http://localhost:8008/api/v1/playlog/store
    
    David Trattnig's avatar
    David Trattnig committed
    ```
    
    
    David Trattnig's avatar
    David Trattnig committed
    This newly added entry can be queried using your browser in one of the following ways:
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    David Trattnig's avatar
    David Trattnig committed
    ```bash
    # Get the latest entry
    http://localhost:8008/api/v1/trackservice/current
    # Get a set of the most recent entries
    http://localhost:8008/api/v1/trackservice/
    # Filter some specific page (the three most recent entries)
    http://localhost:8008/api/v1/trackservice?page=0&limit=3
    ```
    
    All other API endpoints are listed in the interactive documentation.
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    David Trattnig's avatar
    David Trattnig committed
    ```bash
    
    David Trattnig's avatar
    David Trattnig committed
    http://localhost:8008/api/v1/ui/
    
    David Trattnig's avatar
    David Trattnig committed
    ```
    
    
    David Trattnig's avatar
    David Trattnig committed
    Your OpenAPI definition lives here:
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    David Trattnig's avatar
    David Trattnig committed
    ```bash
    
    David Trattnig's avatar
    David Trattnig committed
    http://localhost:8008/api/v1/openapi.json
    
    David Trattnig's avatar
    David Trattnig committed
    ```
    
    
    David Trattnig's avatar
    David Trattnig committed
    # About
    
    Aura Engine API is the API interface for the play-out engine of the [Aura Radio Software Suite](https://gitlab.servus.at/aura/meta).
    
    David Trattnig's avatar
    David Trattnig committed
    This project is based on a swagger-enabled Flask server using an *API First* approach. It also uses the [Connexion](https://github.com/zalando/connexion) library on top of Flask.
    
    David Trattnig's avatar
    David Trattnig committed
    
    
    [<img src="https://gitlab.servus.at/autoradio/meta/-/raw/master/images/aura-logo.png" width="150" />](https://gitlab.servus.at/aura/meta)
    
    AURA stands for Automated Radio and is a swiss army knife for community radio stations. Beside the Engine it provides Steering (Admin Interface for the radio station), Dashboard (Collaborative scheduling and programme coordination), Tank (Audio uploading, pre-processing and delivery). Read more in the [Aura Meta](https://gitlab.servus.at/aura/meta) repository or on the specific project pages.
    
    | [<img src="https://gitlab.servus.at/aura/meta/-/raw/master/images/aura-steering.png" width="150" align="left" />](https://gitlab.servus.at/aura/steering)  |  [<img src="https://gitlab.servus.at/aura/meta/-/raw/master/images/aura-dashboard.png" width="150" align="left" />](https://gitlab.servus.at/aura/dashboard)  |  [<img src="https://gitlab.servus.at/aura/meta/-/raw/master/images/aura-tank.png" width="150" align="left" />](https://gitlab.servus.at/aura/tank) | [<img src="https://gitlab.servus.at/aura/meta/-/raw/master/images/aura-engine.png" width="150" align="left" />](https://gitlab.servus.at/aura/engine)  |
    
    David Trattnig's avatar
    David Trattnig committed
    |---|---|---|---|
    
    | [Steering](https://gitlab.servus.at/aura/steering)  | [Dashboard](https://gitlab.servus.at/aura/dashboard)  | [Tank](https://gitlab.servus.at/aura/tank)  | [Engine](https://gitlab.servus.at/aura/engine)<br/>[Engine API](https://gitlab.servus.at/aura/engine-api)  |