Merge "Switch isolated metadata proxy to bind to 169.254.169.254"
This commit is contained in:
commit
46dc30991a
@ -657,7 +657,7 @@ class DhcpAgent(manager.Manager):
|
|||||||
|
|
||||||
metadata_driver.MetadataDriver.spawn_monitored_metadata_proxy(
|
metadata_driver.MetadataDriver.spawn_monitored_metadata_proxy(
|
||||||
self._process_monitor, network.namespace, dhcp.METADATA_PORT,
|
self._process_monitor, network.namespace, dhcp.METADATA_PORT,
|
||||||
self.conf, **kwargs)
|
self.conf, bind_address=dhcp.METADATA_DEFAULT_IP, **kwargs)
|
||||||
|
|
||||||
def disable_isolated_metadata_proxy(self, network):
|
def disable_isolated_metadata_proxy(self, network):
|
||||||
if (self.conf.enable_metadata_network and
|
if (self.conf.enable_metadata_network and
|
||||||
|
@ -208,16 +208,8 @@ class FipNamespace(namespaces.Namespace):
|
|||||||
LOG.debug("DVR: add fip namespace: %s", self.name)
|
LOG.debug("DVR: add fip namespace: %s", self.name)
|
||||||
# parent class will ensure the namespace exists and turn-on forwarding
|
# parent class will ensure the namespace exists and turn-on forwarding
|
||||||
super(FipNamespace, self).create()
|
super(FipNamespace, self).create()
|
||||||
# Somewhere in the 3.19 kernel timeframe ip_nonlocal_bind was
|
ip_lib.set_ip_nonlocal_bind_for_namespace(self.name, 1,
|
||||||
# changed to be a per-namespace attribute. To be backwards
|
root_namespace=True)
|
||||||
# compatible we need to try both if at first we fail.
|
|
||||||
failed = ip_lib.set_ip_nonlocal_bind(
|
|
||||||
value=1, namespace=self.name, log_fail_as_error=False)
|
|
||||||
if failed:
|
|
||||||
LOG.debug('DVR: fip namespace (%s) does not support setting '
|
|
||||||
'net.ipv4.ip_nonlocal_bind, trying in root namespace',
|
|
||||||
self.name)
|
|
||||||
ip_lib.set_ip_nonlocal_bind(value=1)
|
|
||||||
|
|
||||||
# no connection tracking needed in fip namespace
|
# no connection tracking needed in fip namespace
|
||||||
self._iptables_manager.ipv4['raw'].add_rule('PREROUTING',
|
self._iptables_manager.ipv4['raw'].add_rule('PREROUTING',
|
||||||
|
@ -32,7 +32,7 @@ class SnatNamespace(namespaces.Namespace):
|
|||||||
super(SnatNamespace, self).create()
|
super(SnatNamespace, self).create()
|
||||||
# This might be an HA router namespaces and it should not have
|
# This might be an HA router namespaces and it should not have
|
||||||
# ip_nonlocal_bind enabled
|
# ip_nonlocal_bind enabled
|
||||||
ip_lib.set_ip_nonlocal_bind_for_namespace(self.name)
|
ip_lib.set_ip_nonlocal_bind_for_namespace(self.name, 0)
|
||||||
# Set nf_conntrack_tcp_loose to 0 to ensure mid-stream
|
# Set nf_conntrack_tcp_loose to 0 to ensure mid-stream
|
||||||
# TCP conversations aren't taken over by SNAT
|
# TCP conversations aren't taken over by SNAT
|
||||||
cmd = ['net.netfilter.nf_conntrack_tcp_loose=0']
|
cmd = ['net.netfilter.nf_conntrack_tcp_loose=0']
|
||||||
|
@ -57,7 +57,7 @@ class HaRouterNamespace(namespaces.RouterNamespace):
|
|||||||
def create(self):
|
def create(self):
|
||||||
super(HaRouterNamespace, self).create(ipv6_forwarding=False)
|
super(HaRouterNamespace, self).create(ipv6_forwarding=False)
|
||||||
# HA router namespaces should not have ip_nonlocal_bind enabled
|
# HA router namespaces should not have ip_nonlocal_bind enabled
|
||||||
ip_lib.set_ip_nonlocal_bind_for_namespace(self.name)
|
ip_lib.set_ip_nonlocal_bind_for_namespace(self.name, 0)
|
||||||
|
|
||||||
|
|
||||||
class HaRouter(router.RouterInfo):
|
class HaRouter(router.RouterInfo):
|
||||||
|
@ -1486,6 +1486,8 @@ class DeviceManager(object):
|
|||||||
# and added back statically in the call to init_l3() below.
|
# and added back statically in the call to init_l3() below.
|
||||||
if network.namespace:
|
if network.namespace:
|
||||||
ip_lib.IPWrapper().ensure_namespace(network.namespace)
|
ip_lib.IPWrapper().ensure_namespace(network.namespace)
|
||||||
|
ip_lib.set_ip_nonlocal_bind_for_namespace(network.namespace, 1,
|
||||||
|
root_namespace=True)
|
||||||
if ipv6_utils.is_enabled_and_bind_by_default():
|
if ipv6_utils.is_enabled_and_bind_by_default():
|
||||||
self.driver.configure_ipv6_ra(network.namespace, 'default',
|
self.driver.configure_ipv6_ra(network.namespace, 'default',
|
||||||
n_const.ACCEPT_RA_DISABLED)
|
n_const.ACCEPT_RA_DISABLED)
|
||||||
|
@ -1175,18 +1175,25 @@ def set_ip_nonlocal_bind(value, namespace=None, log_fail_as_error=True):
|
|||||||
log_fail_as_error=log_fail_as_error)
|
log_fail_as_error=log_fail_as_error)
|
||||||
|
|
||||||
|
|
||||||
def set_ip_nonlocal_bind_for_namespace(namespace):
|
def set_ip_nonlocal_bind_for_namespace(namespace, value, root_namespace=False):
|
||||||
"""Set ip_nonlocal_bind but don't raise exception on failure."""
|
"""Set ip_nonlocal_bind but don't raise exception on failure."""
|
||||||
failed = set_ip_nonlocal_bind(value=0, namespace=namespace,
|
failed = set_ip_nonlocal_bind(value, namespace=namespace,
|
||||||
log_fail_as_error=False)
|
log_fail_as_error=False)
|
||||||
|
if failed and root_namespace:
|
||||||
|
# Somewhere in the 3.19 kernel timeframe ip_nonlocal_bind was
|
||||||
|
# changed to be a per-namespace attribute. To be backwards
|
||||||
|
# compatible we need to try both if at first we fail.
|
||||||
|
LOG.debug('Namespace (%s) does not support setting %s, '
|
||||||
|
'trying in root namespace', namespace, IP_NONLOCAL_BIND)
|
||||||
|
return set_ip_nonlocal_bind(value)
|
||||||
if failed:
|
if failed:
|
||||||
LOG.warning(
|
LOG.warning(
|
||||||
"%s will not be set to 0 in the root namespace in order to "
|
"%s will not be set to %d in the root namespace in order to "
|
||||||
"not break DVR, which requires this value be set to 1. This "
|
"not break DVR, which requires this value be set to 1. This "
|
||||||
"may introduce a race between moving a floating IP to a "
|
"may introduce a race between moving a floating IP to a "
|
||||||
"different network node, and the peer side getting a "
|
"different network node, and the peer side getting a "
|
||||||
"populated ARP cache for a given floating IP address.",
|
"populated ARP cache for a given floating IP address.",
|
||||||
IP_NONLOCAL_BIND)
|
IP_NONLOCAL_BIND, value)
|
||||||
|
|
||||||
|
|
||||||
def get_ipv6_forwarding(device, namespace=None):
|
def get_ipv6_forwarding(device, namespace=None):
|
||||||
|
@ -62,7 +62,7 @@ defaults
|
|||||||
timeout http-keep-alive 30s
|
timeout http-keep-alive 30s
|
||||||
|
|
||||||
listen listener
|
listen listener
|
||||||
bind 0.0.0.0:%(port)s
|
bind %(host)s:%(port)s
|
||||||
server metadata %(unix_socket_path)s
|
server metadata %(unix_socket_path)s
|
||||||
http-request add-header X-Neutron-%(res_type)s-ID %(res_id)s
|
http-request add-header X-Neutron-%(res_type)s-ID %(res_id)s
|
||||||
"""
|
"""
|
||||||
@ -73,13 +73,14 @@ class InvalidUserOrGroupException(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class HaproxyConfigurator(object):
|
class HaproxyConfigurator(object):
|
||||||
def __init__(self, network_id, router_id, unix_socket_path, port, user,
|
def __init__(self, network_id, router_id, unix_socket_path, host, port,
|
||||||
group, state_path, pid_file):
|
user, group, state_path, pid_file):
|
||||||
self.network_id = network_id
|
self.network_id = network_id
|
||||||
self.router_id = router_id
|
self.router_id = router_id
|
||||||
if network_id is None and router_id is None:
|
if network_id is None and router_id is None:
|
||||||
raise exceptions.NetworkIdOrRouterIdRequiredError()
|
raise exceptions.NetworkIdOrRouterIdRequiredError()
|
||||||
|
|
||||||
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.user = user
|
self.user = user
|
||||||
self.group = group
|
self.group = group
|
||||||
@ -117,6 +118,7 @@ class HaproxyConfigurator(object):
|
|||||||
_("Invalid group/gid: '%s'") % self.group)
|
_("Invalid group/gid: '%s'") % self.group)
|
||||||
|
|
||||||
cfg_info = {
|
cfg_info = {
|
||||||
|
'host': self.host,
|
||||||
'port': self.port,
|
'port': self.port,
|
||||||
'unix_socket_path': self.unix_socket_path,
|
'unix_socket_path': self.unix_socket_path,
|
||||||
'user': username,
|
'user': username,
|
||||||
@ -210,8 +212,8 @@ class MetadataDriver(object):
|
|||||||
return user, group
|
return user, group
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_metadata_proxy_callback(cls, port, conf, network_id=None,
|
def _get_metadata_proxy_callback(cls, bind_address, port, conf,
|
||||||
router_id=None):
|
network_id=None, router_id=None):
|
||||||
def callback(pid_file):
|
def callback(pid_file):
|
||||||
metadata_proxy_socket = conf.metadata_proxy_socket
|
metadata_proxy_socket = conf.metadata_proxy_socket
|
||||||
user, group = (
|
user, group = (
|
||||||
@ -219,6 +221,7 @@ class MetadataDriver(object):
|
|||||||
haproxy = HaproxyConfigurator(network_id,
|
haproxy = HaproxyConfigurator(network_id,
|
||||||
router_id,
|
router_id,
|
||||||
metadata_proxy_socket,
|
metadata_proxy_socket,
|
||||||
|
bind_address,
|
||||||
port,
|
port,
|
||||||
user,
|
user,
|
||||||
group,
|
group,
|
||||||
@ -233,10 +236,12 @@ class MetadataDriver(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def spawn_monitored_metadata_proxy(cls, monitor, ns_name, port, conf,
|
def spawn_monitored_metadata_proxy(cls, monitor, ns_name, port, conf,
|
||||||
network_id=None, router_id=None):
|
bind_address="0.0.0.0", network_id=None,
|
||||||
|
router_id=None):
|
||||||
uuid = network_id or router_id
|
uuid = network_id or router_id
|
||||||
callback = cls._get_metadata_proxy_callback(
|
callback = cls._get_metadata_proxy_callback(
|
||||||
port, conf, network_id=network_id, router_id=router_id)
|
bind_address, port, conf, network_id=network_id,
|
||||||
|
router_id=router_id)
|
||||||
pm = cls._get_metadata_proxy_process_manager(uuid, conf,
|
pm = cls._get_metadata_proxy_process_manager(uuid, conf,
|
||||||
ns_name=ns_name,
|
ns_name=ns_name,
|
||||||
callback=callback)
|
callback=callback)
|
||||||
@ -270,7 +275,7 @@ def after_router_added(resource, event, l3_agent, **kwargs):
|
|||||||
router = kwargs['router']
|
router = kwargs['router']
|
||||||
proxy = l3_agent.metadata_driver
|
proxy = l3_agent.metadata_driver
|
||||||
for c, r in proxy.metadata_filter_rules(proxy.metadata_port,
|
for c, r in proxy.metadata_filter_rules(proxy.metadata_port,
|
||||||
proxy.metadata_access_mark):
|
proxy.metadata_access_mark):
|
||||||
router.iptables_manager.ipv4['filter'].add_rule(c, r)
|
router.iptables_manager.ipv4['filter'].add_rule(c, r)
|
||||||
for c, r in proxy.metadata_nat_rules(proxy.metadata_port):
|
for c, r in proxy.metadata_nat_rules(proxy.metadata_port):
|
||||||
router.iptables_manager.ipv4['nat'].add_rule(c, r)
|
router.iptables_manager.ipv4['nat'].add_rule(c, r)
|
||||||
|
@ -221,6 +221,9 @@ fake_down_network = dhcp.NetModel(
|
|||||||
|
|
||||||
|
|
||||||
class TestDhcpAgent(base.BaseTestCase):
|
class TestDhcpAgent(base.BaseTestCase):
|
||||||
|
|
||||||
|
METADATA_DEFAULT_IP = dhcp.METADATA_DEFAULT_IP
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestDhcpAgent, self).setUp()
|
super(TestDhcpAgent, self).setUp()
|
||||||
entry.register_options(cfg.CONF)
|
entry.register_options(cfg.CONF)
|
||||||
@ -495,6 +498,7 @@ class TestDhcpAgent(base.BaseTestCase):
|
|||||||
dhcp.configure_dhcp_for_network(fake_network)
|
dhcp.configure_dhcp_for_network(fake_network)
|
||||||
md_cls.spawn_monitored_metadata_proxy.assert_called_once_with(
|
md_cls.spawn_monitored_metadata_proxy.assert_called_once_with(
|
||||||
mock.ANY, mock.ANY, mock.ANY, mock.ANY,
|
mock.ANY, mock.ANY, mock.ANY, mock.ANY,
|
||||||
|
bind_address=self.METADATA_DEFAULT_IP,
|
||||||
network_id=fake_network.id)
|
network_id=fake_network.id)
|
||||||
dhcp.disable_dhcp_helper(fake_network.id)
|
dhcp.disable_dhcp_helper(fake_network.id)
|
||||||
md_cls.destroy_monitored_metadata_proxy.assert_called_once_with(
|
md_cls.destroy_monitored_metadata_proxy.assert_called_once_with(
|
||||||
@ -890,10 +894,12 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
|||||||
'.spawn_monitored_metadata_proxy')
|
'.spawn_monitored_metadata_proxy')
|
||||||
with mock.patch(method_path) as spawn:
|
with mock.patch(method_path) as spawn:
|
||||||
self.dhcp.enable_isolated_metadata_proxy(network)
|
self.dhcp.enable_isolated_metadata_proxy(network)
|
||||||
|
metadata_ip = dhcp.METADATA_DEFAULT_IP
|
||||||
spawn.assert_called_once_with(self.dhcp._process_monitor,
|
spawn.assert_called_once_with(self.dhcp._process_monitor,
|
||||||
network.namespace,
|
network.namespace,
|
||||||
dhcp.METADATA_PORT,
|
dhcp.METADATA_PORT,
|
||||||
cfg.CONF,
|
cfg.CONF,
|
||||||
|
bind_address=metadata_ip,
|
||||||
router_id='forzanapoli')
|
router_id='forzanapoli')
|
||||||
|
|
||||||
def test_enable_isolated_metadata_proxy_with_metadata_network(self):
|
def test_enable_isolated_metadata_proxy_with_metadata_network(self):
|
||||||
|
@ -1712,7 +1712,7 @@ class TestSetIpNonlocalBindForHaNamespace(base.BaseTestCase):
|
|||||||
def test_setting_failure(self):
|
def test_setting_failure(self):
|
||||||
"""Make sure message is formatted correctly."""
|
"""Make sure message is formatted correctly."""
|
||||||
with mock.patch.object(ip_lib, 'set_ip_nonlocal_bind', return_value=1):
|
with mock.patch.object(ip_lib, 'set_ip_nonlocal_bind', return_value=1):
|
||||||
ip_lib.set_ip_nonlocal_bind_for_namespace('foo')
|
ip_lib.set_ip_nonlocal_bind_for_namespace('foo', value=1)
|
||||||
|
|
||||||
|
|
||||||
class TestSysctl(base.BaseTestCase):
|
class TestSysctl(base.BaseTestCase):
|
||||||
|
@ -64,6 +64,7 @@ class TestMetadataDriverProcess(base.BaseTestCase):
|
|||||||
|
|
||||||
EUNAME = 'neutron'
|
EUNAME = 'neutron'
|
||||||
EGNAME = 'neutron'
|
EGNAME = 'neutron'
|
||||||
|
METADATA_DEFAULT_IP = '169.254.169.254'
|
||||||
METADATA_PORT = 8080
|
METADATA_PORT = 8080
|
||||||
METADATA_SOCKET = '/socket/path'
|
METADATA_SOCKET = '/socket/path'
|
||||||
PIDFILE = 'pidfile'
|
PIDFILE = 'pidfile'
|
||||||
@ -146,6 +147,7 @@ class TestMetadataDriverProcess(base.BaseTestCase):
|
|||||||
router_ns,
|
router_ns,
|
||||||
self.METADATA_PORT,
|
self.METADATA_PORT,
|
||||||
agent.conf,
|
agent.conf,
|
||||||
|
bind_address=self.METADATA_DEFAULT_IP,
|
||||||
router_id=router_id)
|
router_id=router_id)
|
||||||
|
|
||||||
netns_execute_args = [
|
netns_execute_args = [
|
||||||
@ -157,6 +159,7 @@ class TestMetadataDriverProcess(base.BaseTestCase):
|
|||||||
cfg_contents = metadata_driver._HAPROXY_CONFIG_TEMPLATE % {
|
cfg_contents = metadata_driver._HAPROXY_CONFIG_TEMPLATE % {
|
||||||
'user': self.EUNAME,
|
'user': self.EUNAME,
|
||||||
'group': self.EGNAME,
|
'group': self.EGNAME,
|
||||||
|
'host': self.METADATA_DEFAULT_IP,
|
||||||
'port': self.METADATA_PORT,
|
'port': self.METADATA_PORT,
|
||||||
'unix_socket_path': self.METADATA_SOCKET,
|
'unix_socket_path': self.METADATA_SOCKET,
|
||||||
'res_type': 'Router',
|
'res_type': 'Router',
|
||||||
@ -178,7 +181,8 @@ class TestMetadataDriverProcess(base.BaseTestCase):
|
|||||||
|
|
||||||
def test_create_config_file_wrong_user(self):
|
def test_create_config_file_wrong_user(self):
|
||||||
with mock.patch('pwd.getpwnam', side_effect=KeyError):
|
with mock.patch('pwd.getpwnam', side_effect=KeyError):
|
||||||
config = metadata_driver.HaproxyConfigurator(_uuid(), mock.ANY,
|
config = metadata_driver.HaproxyConfigurator(_uuid(),
|
||||||
|
mock.ANY, mock.ANY,
|
||||||
mock.ANY, mock.ANY,
|
mock.ANY, mock.ANY,
|
||||||
self.EUNAME,
|
self.EUNAME,
|
||||||
self.EGNAME,
|
self.EGNAME,
|
||||||
@ -190,7 +194,8 @@ class TestMetadataDriverProcess(base.BaseTestCase):
|
|||||||
with mock.patch('grp.getgrnam', side_effect=KeyError),\
|
with mock.patch('grp.getgrnam', side_effect=KeyError),\
|
||||||
mock.patch('pwd.getpwnam',
|
mock.patch('pwd.getpwnam',
|
||||||
return_value=test_utils.FakeUser(self.EUNAME)):
|
return_value=test_utils.FakeUser(self.EUNAME)):
|
||||||
config = metadata_driver.HaproxyConfigurator(_uuid(), mock.ANY,
|
config = metadata_driver.HaproxyConfigurator(_uuid(),
|
||||||
|
mock.ANY, mock.ANY,
|
||||||
mock.ANY, mock.ANY,
|
mock.ANY, mock.ANY,
|
||||||
self.EUNAME,
|
self.EUNAME,
|
||||||
self.EGNAME,
|
self.EGNAME,
|
||||||
|
Loading…
Reference in New Issue
Block a user