Merge "dhcp: move dnsmasq version check to sanity_check"

This commit is contained in:
Jenkins 2015-01-27 17:25:07 +00:00 committed by Gerrit Code Review
commit 4143763913
6 changed files with 48 additions and 52 deletions

View File

@ -287,27 +287,10 @@ class Dnsmasq(DhcpLocalProcess):
NEUTRON_NETWORK_ID_KEY = 'NEUTRON_NETWORK_ID' NEUTRON_NETWORK_ID_KEY = 'NEUTRON_NETWORK_ID'
NEUTRON_RELAY_SOCKET_PATH_KEY = 'NEUTRON_RELAY_SOCKET_PATH' NEUTRON_RELAY_SOCKET_PATH_KEY = 'NEUTRON_RELAY_SOCKET_PATH'
MINIMUM_VERSION = 2.67
@classmethod @classmethod
def check_version(cls): def check_version(cls):
ver = 0 pass
try:
cmd = ['dnsmasq', '--version']
out = utils.execute(cmd)
m = re.search(r"version (\d+\.\d+)", out)
ver = float(m.group(1)) if m else 0
if ver < cls.MINIMUM_VERSION:
LOG.error(_LE('FAILED VERSION REQUIREMENT FOR DNSMASQ. '
'Please ensure that its version is %s '
'or above!'), cls.MINIMUM_VERSION)
raise SystemExit(1)
except (OSError, RuntimeError, IndexError, ValueError):
LOG.error(_LE('Unable to determine dnsmasq version. '
'Please ensure that its version is %s '
'or above!'), cls.MINIMUM_VERSION)
raise SystemExit(1)
return ver
@classmethod @classmethod
def existing_dhcp_networks(cls, conf, root_helper): def existing_dhcp_networks(cls, conf, root_helper):

View File

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import re
import netaddr import netaddr
from neutron.agent.linux import ip_lib from neutron.agent.linux import ip_lib
@ -29,6 +31,9 @@ from neutron.plugins.openvswitch.common import constants as ovs_const
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
MINIMUM_DNSMASQ_VERSION = 2.67
def ovs_vxlan_supported(root_helper, from_ip='192.0.2.1', to_ip='192.0.2.2'): def ovs_vxlan_supported(root_helper, from_ip='192.0.2.1', to_ip='192.0.2.2'):
name = "vxlantest-" + utils.get_random_string(6) name = "vxlantest-" + utils.get_random_string(6)
with ovs_lib.OVSBridge(name, root_helper) as br: with ovs_lib.OVSBridge(name, root_helper) as br:
@ -130,3 +135,22 @@ def netns_read_requires_helper(root_helper):
finally: finally:
ipw.netns.delete(nsname) ipw.netns.delete(nsname)
return not exists return not exists
def get_minimal_dnsmasq_version_supported():
return MINIMUM_DNSMASQ_VERSION
def dnsmasq_version_supported():
try:
cmd = ['dnsmasq', '--version']
out = agent_utils.execute(cmd)
m = re.search(r"version (\d+\.\d+)", out)
ver = float(m.group(1)) if m else 0
if ver < MINIMUM_DNSMASQ_VERSION:
return False
except (OSError, RuntimeError, IndexError, ValueError) as e:
LOG.debug("Exception while checking minimal dnsmasq version. "
"Exception: %s", e)
return False
return True

View File

@ -15,6 +15,7 @@
import sys import sys
from neutron.agent import dhcp_agent
from neutron.cmd.sanity import checks from neutron.cmd.sanity import checks
from neutron.common import config from neutron.common import config
from neutron.i18n import _LE, _LW from neutron.i18n import _LE, _LW
@ -29,6 +30,7 @@ cfg.CONF.import_group('VXLAN', 'neutron.plugins.linuxbridge.common.config')
cfg.CONF.import_group('ml2', 'neutron.plugins.ml2.config') cfg.CONF.import_group('ml2', 'neutron.plugins.ml2.config')
cfg.CONF.import_group('ml2_sriov', cfg.CONF.import_group('ml2_sriov',
'neutron.plugins.ml2.drivers.mech_sriov.mech_driver') 'neutron.plugins.ml2.drivers.mech_sriov.mech_driver')
dhcp_agent.register_options()
class BoolOptCallback(cfg.BoolOpt): class BoolOptCallback(cfg.BoolOpt):
@ -88,6 +90,19 @@ def check_read_netns():
return result return result
# NOTE(ihrachyshka): since the minimal version is currently capped due to
# missing hwaddr matching in dnsmasq < 2.67, a better version of the check
# would actually start dnsmasq server and issue a DHCP request using a IPv6
# DHCP client.
def check_dnsmasq_version():
result = checks.dnsmasq_version_supported()
if not result:
LOG.error(_LE('The installed version of dnsmasq is too old. '
'Please update to at least version %s.'),
checks.get_minimal_dnsmasq_version_supported())
return result
def check_nova_notify(): def check_nova_notify():
result = checks.nova_notify_supported() result = checks.nova_notify_supported()
if not result: if not result:
@ -133,6 +148,8 @@ OPTS = [
help=_('Check for VF management support')), help=_('Check for VF management support')),
BoolOptCallback('read_netns', check_read_netns, BoolOptCallback('read_netns', check_read_netns,
help=_('Check netns permission settings')), help=_('Check netns permission settings')),
BoolOptCallback('dnsmasq_version', check_dnsmasq_version,
help=_('Check minimal dnsmasq version')),
] ]
@ -160,6 +177,8 @@ def enable_tests_from_config():
cfg.CONF.set_override('vf_management', True) cfg.CONF.set_override('vf_management', True)
if not cfg.CONF.AGENT.use_helper_for_ns_read: if not cfg.CONF.AGENT.use_helper_for_ns_read:
cfg.CONF.set_override('read_netns', True) cfg.CONF.set_override('read_netns', True)
if cfg.CONF.dhcp_driver == 'neutron.agent.linux.dhcp.Dnsmasq':
cfg.CONF.set_override('dnsmasq_version', True)
def all_tests_passed(): def all_tests_passed():

