Developing and Testing the 5GMSd Application Server

Here you will find information to assist with development and testing of the 5G-MAG Reference Tools 5GMS Application Server (AS).

Files in the 5GMS AS repository include:

  • ATTRIBUTION_NOTICE - List of 3rd party software used when running the 5GMS application server.
  • LICENSE - The software license for this project.
  • README.md - Project README file.
  • pyproject.toml - The Python project description for building and installing the application.
  • build_scripts/ - Scripts used when building the python project.
    • api.mustache - openapi-generator template file to pass operations onto methods in the class defined in src/rt_5gms_as/server.py.
    • backend.py - build backend wrapper to trigger extra build actions.
    • generate_5gms_as_openapi - Will generate the OpenAPI python modules if not already present.
    • M3_merged.yaml - OpenAPI YAML wrapper file to merge the M3 interface files into one for API bindings generation.
    • openapi-generator-config.yaml.in - openapi-generator configuration file template.
  • docs/ - Development documentation and examples.
    • example-application-server.conf - An application configuration which documents the defaults and meaning for each application configuration option.
  • external/ - Directory containing submodule mount points.
    • rt-common-shared/ - The common shared examples and scripts.
  • src/ - The application source modules.
    • rt_5gms_as/ - The main Python module for this application
      • app.py - Application entry point.
      • exceptions.py - Application specific Exception class definitions.
      • context.py - Module for the application Context class.
      • openapi_5g/ - Python bindings generated by openapi-generator-cli from the 5G APIs. Note: This directory is not present in the tree until build_scripts/generate_openapi is run.
      • proxies/ - Contains the web server/proxy detection and configuration classes and any data files they need.
      • proxy_factory.py - Factory module to pick a suitable web server/proxy.
      • server.py - M3 Server implementation.
      • utils.py - Common utility functions for the web server/proxy classes.
  • tests/ - Regression and build acceptance tests and other testing tools.
    • examples/ - Example configurations to go along with the tests.

While the instructions in the main project README tell you how to install the 5GMSd Application Server as a system-wide application, during development it is usually more appropriate to have one or more local clones of the repository that are being used for development and testing. This page provides details of one suggested way to arrange your development environment to ensure separation from the main system during development and testing.

Prerequisites

There are some packages that will need to be installed system wide that the build and install system relies on. These prerequisite packages are:

  • Commands
    • Git
    • Java
    • Python 3
    • Wget
  • Python 3 modules
    • pip
    • venv

These can usually be installed as system packages, for example: Debian/Ubuntu Linux and derivatives

sudo apt -y install git default-jdk python3 wget python3-pip python3-venv

RHEL/CentOS/Fedora/Rocky

sudo dnf -y install git java-latest-openjdk python3 wget python3-pip python3-venv

Checking out the project code

Since this will be used for development and testing, the instructions here will show you how to check out the latest development branch.

Checkout for development

  1. Create a fork
    1. Login to GitHub (create a GitHub account and set an SSH key if you haven’t already done so).
    2. On the main GitHub project page click on the “Fork” label in the top right of the page, then untick “Copy the main branch only” on the page that appears and select the “Create fork” button.
    3. On your new fork page select the Settings option just below the main repository title. Then select “Branches” under the “Code and automation” topic from the sections on the left, and edit the “Default branch” to change it to development.
    4. Clone the repository
      cd
      git clone --recurse-submodules git@github.com:<your-github-user>/rt-5gms-application-server.git
      

      Where <your-github-user> is the username of your GitHub login.

Checkout for testing only

  1. Clone the 5G-MAG repository
    cd
    git clone -b development --recurse-submodules https://github.com/5G-MAG/rt-5gms-application-server.git
    

Creating the virtual Python environment

By using a Python virtual environment you can use upgraded versions of existing system Python modules and automatically install project module dependencies without having to install or upgrade modules system wide.

  1. Create the virtual Python environment

    cd ~/rt-5gms-application-server
    python3 -m venv venv
    
  2. Update base modules and test script dependencies

    cd ~/rt-5gms-application-server
    venv/bin/python3 -m pip install --upgrade pip build setuptools docopt PyYAML
    

Build and install the 5GMSd Application Server

cd ~/rt-5gms-application-server
venv/bin/python3 -m pip install .

Create a local-user friendly configuration

Save these configuration file contents as ~/rt-5gms-application-server/local-dev.conf:

### Defaults for the 5G-MAG Reference Tools: 5GMSd applications
[DEFAULT]
log_dir = /tmp/rt-5gms-as/logs
run_dir = /tmp/rt-5gms-as

