10 import xml.dom.minidom as md
11 from xml.etree import ElementTree as ET
13 from openvswitch.mininet_tools import MininetTools
14 from openvswitch.flow_tools import FlowAdderThread, FlowRemoverThread, MapNames, loglevels, TO_GET, WAIT_TIME, OPERATIONAL_DELAY, FLOWS_PER_SECOND
15 from openvswitch.testclass_templates import TestClassAdd, TestClassRemove
16 from openvswitch.testclass_components import CheckConfigFlowsComponent, CheckOperFlowsComponent
18 class MultiTest(unittest.TestCase, TestClassAdd, TestClassRemove, CheckConfigFlowsComponent, CheckOperFlowsComponent):
20 log = logging.getLogger('MultiTest')
27 MultiTest.log.info('test setup...')
30 MultiTest.id_maps[MapNames.TEST] = dict()
31 MultiTest.id_maps[MapNames.DUMMY] = dict()
33 MultiTest.active_map = MultiTest.id_maps[MapNames.TEST]
37 MultiTest.log.info('test cleanup...')
38 self.__set_active_map(MapNames.DUMMY)
39 self.remover = FlowRemoverThread(self, 1, self.host, self.port, self.net, list(MultiTest.active_map.items()))
42 for k, v in MultiTest.id_maps.items():
44 MultiTest.log.warning('not all flows were deleted, remaining test flows: {0}, from map: {1}'.format(len(v),k))
46 def __set_active_map(self, key):
48 MultiTest.active_map = MultiTest.id_maps[key]
50 MultiTest.log.warning('Error switching between map ids: {0}'.format(str(e)))
53 def inc_error(self, value=1):
54 MultiTest.total_errors += value
56 def inc_flow(self, flow_id= None, cookie_id=1):
57 if flow_id is not None and cookie_id is not None:
58 #we dont care about actual value, just need to store flow_id as unique identifier
59 MultiTest.active_map[flow_id] = flow_id
61 def delete_flow_from_map(self, flow_id, cookie_id=None):
62 del MultiTest.active_map[flow_id]
65 self.net = MininetTools.create_network(self.host, self.mn_port)
67 MultiTest.log.info('mininet stared')
68 MultiTest.log.info('waiting {0} seconds...'.format(WAIT_TIME))
72 # add dummy flows to test removal when there are already some flows in operational
73 self.__set_active_map(MapNames.DUMMY)
74 self.adder = FlowAdderThread(self, 0, self.host, self.port, self.net, MultiTest.flows + 1, MultiTest.flows + 11)
77 self.__set_active_map(MapNames.TEST)
78 self.adder = FlowAdderThread(self, 1, self.host, self.port, self.net, 1, MultiTest.flows + 1)
81 # if we didn't manage to get any flows on controller there is no point doing test
82 assert len(MultiTest.active_map) > 0, ('Stored flows should be greater than 0, actual is {0}'.format(len(MultiTest.active_map)))
84 # check numer of flows before deletion
85 MultiTest.log.debug('{0} flows are stored by results from threads, {1} errors'.format(len(MultiTest.active_map), MultiTest.total_errors))
86 MultiTest.log.debug('{0} flows are stored in controller config'.format(self.check_config_flows(self.host, self.port, self.active_map)))
87 MultiTest.log.info('{0} flows are stored in controller operational'.format(self.check_oper_flows_loop(self.host, self.port, self.active_map)))
89 self.remover = FlowRemoverThread(self, 0, self.host, self.port, self.net, list(MultiTest.active_map.items()))
92 MultiTest.log.info('\n\n---------- preparation finished, running test ----------')
94 # check and test after deletion
95 flows_oper_after = self.check_oper_flows_loop(self.host, self.port, self.active_map)
96 MultiTest.log.debug('{0} flows are stored in controller config'.format(self.check_config_flows(self.host, self.port, self.active_map)))
97 MultiTest.log.info('{0} flows are stored in controller operational'.format(flows_oper_after))
99 # check if we have managed to delete all test
100 if len(MultiTest.active_map) <> 0:
101 MultiTest.log.warning('Not all flows added during test have been deleted, ids of remaining flows are: {0}'.format(sorted(MultiTest.active_map)))
103 # if we didn't manage to get any flows on controller there is no point doing test
104 assert flows_oper_after == len(MultiTest.active_map), 'Number of flows added during test stored in operational should be {0}, is {1}'.format(len(MultiTest.active_map), flows_oper_after)
107 if __name__ == '__main__':
109 requests_log = logging.getLogger("requests")
110 requests_log.setLevel(logging.WARNING)
112 # parse cmdline arguments
113 parser = argparse.ArgumentParser(description='End to end stress tests of flows '
114 'addition from multiple connections')
115 parser.add_argument('--odlhost', default='127.0.0.1', help='host where '
116 'odl controller is running (default = 127.0.0.1) ')
117 parser.add_argument('--odlport', type=int, default=8080, help='port on '
118 'which odl\'s RESTCONF is listening (default = 8080) ')
119 parser.add_argument('--mnport', type=int, default=6653, help='port on '
120 'which odl\'s controller is listening (default = 6653)')
121 parser.add_argument('--flows', default=100, help='how many flows will be added'
123 parser.add_argument('--log', default='info', help='log level, permitted values are'
124 ' debug/info/warning/error (default = info)')
125 args = parser.parse_args()
127 #logging.basicConfig(level=logging.DEBUG)
128 logging.basicConfig(level=loglevels.get(args.log, logging.INFO))
130 # set host and port of ODL controller for test cases
131 MultiTest.port = args.odlport
132 MultiTest.host = args.odlhost
133 MultiTest.mn_port = args.mnport
134 MultiTest.flows = int(args.flows)
138 suite = unittest.TestSuite()
139 test = MultiTest('test')
143 unittest.TextTestRunner(verbosity=2).run(suite)