7 from openvswitch.flow_tools import FlowAdderThread, FlowRemoverThread, loglevels, \
9 from openvswitch.mininet_tools import MininetTools
10 from openvswitch.testclass_components import CheckOperFlowsComponent, \
11 CheckConfigFlowsComponent, CheckSwitchDump
14 REMOVE_FLOWS_PER_THREAD = 250
16 class MultiTest(unittest.TestCase):
18 log = logging.getLogger('MultiTest')
21 stored_before_test_flows = 0
24 MultiTest.log.info('test setup...')
25 self.threads_count = 50
26 self.thread_pool = list()
28 self.active_map = dict()
31 self.__setup_threads()
36 MultiTest.log.info('test cleanup...')
37 MultiTest.total_deleted = 0
40 def inc_error(self, value=1):
41 MultiTest.total_errors += value
43 def inc_flow(self, flow_id= None, cookie_id=None):
44 if flow_id is not None and cookie_id is not None:
45 self.active_map[cookie_id] = flow_id
47 def delete_flow_from_map(self, flow_id, cookie_id):
48 del self.active_map[cookie_id]
51 self.net = MininetTools.create_network(self.host, self.mn_port)
53 MultiTest.log.info('mininet stared')
54 MultiTest.log.info('waiting {0} seconds...'.format(WAIT_TIME))
56 self.stored_before_test_flows = len(MininetTools.get_flows_string(self.net))
58 def __setup_threads(self):
59 if in_args.threads is not None:
60 self.threads_count = int(in_args.threads)
62 for i in range(0, self.threads_count):
63 t = FlowAdderThread(self, i, self.host, self.port, self.net,\
64 flows_ids_from=i*MultiTest.flows + 1, flows_ids_to=i*MultiTest.flows + MultiTest.flows)
66 self.thread_pool.append(t)
68 def __run_threads(self):
69 for t in self.thread_pool:
72 for t in self.thread_pool:
77 total_flows = len(self.active_map.keys())
79 assert total_flows > 0, ('Stored flows should be greater than 0, actual is {0}'.format(total_flows))
81 MultiTest.log.info('\n\n---------- preparation finished, running test ----------')
84 flows_on_controller = CheckConfigFlowsComponent().check_config_flows(self.host, self.port, self.active_map)
87 flows_on_controller_operational = CheckOperFlowsComponent().check_oper_flows_loop(self.host, self.port, self.active_map)
90 switch_flows_list = MininetTools.get_flows_string(self.net)
91 MultiTest.log.info('flow dump has {0} entries (including informational)'.format(len(switch_flows_list)))
92 for item in switch_flows_list:
93 if CheckSwitchDump().get_id_by_entry(item, self.active_map) is not None:
94 MultiTest.log.debug('flow_id:{0} = {1}'.format(CheckSwitchDump().get_id_by_entry(item, self.active_map), item))
98 MultiTest.log.info('{0} flows are stored by results from threads, {1} errors'.format(total_flows, MultiTest.total_errors))
99 MultiTest.log.info('{0} flows are stored in controller config'.format(flows_on_controller))
100 MultiTest.log.info('{0} flows are stored in controller operational'.format(flows_on_controller_operational))
101 MultiTest.log.info('{0} flows are stored on switch'.format(switch_flows))
103 assert total_flows == switch_flows, 'Added amount of flows to switch should be equal to successfully added flows to controller {0} <> {1}'.format(switch_flows,total_flows)
105 def __delete_flows(self):
106 MultiTest.log.info('deleting flows added during test')
108 # using threads to delete to speed up cleanup
109 items_to_delete = list(self.active_map.items())
110 self.thread_pool = []
112 slice_from = REMOVE_FLOWS_PER_THREAD * thread_id
113 slice_to = REMOVE_FLOWS_PER_THREAD * (thread_id + 1)
115 while(slice_from < len(items_to_delete)):
116 self.thread_pool.append(FlowRemoverThread(self, thread_id, self.host, self.port, self.net, items_to_delete[slice_from:slice_to]))
118 slice_from = REMOVE_FLOWS_PER_THREAD * thread_id
119 slice_to = REMOVE_FLOWS_PER_THREAD * (thread_id + 1)
121 for t in self.thread_pool:
124 for t in self.thread_pool:
128 if __name__ == '__main__':
130 requests_log = logging.getLogger("requests")
131 requests_log.setLevel(logging.WARNING)
133 # parse cmdline arguments
134 parser = argparse.ArgumentParser(description='End to end stress tests of flows '
135 'addition from multiple connections')
136 parser.add_argument('--odlhost', default='127.0.0.1', help='host where '
137 'odl controller is running (default = 127.0.0.1) ')
138 parser.add_argument('--odlport', type=int, default=8080, help='port on '
139 'which odl\'s RESTCONF is listening (default = 8080) ')
140 parser.add_argument('--mnport', type=int, default=6633, help='port on '
141 'which odl\'s controller is listening (default = 6633)')
142 parser.add_argument('--threads', default=50, help='how many threads '
143 'should be used (default = 50)')
144 parser.add_argument('--flows', default=20, help='how many flows will add'
145 ' one thread (default = 20)')
146 parser.add_argument('--log', default='info', help='log level, permitted values are'
147 ' debug/info/warning/error (default = info)')
148 # parser.add_argument('--xmls', default=None, help='generete tests only '
149 # 'from some xmls (i.e. 1,3,34) (default = None)')
150 in_args = parser.parse_args()
152 #logging.basicConfig(level=logging.DEBUG)
153 logging.basicConfig(level=loglevels.get(in_args.log, logging.INFO))
155 # set host and port of ODL controller for test cases
156 MultiTest.port = in_args.odlport
157 MultiTest.host = in_args.odlhost
158 MultiTest.mn_port = in_args.mnport
159 MultiTest.threads = int(in_args.threads)
160 MultiTest.flows = int(in_args.flows)
164 suite = unittest.TestSuite()
165 test = MultiTest('test')
169 unittest.TextTestRunner(verbosity=2).run(suite)