Fix Flake8 errors
[integration/test.git] / tools / odl-mdsal-clustering-tests / clustering-performance-test / flow_config_blaster.py
index d7e5bb9932a7c59a6232bed388e0dd111a0fc86b..a07748150cbe768f743b9e537069725ef9f71f87 100755 (executable)
@@ -1,8 +1,4 @@
 #!/usr/bin/python
 #!/usr/bin/python
-__author__ = "Jan Medved"
-__copyright__ = "Copyright(c) 2014, Cisco Systems, Inc."
-__license__ = "New-style BSD"
-__email__ = "jmedved@cisco.com"
 
 from random import randrange
 import json
 
 from random import randrange
 import json
@@ -16,6 +12,12 @@ import requests
 import netaddr
 
 
 import netaddr
 
 
+__author__ = "Jan Medved"
+__copyright__ = "Copyright(c) 2014, Cisco Systems, Inc."
+__license__ = "New-style BSD"
+__email__ = "jmedved@cisco.com"
+
+
 class Counter(object):
     def __init__(self, start=0):
         self.lock = threading.Lock()
 class Counter(object):
     def __init__(self, start=0):
         self.lock = threading.Lock()
@@ -44,7 +46,7 @@ class Timer(object):
         self.secs = self.end - self.start
         self.msecs = self.secs * 1000  # millisecs
         if self.verbose:
         self.secs = self.end - self.start
         self.msecs = self.secs * 1000  # millisecs
         if self.verbose:
-            print ("elapsed time: %f ms" % self.msecs)
+            print("elapsed time: %f ms" % self.msecs)
 
 
 class FlowConfigBlaster(object):
 
 
 class FlowConfigBlaster(object):
@@ -104,6 +106,7 @@ class FlowConfigBlaster(object):
         FlowConfigBlaster Statistics: a class that stores and further processes
         statistics collected by Blaster worker threads during their execution.
         """
         FlowConfigBlaster Statistics: a class that stores and further processes
         statistics collected by Blaster worker threads during their execution.
         """
+
         def __init__(self):
             self.ok_rqst_rate = Counter(0.0)
             self.total_rqst_rate = Counter(0.0)
         def __init__(self):
             self.ok_rqst_rate = Counter(0.0)
             self.total_rqst_rate = Counter(0.0)
@@ -118,6 +121,15 @@ class FlowConfigBlaster(object):
             """
             Calculates the stats for RESTCONF request and flow programming
             throughput, and aggregates statistics across all Blaster threads.
             """
             Calculates the stats for RESTCONF request and flow programming
             throughput, and aggregates statistics across all Blaster threads.
+
+            Args:
+                rqst_stats: Request statistics dictionary
+                flow_stats: Flow statistcis dictionary
+                elapsed_time: Elapsed time for the test
+
+            Returns: Rates (requests/sec) for successfully finished requests,
+                     the total number of requests, sucessfully installed flow and
+                     the total number of flows
             """
             ok_rqsts = rqst_stats[200] + rqst_stats[204]
             total_rqsts = sum(rqst_stats.values())
             """
             ok_rqsts = rqst_stats[200] + rqst_stats[204]
             total_rqsts = sum(rqst_stats.values())
@@ -234,13 +246,18 @@ class FlowConfigBlaster(object):
         FlowConfigBlaster instantiation. Flow templates are json-compatible
         dictionaries that MUST contain elements for flow cookie, flow name,
         flow id and the destination IPv4 address in the flow match field.
         FlowConfigBlaster instantiation. Flow templates are json-compatible
         dictionaries that MUST contain elements for flow cookie, flow name,
         flow id and the destination IPv4 address in the flow match field.
-        :param flow_id: Id for the new flow to create
-        :param ipaddr: IP Address to put into the flow's match
-        :return: The newly created flow instance
+
+        Args:
+            flow_id: Id for the new flow to create
+            ipaddr: IP Address to put into the flow's match
+            node_id: ID of the node where to create the flow
+
+        Returns: The flow that gas been created from the template
+
         """
         flow = copy.deepcopy(self.flow_mode_template['flow'][0])
         flow['cookie'] = flow_id
         """
         flow = copy.deepcopy(self.flow_mode_template['flow'][0])
         flow['cookie'] = flow_id
