Set lock_path correctly.
[openstack-build/neutron-build.git] / neutron / tests / functional / agent / test_ovs_lib.py
1 # Copyright (c) 2015 Red Hat, Inc.
2 # All Rights Reserved.
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15
16 import collections
17 import mock
18 import uuid
19
20 from neutron.agent.common import ovs_lib
21 from neutron.agent.linux import ip_lib
22 from neutron.tests import base as tests_base
23 from neutron.tests.common import net_helpers
24 from neutron.tests.functional.agent.linux import base
25
26
27 class OVSBridgeTestBase(base.BaseOVSLinuxTestCase):
28     # TODO(twilson) So far, only ovsdb-related tests are written. It would be
29     # good to also add the openflow-related functions
30     def setUp(self):
31         super(OVSBridgeTestBase, self).setUp()
32         self.ovs = ovs_lib.BaseOVS()
33         self.br = self.useFixture(net_helpers.OVSBridgeFixture()).bridge
34
35     def create_ovs_port(self, *interface_attrs):
36         # Convert ((a, b), (c, d)) to {a: b, c: d} and add 'type' by default
37         attrs = collections.OrderedDict(interface_attrs)
38         attrs.setdefault('type', 'internal')
39         port_name = tests_base.get_rand_device_name(net_helpers.PORT_PREFIX)
40         return (port_name, self.br.add_port(port_name, *attrs.items()))
41
42     def create_ovs_vif_port(self, iface_id=None, mac=None,
43                             iface_field='iface-id'):
44         if iface_id is None:
45             iface_id = base.get_rand_name()
46         if mac is None:
47             mac = base.get_rand_name()
48         attrs = ('external_ids', {iface_field: iface_id, 'attached-mac': mac})
49         port_name, ofport = self.create_ovs_port(attrs)
50         return ovs_lib.VifPort(port_name, ofport, iface_id, mac, self.br)
51
52
53 class OVSBridgeTestCase(OVSBridgeTestBase):
54
55     def test_port_lifecycle(self):
56         (port_name, ofport) = self.create_ovs_port(('type', 'internal'))
57         # ofport should always be an integer string with value -1 or > 0.
58         self.assertTrue(int(ofport))
59         self.assertTrue(int(self.br.get_port_ofport(port_name)))
60         self.assertTrue(self.br.port_exists(port_name))
61         self.assertEqual(self.br.br_name,
62                          self.br.get_bridge_for_iface(port_name))
63         self.br.delete_port(port_name)
64         self.assertFalse(self.br.port_exists(port_name))
65
66     def test_duplicate_port_may_exist_false(self):
67         port_name, ofport = self.create_ovs_port(('type', 'internal'))
68         cmd = self.br.ovsdb.add_port(self.br.br_name,
69                                      port_name, may_exist=False)
70         self.assertRaises(RuntimeError, cmd.execute, check_error=True)
71
72     def test_delete_port_if_exists_false(self):
73         cmd = self.br.ovsdb.del_port('nonexistantport', if_exists=False)
74         self.assertRaises(RuntimeError, cmd.execute, check_error=True)
75
76     def test_replace_port(self):
77         port_name = tests_base.get_rand_device_name(net_helpers.PORT_PREFIX)
78         self.br.replace_port(port_name, ('type', 'internal'))
79         self.assertTrue(self.br.port_exists(port_name))
80         self.assertEqual('internal',
81                          self.br.db_get_val('Interface', port_name, 'type'))
82         self.br.replace_port(port_name, ('type', 'internal'),
83                              ('external_ids', {'test': 'test'}))
84         self.assertTrue(self.br.port_exists(port_name))
85         self.assertEqual('test', self.br.db_get_val('Interface', port_name,
86                                                     'external_ids')['test'])
87
88     def test_attribute_lifecycle(self):
89         (port_name, ofport) = self.create_ovs_port()
90         tag = 42
91         self.ovs.set_db_attribute('Port', port_name, 'tag', tag)
92         self.assertEqual(tag, self.ovs.db_get_val('Port', port_name, 'tag'))
93         self.assertEqual(tag, self.br.get_port_tag_dict()[port_name])
94         self.ovs.clear_db_attribute('Port', port_name, 'tag')
95         self.assertEqual([], self.ovs.db_get_val('Port', port_name, 'tag'))
96         self.assertEqual([], self.br.get_port_tag_dict()[port_name])
97
98     def test_get_bridge_external_bridge_id(self):
99         self.ovs.set_db_attribute('Bridge', self.br.br_name,
100                                   'external_ids',
101                                   {'bridge-id': self.br.br_name})
102         self.assertEqual(
103             self.br.br_name,
104             self.ovs.get_bridge_external_bridge_id(self.br.br_name))
105
106     def test_controller_lifecycle(self):
107         controllers = {'tcp:127.0.0.1:6633', 'tcp:172.17.16.10:55'}
108         self.br.set_controller(controllers)
109         self.assertSetEqual(controllers, set(self.br.get_controller()))
110         self.br.del_controller()
111         self.assertEqual([], self.br.get_controller())
112
113     def test_non_index_queries(self):
114         controllers = ['tcp:127.0.0.1:6633']
115         self.br.set_controller(controllers)
116         cmd = self.br.ovsdb.db_set('Controller', self.br.br_name,
117                                    ('connection_mode', 'out-of-band'))
118         cmd.execute(check_error=True)
119         self.assertEqual('out-of-band',
120                          self.br.db_get_val('Controller', self.br.br_name,
121                                             'connection_mode'))
122
123     def test_set_fail_mode_secure(self):
124         self.br.set_secure_mode()
125         self._assert_br_fail_mode(ovs_lib.FAILMODE_SECURE)
126
127     def test_set_fail_mode_standalone(self):
128         self.br.set_standalone_mode()
129         self._assert_br_fail_mode(ovs_lib.FAILMODE_STANDALONE)
130
131     def _assert_br_fail_mode(self, fail_mode):
132         self.assertEqual(
133             self.br.db_get_val('Bridge', self.br.br_name, 'fail_mode'),
134             fail_mode)
135
136     def test_set_protocols(self):
137         self.br.set_protocols('OpenFlow10')
138         self.assertEqual(
139             self.br.db_get_val('Bridge', self.br.br_name, 'protocols'),
140             "OpenFlow10")
141
142     def test_get_datapath_id(self):
143         brdev = ip_lib.IPDevice(self.br.br_name)
144         dpid = brdev.link.attributes['link/ether'].replace(':', '')
145         self.br.set_db_attribute('Bridge',
146                                  self.br.br_name, 'datapath_id', dpid)
147         self.assertIn(dpid, self.br.get_datapath_id())
148
149     def test_add_tunnel_port(self):
150         attrs = {
151             'remote_ip': '192.0.2.1',  # RFC 5737 TEST-NET-1
152             'local_ip': '198.51.100.1',  # RFC 5737 TEST-NET-2
153         }
154         port_name = tests_base.get_rand_device_name(net_helpers.PORT_PREFIX)
155         self.br.add_tunnel_port(port_name, attrs['remote_ip'],
156                                 attrs['local_ip'])
157         self.assertEqual(self.ovs.db_get_val('Interface', port_name, 'type'),
158                          'gre')
159         options = self.ovs.db_get_val('Interface', port_name, 'options')
160         for attr, val in attrs.items():
161             self.assertEqual(val, options[attr])
162
163     def test_add_patch_port(self):
164         local = tests_base.get_rand_device_name(net_helpers.PORT_PREFIX)
165         peer = 'remotepeer'
166         self.br.add_patch_port(local, peer)
167         self.assertEqual(self.ovs.db_get_val('Interface', local, 'type'),
168                          'patch')
169         options = self.ovs.db_get_val('Interface', local, 'options')
170         self.assertEqual(peer, options['peer'])
171
172     def test_get_port_name_list(self):
173         # Note that ovs-vsctl's list-ports does not include the port created
174         # with the same name as the bridge
175         ports = {self.create_ovs_port()[0] for i in range(5)}
176         self.assertSetEqual(ports, set(self.br.get_port_name_list()))
177
178     def test_get_iface_name_list(self):
179         ifaces = {self.create_ovs_port()[0] for i in range(5)}
180         self.assertSetEqual(ifaces, set(self.br.get_iface_name_list()))
181
182     def test_get_port_stats(self):
183         # Nothing seems to use this function?
184         (port_name, ofport) = self.create_ovs_port()
185         stats = set(self.br.get_port_stats(port_name).keys())
186         self.assertTrue(set(['rx_packets', 'tx_packets']).issubset(stats))
187
188     def test_get_vif_ports(self):
189         for i in range(2):
190             self.create_ovs_port()
191         vif_ports = [self.create_ovs_vif_port() for i in range(3)]
192         ports = self.br.get_vif_ports()
193         self.assertEqual(3, len(ports))
194         self.assertTrue(all([isinstance(x, ovs_lib.VifPort) for x in ports]))
195         self.assertEqual(sorted([x.port_name for x in vif_ports]),
196                          sorted([x.port_name for x in ports]))
197
198     def test_get_vif_ports_with_bond(self):
199         for i in range(2):
200             self.create_ovs_port()
201         vif_ports = [self.create_ovs_vif_port() for i in range(3)]
202         # bond ports don't have records in the Interface table but they do in
203         # the Port table
204         orig = self.br.get_port_name_list
205         new_port_name_list = lambda: orig() + ['bondport']
206         mock.patch.object(self.br, 'get_port_name_list',
207                           new=new_port_name_list).start()
208         ports = self.br.get_vif_ports()
209         self.assertEqual(3, len(ports))
210         self.assertTrue(all([isinstance(x, ovs_lib.VifPort) for x in ports]))
211         self.assertEqual(sorted([x.port_name for x in vif_ports]),
212                          sorted([x.port_name for x in ports]))
213
214     def test_get_vif_port_set(self):
215         for i in range(2):
216             self.create_ovs_port()
217         vif_ports = [self.create_ovs_vif_port() for i in range(2)]
218         ports = self.br.get_vif_port_set()
219         expected = set([x.vif_id for x in vif_ports])
220         self.assertEqual(expected, ports)
221
222     def test_get_vif_port_set_with_missing_port(self):
223         self.create_ovs_port()
224         vif_ports = [self.create_ovs_vif_port()]
225
226         # return an extra port to make sure the db list ignores it
227         orig = self.br.get_port_name_list
228         new_port_name_list = lambda: orig() + ['anotherport']
229         mock.patch.object(self.br, 'get_port_name_list',
230                           new=new_port_name_list).start()
231         ports = self.br.get_vif_port_set()
232         expected = set([vif_ports[0].vif_id])
233         self.assertEqual(expected, ports)
234
235     def test_get_vif_port_set_on_empty_bridge_returns_empty_set(self):
236         # Create a port on self.br
237         self.create_ovs_vif_port()
238
239         # Create another, empty bridge
240         br_2 = self.useFixture(net_helpers.OVSBridgeFixture()).bridge
241
242         # Assert that get_vif_port_set on an empty bridge returns an empty set,
243         # and does not return the other bridge's ports.
244         self.assertEqual(set(), br_2.get_vif_port_set())
245
246     def test_get_ports_attributes(self):
247         port_names = [self.create_ovs_port()[0], self.create_ovs_port()[0]]
248         db_ports = self.br.get_ports_attributes('Interface', columns=['name'])
249         db_ports_names = [p['name'] for p in db_ports]
250         self.assertEqual(sorted(port_names), sorted(db_ports_names))
251
252     def test_get_port_tag_dict(self):
253         # Simple case tested in port test_set_get_clear_db_val
254         pass
255
256     def test_get_vif_port_by_id(self):
257         for i in range(2):
258             self.create_ovs_port()
259         vif_ports = [self.create_ovs_vif_port() for i in range(3)]
260         for vif in vif_ports:
261             self.assertEqual(self.br.get_vif_port_by_id(vif.vif_id).vif_id,
262                              vif.vif_id)
263
264     def test_get_vifs_by_ids(self):
265         for i in range(2):
266             self.create_ovs_port()
267         vif_ports = [self.create_ovs_vif_port() for i in range(3)]
268         by_id = self.br.get_vifs_by_ids([v.vif_id for v in vif_ports])
269         # convert to str for comparison of VifPorts
270         by_id = {vid: str(vport) for vid, vport in by_id.items()}
271         self.assertEqual({v.vif_id: str(v) for v in vif_ports}, by_id)
272
273     def test_delete_ports(self):
274         # TODO(twilson) I intensely dislike the current delete_ports function
275         # as the default behavior is really delete_vif_ports(), then it acts
276         # more like a delete_ports() seems like it should if all_ports=True is
277         # passed
278         # Create 2 non-vif ports and 2 vif ports
279         nonvifs = {self.create_ovs_port()[0] for i in range(2)}
280         vifs = {self.create_ovs_vif_port().port_name for i in range(2)}
281         self.assertSetEqual(nonvifs.union(vifs),
282                             set(self.br.get_port_name_list()))
283         self.br.delete_ports()
284         self.assertSetEqual(nonvifs, set(self.br.get_port_name_list()))
285         self.br.delete_ports(all_ports=True)
286         self.assertEqual(len(self.br.get_port_name_list()), 0)
287
288     def test_set_controller_connection_mode(self):
289         controllers = ['tcp:192.0.2.0:6633']
290         self._set_controllers_connection_mode(controllers)
291
292     def test_set_multi_controllers_connection_mode(self):
293         controllers = ['tcp:192.0.2.0:6633', 'tcp:192.0.2.1:55']
294         self._set_controllers_connection_mode(controllers)
295
296     def _set_controllers_connection_mode(self, controllers):
297         self.br.set_controller(controllers)
298         self.assertEqual(sorted(controllers), sorted(self.br.get_controller()))
299         self.br.set_controllers_connection_mode('out-of-band')
300         self._assert_controllers_connection_mode('out-of-band')
301         self.br.del_controller()
302         self.assertEqual([], self.br.get_controller())
303
304     def _assert_controllers_connection_mode(self, connection_mode):
305         controllers = self.br.db_get_val('Bridge', self.br.br_name,
306                                          'controller')
307         controllers = [controllers] if isinstance(
308             controllers, uuid.UUID) else controllers
309         for controller in controllers:
310             self.assertEqual(connection_mode,
311                              self.br.db_get_val('Controller',
312                                                 controller,
313                                                 'connection_mode'))
314
315     def test_egress_bw_limit(self):
316         port_name, _ = self.create_ovs_port()
317         self.br.create_egress_bw_limit_for_port(port_name, 700, 70)
318         max_rate, burst = self.br.get_egress_bw_limit_for_port(port_name)
319         self.assertEqual(700, max_rate)
320         self.assertEqual(70, burst)
321         self.br.delete_egress_bw_limit_for_port(port_name)
322         max_rate, burst = self.br.get_egress_bw_limit_for_port(port_name)
323         self.assertIsNone(max_rate)
324         self.assertIsNone(burst)
325
326
327 class OVSLibTestCase(base.BaseOVSLinuxTestCase):
328
329     def setUp(self):
330         super(OVSLibTestCase, self).setUp()
331         self.ovs = ovs_lib.BaseOVS()
332
333     def test_bridge_lifecycle_baseovs(self):
334         name = base.get_rand_name(prefix=net_helpers.BR_PREFIX)
335         self.addCleanup(self.ovs.delete_bridge, name)
336         br = self.ovs.add_bridge(name)
337         self.assertEqual(br.br_name, name)
338         self.assertTrue(self.ovs.bridge_exists(name))
339         self.ovs.delete_bridge(name)
340         self.assertFalse(self.ovs.bridge_exists(name))
341
342     def test_get_bridges(self):
343         bridges = {
344             self.useFixture(net_helpers.OVSBridgeFixture()).bridge.br_name
345             for i in range(5)}
346         self.assertTrue(set(self.ovs.get_bridges()).issuperset(bridges))
347
348     def test_bridge_lifecycle_ovsbridge(self):
349         name = base.get_rand_name(prefix=net_helpers.BR_PREFIX)
350         br = ovs_lib.OVSBridge(name)
351         self.assertEqual(br.br_name, name)
352         # Make sure that instantiating an OVSBridge does not actually create
353         self.assertFalse(self.ovs.bridge_exists(name))
354         self.addCleanup(self.ovs.delete_bridge, name)
355         br.create()
356         self.assertTrue(self.ovs.bridge_exists(name))
357         br.destroy()
358         self.assertFalse(self.ovs.bridge_exists(name))