Merge "Bugfix: Add missing dashes"
[yardstick.git] / yardstick / cmd / cli.py
1 ##############################################################################
2 # Copyright (c) 2015 Ericsson AB and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 '''
11 Command-line interface to yardstick
12 '''
13
14 import logging
15 import os
16 import sys
17
18 from pkg_resources import get_distribution
19 from argparse import RawDescriptionHelpFormatter
20 from oslo_config import cfg
21
22 from yardstick.cmd.commands import task
23 from yardstick.cmd.commands import runner
24 from yardstick.cmd.commands import scenario
25 from yardstick.cmd.commands import testcase
26 from yardstick.cmd.commands import plugin
27
28 CONF = cfg.CONF
29 cli_opts = [
30     cfg.BoolOpt('debug',
31                 short='d',
32                 default=False,
33                 help='increase output verbosity to debug'),
34     cfg.BoolOpt('verbose',
35                 short='v',
36                 default=False,
37                 help='increase output verbosity to info')
38 ]
39 CONF.register_cli_opts(cli_opts)
40
41 CONFIG_SEARCH_PATHS = [sys.prefix + "/etc/yardstick",
42                        "~/.yardstick",
43                        "/etc/yardstick"]
44
45
46 def find_config_files(path_list):
47     for path in path_list:
48         abspath = os.path.abspath(os.path.expanduser(path))
49         confname = abspath + "/yardstick.conf"
50         if os.path.isfile(confname):
51             return [confname]
52
53     return None
54
55
56 class YardstickCLI():
57     '''Command-line interface to yardstick'''
58
59     # Command categories
60     categories = {
61         'task': task.TaskCommands,
62         'runner': runner.RunnerCommands,
63         'scenario': scenario.ScenarioCommands,
64         'testcase': testcase.TestcaseCommands,
65         'plugin': plugin.PluginCommands
66     }
67
68     def __init__(self):
69         self._version = 'yardstick version %s ' % \
70             get_distribution('yardstick').version
71
72     def _find_actions(self, subparsers, actions_module):
73         '''find action methods'''
74         # Find action methods inside actions_module and
75         # add them to the command parser.
76         # The 'actions_module' argument may be a class
77         # or module. Action methods start with 'do_'
78         for attr in (a for a in dir(actions_module) if a.startswith('do_')):
79             command = attr[3:].replace('_', '-')
80             callback = getattr(actions_module, attr)
81             desc = callback.__doc__ or ''
82             arguments = getattr(callback, 'arguments', [])
83             subparser = subparsers.add_parser(
84                 command,
85                 description=desc
86             )
87             for (args, kwargs) in arguments:
88                 subparser.add_argument(*args, **kwargs)
89             subparser.set_defaults(func=callback)
90
91     def _add_command_parsers(self, categories, subparsers):
92         '''add commands to command-line parser'''
93         for category in categories:
94             command_object = categories[category]()
95             desc = command_object.__doc__ or ''
96             subparser = subparsers.add_parser(
97                 category, description=desc,
98                 formatter_class=RawDescriptionHelpFormatter
99             )
100             subparser.set_defaults(command_object=command_object)
101             cmd_subparsers = subparser.add_subparsers(title='subcommands')
102             self._find_actions(cmd_subparsers, command_object)
103
104     def main(self, argv):
105         '''run the command line interface'''
106
107         # register subcommands to parse additional command line arguments
108         def parser(subparsers):
109             self._add_command_parsers(YardstickCLI.categories, subparsers)
110
111         category_opt = cfg.SubCommandOpt("category",
112                                          title="Command categories",
113                                          help="Available categories",
114                                          handler=parser)
115         CONF.register_cli_opt(category_opt)
116
117         # load CLI args and config files
118         CONF(argv, project="yardstick", version=self._version,
119              default_config_files=find_config_files(CONFIG_SEARCH_PATHS))
120
121         # handle global opts
122         logger = logging.getLogger('yardstick')
123         logger.setLevel(logging.WARNING)
124
125         if CONF.verbose:
126             logger.setLevel(logging.INFO)
127
128         if CONF.debug:
129             logger.setLevel(logging.DEBUG)
130
131         # dispatch to category parser
132         func = CONF.category.func
133         func(CONF.category)