-        flow['flow-name'] = 'TestFlow-%d' % flow_id
+        flow['flow-name'] = self.create_flow_name(flow_id)
         flow['id'] = str(flow_id)
         flow['match']['ipv4-destination'] = '%s/32' % str(netaddr.IPAddress(ipaddr))
         return flow
         flow['id'] = str(flow_id)
         flow['match']['ipv4-destination'] = '%s/32' % str(netaddr.IPAddress(ipaddr))
         return flow
@@ -251,6 +268,8 @@ class FlowConfigBlaster(object):
         :param session: 'requests' session on which to perform the POST
         :param node: The ID of the openflow node to which to post the flows
         :param flow_list: List of flows (in dictionary form) to POST
         :param session: 'requests' session on which to perform the POST
         :param node: The ID of the openflow node to which to post the flows
         :param flow_list: List of flows (in dictionary form) to POST
+        :param flow_count: Flow counter for round-robin host load balancing
+
         :return: status code from the POST operation
         """
         flow_data = self.convert_to_json(flow_list, node)
         :return: status code from the POST operation
         """
         flow_data = self.convert_to_json(flow_list, node)
@@ -258,7 +277,6 @@ class FlowConfigBlaster(object):
         hosts = self.host.split(",")
         host = hosts[flow_count % len(hosts)]
         flow_url = self.assemble_post_url(host, node)
         hosts = self.host.split(",")
         host = hosts[flow_count % len(hosts)]
         flow_url = self.assemble_post_url(host, node)
-        # print flow_url
 
         if not self.auth:
             r = session.post(flow_url, data=flow_data, headers=self.putheaders, stream=False, timeout=self.TIMEOUT)
 
         if not self.auth:
             r = session.post(flow_url, data=flow_data, headers=self.putheaders, stream=False, timeout=self.TIMEOUT)
@@ -287,7 +305,6 @@ class FlowConfigBlaster(object):
         fmod = dict(self.flow_mode_template)
         fmod['flow'] = flow_list
         flow_data = json.dumps(fmod)
         fmod = dict(self.flow_mode_template)
         fmod['flow'] = flow_list
         flow_data = json.dumps(fmod)
-        # print flow_data
         return flow_data
 
     def add_flows(self, start_flow_id, tid):
         return flow_data
 
     def add_flows(self, start_flow_id, tid):
@@ -311,38 +328,42 @@ class FlowConfigBlaster(object):
         n_nodes = self.get_num_nodes(s)
 
         with self.print_lock:
         n_nodes = self.get_num_nodes(s)
 
         with self.print_lock:
-            print '    Thread %d:\n        Adding %d flows on %d nodes' % (tid, self.nflows, n_nodes)
+            print('    Thread %d:\n        Adding %d flows on %d nodes' % (tid, self.nflows, n_nodes))
 
         nflows = 0
 
         nflows = 0
+        nb_actions = []
+        while nflows < self.nflows:
+            node_id = randrange(1, n_nodes + 1)
+            flow_list = []
+            for i in range(self.fpr):
+                flow_id = tid * (self.ncycles * self.nflows) + nflows + start_flow_id + self.startflow
+                self.flows[tid][flow_id] = node_id
+                flow_list.append(self.create_flow_from_template(flow_id, self.ip_addr.increment(), node_id))
+                nflows += 1
+                if nflows >= self.nflows:
+                    break
+            nb_actions.append((s, node_id, flow_list, nflows))
+
         with Timer() as t:
         with Timer() as t:
