]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Mangle network namespace name used by dhcp_agent
authorMark McClain <mark.mcclain@dreamhost.com>
Thu, 30 Aug 2012 23:18:41 +0000 (19:18 -0400)
committerMark McClain <mark.mcclain@dreamhost.com>
Thu, 30 Aug 2012 23:50:19 +0000 (19:50 -0400)
fixes bug 1044113

This fix managles the network namespace by prefixing the network id with
qdhcp.

Change-Id: I41f48f805efd83bd3e12049007067200cc384ffe

quantum/agent/dhcp_agent.py
quantum/agent/linux/dhcp.py
quantum/tests/unit/test_dhcp_agent.py
quantum/tests/unit/test_linux_dhcp.py

index 815f78a54ddf1c4c95cacf6ce938113e59dc6b24..f630fe0242bc82aefa43fe522b83bfa7be424417 100644 (file)
@@ -41,6 +41,7 @@ from quantum.openstack.common.rpc import proxy
 from quantum.version import version_string
 
 LOG = logging.getLogger(__name__)
+NS_PREFIX = 'qdhcp-'
 
 
 class DhcpAgent(object):
@@ -76,13 +77,18 @@ class DhcpAgent(object):
 
     def call_driver(self, action, network):
         """Invoke an action on a DHCP driver instance."""
+        if self.conf.use_namespaces:
+            namespace = NS_PREFIX + network.id
+        else:
+            namespace = None
         try:
             # the Driver expects something that is duck typed similar to
             # the base models.
             driver = self.dhcp_driver_cls(self.conf,
                                           network,
                                           self.conf.root_helper,
-                                          self.device_manager)
+                                          self.device_manager,
+                                          namespace)
             getattr(driver, action)()
 
         except Exception, e:
@@ -355,7 +361,7 @@ class DeviceManager(object):
         interface_name = self.get_interface_name(network, port)
 
         if self.conf.use_namespaces:
-            namespace = network.id
+            namespace = NS_PREFIX + network.id
         else:
             namespace = None
 
@@ -388,7 +394,7 @@ class DeviceManager(object):
     def destroy(self, network, device_name):
         """Destroy the device used for the network's DHCP on this host."""
         if self.conf.use_namespaces:
-            namespace = network.id
+            namespace = NS_PREFIX + network.id
         else:
             namespace = None
 
index 54b4ba6b2d0f15d161b014664ec91ab09e8bcf61..add556b0a4279d92f0a5a7c6e22468598452d0d0 100644 (file)
@@ -64,11 +64,12 @@ class DhcpBase(object):
     __metaclass__ = abc.ABCMeta
 
     def __init__(self, conf, network, root_helper='sudo',
-                 device_delegate=None):
+                 device_delegate=None, namespace=None):
         self.conf = conf
         self.network = network
         self.root_helper = root_helper
         self.device_delegate = device_delegate
+        self.namespace = namespace
 
     @abc.abstractmethod
     def enable(self):
@@ -118,9 +119,8 @@ class DhcpLocalProcess(DhcpBase):
 
         if self.active:
             cmd = ['kill', '-9', pid]
-            if self.conf.use_namespaces:
-                ip_wrapper = ip_lib.IPWrapper(self.root_helper,
-                                              namespace=self.network.id)
+            if self.namespace:
+                ip_wrapper = ip_lib.IPWrapper(self.root_helper, self.namespace)
                 ip_wrapper.netns.execute(cmd)
             else:
                 utils.execute(cmd, self.root_helper)
@@ -250,9 +250,8 @@ class Dnsmasq(DhcpLocalProcess):
         if self.conf.dnsmasq_dns_server:
             cmd.append('--server=%s' % self.conf.dnsmasq_dns_server)
 
-        if self.conf.use_namespaces:
-            ip_wrapper = ip_lib.IPWrapper(self.root_helper,
-                                          namespace=self.network.id)
+        if self.namespace:
+            ip_wrapper = ip_lib.IPWrapper(self.root_helper, self.namespace)
             ip_wrapper.netns.execute(cmd, addl_env=env)
         else:
             # For normal sudo prepend the env vars before command
@@ -272,9 +271,8 @@ class Dnsmasq(DhcpLocalProcess):
         self._output_opts_file()
         cmd = ['kill', '-HUP', self.pid]
 
-        if self.conf.use_namespaces:
-            ip_wrapper = ip_lib.IPWrapper(self.root_helper,
-                                          namespace=self.network.id)
+        if self.namespace:
+            ip_wrapper = ip_lib.IPWrapper(self.root_helper, self.namespace)
             ip_wrapper.netns.execute(cmd)
         else:
             utils.execute(cmd, self.root_helper)
index cb1d20cd6453d67e64dffa08ab4c968cdcc223cf..e1b5bce702b8364412f414d4a1e9c9181ac64112 100644 (file)
@@ -118,14 +118,17 @@ class TestDhcpAgent(unittest.TestCase):
         self.notification.assert_has_calls([mock.call.run_dispatch()])
 
     def test_call_driver(self):
