[OVN] Correctly set dns_server in dhcpv4/v6 options
When ovn/dns_servers consist of IPv6 dns nameservers, it was getting added to IPv4 dhcp options also, and due to this an invalid nameserver(last 4 octets of an IPv6 address) is set in the instances. This patch filters IPv4/IPv6 dns nameservers and set dhcpv4/dhcpv6 options accordingly. Also when dns_nameservers are not set for IPv6 subnets, get those from ovn/dns_servers config or system nameservers just like it's done with the IPv4 subnets. Updated get_system_dns_resolvers to pick both IPv4/IPv6 valid ips, this also requires bump of oslo.utils minimum version to 4.8.0 to use strict option for IPv4[1]. Additionally fix some unit tests which were setting IPv4 dns nameservers on the IPv6 subnets, this is not allowed with api. [1] https://github.com/openstack/oslo.utils/commit/3288539 Closes-Bug: #1951816 Change-Id: I9f914e721201072e43a8c6c266ed97ca85fcc13d
This commit is contained in:
parent
7aba1bddab
commit
4a06685098
@ -74,7 +74,7 @@ oslo.rootwrap==5.15.0
|
||||
oslo.serialization==2.25.0
|
||||
oslo.service==1.31.0
|
||||
oslo.upgradecheck==1.3.0
|
||||
oslo.utils==4.5.0
|
||||
oslo.utils==4.8.0
|
||||
oslo.versionedobjects==1.35.1
|
||||
oslotest==3.2.0
|
||||
osprofiler==2.3.0
|
||||
|
@ -410,9 +410,11 @@ def get_system_dns_resolvers(resolver_file=DNS_RESOLVER_FILE):
|
||||
continue
|
||||
|
||||
line = line.split('nameserver')[1].strip()
|
||||
ipv4 = re.search(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}', line)
|
||||
if ipv4:
|
||||
resolvers.append(ipv4.group(0))
|
||||
valid_ip = (netutils.is_valid_ipv4(line, strict=True) or
|
||||
netutils.is_valid_ipv6(line))
|
||||
if valid_ip:
|
||||
resolvers.append(line)
|
||||
|
||||
return resolvers
|
||||
|
||||
|
||||
@ -423,12 +425,13 @@ def get_dhcp_dns_servers(subnet, ip_version=const.IP_VERSION_4):
|
||||
configured DNS server is "0.0.0.0" (IPv4) or "::" (IPv6).
|
||||
https://docs.openstack.org/neutron/latest/admin/config-dns-res.html
|
||||
"""
|
||||
if ip_version == const.IP_VERSION_4:
|
||||
dns_servers = (subnet.get('dns_nameservers') or
|
||||
ovn_conf.get_dns_servers() or
|
||||
get_system_dns_resolvers())
|
||||
else:
|
||||
dns_servers = subnet['dns_nameservers']
|
||||
def filter_ips(ips, ip_version=const.IP_VERSION_4):
|
||||
return [ip for ip in ips
|
||||
if netaddr.IPAddress(ip).version == ip_version]
|
||||
|
||||
dns_servers = (subnet.get('dns_nameservers') or
|
||||
filter_ips(ovn_conf.get_dns_servers(), ip_version) or
|
||||
filter_ips(get_system_dns_resolvers(), ip_version))
|
||||
|
||||
if common_utils.is_dns_servers_any_address(dns_servers, ip_version):
|
||||
return []
|
||||
|
@ -36,7 +36,9 @@ nameserver foo 10.0.0.4
|
||||
nameserver aef0::4
|
||||
foo 10.0.0.5
|
||||
"""
|
||||
RESOLV_DNS_SERVERS = ['10.0.0.1', '10.0.0.3']
|
||||
RESOLV_DNS_SERVERS = ['10.0.0.1', '10.0.0.3', 'aef0::4']
|
||||
RESOLV_DNS_SERVERS_V4 = ['10.0.0.1', '10.0.0.3']
|
||||
RESOLV_DNS_SERVERS_V6 = ['aef0::4']
|
||||
|
||||
|
||||
class TestUtils(base.BaseTestCase):
|
||||
@ -405,7 +407,7 @@ class TestGetDhcpDnsServers(base.BaseTestCase):
|
||||
mock.mock_open(read_data=RESOLV_CONF_TEMPLATE)), \
|
||||
mock.patch.object(path, 'exists', return_value=True):
|
||||
dns_servers = utils.get_dhcp_dns_servers({})
|
||||
self.assertEqual(RESOLV_DNS_SERVERS, dns_servers)
|
||||
self.assertEqual(RESOLV_DNS_SERVERS_V4, dns_servers)
|
||||
|
||||
# No DNS servers if only '0.0.0.0' configured.
|
||||
dns_servers = utils.get_dhcp_dns_servers(
|
||||
@ -424,6 +426,14 @@ class TestGetDhcpDnsServers(base.BaseTestCase):
|
||||
self.assertEqual(['2001:4860:4860::8888',
|
||||
'2001:4860:4860::8844'], dns_servers)
|
||||
|
||||
# DNS servers from local DNS resolver.
|
||||
cfg.CONF.set_override('dns_servers', '', group='ovn')
|
||||
with mock.patch('builtins.open',
|
||||
mock.mock_open(read_data=RESOLV_CONF_TEMPLATE)), \
|
||||
mock.patch.object(path, 'exists', return_value=True):
|
||||
dns_servers = utils.get_dhcp_dns_servers({}, ip_version=6)
|
||||
self.assertEqual(RESOLV_DNS_SERVERS_V6, dns_servers)
|
||||
|
||||
# No DNS servers if only '::' configured.
|
||||
dns_servers = utils.get_dhcp_dns_servers(
|
||||
{'dns_nameservers': ['2001:4860:4860::8888', '::']},
|
||||
|
@ -2725,6 +2725,58 @@ class TestOVNMechanismDriverDHCPOptions(OVNMechanismDriverTestCase):
|
||||
self._test_get_ovn_dhcp_options_helper(subnet, network,
|
||||
expected_dhcp_options)
|
||||
|
||||
def test_get_ovn_dhcpv4_options_ovn_conf_ip4_ip6_dns(self):
|
||||
ovn_conf.cfg.CONF.set_override('dns_servers',
|
||||
'8.8.8.8,2001:db8::8888',
|
||||
group='ovn')
|
||||
subnet = {'id': 'foo-subnet', 'network_id': 'network-id',
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'enable_dhcp': True,
|
||||
'host_routes': [],
|
||||
'gateway_ip': '10.0.0.1'}
|
||||
network = {'id': 'network-id', 'mtu': 1400}
|
||||
|
||||
expected_dhcpv4_options = {'cidr': subnet['cidr'],
|
||||
'external_ids': {
|
||||
'subnet_id': subnet['id'],
|
||||
ovn_const.OVN_REV_NUM_EXT_ID_KEY: '1'}}
|
||||
expected_dhcpv4_options['options'] = {
|
||||
'server_id': subnet['gateway_ip'],
|
||||
'server_mac': '01:02:03:04:05:06',
|
||||
'lease_time': str(12 * 60 * 60),
|
||||
'mtu': str(network['mtu']),
|
||||
'router': subnet['gateway_ip'],
|
||||
'dns_server': '{8.8.8.8}'
|
||||
}
|
||||
|
||||
self._test_get_ovn_dhcp_options_helper(subnet, network,
|
||||
expected_dhcpv4_options)
|
||||
|
||||
def test_get_ovn_dhcpv6_options_ovn_conf_ip4_ip6_dns(self):
|
||||
ovn_conf.cfg.CONF.set_override('dns_servers',
|
||||
'8.8.8.8,2001:db8::8888',
|
||||
group='ovn')
|
||||
subnet = {'id': 'foo-subnet', 'network_id': 'network-id',
|
||||
'cidr': '2001:db8::/64',
|
||||
'ip_version': 6,
|
||||
'enable_dhcp': True,
|
||||
'host_routes': [],
|
||||
'gateway_ip': '2001:db8::1'}
|
||||
network = {'id': 'network-id', 'mtu': 1400}
|
||||
|
||||
expected_dhcpv6_options = {'cidr': subnet['cidr'],
|
||||
'external_ids': {
|
||||
'subnet_id': subnet['id'],
|
||||
ovn_const.OVN_REV_NUM_EXT_ID_KEY: '1'}}
|
||||
expected_dhcpv6_options['options'] = {
|
||||
'server_id': '01:02:03:04:05:06',
|
||||
'dns_server': '{2001:db8::8888}'
|
||||
}
|
||||
|
||||
self._test_get_ovn_dhcp_options_helper(subnet, network,
|
||||
expected_dhcpv6_options)
|
||||
|
||||
def test_get_ovn_dhcp_options_with_global_options(self):
|
||||
ovn_conf.cfg.CONF.set_override('ovn_dhcp4_global_options',
|
||||
'ntp_server:8.8.8.8,'
|
||||
@ -2776,7 +2828,7 @@ class TestOVNMechanismDriverDHCPOptions(OVNMechanismDriverTestCase):
|
||||
'cidr': 'ae70::/24',
|
||||
'ip_version': 6,
|
||||
'enable_dhcp': True,
|
||||
'dns_nameservers': ['7.7.7.7', '8.8.8.8']}
|
||||
'dns_nameservers': ['2001:db8::4444', '2001:db8::8888']}
|
||||
network = {'id': 'network-id', 'mtu': 1400}
|
||||
|
||||
ext_ids = {'subnet_id': 'foo-subnet',
|
||||
@ -2785,7 +2837,7 @@ class TestOVNMechanismDriverDHCPOptions(OVNMechanismDriverTestCase):
|
||||
'cidr': 'ae70::/24', 'external_ids': ext_ids,
|
||||
'options': {'server_id': '01:02:03:04:05:06',
|
||||
'ntp_server': '8.8.8.8',
|
||||
'dns_server': '{7.7.7.7, 8.8.8.8}'}}
|
||||
'dns_server': '{2001:db8::4444, 2001:db8::8888}'}}
|
||||
|
||||
self._test_get_ovn_dhcp_options_helper(subnet, network,
|
||||
expected_dhcp_options)
|
||||
@ -2799,7 +2851,7 @@ class TestOVNMechanismDriverDHCPOptions(OVNMechanismDriverTestCase):
|
||||
'cidr': 'ae70::/24',
|
||||
'ip_version': 6,
|
||||
'enable_dhcp': True,
|
||||
'dns_nameservers': ['7.7.7.7', '8.8.8.8']}
|
||||
'dns_nameservers': ['2001:db8::4444', '2001:db8::8888']}
|
||||
network = {'id': 'network-id', 'mtu': 1400}
|
||||
|
||||
ext_ids = {'subnet_id': 'foo-subnet',
|
||||
@ -2807,7 +2859,7 @@ class TestOVNMechanismDriverDHCPOptions(OVNMechanismDriverTestCase):
|
||||
expected_dhcp_options = {
|
||||
'cidr': 'ae70::/24', 'external_ids': ext_ids,
|
||||
'options': {'server_id': '01:02:03:04:05:06',
|
||||
'dns_server': '{7.7.7.7, 8.8.8.8}'}}
|
||||
'dns_server': '{2001:db8::4444, 2001:db8::8888}'}}
|
||||
|
||||
self._test_get_ovn_dhcp_options_helper(subnet, network,
|
||||
expected_dhcp_options)
|
||||
@ -2821,7 +2873,7 @@ class TestOVNMechanismDriverDHCPOptions(OVNMechanismDriverTestCase):
|
||||
'cidr': 'ae70::/24',
|
||||
'ip_version': 6,
|
||||
'enable_dhcp': True,
|
||||
'dns_nameservers': ['7.7.7.7', '8.8.8.8'],
|
||||
'dns_nameservers': ['2001:db8::4444', '2001:db8::8888'],
|
||||
'ipv6_address_mode': const.DHCPV6_STATELESS}
|
||||
network = {'id': 'network-id', 'mtu': 1400}
|
||||
|
||||
@ -2830,7 +2882,7 @@ class TestOVNMechanismDriverDHCPOptions(OVNMechanismDriverTestCase):
|
||||
expected_dhcp_options = {
|
||||
'cidr': 'ae70::/24', 'external_ids': ext_ids,
|
||||
'options': {'server_id': '01:02:03:04:05:06',
|
||||
'dns_server': '{7.7.7.7, 8.8.8.8}',
|
||||
'dns_server': '{2001:db8::4444, 2001:db8::8888}',
|
||||
'dhcpv6_stateless': 'true'}}
|
||||
|
||||
self._test_get_ovn_dhcp_options_helper(subnet, network,
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
For IPv4 subnets when dns_nameservers is not set in the subnet,
|
||||
servers defined in 'ovn/dns_servers' config option or system's
|
||||
resolv.conf are used, but for IPv6 subnets these are
|
||||
not used. The same will now be used for IPv6 subnets too.
|
||||
Additionally dns servers added in 'ovn/dns_servers' config
|
||||
option or system's resolv.conf will be filtered as per
|
||||
the subnet's IP version. For more info see the bug report
|
||||
`1951816 <https://bugs.launchpad.net/neutron/+bug/1951816>`_.
|
@ -40,7 +40,7 @@ oslo.rootwrap>=5.15.0 # Apache-2.0
|
||||
oslo.serialization>=2.25.0 # Apache-2.0
|
||||
oslo.service>=1.31.0 # Apache-2.0
|
||||
oslo.upgradecheck>=1.3.0 # Apache-2.0
|
||||
oslo.utils>=4.5.0 # Apache-2.0
|
||||
oslo.utils>=4.8.0 # Apache-2.0
|
||||
oslo.versionedobjects>=1.35.1 # Apache-2.0
|
||||
osprofiler>=2.3.0 # Apache-2.0
|
||||
os-ken>=2.2.0 # Apache-2.0
|
||||
|
Loading…
Reference in New Issue
Block a user