-            while nflows < self.nflows:
-                node_id = randrange(1, n_nodes + 1)
-                flow_list = []
-                for i in range(self.fpr):
-                    flow_id = tid * (self.ncycles * self.nflows) + nflows + start_flow_id + self.startflow
-                    self.flows[tid][flow_id] = node_id
-                    flow_list.append(self.create_flow_from_template(flow_id, self.ip_addr.increment(), node_id))
-                    nflows += 1
-                    if nflows >= self.nflows:
-                        break
-                sts = self.post_flows(s, node_id, flow_list, nflows)
+            for nb_action in nb_actions:
+                sts = self.post_flows(*nb_action)
                 try:
                     rqst_stats[sts] += 1
                 try:
                     rqst_stats[sts] += 1
-                    flow_stats[sts] += len(flow_list)
+                    flow_stats[sts] += len(nb_action[2])
                 except KeyError:
                     rqst_stats[sts] = 1
                 except KeyError:
                     rqst_stats[sts] = 1
-                    flow_stats[sts] = len(flow_list)
+                    flow_stats[sts] = len(nb_action[2])
 
         ok_rps, total_rps, ok_fps, total_fps = self.stats.process_stats(rqst_stats, flow_stats, t.secs)
 
         with self.print_lock:
 
         ok_rps, total_rps, ok_fps, total_fps = self.stats.process_stats(rqst_stats, flow_stats, t.secs)
 
         with self.print_lock:
-            print '\n    Thread %d results (ADD): ' % tid
-            print '        Elapsed time: %.2fs,' % t.secs
-            print '        Requests/s: %.2f OK, %.2f Total' % (ok_rps, total_rps)
-            print '        Flows/s:    %.2f OK, %.2f Total' % (ok_fps, total_fps)
-            print '        Stats ({Requests}, {Flows}): ',
-            print rqst_stats,
-            print flow_stats
+            print('\n    Thread %d results (ADD): ' % tid)
+            print('        Elapsed time: %.2fs,' % t.secs)
+            print('        Requests/s: %.2f OK, %.2f Total' % (ok_rps, total_rps))
+            print('        Flows/s:    %.2f OK, %.2f Total' % (ok_fps, total_fps))
+            print('        Stats ({Requests}, {Flows}): ')
+            print(rqst_stats,)
+            print(flow_stats)
             self.threads_done += 1
 
         s.close()
             self.threads_done += 1
 
         s.close()
@@ -353,16 +374,19 @@ class FlowConfigBlaster(object):
     def delete_flow(self, session, node, flow_id, flow_count):
         """
         Deletes a single flow from the ODL config data store using RESTCONF
     def delete_flow(self, session, node, flow_id, flow_count):
         """
         Deletes a single flow from the ODL config data store using RESTCONF
-        :param session: 'requests' session on which to perform the POST
-        :param node: Id of the openflow node from which to delete the flow
-        :param flow_id: ID of the to-be-deleted flow
-        :return: status code from the DELETE operation
+        Args:
+            session: 'requests' session on which to perform the POST
+            node:  Id of the openflow node from which to delete the flow
+            flow_id: ID of the to-be-deleted flow
+            flow_count: Index of the flow being processed (for round-robin LB)
+
+        Returns: status code from the DELETE operation
+
         """
 
         hosts = self.host.split(",")
         host = hosts[flow_count % len(hosts)]
         flow_url = self.del_url_template % (host, node, flow_id)
         """
 
         hosts = self.host.split(",")
         host = hosts[flow_count % len(hosts)]
         flow_url = self.del_url_template % (host, node, flow_id)
-        # print flow_url
 
         if not self.auth:
             r = session.delete(flow_url, headers=self.getheaders, timeout=self.TIMEOUT)
 
         if not self.auth:
             r = session.delete(flow_url, headers=self.getheaders, timeout=self.TIMEOUT)
@@ -388,7 +412,7 @@ class FlowConfigBlaster(object):
         n_nodes = self.get_num_nodes(s)
 
         with self.print_lock:
         n_nodes = self.get_num_nodes(s)
 
         with self.print_lock:
