Merge "Add support for dnsmasq version 2.48" into stable/grizzly

This commit is contained in:
Jenkins 2013-05-29 13:31:26 +00:00 committed by Gerrit Code Review
commit e5c2c700a9
4 changed files with 53 additions and 20 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)