#!/usr/bin/python
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""This tool manages the lxc container pool service."""

import argparse
import logging
import os
import signal
import time
from contextlib import contextmanager

import common
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import logging_config
from autotest_lib.server import server_logging_config
from autotest_lib.site_utils import lxc
from autotest_lib.site_utils.lxc import container_pool

try:
    from chromite.lib import ts_mon_config
except ImportError:
    ts_mon_config = utils.metrics_mock


# Location and base name of log files.
_LOG_LOCATION = '/usr/local/autotest/logs'
_LOG_NAME = 'lxc_pool.%d' % time.time()


def _start(args):
    """Starts up the container pool service.

    This function instantiates and starts up the pool service on the current
    thread (i.e. the function will block, and not return until the service is
    shut down).
    """
    # TODO(dshi): crbug.com/459344 Set remove this enforcement when test
    # container can be unprivileged container.
    if utils.sudo_require_password():
        logging.warning('SSP requires root privilege to run commands, please '
                        'grant root access to this process.')
        utils.run('sudo true')

    # Configure logging.
    config = server_logging_config.ServerLoggingConfig()
    config.configure_logging(verbose=args.verbose)
    config.add_debug_file_handlers(log_dir=_LOG_LOCATION, log_name=_LOG_NAME)
    # Pool code is heavily multi-threaded.  This will help debugging.
    logging_config.add_threadname_in_log()

    host_dir = lxc.SharedHostDir()
    service = container_pool.Service(host_dir)
    # Catch signals, and send the appropriate stop request to the service
    # instead of killing the main thread.
    # - SIGINT is generated by Ctrl-C
    # - SIGTERM is generated by an upstart stopping event.
    for sig in (signal.SIGINT, signal.SIGTERM):
        signal.signal(sig, lambda s, f: service.stop())

    with ts_mon_config.SetupTsMonGlobalState(service_name='lxc_pool_service',
                                             indirect=True,
                                             short_lived=False):
        # Start the service.  This blocks and does not return till the service
        # shuts down.
        service.start(pool_size=args.size)


def _status(_args):
    """Requests status from the running container pool.

    The retrieved status is printed out via logging.
    """
    with _create_client() as client:
        logging.debug('Requesting status...')
        logging.info(client.get_status())


def _stop(_args):
    """Shuts down the running container pool."""
    with _create_client() as client:
        logging.debug('Requesting stop...')
        logging.info(client.shutdown())


@contextmanager
# TODO(kenobi): Don't hard-code the timeout.
def _create_client(timeout=3):
    logging.debug('Creating client...')
    address = os.path.join(lxc.SharedHostDir().path,
                           lxc.DEFAULT_CONTAINER_POOL_SOCKET)
    with container_pool.Client.connect(address, timeout) as connection:
        yield connection


def parse_args():
    """Parse command line inputs.

    @raise argparse.ArgumentError: If command line arguments are invalid.
    """
    parser = argparse.ArgumentParser()

    parser.add_argument('-v', '--verbose',
                        help='Enable verbose output.',
                        action='store_true')

    subparsers = parser.add_subparsers(title='Commands')

    parser_start = subparsers.add_parser('start',
                                         help='Start the LXC container pool.')
    parser_start.set_defaults(func=_start)
    parser_start.add_argument('--size',
                              type=int,
                              default=lxc.DEFAULT_CONTAINER_POOL_SIZE,
                              help='Pool size (default=%d)' %
                                      lxc.DEFAULT_CONTAINER_POOL_SIZE)

    parser_stop = subparsers.add_parser('stop',
                                        help='Stop the container pool.')
    parser_stop.set_defaults(func=_stop)

    parser_status = subparsers.add_parser('status',
                                          help='Query pool status.')
    parser_status.set_defaults(func=_status)

    options = parser.parse_args()
    return options


def main():
    """Main function."""
    # Parse args
    args = parse_args()

    # Dispatch control to the appropriate helper.
    args.func(args)


if __name__ == '__main__':
    main()
