1 # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 from distutils.spawn import find_executable
21 from nose.tools import eq_
22 from nose.tools import ok_
24 from ryu.lib.hub import sleep
25 from ryu.lib.ovs import vsctl
28 import mock # Python 2
30 from unittest import mock # Python 3
33 LOG = logging.getLogger(__name__)
35 DOCKER_IMAGE_MININET = 'osrg/ryu-book'
37 OVSDB_MANAGER_ADDR = 'ptcp:6640'
38 OVSDB_SWITCH_ADDR = 'tcp:%s:6640'
42 if not find_executable('docker'):
43 raise unittest.SkipTest(
44 'Docker is not available. Test in %s will be skipped.' % __name__)
47 class TestUtils(unittest.TestCase):
49 Test cases for utilities defined in module.
52 @mock.patch('os.path.isfile', mock.MagicMock(return_value=True))
53 def test_valid_ovsdb_addr_with_unix(self):
54 ok_(vsctl.valid_ovsdb_addr('unix:/var/run/openvswitch/db.sock'))
56 def test_valid_ovsdb_addr_with_ipv4(self):
57 ok_(vsctl.valid_ovsdb_addr('tcp:127.0.0.1:6640'))
59 def test_valid_ovsdb_addr_with_ipv6(self):
60 ok_(vsctl.valid_ovsdb_addr('ssl:[::1]:6640'))
62 def test_valid_ovsdb_addr_with_invalid_type(self):
63 eq_(vsctl.valid_ovsdb_addr('invalid:127.0.0.1:6640'), False)
67 popen = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
69 result = popen.stdout.read().decode('utf-8')
72 return [str(r.strip('\r')) for r in result.split('\n')]
77 class TestVSCtl(unittest.TestCase):
79 Test cases for ryu.lib.ovs.vsctl.VSCtl
81 container_mn = None # Container ID of Mininet
82 container_mn_ip = None # IP of Mininet container
84 vsctl = None # instance of vsctl.VSCtl
87 def _docker_exec(cls, container, command):
88 return _run('docker exec -t %s %s' % (container, command))
91 def _docker_exec_mn(cls, command):
92 return cls._docker_exec(cls.container_mn, command)
95 def _docker_run(cls, image):
96 return _run('docker run --privileged -t -d %s' % image)[0]
99 def _docker_stop(cls, container):
100 return _run('docker stop %s' % container)[0]
103 def _docker_rm(cls, container):
104 return _run('docker rm %s' % container)[0]
107 def _docker_inspect_ip_addr(cls, container):
109 'docker inspect --format="{{.NetworkSettings.IPAddress}}" %s' %
110 container)[0].strip('"')
113 def _set_up_mn_container(cls):
114 cls.container_mn = cls._docker_run(DOCKER_IMAGE_MININET)
115 cls.container_mn_ip = cls._docker_inspect_ip_addr(cls.container_mn)
117 # Note: Wait for loading the OVS kernel module.
118 # If the OVS kernel module is loaded at first time, it might take
123 'ovs-vsctl set-manager %s' % OVSDB_MANAGER_ADDR)
126 def _set_up_vsctl(cls):
127 cls.vsctl = vsctl.VSCtl(OVSDB_SWITCH_ADDR % cls.container_mn_ip)
131 cls._set_up_mn_container()
135 def _tear_down_mn_container(cls):
136 cls._docker_exec_mn('mn --clean')
137 cls._docker_stop(cls.container_mn)
138 cls._docker_rm(cls.container_mn)
141 def tearDownClass(cls):
142 cls._tear_down_mn_container()
150 def _run_commands(self, commands):
151 self.vsctl.run_command(commands, timeout_sec=1)
153 # 00: Open vSwitch commands
155 def test_00_01_init(self):
156 command = vsctl.VSCtlCommand('init')
157 self._run_commands([command])
159 ok_(command.result is None)
161 def test_00_02_show(self):
162 command = vsctl.VSCtlCommand('show')
163 self._run_commands([command])
165 ok_(command.result is not None)
167 # 01: Bridge commands
169 def test_01_01_add_br_bridge(self):
171 command = vsctl.VSCtlCommand('add-br', (bridge,))
172 self._run_commands([command])
174 result = self._docker_exec_mn('ovs-vsctl list-br')
175 ok_(bridge in result)
177 def test_01_02_add_br_parent_vlan(self):
178 bridge = 'sub-s1-100'
181 command = vsctl.VSCtlCommand('add-br', (bridge, parent, vlan))
182 self._run_commands([command])
184 result = self._docker_exec_mn('ovs-vsctl list-br')
185 ok_(bridge in result)
186 result = self._docker_exec_mn(
187 'ovs-vsctl br-to-parent %s' % bridge)
188 eq_(parent, result[0])
189 result = self._docker_exec_mn(
190 'ovs-vsctl br-to-vlan %s' % bridge)
193 def test_01_03_del_br(self):
197 command = vsctl.VSCtlCommand('del-br', (bridge,))
198 self._run_commands([command])
200 result = self._docker_exec_mn('ovs-vsctl list-br')
201 ok_(bridge not in result)
202 ok_(child not in result)
204 def test_01_04_list_br(self):
208 self._docker_exec_mn('ovs-vsctl add-br %s' % bridge)
209 self._docker_exec_mn(
210 'ovs-vsctl add-br %s %s %s' % (child, bridge, vlan))
212 command = vsctl.VSCtlCommand('list-br')
213 self._run_commands([command])
215 ok_(bridge in command.result)
216 ok_(child in command.result)
218 def test_01_05_br_exists(self):
221 command = vsctl.VSCtlCommand('br-exists', (bridge, ))
222 self._run_commands([command])
224 eq_(True, command.result)
226 def test_01_06_br_to_vlan(self):
229 command = vsctl.VSCtlCommand('br-to-vlan', (bridge, ))
230 self._run_commands([command])
232 eq_(0, command.result)
234 def test_01_06_br_to_vlan_fake_bridge(self):
235 bridge = 'sub-s1-100'
237 command = vsctl.VSCtlCommand('br-to-vlan', (bridge, ))
238 self._run_commands([command])
240 eq_(100, command.result)
242 def test_01_07_br_to_parent(self):
246 command = vsctl.VSCtlCommand('br-to-parent', (bridge, ))
247 self._run_commands([command])
249 # result = <ryu.lib.ovs.vsctl.VSCtlBridge object>
250 eq_(parent, command.result.name)
252 def test_01_07_br_to_parent_fake_bridge(self):
253 bridge = 'sub-s1-100'
256 command = vsctl.VSCtlCommand('br-to-parent', (bridge, ))
257 self._run_commands([command])
259 # result = <ryu.lib.ovs.vsctl.VSCtlBridge object>
260 eq_(parent, command.result.name)
262 def test_01_08_br_set_external_id_add(self):
265 value = 'ext_id_value'
267 command = vsctl.VSCtlCommand(
268 'br-set-external-id', (bridge, key, value))
269 self._run_commands([command])
271 result = self._docker_exec_mn(
272 'ovs-vsctl br-get-external-id %s %s' % (bridge, key))
273 eq_(value, result[0])
275 def test_01_09_br_get_external_id_value(self):
278 value = 'ext_id_value'
280 command = vsctl.VSCtlCommand(
281 'br-get-external-id', (bridge, key))
282 self._run_commands([command])
284 eq_(value, command.result)
286 def test_01_10_br_get_external_id_dict(self):
289 value = 'ext_id_value'
291 command = vsctl.VSCtlCommand(
292 'br-get-external-id', (bridge,))
293 self._run_commands([command])
295 eq_({key: value}, command.result)
297 def test_01_11_br_set_external_id_clear(self):
301 command = vsctl.VSCtlCommand(
302 'br-set-external-id', (bridge, key))
303 self._run_commands([command])
305 result = self._docker_exec_mn(
306 'ovs-vsctl br-get-external-id %s %s' % (bridge, key))
310 self._docker_exec_mn('mn --clean')
314 def test_02_01_list_ports(self):
316 interface_1 = 's1-eth1'
317 interface_2 = 's1-eth2'
319 self._docker_exec_mn(
320 'ip link add %s type dummy' % interface_1)
321 self._docker_exec_mn(
322 'ip link add %s type dummy' % interface_2)
323 self._docker_exec_mn(
324 'ovs-vsctl add-br %(bridge)s'
325 ' -- add-port %(bridge)s %(interface_1)s'
326 ' -- add-port %(bridge)s %(interface_2)s' % locals())
328 command = vsctl.VSCtlCommand('list-ports', (bridge,))
329 self._run_commands([command])
331 ok_(interface_1 in command.result)
332 ok_(interface_2 in command.result)
334 def test_02_02_add_port(self):
336 interface_1 = 's1-eth1'
337 self._docker_exec_mn(
338 'ovs-vsctl del-port %s %s' % (bridge, interface_1))
340 command = vsctl.VSCtlCommand('add-port', (bridge, interface_1))
341 self._run_commands([command])
343 result = self._docker_exec_mn(
344 'ovs-vsctl port-to-br %s' % interface_1)
345 eq_(bridge, result[0])
347 def test_02_03_add_bond(self):
349 interface_1 = 's1-eth1'
350 interface_2 = 's1-eth2'
352 interface_list = [interface_1, interface_2]
353 self._docker_exec_mn('ovs-vsctl del-br %s' % bridge)
354 self._docker_exec_mn('ovs-vsctl add-br %s' % bridge)
356 command = vsctl.VSCtlCommand(
357 'add-bond', (bridge, port, interface_list))
358 self._run_commands([command])
360 result = self._docker_exec_mn(
361 'ovs-vsctl port-to-br %s' % port)
362 eq_(bridge, result[0])
364 def test_02_04_del_port(self):
368 command = vsctl.VSCtlCommand('del-port', (bridge, port))
369 self._run_commands([command])
371 result = self._docker_exec_mn(
372 'ovs-vsctl list-ports %s' % bridge)
375 def test_02_05_port_to_br(self):
379 self._docker_exec_mn('ovs-vsctl del-br %s' % bridge)
380 self._docker_exec_mn(
381 'ovs-vsctl add-br %(bridge)s'
382 ' -- add-port %(bridge)s %(port_1)s'
383 ' -- add-port %(bridge)s %(port_2)s' % locals())
385 command = vsctl.VSCtlCommand('port-to-br', (port_1,))
386 self._run_commands([command])
388 eq_(bridge, command.result)
391 self._docker_exec_mn('mn --clean')
393 # 03: Interface commands
395 def test_03_01_list_ifaces(self):
397 interface_1 = 's1-eth1'
398 interface_2 = 's1-eth2'
400 self._docker_exec_mn(
401 'ip link add %s type dummy' % interface_1)
402 self._docker_exec_mn(
403 'ip link add %s type dummy' % interface_2)
404 self._docker_exec_mn(
405 'ovs-vsctl add-br %(bridge)s'
406 ' -- add-port %(bridge)s %(interface_1)s'
407 ' -- add-port %(bridge)s %(interface_2)s' % locals())
409 command = vsctl.VSCtlCommand('list-ifaces', (bridge,))
410 self._run_commands([command])
412 ok_(interface_1 in command.result)
413 ok_(interface_2 in command.result)
415 def test_03_02_ifaces_to_br(self):
417 interface_1 = 's1-eth1'
419 command = vsctl.VSCtlCommand('iface-to-br', (interface_1,))
420 self._run_commands([command])
422 eq_(bridge, command.result)
425 self._docker_exec_mn('mn --clean')
427 # 04: Controller commands
429 def test_04_01_get_controller(self):
431 controller = 'tcp:127.0.0.1:6653'
432 self._docker_exec_mn(
433 'ovs-vsctl add-br %(bridge)s'
434 ' -- set-controller %(bridge)s %(controller)s' % locals())
436 command = vsctl.VSCtlCommand('get-controller', (bridge,))
437 self._run_commands([command])
439 eq_(1, len(command.result))
440 eq_(controller, command.result[0])
442 def test_04_02_del_controller(self):
445 command = vsctl.VSCtlCommand('del-controller', (bridge,))
446 self._run_commands([command])
448 result = self._docker_exec_mn(
449 'ovs-vsctl get-controller %s' % bridge)
452 def test_04_03_set_controller(self):
454 controller = 'tcp:127.0.0.1:6653'
456 command = vsctl.VSCtlCommand('set-controller', (bridge, controller))
457 self._run_commands([command])
459 result = self._docker_exec_mn(
460 'ovs-vsctl get-controller %s' % bridge)
461 eq_(controller, result[0])
463 def test_04_04_get_fail_mode(self):
466 self._docker_exec_mn(
467 'ovs-vsctl set-fail-mode %s %s' % (bridge, fai_mode))
469 command = vsctl.VSCtlCommand('get-fail-mode', (bridge,))
470 self._run_commands([command])
472 eq_(fai_mode, command.result)
474 def test_04_05_del_fail_mode(self):
477 command = vsctl.VSCtlCommand('del-fail-mode', (bridge,))
478 self._run_commands([command])
480 result = self._docker_exec_mn(
481 'ovs-vsctl get-fail-mode %s' % bridge)
484 def test_04_06_set_fail_mode(self):
488 command = vsctl.VSCtlCommand('set-fail-mode', (bridge, fail_mode))
489 self._run_commands([command])
491 result = self._docker_exec_mn(
492 'ovs-vsctl get-fail-mode %s' % bridge)
493 eq_(fail_mode, result[0])
496 self._docker_exec_mn('mn --clean')
498 # 05: Manager commands (not implemented yet)
499 # 06: SSL commands (not implemented yet)
500 # 07: Switch commands (not implemented yet)
502 # 08: Database commands
504 def test_08_01_list(self):
507 interface_1 = 's1-eth1'
508 interface_2 = 's1-eth2'
510 protocols = 'OpenFlow10,OpenFlow13'
511 datapath_id = '1111111111111111'
513 self._docker_exec_mn(
514 'ip link add %s type dummy' % interface_1)
515 self._docker_exec_mn(
516 'ip link add %s type dummy' % interface_2)
517 self._docker_exec_mn(
518 'ovs-vsctl add-br %(bridge)s'
519 ' -- add-port %(bridge)s %(interface_1)s'
520 ' -- add-port %(bridge)s %(interface_2)s' % locals())
521 self._docker_exec_mn(
522 'ovs-vsctl set %(table)s %(bridge)s '
523 'fail_mode=%(fail_mode)s '
524 'protocols=%(protocols)s '
525 'other_config:datapath-id=%(datapath_id)s' % locals())
527 command = vsctl.VSCtlCommand('list', (table,))
528 self._run_commands([command])
530 eq_(1, len(command.result))
531 # command.result[0] = <ryu.lib.ovs.vsctl.VSCtlBridge object>
532 eq_(bridge, command.result[0].name)
534 def test_08_02_find(self):
538 command = vsctl.VSCtlCommand('find', (table, 'name=%s' % bridge))
539 self._run_commands([command])
541 eq_(1, len(command.result))
542 # command.result[0] = <ovs.db.idl.Row object object> for Bridge
543 eq_(bridge, command.result[0].name)
545 def test_08_02_find_complex(self):
549 protocols = 'OpenFlow10,OpenFlow13'
550 datapath_id = '1111111111111111'
552 command = vsctl.VSCtlCommand(
553 'find', (table, 'fail_mode=%s' % fail_mode,
554 'protocols=%s' % protocols,
555 'other_config:datapath-id=%s' % datapath_id))
556 self._run_commands([command])
558 eq_(1, len(command.result))
559 # command.result[0] = <ovs.db.idl.Row object object> for Bridge
560 eq_(bridge, command.result[0].name)
562 def test_08_03_get_01_value(self):
568 command = vsctl.VSCtlCommand('get', (table, bridge, column))
569 self._run_commands([command])
571 # command.result[0] is a list of return values
572 eq_(value, command.result[0][0])
574 def test_08_03_get_02_set(self):
578 value = 'OpenFlow10,OpenFlow13'.split(',')
580 command = vsctl.VSCtlCommand('get', (table, bridge, column))
581 self._run_commands([command])
583 # command.result[0] is a list
584 eq_(value, command.result[0])
586 def test_08_03_get_03_map(self):
589 column = 'other_config'
591 datapath_id = '1111111111111111'
592 value = {key: datapath_id}
594 command = vsctl.VSCtlCommand('get', (table, bridge, column))
595 self._run_commands([command])
597 # command.result[0] is a dict
598 eq_(value, command.result[0])
600 def test_08_03_get_04_map_value(self):
603 column = 'other_config'
605 datapath_id = '1111111111111111'
608 command = vsctl.VSCtlCommand(
609 'get', (table, bridge, '%s:%s' % (column, key)))
610 self._run_commands([command])
612 # command.result[0] is a dict
613 eq_(value, command.result[0])
615 def test_08_04_set_01_value(self):
621 command = vsctl.VSCtlCommand(
622 'set', (table, bridge, '%s=%s' % (column, value)))
623 self._run_commands([command])
625 result = self._docker_exec_mn(
626 'ovs-vsctl get %s %s %s' % (table, bridge, column))
627 eq_(value, result[0])
629 def test_08_04_set_02_set(self):
633 value = 'OpenFlow10,OpenFlow12,OpenFlow13'
635 command = vsctl.VSCtlCommand(
636 'set', (table, bridge, '%s=%s' % (column, value)))
637 self._run_commands([command])
639 result = self._docker_exec_mn(
640 'ovs-vsctl get %s %s %s' % (table, bridge, column))
641 expected_value = '["OpenFlow10", "OpenFlow12", "OpenFlow13"]'
642 eq_(expected_value, result[0])
644 def test_08_04_set_03_map(self):
647 column = 'other_config'
649 value = '0000000000000001'
651 command = vsctl.VSCtlCommand(
652 'set', (table, bridge, '%s:%s=%s' % (column, key, value)))
653 self._run_commands([command])
655 result = self._docker_exec_mn(
656 'ovs-vsctl get %s %s %s:%s' % (table, bridge, column, key))
657 expected_value = '"0000000000000001"'
658 eq_(expected_value, result[0])
660 def test_08_05_add_01_value(self):
666 command = vsctl.VSCtlCommand(
667 'add', (table, bridge, column, value))
668 self._run_commands([command])
670 result = self._docker_exec_mn(
671 'ovs-vsctl get %s %s %s' % (table, bridge, column))
672 eq_(value, result[0])
674 def test_08_05_add_02_set(self):
680 command = vsctl.VSCtlCommand(
681 'add', (table, bridge, column, value))
682 self._run_commands([command])
684 result = self._docker_exec_mn(
685 'ovs-vsctl get %s %s %s' % (table, bridge, column))
686 expected_value = '[100, 200]'
687 eq_(expected_value, result[0])
689 def test_08_05_add_03_map(self):
692 column = 'other_config'
694 value = '0000000000000011'
696 command = vsctl.VSCtlCommand(
697 'add', (table, bridge, column, '%s=%s' % (key, value)))
698 self._run_commands([command])
700 result = self._docker_exec_mn(
701 'ovs-vsctl get %s %s %s:%s' % (table, bridge, column, key))
702 expected_value = '"0000000000000011"'
703 eq_(expected_value, result[0])
705 def test_08_06_remove_01_value(self):
710 self._docker_exec_mn(
711 'ovs-vsctl set %s %s %s=%s' % (table, bridge, column, value))
713 command = vsctl.VSCtlCommand(
714 'remove', (table, bridge, column, value))
715 self._run_commands([command])
717 result = self._docker_exec_mn(
718 'ovs-vsctl get %s %s %s' % (table, bridge, column))
719 expected_value = '[]'
720 eq_(expected_value, result[0])
722 def test_08_06_remove_02_set(self):
726 init_value = '100,200,300'
728 self._docker_exec_mn(
729 'ovs-vsctl set %s %s %s=%s' % (table, bridge, column, init_value))
731 command = vsctl.VSCtlCommand(
732 'remove', (table, bridge, column, value))
733 self._run_commands([command])
735 result = self._docker_exec_mn(
736 'ovs-vsctl get %s %s %s' % (table, bridge, column))
737 expected_value = '[300]'
738 eq_(expected_value, result[0])
740 def test_08_06_remove_03_map(self):
743 column = 'other_config'
746 self._docker_exec_mn(
747 'ovs-vsctl set %s %s %s:%s=%s' %
748 (table, bridge, column, key, value))
750 command = vsctl.VSCtlCommand(
751 'remove', (table, bridge, column, '%s=%s' % (key, value)))
752 self._run_commands([command])
754 result = self._docker_exec_mn(
755 'ovs-vsctl get %s %s %s' % (table, bridge, column))
756 expected_value = '{}'
757 eq_(expected_value, result[0])
759 def test_08_07_clear_01_value(self):
764 self._docker_exec_mn(
765 'ovs-vsctl set %s %s %s=%s' % (table, bridge, column, value))
767 command = vsctl.VSCtlCommand(
768 'clear', (table, bridge, column))
769 self._run_commands([command])
771 result = self._docker_exec_mn(
772 'ovs-vsctl get %s %s %s' % (table, bridge, column))
773 expected_value = '[]'
774 eq_(expected_value, result[0])
776 def test_08_07_clear_02_set(self):
781 self._docker_exec_mn(
782 'ovs-vsctl set %s %s %s=%s' % (table, bridge, column, value))
784 command = vsctl.VSCtlCommand(
785 'clear', (table, bridge, column))
786 self._run_commands([command])
788 result = self._docker_exec_mn(
789 'ovs-vsctl get %s %s %s' % (table, bridge, column))
790 expected_value = '[]'
791 eq_(expected_value, result[0])
793 def test_08_07_clear_03_map(self):
796 column = 'other_config'
799 self._docker_exec_mn(
800 'ovs-vsctl set %s %s %s:%s=%s' %
801 (table, bridge, column, key, value))
803 command = vsctl.VSCtlCommand(
804 'clear', (table, bridge, column, '%s=%s' % (key, value)))
805 self._run_commands([command])
807 result = self._docker_exec_mn(
808 'ovs-vsctl get %s %s %s' % (table, bridge, column))
809 expected_value = '{}'
810 eq_(expected_value, result[0])
813 self._docker_exec_mn('mn --clean')