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