Merge "Fix extra-dhcp-opt on stateless dhcpv6 subnet" into stable/juno

This commit is contained in:
Jenkins 2015-04-01 20:56:23 +00:00 committed by Gerrit Code Review
commit de6b3806c6
2 changed files with 75 additions and 6 deletions

View File

@ -469,6 +469,8 @@ class Dnsmasq(DhcpLocalProcess):
(
port, # a DictModel instance representing the port.
alloc, # a DictModel instance of the allocated ip and subnet.
# if alloc is None, it means there is no need to allocate
# an IPv6 address because of stateless DHCPv6 network.
host_name, # Host name.
name, # Canonical hostname in the format 'hostname[.domain]'.
)
@ -482,8 +484,13 @@ class Dnsmasq(DhcpLocalProcess):
# dhcp agent
if alloc.subnet_id in v6_nets:
addr_mode = v6_nets[alloc.subnet_id].ipv6_address_mode
if addr_mode != constants.DHCPV6_STATEFUL:
if addr_mode == constants.IPV6_SLAAC:
continue
elif addr_mode == constants.DHCPV6_STATELESS:
alloc = hostname = fqdn = None
yield (port, alloc, hostname, fqdn)
continue
hostname = 'host-%s' % alloc.ip_address.replace(
'.', '-').replace(':', '-')
fqdn = hostname
@ -512,6 +519,14 @@ class Dnsmasq(DhcpLocalProcess):
LOG.debug(_('Building host file: %s'), filename)
for (port, alloc, hostname, name) in self._iter_hosts():
if not alloc:
if getattr(port, 'extra_dhcp_opts', False):
buf.write('%s,%s%s\n' %
(port.mac_address, 'set:', port.id))
LOG.debug('Adding %(mac)s : set:%(tag)s',
{"mac": port.mac_address, "tag": port.id})
continue
# (dzyu) Check if it is legal ipv6 address, if so, need wrap
# it with '[]' to let dnsmasq to distinguish MAC address from
# IPv6 address.
@ -519,17 +534,20 @@ class Dnsmasq(DhcpLocalProcess):
if netaddr.valid_ipv6(ip_address):
ip_address = '[%s]' % ip_address
LOG.debug(_('Adding %(mac)s : %(name)s : %(ip)s'),
{"mac": port.mac_address, "name": name,
"ip": ip_address})
if getattr(port, 'extra_dhcp_opts', False):
buf.write('%s,%s,%s,%s%s\n' %
(port.mac_address, name, ip_address,
'set:', port.id))
LOG.debug('Adding %(mac)s : %(name)s : %(ip)s : '
'set:%(tag)s',
{"mac": port.mac_address, "name": name,
"ip": ip_address, "tag": port.id})
else:
buf.write('%s,%s,%s\n' %
(port.mac_address, name, ip_address))
LOG.debug('Adding %(mac)s : %(name)s : %(ip)s',
{"mac": port.mac_address, "name": name,
"ip": ip_address})
utils.replace_file(filename, buf.getvalue())
LOG.debug(_('Done building host file %s'), filename)
@ -570,7 +588,8 @@ class Dnsmasq(DhcpLocalProcess):
for (port, alloc, hostname, fqdn) in self._iter_hosts():
# It is compulsory to write the `fqdn` before the `hostname` in
# order to obtain it in PTR responses.
buf.write('%s\t%s %s\n' % (alloc.ip_address, fqdn, hostname))
if alloc:
buf.write('%s\t%s %s\n' % (alloc.ip_address, fqdn, hostname))
addn_hosts = self.get_conf_file_name('addn_hosts')
utils.replace_file(addn_hosts, buf.getvalue())
return addn_hosts

View File

@ -108,6 +108,21 @@ class FakeV6Port:
self.extra_dhcp_opts = []
class FakeV6PortExtraOpt(object):
id = 'hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh'
admin_state_up = True
device_owner = 'foo3'
fixed_ips = [FakeIPAllocation('ffea:3ba5:a17a:4ba3:0216:3eff:fec2:771d',
'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee')]
mac_address = '00:16:3e:c2:77:1d'
def __init__(self):
self.extra_dhcp_opts = [
DhcpOpt(opt_name='dns-server',
opt_value='ffea:3ba5:a17a:4ba3::100',
ip_version=6)]
class FakeDualPort:
id = 'hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh'
admin_state_up = True
@ -286,6 +301,18 @@ class FakeV6SubnetSlaac:
ipv6_ra_mode = None
class FakeV6SubnetStateless(object):
id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
ip_version = 6
cidr = 'ffea:3ba5:a17a:4ba3::/64'
gateway_ip = 'ffea:3ba5:a17a:4ba3::1'
enable_dhcp = True
dns_nameservers = []
host_routes = []
ipv6_address_mode = constants.DHCPV6_STATELESS
ipv6_ra_mode = None
class FakeV4SubnetNoGateway:
id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
ip_version = 4
@ -470,6 +497,14 @@ class FakeDualStackNetworkSingleDHCP:
ports = [FakePort1(), FakePort4(), FakeRouterPort()]
class FakeV6NetworkStatelessDHCP(object):
id = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'
subnets = [FakeV6SubnetStateless()]
ports = [FakeV6PortExtraOpt()]
namespace = 'qdhcp-ns'
class LocalChild(dhcp.DhcpLocalProcess):
PORTS = {4: [4], 6: [6]}
@ -1406,6 +1441,21 @@ tag:tag0,option:router""".lstrip()
self.safe.assert_has_calls([mock.call(exp_host_name,
exp_host_data)])
def test_host_and_opts_file_on_stateless_dhcpv6_network(self):
exp_host_name = '/dhcp/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb/host'
exp_host_data = ('00:16:3e:c2:77:1d,'
'set:hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh\n').lstrip()
exp_opt_name = '/dhcp/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb/opts'
exp_opt_data = ('tag:tag0,option6:domain-search,openstacklocal\n'
'tag:hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh,'
'option6:dns-server,ffea:3ba5:a17a:4ba3::100').lstrip()
dm = dhcp.Dnsmasq(self.conf, FakeV6NetworkStatelessDHCP(),
version=dhcp.Dnsmasq.MINIMUM_VERSION)
dm._output_hosts_file()
dm._output_opts_file()
self.safe.assert_has_calls([mock.call(exp_host_name, exp_host_data),
mock.call(exp_opt_name, exp_opt_data)])
def test_should_enable_metadata_namespaces_disabled_returns_false(self):
self.conf.set_override('use_namespaces', False)
self.assertFalse(dhcp.Dnsmasq.should_enable_metadata(self.conf,