#!/usr/bin/env python3.6

import asyncio
import os
import signal

import libvirtaio

import qubes
import qubes.api
import qubes.api.admin
import qubes.api.internal
import qubes.api.misc
import qubes.log
import qubes.utils
import qubes.vm.qubesvm

def sighandler(loop, signame, servers):
    print('caught {}, exiting'.format(signame))
    for server in servers:
        server.close()
    loop.stop()

parser = qubes.tools.QubesArgumentParser(description='Qubes OS daemon')
parser.add_argument('--debug', action='store_true', default=False,
    help='Enable verbose error logging (all exceptions with full '
         'tracebacks) and also send tracebacks to Admin API clients')

def main(args=None):
    loop = asyncio.get_event_loop()
    libvirtaio.virEventRegisterAsyncIOImpl(loop=loop)
    try:
        args = parser.parse_args(args)
    except:
        loop.close()
        raise

    args.app.register_event_handlers()

    if args.debug:
        qubes.log.enable_debug()

    servers = loop.run_until_complete(qubes.api.create_servers(
        qubes.api.admin.QubesAdminAPI,
        qubes.api.internal.QubesInternalAPI,
        qubes.api.misc.QubesMiscAPI,
        app=args.app, debug=args.debug))

    socknames = []
    for server in servers:
        for sock in server.sockets:
            socknames.append(sock.getsockname())

    for signame in ('SIGINT', 'SIGTERM'):
        loop.add_signal_handler(getattr(signal, signame),
            sighandler, loop, signame, servers)

    qubes.utils.systemd_notify()
    # make sure children will not inherit this
    os.environ.pop('NOTIFY_SOCKET', None)

    try:
        loop.run_forever()
        loop.run_until_complete(asyncio.wait([
            server.wait_closed() for server in servers]))
        for sockname in socknames:
            try:
                os.unlink(sockname)
            except FileNotFoundError:
                args.app.log.warning(
                    'socket {} got unlinked sometime before shutdown'.format(
                        sockname))
    finally:
        loop.close()

if __name__ == '__main__':
    main()