8 from xml.etree import ElementTree as ET
10 from odl_tests_new import MininetTools, FileLoaderTools, ParseTools
11 import xml.dom.minidom as md
14 class TestRestartMininet(unittest.TestCase):
16 log = logging.getLogger('TestRestartMininet')
19 TestRestartMininet.log.info('setUp')
20 self.switch_flows_stored = 0
26 TestRestartMininet.log.info('tearDown')
32 self.net = MininetTools.create_network(self.host, self.mn_port)
34 TestRestartMininet.log.info('mininet stared')
35 TestRestartMininet.log.info('waiting {0} seconds...'.format(wait_time))
38 def __get_flows_string(self, net=None):
41 switch = net.switches[0]
42 output = switch.cmdPrint(
43 'ovs-ofctl -O OpenFlow13 dump-flows %s' % switch.name)
45 TestRestartMininet.log.debug('switch flow table: {0}'.format(output))
47 return output.splitlines()[1:]
49 def __load_xmls(self, path='xmls'):
50 TestRestartMininet.log.info('loading xmls')
52 if in_args.xmls is not None:
53 xmls = map(int, in_args.xmls.split(','))
57 xmlfiles = (path + '/f%d.xml' % fid for fid in xmls)
59 xmlfiles = (path + '/' + xml for xml in os.listdir(path) if xml.endswith('.xml'))
63 def __add_flows(self, path_to_xml):
64 TestRestartMininet.log.info('adding flow from xml: {0}'.format(path_to_xml))
65 xml_string = FileLoaderTools.load_file_to_string(path_to_xml)
66 #TestRestartMininet.log.info('loaded xml: {}'.format(''.join(xml_string.split())))
67 tree = md.parseString(xml_string)
69 ids = ParseTools.get_values(tree.documentElement, 'table_id', 'id')
71 data = (self.host, self.port, ids['table_id'], ids['id'])
73 url = 'http://%s:%d/restconf/config/opendaylight-inventory:nodes' \
74 '/node/openflow:1/table/%s/flow/%s' % data
75 # send request via RESTCONF
77 'Content-Type': 'application/xml',
78 'Accept': 'application/xml',
80 TestRestartMininet.log.info('sending request to url: {0}'.format(url))
81 rsp = requests.put(url, auth=('admin', 'admin'), data=xml_string,
83 TestRestartMininet.log.info('received status code: {0}'.format(rsp.status_code))
84 TestRestartMininet.log.debug('received content: {0}'.format(rsp.text))
85 assert rsp.status_code == 204 or rsp.status_code == 200, 'Status' \
86 ' code returned %d' % rsp.status_code
88 # check request content against restconf's datastore
89 response = requests.get(url, auth=('admin', 'admin'),
90 headers={'Accept': 'application/xml'})
91 assert response.status_code == 200
93 switch_flows = self.__get_flows_string(self.net)
94 assert len(switch_flows) > 0
96 # store last used table id which got flows for later checkup
97 self.table_id = ids['table_id']
98 self.switch_flows_stored = len(switch_flows)
99 TestRestartMininet.log.info('stored: {0} flows'.format(self.switch_flows_stored))
103 xmls = self.__load_xmls()
105 self.__add_flows(xml)
109 TestRestartMininet.log.info('---------- preparation finished, running test ----------\n\n')
110 assert self.switch_flows_stored > 0, 'don\'t have any stored flows'
111 TestRestartMininet.log.info('got {0} stored flows'.format(self.switch_flows_stored))
113 #STOP mininet and start it again - then check flows
114 TestRestartMininet.log.info('restaring mininet...')
116 TestRestartMininet.log.info('mininet stopped')
119 url = 'http://%s:%d/restconf/config/opendaylight-inventory:nodes' \
120 '/node/openflow:1/table/%s/' % (self.host, self.port, self.table_id)
121 TestRestartMininet.log.info('checking flows in controller - sending request to url: {0}'.format(url))
122 response = requests.get(url, auth=('admin', 'admin'),
123 headers={'Accept': 'application/xml'})
124 assert response.status_code == 200
126 tree = ET.ElementTree(ET.fromstring(response.text))
127 flows_on_controller = len(tree.getroot())
128 TestRestartMininet.log.info('{0} flows are stored in switch config datastore'.format(flows_on_controller))
132 while current_try <= self.retry and switch_flows != self.switch_flows_stored:
133 TestRestartMininet.log.info('trying to get flows from mininet switch: {0}/{1}...'.format(current_try, self.retry))
134 TestRestartMininet.log.info('waiting {0} more seconds...'.format(self.wait))
135 time.sleep(self.wait)
136 switch_flows = len(self.__get_flows_string(self.net))
137 TestRestartMininet.log.info('got {0} flows...'.format(switch_flows))
138 current_try = current_try + 1
140 assert self.switch_flows_stored == switch_flows, 'Stored amount of flows on switch should be equal to stored flows on controller'\
141 ' %d <> %d' % (switch_flows,self.switch_flows_stored)
143 if __name__ == '__main__':
144 logging.basicConfig(level=logging.INFO)
146 # parse cmdline arguments
147 parser = argparse.ArgumentParser(description='Test for flow addition to'
148 ' switch after the switch has been restarted')
149 parser.add_argument('--odlhost', default='127.0.0.1', help='host where '
150 'odl controller is running (default is 127.0.0.1)')
151 parser.add_argument('--odlport', type=int, default=8080, help='port on '
152 'which odl\'s RESTCONF is listening (default is 8080)')
153 parser.add_argument('--mnport', type=int, default=6653, help='port on '
154 'which odl\'s controller is listening (default is 6653)')
155 parser.add_argument('--xmls', default=None, help='generete tests only '
156 'from some xmls (i.e. 1,3,34) (default is None)')
157 parser.add_argument('--wait', default=30, help='number of second that '
158 'should test wait before trying to get flows from '
159 'restared mininet switch (default is 30)')
160 parser.add_argument('--retry', default=1, help='number of tries to get'
161 'flows from restarted mininet (default is 1)')
162 in_args = parser.parse_args()
164 # set host and port of ODL controller for test cases
165 TestRestartMininet.port = in_args.odlport
166 TestRestartMininet.host = in_args.odlhost
167 TestRestartMininet.mn_port = in_args.mnport
168 TestRestartMininet.wait = in_args.wait
169 TestRestartMininet.retry = in_args.retry