pymtt
 All Classes Namespaces Files Functions Variables Groups
pymtt.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
4 # Copyright (c) 2018 Cisco Systems, Inc. All rights reserved.
5 # $COPYRIGHT$
6 #
7 # Additional copyrights may follow
8 #
9 # $HEADER$
10 #
11 
12 from __future__ import print_function
13 from future import standard_library
14 standard_library.install_aliases()
15 import os
16 import sys
17 import configparser
18 import importlib
19 import logging
20 import imp
21 from yapsy.PluginManager import PluginManager
22 import argparse
23 
24 # First check for bozo error - we need to be given
25 # at least a cmd line option, so no params at all
26 # sounds like a plea for "help"
27 #if 1 == len(sys.argv):
28 # sys.exit('MTT usage error: add -h for help')
29 
30 # define the cmd line arguments
31 parser = argparse.ArgumentParser(description="usage: %prog [options] testfile1 testfile2 ...")
32 
33 parser.add_argument('ini_files', action='append', metavar='FILE', nargs='*', help = ".ini file to be used")
34 
35 infoGroup = parser.add_argument_group('InfoGroup','Informational Options')
36 infoGroup.add_argument("-v", "--version",
37  action="store_true", dest="version", default=False,
38  help="Print version")
39 infoGroup.add_argument("--list-stages",
40  action="store_true", dest="listsections", default=False,
41  help="List section names understood by this client")
42 infoGroup.add_argument("--list-stage-plugins",
43  action="store", dest="listplugins", metavar="STAGE",
44  help="List available plugins for SECTION (* => all)")
45 infoGroup.add_argument("--list-stage-options",
46  action="store", dest="liststageoptions", metavar="STAGE",
47  help="List available options for STAGE (* => all)")
48 infoGroup.add_argument("--list-tools",
49  action="store_true", dest="listtools", default=False,
50  help="List tools available to this client")
51 infoGroup.add_argument("--list-tool-plugins",
52  action="store", dest="listtoolmodules", metavar="TYPE",
53  help="List available modules for TYPE (* => all)")
54 infoGroup.add_argument("--list-tool-options",
55  action="store", dest="listtooloptions", metavar="TOOL",
56  help="List available options for TOOL (* => all)")
57 infoGroup.add_argument("--list-utilities",
58  action="store_true", dest="listutils", default=False,
59  help="List utilities available to this client")
60 infoGroup.add_argument("--list-utility-plugins",
61  action="store", dest="listutilmodules", metavar="TYPE",
62  help="List available modules for TYPE (* => all)")
63 infoGroup.add_argument("--list-utility-options",
64  action="store", dest="listutiloptions", metavar="UTILITY",
65  help="List available options for UTILITY (* => all)")
66 
67 execGroup = parser.add_argument_group('execGroup', "Execution Options")
68 execGroup.add_argument("--description", dest="description",
69  help="Provide a brief title/description to be included in the log for this test")
70 execGroup.add_argument("-e", "--executor", dest="executor",
71  help="Use the specified execution STRATEGY module", metavar="STRATEGY")
72 execGroup.add_argument("--base-dir", dest="basedir",
73  help="Specify the DIRECTORY where we can find the TestDef class (checks DIRECTORY, DIRECTORY/Utilities, and DIRECTORY/pylib/Utilities locations) - also serves as default plugin-dir", metavar="DIRECTORY")
74 execGroup.add_argument("--plugin-dir", dest="plugindir",
75  help="Specify the DIRECTORY where additional plugins can be found (or comma-delimited list of DIRECTORYs)", metavar="DIRECTORY")
76 execGroup.add_argument("--ignore-loadpath-errors", action="store_true", dest="ignoreloadpatherrs", default=False,
77  help="Ignore errors in plugin paths")
78 execGroup.add_argument("--scratch-dir", dest="scratchdir", default="./mttscratch",
79  help="Specify the DIRECTORY under which scratch files are to be stored", metavar="DIRECTORY")
80 execGroup.add_argument("--print-section-time", dest="sectime",
81  action="store_true", default=True,
82  help="Display section timestamps and execution time")
83 execGroup.add_argument("--print-cmd-time", dest="cmdtime",
84  action="store_true", default=False,
85  help="Display stdout/stderr timestamps and cmd execution time")
86 execGroup.add_argument("--timestamp", dest="time",
87  action="store_true", default=False,
88  help="Alias for --print-section-time --print-cmd-time")
89 execGroup.add_argument("--clean-start", dest="clean",
90  action="store_true",
91  help="Clean the scratch directory from past MTT invocations before running")
92 execGroup.add_argument("-c", "--cleanup", dest="clean_after",
93  action="store_true",
94  help="Clean the scratch directory after a successful run")
95 execGroup.add_argument("-s", "--sections", dest="section",
96  help="Execute the specified SECTION (or comma-delimited list of SECTIONs)", metavar="SECTION")
97 execGroup.add_argument("--skip-sections", dest="skipsections",
98  help="Skip the specified SECTION (or comma-delimited list of SECTIONs)", metavar="SECTION")
99 execGroup.add_argument("--no-reporter", dest="reporter",
100  action="store_true", default=False,
101  help="Do not invoke any MTT Reporter modules")
102 execGroup.add_argument("-l", "--log", dest="logfile", default=None,
103  help="Log all output to FILE (defaults to stdout)", metavar="FILE")
104 execGroup.add_argument("--group-results", dest="submit_group_results", default=True,
105  help="Report results from each test section as it is completed")
106 execGroup.add_argument("--default-make-options", dest="default_make_options", default="-j10",
107  help="Default options when running the \"make\" command")
108 execGroup.add_argument("--env-module-wrapper", dest="env_module_wrapper", default=None,
109  help="Python environment module wrapper")
110 execGroup.add_argument("--stop-on-fail", dest="stop_on_fail",
111  action="store_true", default=False,
112  help="If a stage fails, exit and issue a non-zero return code")
113 execGroup.add_argument("--duration",
114  dest="duration", default=None,
115  help="Add a maximum duration for test before interrupting.")
116 execGroup.add_argument("--loopforever", dest="loopforever",
117  action="store_true", default=False,
118  help="Causes MTT to continue to loop forever running same set of tests. Use this in conjunction with --duration switch to loop for a specific amount of time.")
119 execGroup.add_argument("--harass_trigger",
120  dest="harass_trigger_scripts", default=None,
121  help="Paths to scripts that are run to harass the system while the test is running.")
122 execGroup.add_argument("--harass_stop",
123  dest="harass_stop_scripts", default=None,
124  help="Paths to scripts that are run to stop harassing the system after the test finishes.")
125 execGroup.add_argument("--harass_join_timeout",
126  dest="harass_join_timeout", default=None,
127  help="Number of seconds to wait while ending harass scripts. Default is infinity.")
128 
129 debugGroup = parser.add_argument_group('debugGroup', 'Debug Options')
130 debugGroup.add_argument("-d", "--debug", dest="debug",
131  action="store_true", default=False,
132  help="Output lots of debug messages")
133 debugGroup.add_argument("--verbose",
134  action="store_true", dest="verbose", default=False,
135  help="Output some status/verbose messages while processing")
136 debugGroup.add_argument("--extraverbose",
137  action="store_true", dest="extraverbose", default=False,
138  help="Output timestamps with every verbose message")
139 debugGroup.add_argument("--dryrun",
140  action="store_true", dest="dryrun", default=False,
141  help="Show commands, but do not execute them")
142 debugGroup.add_argument("--trial",
143  action="store_true", dest="trial", default=False,
144  help="Use when testing your MTT client setup; results that are generated and submitted to the database are marked as \"trials\" and are not included in normal reporting.")
145 args = parser.parse_args()
146 
147 # check to see if MTT_HOME has been set - we require it
148 try:
149  mtthome = os.environ['MTT_HOME']
150 except KeyError:
151  print("MTT_HOME could not be found in your environment")
152  print("Python client requires that this be set and point")
153  print("to the top-level directory of your MTT installation")
154  sys.exit(1)
155 
156 # check to see if it is an absolute path, as we require
157 if not os.path.isabs(mtthome):
158  print("MTT_HOME environment variable:")
159  print(" ", mtthome)
160  print("is not an absolute path")
161  sys.exit(1)
162 
163 # check to see if MTT_HOME exists
164 if not os.path.exists(mtthome):
165  print("MTT_HOME points to a non-existent location:")
166  print(" ", mtthome)
167  print("Please correct")
168  sys.exit(1)
169 
170 # set topdir and check for existence
171 topdir = os.path.join(mtthome, "pylib")
172 if not os.path.exists(topdir) or not os.path.isdir(topdir):
173  print("MTT_HOME points to a location that does not\ninclude the \"pylib\" subdirectory:")
174  print(" ", topdir)
175  print("does not exist. Please correct")
176  sys.exit(1)
177 
178 # set basedir and check for existence
179 if args.basedir and not os.path.isabs(args.basedir):
180  print("The basedir cmd line option is not an absolute path:")
181  print(" ", args.basedir)
182  print("Please correct")
183  sys.exit(1)
184 
185 basedir = args.basedir or os.path.join(mtthome, "pylib", "System")
186 if not os.path.exists(basedir) or not os.path.isdir(basedir):
187  if basedir == args.basedir:
188  print("The basedir cmd line option points to a location that does not exist:")
189  print(" ", basedir)
190  print("Please correct")
191  else:
192  print("MTT_HOME points to a location that does not\ninclude the \"pylib/System\" subdirectory:")
193  print(" ", basedir)
194  print("does not exist. Please correct")
195  sys.exit(1)
196 
197 # if they want debug, set the logging level
198 if (args.debug):
199  logging.basicConfig(level=logging.DEBUG)
200 
201 # load the "testdef" Test Definition class so we can
202 # begin building this test
203 try:
204  m = imp.load_source("TestDef", os.path.join(basedir, "TestDef.py"))
205 except ImportError:
206  print("ERROR: unable to load TestDef that must contain the Test Definition object")
207  exit(1)
208 cls = getattr(m, "TestDef")
209 a = cls()
210 
211 # create the Test Definition object and set the
212 # options and arguments
213 # create the scratch directory
214 testDef = a.__class__();
215 testDef.setOptions(args)
216 
217 # load the plugins for this test
218 testDef.loadPlugins(basedir, topdir)
219 
220 # provide an opportunity to print various requested
221 # outputs before starting to process the test
222 testDef.printInfo()
223 
224 # if they didn't specify any files, then there is nothing
225 # for us to do
226 if not args.ini_files or not args.ini_files[0]:
227  sys.exit('MTT requires at least one test-specification file')
228 
229 # sanity check a couple of options
230 if args.section and args.skipsections:
231  print("ERROR: Cannot both execute specific sections and specify sections to be skipped")
232  sys.exit(1)
233 
234 # open the logging file if given - otherwise, we log
235 # to stdout
236 testDef.openLogger()
237 
238 # Read the input test definition file(s)
239 testDef.configTest()
240 
241 # Cli specified executor takes precedent over INI
242 # If there is nothing defined in either use fallback
243 fallback = "sequential"
244 executor = args.executor or testDef.config.get('MTTDefaults', 'executor', fallback=fallback)
245 
246 # Do not verify that executor exists now
247 # When the executor is loaded it ensures it exists
248 testDef.config.set('MTTDefaults', 'executor', executor.lower())
249 
250 status = testDef.executeTest()
251 sys.exit(status)
tuple cls
Definition: pymtt.py:208