### 5GMSd Application Server specific configurations
[5gms_as]
log_level = debug
cache_dir = /tmp/rt-5gms-as/cache
certificates_cache = /tmp/rt-5gms-as/certificates
http_port = 8080
https_port = 8443
#m3_listen = localhost
#m3_port = 7777
#access_log = %(log_dir)s/application-server-access.log
#error_log = %(log_dir)s/application-server-error.log
#pid_path = %(run_dir)s/application-server.pid

### 5GMSd Application Server nginx specific configuration
[5gms_as.nginx]
root_temp = /tmp/rt-5gms-as
#client_body_temp = %(root_temp)s/client-body-tmp
#proxy_temp = %(root_temp)s/proxy-tmp
#fastcgi_temp = %(root_temp)s/fastcgi-tmp
#uwsgi_temp = %(root_temp)s/uwsgi-tmp
#scgi_temp = %(root_temp)s/scgi-tmp
#pid_path = %(root_temp)s/5gms-as-nginx.pid

Using this configuration will:

  • Place all 5GMSd Application Server cache directories and other temporary files and logs under the /tmp/rt-5gms-as directory for testing.
  • Change the default ports used for the 5GMSd distribution service at reference point M4d. Note that this means that all URLs output by the 5GMSd Application Function with respect to M4d will need to be manually modified to insert the new port numbers before use, e.g. if the AF publishes a URL starting http://your.hostname/... you will need to change that to http://your.hostname:8080/... in order to use the URL. This is necessary as the default ports of 80 and 443 are not available to normal unprivileged users. A normal user has to use ports with a number greater than 1024.
  • Turn on debug level output from the 5GMSd Application Server in order to better see what it happening.
  • Some settings above are commented out but may be useful while testing and so have been left in with their default values and prefixed with # to comment them out. If you wish to change one then remove the # and change the value to your desired setting.

Running the installed 5GMSd Application server

To run the version of the 5GMSd Application Server installed in the virtual environment with the local-dev.conf configuration (above), use:

cd ~/rt-5gms-application-server
PATH="/usr/local/openresty/nginx/sbin:$PATH" venv/bin/5gms-application-server -c local-dev.conf

Testing

Running the example without building

Make sure that git, java, wget and nginx are installed on the local system and can be found on the current command path ($PATH).

sudo apt install git wget nginx default-jdk python3-regex

Generate the OpenAPI python modules (these are not part of the source distribution). Read documentation below on “Regenerating the 5G API bindings”:

cd ~/rt-5gms-application-server
build_scripts/generate_5gms_as_openapi

Create a configuration to run the application server as a local, unprivileged, user.

mkdir ~/.rt_5gms
cat > ~/.rt_5gms/application-server.conf <<EOF
[DEFAULT]
log_dir = /tmp/rt-5gms-as/logs
run_dir = /tmp/rt-5gms-as

### 5GMS Application Server specific configurations
[5gms_as]
log_level = info
cache_dir = /tmp/rt-5gms-as/cache
certificates_cache = /tmp/rt-5gms-as/certificates
http_port = 8080
https_port = 8443
m3_listen = localhost
m3_port = 7777
m4d_path_prefix = /m4d/provisioning-session-{provisioningSessionId}/

### 5GMS Application Server nginx specific configuration
[5gms_as.nginx]
root_temp = /tmp/rt-5gms-as
EOF
mkdir -p /tmp/rt-5gms-as/cache
mkdir /tmp/rt-5gms-as/logs

Run the example directly:

cd ~/rt-5gms-application-server/src
python3 -m rt_5gms_as.app

This will start nginx with a default configuration that will respond with a 404 to any request on http://localhost:8080/.

At this point the 5GMS Application Server is ready for configuration by an M3 client such as the 5GMS Application Function or the m3_client_cli.py test script.

Testing with the Application Function

  1. Install both the 5GMS Application Server and Application Function.
    • To install the 5GMS Application Server follow either the sdist, direct from source or in a virtual environment instructions from the Installing section of the main README.
    • To install the 5GMS Application Function follow the directions to install the dependencies, retrieve, build and install the 5GMS Application Function from the 5GMS Application Function documentation.
  2. Configure the Application Function with the M3 port number of the Application Server (i.e. 7777) in the msaf.applicationServers section of the msaf.yaml file.
  • This is an example applicationServers entry from the msaf.yaml configuration file with the m3Port set.
    msaf:
        ...
        applicationServers:
          - canonicalHostname: localhost
            urlPathPrefixFormat: /m4d/provisioning-session-{provisioningSessionId}/
            m3Port: 7777
        ...
    
    1. In one terminal window, start the Application Server.
  • e.g. use the command 5gms-application-server
    1. In another terminal window, start the Application Function.
  • e.g. use the command ~/rt-5gms-application-function/install/bin/open5gs-msafd

