#!/usr/bin/env python3

"""
This script can be used to enable, disable or query the status of dom0 and
xen's use of the primary display device.

n.b. the value returned by the "status" command will be correct as of the next
boot (assuming that the boot config is not modified further), and is not
necessarily correct at the time this script is called.
"""

import os
import re
import sys
import syslog
from pathlib import Path

from xcp.bootloader import Bootloader
from xcp.cmd import runCmd

SHORT_COMMAND_NAME = Path(__file__).name

XE_SERIAL = "xe-serial"
XEN_CMDLINE = "/opt/xensource/libexec/xen-cmdline"


def send_to_syslog(msg):
    """Send a message to syslog."""
    pid = os.getpid()
    syslog.syslog("%s[%d] - %s" % (SHORT_COMMAND_NAME, pid, msg))


def doexec(args, with_stdout=False):
    send_to_syslog(args)
    return runCmd(args, with_stdout)

def disable(bootloader):
    """
    Configure the host not to output its console to the physical display on
    next boot.
    """
    if bootloader.default == XE_SERIAL:
        doexec([XEN_CMDLINE, "--set-xen", "console=%s" % (_get_com_port())])
    else:
        doexec([XEN_CMDLINE, "--delete-dom0", "console=tty0"])
        doexec([XEN_CMDLINE, "--delete-xen", "console"])


def enable(bootloader):
    """
    Configure the host to output its console to the physical display on
    next boot.
    """
    if bootloader.default == XE_SERIAL:
        doexec([XEN_CMDLINE, "--set-xen", "console=%s,vga" % (_get_com_port())])
    else:
        doexec([XEN_CMDLINE, "--set-xen", "console=vga"])
        doexec([XEN_CMDLINE, "--set-dom0", "console=hvc0 console=tty0"])


def status(_):
    """
    Determine from the bootloader config whether the host is currently
    configured to output its console to the physical display.
    """
    (_, stdout) = doexec([XEN_CMDLINE, "--get-xen", "console"], with_stdout=True)
    if "vga" in stdout:
        sys.stdout.write("enabled")
    else:
        sys.stdout.write("disabled")

COMMANDS = {
    'disable': disable,
    'enable': enable,
    'status': status
}

def _get_com_port():
    """
    Determine from the current bootloader config which COM port is in use
    """
    (_, stdout) = doexec([XEN_CMDLINE, "--get-xen", "console"], with_stdout=True)
    m = re.match(r"console=.*(com\d).*", stdout.strip())
    if m:
        return m.group(1)
    else:
        return "com1"


def usage():
    """Display a usage string."""
    command_names = sorted(COMMANDS.keys())
    print("Usage:")
    print("    %s {%s}" % (sys.argv[0], "|".join(command_names)))


def main():
    """Program entry point."""
    if len(sys.argv) == 2 and sys.argv[1] in COMMANDS:
        bootloader = Bootloader.loadExisting()
        command = COMMANDS[sys.argv[1]]
        command(bootloader)
    else:
        usage()
        sys.exit(1)


if __name__ == "__main__":
    main()
