# 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
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__)
AdvManagedFlag on;
{% endif %}
+ {% if dns_servers %}
+ RDNSS {% for dns in dns_servers %} {{ dns }} {% endfor %} {};
+ {% endif %}
+
{% for prefix in prefixes %}
prefix {{ prefix }}
{
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))
utils.replace_file(radvd_conf, buf.getvalue())
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)
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']:
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:
{'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']})
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()
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
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:
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]}