The Application Function should then configure the Application Server using the Server Certificates and Content Hosting Configuration it has been configured with. This should be evident from log messages from the Application Server and Application Function and from the /tmp/rt_5gms_as.conf NGINX configuration.

See the 5GMS Application Function documentation for more details on configuring it with Certificates and a Content Hosting Configuration.

Testing without the Application Function

To enable debugging and testing, a simple M3 client command can be found the the tests subdirectory:

Usage:
    m3_client_cli.py -h | --help
    m3_client_cli.py -c | --certificate <connect>
    m3_client_cli.py -c | --certificate <connect> (add|update) <certificate-id> <pem-file>
    m3_client_cli.py -c | --certificate <connect> delete <certificate-id>
    m3_client_cli.py -H | --content-hosting-configuration <connect>
    m3_client_cli.py -H | --content-hosting-configuration <connect> (add|update) <provisioning-session-id> <content-hosting-configuration-json-file>
    m3_client_cli.py -H | --content-hosting-configuration <connect> delete <provisioning-session-id>
    m3_client_cli.py -H | --content-hosting-configuration <connect> purge <provisioning-session-id> [<pattern>]

Parameters:
    connect                  Hostname:Port of the server providing M3.
    provisioning-session-id  Provisioning Session Identifier.
    certificate-id           Certificate Identifier.
    pem-file                 Server PEM format X.509 public certificate, private key and intermediate CA certificates.
    content-hosting-configuration-json-file
                             Filename of a ContentHostingConfiguration in JSON format.
    pattern                  Regular expression to match the cache entry URL paths to delete.

Options:
    -h --help                Display the command help
    -v --version             Display command version
    -c --certificate         List known certificates or perform a certificate operation.
    -H --content-hosting-configuration
                             List known ContentHostingConfigurations or perform an operation on ContentHostingConfigurations.

This can be used instead of the AF to configure a running AS.

Prerequisite packages

These testing scripts require a few more Python 3 modules to be installed, beyond what is brought in as requirements when the when the application server is installed.

The extra modules are: docopt, aiofiles and httpx[http2].

These can be installed on ubuntu using:

apt install python3-docopt python3-aiofiles python3-httpx python3-h2

…or on most distributions by using the python pip module:

python3 -m pip install docopt aiofiles 'httpx[http2]'

Running the Application Server for testing with m3_client_cli.py

When running any of the following tests the Application Server must be running first. The exact command will depend on how you installed the Application Server or whether you are running directly without building.

Running from a virtual Python environment installation

If the AS you are testing has been installed in a virtual Python environment, as described in the Development and Testing wiki page, then you would simply run the AS from the virtual environment using your local configuration file. For example:

cd ~/rt-5gms-application-server
venv/bin/5gms-application-server -c local-dev.conf

Running a system wide AS installation

If the Application Server under test has been installed as a system process, using a command like sudo python3 -m pip install . or sudo python3 -m pip install rt-5gms-application-server-1.X.X.tar.gz, then you can run the AS as root. For example:

sudo 5gms-application-server

To configure a simple HTTP Application Server

Make sure the AS is running first (see “Running the Application Server for testing with m3_client_cli.py above).

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777 add ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest.json

This should respond with a “Success!” message, and NGINX should now be running on port 8080 using the example Big Buck Bunny configuration. You can check the NGINX configuration in /tmp/rt_5gms_as.conf.

To configure an HTTPS Application Server

Make sure the AS is running first (see “Running the Application Server for testing with m3_client_cli.py above).

This requires that the server certificate is pushed to the Application Server before the content hosting configuration is.

To generate server certificates, ensure that openssl is installed (e.g. apt -y install openssl), and then:

cd ~/rt-5gms-application-server
external/rt-common-shared/5gms/scripts/make_self_signed_certs.py tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_https.json tests/examples/Certificates.json

The 5GMS Application Server stores the certificates it has been configured with in a certificates cache. This cache is reloaded when the Application Server starts up, so it will remember certificates from previous runs.

The 5GMS Application Server can be checked for what certificates it already has by using the command:

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -c localhost:7777

