Merge "[NSB] Adds support for running "black box" test cases for VNFs"
[yardstick.git] / yardstick / plot / plotter.py
index 4cbbdfe..2f1f252 100644 (file)
@@ -9,24 +9,30 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-''' yardstick-plot - a command line tool for visualizing results from the
+""" yardstick-plot - a command line tool for visualizing results from the
     output file of yardstick framework.
 
     Example invocation:
     $ yardstick-plot -i /tmp/yardstick.out -o /tmp/plots/
-'''
+"""
+
+from __future__ import absolute_import
+from __future__ import print_function
 
 import argparse
-import json
 import os
 import sys
 import time
-import matplotlib.pyplot as plt
+
 import matplotlib.lines as mlines
+import matplotlib.pyplot as plt
+from oslo_serialization import jsonutils
+from six.moves import range
+from six.moves import zip
 
 
 class Parser(object):
-    ''' Command-line argument and input file parser for yardstick-plot tool'''
+    """ Command-line argument and input file parser for yardstick-plot tool"""
 
     def __init__(self):
         self.data = {
@@ -39,12 +45,12 @@ class Parser(object):
         self.scenarios = {}
 
     def _get_parser(self):
-        '''get a command-line parser'''
+        """get a command-line parser"""
         parser = argparse.ArgumentParser(
             prog='yardstick-plot',
             description="A tool for visualizing results from yardstick. "
                         "Currently supports plotting graphs for output files "
-                        "from tests: " + str(self.data.keys())
+                        "from tests: " + str(list(self.data.keys()))
         )
         parser.add_argument(
             '-i', '--input',
@@ -59,43 +65,43 @@ class Parser(object):
         return parser
 
     def _add_record(self, record):
-        '''add record to the relevant scenario'''
+        """add record to the relevant scenario"""
         if "runner_id" in record and "benchmark" not in record:
             obj_name = record["scenario_cfg"]["runner"]["object"]
             self.scenarios[record["runner_id"]] = obj_name
             return
         runner_object = self.scenarios[record["runner_id"]]
-        for test_type in self.data.keys():
+        for test_type in self.data:
             if test_type in runner_object:
                 self.data[test_type].append(record)
 
     def parse_args(self):
-        '''parse command-line arguments'''
+        """parse command-line arguments"""
         parser = self._get_parser()
         self.args = parser.parse_args()
         return self.args
 
     def parse_input_file(self):
-        '''parse the input test results file'''
+        """parse the input test results file"""
         if self.args.input:
             input_file = self.args.input
         else:
-            print("No input file specified, reading from %s"
-                  % self.default_input_loc)
+            print(("No input file specified, reading from %s"
+                   % self.default_input_loc))
             input_file = self.default_input_loc
 
         try:
             with open(input_file) as f:
                 for line in f:
-                    record = json.loads(line)
+                    record = jsonutils.loads(line)
                     self._add_record(record)
         except IOError as e:
-            print(os.strerror(e.errno))
+            print((os.strerror(e.errno)))
             sys.exit(1)
 
 
 class Plotter(object):
-    '''Graph plotter for scenario-specific results from yardstick framework'''
+    """Graph plotter for scenario-specific results from yardstick framework"""
 
     def __init__(self, data, output_folder):
         self.data = data
@@ -104,7 +110,7 @@ class Plotter(object):
         self.colors = ['g', 'b', 'c', 'm', 'y']
 
     def plot(self):
-        '''plot the graph(s)'''
+        """plot the graph(s)"""
         for test_type in self.data.keys():
             if self.data[test_type]:
                 plt.figure(self.fig_counter)
@@ -116,7 +122,7 @@ class Plotter(object):
                 self._save_plot(test_type)
 
     def _save_plot(self, test_type):
-        '''save the graph to output folder'''
+        """save the graph to output folder"""
         timestr = time.strftime("%Y%m%d-%H%M%S")
         file_name = test_type + "_" + timestr + ".png"
         if not self.output_folder:
@@ -126,10 +132,10 @@ class Plotter(object):
             os.makedirs(self.output_folder)
         new_file = os.path.join(self.output_folder, file_name)
         plt.savefig(new_file)
-        print("Saved graph to " + new_file)
+        print(("Saved graph to " + new_file))
 
     def _plot_ping(self, records):
-        '''ping test result interpretation and visualization on the graph'''
+        """ping test result interpretation and visualization on the graph"""
         rtts = [r['benchmark']['data']['rtt'] for r in records]
         seqs = [r['benchmark']['sequence'] for r in records]
 
@@ -143,7 +149,7 @@ class Plotter(object):
         if len(rtts) == 1:
             plt.bar(1, rtts[0], 0.35, color=self.colors[0])
         else:
-            plt.plot(seqs, rtts, self.colors[0]+'-')
+            plt.plot(seqs, rtts, self.colors[0] + '-')
 
         self._construct_legend(['rtt'])
         plt.xlabel("sequence number")
@@ -151,7 +157,7 @@ class Plotter(object):
         plt.ylabel("round trip time in milliseconds (rtt)")
 
     def _plot_pktgen(self, records):
-        '''pktgen test result interpretation and visualization on the graph'''
+        """pktgen test result interpretation and visualization on the graph"""
         flows = [r['benchmark']['data']['flows'] for r in records]
         sent = [r['benchmark']['data']['packets_sent'] for r in records]
         received = [int(r['benchmark']['data']['packets_received'])
@@ -164,20 +170,20 @@ class Plotter(object):
                 received[i] = 0.0
                 plt.axvline(flows[i], color='r')
 
-        ppm = [1000000.0*(i - j)/i for i, j in zip(sent, received)]
+        ppm = [1000000.0 * (i - j) / i for i, j in zip(sent, received)]
 
         # If there is a single data-point then display a bar-chart
         if len(ppm) == 1:
             plt.bar(1, ppm[0], 0.35, color=self.colors[0])
         else:
-            plt.plot(flows, ppm, self.colors[0]+'-')
+            plt.plot(flows, ppm, self.colors[0] + '-')
 
         self._construct_legend(['ppm'])
         plt.xlabel("number of flows")
         plt.ylabel("lost packets per million packets (ppm)")
 
     def _plot_iperf3(self, records):
-        '''iperf3 test result interpretation and visualization on the graph'''
+        """iperf3 test result interpretation and visualization on the graph"""
         intervals = []
         for r in records:
             #  If did not fail the SLA
@@ -191,7 +197,7 @@ class Plotter(object):
         for i, val in enumerate(intervals):
             if val:
                 for j, _ in enumerate(intervals):
-                    kbps.append(val[j]['sum']['bits_per_second']/1000)
+                    kbps.append(val[j]['sum']['bits_per_second'] / 1000)
                     seconds.append(seconds[-1] + val[j]['sum']['seconds'])
             else:
                 kbps.append(0.0)
@@ -202,12 +208,12 @@ class Plotter(object):
                 plt.axvline(seconds[-1], color='r')
 
         self._construct_legend(['bandwidth'])
-        plt.plot(seconds[1:], kbps[1:], self.colors[0]+'-')
+        plt.plot(seconds[1:], kbps[1:], self.colors[0] + '-')
         plt.xlabel("time in seconds")
         plt.ylabel("bandwidth in Kb/s")
 
     def _plot_fio(self, records):
-        '''fio test result interpretation and visualization on the graph'''
+        """fio test result interpretation and visualization on the graph"""
         rw_types = [r['sargs']['options']['rw'] for r in records]
         seqs = [x for x in range(1, len(records) + 1)]
         data = {}
@@ -271,8 +277,8 @@ class Plotter(object):
         plt.xticks(seqs, seqs)
 
     def _plot_fio_helper(self, data, seqs, key, bar_color, axl):
-        '''check if measurements exist for a key and then plot the
-           data to a given subplot'''
+        """check if measurements exist for a key and then plot the
+           data to a given subplot"""
         if key in data:
             if len(data[key]) == 1:
                 axl.bar(0.1, data[key], 0.35, color=bar_color)
@@ -281,7 +287,7 @@ class Plotter(object):
                 axl.plot(seqs, data[key], line_style)
 
     def _construct_legend(self, legend_texts, obj=plt):
-        '''construct legend for the plot or subplot'''
+        """construct legend for the plot or subplot"""
         ci = 0
         lines = []
 
@@ -312,5 +318,6 @@ def main():
     print("Plotting graph(s)")
     plotter.plot()
 
+
 if __name__ == '__main__':
     main()