metadata-ipv6: Router namespace
We push a v6 host route to make the guest send its metadata requests in the direction of our router. We redirect it to haproxy which mangles the headers and sends the request along to metadata-agent. Apparently the supported list of dhcp options for dhcpv6 is quite short in dnsmasq (cf. dnsmasq --help dhcp6) - not including anything like classless-static-route for dhcpv4. So we must rely solely on radvd to push host routes to the guest. Metadata access over IPv6 is supposed to work both on dual-stack and v6-only networks. The following v6 subnet modes are supposed to work: --ipv6-ra-mode slaac --ipv6-address-mode slaac --ipv6-ra-mode dhcpv6-stateless --ipv6-address-mode dhcpv6-stateless --ipv6-ra-mode dhcpv6-stateful --ipv6-address-mode dhcpv6-stateful Change-Id: I28f2914b1b67659af2db7240eae730ac43daccd2 Partial-Bug: #1460177
This commit is contained in:
parent
a0b18d553d
commit
a1f4ee3ade
@ -20,6 +20,7 @@ from neutron_lib import constants as lib_constants
|
||||
from neutron_lib.exceptions import l3 as l3_exc
|
||||
from neutron_lib.utils import helpers
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import netutils
|
||||
from pyroute2.netlink import exceptions as pyroute2_exc
|
||||
|
||||
from neutron._i18n import _
|
||||
@ -1088,6 +1089,18 @@ class RouterInfo(BaseRouterInfo):
|
||||
self.iptables_manager.ipv4['mangle'].add_rule(
|
||||
'PREROUTING', mark_metadata_for_internal_interfaces)
|
||||
|
||||
if netutils.is_ipv6_enabled():
|
||||
mark_metadata_v6_for_internal_interfaces = (
|
||||
'-d fe80::a9fe:a9fe/128 '
|
||||
'-i %(interface_name)s '
|
||||
'-p tcp -m tcp --dport 80 '
|
||||
'-j MARK --set-xmark %(value)s/%(mask)s' %
|
||||
{'interface_name': INTERNAL_DEV_PREFIX + '+',
|
||||
'value': self.agent_conf.metadata_access_mark,
|
||||
'mask': lib_constants.ROUTER_MARK_MASK})
|
||||
self.iptables_manager.ipv6['mangle'].add_rule(
|
||||
'PREROUTING', mark_metadata_v6_for_internal_interfaces)
|
||||
|
||||
def _get_port_devicename_scopemark(self, ports, name_generator):
|
||||
devicename_scopemark = {lib_constants.IP_VERSION_4: dict(),
|
||||
lib_constants.IP_VERSION_6: dict()}
|
||||
|
@ -372,9 +372,12 @@ class IptablesManager(object):
|
||||
def initialize_nat_table(self):
|
||||
self.ipv4.update(
|
||||
{'nat': IptablesTable(binary_name=self.wrap_name)})
|
||||
self.ipv6.update(
|
||||
{'nat': IptablesTable(binary_name=self.wrap_name)})
|
||||
|
||||
builtin_chains = {
|
||||
4: {'nat': ['PREROUTING', 'OUTPUT', 'POSTROUTING']}}
|
||||
4: {'nat': ['PREROUTING', 'OUTPUT', 'POSTROUTING']},
|
||||
6: {'nat': ['PREROUTING']}}
|
||||
self._configure_builtin_chains(builtin_chains)
|
||||
|
||||
# Add a neutron-postrouting-bottom chain. It's intended to be
|
||||
|
@ -73,6 +73,9 @@ CONFIG_TEMPLATE = jinja2.Template("""interface {{ interface_name }}
|
||||
AdvAutonomous off;
|
||||
};
|
||||
{% endfor %}
|
||||
|
||||
route fe80::a9fe:a9fe/128 {
|
||||
};
|
||||
};
|
||||
""")
|
||||
|
||||
|
@ -16,6 +16,8 @@ import hashlib
|
||||
import hmac
|
||||
import urllib
|
||||
|
||||
import netaddr
|
||||
|
||||
from neutron_lib.agent import topics
|
||||
from neutron_lib import constants
|
||||
from neutron_lib import context
|
||||
@ -168,7 +170,7 @@ class MetadataProxyHandler(object):
|
||||
skip_cache=skip_cache)
|
||||
|
||||
def _get_instance_and_tenant_id(self, req, skip_cache=False):
|
||||
remote_address = req.headers.get('X-Forwarded-For')
|
||||
forwarded_for = req.headers.get('X-Forwarded-For')
|
||||
network_id = req.headers.get('X-Neutron-Network-ID')
|
||||
router_id = req.headers.get('X-Neutron-Router-ID')
|
||||
|
||||
@ -179,12 +181,19 @@ class MetadataProxyHandler(object):
|
||||
"dropping")
|
||||
return None, None
|
||||
|
||||
ports = self._get_ports(remote_address, network_id, router_id,
|
||||
remote_ip = netaddr.IPAddress(forwarded_for)
|
||||
if remote_ip.version == constants.IP_VERSION_6:
|
||||
if remote_ip.is_ipv4_mapped():
|
||||
# When haproxy listens on v4 AND v6 then it inserts ipv4
|
||||
# addresses as ipv4-mapped v6 addresses into X-Forwarded-For.
|
||||
forwarded_for = str(remote_ip.ipv4())
|
||||
|
||||
ports = self._get_ports(forwarded_for, network_id, router_id,
|
||||
skip_cache=skip_cache)
|
||||
LOG.debug("Gotten ports for remote_address %(remote_address)s, "
|
||||
"network_id %(network_id)s, router_id %(router_id)s are: "
|
||||
"%(ports)s",
|
||||
{"remote_address": remote_address,
|
||||
{"remote_address": forwarded_for,
|
||||
"network_id": network_id,
|
||||
"router_id": router_id,
|
||||
"ports": ports})
|
||||
|
@ -25,10 +25,12 @@ from neutron_lib import constants
|
||||
from neutron_lib import exceptions
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import netutils
|
||||
|
||||
from neutron._i18n import _
|
||||
from neutron.agent.l3 import ha_router
|
||||
from neutron.agent.l3 import namespaces
|
||||
from neutron.agent.linux import dhcp
|
||||
from neutron.agent.linux import external_process
|
||||
from neutron.agent.linux import ip_lib
|
||||
|
||||
@ -205,12 +207,14 @@ class MetadataDriver(object):
|
||||
'-j DROP' % port)]
|
||||
|
||||
@classmethod
|
||||
def metadata_nat_rules(cls, port):
|
||||
return [('PREROUTING', '-d 169.254.169.254/32 '
|
||||
def metadata_nat_rules(
|
||||
cls, port, metadata_address=(dhcp.METADATA_DEFAULT_IP + '/32')):
|
||||
return [('PREROUTING', '-d %(metadata_address)s '
|
||||
'-i %(interface_name)s '
|
||||
'-p tcp -m tcp --dport 80 -j REDIRECT '
|
||||
'--to-ports %(port)s' %
|
||||
{'interface_name': namespaces.INTERNAL_DEV_PREFIX + '+',
|
||||
{'metadata_address': metadata_address,
|
||||
'interface_name': namespaces.INTERNAL_DEV_PREFIX + '+',
|
||||
'port': port})]
|
||||
|
||||
@classmethod
|
||||
@ -297,20 +301,34 @@ class MetadataDriver(object):
|
||||
def after_router_added(resource, event, l3_agent, **kwargs):
|
||||
router = kwargs['router']
|
||||
proxy = l3_agent.metadata_driver
|
||||
ipv6_enabled = netutils.is_ipv6_enabled()
|
||||
for c, r in proxy.metadata_filter_rules(proxy.metadata_port,
|
||||
proxy.metadata_access_mark):
|
||||
router.iptables_manager.ipv4['filter'].add_rule(c, r)
|
||||
if ipv6_enabled:
|
||||
for c, r in proxy.metadata_filter_rules(proxy.metadata_port,
|
||||
proxy.metadata_access_mark):
|
||||
router.iptables_manager.ipv6['filter'].add_rule(c, r)
|
||||
for c, r in proxy.metadata_nat_rules(proxy.metadata_port):
|
||||
router.iptables_manager.ipv4['nat'].add_rule(c, r)
|
||||
if ipv6_enabled:
|
||||
for c, r in proxy.metadata_nat_rules(
|
||||
proxy.metadata_port,
|
||||
metadata_address=(dhcp.METADATA_V6_IP + '/128')):
|
||||
router.iptables_manager.ipv6['nat'].add_rule(c, r)
|
||||
router.iptables_manager.apply()
|
||||
|
||||
if not isinstance(router, ha_router.HaRouter):
|
||||
spawn_kwargs = {}
|
||||
if ipv6_enabled:
|
||||
spawn_kwargs['bind_address'] = '::'
|
||||
proxy.spawn_monitored_metadata_proxy(
|
||||
l3_agent.process_monitor,
|
||||
router.ns_name,
|
||||
proxy.metadata_port,
|
||||
l3_agent.conf,
|
||||
router_id=router.router_id)
|
||||
router_id=router.router_id,
|
||||
**spawn_kwargs)
|
||||
|
||||
|
||||
def after_router_updated(resource, event, l3_agent, **kwargs):
|
||||
@ -318,12 +336,16 @@ def after_router_updated(resource, event, l3_agent, **kwargs):
|
||||
proxy = l3_agent.metadata_driver
|
||||
if (not proxy.monitors.get(router.router_id) and
|
||||
not isinstance(router, ha_router.HaRouter)):
|
||||
spawn_kwargs = {}
|
||||
if netutils.is_ipv6_enabled():
|
||||
spawn_kwargs['bind_address'] = '::'
|
||||
proxy.spawn_monitored_metadata_proxy(
|
||||
l3_agent.process_monitor,
|
||||
router.ns_name,
|
||||
proxy.metadata_port,
|
||||
l3_agent.conf,
|
||||
router_id=router.router_id)
|
||||
router_id=router.router_id,
|
||||
**spawn_kwargs)
|
||||
|
||||
|
||||
def before_router_removed(resource, event, l3_agent, payload=None):
|
||||
|
@ -2664,28 +2664,31 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
'distributed': False}
|
||||
driver = metadata_driver.MetadataDriver
|
||||
with mock.patch.object(
|
||||
driver, 'destroy_monitored_metadata_proxy') as destroy_proxy:
|
||||
with mock.patch.object(
|
||||
driver, 'spawn_monitored_metadata_proxy') as spawn_proxy:
|
||||
agent._process_added_router(router)
|
||||
if enableflag:
|
||||
spawn_proxy.assert_called_with(
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
self.conf.metadata_port,
|
||||
mock.ANY,
|
||||
router_id=router_id
|
||||
)
|
||||
else:
|
||||
self.assertFalse(spawn_proxy.call_count)
|
||||
agent._safe_router_removed(router_id)
|
||||
if enableflag:
|
||||
destroy_proxy.assert_called_with(mock.ANY,
|
||||
router_id,
|
||||
mock.ANY,
|
||||
'qrouter-' + router_id)
|
||||
else:
|
||||
self.assertFalse(destroy_proxy.call_count)
|
||||
driver, 'destroy_monitored_metadata_proxy') as destroy_proxy, \
|
||||
mock.patch.object(
|
||||
driver, 'spawn_monitored_metadata_proxy') as spawn_proxy, \
|
||||
mock.patch.object(netutils, 'is_ipv6_enabled') as ipv6_mock:
|
||||
ipv6_mock.return_value = True
|
||||
agent._process_added_router(router)
|
||||
if enableflag:
|
||||
spawn_proxy.assert_called_with(
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
self.conf.metadata_port,
|
||||
mock.ANY,
|
||||
router_id=router_id,
|
||||
bind_address='::',
|
||||
)
|
||||
else:
|
||||
self.assertFalse(spawn_proxy.call_count)
|
||||
agent._safe_router_removed(router_id)
|
||||
if enableflag:
|
||||
destroy_proxy.assert_called_with(mock.ANY,
|
||||
router_id,
|
||||
mock.ANY,
|
||||
'qrouter-' + router_id)
|
||||
else:
|
||||
self.assertFalse(destroy_proxy.call_count)
|
||||
|
||||
def test_enable_metadata_proxy(self):
|
||||
self._configure_metadata_proxy()
|
||||
|
@ -314,6 +314,16 @@ def _generate_mangle_dump_v6(iptables_args):
|
||||
'# Completed by iptables_manager\n' % iptables_args)
|
||||
|
||||
|
||||
def _generate_nat_dump_v6(iptables_args):
|
||||
return ('# Generated by iptables_manager\n'
|
||||
'*nat\n'
|
||||
':PREROUTING - [0:0]\n'
|
||||
':%(bn)s-PREROUTING - [0:0]\n'
|
||||
'-I PREROUTING 1 -j %(bn)s-PREROUTING\n'
|
||||
'COMMIT\n'
|
||||
'# Completed by iptables_manager\n' % iptables_args)
|
||||
|
||||
|
||||
def _generate_raw_dump(iptables_args):
|
||||
return ('# Generated by iptables_manager\n'
|
||||
'*raw\n'
|
||||
@ -366,6 +376,7 @@ def _generate_raw_restore_dump(iptables_args):
|
||||
|
||||
MANGLE_DUMP = _generate_mangle_dump(IPTABLES_ARG)
|
||||
MANGLE_DUMP_V6 = _generate_mangle_dump_v6(IPTABLES_ARG)
|
||||
NAT_DUMP_V6 = _generate_nat_dump_v6(IPTABLES_ARG)
|
||||
RAW_DUMP = _generate_raw_dump(IPTABLES_ARG)
|
||||
MANGLE_RESTORE_DUMP = _generate_mangle_restore_dump(IPTABLES_ARG)
|
||||
RAW_RESTORE_DUMP = _generate_raw_restore_dump(IPTABLES_ARG)
|
||||
@ -468,7 +479,7 @@ class IptablesManagerStateFulTestCase(IptablesManagerBaseTestCase):
|
||||
if self.use_ipv6:
|
||||
self._extend_with_ip6tables_filter(
|
||||
expected_calls_and_values,
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + RAW_DUMP)
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + NAT_DUMP_V6 + RAW_DUMP)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
@ -512,7 +523,7 @@ class IptablesManagerStateFulTestCase(IptablesManagerBaseTestCase):
|
||||
if self.use_ipv6:
|
||||
self._extend_with_ip6tables_filter(
|
||||
expected_calls_and_values,
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + raw_dump)
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + NAT_DUMP_V6 + raw_dump)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
@ -588,7 +599,7 @@ class IptablesManagerStateFulTestCase(IptablesManagerBaseTestCase):
|
||||
if self.use_ipv6:
|
||||
self._extend_with_ip6tables_filter(
|
||||
expected_calls_and_values,
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + raw_dump)
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + NAT_DUMP_V6 + raw_dump)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
@ -654,7 +665,7 @@ class IptablesManagerStateFulTestCase(IptablesManagerBaseTestCase):
|
||||
if self.use_ipv6:
|
||||
self._extend_with_ip6tables_filter(
|
||||
expected_calls_and_values,
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + RAW_DUMP)
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + NAT_DUMP_V6 + RAW_DUMP)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
@ -725,7 +736,7 @@ class IptablesManagerStateFulTestCase(IptablesManagerBaseTestCase):
|
||||
if self.use_ipv6:
|
||||
self._extend_with_ip6tables_filter(
|
||||
expected_calls_and_values,
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + raw_dump)
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + NAT_DUMP_V6 + raw_dump)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
@ -787,7 +798,7 @@ class IptablesManagerStateFulTestCase(IptablesManagerBaseTestCase):
|
||||
if self.use_ipv6:
|
||||
self._extend_with_ip6tables_filter(
|
||||
expected_calls_and_values,
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + RAW_DUMP)
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + NAT_DUMP_V6 + RAW_DUMP)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
@ -1164,7 +1175,7 @@ class IptablesManagerStateFulTestCase(IptablesManagerBaseTestCase):
|
||||
if self.use_ipv6:
|
||||
self._extend_with_ip6tables_filter_end(
|
||||
expected_calls_and_values,
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + RAW_DUMP)
|
||||
FILTER_DUMP + MANGLE_DUMP_V6 + NAT_DUMP_V6 + RAW_DUMP)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
@ -1227,9 +1238,10 @@ class IptablesManagerStateFulTestCaseCustomBinaryName(
|
||||
]
|
||||
if self.use_ipv6:
|
||||
mangle_dump_v6 = _generate_mangle_dump_v6(iptables_args)
|
||||
nat_dump_v6 = _generate_nat_dump_v6(iptables_args)
|
||||
self._extend_with_ip6tables_filter(
|
||||
expected_calls_and_values,
|
||||
filter_dump_ipv6 + mangle_dump_v6 + raw_dump)
|
||||
filter_dump_ipv6 + mangle_dump_v6 + nat_dump_v6 + raw_dump)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
@ -1294,9 +1306,10 @@ class IptablesManagerStateFulTestCaseEmptyCustomBinaryName(
|
||||
]
|
||||
if self.use_ipv6:
|
||||
mangle_dump_v6 = _generate_mangle_dump_v6(iptables_args)
|
||||
nat_dump_v6 = _generate_nat_dump_v6(iptables_args)
|
||||
self._extend_with_ip6tables_filter(
|
||||
expected_calls_and_values,
|
||||
filter_dump + mangle_dump_v6 + raw_dump)
|
||||
filter_dump + mangle_dump_v6 + nat_dump_v6 + raw_dump)
|
||||
|
||||
tools.setup_mock_calls(self.execute, expected_calls_and_values)
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
from neutron_lib import constants as n_const
|
||||
import testtools
|
||||
import webob
|
||||
@ -102,6 +103,7 @@ class TestMetadataProxyHandlerRpc(TestMetadataProxyHandlerBase):
|
||||
self.assertEqual(expected, ports)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class _TestMetadataProxyHandlerCacheMixin(object):
|
||||
|
||||
def test_call(self):
|
||||
@ -242,8 +244,8 @@ class _TestMetadataProxyHandlerCacheMixin(object):
|
||||
self.assertRaises(TypeError, self.handler._get_ports, 'remote_address')
|
||||
|
||||
def _get_instance_and_tenant_id_helper(self, headers, list_ports_retval,
|
||||
networks=None, router_id=None):
|
||||
remote_address = '192.168.1.1'
|
||||
networks=None, router_id=None,
|
||||
remote_address='192.168.1.1'):
|
||||
headers['X-Forwarded-For'] = remote_address
|
||||
req = mock.Mock(headers=headers)
|
||||
|
||||
@ -279,7 +281,8 @@ class _TestMetadataProxyHandlerCacheMixin(object):
|
||||
|
||||
return (instance_id, tenant_id)
|
||||
|
||||
def test_get_instance_id_router_id(self):
|
||||
@ddt.data('192.168.1.1', '::ffff:192.168.1.1')
|
||||
def test_get_instance_id_router_id(self, remote_address):
|
||||
router_id = 'the_id'
|
||||
headers = {
|
||||
'X-Neutron-Router-ID': router_id
|
||||
@ -294,12 +297,13 @@ class _TestMetadataProxyHandlerCacheMixin(object):
|
||||
|
||||
self.assertEqual(
|
||||
('device_id', 'tenant_id'),
|
||||
self._get_instance_and_tenant_id_helper(headers, ports,
|
||||
networks=networks,
|
||||
router_id=router_id)
|
||||
self._get_instance_and_tenant_id_helper(
|
||||
headers, ports, networks=networks, router_id=router_id,
|
||||
remote_address=remote_address)
|
||||
)
|
||||
|
||||
def test_get_instance_id_router_id_no_match(self):
|
||||
@ddt.data('192.168.1.1', '::ffff:192.168.1.1')
|
||||
def test_get_instance_id_router_id_no_match(self, remote_address):
|
||||
router_id = 'the_id'
|
||||
headers = {
|
||||
'X-Neutron-Router-ID': router_id
|
||||
@ -312,12 +316,13 @@ class _TestMetadataProxyHandlerCacheMixin(object):
|
||||
]
|
||||
self.assertEqual(
|
||||
(None, None),
|
||||
self._get_instance_and_tenant_id_helper(headers, ports,
|
||||
networks=networks,
|
||||
router_id=router_id)
|
||||
self._get_instance_and_tenant_id_helper(
|
||||
headers, ports, networks=networks, router_id=router_id,
|
||||
remote_address=remote_address)
|
||||
)
|
||||
|
||||
def test_get_instance_id_network_id(self):
|
||||
@ddt.data('192.168.1.1', '::ffff:192.168.1.1')
|
||||
def test_get_instance_id_network_id(self, remote_address):
|
||||
network_id = 'the_id'
|
||||
headers = {
|
||||
'X-Neutron-Network-ID': network_id
|
||||
@ -331,11 +336,13 @@ class _TestMetadataProxyHandlerCacheMixin(object):
|
||||
|
||||
self.assertEqual(
|
||||
('device_id', 'tenant_id'),
|
||||
self._get_instance_and_tenant_id_helper(headers, ports,
|
||||
networks=('the_id',))
|
||||
self._get_instance_and_tenant_id_helper(
|
||||
headers, ports, networks=('the_id',),
|
||||
remote_address=remote_address)
|
||||
)
|
||||
|
||||
def test_get_instance_id_network_id_no_match(self):
|
||||
@ddt.data('192.168.1.1', '::ffff:192.168.1.1')
|
||||
def test_get_instance_id_network_id_no_match(self, remote_address):
|
||||
network_id = 'the_id'
|
||||
headers = {
|
||||
'X-Neutron-Network-ID': network_id
|
||||
@ -345,11 +352,14 @@ class _TestMetadataProxyHandlerCacheMixin(object):
|
||||
|
||||
self.assertEqual(
|
||||
(None, None),
|
||||
self._get_instance_and_tenant_id_helper(headers, ports,
|
||||
networks=('the_id',))
|
||||
self._get_instance_and_tenant_id_helper(
|
||||
headers, ports, networks=('the_id',),
|
||||
remote_address=remote_address)
|
||||
)
|
||||
|
||||
def test_get_instance_id_network_id_and_router_id_invalid(self):
|
||||
@ddt.data('192.168.1.1', '::ffff:192.168.1.1')
|
||||
def test_get_instance_id_network_id_and_router_id_invalid(
|
||||
self, remote_address):
|
||||
network_id = 'the_nid'
|
||||
router_id = 'the_rid'
|
||||
headers = {
|
||||
@ -366,9 +376,9 @@ class _TestMetadataProxyHandlerCacheMixin(object):
|
||||
|
||||
self.assertEqual(
|
||||
(None, None),
|
||||
self._get_instance_and_tenant_id_helper(headers, ports,
|
||||
networks=(network_id,),
|
||||
router_id=router_id)
|
||||
self._get_instance_and_tenant_id_helper(
|
||||
headers, ports, networks=(network_id,), router_id=router_id,
|
||||
remote_address=remote_address)
|
||||
)
|
||||
|
||||
def _proxy_request_test_helper(self, response_code=200, method='GET'):
|
||||
|
@ -44,6 +44,14 @@ class TestMetadataDriverRules(base.BaseTestCase):
|
||||
[rules],
|
||||
metadata_driver.MetadataDriver.metadata_nat_rules(9697))
|
||||
|
||||
def test_metadata_nat_rules_ipv6(self):
|
||||
rules = ('PREROUTING', '-d fe80::a9fe:a9fe/128 -i qr-+ '
|
||||
'-p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697')
|
||||
self.assertEqual(
|
||||
[rules],
|
||||
metadata_driver.MetadataDriver.metadata_nat_rules(
|
||||
9697, metadata_address='fe80::a9fe:a9fe/128'))
|
||||
|
||||
def test_metadata_filter_rules(self):
|
||||
rules = [('INPUT', '-m mark --mark 0x1/%s -j ACCEPT' %
|
||||
constants.ROUTER_MARK_MASK),
|
||||
|
Loading…
x
Reference in New Issue
Block a user