It has been noted that older versions of dnsmasq may have unexpected
behavior, so this patch introduces a check on dnsmasq version; if
the minimum version is not met, a warning is logged. This is less
invasive than raising an Exception and abort the dhcp agent, even
though this also seems like a perfectly acceptable behavior.
Fixes bug
1170793
Change-Id: Idd91c3753fb05f223ed0e3c53ad692ee65ea4905
# dhcp-agent
ip_exec_dnsmasq: DnsmasqNetnsFilter, /sbin/ip, root
dnsmasq: DnsmasqFilter, /sbin/dnsmasq, root
+dnsmasq_ver: DnsmasqVersionFilter, /sbin/dnsmasq, root
dnsmasq_usr: DnsmasqFilter, /usr/sbin/dnsmasq, root
+dnsmasq_usr_ver: DnsmasqVersionFilter, /usr/sbin/dnsmasq, root
# dhcp-agent uses kill as well, that's handled by the generic KillFilter
# it looks like these are the only signals needed, per
# quantum/agent/linux/dhcp.py
self.device_manager = DeviceManager(self.conf, self.plugin_rpc)
self.lease_relay = DhcpLeaseRelay(self.update_lease)
+ self.dhcp_driver_cls.check_version(self.root_helper)
self._populate_networks_cache()
def _populate_networks_cache(self):
raise NotImplementedError
+ @classmethod
+ def check_version(cls, root_helper):
+ """Execute version checks on DHCP server."""
+
+ raise NotImplementedError
+
class DhcpLocalProcess(DhcpBase):
PORTS = []
QUANTUM_NETWORK_ID_KEY = 'QUANTUM_NETWORK_ID'
QUANTUM_RELAY_SOCKET_PATH_KEY = 'QUANTUM_RELAY_SOCKET_PATH'
+ MINIMUM_VERSION = 2.59
+
+ @classmethod
+ def check_version(cls, root_helper):
+ is_valid_version = None
+ try:
+ cmd = ['dnsmasq', '--version']
+ out = utils.execute(cmd, root_helper)
+ ver = re.findall("\d+.\d+", out)[0]
+ is_valid_version = float(ver) >= cls.MINIMUM_VERSION
+ if not is_valid_version:
+ LOG.warning(_('FAILED VERSION REQUIREMENT FOR DNSMASQ. '
+ 'DHCP AGENT MAY NOT RUN CORRECTLY! '
+ 'Please ensure that its version is %s '
+ 'or above!'), cls.MINIMUM_VERSION)
+ except (RuntimeError, IndexError, ValueError):
+ LOG.warning(_('Unable to determine dnsmasq version. '
+ 'Please ensure that its version is %s '
+ 'or above!'), cls.MINIMUM_VERSION)
+ return is_valid_version
@classmethod
def existing_dhcp_networks(cls, conf, root_helper):
return env
+class DnsmasqVersionFilter(CommandFilter):
+ """Specific filter to check dnsmasq version."""
+ def match(self, userargs):
+ return userargs[0] == "dnsmasq" and userargs[1] == "--version"
+
+
class DnsmasqNetnsFilter(DnsmasqFilter):
"""Specific filter for the dnsmasq call (which includes env)."""
dhcp.DhcpBase.existing_dhcp_networks,
None, None)
+ def test_check_version_abstract_error(self):
+ self.assertRaises(NotImplementedError,
+ dhcp.DhcpBase.check_version, None)
+
def test_base_abc_error(self):
self.assertRaises(TypeError, dhcp.DhcpBase, None)
mock_listdir.assert_called_once_with(path)
self.assertEquals(['aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'],
result)
+
+ def _check_version(self, cmd_out, expected_value):
+ with mock.patch('quantum.agent.linux.utils.execute') as cmd:
+ cmd.return_value = cmd_out
+ result = dhcp.Dnsmasq.check_version('sudo')
+ self.assertEqual(result, expected_value)
+
+ def test_check_minimum_version(self):
+ self._check_version('Dnsmasq version 2.59 Copyright (c)...', True)
+
+ def test_check_future_version(self):
+ self._check_version('Dnsmasq version 2.65 Copyright (c)...', True)
+
+ def test_check_fail_version(self):
+ self._check_version('Dnsmasq version 2.48 Copyright (c)...', False)
+
+ def test_check_version_failed_cmd_execution(self):
+ self._check_version('Error while executing command', None)