← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~rvb/maas/dns-setup-command2 into lp:maas

 

Raphaël Badin has proposed merging lp:~rvb/maas/dns-setup-command2 into lp:maas with lp:~rvb/maas/dns-setup-command as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~rvb/maas/dns-setup-command2/+merge/114396

This is, again, preparation work for a follow-up branch which will add a new 'set_up_dns' command which will return the configuration snippet used to hook up MAAS' dns configuration within an existing Bind instance.

It fixes several things:
- Replace zone_id by zone_name.  A zone name is the real key for a zone (it will be taken from NodeGroup.name which is unique).

- Fix the templates:
    - the logging/options statements will be defined in the main bind config option, we have no possibility to override them in MAAS.
    - s/maas_server/domain/ because each zone will have its own domain (the zone name take n from NodeGroup.name).

- I've changed MAAS' configuration file named from 'named.conf' to 'maas_named.conf' for clarity and convenience (in a dev environment, I'm planning to write this file next to the fixture's main named.conf configuration file).

- Add task to write the full configuration.  This task will be used when setting up DNS support (after it's been disabled for instance) or when/if we will be wanting to completely rewrite the full DNS configuration. (I confess this could have gone in another branch.)

-- 
https://code.launchpad.net/~rvb/maas/dns-setup-command2/+merge/114396
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/dns-setup-command2 into lp:maas.
=== modified file 'src/provisioningserver/dns/config.py'
--- src/provisioningserver/dns/config.py	2012-07-09 08:20:12 +0000
+++ src/provisioningserver/dns/config.py	2012-07-11 11:27:21 +0000
@@ -33,6 +33,9 @@
 import tempita
 
 
+MAAS_NAMED_CONF_NAME = 'maas_named.conf'
+
+
 class DNSConfigFail(Exception):
     """Raised if there's a problem with a DNS config."""
 
@@ -146,11 +149,11 @@
     """
 
     template_file_name = 'named.conf.template'
-    target_file_name = 'named.conf'
+    target_file_name = MAAS_NAMED_CONF_NAME
 
-    def __init__(self, zone_ids=(), reverse_zone_ids=()):
-        self.zone_ids = zone_ids
-        self.reverse_zone_ids = reverse_zone_ids
+    def __init__(self, zone_names=(), reverse_zone_names=()):
+        self.zone_names = zone_names
+        self.reverse_zone_names = reverse_zone_names
 
     @property
     def template_path(self):
@@ -162,10 +165,12 @@
 
     def get_extra_context(self):
         return {
-            'zones': [DNSZoneConfig(zone_id) for zone_id in self.zone_ids],
+            'zones': [
+                DNSZoneConfig(zone_name)
+                for zone_name in self.zone_names],
             'rev_zones': [
-                RevDNSZoneConfig(reverse_zone_id)
-                for reverse_zone_id in self.reverse_zone_ids],
+                RevDNSZoneConfig(reverse_zone_name)
+                for reverse_zone_name in self.reverse_zone_names],
             'DNS_CONFIG_DIR': conf.DNS_CONFIG_DIR,
             'named_rndc_conf_path':  get_named_rndc_conf_path()
         }
@@ -185,15 +190,15 @@
     """A specialized version of DNSConfig that writes zone files."""
 
     template_file_name = 'zone.template'
-    zone_name_string = '%d'
-    zone_filename_string = 'zone.%d'
+    zone_name_string = '%s'
+    zone_filename_string = 'zone.%s'
 
-    def __init__(self, zone_id):
-        self.zone_id = zone_id
+    def __init__(self, zone_name):
+        self.zone_name = zone_name
 
     @property
     def name(self):
-        return self.zone_name_string % self.zone_id
+        return self.zone_name_string % self.zone_name
 
     @property
     def template_path(self):
@@ -202,7 +207,7 @@
     @property
     def target_path(self):
         return os.path.join(
-            self.target_dir, self.zone_filename_string % self.zone_id)
+            self.target_dir, self.zone_filename_string % self.zone_name)
 
     def get_extra_context(self):
         return {}
@@ -215,5 +220,5 @@
 
     template_file_name = 'zone.template'
     # TODO: create a proper reverse zone template, create test for this class.
-    zone_name_string = '%d.rev'
-    zone_filename_string = 'zone.rev.%d'
+    zone_name_string = '%s.rev'
+    zone_filename_string = 'zone.rev.%s'

=== modified file 'src/provisioningserver/dns/templates/named.conf.template'
--- src/provisioningserver/dns/templates/named.conf.template	2012-07-06 11:02:29 +0000
+++ src/provisioningserver/dns/templates/named.conf.template	2012-07-11 11:27:21 +0000
@@ -1,21 +1,5 @@
 include "{{named_rndc_conf_path}}";
 
-options {
-    listen-on port 53 { any; };
-    directory       "{{ DNS_CONFIG_DIR }}/";
-    dump-file       "{{ DNS_CONFIG_DIR }}/data/cache_dump.db";
-    statistics-file "{{ DNS_CONFIG_DIR }}/data/named_stats.txt";
-    memstatistics-file "{{ DNS_CONFIG_DIR }}/data/named_mem_stats.txt";
-    recursion yes;
-};
-
-logging {
-    channel default_debug {
-    file "data/named.run";
-    severity dynamic;
-    };
-};
-
 # Zone declarations
 {{for zone in zones}}
 zone "{{zone.name}}" {

=== modified file 'src/provisioningserver/dns/templates/zone.template'
--- src/provisioningserver/dns/templates/zone.template	2012-07-06 10:53:19 +0000
+++ src/provisioningserver/dns/templates/zone.template	2012-07-11 11:27:21 +0000
@@ -1,5 +1,5 @@
 $TTL    300
-@   IN    SOA {{maas_server}}. nobody.example.com. (
+@   IN    SOA {{domain}}. nobody.example.com. (
               {{serial}} ; serial
               600 ; Refresh
               1800 ; Retry
@@ -7,7 +7,7 @@
               300 ; TTL
               )
 
-    IN  NS  {{maas_server}}.
+    IN  NS  {{domain}}.
 {{for host in hosts}}
 {{host['hostname']}} IN A {{host['ip']}}
 {{endfor}}

=== modified file 'src/provisioningserver/dns/tests/test_config.py'
--- src/provisioningserver/dns/tests/test_config.py	2012-07-06 15:53:48 +0000
+++ src/provisioningserver/dns/tests/test_config.py	2012-07-11 11:27:21 +0000
@@ -28,6 +28,7 @@
     execute_rndc_command,
     generate_rndc,
     InactiveDNSConfig,
+    MAAS_NAMED_CONF_NAME,
     setup_rndc,
     TEMPLATES_PATH,
     )
@@ -79,7 +80,7 @@
         self.assertEqual(
             (
                 os.path.join(TEMPLATES_PATH, 'named.conf.template'),
-                os.path.join(conf.DNS_CONFIG_DIR, 'named.conf')
+                os.path.join(conf.DNS_CONFIG_DIR, MAAS_NAMED_CONF_NAME)
             ),
             (dnsconfig.template_path, dnsconfig.target_path))
 
@@ -107,18 +108,18 @@
     def test_write_config_writes_config(self):
         target_dir = self.make_dir()
         self.patch(DNSConfig, 'target_dir', target_dir)
-        zone_ids = [random.randint(0, 100)]
-        reverse_zone_ids = [random.randint(0, 100)]
+        zone_names = [factory.getRandomString()]
+        reverse_zone_names = [factory.getRandomString()]
         dnsconfig = DNSConfig(
-            zone_ids=zone_ids, reverse_zone_ids=reverse_zone_ids)
+            zone_names=zone_names, reverse_zone_names=reverse_zone_names)
         dnsconfig.write_config()
         self.assertThat(
-            os.path.join(target_dir, 'named.conf'),
+            os.path.join(target_dir, MAAS_NAMED_CONF_NAME),
             FileContains(
                 matcher=ContainsAll(
                     [
-                        'zone "%d"' % zone_ids[0],
-                        'zone "%d.rev"' % reverse_zone_ids[0],
+                        'zone "%s"' % zone_names[0],
+                        'zone "%s.rev"' % reverse_zone_names[0],
                         'named.conf.rndc',
                     ])))
 
@@ -139,38 +140,38 @@
     """Tests for DNSZoneConfig."""
 
     def test_name_returns_zone_name(self):
-        zone_id = random.randint(0, 100)
-        dnszoneconfig = DNSZoneConfig(zone_id)
-        self.assertEqual(dnszoneconfig.name, '%d' % zone_id)
+        zone_name = factory.getRandomString()
+        dnszoneconfig = DNSZoneConfig(zone_name)
+        self.assertEqual(dnszoneconfig.name, '%s' % zone_name)
 
     def test_DNSZoneConfig_fields(self):
-        zone_id = random.randint(0, 100)
-        dnszoneconfig = DNSZoneConfig(zone_id)
+        zone_name = factory.getRandomString()
+        dnszoneconfig = DNSZoneConfig(zone_name)
         self.assertEqual(
             (
                 os.path.join(TEMPLATES_PATH, 'zone.template'),
-                os.path.join(conf.DNS_CONFIG_DIR, 'zone.%d' % zone_id)
+                os.path.join(conf.DNS_CONFIG_DIR, 'zone.%s' % zone_name)
             ),
             (dnszoneconfig.template_path, dnszoneconfig.target_path))
 
     def test_write_config_writes_zone_config(self):
         target_dir = self.make_dir()
         self.patch(DNSConfig, 'target_dir', target_dir)
-        zone_id = random.randint(0, 100)
-        dnszoneconfig = DNSZoneConfig(zone_id)
-        maas_server = factory.getRandomString()
+        zone_name = factory.getRandomString()
+        dnszoneconfig = DNSZoneConfig(zone_name)
+        domain = factory.getRandomString()
         serial = random.randint(1, 100)
         hosts = [{
             'ip': factory.getRandomIPAddress(),
             'hostname': factory.getRandomString()}]
         dnszoneconfig.write_config(
-            maas_server=maas_server, serial=serial, hosts=hosts)
+            domain=domain, serial=serial, hosts=hosts)
         self.assertThat(
-            os.path.join(target_dir, 'zone.%d' % zone_id),
+            os.path.join(target_dir, 'zone.%s' % zone_name),
             FileContains(
                 matcher=ContainsAll(
                     [
-                        'IN  NS  %s.' % maas_server,
+                        'IN  NS  %s.' % domain,
                         '%s IN A %s' % (
                             hosts[0]['hostname'], hosts[0]['ip']),
                     ])))

=== modified file 'src/provisioningserver/tasks.py'
--- src/provisioningserver/tasks.py	2012-07-06 16:06:21 +0000
+++ src/provisioningserver/tasks.py	2012-07-11 11:27:21 +0000
@@ -17,6 +17,7 @@
     'reload_zone_config',
     'write_dns_config',
     'write_dns_zone_config',
+    'write_full_dns_config',
     'setup_rndc_configuration',
     ]
 
@@ -102,46 +103,80 @@
 
 
 @task
-def reload_zone_config(zone_id):
+def reload_zone_config(zone_name):
     """Use rndc to reload the DNS configuration for a zone."""
-    execute_rndc_command('reload', zone_id)
-
-
-@task
-def write_dns_config(inactive=False, zone_ids=(),
-                     reverse_zone_ids=(), **kwargs):
+    execute_rndc_command('reload', zone_name)
+
+
+@task
+def write_full_dns_config(zones=None, reverse_zones=None,
+                          **kwargs):
+    """Write out the DNS configuration files: the main configuration
+    file and the zone files.
+    :param zones: Mapping between zone names and the zone data used
+        to write the zone config files.
+    :type zones: dict
+    :param reverse_zones: Mapping between reverse zone names and the
+        reverse zone data used to write the reverse zone config
+        files.
+    :type reverse_zones: dict
+    :param **kwargs: Keyword args passed to DNSConfig.write_config()
+    """
+    if zones is None:
+        zones = {}
+    if reverse_zones is None:
+        reverse_zones = {}
+    # Write zone files.
+    for zone_name, zone_data in zones.items():
+        DNSZoneConfig(zone_name).write_config(**zone_data)
+    # TODO: Write reverse zone files.
+    # for zone_name, zone_data in zones.items():
+    #    DNSZoneConfig(zone_name).write_config(**zone_data)
+    # Write main config file.
+    config = DNSConfig(
+        zone_names=list(zones),
+        reverse_zone_names=list(reverse_zones))
+    config.write_config(**kwargs)
+    subtask(reload_dns_config.subtask()).delay()
+
+
+@task
+def write_dns_config(inactive=False, zone_names=(),
+                     reverse_zone_names=(), **kwargs):
     """Write out the DNS configuration file.
 
     :param inactive: Whether or not an inactive (i.e. blank)
         configuration should be written. False by default.
     :type inactive: boolean
-    :param zone_ids: List of zone ids to include as part of the main config.
-    :type zone_ids: list
-    :param reverse_zone_ids: List of reverse zone ids to include as part of
+    :param zone_names: List of zone names to include as part of the
+        main config.
+    :type zone_names: list
+    :param reverse_zone_names: List of reverse zone names to include as part of
         the main config.
-    :type reverse_zone_ids: list
+    :type reverse_zone_names: list
     :param **kwargs: Keyword args passed to DNSConfig.write_config()
     """
     if inactive:
         InactiveDNSConfig().write_config()
     else:
         config = DNSConfig(
-            zone_ids=zone_ids,
-            reverse_zone_ids=reverse_zone_ids)
+            zone_names=zone_names,
+            reverse_zone_names=reverse_zone_names)
         config.write_config(**kwargs)
     subtask(reload_dns_config.subtask()).delay()
 
 
 @task
-def write_dns_zone_config(zone_id, **kwargs):
+def write_dns_zone_config(zone_name, **kwargs):
     """Write out a DNS zone configuration file.
 
-    :param zone_id: The identifier of the zone to write the configuration for.
-    :type zone_id: int
+    :param zone_name: The identifier of the zone to write the configuration
+        for.
+    :type zone_name: basestring
     :param **kwargs: Keyword args passed to DNSZoneConfig.write_config()
     """
-    DNSZoneConfig(zone_id).write_config(**kwargs)
-    subtask(reload_zone_config.subtask(args=[zone_id])).delay()
+    DNSZoneConfig(zone_name).write_config(**kwargs)
+    subtask(reload_zone_config.subtask(args=[zone_name])).delay()
 
 
 @task

=== modified file 'src/provisioningserver/tests/test_tasks.py'
--- src/provisioningserver/tests/test_tasks.py	2012-07-06 16:06:21 +0000
+++ src/provisioningserver/tests/test_tasks.py	2012-07-11 11:27:21 +0000
@@ -22,7 +22,10 @@
 from maastesting.matchers import ContainsAll
 from maastesting.testcase import TestCase
 from provisioningserver import tasks
-from provisioningserver.dns.config import conf
+from provisioningserver.dns.config import (
+    conf,
+    MAAS_NAMED_CONF_NAME,
+    )
 from provisioningserver.enum import POWER_TYPE
 from provisioningserver.power.poweraction import PowerActionFail
 from provisioningserver.tasks import (
@@ -33,6 +36,7 @@
     setup_rndc_configuration,
     write_dns_config,
     write_dns_zone_config,
+    write_full_dns_config,
     write_tftp_config_for_node,
     )
 from testresources import FixtureResource
@@ -123,13 +127,13 @@
         self.patch(tasks, 'execute_rndc_command', self.rndc_recorder)
 
     def test_write_dns_config_writes_file(self):
-        zone_ids = [random.randint(1, 100), random.randint(1, 100)]
-        result = write_dns_config.delay(inactive=False, zone_ids=zone_ids)
+        zone_names = [random.randint(1, 100), random.randint(1, 100)]
+        result = write_dns_config.delay(inactive=False, zone_names=zone_names)
 
         self.assertThat(
             (
                 result.successful(),
-                os.path.join(self.dns_conf_dir, 'named.conf'),
+                os.path.join(self.dns_conf_dir, MAAS_NAMED_CONF_NAME),
                 self.rndc_recorder.calls,
             ),
             MatchesListwise(
@@ -146,7 +150,7 @@
         self.assertThat(
             (
                 result.successful(),
-                os.path.join(self.dns_conf_dir, 'named.conf'),
+                os.path.join(self.dns_conf_dir, MAAS_NAMED_CONF_NAME),
                 self.rndc_recorder.calls,
             ),
             MatchesListwise(
@@ -158,22 +162,22 @@
             result)
 
     def test_write_dns_zone_config_writes_file(self):
-        zone_id = random.randint(1, 100)
+        zone_name = factory.getRandomString()
         result = write_dns_zone_config.delay(
-            zone_id=zone_id, maas_server=factory.getRandomString(),
+            zone_name=zone_name, domain=factory.getRandomString(),
             serial=random.randint(1, 100), hosts=[])
 
         self.assertThat(
             (
                 result.successful(),
-                os.path.join(self.dns_conf_dir, 'zone.%d' % zone_id),
+                os.path.join(self.dns_conf_dir, 'zone.%s' % zone_name),
                 self.rndc_recorder.calls,
             ),
             MatchesListwise(
                 (
                     Equals(True),
                     FileExists(),
-                    Equals([(('reload', zone_id), {})]),
+                    Equals([(('reload', zone_name), {})]),
                 )),
             result)
 
@@ -208,13 +212,46 @@
                 )))
 
     def test_reload_zone_config_issues_zone_reload_command(self):
-        zone_id = random.randint(1, 100)
-        result = reload_zone_config.delay(zone_id)
+        zone_name = factory.getRandomString()
+        result = reload_zone_config.delay(zone_name)
 
         self.assertThat(
             (result.successful(), self.rndc_recorder.calls),
             MatchesListwise(
                 (
                     Equals(True),
-                    Equals([(('reload', zone_id), {})]),
+                    Equals([(('reload', zone_name), {})]),
+                )))
+
+    def test_write_full_dns_config_sets_up_config(self):
+        # write_full_dns_config writes the config file, writes
+        # the zone files, and reloads the dns service.
+        hostname = factory.getRandomString()
+        ip = factory.getRandomIPAddress()
+        zone_name = factory.getRandomString()
+        domain = factory.getRandomString()
+        zones = {
+            zone_name: {
+                'serial': random.randint(1, 100),
+                'hosts': [{'hostname': hostname, 'ip': ip}],
+                'domain': domain,
+            }
+        }
+        result = write_full_dns_config.delay(zones=zones)
+
+        self.assertThat(
+            (
+                result.successful(),
+                self.rndc_recorder.calls,
+                os.path.join(
+                    self.dns_conf_dir, 'zone.%s' % zone_name),
+                os.path.join(
+                    self.dns_conf_dir, MAAS_NAMED_CONF_NAME),
+            ),
+            MatchesListwise(
+                (
+                    Equals(True),
+                    Equals([(('reload',), {})]),
+                    FileExists(),
+                    FileExists(),
                 )))