3896ce47c6f65c2867c742cf73f9bfe218ffc8be
[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 _register_cli_opt(self):
105
106         # register subcommands to parse additional command line arguments
107         def parser(subparsers):
108             self._add_command_parsers(YardstickCLI.categories, subparsers)
109
110         category_opt = cfg.SubCommandOpt("category",
111                                          title="Command categories",
112                                          help="Available categories",
113                                          handler=parser)
114         CONF.register_cli_opt(category_opt)
115
116     def _load_cli_config(self, argv):
117
118         # load CLI args and config files
119         CONF(argv, project="yardstick", version=self._version,
120              default_config_files=find_config_files(CONFIG_SEARCH_PATHS))
121
122     def _handle_global_opts(self):
123
124         # handle global opts
125         logger = logging.getLogger('yardstick')
126         logger.setLevel(logging.WARNING)
127
128         if CONF.verbose:
129             logger.setLevel(logging.INFO)
130
131         if CONF.debug:
132             logger.setLevel(logging.DEBUG)
133
134     def _dispath_func_notask(self):
135
136         # dispatch to category parser
137         func = CONF.category.func
138         func(CONF.category)
139
140     def _dispath_func_task(self, task_id):
141
142         # dispatch to category parser
143         func = CONF.category.func
144         func(CONF.category, task_id=task_id)
145
146     def main(self, argv):    # pragma: no cover
147         '''run the command line interface'''
148         self._register_cli_opt()
149
150         self._load_cli_config(argv)
151
152         self._handle_global_opts()
153
154         self._dispath_func_notask()
155
156     def api(self, argv, task_id):    # pragma: no cover
157         '''run the api interface'''
158         self._register_cli_opt()
159
160         self._load_cli_config(argv)
161
162         self._handle_global_opts()
163
164         self._dispath_func_task(task_id)