Rename ipv6_utils.is_enabled()

IPv6 utils is_enabled() doesn't actually determine if IPv6 is enabled on
the host. It checks if /proc/sys/net/ipv6/conf/default/disable_ipv6 is
present and is set to 0. This kernel configuration option controls if
the kernel will automatically assign IPv6 link-local addresses to newly
created network interfaces when their link state changes to up. The
existence of this /proc files does indicate that the Linux kernel has
the ipv6 module loaded or ipv6 was compiled in. Having this /proc file
set to zero does not indicate IPv6 is not available on the system, just
that newly created interfaces will inherit this configuration and will
not have IPv6 addresses bound to them unless the administrator changes
the interfaces specific /proc/sys/net/ipv6/conf/$IFACE/disable_ipv6
configuration.

This check was added to Neutron so it could operate with distributions
which didn't load the ipv6 kernel module, preventing errors when
attempting to make IPv6 specific configurations in the iptables firewall
driver and the L3 agent. Removing it would break existing deployments.

Renaming this function to provide clarity for complex conditions tested
by this function. In fact it is a good security practice to set this
default disable_ipv6 option to 1, and explicitly enable IPv6 by setting
disable_ipv6=0 on individual interfaces which the administrator intends
to bind IPv6 addresses on. This establishes parity with IPv4 behavior
where interfaces are not active in an address family until the
administrator explicitly configures them to be active in that address
family. This practice does not currently work as expected with the
Neutron, since setting /proc/sys/net/ipv6/conf/default/disable_ipv6 to 1
unexpectedly disables creating IPv6 security group rules leaving
instances completely exposed via IPv6 regardless of security group
rules.

Change-Id: I844b992240a5db642766ec9c04e3b5fcab8e2e23
This commit is contained in:
Dustin Lundquist 2016-08-19 18:44:49 +01:00
parent 571e873427
commit 4f0caa0ece
6 changed files with 26 additions and 13 deletions

View File

@ -250,7 +250,7 @@ class L3NATAgent(ha.AgentMixin,
super(L3NATAgent, self).__init__(host=self.conf.host)
self.target_ex_net_id = None
self.use_ipv6 = ipv6_utils.is_enabled()
self.use_ipv6 = ipv6_utils.is_enabled_and_bind_by_default()
self.pd = pd.PrefixDelegation(self.context, self.process_monitor,
self.driver,

View File

@ -66,7 +66,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
def __init__(self, namespace=None):
self.iptables = iptables_manager.IptablesManager(
use_ipv6=ipv6_utils.is_enabled(),
use_ipv6=ipv6_utils.is_enabled_and_bind_by_default(),
namespace=namespace)
# TODO(majopela, shihanzhang): refactor out ipset to a separate
# driver composed over this one

View File

@ -18,6 +18,7 @@ IPv6-related utilities and helper functions.
"""
import os
from debtcollector import moves
from debtcollector import removals
import netaddr
from neutron_lib import constants as const
@ -53,7 +54,10 @@ def get_ipv6_addr_by_EUI64(prefix, mac):
'EUI-64: %s') % prefix)
def is_enabled():
def is_enabled_and_bind_by_default():
"""Check if host has the IPv6 support and is configured to bind IPv6
address to new interfaces by default.
"""
global _IS_IPV6_ENABLED
if _IS_IPV6_ENABLED is None:
@ -65,10 +69,18 @@ def is_enabled():
else:
_IS_IPV6_ENABLED = False
if not _IS_IPV6_ENABLED:
LOG.info(_LI("IPv6 is not enabled on this system."))
LOG.info(_LI("IPv6 not present or configured not to bind to new "
"interfaces on this system. Please ensure IPv6 is "
"enabled and /proc/sys/net/ipv6/conf/default/"
"disable_ipv6 is set to 1 to enable IPv6."))
return _IS_IPV6_ENABLED
is_enabled = moves.moved_function(is_enabled_and_bind_by_default,
'is_enabled', __name__, version='Ocata',
removal_version='Pike')
def is_auto_address_subnet(subnet):
"""Check if subnet is an auto address subnet."""
modes = [const.IPV6_SLAAC, const.DHCPV6_STATELESS]

View File

@ -74,7 +74,7 @@ class RouterWithMetering(object):
namespace=self.ns_name,
binary_name=WRAP_NAME,
state_less=True,
use_ipv6=ipv6_utils.is_enabled())
use_ipv6=ipv6_utils.is_enabled_and_bind_by_default())
self.metering_labels = {}

View File

@ -98,7 +98,8 @@ class L3HATestCase(framework.L3AgentTestFramework):
self._router_lifecycle(enable_ha=True, dual_stack=True,
v6_ext_gw_with_sub=False)
@testtools.skipUnless(ipv6_utils.is_enabled(), "IPv6 is not enabled")
@testtools.skipUnless(ipv6_utils.is_enabled_and_bind_by_default(),
"IPv6 is not enabled")
def test_ipv6_router_advts_after_router_state_change(self):
# Schedule router to l3 agent, and then add router gateway. Verify
# that router gw interface is configured to receive Router Advts.

View File

@ -55,10 +55,10 @@ class IPv6byEUI64TestCase(base.BaseTestCase):
ipv6_utils.get_ipv6_addr_by_EUI64(prefix, mac))
class TestIsEnabled(base.BaseTestCase):
class TestIsEnabledAndBindByDefault(base.BaseTestCase):
def setUp(self):
super(TestIsEnabled, self).setUp()
super(TestIsEnabledAndBindByDefault, self).setUp()
def reset_detection_flag():
ipv6_utils._IS_IPV6_ENABLED = None
@ -70,25 +70,25 @@ class TestIsEnabled(base.BaseTestCase):
def test_enabled(self):
self.useFixture(tools.OpenFixture(self.proc_path, '0'))
enabled = ipv6_utils.is_enabled()
enabled = ipv6_utils.is_enabled_and_bind_by_default()
self.assertTrue(enabled)
def test_disabled(self):
self.useFixture(tools.OpenFixture(self.proc_path, '1'))
enabled = ipv6_utils.is_enabled()
enabled = ipv6_utils.is_enabled_and_bind_by_default()
self.assertFalse(enabled)
def test_disabled_non_exists(self):
mo = self.useFixture(tools.OpenFixture(self.proc_path, '1')).mock_open
self.mock_exists.return_value = False
enabled = ipv6_utils.is_enabled()
enabled = ipv6_utils.is_enabled_and_bind_by_default()
self.assertFalse(enabled)
self.assertFalse(mo.called)
def test_memoize(self):
mo = self.useFixture(tools.OpenFixture(self.proc_path, '0')).mock_open
ipv6_utils.is_enabled()
enabled = ipv6_utils.is_enabled()
ipv6_utils.is_enabled_and_bind_by_default()
enabled = ipv6_utils.is_enabled_and_bind_by_default()
self.assertTrue(enabled)
mo.assert_called_once_with(self.proc_path, 'r')