summaryrefslogtreecommitdiffstats
path: root/rteval-cmd
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2012-12-17 15:30:27 +0100
committerDavid Sommerseth <davids@redhat.com>2012-12-17 15:30:27 +0100
commit189b3a3cbbc156c20fe9bf7a76aca6f35b53e2e9 (patch)
treecd920a76201c14440f040e6ef38691f0d1f46ab5 /rteval-cmd
parentfe0c14d6ea7d9e3390f34f62511048e0d9feaca4 (diff)
downloadrteval-189b3a3cbbc156c20fe9bf7a76aca6f35b53e2e9.tar.gz
rteval-189b3a3cbbc156c20fe9bf7a76aca6f35b53e2e9.tar.xz
rteval-189b3a3cbbc156c20fe9bf7a76aca6f35b53e2e9.zip
Split up rteval.py into a pure measurement module and the command line tool
This cleans up rteval further by making the RtEval class a pure measurement feature which receives all the needed setup and controls loads and measurment modules, in addition to the final reporting. The command line and config parsing is kept inside the command line tool, where it will set up everything before passing it all to the RtEval calss. Signed-off-by: David Sommerseth <davids@redhat.com>
Diffstat (limited to 'rteval-cmd')
-rwxr-xr-xrteval-cmd311
1 files changed, 311 insertions, 0 deletions
diff --git a/rteval-cmd b/rteval-cmd
new file mode 100755
index 0000000..8d1e30d
--- /dev/null
+++ b/rteval-cmd
@@ -0,0 +1,311 @@
+#!/usr/bin/python -tt
+#
+# rteval - script for evaluating platform suitability for RT Linux
+#
+# This program is used to determine the suitability of
+# a system for use in a Real Time Linux environment.
+# It starts up various system loads and measures event
+# latency while the loads are running. A report is generated
+# to show the latencies encountered during the run.
+#
+# Copyright 2009,2010,2011,2012 Clark Williams <williams@redhat.com>
+# Copyright 2009,2010,2011,2012 David Sommerseth <davids@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# For the avoidance of doubt the "preferred form" of this code is one which
+# is in an open unpatent encumbered format. Where cryptographic key signing
+# forms part of the process of creating an executable the information
+# including keys needed to generate an equivalently functional executable
+# are deemed to be part of the source code.
+#
+
+import sys, os, time, optparse, tempfile
+import libxml2, libxslt
+from datetime import datetime
+from rteval.Log import Log
+from rteval import RtEval, rtevalConfig
+from rteval.modules.loads import LoadModules
+from rteval.modules.measurement import MeasurementModules
+
+
+
+def summarize(repfile, xslt):
+ isarchive = False
+ summaryfile = repfile
+ if repfile.endswith(".tar.bz2"):
+ import tarfile
+ try:
+ t = tarfile.open(repfile)
+ except:
+ print "Don't know how to summarize %s (tarfile open failed)" % repfile
+ return
+ element = None
+ for f in t.getnames():
+ if f.find('summary.xml') != -1:
+ element = f
+ break
+ if element == None:
+ print "No summary.xml found in tar archive %s" % repfile
+ return
+ tmp = tempfile.gettempdir()
+ t.extract(element, path=tmp)
+ summaryfile = os.path.join(tmp, element)
+ isarchive = True
+
+ # Load the XSLT template
+ xsltdoc = libxml2.parseFile(xslt)
+ xsltprs = libxslt.parseStylesheetDoc(xsltdoc)
+
+ # Load the summay.xml report - with some simple sanity checks
+ xmldoc = libxml2.parseFile(summaryfile)
+ if xmldoc.name != summaryfile:
+ raise RuntimeError("Failed to load the report")
+ if xmldoc.children.name != 'rteval':
+ raise RuntimeError("The report doesn't seem like a rteval summary report")
+
+ # Parse the report through the XSLT template - preserve proper encoding
+ resdoc = xsltprs.applyStylesheet(xmldoc, None)
+ report = xsltprs.saveResultToString(resdoc).encode(xsltprs.encoding())
+
+ # Dump the report to stdout - as UTF-8
+ print report.encode('UTF-8')
+
+ # Clean up
+ del report
+ del resdoc
+ del xmldoc
+ del xsltprs
+ del xsltdoc
+
+ if isarchive:
+ os.unlink(summaryfile)
+
+
+
+def parse_options(cfg, cmdargs):
+ '''parse the command line arguments'''
+
+ rtevcfg = cfg.GetSection('rteval')
+ parser = optparse.OptionParser()
+ parser.add_option("-d", "--duration", dest="duration",
+ type="string", default=rtevcfg.duration,
+ help="specify length of test run (default: %default)")
+ parser.add_option("-v", "--verbose", dest="verbose",
+ action="store_true", default=rtevcfg.verbose,
+ help="turn on verbose prints (default: %default)")
+ parser.add_option("-w", "--workdir", dest="workdir",
+ type="string", default=rtevcfg.workdir,
+ help="top directory for rteval data (default: %default)")
+ parser.add_option("-l", "--loaddir", dest="srcdir",
+ type="string", default=rtevcfg.srcdir,
+ help="directory for load source tarballs (default: %default)")
+ parser.add_option("-i", "--installdir", dest="installdir",
+ type="string", default=rtevcfg.installdir,
+ help="place to locate installed templates (default: %default)")
+ parser.add_option("-s", "--sysreport", dest="sysreport",
+ action="store_true", default=rtevcfg.sysreport,
+ help='run sysreport to collect system data (default: %default)')
+ parser.add_option("-D", '--debug', dest='debugging',
+ action='store_true', default=rtevcfg.debugging,
+ help='turn on debug prints (default: %default)')
+ parser.add_option("-X", '--xmlrpc-submit', dest='xmlrpc',
+ action='store', default=rtevcfg.xmlrpc, metavar='HOST',
+ help='Hostname to XML-RPC server to submit reports')
+ parser.add_option("-P", "--xmlrpc-no-abort", dest="xmlrpc_noabort",
+ action='store_true', default=False,
+ help="Do not abort if XML-RPC server do not respond to ping request");
+ parser.add_option("-Z", '--summarize', dest='summarize',
+ action='store_true', default=False,
+ help='summarize an already existing XML report')
+ parser.add_option("-H", '--raw-histogram', dest='rawhistogram',
+ action='store_true', default=False,
+ help='Generate raw histogram data for an already existing XML report')
+ parser.add_option("-f", "--inifile", dest="inifile",
+ type='string', default=None,
+ help="initialization file for configuring loads and behavior")
+ parser.add_option("-a", "--annotate", dest="annotate",
+ type="string", default=None,
+ help="Add a little annotation which is stored in the report")
+ parser.add_option("-L", "--logging", dest="logging",
+ action='store_true', default=False,
+ help='log the output of the loads in the report directory')
+ parser.add_option("-O", "--onlyload", dest="onlyload",
+ action='store_true', default=False,
+ help="only run the loads (don't run measurement threads)")
+
+ (cmd_opts, cmd_args) = parser.parse_args(args = cmdargs)
+ if cmd_opts.duration:
+ mult = 1.0
+ v = cmd_opts.duration.lower()
+ if v.endswith('s'):
+ v = v[:-1]
+ elif v.endswith('m'):
+ v = v[:-1]
+ mult = 60.0
+ elif v.endswith('h'):
+ v = v[:-1]
+ mult = 3600.0
+ elif v.endswith('d'):
+ v = v[:-1]
+ mult = 3600.0 * 24.0
+ cmd_opts.duration = float(v) * mult
+ return (cmd_opts, cmd_args)
+
+
+
+if __name__ == '__main__':
+ from rteval.sysinfo import dmi
+
+ dmi.ProcessWarnings()
+
+ try:
+ default_config = {
+ 'rteval': {
+ 'quiet' : False,
+ 'verbose' : False,
+ 'keepdata' : True,
+ 'debugging' : False,
+ 'duration' : '60',
+ 'sysreport' : False,
+ 'reportdir' : None,
+ 'reportfile' : None,
+ 'workdir' : os.getcwd(),
+ 'installdir' : '/usr/share/rteval',
+ 'srcdir' : '/usr/share/rteval/loadsource',
+ 'xmlrpc' : None,
+ 'xslt_report': '/usr/share/rteval/rteval_text.xsl',
+ 'report_interval': '600',
+ 'logging' : False,
+ },
+ 'loads' : {
+ 'kcompile' : 'module',
+ 'hackbench' : 'module',
+ },
+ 'kcompile' : {
+ 'source' : 'linux-2.6.21.tar.bz2',
+ 'jobspercore': '2',
+ },
+ 'hackbench' : {
+ 'source' : 'hackbench.tar.bz2',
+ 'jobspercore': '5',
+ },
+ 'cyclictest' : {
+ 'interval' : '100',
+ 'buckets' : '2000',
+ 'distance' : '25',
+ },
+ 'measurement' : {
+ 'cyclictest' : 'module',
+ }
+ }
+
+ # Prepare logging
+ logger = Log()
+ logger.SetLogVerbosity(Log.INFO)
+
+ # setup initial configuration
+ config = rtevalConfig.rtevalConfig(default_config, logger=logger)
+
+ # Before really parsing options, see if we have been given a config file in the args
+ # and load it - just so that default values are according to the config file
+ try:
+ cfgfile = sys.argv[sys.argv.index('-f')+1]
+ config.Load(cfgfile)
+ except IndexError:
+ # Missing file argument
+ raise RuntimeError('The -f option requires a file name to the configuration file')
+ except ValueError:
+ # No configuration file given
+ pass
+
+ loadmods = LoadModules(config, logger=logger)
+ measuremods = MeasurementModules(config, logger=logger)
+
+ # parse command line options
+ (cmd_opts, cmd_args) = parse_options(config, sys.argv[1:])
+
+ # copy the command line options into the rteval config section
+ # (cmd line overrides config file values)
+ config.AppendConfig('rteval', vars(cmd_opts))
+ rtevcfg = config.GetSection('rteval')
+
+ rtevcfg.workdir = os.path.abspath(cmd_opts.workdir)
+
+ # Update log level, based on config/command line args
+ loglev = (not rtevcfg.quiet and (Log.ERR | Log.WARN)) \
+ | (rtevcfg.verbose and Log.INFO) \
+ | (rtevcfg.debugging and Log.DEBUG)
+ logger.SetLogVerbosity(loglev)
+
+ logger.log(Log.DEBUG, "workdir: %s" % rtevcfg.workdir)
+
+ # if --summarize was specified then just parse the XML, print it and exit
+ if cmd_opts.summarize or cmd_opts.rawhistogram:
+ if len(cmd_args) < 1:
+ raise RuntimeError, "Must specify at least one XML file with --summarize!"
+
+ for x in cmd_args:
+ if cmd_opts.summarize:
+ summarize(x, '%s/rteval_text.xsl' % rtevcfg.installdir)
+ elif cmd_opts.rawhistogram:
+ summarize(x, '%s/rteval_histogram_raw.xsl' % rtevcfg.installdir)
+
+ sys.exit(0)
+
+ if os.getuid() != 0:
+ print "Must be root to run rteval!"
+ sys.exit(-1)
+
+ logger.log(Log.DEBUG, '''rteval options:
+ workdir: %s
+ loaddir: %s
+ reportdir: %s
+ verbose: %s
+ debugging: %s
+ logging: %s
+ duration: %f
+ sysreport: %s''' % (
+ rtevcfg.workdir, rtevcfg.srcdir,
+ rtevcfg.reportdir, rtevcfg.verbose,
+ rtevcfg.debugging, rtevcfg.logging,
+ rtevcfg.duration, rtevcfg.sysreport))
+
+ if not os.path.isdir(rtevcfg.workdir):
+ raise RuntimeError, "work directory %d does not exist" % rtevcfg.workdir
+
+
+ rteval = RtEval(config, loadmods, measuremods, logger)
+ rteval.Prepare(cmd_opts.onlyload)
+
+ if cmd_opts.onlyload:
+ # If --onlyload were given, just kick off the loads and nothing more
+ # No reports will be created.
+ loadmods.Start()
+ nthreads = loadmods.Unleash()
+ logger.log(Log.INFO, "Started %i load threads - will run for %f seconds" % (
+ nthreads, rtevcfg.duration))
+ logger.log(Log.INFO, "No measurements will be performed, due to the --onlyload option")
+ time.sleep(rtevcfg.duration)
+ loadmods.Stop()
+ ec = 0
+ else:
+ # ... otherwise, run the full measurement suite with loads
+ ec = rteval.Measure()
+ logger.log(Log.DEBUG, "exiting with exit code: %d" % ec)
+
+ sys.exit(ec)
+ except KeyboardInterrupt:
+ sys.exit(0)