-            print 'Thread %d: Deleting %d flows on %d nodes' % (tid, self.nflows, n_nodes)
+            print('Thread %d: Deleting %d flows on %d nodes' % (tid, self.nflows, n_nodes))
 
         with Timer() as t:
             for flow in range(self.nflows):
 
         with Timer() as t:
             for flow in range(self.nflows):
@@ -402,12 +426,12 @@ class FlowConfigBlaster(object):
         ok_rps, total_rps, ok_fps, total_fps = self.stats.process_stats(rqst_stats, rqst_stats, t.secs)
 
         with self.print_lock:
         ok_rps, total_rps, ok_fps, total_fps = self.stats.process_stats(rqst_stats, rqst_stats, t.secs)
 
         with self.print_lock:
-            print '\n    Thread %d results (DELETE): ' % tid
-            print '        Elapsed time: %.2fs,' % t.secs
-            print '        Requests/s:  %.2f OK,  %.2f Total' % (ok_rps, total_rps)
-            print '        Flows/s:     %.2f OK,  %.2f Total' % (ok_fps, total_fps)
-            print '        Stats ({Requests})',
-            print rqst_stats
+            print('\n    Thread %d results (DELETE): ' % tid)
+            print('        Elapsed time: %.2fs,' % t.secs)
+            print('        Requests/s:  %.2f OK,  %.2f Total' % (ok_rps, total_rps))
+            print('        Flows/s:     %.2f OK,  %.2f Total' % (ok_fps, total_fps))
+            print('        Stats ({Requests})',)
+            print(rqst_stats)
             self.threads_done += 1
 
         s.close()
             self.threads_done += 1
 
         s.close()
@@ -430,7 +454,7 @@ class FlowConfigBlaster(object):
         for c in range(self.ncycles):
             self.stats = self.FcbStats()
             with self.print_lock:
         for c in range(self.ncycles):
             self.stats = self.FcbStats()
             with self.print_lock:
-                print '\nCycle %d:' % c
+                print('\nCycle %d:' % c)
 
             threads = []
             for i in range(self.nthreads):
 
             threads = []
             for i in range(self.nthreads):
@@ -444,20 +468,20 @@ class FlowConfigBlaster(object):
                     thread.join()
 
             with self.print_lock:
                     thread.join()
 
             with self.print_lock:
-                print '\n*** Test summary:'
-                print '    Elapsed time:    %.2fs' % t.secs
-                print '    Peak requests/s: %.2f OK, %.2f Total' % (
-                    self.stats.get_ok_rqst_rate(), self.stats.get_total_rqst_rate())
-                print '    Peak flows/s:    %.2f OK, %.2f Total' % (
-                    self.stats.get_ok_flow_rate(), self.stats.get_total_flow_rate())
-                print '    Avg. requests/s: %.2f OK, %.2f Total (%.2f%% of peak total)' % (
+                print('\n*** Test summary:')
+                print('    Elapsed time:    %.2fs' % t.secs)
+                print('    Peak requests/s: %.2f OK, %.2f Total' % (
+                    self.stats.get_ok_rqst_rate(), self.stats.get_total_rqst_rate()))
+                print('    Peak flows/s:    %.2f OK, %.2f Total' % (
+                    self.stats.get_ok_flow_rate(), self.stats.get_total_flow_rate()))
+                print('    Avg. requests/s: %.2f OK, %.2f Total (%.2f%% of peak total)' % (
                     self.stats.get_ok_rqsts() / t.secs,
                     self.stats.get_total_rqsts() / t.secs,
                     self.stats.get_ok_rqsts() / t.secs,
                     self.stats.get_total_rqsts() / t.secs,
-                    (self.stats.get_total_rqsts() / t.secs * 100) / self.stats.get_total_rqst_rate())
-                print '    Avg. flows/s:    %.2f OK, %.2f Total (%.2f%% of peak total)' % (
-                    self.stats.get_ok_flows() / t.secs,
-                    self.stats.get_total_flows() / t.secs,
-                    (self.stats.get_total_flows() / t.secs * 100) / self.stats.get_total_flow_rate())
+                    (self.stats.get_total_rqsts() / t.secs * 100) / self.stats.get_total_rqst_rate()))
+                print('    Avg. flows/s:    %.2f OK, %.2f Total (%.2f%% of peak total)' % (
+                      self.stats.get_ok_flows() / t.secs,
+                      self.stats.get_total_flows() / t.secs,
+                      (self.stats.get_total_flows() / t.secs * 100) / self.stats.get_total_flow_rate()))
 
                 self.total_ok_flows += self.stats.get_ok_flows()
                 self.total_ok_rqsts += self.stats.get_ok_rqsts()
 
                 self.total_ok_flows += self.stats.get_ok_flows()
                 self.total_ok_rqsts += self.stats.get_ok_rqsts()
