1# Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
2#
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
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
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
12# implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16from distutils.spawn import find_executable
17import logging
18import subprocess
19import unittest
20
21from nose.tools import eq_
22from nose.tools import ok_
23
24from ryu.lib.hub import sleep
25from ryu.lib.ovs import vsctl
26
27try:
28    import mock  # Python 2
29except ImportError:
30    from unittest import mock  # Python 3
31
32
33LOG = logging.getLogger(__name__)
34
35DOCKER_IMAGE_MININET = 'osrg/ryu-book'
36
37OVSDB_MANAGER_ADDR = 'ptcp:6640'
38OVSDB_SWITCH_ADDR = 'tcp:%s:6640'
39
40
41def setUpModule():
42    if not find_executable('docker'):
43        raise unittest.SkipTest(
44            'Docker is not available. Test in %s will be skipped.' % __name__)
45
46
47class TestUtils(unittest.TestCase):
48    """
49    Test cases for utilities defined in module.
50    """
51
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'))
55
56    def test_valid_ovsdb_addr_with_ipv4(self):
57        ok_(vsctl.valid_ovsdb_addr('tcp:127.0.0.1:6640'))
58
59    def test_valid_ovsdb_addr_with_ipv6(self):
60        ok_(vsctl.valid_ovsdb_addr('ssl:[::1]:6640'))
61
62    def test_valid_ovsdb_addr_with_invalid_type(self):
63        eq_(vsctl.valid_ovsdb_addr('invalid:127.0.0.1:6640'), False)
64
65
66def _run(command):
67    popen = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
68    popen.wait()
69    result = popen.stdout.read().decode('utf-8')
70
71    if result:
72        return [str(r.strip('\r')) for r in result.split('\n')]
73    else:
74        return []
75
76
77class TestVSCtl(unittest.TestCase):
78    """
79    Test cases for ryu.lib.ovs.vsctl.VSCtl
80    """
81    container_mn = None  # Container ID of Mininet
82    container_mn_ip = None  # IP of Mininet container
83
84    vsctl = None  # instance of vsctl.VSCtl
85
86    @classmethod
87    def _docker_exec(cls, container, command):
88        return _run('docker exec -t %s %s' % (container, command))
89
90    @classmethod
91    def _docker_exec_mn(cls, command):
92        return cls._docker_exec(cls.container_mn, command)
93
94    @classmethod
95    def _docker_run(cls, image):
96        return _run('docker run --privileged -t -d %s' % image)[0]
97
98    @classmethod
99    def _docker_stop(cls, container):
100        return _run('docker stop %s' % container)[0]
101
102    @classmethod
103    def _docker_rm(cls, container):
104        return _run('docker rm %s' % container)[0]
105
106    @classmethod
107    def _docker_inspect_ip_addr(cls, container):
108        return _run(
109            'docker inspect --format="{{.NetworkSettings.IPAddress}}" %s' %
110            container)[0].strip('"')
111
112    @classmethod
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)
116
117        # Note: Wait for loading the OVS kernel module.
118        # If the OVS kernel module is loaded at first time, it might take
119        # a few seconds.
120        sleep(5)
121
122        cls._docker_exec_mn(
123            'ovs-vsctl set-manager %s' % OVSDB_MANAGER_ADDR)
124
125    @classmethod
126    def _set_up_vsctl(cls):
127        cls.vsctl = vsctl.VSCtl(OVSDB_SWITCH_ADDR % cls.container_mn_ip)
128
129    @classmethod
130    def setUpClass(cls):
131        cls._set_up_mn_container()
132        cls._set_up_vsctl()
133
134    @classmethod
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)
139
140    @classmethod
141    def tearDownClass(cls):
142        cls._tear_down_mn_container()
143
144    def setUp(self):
145        pass
146
147    def tearDown(self):
148        pass
149
150    def _run_commands(self, commands):
151        self.vsctl.run_command(commands, timeout_sec=1)
152
153    # 00: Open vSwitch commands
154
155    def test_00_01_init(self):
156        command = vsctl.VSCtlCommand('init')
157        self._run_commands([command])
158
159        ok_(command.result is None)
160
161    def test_00_02_show(self):
162        command = vsctl.VSCtlCommand('show')
163        self._run_commands([command])
164
165        ok_(command.result is not None)
166
167    # 01: Bridge commands
168
169    def test_01_01_add_br_bridge(self):
170        bridge = 's1'
171        command = vsctl.VSCtlCommand('add-br', (bridge,))
172        self._run_commands([command])
173
174        result = self._docker_exec_mn('ovs-vsctl list-br')
175        ok_(bridge in result)
176
177    def test_01_02_add_br_parent_vlan(self):
178        bridge = 'sub-s1-100'
179        parent = 's1'
180        vlan = '100'
181        command = vsctl.VSCtlCommand('add-br', (bridge, parent, vlan))
182        self._run_commands([command])
183
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)
191        eq_(vlan, result[0])
192
193    def test_01_03_del_br(self):
194        bridge = 's1'
195        child = 'sub-s1-100'
196
197        command = vsctl.VSCtlCommand('del-br', (bridge,))
198        self._run_commands([command])
199
200        result = self._docker_exec_mn('ovs-vsctl list-br')
201        ok_(bridge not in result)
202        ok_(child not in result)
203
204    def test_01_04_list_br(self):
205        bridge = 's1'
206        child = 'sub-s1-100'
207        vlan = '100'
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))
211
212        command = vsctl.VSCtlCommand('list-br')
213        self._run_commands([command])
214
215        ok_(bridge in command.result)
216        ok_(child in command.result)
217
218    def test_01_05_br_exists(self):
219        bridge = 's1'
220
221        command = vsctl.VSCtlCommand('br-exists', (bridge, ))
222        self._run_commands([command])
223
224        eq_(True, command.result)
225
226    def test_01_06_br_to_vlan(self):
227        bridge = 's1'
228
229        command = vsctl.VSCtlCommand('br-to-vlan', (bridge, ))
230        self._run_commands([command])
231
232        eq_(0, command.result)
233
234    def test_01_06_br_to_vlan_fake_bridge(self):
235        bridge = 'sub-s1-100'
236
237        command = vsctl.VSCtlCommand('br-to-vlan', (bridge, ))
238        self._run_commands([command])
239
240        eq_(100, command.result)
241
242    def test_01_07_br_to_parent(self):
243        bridge = 's1'
244        parent = bridge
245
246        command = vsctl.VSCtlCommand('br-to-parent', (bridge, ))
247        self._run_commands([command])
248
249        # result = <ryu.lib.ovs.vsctl.VSCtlBridge object>
250        eq_(parent, command.result.name)
251
252    def test_01_07_br_to_parent_fake_bridge(self):
253        bridge = 'sub-s1-100'
254        parent = 's1'
255
256        command = vsctl.VSCtlCommand('br-to-parent', (bridge, ))
257        self._run_commands([command])
258
259        # result = <ryu.lib.ovs.vsctl.VSCtlBridge object>
260        eq_(parent, command.result.name)
261
262    def test_01_08_br_set_external_id_add(self):
263        bridge = 's1'
264        key = 'ext_id_key'
265        value = 'ext_id_value'
266
267        command = vsctl.VSCtlCommand(
268            'br-set-external-id', (bridge, key, value))
269        self._run_commands([command])
270
271        result = self._docker_exec_mn(
272            'ovs-vsctl br-get-external-id %s %s' % (bridge, key))
273        eq_(value, result[0])
274
275    def test_01_09_br_get_external_id_value(self):
276        bridge = 's1'
277        key = 'ext_id_key'
278        value = 'ext_id_value'
279
280        command = vsctl.VSCtlCommand(
281            'br-get-external-id', (bridge, key))
282        self._run_commands([command])
283
284        eq_(value, command.result)
285
286    def test_01_10_br_get_external_id_dict(self):
287        bridge = 's1'
288        key = 'ext_id_key'
289        value = 'ext_id_value'
290
291        command = vsctl.VSCtlCommand(
292            'br-get-external-id', (bridge,))
293        self._run_commands([command])
294
295        eq_({key: value}, command.result)
296
297    def test_01_11_br_set_external_id_clear(self):
298        bridge = 's1'
299        key = 'ext_id_key'
300
301        command = vsctl.VSCtlCommand(
302            'br-set-external-id', (bridge, key))
303        self._run_commands([command])
304
305        result = self._docker_exec_mn(
306            'ovs-vsctl br-get-external-id %s %s' % (bridge, key))
307        eq_([], result)
308
309        # Clean up
310        self._docker_exec_mn('mn --clean')
311
312    # 02: Port commands
313
314    def test_02_01_list_ports(self):
315        bridge = 's1'
316        interface_1 = 's1-eth1'
317        interface_2 = 's1-eth2'
318
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())
327
328        command = vsctl.VSCtlCommand('list-ports', (bridge,))
329        self._run_commands([command])
330
331        ok_(interface_1 in command.result)
332        ok_(interface_2 in command.result)
333
334    def test_02_02_add_port(self):
335        bridge = 's1'
336        interface_1 = 's1-eth1'
337        self._docker_exec_mn(
338            'ovs-vsctl del-port %s %s' % (bridge, interface_1))
339
340        command = vsctl.VSCtlCommand('add-port', (bridge, interface_1))
341        self._run_commands([command])
342
343        result = self._docker_exec_mn(
344            'ovs-vsctl port-to-br %s' % interface_1)
345        eq_(bridge, result[0])
346
347    def test_02_03_add_bond(self):
348        bridge = 's1'
349        interface_1 = 's1-eth1'
350        interface_2 = 's1-eth2'
351        port = 's1-bond1'
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)
355
356        command = vsctl.VSCtlCommand(
357            'add-bond', (bridge, port, interface_list))
358        self._run_commands([command])
359
360        result = self._docker_exec_mn(
361            'ovs-vsctl port-to-br %s' % port)
362        eq_(bridge, result[0])
363
364    def test_02_04_del_port(self):
365        bridge = 's1'
366        port = 's1-bond1'
367
368        command = vsctl.VSCtlCommand('del-port', (bridge, port))
369        self._run_commands([command])
370
371        result = self._docker_exec_mn(
372            'ovs-vsctl list-ports %s' % bridge)
373        eq_([], result)
374
375    def test_02_05_port_to_br(self):
376        bridge = 's1'
377        port_1 = 's1-eth1'
378        port_2 = 's1-eth2'
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())
384
385        command = vsctl.VSCtlCommand('port-to-br', (port_1,))
386        self._run_commands([command])
387
388        eq_(bridge, command.result)
389
390        # Clean up
391        self._docker_exec_mn('mn --clean')
392
393    # 03: Interface commands
394
395    def test_03_01_list_ifaces(self):
396        bridge = 's1'
397        interface_1 = 's1-eth1'
398        interface_2 = 's1-eth2'
399
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())
408
409        command = vsctl.VSCtlCommand('list-ifaces', (bridge,))
410        self._run_commands([command])
411
412        ok_(interface_1 in command.result)
413        ok_(interface_2 in command.result)
414
415    def test_03_02_ifaces_to_br(self):
416        bridge = 's1'
417        interface_1 = 's1-eth1'
418
419        command = vsctl.VSCtlCommand('iface-to-br', (interface_1,))
420        self._run_commands([command])
421
422        eq_(bridge, command.result)
423
424        # Clean up
425        self._docker_exec_mn('mn --clean')
426
427    # 04: Controller commands
428
429    def test_04_01_get_controller(self):
430        bridge = 's1'
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())
435
436        command = vsctl.VSCtlCommand('get-controller', (bridge,))
437        self._run_commands([command])
438
439        eq_(1, len(command.result))
440        eq_(controller, command.result[0])
441
442    def test_04_02_del_controller(self):
443        bridge = 's1'
444
445        command = vsctl.VSCtlCommand('del-controller', (bridge,))
446        self._run_commands([command])
447
448        result = self._docker_exec_mn(
449            'ovs-vsctl get-controller %s' % bridge)
450        eq_([], result)
451
452    def test_04_03_set_controller(self):
453        bridge = 's1'
454        controller = 'tcp:127.0.0.1:6653'
455
456        command = vsctl.VSCtlCommand('set-controller', (bridge, controller))
457        self._run_commands([command])
458
459        result = self._docker_exec_mn(
460            'ovs-vsctl get-controller %s' % bridge)
461        eq_(controller, result[0])
462
463    def test_04_04_get_fail_mode(self):
464        bridge = 's1'
465        fai_mode = 'secure'
466        self._docker_exec_mn(
467            'ovs-vsctl set-fail-mode %s %s' % (bridge, fai_mode))
468
469        command = vsctl.VSCtlCommand('get-fail-mode', (bridge,))
470        self._run_commands([command])
471
472        eq_(fai_mode, command.result)
473
474    def test_04_05_del_fail_mode(self):
475        bridge = 's1'
476
477        command = vsctl.VSCtlCommand('del-fail-mode', (bridge,))
478        self._run_commands([command])
479
480        result = self._docker_exec_mn(
481            'ovs-vsctl get-fail-mode %s' % bridge)
482        eq_([], result)
483
484    def test_04_06_set_fail_mode(self):
485        bridge = 's1'
486        fail_mode = 'secure'
487
488        command = vsctl.VSCtlCommand('set-fail-mode', (bridge, fail_mode))
489        self._run_commands([command])
490
491        result = self._docker_exec_mn(
492            'ovs-vsctl get-fail-mode %s' % bridge)
493        eq_(fail_mode, result[0])
494
495        # Clean up
496        self._docker_exec_mn('mn --clean')
497
498    # 05: Manager commands (not implemented yet)
499    # 06: SSL commands (not implemented yet)
500    # 07: Switch commands (not implemented yet)
501
502    # 08: Database commands
503
504    def test_08_01_list(self):
505        table = 'Bridge'
506        bridge = 's1'
507        interface_1 = 's1-eth1'
508        interface_2 = 's1-eth2'
509        fail_mode = 'secure'
510        protocols = 'OpenFlow10,OpenFlow13'
511        datapath_id = '1111111111111111'
512
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())
526
527        command = vsctl.VSCtlCommand('list', (table,))
528        self._run_commands([command])
529
530        eq_(1, len(command.result))
531        # command.result[0] = <ryu.lib.ovs.vsctl.VSCtlBridge object>
532        eq_(bridge, command.result[0].name)
533
534    def test_08_02_find(self):
535        table = 'Bridge'
536        bridge = 's1'
537
538        command = vsctl.VSCtlCommand('find', (table, 'name=%s' % bridge))
539        self._run_commands([command])
540
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)
544
545    def test_08_02_find_complex(self):
546        table = 'Bridge'
547        bridge = 's1'
548        fail_mode = 'secure'
549        protocols = 'OpenFlow10,OpenFlow13'
550        datapath_id = '1111111111111111'
551
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])
557
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)
561
562    def test_08_03_get_01_value(self):
563        table = 'Bridge'
564        bridge = 's1'
565        column = 'fail_mode'
566        value = 'secure'
567
568        command = vsctl.VSCtlCommand('get', (table, bridge, column))
569        self._run_commands([command])
570
571        # command.result[0] is a list of return values
572        eq_(value, command.result[0][0])
573
574    def test_08_03_get_02_set(self):
575        table = 'Bridge'
576        bridge = 's1'
577        column = 'protocols'
578        value = 'OpenFlow10,OpenFlow13'.split(',')
579
580        command = vsctl.VSCtlCommand('get', (table, bridge, column))
581        self._run_commands([command])
582
583        # command.result[0] is a list
584        eq_(value, command.result[0])
585
586    def test_08_03_get_03_map(self):
587        table = 'Bridge'
588        bridge = 's1'
589        column = 'other_config'
590        key = 'datapath-id'
591        datapath_id = '1111111111111111'
592        value = {key: datapath_id}
593
594        command = vsctl.VSCtlCommand('get', (table, bridge, column))
595        self._run_commands([command])
596
597        # command.result[0] is a dict
598        eq_(value, command.result[0])
599
600    def test_08_03_get_04_map_value(self):
601        table = 'Bridge'
602        bridge = 's1'
603        column = 'other_config'
604        key = 'datapath-id'
605        datapath_id = '1111111111111111'
606        value = datapath_id
607
608        command = vsctl.VSCtlCommand(
609            'get', (table, bridge, '%s:%s' % (column, key)))
610        self._run_commands([command])
611
612        # command.result[0] is a dict
613        eq_(value, command.result[0])
614
615    def test_08_04_set_01_value(self):
616        table = 'Bridge'
617        bridge = 's1'
618        column = 'fail_mode'
619        value = 'standalone'
620
621        command = vsctl.VSCtlCommand(
622            'set', (table, bridge, '%s=%s' % (column, value)))
623        self._run_commands([command])
624
625        result = self._docker_exec_mn(
626            'ovs-vsctl get %s %s %s' % (table, bridge, column))
627        eq_(value, result[0])
628
629    def test_08_04_set_02_set(self):
630        table = 'Bridge'
631        bridge = 's1'
632        column = 'protocols'
633        value = 'OpenFlow10,OpenFlow12,OpenFlow13'
634
635        command = vsctl.VSCtlCommand(
636            'set', (table, bridge, '%s=%s' % (column, value)))
637        self._run_commands([command])
638
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])
643
644    def test_08_04_set_03_map(self):
645        table = 'Bridge'
646        bridge = 's1'
647        column = 'other_config'
648        key = 'datapath-id'
649        value = '0000000000000001'
650
651        command = vsctl.VSCtlCommand(
652            'set', (table, bridge, '%s:%s=%s' % (column, key, value)))
653        self._run_commands([command])
654
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])
659
660    def test_08_05_add_01_value(self):
661        table = 'Port'
662        bridge = 's1'
663        column = 'tag'
664        value = '100'
665
666        command = vsctl.VSCtlCommand(
667            'add', (table, bridge, column, value))
668        self._run_commands([command])
669
670        result = self._docker_exec_mn(
671            'ovs-vsctl get %s %s %s' % (table, bridge, column))
672        eq_(value, result[0])
673
674    def test_08_05_add_02_set(self):
675        table = 'Port'
676        bridge = 's1'
677        column = 'trunks'
678        value = '100,200'
679
680        command = vsctl.VSCtlCommand(
681            'add', (table, bridge, column, value))
682        self._run_commands([command])
683
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])
688
689    def test_08_05_add_03_map(self):
690        table = 'Bridge'
691        bridge = 's1'
692        column = 'other_config'
693        key = 'datapath-id'
694        value = '0000000000000011'
695
696        command = vsctl.VSCtlCommand(
697            'add', (table, bridge, column, '%s=%s' % (key, value)))
698        self._run_commands([command])
699
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])
704
705    def test_08_06_remove_01_value(self):
706        table = 'Port'
707        bridge = 's1'
708        column = 'tag'
709        value = '100'
710        self._docker_exec_mn(
711            'ovs-vsctl set %s %s %s=%s' % (table, bridge, column, value))
712
713        command = vsctl.VSCtlCommand(
714            'remove', (table, bridge, column, value))
715        self._run_commands([command])
716
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])
721
722    def test_08_06_remove_02_set(self):
723        table = 'Port'
724        bridge = 's1'
725        column = 'trunks'
726        init_value = '100,200,300'
727        value = '100,200'
728        self._docker_exec_mn(
729            'ovs-vsctl set %s %s %s=%s' % (table, bridge, column, init_value))
730
731        command = vsctl.VSCtlCommand(
732            'remove', (table, bridge, column, value))
733        self._run_commands([command])
734
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])
739
740    def test_08_06_remove_03_map(self):
741        table = 'Port'
742        bridge = 's1'
743        column = 'other_config'
744        key = 'priority-tag'
745        value = 'true'
746        self._docker_exec_mn(
747            'ovs-vsctl set %s %s %s:%s=%s' %
748            (table, bridge, column, key, value))
749
750        command = vsctl.VSCtlCommand(
751            'remove', (table, bridge, column, '%s=%s' % (key, value)))
752        self._run_commands([command])
753
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])
758
759    def test_08_07_clear_01_value(self):
760        table = 'Port'
761        bridge = 's1'
762        column = 'tag'
763        value = '100'
764        self._docker_exec_mn(
765            'ovs-vsctl set %s %s %s=%s' % (table, bridge, column, value))
766
767        command = vsctl.VSCtlCommand(
768            'clear', (table, bridge, column))
769        self._run_commands([command])
770
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])
775
776    def test_08_07_clear_02_set(self):
777        table = 'Port'
778        bridge = 's1'
779        column = 'trunks'
780        value = '100,200'
781        self._docker_exec_mn(
782            'ovs-vsctl set %s %s %s=%s' % (table, bridge, column, value))
783
784        command = vsctl.VSCtlCommand(
785            'clear', (table, bridge, column))
786        self._run_commands([command])
787
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])
792
793    def test_08_07_clear_03_map(self):
794        table = 'Port'
795        bridge = 's1'
796        column = 'other_config'
797        key = 'priority-tag'
798        value = 'true'
799        self._docker_exec_mn(
800            'ovs-vsctl set %s %s %s:%s=%s' %
801            (table, bridge, column, key, value))
802
803        command = vsctl.VSCtlCommand(
804            'clear', (table, bridge, column, '%s=%s' % (key, value)))
805        self._run_commands([command])
806
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])
811
812        # Clean up
813        self._docker_exec_mn('mn --clean')
814