launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #12701
[Merge] lp:~allenap/maas/split-forward-and-reverse-zones into lp:maas
Gavin Panella has proposed merging lp:~allenap/maas/split-forward-and-reverse-zones into lp:maas.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~allenap/maas/split-forward-and-reverse-zones/+merge/127124
This splits DNSZoneConfig into two: DNSForwardZoneConfig and DNSReverseZoneConfig. This is step one in preparation for sharing forward zones across networks. This branch will *not* be landed on its own.
--
https://code.launchpad.net/~allenap/maas/split-forward-and-reverse-zones/+merge/127124
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~allenap/maas/split-forward-and-reverse-zones into lp:maas.
=== modified file 'src/provisioningserver/dns/config.py'
--- src/provisioningserver/dns/config.py 2012-09-03 14:21:02 +0000
+++ src/provisioningserver/dns/config.py 2012-09-29 23:25:24 +0000
@@ -12,7 +12,8 @@
__metaclass__ = type
__all__ = [
'DNSConfig',
- 'DNSZoneConfig',
+ 'DNSForwardZoneConfig',
+ 'DNSReverseZoneConfig',
'setup_rndc',
]
@@ -22,6 +23,10 @@
abstractproperty,
)
from datetime import datetime
+from itertools import (
+ imap,
+ islice,
+ )
import os.path
from subprocess import (
check_call,
@@ -29,7 +34,6 @@
)
from celery.conf import conf
-from netaddr import IPRange
from provisioningserver.dns.utils import generated_hostname
from provisioningserver.utils import (
atomic_write,
@@ -170,8 +174,9 @@
template_file_name = 'named.conf.template'
target_file_name = MAAS_NAMED_CONF_NAME
- def __init__(self, zones=()):
- self.zones = zones
+ def __init__(self, forward_zones=(), reverse_zones=()):
+ self.forward_zones = forward_zones
+ self.reverse_zones = reverse_zones
return super(DNSConfig, self).__init__()
@property
@@ -184,7 +189,8 @@
def get_context(self):
return {
- 'zones': self.zones,
+ 'forward_zones': self.forward_zones,
+ 'reverse_zones': self.reverse_zones,
'DNS_CONFIG_DIR': conf.DNS_CONFIG_DIR,
'named_rndc_conf_path': get_named_rndc_conf_path(),
'modified': unicode(datetime.today()),
@@ -201,46 +207,68 @@
>>> shortened_reversed_ip('192.156.0.3', 2)
'3.0'
+
+ :type ip: :class:`netaddr.IPAddress`
"""
assert 0 <= byte_num <= 4, ("byte_num should be >=0 and <= 4.")
- ip_octets = ip.split('.')
- significant_octets = list(
- reversed(ip_octets))[:byte_num]
- return '.'.join(significant_octets)
-
-
-class DNSZoneConfig(DNSConfig):
- """A specialized version of DNSConfig that writes zone files."""
+ significant_octets = islice(reversed(ip.words), byte_num)
+ return '.'.join(imap(unicode, significant_octets))
+
+
+class DNSZoneConfigBase(DNSConfigBase):
+ """Base class for zone writers."""
template_file_name = 'zone.template'
- def __init__(self, zone_name, serial=None, mapping=None, dns_ip=None,
- subnet_mask=None, broadcast_ip=None, ip_range_low=None,
- ip_range_high=None):
- self.zone_name = zone_name
+ def __init__(self, domain, serial=None, mapping=None, dns_ip=None,
+ network=None):
+ """
+ :param domain: The domain name of the forward zone.
+ :param serial: The serial to use in the zone file. This must increment
+ on each change.
+ :param mapping: A hostname:ip-address mapping for all known hosts in
+ the zone.
+ :param dns_ip: The IP address of the DNS server authoritative for this
+ zone.
+ :param network: The network that the mapping exists within.
+ :type network: :class:`netaddr.IPNetwork`
+ """
+ self.domain = domain
self.serial = serial
- if mapping is None:
- self.mapping = {}
- else:
- self.mapping = mapping
+ self.mapping = {} if mapping is None else mapping
self.dns_ip = dns_ip
- self.subnet_mask = subnet_mask
- self.broadcast_ip = broadcast_ip
- self.ip_range_low = ip_range_low
- self.ip_range_high = ip_range_high
-
- @property
- def byte_num(self):
- """Number of significant octets for the IPs of this zone."""
- return 4 - len(
- [byte for byte in self.subnet_mask.split('.')
- if byte == '255'])
-
- @property
- def reverse_zone_name(self):
- """Return the name of the reverse zone."""
- significant_bits = self.broadcast_ip.split('.')[:4 - self.byte_num]
- return '%s.in-addr.arpa' % '.'.join(reversed(significant_bits))
+ self.network = network
+
+ @abstractproperty
+ def zone_name(self):
+ """Return the zone's fully-qualified name."""
+
+ @property
+ def template_path(self):
+ return os.path.join(self.template_dir, self.template_file_name)
+
+ @property
+ def target_path(self):
+ """Return the full path of the DNS zone file."""
+ return os.path.join(
+ self.target_dir, 'zone.%s' % self.zone_name)
+
+ def write_config(self, **kwargs):
+ """Write out the DNS config file for this zone."""
+ template = self.get_template()
+ kwargs.update(self.get_context())
+ rendered = self.render_template(template, **kwargs)
+ incremental_write(
+ rendered, self.target_path, mode=self.access_permissions)
+
+
+class DNSForwardZoneConfig(DNSZoneConfigBase):
+ """Writes forward zone files."""
+
+ @property
+ def zone_name(self):
+ """Return the name of the forward zone."""
+ return self.domain
def get_mapping(self):
"""Return the mapping: hostname->generated hostname."""
@@ -256,45 +284,8 @@
and the IP addresses for all the possible IP addresses in zone.
"""
return {
- generated_hostname(str(ip)): str(ip)
- for ip in IPRange(self.ip_range_low, self.ip_range_high)
- }
-
- def get_generated_reverse_mapping(self):
- """Return the reverse generated mapping: (shortened) ip->fqdn.
-
- The reverse generated mapping is the mapping between the IP addresses
- and the generated hostnames for all the possible IP addresses in zone.
- """
- return dict(
- (
- shortened_reversed_ip(ip, self.byte_num),
- '%s.%s.' % (hostname, self.zone_name)
- )
- for hostname, ip in self.get_generated_mapping().items())
-
- @property
- def template_path(self):
- return os.path.join(self.template_dir, self.template_file_name)
-
- @property
- def target_path(self):
- """Return the full path of the DNS zone config file."""
- return os.path.join(
- self.target_dir, 'zone.%s' % self.zone_name)
-
- @property
- def target_reverse_path(self):
- """Return the full path of the DNS reverse zone config file."""
- return os.path.join(
- self.target_dir, 'zone.rev.%s' % self.reverse_zone_name)
-
- def get_base_context(self):
- """Return the dict used to render both zone files."""
- return {
- 'domain': self.zone_name,
- 'serial': self.serial,
- 'modified': unicode(datetime.today()),
+ generated_hostname(ip): ip
+ for ip in imap(str, self.network)
}
def get_context(self):
@@ -302,39 +293,53 @@
That context dict is used to render the DNS zone file.
"""
- context = self.get_base_context()
mapping = self.get_generated_mapping()
# Add A record for the name server's IP.
- mapping['%s.' % self.zone_name] = self.dns_ip
- mappings = {
- 'CNAME': self.get_mapping(),
- 'A': mapping,
- }
- context.update(mappings=mappings)
- return context
-
- def get_reverse_context(self):
+ mapping['%s.' % self.domain] = self.dns_ip
+ return {
+ 'domain': self.domain,
+ 'serial': self.serial,
+ 'modified': unicode(datetime.today()),
+ 'mappings': {
+ 'CNAME': self.get_mapping(),
+ 'A': mapping,
+ }
+ }
+
+
+class DNSReverseZoneConfig(DNSZoneConfigBase):
+ """Writes reverse zone files."""
+
+ @property
+ def zone_name(self):
+ """Return the name of the reverse zone."""
+ broadcast, netmask = self.network.broadcast, self.network.netmask
+ octets = broadcast.words[:netmask.words.count(255)]
+ return '%s.in-addr.arpa' % '.'.join(imap(unicode, reversed(octets)))
+
+ def get_generated_mapping(self):
+ """Return the reverse generated mapping: (shortened) ip->fqdn.
+
+ The reverse generated mapping is the mapping between the IP addresses
+ and the generated hostnames for all the possible IP addresses in zone.
+ """
+ byte_num = 4 - self.network.netmask.words.count(255)
+ return {
+ shortened_reversed_ip(ip, byte_num):
+ '%s.%s.' % (generated_hostname(ip), self.domain)
+ for ip in self.network
+ }
+
+ def get_context(self):
"""Return the dict used to render the DNS reverse zone file.
That context dict is used to render the DNS reverse zone file.
"""
- context = self.get_base_context()
- mappings = {'PTR': self.get_generated_reverse_mapping()}
- context.update(mappings=mappings)
- return context
-
- def write_config(self, **kwargs):
- """Write out the DNS config file for this zone."""
- template = self.get_template()
- kwargs.update(self.get_context())
- rendered = self.render_template(template, **kwargs)
- incremental_write(
- rendered, self.target_path, mode=self.access_permissions)
-
- def write_reverse_config(self, **kwargs):
- """Write out the DNS reverse config file for this zone."""
- template = self.get_template()
- kwargs.update(self.get_reverse_context())
- rendered = self.render_template(template, **kwargs)
- incremental_write(
- rendered, self.target_reverse_path, mode=self.access_permissions)
+ return {
+ 'domain': self.domain,
+ 'serial': self.serial,
+ 'modified': unicode(datetime.today()),
+ 'mappings': {
+ 'PTR': self.get_generated_mapping(),
+ }
+ }
=== modified file 'src/provisioningserver/dns/templates/named.conf.template'
--- src/provisioningserver/dns/templates/named.conf.template 2012-07-25 09:36:03 +0000
+++ src/provisioningserver/dns/templates/named.conf.template 2012-09-29 23:25:24 +0000
@@ -1,7 +1,7 @@
include "{{named_rndc_conf_path}}";
# Zone declarations.
-{{for zone in zones}}
+{{for zone in forward_zones}}
zone "{{zone.zone_name}}" {
type master;
file "{{zone.target_path}}";
@@ -9,9 +9,9 @@
{{endfor}}
# Reverse zone declarations.
-{{for zone in zones}}
-zone "{{zone.reverse_zone_name}}" {
+{{for zone in reverse_zones}}
+zone "{{zone.zone_name}}" {
type master;
- file "{{zone.target_reverse_path}}";
+ file "{{zone.target_path}}";
};
{{endfor}}
=== added file 'src/provisioningserver/dns/tests/__init__.py'
=== modified file 'src/provisioningserver/dns/tests/test_config.py'
--- src/provisioningserver/dns/tests/test_config.py 2012-09-03 15:32:04 +0000
+++ src/provisioningserver/dns/tests/test_config.py 2012-09-29 23:25:24 +0000
@@ -23,12 +23,16 @@
MatchesAll,
)
from maastesting.testcase import TestCase
-from netaddr import IPNetwork
+from netaddr import (
+ IPAddress,
+ IPNetwork,
+ )
from provisioningserver.dns import config
from provisioningserver.dns.config import (
DNSConfig,
DNSConfigFail,
- DNSZoneConfig,
+ DNSForwardZoneConfig,
+ DNSReverseZoneConfig,
execute_rndc_command,
generate_rndc,
MAAS_NAMED_CONF_NAME,
@@ -39,7 +43,6 @@
TEMPLATES_PATH,
)
from provisioningserver.dns.utils import generated_hostname
-from provisioningserver.testing import network_infos
import tempita
from testtools.matchers import (
Contains,
@@ -148,21 +151,26 @@
def test_write_config_writes_config(self):
target_dir = self.make_dir()
self.patch(DNSConfig, 'target_dir', target_dir)
- zone_name = factory.getRandomString()
+ domain = factory.getRandomString()
network = IPNetwork('192.168.0.3/24')
ip = factory.getRandomIPInNetwork(network)
- zone = DNSZoneConfig(
- zone_name, mapping={factory.getRandomString(): ip},
- **network_infos(network))
- dnsconfig = DNSConfig(zones=[zone])
+ forward_zone = DNSForwardZoneConfig(
+ domain, mapping={factory.getRandomString(): ip},
+ network=network)
+ reverse_zone = DNSReverseZoneConfig(
+ domain, mapping={factory.getRandomString(): ip},
+ network=network)
+ dnsconfig = DNSConfig(
+ forward_zones=[forward_zone],
+ reverse_zones=[reverse_zone])
dnsconfig.write_config()
self.assertThat(
os.path.join(target_dir, MAAS_NAMED_CONF_NAME),
FileContains(
matcher=ContainsAll(
[
- 'zone.%s' % zone_name,
- 'zone.rev.0.168.192.in-addr.arpa',
+ 'zone.%s' % domain,
+ 'zone.0.168.192.in-addr.arpa',
MAAS_NAMED_RNDC_CONF_NAME,
])))
@@ -192,125 +200,184 @@
def test_shortened_reversed_ip_2(self):
self.assertEqual(
'3.0',
- shortened_reversed_ip('192.156.0.3', 2))
+ shortened_reversed_ip(IPAddress('192.156.0.3'), 2))
def test_shortened_reversed_ip_0(self):
self.assertEqual(
'',
- shortened_reversed_ip('192.156.0.3', 0))
+ shortened_reversed_ip(IPAddress('192.156.0.3'), 0))
def test_shortened_reversed_ip_4(self):
self.assertEqual(
'3.0.156.192',
- shortened_reversed_ip('192.156.0.3', 4))
-
-
-class TestDNSZoneConfig(TestCase):
- """Tests for DNSZoneConfig."""
-
- def test_DNSZoneConfig_fields(self):
- zone_name = factory.getRandomString()
- serial = random.randint(1, 200)
- hostname = factory.getRandomString()
- network = factory.getRandomNetwork()
- ip = factory.getRandomIPInNetwork(network)
- mapping = {hostname: ip}
- dns_zone_config = DNSZoneConfig(
- zone_name, serial, mapping, **network_infos(network))
- self.assertThat(
- dns_zone_config,
- MatchesStructure.byEquality(
- zone_name=zone_name,
- serial=serial,
- mapping=mapping,
- subnet_mask=str(network.netmask),
- broadcast_ip=str(network.broadcast),
- ip_range_low=str(network.first),
- ip_range_high=str(network.last),
- )
- )
-
- def test_DNSZoneConfig_computes_dns_config_file_paths(self):
- zone_name = factory.make_name('zone')
- reverse_file_name = 'zone.rev.168.192.in-addr.arpa'
- dns_zone_config = DNSZoneConfig(
- zone_name, broadcast_ip='192.168.0.255',
- subnet_mask='255.255.252.0',
- )
- self.assertEqual(
- (
- os.path.join(TEMPLATES_PATH, 'zone.template'),
- os.path.join(conf.DNS_CONFIG_DIR, 'zone.%s' % zone_name),
+ shortened_reversed_ip(IPAddress('192.156.0.3'), 4))
+
+
+class TestDNSForwardZoneConfig(TestCase):
+ """Tests for DNSForwardZoneConfig."""
+
+ def test_DNSForwardZoneConfig_fields(self):
+ domain = factory.getRandomString()
+ serial = random.randint(1, 200)
+ hostname = factory.getRandomString()
+ network = factory.getRandomNetwork()
+ ip = factory.getRandomIPInNetwork(network)
+ mapping = {hostname: ip}
+ dns_zone_config = DNSForwardZoneConfig(
+ domain, serial, mapping, network=network)
+ self.assertThat(
+ dns_zone_config,
+ MatchesStructure.byEquality(
+ domain=domain,
+ serial=serial,
+ mapping=mapping,
+ network=network,
+ )
+ )
+
+ def test_DNSForwardZoneConfig_computes_dns_config_file_paths(self):
+ domain = factory.make_name('zone')
+ dns_zone_config = DNSForwardZoneConfig(domain)
+ self.assertEqual(
+ (
+ os.path.join(TEMPLATES_PATH, 'zone.template'),
+ os.path.join(conf.DNS_CONFIG_DIR, 'zone.%s' % domain),
+ ),
+ (
+ dns_zone_config.template_path,
+ dns_zone_config.target_path,
+ ))
+
+ def test_DNSForwardZoneConfig_get_generated_mapping(self):
+ name = factory.getRandomString()
+ network = IPNetwork('192.12.0.1/30')
+ dns_zone_config = DNSForwardZoneConfig(name, network=network)
+ self.assertEqual(
+ {
+ generated_hostname('192.12.0.0'): '192.12.0.0',
+ generated_hostname('192.12.0.1'): '192.12.0.1',
+ generated_hostname('192.12.0.2'): '192.12.0.2',
+ generated_hostname('192.12.0.3'): '192.12.0.3',
+ },
+ dns_zone_config.get_generated_mapping(),
+ )
+
+ def test_DNSForwardZoneConfig_writes_dns_zone_config(self):
+ target_dir = self.make_dir()
+ self.patch(DNSForwardZoneConfig, 'target_dir', target_dir)
+ domain = factory.getRandomString()
+ hostname = factory.getRandomString()
+ network = factory.getRandomNetwork()
+ ip = factory.getRandomIPInNetwork(network)
+ dns_zone_config = DNSForwardZoneConfig(
+ domain, serial=random.randint(1, 100),
+ mapping={hostname: ip}, network=network)
+ dns_zone_config.write_config()
+ self.assertThat(
+ os.path.join(target_dir, 'zone.%s' % domain),
+ FileContains(
+ matcher=ContainsAll(
+ [
+ '%s IN CNAME %s' % (hostname, generated_hostname(ip)),
+ '%s IN A %s' % (generated_hostname(ip), ip),
+ ])))
+
+ def test_DNSForwardZoneConfig_writes_dns_zone_config_with_NS_record(self):
+ target_dir = self.make_dir()
+ self.patch(DNSForwardZoneConfig, 'target_dir', target_dir)
+ network = factory.getRandomNetwork()
+ dns_ip = factory.getRandomIPAddress()
+ dns_zone_config = DNSForwardZoneConfig(
+ factory.getRandomString(), serial=random.randint(1, 100),
+ dns_ip=dns_ip, network=network)
+ dns_zone_config.write_config()
+ self.assertThat(
+ os.path.join(target_dir, 'zone.%s' % dns_zone_config.domain),
+ FileContains(
+ matcher=ContainsAll(
+ [
+ 'IN NS %s.' % dns_zone_config.domain,
+ '%s. IN A %s' % (dns_zone_config.domain, dns_ip),
+ ])))
+
+ def test_DNSForwardZoneConfig_config_file_is_world_readable(self):
+ self.patch(DNSForwardZoneConfig, 'target_dir', self.make_dir())
+ network = factory.getRandomNetwork()
+ dns_zone_config = DNSForwardZoneConfig(
+ factory.getRandomString(), serial=random.randint(1, 100),
+ dns_ip=factory.getRandomIPAddress(), network=network)
+ dns_zone_config.write_config()
+ filepath = FilePath(dns_zone_config.target_path)
+ self.assertTrue(filepath.getPermissions().other.read)
+
+
+class TestDNSReverseZoneConfig(TestCase):
+ """Tests for DNSReverseZoneConfig."""
+
+ def test_DNSReverseZoneConfig_fields(self):
+ domain = factory.getRandomString()
+ serial = random.randint(1, 200)
+ hostname = factory.getRandomString()
+ network = factory.getRandomNetwork()
+ ip = factory.getRandomIPInNetwork(network)
+ mapping = {hostname: ip}
+ dns_zone_config = DNSReverseZoneConfig(
+ domain, serial, mapping, network=network)
+ self.assertThat(
+ dns_zone_config,
+ MatchesStructure.byEquality(
+ domain=domain,
+ serial=serial,
+ mapping=mapping,
+ network=network,
+ )
+ )
+
+ def test_DNSReverseZoneConfig_computes_dns_config_file_paths(self):
+ domain = factory.make_name('zone')
+ reverse_file_name = 'zone.168.192.in-addr.arpa'
+ dns_zone_config = DNSReverseZoneConfig(
+ domain, network=IPNetwork("192.168.0.0/22"))
+ self.assertEqual(
+ (
+ os.path.join(TEMPLATES_PATH, 'zone.template'),
os.path.join(conf.DNS_CONFIG_DIR, reverse_file_name)
),
(
dns_zone_config.template_path,
dns_zone_config.target_path,
- dns_zone_config.target_reverse_path,
))
- def test_DNSZoneConfig_reverse_data_slash_24(self):
- # DNSZoneConfig calculates the reverse data correctly for
+ def test_DNSReverseZoneConfig_reverse_data_slash_24(self):
+ # DNSReverseZoneConfig calculates the reverse data correctly for
# a /24 network.
- zone_name = factory.make_name('zone')
+ domain = factory.make_name('zone')
hostname = factory.getRandomString()
ip = '192.168.0.5'
network = IPNetwork('192.168.0.1/24')
- dns_zone_config = DNSZoneConfig(
- zone_name, mapping={hostname: ip}, **network_infos(network))
+ dns_zone_config = DNSReverseZoneConfig(
+ domain, mapping={hostname: ip}, network=network)
self.assertEqual(
- (
- 1,
- {hostname: generated_hostname(ip)},
- '0.168.192.in-addr.arpa',
- ),
- (
- dns_zone_config.byte_num,
- dns_zone_config.get_mapping(),
- dns_zone_config.reverse_zone_name,
- ))
+ '0.168.192.in-addr.arpa',
+ dns_zone_config.zone_name)
- def test_DNSZoneConfig_reverse_data_slash_22(self):
- # DNSZoneConfig calculates the reverse data correctly for
+ def test_DNSReverseZoneConfig_reverse_data_slash_22(self):
+ # DNSReverseZoneConfig calculates the reverse data correctly for
# a /22 network.
- zone_name = factory.getRandomString()
+ domain = factory.getRandomString()
hostname = factory.getRandomString()
ip = '192.168.0.10'
network = IPNetwork('192.168.0.1/22')
- dns_zone_config = DNSZoneConfig(
- zone_name, mapping={hostname: ip}, **network_infos(network))
- self.assertEqual(
- (
- 2,
- {hostname: generated_hostname(ip)},
- '168.192.in-addr.arpa',
- ),
- (
- dns_zone_config.byte_num,
- dns_zone_config.get_mapping(),
- dns_zone_config.reverse_zone_name,
- ))
-
- def test_DNSZoneConfig_get_generated_mapping(self):
- name = factory.getRandomString()
- network = IPNetwork('192.12.0.1/30')
- dns_zone_config = DNSZoneConfig(
- name, **network_infos(network))
- self.assertEqual(
- {
- generated_hostname('192.12.0.0'): '192.12.0.0',
- generated_hostname('192.12.0.1'): '192.12.0.1',
- generated_hostname('192.12.0.2'): '192.12.0.2',
- generated_hostname('192.12.0.3'): '192.12.0.3',
- },
- dns_zone_config.get_generated_mapping(),
- )
-
- def test_DNSZoneConfig_get_generated_reverse_mapping(self):
- name = factory.getRandomString()
- network = IPNetwork('192.12.0.1/30')
- dns_zone_config = DNSZoneConfig(
- name, **network_infos(network))
+ dns_zone_config = DNSReverseZoneConfig(
+ domain, mapping={hostname: ip}, network=network)
+ self.assertEqual(
+ '168.192.in-addr.arpa',
+ dns_zone_config.zone_name)
+
+ def test_DNSReverseZoneConfig_get_generated_mapping(self):
+ name = factory.getRandomString()
+ network = IPNetwork('192.12.0.1/30')
+ dns_zone_config = DNSReverseZoneConfig(name, network=network)
self.assertEqual(
{
'0': '%s.' % generated_hostname('192.12.0.0', name),
@@ -318,56 +385,33 @@
'2': '%s.' % generated_hostname('192.12.0.2', name),
'3': '%s.' % generated_hostname('192.12.0.3', name),
},
- dns_zone_config.get_generated_reverse_mapping(),
+ dns_zone_config.get_generated_mapping(),
)
- def test_DNSZoneConfig_writes_dns_zone_config(self):
- target_dir = self.make_dir()
- self.patch(DNSConfig, 'target_dir', target_dir)
- zone_name = factory.getRandomString()
- hostname = factory.getRandomString()
- network = factory.getRandomNetwork()
- ip = factory.getRandomIPInNetwork(network)
- dns_zone_config = DNSZoneConfig(
- zone_name, serial=random.randint(1, 100),
- mapping={hostname: ip}, **network_infos(network))
- dns_zone_config.write_config()
- self.assertThat(
- os.path.join(target_dir, 'zone.%s' % zone_name),
- FileContains(
- matcher=ContainsAll(
- [
- '%s IN CNAME %s' % (hostname, generated_hostname(ip)),
- '%s IN A %s' % (generated_hostname(ip), ip),
- ])))
-
- def test_DNSZoneConfig_writes_dns_zone_config_with_NS_record(self):
- target_dir = self.make_dir()
- self.patch(DNSConfig, 'target_dir', target_dir)
+ def test_DNSReverseZoneConfig_writes_dns_zone_config_with_NS_record(self):
+ target_dir = self.make_dir()
+ self.patch(DNSReverseZoneConfig, 'target_dir', target_dir)
network = factory.getRandomNetwork()
dns_ip = factory.getRandomIPAddress()
- dns_zone_config = DNSZoneConfig(
+ dns_zone_config = DNSReverseZoneConfig(
factory.getRandomString(), serial=random.randint(1, 100),
- dns_ip=dns_ip, **network_infos(network))
+ dns_ip=dns_ip, network=network)
dns_zone_config.write_config()
self.assertThat(
- os.path.join(target_dir, 'zone.%s' % dns_zone_config.zone_name),
+ os.path.join(
+ target_dir, 'zone.%s' % dns_zone_config.zone_name),
FileContains(
- matcher=ContainsAll(
- [
- 'IN NS %s.' % dns_zone_config.zone_name,
- '%s. IN A %s' % (dns_zone_config.zone_name, dns_ip),
- ])))
+ matcher=Contains('IN NS %s.' % dns_zone_config.domain)))
- def test_DNSZoneConfig_writes_reverse_dns_zone_config(self):
+ def test_DNSReverseZoneConfig_writes_reverse_dns_zone_config(self):
target_dir = self.make_dir()
- self.patch(DNSConfig, 'target_dir', target_dir)
- zone_name = factory.getRandomString()
+ self.patch(DNSReverseZoneConfig, 'target_dir', target_dir)
+ domain = factory.getRandomString()
network = IPNetwork('192.168.0.1/22')
- dns_zone_config = DNSZoneConfig(
- zone_name, serial=random.randint(1, 100), **network_infos(network))
- dns_zone_config.write_reverse_config()
- reverse_file_name = 'zone.rev.168.192.in-addr.arpa'
+ dns_zone_config = DNSReverseZoneConfig(
+ domain, serial=random.randint(1, 100), network=network)
+ dns_zone_config.write_config()
+ reverse_file_name = 'zone.168.192.in-addr.arpa'
self.assertThat(
os.path.join(target_dir, reverse_file_name),
FileContains(
@@ -381,22 +425,12 @@
)
)
- def test_DNSZoneConfig_config_file_is_world_readable(self):
- self.patch(DNSConfig, 'target_dir', self.make_dir())
- dns_zone_config = DNSZoneConfig(
+ def test_DNSReverseZoneConfig_reverse_config_file_is_world_readable(self):
+ self.patch(DNSReverseZoneConfig, 'target_dir', self.make_dir())
+ dns_zone_config = DNSReverseZoneConfig(
factory.getRandomString(), serial=random.randint(1, 100),
dns_ip=factory.getRandomIPAddress(),
- **network_infos(factory.getRandomNetwork()))
+ network=factory.getRandomNetwork())
dns_zone_config.write_config()
filepath = FilePath(dns_zone_config.target_path)
self.assertTrue(filepath.getPermissions().other.read)
-
- def test_DNSZoneConfig_reverse_config_file_is_world_readable(self):
- self.patch(DNSConfig, 'target_dir', self.make_dir())
- dns_zone_config = DNSZoneConfig(
- factory.getRandomString(), serial=random.randint(1, 100),
- dns_ip=factory.getRandomIPAddress(),
- **network_infos(factory.getRandomNetwork()))
- dns_zone_config.write_reverse_config()
- filepath = FilePath(dns_zone_config.target_reverse_path)
- self.assertTrue(filepath.getPermissions().other.read)
=== modified file 'src/provisioningserver/dns/tests/test_utils.py'
--- src/provisioningserver/dns/tests/test_utils.py 2012-07-24 17:47:48 +0000
+++ src/provisioningserver/dns/tests/test_utils.py 2012-09-29 23:25:24 +0000
@@ -15,6 +15,7 @@
from maastesting.factory import factory
from maastesting.testcase import TestCase
+from netaddr import IPAddress
from provisioningserver.dns.utils import generated_hostname
@@ -29,3 +30,7 @@
self.assertEqual(
'192-168-0-1.%s' % domain,
generated_hostname('192.168.0.1', domain))
+
+ def test_generated_hostname_accepts_IPAddress(self):
+ address = IPAddress("12.34.56.78")
+ self.assertEqual("12-34-56-78", generated_hostname(address))
=== modified file 'src/provisioningserver/dns/utils.py'
--- src/provisioningserver/dns/utils.py 2012-07-24 17:47:48 +0000
+++ src/provisioningserver/dns/utils.py 2012-09-29 23:25:24 +0000
@@ -23,7 +23,7 @@
>>> generated_hostname('192.168.0.1', 'mydomain.com')
'192-168-0-1.mydomain.com'
"""
- hostname = ip.replace('.', '-')
+ hostname = unicode(ip).replace('.', '-')
if domain is not None:
return '%s.%s' % (hostname, domain)
else: