launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #10304
[Merge] lp:~rvb/maas/add-ns-server into lp:maas
Raphaël Badin has proposed merging lp:~rvb/maas/add-ns-server into lp:maas.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~rvb/maas/add-ns-server/+merge/116824
This branch adds a new method to retrieve the MAAS' DNS server IP. That information will be used in the zone files. We derive that information from settings.DEFAULT_MAAS_URL: we already have the code in place to guess the MAAS server's IP address and we still give the user the possibility to tweak that parameter if needed.
Note that I didn't test the log content. Not sure this is useful as long as every code path is tested.
= Pre-imp =
Talked about this with Jeroen.
--
https://code.launchpad.net/~rvb/maas/add-ns-server/+merge/116824
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/add-ns-server into lp:maas.
=== modified file 'src/maasserver/dns.py'
--- src/maasserver/dns.py 2012-07-25 16:15:24 +0000
+++ src/maasserver/dns.py 2012-07-26 10:31:22 +0000
@@ -19,6 +19,9 @@
import collections
+import logging
+import socket
+from urlparse import urlparse
from django.conf import settings
from django.db.models.signals import (
@@ -26,6 +29,7 @@
post_save,
)
from django.dispatch import receiver
+from maasserver.exceptions import MAASException
from maasserver.models import (
DHCPLease,
Node,
@@ -36,6 +40,11 @@
INT_MAX,
Sequence,
)
+from netaddr import (
+ AddrFormatError,
+ IPAddress,
+ IPNetwork,
+ )
from provisioningserver import tasks
from provisioningserver.dns.config import DNSZoneConfig
@@ -54,6 +63,54 @@
return settings.DNS_CONNECT
+class DNSException(MAASException):
+ """An error occured when setting up MAAS' DNS server."""
+
+
+def _warn_loopback(ip):
+ """Warn if the given IP address is in the loopback network."""
+ if IPAddress(ip) in IPNetwork('127.0.0.1/8'):
+ logging.getLogger('maas').warn(
+ "The DNS server address used will be '%s'. That address is "
+ "in the loopback network. This might not be a problem "
+ "if you're not using MAAS' DNS features or if "
+ "you don't rely on this information. Be sure to set the "
+ "setting DEFAULT_MAAS_URL." % ip)
+
+
+def get_dns_server_address():
+ """Return the DNS server's IP address.
+
+ That address is derived from DEFAULT_MAAS_URL in order to get a sensible
+ default and at the same time give a possibility to the user to change this.
+ """
+ hostname_or_ip = urlparse(settings.DEFAULT_MAAS_URL).netloc.split(':')[0]
+
+ # If 'hostname_or_ip' is a valid IP address, return it.
+ try:
+ IPAddress(hostname_or_ip)
+ _warn_loopback(hostname_or_ip)
+ return hostname_or_ip
+ except AddrFormatError:
+ pass
+
+ # Try to resolve the hostname.
+ try:
+ ip = socket.gethostbyname(hostname_or_ip)
+ _warn_loopback(ip)
+ return ip
+ except socket.error:
+ pass
+
+ # No suitable address has been found.
+ raise DNSException(
+ "Unable to find a suitable IP for the MAAS server. Such an IP "
+ "is required for MAAS' DNS features to work. Make sure that the "
+ "setting DEFAULT_MAAS_URL is defined properly. The IP in "
+ "DEFAULT_MAAS_URL is the one which will be used for the NS record "
+ "in MAAS' zone files.")
+
+
@receiver(post_save, sender=NodeGroup)
def dns_post_save_NodeGroup(sender, instance, created, **kwargs):
"""Create or update DNS zones related to the new nodegroup."""
=== modified file 'src/maasserver/tests/test_dns.py'
--- src/maasserver/tests/test_dns.py 2012-07-25 15:25:42 +0000
+++ src/maasserver/tests/test_dns.py 2012-07-26 10:31:22 +0000
@@ -14,12 +14,15 @@
from itertools import islice
+import socket
from django.conf import settings
from django.core.management import call_command
from maasserver.dns import (
add_zone,
change_dns_zones,
+ DNSException,
+ get_dns_server_address,
is_dns_enabled,
next_zone_serial,
write_full_dns_config,
@@ -33,6 +36,7 @@
from maasserver.testing.testcase import TestCase
from maastesting.bindfixture import BINDServer
from maastesting.celery import CeleryFixture
+from maastesting.fakemethod import FakeMethod
from maastesting.tests.test_bindfixture import dig_call
from netaddr import (
IPNetwork,
@@ -62,6 +66,53 @@
['%0.10d' % i for i in range(initial + 1, initial + 11)],
[next_zone_serial() for i in range(initial, initial + 10)])
+ def test_get_dns_server_address_returns_IP(self):
+ ip = factory.getRandomIPAddress()
+ url = 'http://%s:%d/%s' % (
+ ip, factory.getRandomPort(), factory.getRandomString())
+ self.patch(settings, 'DEFAULT_MAAS_URL', url)
+ self.assertEqual(ip, get_dns_server_address())
+
+ def test_get_dns_server_address_returns_IP_if_IP_is_localhost(self):
+ ip = factory.getRandomIPInNetwork(IPNetwork('127.0.0.1/8'))
+ url = 'http://%s:%d/%s' % (
+ ip, factory.getRandomPort(), factory.getRandomString())
+ self.patch(settings, 'DEFAULT_MAAS_URL', url)
+ self.assertEqual(ip, get_dns_server_address())
+
+ def test_get_dns_server_address_resolves_hostname(self):
+ ip = factory.getRandomIPAddress()
+ resolver = FakeMethod(result=ip)
+ self.patch(socket, 'gethostbyname', resolver)
+ hostname = factory.getRandomString()
+ url = 'http://%s:%d/%s' % (
+ hostname, factory.getRandomPort(), factory.getRandomString())
+ self.patch(settings, 'DEFAULT_MAAS_URL', url)
+ self.assertEqual(
+ (ip, [(hostname, )]),
+ (get_dns_server_address(), resolver.extract_args()))
+
+ def test_get_dns_server_address_resolves_hostname_localhost(self):
+ ip = factory.getRandomIPInNetwork(IPNetwork('127.0.0.1/8'))
+ resolver = FakeMethod(result=ip)
+ self.patch(socket, 'gethostbyname', resolver)
+ hostname = factory.getRandomString()
+ url = 'http://%s:%d/%s' % (
+ hostname, factory.getRandomPort(), factory.getRandomString())
+ self.patch(settings, 'DEFAULT_MAAS_URL', url)
+ self.assertEqual(
+ (ip, [(hostname, )]),
+ (get_dns_server_address(), resolver.extract_args()))
+
+ def test_get_dns_server_address_raises_if_hostname_doesnt_resolve(self):
+ resolver = FakeMethod(failure=socket.error)
+ self.patch(socket, 'gethostbyname', resolver)
+ url = 'http://%s:%d/%s' % (
+ factory.getRandomString(), factory.getRandomPort(),
+ factory.getRandomString())
+ self.patch(settings, 'DEFAULT_MAAS_URL', url)
+ self.assertRaises(DNSException, get_dns_server_address)
+
class TestDNSConfigModifications(TestCase):