]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Log a warning if dnsmasq version is below the minimum required
authorarmando-migliaccio <amigliaccio@nicira.com>
Wed, 8 May 2013 00:10:22 +0000 (17:10 -0700)
committerarmando-migliaccio <amigliaccio@nicira.com>
Wed, 8 May 2013 09:02:10 +0000 (02:02 -0700)
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

etc/quantum/rootwrap.d/dhcp.filters
quantum/agent/dhcp_agent.py
quantum/agent/linux/dhcp.py
quantum/rootwrap/filters.py
quantum/tests/unit/test_linux_dhcp.py

index 89abb02ad67c88174f1a1f5ea7dac5035d933eb1..8e78063cf0ec1038fb7116f2a019dc0f6332a532 100644 (file)
@@ -11,7 +11,9 @@
 # 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
index 7c64d8d82549ffc7acc23546cdc4554ba49c510b..00629c2a2b05c6bbb009910d6566fdccad133719 100644 (file)
@@ -80,6 +80,7 @@ class DhcpAgent(manager.Manager):
         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):
index 4f834a1ea0415dec5f2f974907c3cd228133c3db..95c9f14edfbe9e114ae1a918204e2a0aa91a70c6 100644 (file)
@@ -100,6 +100,12 @@ class DhcpBase(object):
 
         raise NotImplementedError
 
+    @classmethod
+    def check_version(cls, root_helper):
+        """Execute version checks on DHCP server."""
+
+        raise NotImplementedError
+
 
 class DhcpLocalProcess(DhcpBase):
     PORTS = []
@@ -215,6 +221,26 @@ class Dnsmasq(DhcpLocalProcess):
 
     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):
index 28b5e1bd34b4513293a28112c2d0dadebbdd95f6..3aee87a7895809b70fda05a67193d68fe60bf00f 100644 (file)
@@ -106,6 +106,12 @@ class DnsmasqFilter(CommandFilter):
         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)."""
 
index 414b197b190abe9ec8aaec9dc645db87b483208e..c5331b169b490f7e54d7e7a362d8ea1136607c4b 100644 (file)
@@ -140,6 +140,10 @@ class TestDhcpBase(base.BaseTestCase):
                           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)
 
@@ -712,3 +716,21 @@ tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
                 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)