Ensure entries in dnsmasq belong to a subnet using DHCP
In certain configurations, Neutron calculates SLAAC addresses for IPv6 subnets and adds them to the fixed_ips field of a port. Since those subnets are not being managed by DHCP, do not add those fixed_ip entries to the host file. Closes-bug: #1316190 Related-bug: #1257446 Change-Id: I77dd55063296990c9df385f331f5de5d42402786
This commit is contained in:
parent
16eb987558
commit
1715eb7c8e
|
@ -366,9 +366,14 @@ class Dnsmasq(DhcpLocalProcess):
|
|||
if subnet.ip_version == 4:
|
||||
mode = 'static'
|
||||
else:
|
||||
# TODO(mark): how do we indicate other options
|
||||
# ra-only, slaac, ra-nameservers, and ra-stateless.
|
||||
mode = 'static'
|
||||
# Note(scollins) If the IPv6 attributes are not set, set it as
|
||||
# static to preserve previous behavior
|
||||
if (not getattr(subnet, 'ipv6_ra_mode', None) and
|
||||
not getattr(subnet, 'ipv6_address_mode', None)):
|
||||
mode = 'static'
|
||||
elif getattr(subnet, 'ipv6_ra_mode', None) is None:
|
||||
# RA mode is not set - do not launch dnsmasq
|
||||
continue
|
||||
if self.version >= self.MINIMUM_VERSION:
|
||||
set_tag = 'set:'
|
||||
else:
|
||||
|
@ -445,8 +450,18 @@ class Dnsmasq(DhcpLocalProcess):
|
|||
name, # Host name and domain name in the format 'hostname.domain'.
|
||||
)
|
||||
"""
|
||||
v6_nets = dict((subnet.id, subnet) for subnet in
|
||||
self.network.subnets if subnet.ip_version == 6)
|
||||
for port in self.network.ports:
|
||||
for alloc in port.fixed_ips:
|
||||
# Note(scollins) Only create entries that are
|
||||
# associated with the subnet being managed by this
|
||||
# dhcp agent
|
||||
if alloc.subnet_id in v6_nets:
|
||||
ra_mode = v6_nets[alloc.subnet_id].ipv6_ra_mode
|
||||
addr_mode = v6_nets[alloc.subnet_id].ipv6_address_mode
|
||||
if (ra_mode is None and addr_mode == constants.IPV6_SLAAC):
|
||||
continue
|
||||
hostname = 'host-%s' % alloc.ip_address.replace(
|
||||
'.', '-').replace(':', '-')
|
||||
fqdn = '%s.%s' % (hostname, self.conf.dhcp_domain)
|
||||
|
|
|
@ -49,7 +49,8 @@ class FakePort1:
|
|||
id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
|
||||
admin_state_up = True
|
||||
device_owner = 'foo1'
|
||||
fixed_ips = [FakeIPAllocation('192.168.0.2')]
|
||||
fixed_ips = [FakeIPAllocation('192.168.0.2',
|
||||
'dddddddd-dddd-dddd-dddd-dddddddddddd')]
|
||||
mac_address = '00:00:80:aa:bb:cc'
|
||||
|
||||
def __init__(self):
|
||||
|
@ -60,7 +61,8 @@ class FakePort2:
|
|||
id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
|
||||
admin_state_up = False
|
||||
device_owner = 'foo2'
|
||||
fixed_ips = [FakeIPAllocation('fdca:3ba5:a17a:4ba3::2')]
|
||||
fixed_ips = [FakeIPAllocation('fdca:3ba5:a17a:4ba3::2',
|
||||
'ffffffff-ffff-ffff-ffff-ffffffffffff')]
|
||||
mac_address = '00:00:f3:aa:bb:cc'
|
||||
|
||||
def __init__(self):
|
||||
|
@ -71,14 +73,29 @@ class FakePort3:
|
|||
id = '44444444-4444-4444-4444-444444444444'
|
||||
admin_state_up = True
|
||||
device_owner = 'foo3'
|
||||
fixed_ips = [FakeIPAllocation('192.168.0.3'),
|
||||
FakeIPAllocation('fdca:3ba5:a17a:4ba3::3')]
|
||||
fixed_ips = [FakeIPAllocation('192.168.0.3',
|
||||
'dddddddd-dddd-dddd-dddd-dddddddddddd'),
|
||||
FakeIPAllocation('fdca:3ba5:a17a:4ba3::3',
|
||||
'ffffffff-ffff-ffff-ffff-ffffffffffff')]
|
||||
mac_address = '00:00:0f:aa:bb:cc'
|
||||
|
||||
def __init__(self):
|
||||
self.extra_dhcp_opts = []
|
||||
|
||||
|
||||
class FakePort4:
|
||||
|
||||
id = 'gggggggg-gggg-gggg-gggg-gggggggggggg'
|
||||
admin_state_up = False
|
||||
device_owner = 'foo3'
|
||||
fixed_ips = [FakeIPAllocation('192.168.0.4',
|
||||
'ffda:3ba5:a17a:4ba3:0216:3eff:fec2:771d')]
|
||||
mac_address = '00:16:3E:C2:77:1D'
|
||||
|
||||
def __init__(self):
|
||||
self.extra_dhcp_opts = []
|
||||
|
||||
|
||||
class FakeRouterPort:
|
||||
id = 'rrrrrrrr-rrrr-rrrr-rrrr-rrrrrrrrrrrr'
|
||||
admin_state_up = True
|
||||
|
@ -194,6 +211,8 @@ class FakeV6Subnet:
|
|||
enable_dhcp = True
|
||||
host_routes = [FakeV6HostRoute]
|
||||
dns_nameservers = ['2001:0200:feed:7ac0::1']
|
||||
ipv6_ra_mode = None
|
||||
ipv6_address_mode = None
|
||||
|
||||
|
||||
class FakeV4SubnetNoDHCP:
|
||||
|
@ -206,6 +225,17 @@ class FakeV4SubnetNoDHCP:
|
|||
dns_nameservers = []
|
||||
|
||||
|
||||
class FakeV6SubnetSlaac:
|
||||
id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
|
||||
ip_version = 6
|
||||
cidr = 'ffda:3ba5:a17a:4ba3::/64'
|
||||
gateway_ip = 'ffda:3ba5:a17a:4ba3::1'
|
||||
enable_dhcp = True
|
||||
host_routes = [FakeV6HostRoute]
|
||||
ipv6_address_mode = constants.IPV6_SLAAC
|
||||
ipv6_ra_mode = None
|
||||
|
||||
|
||||
class FakeV4SubnetNoGateway:
|
||||
id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
|
||||
ip_version = 4
|
||||
|
@ -370,6 +400,13 @@ class FakeV4NetworkPxe3Ports:
|
|||
DhcpOpt(opt_name='bootfile-name', opt_value='pxelinux3.0')]
|
||||
|
||||
|
||||
class FakeDualStackNetworkSingleDHCP:
|
||||
id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
|
||||
|
||||
subnets = [FakeV4Subnet(), FakeV6SubnetSlaac()]
|
||||
ports = [FakePort1(), FakePort4(), FakeRouterPort()]
|
||||
|
||||
|
||||
class LocalChild(dhcp.DhcpLocalProcess):
|
||||
PORTS = {4: [4], 6: [6]}
|
||||
|
||||
|
@ -1250,3 +1287,17 @@ tag:tag0,option:router""".lstrip()
|
|||
|
||||
def test_check_version_failed_cmd_execution(self):
|
||||
self._check_version('Error while executing command', 0)
|
||||
|
||||
def test_only_populates_dhcp_enabled_subnets(self):
|
||||
exp_host_name = '/dhcp/eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee/host'
|
||||
exp_host_data = ('00:00:80:aa:bb:cc,host-192-168-0-2.openstacklocal,'
|
||||
'192.168.0.2\n'
|
||||
'00:16:3E:C2:77:1D,host-192-168-0-4.openstacklocal,'
|
||||
'192.168.0.4\n'
|
||||
'00:00:0f:rr:rr:rr,host-192-168-0-1.openstacklocal,'
|
||||
'192.168.0.1\n').lstrip()
|
||||
dm = dhcp.Dnsmasq(self.conf, FakeDualStackNetworkSingleDHCP(),
|
||||
version=float(2.59))
|
||||
dm._output_hosts_file()
|
||||
self.safe.assert_has_calls([mock.call(exp_host_name,
|
||||
exp_host_data)])
|
||||
|
|
Loading…
Reference in New Issue