summaryrefslogtreecommitdiffstats
path: root/rteval
diff options
context:
space:
mode:
Diffstat (limited to 'rteval')
-rw-r--r--rteval/cputopology.py28
-rw-r--r--rteval/cyclictest.py4
-rw-r--r--rteval/dmi.py61
-rw-r--r--rteval/hackbench.py9
-rw-r--r--rteval/kcompile.py6
-rw-r--r--rteval/rteval.py87
-rw-r--r--rteval/rtevalConfig.py16
-rw-r--r--rteval/rteval_text.xsl5
-rw-r--r--rteval/xmlout.py126
9 files changed, 247 insertions, 95 deletions
diff --git a/rteval/cputopology.py b/rteval/cputopology.py
index 61ef982..4b696f7 100644
--- a/rteval/cputopology.py
+++ b/rteval/cputopology.py
@@ -99,12 +99,24 @@ class CPUtopology:
def getCPUsockets(self):
return self.__cpu_sockets
-if __name__ == '__main__':
- cputop = CPUtopology()
- n = cputop.parse()
-
- x = libxml2.newDoc('1.0')
- x.setRootElement(n)
- x.saveFormatFileEnc('-','UTF-8',1)
+def unit_test(rootdir):
+ try:
+ cputop = CPUtopology()
+ n = cputop.parse()
+
+ print " ---- XML Result ---- "
+ x = libxml2.newDoc('1.0')
+ x.setRootElement(n)
+ x.saveFormatFileEnc('-','UTF-8',1)
+
+ print " ---- getCPUcores() / getCPUscokets() ---- "
+ print "CPU cores: %i (online: %i) - CPU sockets: %i" % (cputop.getCPUcores(False),
+ cputop.getCPUcores(True),
+ cputop.getCPUsockets())
+ return 0
+ except Exception, e:
+ print "** EXCEPTION %s", str(e)
+ return 1
- # print "CPU cores: %i (online: %i) - CPU sockets: %i" % (cputop.getCPUcores(False), cputop.getCPUcores(True), cputop.getCPUsockets())
+if __name__ == '__main__':
+ unit_test()
diff --git a/rteval/cyclictest.py b/rteval/cyclictest.py
index 5a3ffbf..7970f35 100644
--- a/rteval/cyclictest.py
+++ b/rteval/cyclictest.py
@@ -233,7 +233,8 @@ class Cyclictest(Thread):
break
time.sleep(1.0)
self.debug("stopping")
- os.kill(c.pid, signal.SIGINT)
+ if c.poll() == None:
+ os.kill(c.pid, signal.SIGINT)
# now parse the histogram output
for line in c.stdout:
if line.startswith('#'): continue
@@ -245,6 +246,7 @@ class Cyclictest(Thread):
for n in self.data.keys():
self.data[n].reduce()
self.finished.set()
+ os.close(null)
def genxml(self, x):
x.openblock('cyclictest')
diff --git a/rteval/dmi.py b/rteval/dmi.py
index cd1b05e..7d1ab19 100644
--- a/rteval/dmi.py
+++ b/rteval/dmi.py
@@ -33,6 +33,28 @@ import libxml2
import libxslt
import dmidecode
+def ProcessWarnings():
+ if not hasattr(dmidecode, 'get_warnings'):
+ return
+
+ warnings = dmidecode.get_warnings()
+ if warnings == None:
+ return
+
+ for warnline in warnings.split('\n'):
+ # Ignore these warnings, as they are "valid" if not running as root
+ if warnline == '/dev/mem: Permission denied':
+ continue
+ if warnline == 'No SMBIOS nor DMI entry point found, sorry.':
+ continue
+
+ # All other warnings will be printed
+ if len(warnline) > 0:
+ print "** DMI WARNING ** %s" % warnline
+
+ dmidecode.clear_warnings()
+
+
class DMIinfo(object):
'''class used to obtain DMI info via python-dmidecode'''
@@ -64,12 +86,35 @@ class DMIinfo(object):
xml.AppendXMLnodes(node)
-if __name__ == '__main__':
+def unit_test(rootdir):
from pprint import pprint
-
- d = DMIinfo('.')
- x = xmlout.XMLOut('dmi_test', "0.0")
- x.NewReport()
- d.genxml(x)
- x.close()
- x.Write('-')
+
+ class unittest_ConfigDummy(object):
+ def __init__(self, rootdir):
+ self.config = {'installdir': '%s/rteval'}
+ self.__update_vars()
+
+ def __update_vars(self):
+ for k in self.config.keys():
+ self.__dict__[k] = self.config[k]
+
+ try:
+ ProcessWarnings()
+ if os.getuid() != 0:
+ print "** ERROR ** Must be root to run this unit_test()"
+ return 1
+
+ cfg = unittest_ConfigDummy(rootdir)
+ d = DMIinfo(cfg)
+ x = xmlout.XMLOut('dmi_test', "0.0")
+ x.NewReport()
+ d.genxml(x)
+ x.close()
+ x.Write('-')
+ return 0
+ except Exception, e:
+ print "** EXCEPTION: %s" % str(e)
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(unit_test('.'))
diff --git a/rteval/hackbench.py b/rteval/hackbench.py
index 65d0133..685b8d6 100644
--- a/rteval/hackbench.py
+++ b/rteval/hackbench.py
@@ -30,6 +30,7 @@ import time
import glob
import subprocess
from signal import SIGTERM
+from signal import SIGKILL
sys.pathconf = "."
import load
@@ -41,6 +42,7 @@ class Hackbench(load.Load):
null = open("/dev/null", "w")
subprocess.call(['killall', '-9', 'hackbench'],
stdout=null, stderr=null)
+ os.close(null)
def setup(self):
# find our tarball
@@ -93,6 +95,7 @@ class Hackbench(load.Load):
raise RuntimeError, "Can't find hackbench executable: %s" % self.exe
self.args = [self.exe, str(self.jobs)]
self.ready = True
+ os.close(null)
def runload(self):
null = os.open("/dev/null", os.O_RDWR)
@@ -104,15 +107,11 @@ class Hackbench(load.Load):
p.wait()
p = subprocess.Popen(self.args,stdin=null,stdout=null,stderr=null)
self.debug("stopping")
- os.kill(p.pid, SIGTERM)
- count = 30
- while count > 0 and p.poll() == None:
- time.sleep(1.0)
- count -= 1
if p.poll() == None:
os.kill(p.pid, SIGKILL)
p.wait()
self.debug("returning from runload()")
+ os.close(null)
def genxml(self, x):
x.taggedvalue('command_line', ' '.join(self.args), {'name':'hackbench'})
diff --git a/rteval/kcompile.py b/rteval/kcompile.py
index 1e0863a..f57a18b 100644
--- a/rteval/kcompile.py
+++ b/rteval/kcompile.py
@@ -97,6 +97,7 @@ class Kcompile(load.Load):
return
self.debug("ready to run")
self.ready = True
+ os.close(null)
def runload(self):
null = os.open("/dev/null", os.O_RDWR)
@@ -118,7 +119,10 @@ class Kcompile(load.Load):
p = subprocess.Popen(self.args,
stdin=null,stdout=null,stderr=null)
self.debug("stopping")
- os.kill(p.pid, SIGTERM)
+ if p.poll() == None:
+ os.kill(p.pid, SIGTERM)
+ p.wait()
+ os.close(null)
def genxml(self, x):
x.taggedvalue('command_line', ' '.join(self.args), {'name':'kcompile'})
diff --git a/rteval/rteval.py b/rteval/rteval.py
index 8522dbc..8fcaf1f 100644
--- a/rteval/rteval.py
+++ b/rteval/rteval.py
@@ -44,6 +44,7 @@ import optparse
import tempfile
import statvfs
import shutil
+import signal
import rtevalclient
import ethtool
import xmlrpclib
@@ -59,11 +60,17 @@ import rtevalConfig
import rtevalMailer
from cputopology import CPUtopology
+
+sigint_received = False
+def sigint_handler(signum, frame):
+ global sigint_received
+ sigint_received = True
+ print "*** SIGINT received - stopping rteval run ***"
+
+
class RtEval(object):
def __init__(self, cmdargs):
- if os.getuid() != 0:
- raise RuntimeError, "must be root to run rteval"
- self.version = "1.19"
+ self.version = "1.21"
self.load_modules = []
self.workdir = os.getcwd()
self.inifile = None
@@ -134,6 +141,7 @@ class RtEval(object):
self.kthreads = None
self.xml = None
self.baseos = "unknown"
+ self.annotate = self.cmd_options.annotate
if not self.config.xslt_report.startswith(self.config.installdir):
self.config.xslt_report = os.path.join(self.config.installdir, "rteval_text.xsl")
@@ -156,18 +164,45 @@ class RtEval(object):
res = None
if self.config.xmlrpc:
self.debug("Checking if XML-RPC server '%s' is reachable" % self.config.xmlrpc)
- try:
- client = rtevalclient.rtevalclient("http://%s/rteval/API1/" % self.config.xmlrpc)
- res = client.Hello()
- except xmlrpclib.ProtocolError:
- # Server do not support Hello(), but is reachable
- self.info("Got XML-RPC connection with %s but it did not support Hello()"
- % self.config.xmlrpc)
- res = None
- except socket.error, err:
- self.info("Could not establish XML-RPC contact with %s\n%s"
- % (self.config.xmlrpc, str(err)))
- sys.exit(2)
+ attempt = 0
+ warning_sent = False
+ ping_failed = False
+ while attempt < 6:
+ try:
+ client = rtevalclient.rtevalclient("http://%s/rteval/API1/" % self.config.xmlrpc)
+ res = client.Hello()
+ attempt = 10
+ ping_failed = False
+ except xmlrpclib.ProtocolError:
+ # Server do not support Hello(), but is reachable
+ self.info("Got XML-RPC connection with %s but it did not support Hello()"
+ % self.config.xmlrpc)
+ res = None
+ except socket.error, err:
+ self.info("Could not establish XML-RPC contact with %s\n%s"
+ % (self.config.xmlrpc, str(err)))
+
+ if (self.mailer is not None) and (not warning_sent):
+ self.mailer.SendMessage("[RTEVAL:WARNING] Failed to ping XML-RPC server",
+ "Server %s did not respond. Not giving up yet."
+ % self.config.xmlrpc)
+ warning_sent = True
+
+ # Do attempts handling
+ attempt += 1
+ if attempt > 5:
+ break # To avoid sleeping before we abort
+
+ print "Failed pinging XML-RPC server. Doing another attempt(%i) " % attempt
+ time.sleep(attempt*15) # Incremental sleep - sleep attempts*15 seconds
+ ping_failed = True
+
+ if ping_failed:
+ if not self.cmd_options.xmlrpc_noabort:
+ print "ERROR: Could not reach XML-RPC server '%s'. Aborting." % self.config.xmlrpc
+ sys.exit(2)
+ else:
+ print "WARNING: Could not ping the XML-RPC server. Will continue anyway."
if res:
self.info("Verified XML-RPC connection with %s (XML-RPC API version: %i)"
@@ -320,6 +355,9 @@ class RtEval(object):
parser.add_option("-X", '--xmlrpc-submit', dest='xmlrpc',
action='store', default=self.config.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')
@@ -329,6 +367,9 @@ class RtEval(object):
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")
(self.cmd_options, self.cmd_arguments) = parser.parse_args(args = cmdargs)
if self.cmd_options.duration:
@@ -398,6 +439,8 @@ class RtEval(object):
'seconds': seconds})
self.xmlreport.taggedvalue('date', self.start.strftime('%Y-%m-%d'))
self.xmlreport.taggedvalue('time', self.start.strftime('%H:%M:%S'))
+ if self.annotate:
+ self.xmlreport.taggedvalue('annotate', self.annotate)
self.xmlreport.closeblock()
self.xmlreport.openblock('uname')
self.xmlreport.taggedvalue('node', node)
@@ -598,6 +641,7 @@ class RtEval(object):
if minutes: r = r - (minutes * 60)
print "rteval time remaining: %d days, %d hours, %d minutes, %d seconds" % (days, hours, minutes, r)
+
def measure(self):
# Collect misc system info
self.baseos = self.get_base_os()
@@ -669,11 +713,12 @@ class RtEval(object):
report_interval = int(self.config.GetSection('rteval').report_interval)
# wait for time to expire or thread to die
+ signal.signal(signal.SIGINT, sigint_handler)
self.info("waiting for duration (%f)" % self.config.duration)
stoptime = (time.time() + self.config.duration)
currtime = time.time()
rpttime = currtime + report_interval
- while currtime <= stoptime:
+ while (currtime <= stoptime) and not sigint_received:
time.sleep(1.0)
if not self.cyclictest.isAlive():
raise RuntimeError, "cyclictest thread died!"
@@ -687,7 +732,7 @@ class RtEval(object):
self.show_remaining_time(left_to_run)
rpttime = currtime + report_interval
currtime = time.time()
-
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
finally:
# stop cyclictest
@@ -801,6 +846,9 @@ class RtEval(object):
''' main function for rteval'''
retval = 0;
+ # Parse initial DMI decoding errors
+ dmi.ProcessWarnings()
+
# if --summarize was specified then just parse the XML, print it and exit
if self.cmd_options.summarize or self.cmd_options.rawhistogram:
if len(self.cmd_arguments) < 1:
@@ -815,7 +863,7 @@ class RtEval(object):
sys.exit(0)
if os.getuid() != 0:
- print "Must be root to run evaluator!"
+ print "Must be root to run rteval!"
sys.exit(-1)
self.debug('''rteval options:
@@ -854,6 +902,9 @@ if __name__ == '__main__':
import pwd, grp
try:
+ # Parse initial DMI decoding errors
+ dmi.ProcessWarnings()
+
rteval = RtEval(sys.argv[1:])
ec = rteval.rteval()
sys.exit(ec)
diff --git a/rteval/rtevalConfig.py b/rteval/rtevalConfig.py
index 5fad260..bb77da2 100644
--- a/rteval/rtevalConfig.py
+++ b/rteval/rtevalConfig.py
@@ -185,3 +185,19 @@ class rtevalConfig(rtevalCfgSection):
return rtevalCfgSection(self.__config_data[section])
except KeyError, err:
raise KeyError("The section '%s' does not exist in the config file" % section)
+
+
+def unit_test(rootdir):
+ try:
+ cfg = rtevalConfig()
+ cfg.Load(rootdir + '/rteval/rteval.conf')
+ print cfg
+ return 0
+ except Exception, e:
+ print "** EXCEPTION %s", str(e)
+ return 1
+
+
+if __name__ == '__main__':
+ import sys
+ sys.exit(unit_test('..'))
diff --git a/rteval/rteval_text.xsl b/rteval/rteval_text.xsl
index d11cda8..2e4d385 100644
--- a/rteval/rteval_text.xsl
+++ b/rteval/rteval_text.xsl
@@ -18,6 +18,11 @@
<xsl:value-of select="run_info/@hours"/><xsl:text>h </xsl:text>
<xsl:value-of select="run_info/@minutes"/><xsl:text>m </xsl:text>
<xsl:value-of select="run_info/@seconds"/><xsl:text>s</xsl:text>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:if test="run_info/annotate">
+ <xsl:text> Remarks: </xsl:text>
+ <xsl:value-of select="run_info/annotate"/>
+ </xsl:if>
<xsl:text>&#10;&#10;</xsl:text>
<xsl:text> Tested node: </xsl:text>
diff --git a/rteval/xmlout.py b/rteval/xmlout.py
index b4fe371..648131b 100644
--- a/rteval/xmlout.py
+++ b/rteval/xmlout.py
@@ -257,58 +257,76 @@ class XMLOut(object):
return self.currtag.addChild(nodes)
+def unit_test(rootdir):
+ try:
+ x = XMLOut('rteval', 'UNIT-TEST', None, 'UTF-8')
+ x.NewReport()
+ x.openblock('run_info', {'days': 0, 'hours': 0, 'minutes': 32, 'seconds': 18})
+ x.taggedvalue('time', '11:22:33')
+ x.taggedvalue('date', '2000-11-22')
+ x.closeblock()
+ x.openblock('uname')
+ x.taggedvalue('node', u'testing - \xe6\xf8')
+ x.taggedvalue('kernel', 'my_test_kernel', {'is_RT': 0})
+ x.taggedvalue('arch', 'mips')
+ x.closeblock()
+ x.openblock('hardware')
+ x.taggedvalue('cpu_cores', 2)
+ x.taggedvalue('memory_size', 1024*1024*2)
+ x.closeblock()
+ x.openblock('loads', {'load_average': 3.29})
+ x.taggedvalue('command_line','./load/loader --extreme --ultimate --threads 4096',
+ {'name': 'heavyloader'})
+ x.taggedvalue('command_line','dd if=/dev/zero of=/dev/null', {'name': 'lightloader'})
+ x.closeblock()
+ x.close()
+ print "------------- XML OUTPUT ----------------------------"
+ x.Write("-")
+ print "------------- XSLT PARSED OUTPUT --------------------"
+ x.Write("-", "rteval_text.xsl")
+ print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ x.Write("/tmp/xmlout-test.xml")
+ del x
+
+ print "------------- LOAD XML FROM FILE -----------------------------"
+ x = XMLOut('rteval','UNIT-TEST', None, 'UTF-8')
+ x.LoadReport("/tmp/xmlout-test.xml", True)
+ print "------------- LOADED XML DATA --------------------------------"
+ x.Write("-")
+ print "------------- XSLT PARSED OUTPUT FROM LOADED XML--------------"
+ x.Write("-", "rteval_text.xsl")
+ x.close()
+
+ ## Test new data parser ... it eats most data types
+ print "------------- TESTING XMLOut::ParseData() --------------"
+ x.NewReport()
+ x.ParseData("ParseTest", "test string", {"type": "simple_string"})
+ x.ParseData("ParseTest", 1234, {"type": "integer"})
+ x.ParseData("ParseTest", 39.3904, {"type": "float"})
+ x.ParseData("ParseTest", (11,22,33,44,55), {"type": "tuples"})
+ x.ParseData("ParseTest", (99,88,77), {"type": "tuples", "comment": "Changed default tuple tag name"},
+ "int_values")
+ test = {"var1": "value 1",
+ "var2": { "varA1": 1,
+ "pi": 3.1415926,
+ "varA3": (1,
+ 2,
+ {"test1": "val1"},
+ (4.1,4.2,4.3),
+ 5),
+ "varA4": {'another_level': True,
+ 'another_value': "blabla"}
+ },
+ "utf8 data": u'æøå',
+ u"løpe": True}
+ x.ParseData("ParseTest", test, {"type": "dict"}, prefix="test ")
+ x.close()
+ x.Write("-")
+ return 0
+ except Exception, e:
+ print "** EXCEPTION %s", str(e)
+ return 1
+
if __name__ == '__main__':
- x = XMLOut('rteval', '0.6', None, 'UTF-8')
- x.NewReport()
- x.openblock('run_info', {'days': 0, 'hours': 0, 'minutes': 32, 'seconds': 18})
- x.taggedvalue('time', '11:22:33')
- x.taggedvalue('date', '2000-11-22')
- x.closeblock()
- x.openblock('uname')
- x.taggedvalue('node', u'testing - \xe6\xf8')
- x.taggedvalue('kernel', 'my_test_kernel', {'is_RT': 0})
- x.taggedvalue('arch', 'mips')
- x.closeblock()
- x.openblock('hardware')
- x.taggedvalue('cpu_cores', 2)
- x.taggedvalue('memory_size', 1024*1024*2)
- x.closeblock()
- x.openblock('loads', {'load_average': 3.29})
- x.taggedvalue('command_line','./load/loader --extreme --ultimate --threads 4096', {'name': 'heavyloader'})
- x.taggedvalue('command_line','dd if=/dev/zero of=/dev/null', {'name': 'lightloader'})
- x.closeblock()
- x.close()
- print "------------- XML OUTPUT ----------------------------"
- x.Write("-")
- print "------------- XSLT PARSED OUTPUT --------------------"
- x.Write("-", "rteval_text.xsl")
- print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
- x.LoadReport("latency.xml", True)
- x.Write("-")
- x.Write("-", "rteval_text.xsl")
- x.close()
-
- ## Test new data parser ... it eats most data types
- x.NewReport()
- x.ParseData("ParseTest", "test string", {"type": "simple_string"})
- x.ParseData("ParseTest", 1234, {"type": "integer"})
- x.ParseData("ParseTest", 39.3904, {"type": "float"})
- x.ParseData("ParseTest", (11,22,33,44,55), {"type": "tuples"})
- x.ParseData("ParseTest", (99,88,77), {"type": "tuples", "comment": "Changed default tuple tag name"},
- "int_values")
- test = {"var1": "value 1",
- "var2": { "varA1": 1,
- "pi": 3.1415926,
- "varA3": (1,
- 2,
- {"test1": "val1"},
- (4.1,4.2,4.3),
- 5),
- "varA4": {'another_level': True,
- 'another_value': "blabla"}
- },
- "utf8 data": u'æøå',
- u"løpe": True}
- x.ParseData("ParseTest", test, {"type": "dict"}, prefix="test ")
- x.close()
- x.Write("-")
+ sys.exit(unit_test('..'))
+