Skip to content
Snippets Groups Projects
test_wowza.py 5.08 KiB
Newer Older
#!/usr/bin/env python3
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

Criticality: Normal
Checks that the streaming server (Wowza) is running correctly.
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

from pathlib import Path
import re
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
import subprocess  # nosec: B404
from defusedxml.ElementTree import parse
from psutil import net_connections
from packaging.version import parse as parse_version
from lxml import etree
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
sys.path.append(str(Path(__file__).parents[1].resolve()))

# pylint: disable=wrong-import-position
from utilities import logging as lg  # noqa: E402
LATEST_VERSION = '4.8.5'
WOWZA_TUNE_FILE = '/usr/local/WowzaStreamingEngine/conf/Tune.xml'
WOWZA_RECOMMENDED_HEAP_SIZE = 2000
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
def main():
    '''Run all checks and exits with corresponding exit code.'''
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    warnings = 0
    errors = 0

    # check if wowza is installed
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    if not check_installed():
        exit(2)

    # check wowza version
    check_warn, check_err = check_version()
    if check_err:
        errors += 1
    elif check_warn:
        warnings += 1

    # check wowza heap size
    check_warn, check_err = check_heap_size()
    if check_err:
        errors += 1
    elif check_warn:
        warnings += 1

    # check that wowza is running
    check_warn, check_err = check_running()
    if check_err:
        errors += 1
    elif check_warn:
        warnings += 1

    # check that wowza is listening
    check_warn, check_err = check_listening()
    if check_err:
        errors += 1
    elif check_warn:
        warnings += 1

Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    if errors:
        exit(1)
    elif warnings:
        exit(3)

    exit(0)


def check_installed() -> bool:
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    :return: Exit return codes
    :rtype: bool
    out = subprocess.getoutput(cmd)
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    state = out.split()[-1]
    if state != 'install':
        lg.info('not installed, skip test')
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        return False

    return True


def check_version() -> tuple:
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    :return: Exit return codes
    :rtype: bool
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    warnings = 0
    errors = 0

Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    out = subprocess.getoutput(cmd)
    version = None
    for line in out.split('\n'):
        if line.split()[-1] == 'install':
            if version:
                lg.error('many Wowza versions installed, keep only latest')
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
                errors += 1
            version = '.'.join(re.findall(r'\d', line))
    if not version:
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        errors += 1

    if parse_version(version) < parse_version(LATEST_VERSION):
        lg.info(
            'using outdated version: {0} < {1} (recommended)'
            .format(version, LATEST_VERSION)
        )
    elif parse_version(version) > parse_version(LATEST_VERSION):
        lg.success(
            'using newer version than the recommended: {0} > {1} (recommended)'
            .format(version, LATEST_VERSION)
        )
        lg.success('using the recommended version: {0}'.format(version))
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    return warnings, errors


def check_heap_size() -> tuple:
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    :return: Exit return codes
    :rtype: bool
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    warnings = 0
    errors = 0

    # Configured wowza heap size extraction
    try:
        tune_xml = etree.parse(WOWZA_TUNE_FILE)
        value = tune_xml.find('Tune/HeapSize').text[0:-1]
        heap_size = int(value)
    except Exception as e:
        lg.info(
            'failed to get heap size value: {0}'
            .format(e)
        if heap_size < WOWZA_RECOMMENDED_HEAP_SIZE:
            lg.error(
                'not using recommended heap size: {0}M < {1}M (recommended)'
                .format(heap_size, WOWZA_RECOMMENDED_HEAP_SIZE)
            )
            errors += 1
        else:
            lg.success(
                'using recommended heap size or above: {0}M'
                .format(heap_size)
            )
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    return warnings, errors


def check_running() -> tuple:
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    :return: Exit return codes
    :rtype: bool
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    warnings = 0
    errors = 0

    cmd = 'systemctl status WowzaStreamingEngine'
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    out = subprocess.getoutput(cmd)
    if 'Active: active (running)' not in out:
        lg.error('service not running')
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        errors += 1
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    return warnings, errors
def check_listening() -> tuple:
    '''Check that Wowza is listening on configured port.

    :return: Exit return codes
    :rtype: bool

    warnings = 0
    errors = 0

    # get port number in Wowza config
    conf = parse('/usr/local/WowzaStreamingEngine/conf/VHost.xml').getroot()
    port = conf.findall('VHost/HostPortList/HostPort/Port')[0].text

    # get listening ports
    listening = set(
        c.laddr[1] for c in net_connections(kind='inet') if c.status == 'LISTEN'
    )

    # check that system is listening on this port
    if int(port) not in listening:
        lg.error('not listening on port {}'.format(port))
        lg.success('listening on port {}'.format(port))
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    main()