To push a new certificate (with id “testcert1” using the generated certificate file):

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -c localhost:7777 add testcert1 tests/examples/certificate-1.pem

…or to update an existing certificate:

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -c localhost:7777 update testcert1 tests/examples/certificate-1.pem

Now the Content Hosting Configuration can be pushed:

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777 add ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_https.json

This should result in “Success!” and NGINX will now be listening on “https://localhost:8443/…”.

To start both HTTPS and HTTP reverse proxies for the Big Buck Bunny content, substitute the ContentHostingConfiguration above for the tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_http_and_https.json file, or update the configuration using:

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777 update ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_http_and_https.json

Note: Following these instructions will create a self-signed certificate for localhost in ~/rt-5gms-application-server/tests/examples/certificate-1.pem, this certificate will not pass normal CA verification so to access the URL you need to turn off SSL validation or accept the self-signed certificate in your browser or media player application.

Runtime configuration

The 5GMSd Application Server is configured at run-time for distribution of media via the interface at reference point M3. This is usually done by the 5GMSd Application Function, but this project also contains a simple M3 client that can be used to push run-time configuration for testing.

M3 test client

This client script provides a simple command line interface to issue M3 API calls and see the result from the response.

The script can be run as:

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -h|{<command> <hostaddr:port> [<command-parameters>...]}

If the default values for m3_listen and m3_port are used in the configuration file the <hostaddr:port> will be localhost:7777.

To see the command line help use:

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -h

M3 Certificates API

List known certificates

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -c localhost:7777

Add a new certificate

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -c localhost:7777 add testcert1 tests/examples/certificate-1.pem

Update an existing certificate

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -c localhost:7777 update testcert1 tests/examples/certificate-1.pem

Delete a certificate

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -c localhost:7777 delete testcert1

M3 ContentHostingConfiguration API

List known ContentHostingConfigurations

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777

Add a new ContentHostingConfiguration

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777 add prov-sess-1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_http_and_https.json

Update an existing ContentHostingConfiguration

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777 update prov-sess-1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_https.json

Delete a ContentHostingConfiguration

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777 delete prov-sess-1

Purge all cached objects for a ContentHostingConfiguration

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777 purge prov-sess-1

Purge cached objects using a path regex for a ContentHostingConfiguration

For example to purge all DASH manifests:

cd ~/rt-5gms-application-server
tests/m3_client_cli.py -H localhost:7777 purge prov-sess-1 '\.mpd$'

Regenerating the 5G API bindings

The build_scripts/generate_5gms_as_openapi script will use wget, git and java to download the openapi-generator tool, the 5G OpenAPI YAML and generate the rt_5gms_as.openapi_5g Python module package. The script will only do this if the src/rt_5gms_as/openapi_5g directory does not already exist.

Therefore to regenerate the API bindings you first need to remove the old bindings:

cd ~/rt-5gms-application-server
rm -rf src/rt_5gms_as/openapi_5g

Then run the generator script:

~/rt-5gms-application-server/build_scripts/generate_5gms_as_openapi

For reference (or if it is desirable to recreate the steps manually) the generate_5gms_as_openapi script performs the following actions:

  • Uses wget to fetch version 6.0.1 of the openapi-generator-cli.
    • e.g. wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/6.0.1/openapi-generator-cli-6.0.1.jar -O openapi-generator-cli.jar
  • Uses git to clone the 5G OpenAPI repository.
    • e.g. git clone -b REL-17 https://forge.3gpp.org/rep/all/5G_APIs.git
  • Copies in the API override files
    • e.g. cp -f ~/rt-5gms-application-server/external/rt-common-shared/5gms/5G_APIs-overrides/*.yaml ~/rt-5gms-application-server/build_scripts/M3_merged.yaml 5G_APIs/
  • Uses the openapi-generator-cli, downloaded in the first step, to generate the API bindings.
    • e.g. mkdir 5g-api-python; java -jar openapi-generator-cli.jar generate -i 5G_APIs/TS26512_M1_ContentHostingProvisioning.yaml -g python --additional-properties packageName=rt_5gms_as.openapi_5g,projectName=openapi-5g -o 5g-api-python; java -jar openapi-generator-cli.jar generate -t ~/rt-5gms-application-server/build_scripts -i 5G_APIs/M3_merged.yaml -g python --additional-properties packageName=rt_5gms_as.openapi_5g,projectName=openapi-5g -o 5g-api-python
  • Copies the API Python package to the src/rt_5gms_as/openapi_5g directory.