#!/usr/bin/python -u
# Copyright 2007-2008 Martin J. Bligh <mbligh@google.com>, Google Inc.
# Released under the GPL v2

"""
Run an control file through the server side engine
"""

import sys, os, re, traceback, signal, time, logging, logging.config

import common
from autotest_lib.server import server_job, utils, autoserv_parser, autotest
from autotest_lib.client.common_lib import pidfile

def run_autoserv(pid_file_manager, results, parser):
    # send stdin to /dev/null
    dev_null = os.open(os.devnull, os.O_RDONLY)
    os.dup2(dev_null, sys.stdin.fileno())
    os.close(dev_null)

    # Create separate process group
    os.setpgrp()

    # Implement SIGTERM handler
    def handle_sigint(signum, frame):
        if pid_file_manager:
            pid_file_manager.close_file(1, signal.SIGTERM)
        os.killpg(os.getpgrp(), signal.SIGKILL)

    # Set signal handler
    signal.signal(signal.SIGTERM, handle_sigint)

    # Get a useful value for running 'USER'
    realuser = os.environ.get('USER')
    if not realuser:
        realuser = 'anonymous'

    if parser.options.machines:
        machines = parser.options.machines.replace(',', ' ').strip().split()
    else:
        machines = []
    machines_file = parser.options.machines_file
    label = parser.options.label
    user = parser.options.user
    client = parser.options.client
    server = parser.options.server
    install_before = parser.options.install_before
    install_after = parser.options.install_after
    verify = parser.options.verify
    repair = parser.options.repair
    cleanup = parser.options.cleanup
    no_tee = parser.options.no_tee
    parse_job = parser.options.parse_job
    host_protection = parser.options.host_protection
    ssh_user = parser.options.ssh_user
    ssh_port = parser.options.ssh_port
    ssh_pass = parser.options.ssh_pass
    collect_crashinfo = parser.options.collect_crashinfo

    # can't be both a client and a server side test
    if client and server:
        print "Can not specify a test as both server and client!"
        sys.exit(1)

    if len(parser.args) < 1 and not (verify or repair or cleanup
                                     or collect_crashinfo):
        print parser.parser.print_help()
        sys.exit(1)

    # We have a control file unless it's just a verify/repair/cleanup job
    if len(parser.args) > 0:
        control = parser.args[0]
    else:
        control = None

    if machines_file:
        machines = []
        for m in open(machines_file, 'r').readlines():
            # remove comments, spaces
            m = re.sub('#.*', '', m).strip()
            if m:
                machines.append(m)
        print "Read list of machines from file: %s" % machines_file
        print ','.join(machines)

    if machines:
        for machine in machines:
            if not machine or re.search('\s', machine):
                print "Invalid machine %s" % str(machine)
                sys.exit(1)
        machines = list(set(machines))
        machines.sort()

    job = server_job.server_job(control, parser.args[1:], results, label,
                                user, machines, client, parse_job,
                                ssh_user, ssh_port, ssh_pass)
    if results:
        debug_dir = os.path.join(results, 'debug')
        stdout = os.path.join(debug_dir, 'autoserv.stdout')
        stderr = os.path.join(debug_dir, 'autoserv.stderr')
        if no_tee:
            job.stdout.redirect(stdout)
            job.stderr.redirect(stderr)
        else:
            job.stdout.tee_redirect(stdout)
            job.stderr.tee_redirect(stderr)

    # perform checks
    job.precheck()

    # run the job
    exit_code = 0
    try:
        if repair:
            job.repair(host_protection)
        elif verify:
            job.verify()
        else:
            try:
                job.run(cleanup, install_before, install_after,
                        only_collect_crashinfo=collect_crashinfo)
            finally:
                while job.hosts:
                    host = job.hosts.pop()
                    host.close()
    except:
        exit_code = 1
        traceback.print_exc()

    if pid_file_manager:
        pid_file_manager.num_tests_failed = job.num_tests_failed
        pid_file_manager.close_file(exit_code)
    job.cleanup_parser()

    sys.exit(exit_code)


def main():
    # grab the parser
    parser = autoserv_parser.autoserv_parser
    parser.parse_args()

    if len(sys.argv) == 1:
        parser.parser.print_help()
        sys.exit(1)

    results = parser.options.results
    if not parser.options.no_logging:
        if not results:
            results = 'results.' + time.strftime('%Y-%m-%d-%H.%M.%S')
        results  = os.path.abspath(results)
        resultdir_exists = os.path.exists(os.path.join(results, 'control.srv'))
        if not parser.options.collect_crashinfo and resultdir_exists:
            error = "Error: results directory already exists: %s\n" % results
            sys.stderr.write(error)
            sys.exit(1)

        # Now that we certified that there's no leftover results dir from
        # previous jobs, lets create the result dir since the logging system
        # needs to create the log file in there.
        if not os.path.isdir(results):
            os.makedirs(results)
        os.environ['AUTOSERV_RESULTS'] = results
        serverdir = os.path.dirname(__file__)
        logging.config.fileConfig('%s/debug_server.ini' % serverdir)
        logging.info("Results placed in %s" % results)
    else:
        # If we supply -N, no results dir will be generated, so
        # we'll configure the logging system on code.
        stamp = '[%(asctime)s - %(levelname)-8s] %(message)s'
        root_logger = logging.getLogger()
        formatter = logging.Formatter(stamp, datefmt='%H:%M:%S')
        # Let's verify if we already have handlers for the root logger 
        # at this point.
        if len(root_logger.handlers) == 0:
            autoserv_handler = logging.StreamHandler(sys.stdout,)
            autoserv_handler.setFormatter(formatter)
            root_logger.addHandler(autoserv_handler)
        else:
            # If we already have any handlers up at this point, let's
            # just configure this one we already have.
            root_logger.handlers[0].setFormatter(formatter)

        # When the -N flag is being used, we are assuming DEBUG level for the
        # execution. We could read the level from the configuration file, 
        # but I am not sure if this is the right way to go, since we are doing
        # all the configuration on code (lmr).
        root_logger.setLevel(logging.DEBUG)


    if parser.options.write_pidfile:
        pid_file_manager = pidfile.PidFileManager("autoserv", results)
        pid_file_manager.open_file()
    else:
        pid_file_manager = None

    autotest.BaseAutotest.set_install_in_tmpdir(
        parser.options.install_in_tmpdir)

    exit_code = 0
    try:
        try:
            run_autoserv(pid_file_manager, results, parser)
        except SystemExit, e:
            exit_code = e.code
        except:
            traceback.print_exc()
            # If we don't know what happened, we'll classify it as
            # an 'abort' and return 1.
            exit_code = 1
    finally:
        if pid_file_manager:
            pid_file_manager.close_file(exit_code)
    sys.exit(exit_code)


if __name__ == '__main__':
    main()