View File

@ -32,6 +32,9 @@ class SanityTestCase(base.BaseTestCase):
def test_nova_notify_runs(self): def test_nova_notify_runs(self):
checks.nova_notify_supported() checks.nova_notify_supported()
def test_dnsmasq_version(self):
checks.dnsmasq_version_supported()
class SanityTestCaseRoot(functional_base.BaseSudoTestCase): class SanityTestCaseRoot(functional_base.BaseSudoTestCase):
"""Sanity checks that require root access. """Sanity checks that require root access.

View File

@ -539,10 +539,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
self.mock_init_p = mock.patch('neutron.agent.dhcp.agent.' self.mock_init_p = mock.patch('neutron.agent.dhcp.agent.'
'DhcpAgent._populate_networks_cache') 'DhcpAgent._populate_networks_cache')
self.mock_init = self.mock_init_p.start() self.mock_init = self.mock_init_p.start()
with mock.patch.object(dhcp.Dnsmasq, self.dhcp = dhcp_agent.DhcpAgent(HOSTNAME)
'check_version') as check_v:
check_v.return_value = dhcp.Dnsmasq.MINIMUM_VERSION
self.dhcp = dhcp_agent.DhcpAgent(HOSTNAME)
self.call_driver_p = mock.patch.object(self.dhcp, 'call_driver') self.call_driver_p = mock.patch.object(self.dhcp, 'call_driver')
self.call_driver = self.call_driver_p.start() self.call_driver = self.call_driver_p.start()
self.schedule_resync_p = mock.patch.object(self.dhcp, self.schedule_resync_p = mock.patch.object(self.dhcp,

View File

@ -18,7 +18,6 @@ import os
import mock import mock
import netaddr import netaddr
from oslo.config import cfg from oslo.config import cfg
import testtools
from neutron.agent.common import config from neutron.agent.common import config
from neutron.agent.dhcp import config as dhcp_config from neutron.agent.dhcp import config as dhcp_config
@ -697,7 +696,6 @@ class TestDnsmasq(TestBase):
def _get_dnsmasq(self, network, process_monitor=None): def _get_dnsmasq(self, network, process_monitor=None):
process_monitor = process_monitor or mock.Mock() process_monitor = process_monitor or mock.Mock()
return dhcp.Dnsmasq(self.conf, network, return dhcp.Dnsmasq(self.conf, network,
version=dhcp.Dnsmasq.MINIMUM_VERSION,
process_monitor=process_monitor) process_monitor=process_monitor)
def _test_spawn(self, extra_options, network=FakeDualNetwork(), def _test_spawn(self, extra_options, network=FakeDualNetwork(),
@ -1251,34 +1249,6 @@ class TestDnsmasq(TestBase):
'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'], 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'],
sorted(result)) sorted(result))
def _check_version(self, cmd_out, expected_value):
with mock.patch('neutron.agent.linux.utils.execute') as cmd:
cmd.return_value = cmd_out
result = dhcp.Dnsmasq.check_version()
self.assertEqual(result, expected_value)
def test_check_find_version(self):
# Dnsmasq output currently gives the version number before the
# copyright year, but just in case ...
self._check_version('Copyright 2000-2014. Dnsmasq version 3.33 ...',
float(3.33))
def test_check_minimum_version(self):
self._check_version('Dnsmasq version 2.67 Copyright (c)...',
dhcp.Dnsmasq.MINIMUM_VERSION)
def test_check_future_version(self):
self._check_version('Dnsmasq version 2.99 Copyright (c)...',
float(2.99))
def test_check_fail_version(self):
with testtools.ExpectedException(SystemExit):
self._check_version('Dnsmasq version 2.62 Copyright (c)...', 0)
def test_check_version_failed_cmd_execution(self):
with testtools.ExpectedException(SystemExit):
self._check_version('Error while executing command', 0)
def test_only_populates_dhcp_enabled_subnets(self): def test_only_populates_dhcp_enabled_subnets(self):
exp_host_name = '/dhcp/eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee/host' exp_host_name = '/dhcp/eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee/host'
exp_host_data = ('00:00:80:aa:bb:cc,host-192-168-0-2.openstacklocal,' exp_host_data = ('00:00:80:aa:bb:cc,host-192-168-0-2.openstacklocal,'