Merge "Add support for dnsmasq version 2.48" into stable/grizzly
This commit is contained in:
commit
e5c2c700a9
|
@ -80,7 +80,7 @@ class DhcpAgent(manager.Manager):
|
||||||
self.device_manager = DeviceManager(self.conf, self.plugin_rpc)
|
self.device_manager = DeviceManager(self.conf, self.plugin_rpc)
|
||||||
self.lease_relay = DhcpLeaseRelay(self.update_lease)
|
self.lease_relay = DhcpLeaseRelay(self.update_lease)
|
||||||
|
|
||||||
self.dhcp_driver_cls.check_version()
|
self.dhcp_version = self.dhcp_driver_cls.check_version()
|
||||||
self._populate_networks_cache()
|
self._populate_networks_cache()
|
||||||
|
|
||||||
def _populate_networks_cache(self):
|
def _populate_networks_cache(self):
|
||||||
|
@ -126,7 +126,8 @@ class DhcpAgent(manager.Manager):
|
||||||
network,
|
network,
|
||||||
self.root_helper,
|
self.root_helper,
|
||||||
self.device_manager,
|
self.device_manager,
|
||||||
self._ns_name(network))
|
self._ns_name(network),
|
||||||
|
self.dhcp_version)
|
||||||
getattr(driver, action)()
|
getattr(driver, action)()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -66,12 +66,13 @@ 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, namespace=None):
|
device_delegate=None, namespace=None, version=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
|
self.namespace = namespace
|
||||||
|
self.version = version
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def enable(self):
|
def enable(self):
|
||||||
|
@ -230,7 +231,7 @@ class Dnsmasq(DhcpLocalProcess):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def check_version(cls):
|
def check_version(cls):
|
||||||
is_valid_version = None
|
ver = 0
|
||||||
try:
|
try:
|
||||||
cmd = ['dnsmasq', '--version']
|
cmd = ['dnsmasq', '--version']
|
||||||
out = utils.execute(cmd)
|
out = utils.execute(cmd)
|
||||||
|
@ -245,7 +246,7 @@ class Dnsmasq(DhcpLocalProcess):
|
||||||
LOG.warning(_('Unable to determine dnsmasq version. '
|
LOG.warning(_('Unable to determine dnsmasq version. '
|
||||||
'Please ensure that its version is %s '
|
'Please ensure that its version is %s '
|
||||||
'or above!'), cls.MINIMUM_VERSION)
|
'or above!'), cls.MINIMUM_VERSION)
|
||||||
return is_valid_version
|
return float(ver)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def existing_dhcp_networks(cls, conf, root_helper):
|
def existing_dhcp_networks(cls, conf, root_helper):
|
||||||
|
@ -299,8 +300,12 @@ class Dnsmasq(DhcpLocalProcess):
|
||||||
# TODO (mark): how do we indicate other options
|
# TODO (mark): how do we indicate other options
|
||||||
# ra-only, slaac, ra-nameservers, and ra-stateless.
|
# ra-only, slaac, ra-nameservers, and ra-stateless.
|
||||||
mode = 'static'
|
mode = 'static'
|
||||||
cmd.append('--dhcp-range=set:%s,%s,%s,%ss' %
|
if self.version >= self.MINIMUM_VERSION:
|
||||||
(self._TAG_PREFIX % i,
|
set_tag = 'set:'
|
||||||
|
else:
|
||||||
|
set_tag = ''
|
||||||
|
cmd.append('--dhcp-range=%s%s,%s,%s,%ss' %
|
||||||
|
(set_tag, self._TAG_PREFIX % i,
|
||||||
netaddr.IPNetwork(subnet.cidr).network,
|
netaddr.IPNetwork(subnet.cidr).network,
|
||||||
mode,
|
mode,
|
||||||
self.conf.dhcp_lease_time))
|
self.conf.dhcp_lease_time))
|
||||||
|
@ -434,7 +439,11 @@ class Dnsmasq(DhcpLocalProcess):
|
||||||
'quantum-dhcp-agent-dnsmasq-lease-update')
|
'quantum-dhcp-agent-dnsmasq-lease-update')
|
||||||
|
|
||||||
def _format_option(self, index, option_name, *args):
|
def _format_option(self, index, option_name, *args):
|
||||||
return ','.join(('tag:' + self._TAG_PREFIX % index,
|
if self.version >= self.MINIMUM_VERSION:
|
||||||
|
set_tag = 'tag:'
|
||||||
|
else:
|
||||||
|
set_tag = ''
|
||||||
|
return ','.join((set_tag + self._TAG_PREFIX % index,
|
||||||
'option:%s' % option_name) + args)
|
'option:%s' % option_name) + args)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -218,7 +218,8 @@ class TestDhcpAgent(base.BaseTestCase):
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
'sudo',
|
'sudo',
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
'qdhcp-1')
|
'qdhcp-1',
|
||||||
|
mock.ANY)
|
||||||
|
|
||||||
def test_call_driver_failure(self):
|
def test_call_driver_failure(self):
|
||||||
network = mock.Mock()
|
network = mock.Mock()
|
||||||
|
@ -233,7 +234,8 @@ class TestDhcpAgent(base.BaseTestCase):
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
'sudo',
|
'sudo',
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
'qdhcp-1')
|
'qdhcp-1',
|
||||||
|
mock.ANY)
|
||||||
self.assertEqual(log.call_count, 1)
|
self.assertEqual(log.call_count, 1)
|
||||||
self.assertTrue(dhcp.needs_resync)
|
self.assertTrue(dhcp.needs_resync)
|
||||||
|
|
||||||
|
|
|
@ -450,7 +450,8 @@ class TestDnsmasq(TestBase):
|
||||||
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')
|
namespace='qdhcp-ns',
|
||||||
|
version=float(2.59))
|
||||||
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,
|
||||||
|
@ -488,7 +489,8 @@ tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
|
||||||
|
|
||||||
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
|
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
|
||||||
conf_fn.return_value = '/foo/opts'
|
conf_fn.return_value = '/foo/opts'
|
||||||
dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork())
|
dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork(),
|
||||||
|
version=float(2.59))
|
||||||
dm._output_opts_file()
|
dm._output_opts_file()
|
||||||
|
|
||||||
self.safe.assert_called_once_with('/foo/opts', expected)
|
self.safe.assert_called_once_with('/foo/opts', expected)
|
||||||
|
@ -500,7 +502,21 @@ tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1
|
||||||
tag:tag0,option:router,192.168.0.1""".lstrip()
|
tag:tag0,option:router,192.168.0.1""".lstrip()
|
||||||
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
|
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
|
||||||
conf_fn.return_value = '/foo/opts'
|
conf_fn.return_value = '/foo/opts'
|
||||||
dm = dhcp.Dnsmasq(self.conf, FakeDualNetworkSingleDHCP())
|
dm = dhcp.Dnsmasq(self.conf, FakeDualNetworkSingleDHCP(),
|
||||||
|
version=float(2.59))
|
||||||
|
dm._output_opts_file()
|
||||||
|
|
||||||
|
self.safe.assert_called_once_with('/foo/opts', expected)
|
||||||
|
|
||||||
|
def test_output_opts_file_single_dhcp_ver2_48(self):
|
||||||
|
expected = """
|
||||||
|
tag0,option:dns-server,8.8.8.8
|
||||||
|
tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1
|
||||||
|
tag0,option:router,192.168.0.1""".lstrip()
|
||||||
|
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
|
||||||
|
conf_fn.return_value = '/foo/opts'
|
||||||
|
dm = dhcp.Dnsmasq(self.conf, FakeDualNetworkSingleDHCP(),
|
||||||
|
version=float(2.48))
|
||||||
dm._output_opts_file()
|
dm._output_opts_file()
|
||||||
|
|
||||||
self.safe.assert_called_once_with('/foo/opts', expected)
|
self.safe.assert_called_once_with('/foo/opts', expected)
|
||||||
|
@ -512,7 +528,8 @@ tag:tag0,option:router""".lstrip()
|
||||||
|
|
||||||
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
|
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
|
||||||
conf_fn.return_value = '/foo/opts'
|
conf_fn.return_value = '/foo/opts'
|
||||||
dm = dhcp.Dnsmasq(self.conf, FakeV4NoGatewayNetwork())
|
dm = dhcp.Dnsmasq(self.conf, FakeV4NoGatewayNetwork(),
|
||||||
|
version=float(2.59))
|
||||||
with mock.patch.object(dm, '_make_subnet_interface_ip_map') as ipm:
|
with mock.patch.object(dm, '_make_subnet_interface_ip_map') as ipm:
|
||||||
ipm.return_value = {FakeV4SubnetNoGateway.id: '192.168.1.1'}
|
ipm.return_value = {FakeV4SubnetNoGateway.id: '192.168.1.1'}
|
||||||
|
|
||||||
|
@ -551,7 +568,8 @@ tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
|
||||||
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')
|
namespace='qdhcp-ns',
|
||||||
|
version=float(2.59))
|
||||||
|
|
||||||
method_name = '_make_subnet_interface_ip_map'
|
method_name = '_make_subnet_interface_ip_map'
|
||||||
with mock.patch.object(dhcp.Dnsmasq,
|
with mock.patch.object(dhcp.Dnsmasq,
|
||||||
|
@ -593,7 +611,7 @@ tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
|
||||||
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')
|
namespace='qdhcp-ns', version=float(2.59))
|
||||||
|
|
||||||
method_name = '_make_subnet_interface_ip_map'
|
method_name = '_make_subnet_interface_ip_map'
|
||||||
with mock.patch.object(dhcp.Dnsmasq, method_name) as ip_map:
|
with mock.patch.object(dhcp.Dnsmasq, method_name) as ip_map:
|
||||||
|
@ -727,13 +745,16 @@ tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
|
||||||
self.assertEqual(result, expected_value)
|
self.assertEqual(result, expected_value)
|
||||||
|
|
||||||
def test_check_minimum_version(self):
|
def test_check_minimum_version(self):
|
||||||
self._check_version('Dnsmasq version 2.59 Copyright (c)...', True)
|
self._check_version('Dnsmasq version 2.59 Copyright (c)...',
|
||||||
|
float(2.59))
|
||||||
|
|
||||||
def test_check_future_version(self):
|
def test_check_future_version(self):
|
||||||
self._check_version('Dnsmasq version 2.65 Copyright (c)...', True)
|
self._check_version('Dnsmasq version 2.65 Copyright (c)...',
|
||||||
|
float(2.65))
|
||||||
|
|
||||||
def test_check_fail_version(self):
|
def test_check_fail_version(self):
|
||||||
self._check_version('Dnsmasq version 2.48 Copyright (c)...', False)
|
self._check_version('Dnsmasq version 2.48 Copyright (c)...',
|
||||||
|
float(2.48))
|
||||||
|
|
||||||
def test_check_version_failed_cmd_execution(self):
|
def test_check_version_failed_cmd_execution(self):
|
||||||
self._check_version('Error while executing command', None)
|
self._check_version('Error while executing command', 0)
|
||||||
|
|
Loading…
Reference in New Issue