1 From edd624ef23d7e6e410aaaf356765c2568e46247d Mon Sep 17 00:00:00 2001
2 From: Maru Newby <marun@redhat.com>
3 Date: Tue, 2 Apr 2013 22:43:37 +0000
4 Subject: [PATCH] Create veth peer in namespace.
6 * Update veth pair creation to set the namespace of the peer
7 device on creation rather than subsequently adding it to the
9 * This change supports kernels with limited namespace support
10 (e.g. RHEL 6.5) so long as ovs_use_veth is set to True.
11 * Addresses bug 1171727
13 Change-Id: I1885acc9934e7627bb9872703df7f5edf2980722
15 quantum/agent/linux/interface.py | 19 +++++++++++--------
16 quantum/agent/linux/ip_lib.py | 15 +++++++++++----
17 quantum/tests/unit/test_linux_interface.py | 22 ++++++----------------
18 quantum/tests/unit/test_linux_ip_lib.py | 11 +++++++++++
19 4 files changed, 39 insertions(+), 28 deletions(-)
21 diff --git a/quantum/agent/linux/interface.py b/quantum/agent/linux/interface.py
22 index e057b24..c0305a2 100644
23 --- a/quantum/agent/linux/interface.py
24 +++ b/quantum/agent/linux/interface.py
25 @@ -167,13 +167,17 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
26 tap_name = self._get_tap_name(device_name, prefix)
28 if self.conf.ovs_use_veth:
29 - root_dev, ns_dev = ip.add_veth(tap_name, device_name)
30 + # Create ns_dev in a namespace if one is configured.
31 + root_dev, ns_dev = ip.add_veth(tap_name,
33 + namespace2=namespace)
35 + ns_dev = ip.device(device_name)
37 internal = not self.conf.ovs_use_veth
38 self._ovs_add_port(bridge, tap_name, port_id, mac_address,
41 - ns_dev = ip.device(device_name)
42 ns_dev.link.set_address(mac_address)
44 if self.conf.network_device_mtu:
45 @@ -181,7 +185,8 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
46 if self.conf.ovs_use_veth:
47 root_dev.link.set_mtu(self.conf.network_device_mtu)
50 + # Add an interface created by ovs to the namespace.
51 + if not self.conf.ovs_use_veth and namespace:
52 namespace_obj = ip.ensure_namespace(namespace)
53 namespace_obj.add_device_to_namespace(ns_dev)
55 @@ -231,17 +236,15 @@ class BridgeInterfaceDriver(LinuxInterfaceDriver):
56 tap_name = device_name.replace(prefix, 'tap')
58 tap_name = device_name.replace(self.DEV_NAME_PREFIX, 'tap')
59 - root_veth, ns_veth = ip.add_veth(tap_name, device_name)
60 + # Create ns_veth in a namespace if one is configured.
61 + root_veth, ns_veth = ip.add_veth(tap_name, device_name,
62 + namespace2=namespace)
63 ns_veth.link.set_address(mac_address)
65 if self.conf.network_device_mtu:
66 root_veth.link.set_mtu(self.conf.network_device_mtu)
67 ns_veth.link.set_mtu(self.conf.network_device_mtu)
70 - namespace_obj = ip.ensure_namespace(namespace)
71 - namespace_obj.add_device_to_namespace(ns_veth)
73 root_veth.link.set_up()
76 diff --git a/quantum/agent/linux/ip_lib.py b/quantum/agent/linux/ip_lib.py
77 index 5207c23..2f56672 100644
78 --- a/quantum/agent/linux/ip_lib.py
79 +++ b/quantum/agent/linux/ip_lib.py
80 @@ -90,12 +90,19 @@ class IPWrapper(SubProcessBase):
81 self._as_root('', 'tuntap', ('add', name, 'mode', mode))
82 return IPDevice(name, self.root_helper, self.namespace)
84 - def add_veth(self, name1, name2):
85 - self._as_root('', 'link',
86 - ('add', name1, 'type', 'veth', 'peer', 'name', name2))
87 + def add_veth(self, name1, name2, namespace2=None):
88 + args = ['add', name1, 'type', 'veth', 'peer', 'name', name2]
90 + if namespace2 is None:
91 + namespace2 = self.namespace
93 + self.ensure_namespace(namespace2)
94 + args += ['netns', namespace2]
96 + self._as_root('', 'link', tuple(args))
98 return (IPDevice(name1, self.root_helper, self.namespace),
99 - IPDevice(name2, self.root_helper, self.namespace))
100 + IPDevice(name2, self.root_helper, namespace2))
102 def ensure_namespace(self, name):
103 if not self.netns.exists(name):
104 diff --git a/quantum/tests/unit/test_linux_interface.py b/quantum/tests/unit/test_linux_interface.py
105 index a386f93..dc1e464 100644
106 --- a/quantum/tests/unit/test_linux_interface.py
107 +++ b/quantum/tests/unit/test_linux_interface.py
108 @@ -199,12 +199,11 @@ class TestOVSInterfaceDriverWithVeth(TestOVSInterfaceDriver):
109 self.device_exists.side_effect = device_exists
111 root_dev = mock.Mock()
112 - _ns_dev = mock.Mock()
114 - self.ip().add_veth = mock.Mock(return_value=(root_dev, _ns_dev))
115 - self.ip().device = mock.Mock(return_value=(ns_dev))
116 - expected = [mock.call('sudo'), mock.call().add_veth('tap0', devname),
117 - mock.call().device(devname)]
118 + self.ip().add_veth = mock.Mock(return_value=(root_dev, ns_dev))
119 + expected = [mock.call('sudo'),
120 + mock.call().add_veth('tap0', devname,
121 + namespace2=namespace)]
123 vsctl_cmd = ['ovs-vsctl', '--', '--may-exist', 'add-port',
124 bridge, 'tap0', '--', 'set', 'Interface', 'tap0',
125 @@ -228,11 +227,6 @@ class TestOVSInterfaceDriverWithVeth(TestOVSInterfaceDriver):
127 ns_dev.assert_has_calls([mock.call.link.set_mtu(mtu)])
128 root_dev.assert_has_calls([mock.call.link.set_mtu(mtu)])
131 - [mock.call().ensure_namespace(namespace),
132 - mock.call().ensure_namespace().add_device_to_namespace(
135 self.ip.assert_has_calls(expected)
136 root_dev.assert_has_calls([mock.call.link.set_up()])
137 @@ -284,13 +278,9 @@ class TestBridgeInterfaceDriver(TestBase):
141 - ip_calls = [mock.call('sudo'), mock.call().add_veth('tap0', 'ns-0')]
142 + ip_calls = [mock.call('sudo'),
143 + mock.call().add_veth('tap0', 'ns-0', namespace2=namespace)]
144 ns_veth.assert_has_calls([mock.call.link.set_address(mac_address)])
147 - mock.call().ensure_namespace('01234567-1234-1234-99'),
148 - mock.call().ensure_namespace().add_device_to_namespace(
151 ns_veth.assert_has_calls([mock.call.link.set_mtu(mtu)])
152 root_veth.assert_has_calls([mock.call.link.set_mtu(mtu)])
153 diff --git a/quantum/tests/unit/test_linux_ip_lib.py b/quantum/tests/unit/test_linux_ip_lib.py
154 index 47b4063..e477f2f 100644
155 --- a/quantum/tests/unit/test_linux_ip_lib.py
156 +++ b/quantum/tests/unit/test_linux_ip_lib.py
157 @@ -205,6 +205,17 @@ class TestIpWrapper(base.BaseTestCase):
158 'peer', 'name', 'tap1'),
161 + def test_add_veth_with_namespaces(self):
163 + with mock.patch.object(ip_lib.IPWrapper, 'ensure_namespace') as en:
164 + ip_lib.IPWrapper('sudo').add_veth('tap0', 'tap1', namespace2=ns2)
165 + en.assert_has_calls([mock.call(ns2)])
166 + self.execute.assert_called_once_with('', 'link',
167 + ('add', 'tap0', 'type', 'veth',
168 + 'peer', 'name', 'tap1',
172 def test_get_device(self):
173 dev = ip_lib.IPWrapper('sudo', 'ns').device('eth0')
174 self.assertEqual(dev.root_helper, 'sudo')