From 650a7d7c871eee49fe0885a717eaeed8e291465f Mon Sep 17 00:00:00 2001 From: Mark McClain Date: Thu, 30 Aug 2012 19:18:41 -0400 Subject: [PATCH] Mangle network namespace name used by dhcp_agent fixes bug 1044113 This fix managles the network namespace by prefixing the network id with qdhcp. Change-Id: I41f48f805efd83bd3e12049007067200cc384ffe --- quantum/agent/dhcp_agent.py | 12 +++++++++--- quantum/agent/linux/dhcp.py | 18 ++++++++---------- quantum/tests/unit/test_dhcp_agent.py | 15 ++++++++++----- quantum/tests/unit/test_linux_dhcp.py | 19 ++++++++++--------- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/quantum/agent/dhcp_agent.py b/quantum/agent/dhcp_agent.py index 815f78a54d..f630fe0242 100644 --- a/quantum/agent/dhcp_agent.py +++ b/quantum/agent/dhcp_agent.py @@ -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 diff --git a/quantum/agent/linux/dhcp.py b/quantum/agent/linux/dhcp.py index 54b4ba6b2d..add556b0a4 100644 --- a/quantum/agent/linux/dhcp.py +++ b/quantum/agent/linux/dhcp.py @@ -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) diff --git a/quantum/tests/unit/test_dhcp_agent.py b/quantum/tests/unit/test_dhcp_agent.py index cb1d20cd64..e1b5bce702 100644 --- a/quantum/tests/unit/test_dhcp_agent.py +++ b/quantum/tests/unit/test_dhcp_agent.py @@ -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)]) diff --git a/quantum/tests/unit/test_linux_dhcp.py b/quantum/tests/unit/test_linux_dhcp.py index f2c6a59e67..93f1ae1f30 100644 --- a/quantum/tests/unit/test_linux_dhcp.py +++ b/quantum/tests/unit/test_linux_dhcp.py @@ -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),