1#
2# Copyright 2008 Google Inc. All Rights Reserved.
3#
4"""Command line interface for autotest
5
6This module contains the generic CLI processing
7
8See topic_common.py for a High Level Design and Algorithm.
9
10This file figures out the topic and action from the 2 first arguments
11on the command line and imports the site_<topic> or <topic> module.
12
13It then creates a <topic>_<action> object, and calls it parses),
14execute() and output() methods.
15"""
16
17__author__ = 'jmeurin@google.com (Jean-Marc Eurin)'
18
19import os, sys, re, traceback
20
21import common
22from autotest_lib.cli import topic_common
23from autotest_lib.server import utils
24
25
26def main():
27    """
28    The generic syntax is:
29    atest <topic> <action> <options>
30    atest-<topic> <action> <options>
31    atest --help
32    """
33    utils.verify_not_root_user()
34    cli = os.path.basename(sys.argv[0])
35    syntax_obj = topic_common.atest()
36
37    # Normalize the various --help, -h and help to -h
38    sys.argv = [re.sub('--help|help', '-h', arg) for arg in sys.argv]
39
40    match = re.search('^atest-(\w+)$', cli)
41    if match:
42        topic = match.group(1)
43    else:
44        if len(sys.argv) > 1:
45            topic = sys.argv.pop(1)
46        else:
47            syntax_obj.invalid_syntax('No topic argument')
48
49
50    if topic == '-h':
51        sys.argv.insert(1, '-h')
52        syntax_obj.parse()
53
54    # The ignore flag should *only* be used by unittests.
55    ignore_site = '--ignore_site_file' in sys.argv
56    if ignore_site:
57        sys.argv.remove('--ignore_site_file')
58
59    # Import the topic specific file
60    cli_dir = os.path.abspath(os.path.dirname(__file__))
61    if (not ignore_site and
62        os.path.exists(os.path.join(cli_dir, 'site_%s.py' % topic))):
63        topic = 'site_%s' % topic
64    elif not os.path.exists(os.path.join(cli_dir, '%s.py' % topic)):
65        syntax_obj.invalid_syntax('Invalid topic %s' % topic)
66    topic_module = common.setup_modules.import_module(topic,
67                                                      'autotest_lib.cli')
68
69    # If we have a syntax error now, it should
70    # refer to the topic class.
71    topic_class = getattr(topic_module, topic)
72    topic_obj = topic_class()
73
74    if len(sys.argv) > 1:
75        action = sys.argv.pop(1)
76
77        if action == '-h':
78            action = 'help'
79            sys.argv.insert(1, '-h')
80    else:
81        topic_obj.invalid_syntax('No action argument')
82
83    # Any backward compatibility changes?
84    action = topic_obj.backward_compatibility(action, sys.argv)
85
86    # Instantiate a topic object
87    try:
88        action_class = getattr(topic_module, topic + '_' + action)
89    except AttributeError:
90        topic_obj.invalid_syntax('Invalid action %s' % action)
91
92    action_obj = action_class()
93
94    action_obj.parse()
95    try:
96        try:
97            results = action_obj.execute()
98        except topic_common.CliError:
99            pass
100        except Exception, err:
101            traceback.print_exc()
102            action_obj.generic_error("Unexpected exception: %s" % err)
103        else:
104            try:
105                action_obj.output(results)
106            except Exception:
107                traceback.print_exc()
108    finally:
109        return action_obj.show_all_failures()
110