Correct yangtools bump
[openflowplugin.git] / test-scripts / sw_restart_test.py
1 import argparse
2 import logging
3 import os
4 import requests
5 import sys
6 import time
7 import unittest
8 from xml.etree import ElementTree as ET
9
10 from odl_tests_new import MininetTools, FileLoaderTools, ParseTools
11 import xml.dom.minidom as md
12
13
14 class TestRestartMininet(unittest.TestCase):
15
16     log = logging.getLogger('TestRestartMininet')
17
18     def setUp(self):
19         TestRestartMininet.log.info('setUp')
20         self.switch_flows_stored = 0
21         self.table_id = 2
22
23         self.__start_MN()
24
25     def tearDown(self):
26         TestRestartMininet.log.info('tearDown')
27         self.net.stop()
28
29     def __start_MN(self):
30         wait_time = 15
31
32         self.net = MininetTools.create_network(self.host, self.mn_port)
33         self.net.start()
34         TestRestartMininet.log.info('mininet stared')
35         TestRestartMininet.log.info('waiting {0} seconds...'.format(wait_time))
36         time.sleep(wait_time)
37
38     def __get_flows_string(self, net=None):
39         if net is None:
40             net = self.net
41         switch = net.switches[0]
42         output = switch.cmdPrint(
43         'ovs-ofctl -O OpenFlow13 dump-flows %s' % switch.name)
44
45         TestRestartMininet.log.debug('switch flow table: {0}'.format(output))
46
47         return output.splitlines()[1:]
48
49     def __load_xmls(self, path='xmls'):
50         TestRestartMininet.log.info('loading xmls')
51         xmls = None
52         if in_args.xmls is not None:
53             xmls = map(int, in_args.xmls.split(','))
54
55         xmlfiles = None
56         if xmls is not None:
57             xmlfiles = (path + '/f%d.xml' % fid for fid in xmls)
58         else:
59             xmlfiles = (path + '/' + xml for xml in os.listdir(path) if xml.endswith('.xml'))
60
61         return xmlfiles
62
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)
68
69         ids = ParseTools.get_values(tree.documentElement, 'table_id', 'id')
70
71         data = (self.host, self.port, ids['table_id'], ids['id'])
72
73         url = 'http://%s:%d/restconf/config/opendaylight-inventory:nodes' \
74               '/node/openflow:1/table/%s/flow/%s' % data
75         # send request via RESTCONF
76         headers = {
77             'Content-Type': 'application/xml',
78             'Accept': 'application/xml',
79         }
80         TestRestartMininet.log.info('sending request to url: {0}'.format(url))
81         rsp = requests.put(url, auth=('admin', 'admin'), data=xml_string,
82                            headers=headers)
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
87         
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
92
93         switch_flows = self.__get_flows_string(self.net)
94         assert len(switch_flows) > 0
95
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))
100
101     def test(self):
102
103         xmls = self.__load_xmls()
104         for xml in xmls:
105             self.__add_flows(xml)
106         
107         switch_flows = 0
108
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))
112
113         #STOP mininet and start it again - then check flows
114         TestRestartMininet.log.info('restaring mininet...')
115         self.net.stop()
116         TestRestartMininet.log.info('mininet stopped')
117         self.__start_MN()
118
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
125
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))
129
130         current_try = 1
131
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
139
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)
142
143 if __name__ == '__main__':
144     logging.basicConfig(level=logging.INFO)
145
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()
163
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
170
171     del sys.argv[1:]
172     unittest.main()