]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
ip_lib: support creating Linux dummy interface
authorNeil Jerram <Neil.Jerram@metaswitch.com>
Mon, 27 Jul 2015 13:43:18 +0000 (14:43 +0100)
committerNeil Jerram <Neil.Jerram@metaswitch.com>
Fri, 21 Aug 2015 12:20:45 +0000 (13:20 +0100)
This is for use by a DHCP agent interface driver in the
networking-calico project.  networking-calico connects VMs without
using bridging, so it needs an unbridged DHCP port interface with
which it can associate the DHCP subnet prefix, and the Linux dummy
interface (in conjunction with use of Dnsmasq's --bridge-interface
feature) is suitable for that purpose.

Partial-Bug: #1486649
Change-Id: I5485c187bc44bac3c2942c4fc9e5a502912a81a2

neutron/agent/linux/ip_lib.py
neutron/tests/functional/agent/linux/test_ip_lib.py
neutron/tests/unit/agent/linux/test_ip_lib.py

index cadbd019fb1d4c989168493685050f627b99f86a..7c4b4e37af949b90437d0f4517b393aef7c79729 100644 (file)
@@ -152,6 +152,11 @@ class IPWrapper(SubProcessBase):
         """Delete a virtual interface between two namespaces."""
         self._as_root([], 'link', ('del', name))
 
+    def add_dummy(self, name):
+        """Create a Linux dummy interface with the given name."""
+        self._as_root([], 'link', ('add', name, 'type', 'dummy'))
+        return IPDevice(name, namespace=self.namespace)
+
     def ensure_namespace(self, name):
         if not self.netns.exists(name):
             ip = self.netns.add(name)
index 4e8316f77ee778ab23fd73feb3ace652126c7330..b166b0ec5cc0115a6482fc1df43d15edb7e36876 100644 (file)
@@ -24,6 +24,7 @@ from neutron.agent.common import config
 from neutron.agent.linux import interface
 from neutron.agent.linux import ip_lib
 from neutron.common import utils
+from neutron.tests.common import net_helpers
 from neutron.tests.functional.agent.linux import base
 from neutron.tests.functional import base as functional_base
 
@@ -164,3 +165,16 @@ class IpLibTestCase(IpLibTestFramework):
 
         routes = ip_lib.get_routing_table(4, namespace=attr.namespace)
         self.assertEqual(expected_routes, routes)
+
+    def _check_for_device_name(self, ip, name, should_exist):
+        exist = any(d for d in ip.get_devices() if d.name == name)
+        self.assertEqual(should_exist, exist)
+
+    def test_dummy_exists(self):
+        namespace = self.useFixture(net_helpers.NamespaceFixture())
+        dev_name = base.get_rand_name()
+        device = namespace.ip_wrapper.add_dummy(dev_name)
+        self.addCleanup(self._safe_delete_device, device)
+        self._check_for_device_name(namespace.ip_wrapper, dev_name, True)
+        device.link.delete()
+        self._check_for_device_name(namespace.ip_wrapper, dev_name, False)
index 87a2a82274c2cc5accc69de17d6b47e21f2373c3..81e310d011a29729742094208275ffc96fe01da0 100644 (file)
@@ -313,6 +313,14 @@ class TestIpWrapper(base.BaseTestCase):
                                              run_as_root=True, namespace=None,
                                              log_fail_as_error=True)
 
+    def test_add_dummy(self):
+        ip_lib.IPWrapper().add_dummy('dummy0')
+        self.execute.assert_called_once_with([], 'link',
+                                             ('add', 'dummy0',
+                                              'type', 'dummy'),
+                                             run_as_root=True, namespace=None,
+                                             log_fail_as_error=True)
+
     def test_get_device(self):
         dev = ip_lib.IPWrapper(namespace='ns').device('eth0')
         self.assertEqual(dev.namespace, 'ns')