@@ -475,6 +499,9 @@ class FlowConfigBlaster(object):
     def get_ok_rqsts(self):
         return self.total_ok_rqsts
 
     def get_ok_rqsts(self):
         return self.total_ok_rqsts
 
+    def create_flow_name(self, flow_id):
+        return 'TestFlow-%d' % flow_id
+
 
 def get_json_from_file(filename):
     """
 
 def get_json_from_file(filename):
     """
@@ -488,14 +515,15 @@ def get_json_from_file(filename):
             keys = ft['flow'][0].keys()
             if (u'cookie' in keys) and (u'flow-name' in keys) and (u'id' in keys) and (u'match' in keys):
                 if u'ipv4-destination' in ft[u'flow'][0]['match'].keys():
             keys = ft['flow'][0].keys()
             if (u'cookie' in keys) and (u'flow-name' in keys) and (u'id' in keys) and (u'match' in keys):
                 if u'ipv4-destination' in ft[u'flow'][0]['match'].keys():
-                    print 'File "%s" ok to use as flow template' % filename
+                    print('File "%s" ok to use as flow template' % filename)
                     return ft
         except ValueError:
                     return ft
         except ValueError:
-            print 'JSON parsing of file %s failed' % filename
+            print('JSON parsing of file %s failed' % filename)
             pass
 
     return None
 
             pass
 
     return None
 
+
 ###############################################################################
 # This is an example of what the content of a JSON flow mode template should
 # look like. Cut & paste to create a custom template. "id" and "ipv4-destination"
 ###############################################################################
 # This is an example of what the content of a JSON flow mode template should
 # look like. Cut & paste to create a custom template. "id" and "ipv4-destination"
@@ -617,16 +645,16 @@ if __name__ == "__main__":
     # <flows> are added from each thread
     fct.add_blaster()
 
     # <flows> are added from each thread
     fct.add_blaster()
 
-    print '\n*** Total flows added: %s' % fct.get_ok_flows()
-    print '    HTTP[OK] results:  %d\n' % fct.get_ok_rqsts()
+    print('\n*** Total flows added: %s' % fct.get_ok_flows())
+    print('    HTTP[OK] results:  %d\n' % fct.get_ok_rqsts())
 
     if in_args.delay > 0:
 
     if in_args.delay > 0:
-        print '*** Waiting for %d seconds before the delete cycle ***\n' % in_args.delay
+        print('*** Waiting for %d seconds before the delete cycle ***\n' % in_args.delay)
         time.sleep(in_args.delay)
 
     # Run through <cycles>, where <threads> are started in each cycle and
     # <flows> previously added in an add cycle are deleted in each thread
     if in_args.delete:
         fct.delete_blaster()
         time.sleep(in_args.delay)
 
     # Run through <cycles>, where <threads> are started in each cycle and
     # <flows> previously added in an add cycle are deleted in each thread
     if in_args.delete:
         fct.delete_blaster()
-        print '\n*** Total flows deleted: %s' % fct.get_ok_flows()
-        print '    HTTP[OK] results:    %d\n' % fct.get_ok_rqsts()
+        print('\n*** Total flows deleted: %s' % fct.get_ok_flows())
+        print('    HTTP[OK] results:    %d\n' % fct.get_ok_rqsts())