Skip to content
Snippets Groups Projects
test_wowza.py 4.21 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

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
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
LATEST_VERSION = "4.7.7"
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
def main():
    """Run all checks and exits with corresponding exit code."""

    print("Checking Wowza settings:")
    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:
    """Check that Wowza is installed.

    :return: Exit return codes
    :rtype: bool
    """

    cmd = "dpkg --get-selections 'wowza*'"
    out = subprocess.getoutput(cmd)
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    state = out.split()[-1]
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    if state != "install":
        lg.info("not installed, skip test")
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        return False

    return True


def check_version() -> tuple:
    """Check the Wowza version installed.

    :return: Exit return codes
    :rtype: bool
    """

    warnings = 0
    errors = 0

    cmd = "dpkg --get-selections 'wowza*'"
    out = subprocess.getoutput(cmd)
    version = None
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

    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:
        lg.error("cannot find wWowza version")
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        errors += 1

    if version != LATEST_VERSION:
        lg.warning("using outdated version: {}".format(version))
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        warnings += 1
        lg.success("using recommended version: {}".format(LATEST_VERSION))
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    return warnings, errors


def check_heap_size() -> tuple:
    """Check the heap size configured.

    :return: Exit return codes
    :rtype: bool
    """

    warnings = 0
    errors = 0

    cmd = "grep '<HeapSize>2000M</HeapSize>' /usr/local/WowzaStreamingEngine/conf/Tune.xml"
    check_heap, _ = subprocess.getstatusoutput(cmd)
    if check_heap != 0:
        lg.warning("not using recommended heap size")
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        warnings += 1
        lg.success("using recommended heap size")
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    return warnings, errors


def check_running() -> tuple:
    """Check that Wowza is running.

    :return: Exit return codes
    :rtype: bool
    """

    warnings = 0
    errors = 0

    cmd = "systemctl status WowzaStreamingEngine"
    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
        lg.success("service running")
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
if __name__ == "__main__":
    main()