Merge "Support for IPv6 RDNSS Option in Router Advts"

This commit is contained in:
Jenkins 2015-12-02 23:18:41 +00:00 committed by Gerrit Code Review
commit 7869954dd3
5 changed files with 36 additions and 4 deletions

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from itertools import chain as iter_chain
import jinja2
import netaddr
from oslo_config import cfg
@ -27,6 +28,8 @@ from neutron.common import utils as common_utils
RADVD_SERVICE_NAME = 'radvd'
RADVD_SERVICE_CMD = 'radvd'
# We can configure max of 3 DNS servers in radvd RDNSS section.
MAX_RDNSS_ENTRIES = 3
LOG = logging.getLogger(__name__)
@ -52,6 +55,10 @@ CONFIG_TEMPLATE = jinja2.Template("""interface {{ interface_name }}
AdvManagedFlag on;
{% endif %}
{% if dns_servers %}
RDNSS {% for dns in dns_servers %} {{ dns }} {% endfor %} {};
{% endif %}
{% for prefix in prefixes %}
prefix {{ prefix }}
{
@ -89,10 +96,15 @@ class DaemonMonitor(object):
subnet['ipv6_ra_mode'] == constants.IPV6_SLAAC or
subnet['ipv6_ra_mode'] == constants.DHCPV6_STATELESS]
interface_name = self._dev_name_helper(p['id'])
slaac_subnets = [subnet for subnet in v6_subnets if
subnet['ipv6_ra_mode'] == constants.IPV6_SLAAC]
dns_servers = list(iter_chain(*[subnet['dns_nameservers'] for
subnet in slaac_subnets if subnet.get('dns_nameservers')]))
buf.write('%s' % CONFIG_TEMPLATE.render(
ra_modes=list(ra_modes),
interface_name=interface_name,
prefixes=auto_config_prefixes,
dns_servers=dns_servers[0:MAX_RDNSS_ENTRIES],
constants=constants))
common_utils.replace_file(radvd_conf, buf.getvalue())

View File

@ -1219,7 +1219,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase):
return {}
filters = {'network_id': [id for id in network_ids]}
fields = ['id', 'cidr', 'gateway_ip',
fields = ['id', 'cidr', 'gateway_ip', 'dns_nameservers',
'network_id', 'ipv6_ra_mode', 'subnetpool_id']
subnets_by_network = dict((id, []) for id in network_ids)
@ -1250,6 +1250,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase):
subnet_info = {'id': subnet['id'],
'cidr': subnet['cidr'],
'gateway_ip': subnet['gateway_ip'],
'dns_nameservers': subnet['dns_nameservers'],
'ipv6_ra_mode': subnet['ipv6_ra_mode'],
'subnetpool_id': subnet['subnetpool_id']}
for fixed_ip in port['fixed_ips']:

View File

@ -175,7 +175,8 @@ def router_append_interface(router, count=1, ip_version=4, ra_mode=None,
def router_append_subnet(router, count=1, ip_version=4,
ipv6_subnet_modes=None, interface_id=None):
ipv6_subnet_modes=None, interface_id=None,
dns_nameservers=None):
if ip_version == 6:
subnet_mode_none = {'ra_mode': None, 'address_mode': None}
if not ipv6_subnet_modes:
@ -222,6 +223,7 @@ def router_append_subnet(router, count=1, ip_version=4,
{'id': subnet_id,
'cidr': cidr_pool % (i + num_existing_subnets),
'gateway_ip': gw_pool % (i + num_existing_subnets),
'dns_nameservers': dns_nameservers,
'ipv6_ra_mode': ipv6_subnet_modes[i]['ra_mode'],
'ipv6_address_mode': ipv6_subnet_modes[i]['address_mode']})

View File

@ -1203,7 +1203,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
return expected_calls
def _process_router_ipv6_subnet_added(
self, router, ipv6_subnet_modes=None):
self, router, ipv6_subnet_modes=None, dns_nameservers=None):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
agent.external_gateway_added = mock.Mock()
@ -1214,7 +1214,8 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
router,
count=len(ipv6_subnet_modes),
ip_version=6,
ipv6_subnet_modes=ipv6_subnet_modes)
ipv6_subnet_modes=ipv6_subnet_modes,
dns_nameservers=dns_nameservers)
# Reassign the router object to RouterInfo
self._process_router_instance_for_agent(agent, ri, router)
return ri
@ -2175,6 +2176,21 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
assertFlag(managed_flag)('AdvManagedFlag on;',
self.utils_replace_file.call_args[0][1])
def test_generate_radvd_rdnss_conf(self):
router = l3_test_common.prepare_router_data()
ipv6_subnet_modes = [{'ra_mode': l3_constants.IPV6_SLAAC,
'address_mode': l3_constants.IPV6_SLAAC}]
dns_list = ['fd01:1::100', 'fd01:1::200', 'fd01::300', 'fd01::400']
ri = self._process_router_ipv6_subnet_added(router,
ipv6_subnet_modes,
dns_nameservers=dns_list)
ri.radvd._generate_radvd_conf(router[l3_constants.INTERFACE_KEY])
# Verify that radvd configuration file includes RDNSS entries
expected = "RDNSS "
for dns in dns_list[0:ra.MAX_RDNSS_ENTRIES]:
expected += "%s " % dns
self.assertIn(expected, self.utils_replace_file.call_args[0][1])
def _pd_expected_call_external_process(self, requestor, ri, enable=True):
expected_calls = []
if enable:

View File

@ -68,6 +68,7 @@ class TestL3_NAT_dbonly_mixin(base.BaseTestCase):
subnet = {'id': mock.sentinel.subnet_id,
'cidr': cidr,
'gateway_ip': mock.sentinel.gateway_ip,
'dns_nameservers': mock.sentinel.dns_nameservers,
'ipv6_ra_mode': mock.sentinel.ipv6_ra_mode,
'subnetpool_id': mock.sentinel.subnetpool_id}
get_subnets_by_network.return_value = {'net_id': [subnet]}