+        network = mock.Mock()
+        network.id = '1'
         with mock.patch('quantum.agent.dhcp_agent.DeviceManager') as dev_mgr:
             dhcp = dhcp_agent.DhcpAgent(cfg.CONF)
-            dhcp.call_driver('foo', '1')
+            dhcp.call_driver('foo', network)
             dev_mgr.assert_called()
             self.driver.assert_called_once_with(cfg.CONF,
                                                 mock.ANY,
                                                 'sudo',
-                                                mock.ANY)
+                                                mock.ANY,
+                                                'qdhcp-1')
 
 
 class TestDhcpAgentEventHandler(unittest.TestCase):
@@ -486,9 +489,11 @@ class TestDeviceManager(unittest.TestCase):
         plugin.assert_has_calls([
             mock.call.get_dhcp_port(fake_network.id, mock.ANY)])
 
+        namespace = dhcp_agent.NS_PREFIX + fake_network.id
+
         expected = [mock.call.init_l3('tap12345678-12',
                                       ['172.9.9.9/24'],
-                                      namespace=fake_network.id)]
+                                      namespace=namespace)]
 
         if not reuse_existing:
             expected.insert(0,
@@ -496,7 +501,7 @@ class TestDeviceManager(unittest.TestCase):
                                            fake_port1.id,
                                            'tap12345678-12',
                                            'aa:bb:cc:dd:ee:ff',
-                                           namespace=fake_network.id))
+                                           namespace=namespace))
 
         self.mock_driver.assert_has_calls(expected)
 
@@ -538,7 +543,7 @@ class TestDeviceManager(unittest.TestCase):
             dvr_cls.assert_called_once_with(cfg.CONF)
             mock_driver.assert_has_calls(
                 [mock.call.unplug('tap12345678-12',
-                                  namespace=fake_network.id)])
+                                  namespace='qdhcp-' + fake_network.id)])
             plugin.assert_has_calls(
                 [mock.call.release_dhcp_port(fake_network.id, mock.ANY)])
 
index f2c6a59e6736c986e1ba4152998412b8b0862895..93f1ae1f30ef4a6e43f2cde1f5c9990476ad439a 100644 (file)
@@ -142,7 +142,7 @@ class TestDhcpBase(unittest.TestCase):
     def test_restart(self):
         class SubClass(dhcp.DhcpBase):
             def __init__(self):
-                dhcp.DhcpBase.__init__(self, None, None)
+                dhcp.DhcpBase.__init__(self, None, None, None)
                 self.called = []
 
             def enable(self):
@@ -306,12 +306,12 @@ class TestDhcpLocalProcess(TestBase):
             mocks['active'].__get__ = mock.Mock(return_value=True)
             mocks['pid'].__get__ = mock.Mock(return_value=5)
             mocks['interface_name'].__get__ = mock.Mock(return_value='tap0')
-            lp = LocalChild(self.conf, network, device_delegate=delegate)
+            lp = LocalChild(self.conf, network, device_delegate=delegate,
+                            namespace='qdhcp-ns')
             lp.disable()
 
         delegate.assert_has_calls([mock.call.destroy(network, 'tap0')])
-        exp_args = ['ip', 'netns', 'exec',
-                    'cccccccc-cccc-cccc-cccc-cccccccccccc', 'kill', '-9', 5]
+        exp_args = ['ip', 'netns', 'exec', 'qdhcp-ns', 'kill', '-9', 5]
         self.execute.assert_called_once_with(exp_args, root_helper='sudo')
 
     def test_pid(self):
@@ -372,7 +372,7 @@ class TestDnsmasq(TestBase):
             'ip',
             'netns',
             'exec',
-            'cccccccc-cccc-cccc-cccc-cccccccccccc',
+            'qdhcp-ns',
             'dnsmasq',
             '--no-hosts',
             '--no-resolv',
@@ -411,7 +411,8 @@ class TestDnsmasq(TestBase):
             with mock.patch.object(dhcp.sys, 'argv') as argv:
                 argv.__getitem__.side_effect = fake_argv
                 dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork(),
-                                  device_delegate=delegate)
+                                  device_delegate=delegate,
+                                  namespace='qdhcp-ns')
                 dm.spawn_process()
                 self.assertTrue(mocks['_output_opts_file'].called)
                 self.execute.assert_called_once_with(expected,
@@ -480,14 +481,14 @@ tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
                                                             fake_v6_cidr,
                                                             fake_v6)
 
-        exp_args = ['ip', 'netns', 'exec',
-                    'cccccccc-cccc-cccc-cccc-cccccccccccc', 'kill', '-HUP', 5]
+        exp_args = ['ip', 'netns', 'exec', 'qdhcp-ns', 'kill', '-HUP', 5]
 
         with mock.patch('os.path.isdir') as isdir:
             isdir.return_value = True
             with mock.patch.object(dhcp.Dnsmasq, 'pid') as pid:
                 pid.__get__ = mock.Mock(return_value=5)
-                dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork())
+                dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork(),
+                                  namespace='qdhcp-ns')
                 dm.reload_allocations()
 
         self.safe.assert_has_calls([mock.call(exp_host_name, exp_host_data),