Correct yangtools bump
[openflowplugin.git] / test-scripts / stress_test.py
1 import argparse
2 import logging
3 import sys
4 import time
5 import unittest
6
7 from openvswitch.flow_tools import FlowAdderThread, FlowRemoverThread, loglevels, \
8     WAIT_TIME
9 from openvswitch.mininet_tools import MininetTools
10 from openvswitch.testclass_components import CheckOperFlowsComponent, \
11     CheckConfigFlowsComponent, CheckSwitchDump
12
13
14 REMOVE_FLOWS_PER_THREAD = 250
15
16 class MultiTest(unittest.TestCase):
17
18     log = logging.getLogger('MultiTest')
19     total_errors = 0
20     total_flows = 0
21     stored_before_test_flows = 0
22
23     def setUp(self):
24         MultiTest.log.info('test setup...')
25         self.threads_count = 50
26         self.thread_pool = list()
27
28         self.active_map = dict()
29
30         self.__start_MN()
31         self.__setup_threads()
32         self.__run_threads()
33
34
35     def tearDown(self):
36         MultiTest.log.info('test cleanup...')
37         MultiTest.total_deleted = 0
38         self.__delete_flows()
39
40     def inc_error(self, value=1):
41         MultiTest.total_errors += value
42
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
46
47     def delete_flow_from_map(self, flow_id, cookie_id):
48         del self.active_map[cookie_id]
49
50     def __start_MN(self):
51         self.net = MininetTools.create_network(self.host, self.mn_port)
52         self.net.start()
53         MultiTest.log.info('mininet stared')
54         MultiTest.log.info('waiting {0} seconds...'.format(WAIT_TIME))
55         time.sleep(WAIT_TIME)
56         self.stored_before_test_flows = len(MininetTools.get_flows_string(self.net))
57
58     def __setup_threads(self):
59         if in_args.threads is not None:
60             self.threads_count = int(in_args.threads)
61
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)
65
66             self.thread_pool.append(t)
67
68     def __run_threads(self):
69         for t in self.thread_pool:
70             t.start()
71
72         for t in self.thread_pool:
73             t.join()
74
75     def test(self):
76         switch_flows = 0
77         total_flows = len(self.active_map.keys())
78
79         assert total_flows > 0, ('Stored flows should be greater than 0, actual is {0}'.format(total_flows))
80
81         MultiTest.log.info('\n\n---------- preparation finished, running test ----------')
82
83         # check config
84         flows_on_controller = CheckConfigFlowsComponent().check_config_flows(self.host, self.port, self.active_map)
85
86         #check operational
87         flows_on_controller_operational = CheckOperFlowsComponent().check_oper_flows_loop(self.host, self.port, self.active_map)
88
89         # check switch
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))
95                 switch_flows += 1
96
97         # print info
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))
102
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)
104
105     def __delete_flows(self):
106         MultiTest.log.info('deleting flows added during test')
107
108         # using threads to delete to speed up cleanup
109         items_to_delete = list(self.active_map.items())
110         self.thread_pool = []
111         thread_id = 0
112         slice_from = REMOVE_FLOWS_PER_THREAD * thread_id
113         slice_to = REMOVE_FLOWS_PER_THREAD * (thread_id + 1)
114
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]))
117             thread_id += 1
118             slice_from = REMOVE_FLOWS_PER_THREAD * thread_id
119             slice_to = REMOVE_FLOWS_PER_THREAD * (thread_id + 1)
120
121         for t in self.thread_pool:
122             t.start()
123
124         for t in self.thread_pool:
125             t.join()
126
127
128 if __name__ == '__main__':
129
130     requests_log = logging.getLogger("requests")
131     requests_log.setLevel(logging.WARNING)
132
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()
151
152     #logging.basicConfig(level=logging.DEBUG)
153     logging.basicConfig(level=loglevels.get(in_args.log, logging.INFO))
154
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)
161
162     del sys.argv[1:]
163
164     suite = unittest.TestSuite()
165     test = MultiTest('test')
166     suite.addTest(test)
167
168     try:
169         unittest.TextTestRunner(verbosity=2).run(suite)
170     finally:
171         test.net.stop()