beaa187aa66dd5c19159e64e32469bc41cb59d59
[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 import _init_logging, LOG
23 from yardstick.cmd.commands import task
24 from yardstick.cmd.commands import runner
25 from yardstick.cmd.commands import scenario
26 from yardstick.cmd.commands import testcase
27 from yardstick.cmd.commands import plugin
28 from yardstick.cmd.commands import env
29
30 CONF = cfg.CONF
31 cli_opts = [
32     cfg.BoolOpt('debug',
33                 short='d',
34                 default=False,
35                 help='increase output verbosity to debug'),
36     cfg.BoolOpt('verbose',
37                 short='v',
38                 default=False,
39                 help='increase output verbosity to info')
40 ]
41 CONF.register_cli_opts(cli_opts)
42
43 CONFIG_SEARCH_PATHS = [sys.prefix + "/etc/yardstick",
44                        "~/.yardstick",
45                        "/etc/yardstick"]
46
47
48 def find_config_files(path_list):
49     for path in path_list:
50         abspath = os.path.abspath(os.path.expanduser(path))
51         confname = abspath + "/yardstick.conf"
52         if os.path.isfile(confname):
53             return [confname]
54
55     return None
56
57
58 class YardstickCLI():
59     '''Command-line interface to yardstick'''
60
61     # Command categories
62     categories = {
63         'task': task.TaskCommands,
64         'runner': runner.RunnerCommands,
65         'scenario': scenario.ScenarioCommands,
66         'testcase': testcase.TestcaseCommands,
67         'plugin': plugin.PluginCommands,
68         'env': env.EnvCommand
69     }
70
71     def __init__(self):
72         self.opts = []
73         self._version = 'yardstick version %s ' % \
74             get_distribution('yardstick').version
75
76     def _find_actions(self, subparsers, actions_module):
77         '''find action methods'''
78         # Find action methods inside actions_module and
79         # add them to the command parser.
80         # The 'actions_module' argument may be a class
81         # or module. Action methods start with 'do_'
82         for attr in (a for a in dir(actions_module) if a.startswith('do_')):
83             command = attr[3:].replace('_', '-')
84             callback = getattr(actions_module, attr)
85             desc = callback.__doc__ or ''
86             arguments = getattr(callback, 'arguments', [])
87             subparser = subparsers.add_parser(
88                 command,
89                 description=desc
90             )
91             for (args, kwargs) in arguments:
92                 subparser.add_argument(*args, **kwargs)
93             subparser.set_defaults(func=callback)
94
95     def _add_command_parsers(self, categories, subparsers):
96         '''add commands to command-line parser'''
97         for category in categories:
98             command_object = categories[category]()
99             desc = command_object.__doc__ or ''
100             subparser = subparsers.add_parser(
101                 category, description=desc,
102                 formatter_class=RawDescriptionHelpFormatter
103             )
104             subparser.set_defaults(command_object=command_object)
105             cmd_subparsers = subparser.add_subparsers(title='subcommands')
106             self._find_actions(cmd_subparsers, command_object)
107
108     def _register_cli_opt(self):
109
110         # register subcommands to parse additional command line arguments
111         def parser(subparsers):
112             self._add_command_parsers(YardstickCLI.categories, subparsers)
113
114         category_opt = cfg.SubCommandOpt("category",
115                                          title="Command categories",
116                                          help="Available categories",
117                                          handler=parser)
118         self._register_opt(category_opt)
119
120     def _register_opt(self, opt):
121
122         CONF.register_cli_opt(opt)
123         self.opts.append(opt)
124
125     def _load_cli_config(self, argv):
126
127         # load CLI args and config files
128         CONF(argv, project="yardstick", version=self._version,
129              default_config_files=find_config_files(CONFIG_SEARCH_PATHS))
130
131     def _handle_global_opts(self):
132
133         _init_logging()
134         if CONF.verbose:
135             LOG.setLevel(logging.INFO)
136
137         if CONF.debug:
138             LOG.setLevel(logging.DEBUG)
139
140     def _dispath_func_notask(self):
141
142         # dispatch to category parser
143         func = CONF.category.func
144         func(CONF.category)
145
146     def _dispath_func_task(self, task_id):
147
148         # dispatch to category parser
149         func = CONF.category.func
150         func(CONF.category, task_id=task_id)
151
152     def _clear_config_opts(self):
153
154         CONF.clear()
155         CONF.unregister_opts(self.opts)
156
157     def main(self, argv):    # pragma: no cover
158         '''run the command line interface'''
159         try:
160             self._register_cli_opt()
161
162             self._load_cli_config(argv)
163
164             self._handle_global_opts()
165
166             self._dispath_func_notask()
167         finally:
168             self._clear_config_opts()
169
170     def api(self, argv, task_id):    # pragma: no cover
171         '''run the api interface'''
172         try:
173             self._register_cli_opt()
174
175             self._load_cli_config(argv)
176
177             self._handle_global_opts()
178
179             self._dispath_func_task(task_id)
180         finally:
181             self._clear_config_opts()