Permalink
Browse files

html output support

html can output nice pretty csv files
tests contain the list of tests that can be performed
  adhere to rules please
  • Loading branch information...
1 parent 98b1452 commit d82b935bb329e5d04f3d9906a8c4b2935d7cc1b8 jvimal committed Jul 21, 2010
Showing with 262 additions and 0 deletions.
  1. +83 −0 html.py
  2. +179 −0 tests.py
View
83 html.py
@@ -0,0 +1,83 @@
+
+csvcount=0
+
+def tag(name, s):
+ return "<%s>%s</%s>" % (name, s, name)
+
+
+def style():
+ return tag("style", """
+ * { padding: 10px; margin: 10px; }
+ thead { background: #eee }
+ th { font-weight: bold; border: 1px solid black }
+ td { border: 1px solid black }
+ hr { padding: 0; margin: 0; border: 2px solid blue }
+ """)
+
+def script():
+ return "<script type='text/javascript' src='dygraph-combined.js'></script>"
+
+def b(s):
+ return tag("b", s)
+
+def td(s):
+ return tag("td", s)
+
+def tr(s):
+ return tag("tr", s)
+
+def join(l):
+ return "\n".join(l)
+
+def hr():
+ return "<hr/>"
+
+def section(name, s):
+ return join([tag("h2", name), s, hr()])
+
+def comments(l):
+ return tag("pre",'\n'.join(l))
+
+def csv(csv,title):
+ global csvcount
+ csvcount += 1
+ csv = map(lambda x: r"'%s\n'" % x, csv)
+ csvtxt = r"""
+ <div id="graphdiv%d"></div>
+ <script type="text/javascript">
+ g = new Dygraph(
+ // containing div
+ document.getElementById("graphdiv%d"),
+ %s
+ );
+ </script>
+ """ % (csvcount, csvcount, "+".join(csv))
+ return join([tag("h3", title), csvtxt, hr()])
+
+
+def table(d):
+ """
+ 'd' is a dictionary of {rowname : { colname : value } }
+ Returns a string of the html form of the table
+ """
+
+ if type(d) == type({}):
+ s = ""
+ cols = d[d.keys()[0]]
+ # first row, headings for cols
+ s += join([td("")] + [td(b(colname)) for colname in cols])
+
+ # every row
+ for rowname in d.keys():
+ s += tr(join( [ td(b(rowname)) ] + [td(d[rowname][colname]) for colname in cols]))
+ else:
+ s = ""
+ s += tr(join([td(x) for x in d]))
+
+ return tag("table", s)
+
+def html(fname, doc):
+ f = open(fname, "w")
+ f.write(tag("html", style() + script() + doc))
+ f.close()
+
View
179 tests.py
@@ -0,0 +1,179 @@
+
+"""
+ A collection of tests
+"""
+from time import sleep
+import html
+
+def log(s):
+ print s
+
+def append_ratios(table):
+ ret = table
+ t = table['values']
+ ret['ratio'] = {}
+
+ m = 0.0000001
+ for k in t.keys():
+ m = max(m, t[k])
+
+ for k in t.keys():
+ ret['ratio'][k] = '%.2f' % (ret['values'][k] / m)
+
+ return ret
+
+class IPerfOneToAllTest:
+ """
+ One to all iperf tests
+ Each iperf client outputs to a file, every 1 s
+ during the test the (exp-moving?) average bandwidth it has
+ received. It is upto the test module to do whatever it wants
+ with it. Here, we will also monitor and collect the TCP window
+ size every 1 second. And finally, we also look at # TCP losses,
+ #TCP Timeouts and whatnot from /proc/net/netstat, which is
+ /var/lib/vz/root/<id>/proc/1/net/netstat
+ """
+
+ def __init__(self, hosts, t=10):
+ self.hosts = hosts
+ self.t = t
+ self.hostnames = [h.name for h in hosts]
+
+ log('IPerf tests on pairs %s for %d seconds' % (self.hostnames, t))
+ self.hosts[0].cmd('iperf -s &')
+
+ def start(self):
+ log('Starting iperf tests on pairs %s' % self.hostnames)
+
+ for h1 in self.hosts[1:]:
+ h1.cmd('rm -rf iperf_output tcpstats.csv')
+ h1.cmd('mkdir -p iperf_output')
+ h1.cmd('iperf -t %d -c %s -i 1 -yc > iperf_output/%s-%s &'
+ % (self.t, self.hosts[0].IP(), h1.name, self.hosts[0].name))
+ h1.cmd('python tcpstats.py > tcpstats.csv &')
+
+ def output(self):
+ ret = ''
+ start_time = 0
+ for h in self.hosts:
+ # time series data from iperf,
+ lines = h.open('iperf_output/%s-%s').readlines()
+ bandwidth = ['Time,Bandwidth (Mbps)']
+
+ for l in lines:
+ arr = l.strip().split(',')
+ tim,val = int(arr[0]), int(arr[-1])
+ if start_time == 0:
+ start_time = tim
+ bandwidth.append( "%d,%.3f" % (tim - start_time, val*1.0/(2**20)) )
+
+ ret += html.csv(bandwidth, "Bandwidth host %s" % (h.name))
+ ret += html.csv(h.open('tcpstats.csv').readlines(), "TCP Window size host %s" % h.name)
+
+ def end(self):
+ #sleep(self.t) # we sleep till user wakes us up
+
+ log('Ending iperf tests on hosts %s' % self.hostnames)
+ # kill the iperf server
+ self.hosts[0].cmd('killall -9 iperf')
+ for h in self.hosts:
+ h.cmd('killall -9 python')
+ return self.output()
+
+
+class IPerfAllPairTest:
+ """ All Pairs iperf tests """
+
+ def __init__(self, hosts, t=10):
+ self.hosts = hosts
+ self.t = t
+ self.hostnames = [h.name for h in hosts]
+
+ log('IPerf tests on pairs %s for %d seconds' % (self.hostnames, t))
+ for h in hosts:
+ h.cmd('iperf -s &')
+
+ def start(self):
+ log('Starting iperf tests on pairs %s' % self.hostnames)
+
+ for h1 in self.hosts:
+ h1.cmd('rm -rf iperf_output')
+ h1.cmd('mkdir -p iperf_output')
+ for h2 in self.hosts:
+ if h1 != h2:
+ h1.cmd('iperf -t %d -c %s > iperf_output/%s-%s &'
+ % (self.t, h2.IP(), h1.name, h2.name))
+
+ def output(self):
+ answer = {}
+ aggregate_in = {}
+ aggregate_out= {}
+ for h in self.hosts:
+ aggregate_in[h.name] = 0.0
+ aggregate_out[h.name]=0.0
+
+ for h1 in self.hosts:
+ answer[h1.name] = {}
+ for h2 in self.hosts:
+ if h1 != h2:
+ out = h1.open('iperf_output/%s-%s' % (h1.name, h2.name)).readlines()
+ vals = out[-1].split(' ')[-2:]
+ answer[h1.name][h2.name] = ' '.join(vals).strip().replace('bits/sec','')
+ aggregate_in[h2.name] += float(vals[0])
+ aggregate_out[h1.name] += float(vals[0])
+ else:
+ answer[h1.name][h2.name] = '----'
+
+ IN = append_ratios({'values' : aggregate_in})
+ OUT= append_ratios({'values' : aggregate_out})
+
+ return '\n'.join([
+ html.section("IPerf all pairs (%d sec)" % self.t, html.table(answer)),
+ html.section("iperf aggregate IN", html.table(IN)),
+ html.section("iperf aggregate OUT", html.table(OUT))
+ ])
+
+ def end(self):
+ sleep(self.t+5)
+ log('Ending iperf tests on hosts %s' % self.hostnames)
+ for h in self.hosts:
+ h.cmd('killall -9 iperf')
+
+ return self.output()
+
+
+
+class CPUStressTest:
+ """ CPU stress test """
+
+ def __init__(self, hosts):
+ self.hosts = hosts
+ self.hostnames = [h.name for h in hosts]
+
+ log('CPU stress on %s' % self.hostnames)
+
+ def start(self):
+ log('Starting CPU stress on %s' % self.hostnames)
+
+ for h in self.hosts:
+ h.cmd('rm -rf cpu_stress_output')
+ h.cmd('mkdir -p cpu_stress_output')
+ h.cmd('cpu-stress > cpu_stress_output/%s &' % h.name)
+
+ def output(self):
+ ret = {'values':{}}
+
+ for h in self.hosts:
+ v = int(h.open('cpu_stress_output/%s' % h.name).read().strip())
+ ret['values'][h.name] = v
+
+ return html.section("CPU Stress (seconds)", html.table(append_ratios(ret)))
+
+ def end(self):
+ log('Ending cpu-stress tests on %s' % self.hostnames)
+
+ for h in self.hosts:
+ h.cmd('killall cpu-stress')
+
+ return self.output()
+

0 comments on commit d82b935

Please sign in to comment.