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