Merge lp:~mpontillo/maas/subnet-dns-override-maas-dns-for-default-gw--bug-1576116 into lp:~maas-committers/maas/trunk

Proposed by Mike Pontillo
Status: Merged
Approved by: Mike Pontillo
Approved revision: no longer in the source branch.
Merged at revision: 5178
Proposed branch: lp:~mpontillo/maas/subnet-dns-override-maas-dns-for-default-gw--bug-1576116
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 343 lines (+220/-17)
4 files modified
src/maasserver/models/node.py (+60/-5)
src/maasserver/models/tests/test_node.py (+155/-0)
src/maasserver/preseed_network.py (+3/-6)
src/maasserver/tests/test_preseed_network.py (+2/-6)
To merge this branch: bzr merge lp:~mpontillo/maas/subnet-dns-override-maas-dns-for-default-gw--bug-1576116
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+299896@code.launchpad.net

Commit message

When deploying a node, override the MAAS DNS server with the DNS servers specified on the subnet for the default gateway, when specifying DNS servers for the loopback interface.

To post a comment you must log in.
Revision history for this message
Mike Pontillo (mpontillo) wrote :

I think this is ready for review now. This branch implements the work we discussed the other day: making curtin's default DNS servers (for the loopback interface) consistent with the DNS servers on the default gateway's subnet. Previously, the DNS server was always the rack-facing MAAS IP address.

The code was relatively simple, but it was pretty gnarly to unit test all the different permutations.

Revision history for this message
Gavin Panella (allenap) wrote :

Looks good. A few comments but they're all minor.

review: Approve
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Thanks for the review. Some replies below.

Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (1.3 MiB)

The attempt to merge lp:~mpontillo/maas/subnet-dns-override-maas-dns-for-default-gw--bug-1576116 into lp:maas failed. Below is the output from the failed tests.

Hit:1 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial InRelease
Hit:2 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates InRelease
Hit:3 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-backports InRelease
Get:4 http://security.ubuntu.com/ubuntu xenial-security InRelease [94.5 kB]
Fetched 94.5 kB in 0s (225 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
    --no-install-recommends install apache2 archdetect-deb authbind bash bind9 bind9utils build-essential bzr bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport dh-systemd distro-info dnsutils firefox freeipmi-tools git gjs ipython isc-dhcp-common libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-yui3-full libjs-yui3-min libpq-dev make nodejs-legacy npm postgresql pxelinux python3-all python3-apt python3-bson python3-convoy python3-crochet python3-cssselect python3-curtin python3-dev python3-distro-info python3-django python3-django-nose python3-django-piston3 python3-dnspython python3-docutils python3-formencode python3-hivex python3-httplib2 python3-jinja2 python3-jsonschema python3-lxml python3-netaddr python3-netifaces python3-novaclient python3-oauth python3-oauthlib python3-openssl python3-paramiko python3-petname python3-pexpect python3-psycopg2 python3-pyinotify python3-pyparsing python3-pyvmomi python3-requests python3-seamicroclient python3-setuptools python3-simplestreams python3-sphinx python3-tempita python3-twisted python3-txtftp python3-tz python3-yaml python3-zope.interface python-bson python-crochet python-django python-django-piston python-djorm-ext-pgarray python-formencode python-lxml python-netaddr python-netifaces python-pocket-lint python-psycopg2 python-simplejson python-tempita python-twisted python-yaml socat syslinux-common tgt ubuntu-cloudimage-keyring wget xvfb
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-2ubuntu3).
archdetect-deb is already the newest version (1.117ubuntu2).
authbind is already the newest version (2.1.1+nmu1).
build-essential is already the newest version (12.1ubuntu2).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubuntu3).
distro-info is already the newest version (0.14build1).
freeipmi-tools is already the newest version (1.4.11-1ubuntu1).
git is already the newest version (1:2.7.4-0ubuntu1).
isc-dhcp-common is already the newest version (4.3.3-5ubuntu12).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is already the newest version (3.5.1-1ubuntu3).
make is already the newest version (4.1-6).
postgresql is already the newest version (9.5+173).
pxelinux is already the newest version (3:6.03+dfsg-11ubuntu1).
python-django is already the newest version (1.8.7-1ubuntu5)...

Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (31.5 KiB)

The attempt to merge lp:~mpontillo/maas/subnet-dns-override-maas-dns-for-default-gw--bug-1576116 into lp:maas failed. Below is the output from the failed tests.

Get:1 http://security.ubuntu.com/ubuntu xenial-security InRelease [94.5 kB]
Hit:2 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial InRelease
Get:3 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates InRelease [95.7 kB]
Hit:4 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-backports InRelease
Get:5 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates/main amd64 Packages [315 kB]
Get:6 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates/universe amd64 Packages [293 kB]
Fetched 799 kB in 0s (1,768 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
    --no-install-recommends install apache2 archdetect-deb authbind bash bind9 bind9utils build-essential bzr bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport dh-systemd distro-info dnsutils firefox freeipmi-tools git gjs ipython isc-dhcp-common libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-yui3-full libjs-yui3-min libpq-dev make nodejs-legacy npm postgresql pxelinux python3-all python3-apt python3-bson python3-convoy python3-crochet python3-cssselect python3-curtin python3-dev python3-distro-info python3-django python3-django-nose python3-django-piston3 python3-dnspython python3-docutils python3-formencode python3-hivex python3-httplib2 python3-jinja2 python3-jsonschema python3-lxml python3-netaddr python3-netifaces python3-novaclient python3-oauth python3-oauthlib python3-openssl python3-paramiko python3-petname python3-pexpect python3-psycopg2 python3-pyinotify python3-pyparsing python3-pyvmomi python3-requests python3-seamicroclient python3-setuptools python3-simplestreams python3-sphinx python3-tempita python3-twisted python3-txtftp python3-tz python3-yaml python3-zope.interface python-bson python-crochet python-django python-django-piston python-djorm-ext-pgarray python-formencode python-lxml python-netaddr python-netifaces python-pocket-lint python-psycopg2 python-simplejson python-tempita python-twisted python-yaml socat syslinux-common tgt ubuntu-cloudimage-keyring wget xvfb
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-2ubuntu3).
archdetect-deb is already the newest version (1.117ubuntu2).
authbind is already the newest version (2.1.1+nmu1).
build-essential is already the newest version (12.1ubuntu2).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubuntu3).
distro-info is already the newest version (0.14build1).
freeipmi-tools is already the newest version (1.4.11-1ubuntu1).
git is already the newest version (1:2.7.4-0ubuntu1).
isc-dhcp-common is already the newest version (4.3.3-5ubuntu12).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is already the newest version (3.5.1-1u...

Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (29.2 KiB)

The attempt to merge lp:~mpontillo/maas/subnet-dns-override-maas-dns-for-default-gw--bug-1576116 into lp:maas failed. Below is the output from the failed tests.

Hit:1 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial InRelease
Get:2 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates InRelease [95.7 kB]
Get:3 http://security.ubuntu.com/ubuntu xenial-security InRelease [94.5 kB]
Hit:4 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-backports InRelease
Fetched 190 kB in 0s (409 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
    --no-install-recommends install apache2 archdetect-deb authbind bash bind9 bind9utils build-essential bzr bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport dh-systemd distro-info dnsutils firefox freeipmi-tools git gjs ipython isc-dhcp-common libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-yui3-full libjs-yui3-min libpq-dev make nodejs-legacy npm postgresql pxelinux python3-all python3-apt python3-bson python3-convoy python3-crochet python3-cssselect python3-curtin python3-dev python3-distro-info python3-django python3-django-nose python3-django-piston3 python3-dnspython python3-docutils python3-formencode python3-hivex python3-httplib2 python3-jinja2 python3-jsonschema python3-lxml python3-netaddr python3-netifaces python3-novaclient python3-oauth python3-oauthlib python3-openssl python3-paramiko python3-petname python3-pexpect python3-psycopg2 python3-pyinotify python3-pyparsing python3-pyvmomi python3-requests python3-seamicroclient python3-setuptools python3-simplestreams python3-sphinx python3-tempita python3-twisted python3-txtftp python3-tz python3-yaml python3-zope.interface python-bson python-crochet python-django python-django-piston python-djorm-ext-pgarray python-formencode python-lxml python-netaddr python-netifaces python-pocket-lint python-psycopg2 python-simplejson python-tempita python-twisted python-yaml socat syslinux-common tgt ubuntu-cloudimage-keyring wget xvfb
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-2ubuntu3).
archdetect-deb is already the newest version (1.117ubuntu2).
authbind is already the newest version (2.1.1+nmu1).
build-essential is already the newest version (12.1ubuntu2).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubuntu3).
distro-info is already the newest version (0.14build1).
freeipmi-tools is already the newest version (1.4.11-1ubuntu1).
git is already the newest version (1:2.7.4-0ubuntu1).
isc-dhcp-common is already the newest version (4.3.3-5ubuntu12).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is already the newest version (3.5.1-1ubuntu3).
make is already the newest version (4.1-6).
postgresql is already the newest version (9.5+173).
pxelinux is already the newest version (3:6.03+dfsg-11ubuntu1).
python-django is already the newest version (1.8.7-...

Revision history for this message
Mike Pontillo (mpontillo) wrote :

Strange error. Trying again...

https://paste.ubuntu.com/19438855/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/maasserver/models/node.py'
--- src/maasserver/models/node.py 2016-07-06 17:22:11 +0000
+++ src/maasserver/models/node.py 2016-07-15 00:08:33 +0000
@@ -215,8 +215,23 @@
215215
216# Return type from `get_effective_power_info`.216# Return type from `get_effective_power_info`.
217PowerInfo = namedtuple("PowerInfo", (217PowerInfo = namedtuple("PowerInfo", (
218 "can_be_started", "can_be_stopped", "can_be_queried", "power_type",218 "can_be_started",
219 "power_parameters"))219 "can_be_stopped",
220 "can_be_queried",
221 "power_type",
222 "power_parameters",
223))
224
225DefaultGateways = namedtuple("DefaultGateways", (
226 "ipv4",
227 "ipv6",
228))
229
230GatewayDefinition = namedtuple("GatewayDefinition", (
231 "interface_id",
232 "subnet_id",
233 "gateway_ip",
234))
220235
221236
222def generate_node_system_id():237def generate_node_system_id():
@@ -2691,7 +2706,7 @@
2691 interface.id2706 interface.id
2692 """, (self.id,))2707 """, (self.id,))
2693 return [2708 return [
2694 (found[0], found[1], found[2])2709 GatewayDefinition._make((found[0], found[1], found[2]))
2695 for found in cursor.fetchall()2710 for found in cursor.fetchall()
2696 ]2711 ]
26972712
@@ -2743,7 +2758,7 @@
27432758
2744 # Early out if we already have both gateways.2759 # Early out if we already have both gateways.
2745 if gateway_ipv4 and gateway_ipv6:2760 if gateway_ipv4 and gateway_ipv6:
2746 return (gateway_ipv4, gateway_ipv6)2761 return DefaultGateways._make((gateway_ipv4, gateway_ipv6))
27472762
2748 # Get the best guesses for the missing IP families.2763 # Get the best guesses for the missing IP families.
2749 found_gateways = self.get_best_guess_for_default_gateways()2764 found_gateways = self.get_best_guess_for_default_gateways()
@@ -2753,7 +2768,47 @@
2753 if not gateway_ipv6:2768 if not gateway_ipv6:
2754 gateway_ipv6 = self._get_gateway_tuple_by_family(2769 gateway_ipv6 = self._get_gateway_tuple_by_family(
2755 found_gateways, IPADDRESS_FAMILY.IPv6)2770 found_gateways, IPADDRESS_FAMILY.IPv6)
2756 return (gateway_ipv4, gateway_ipv6)2771 return DefaultGateways._make((gateway_ipv4, gateway_ipv6))
2772
2773 def get_default_dns_servers(self):
2774 """Return the default DNS servers for this node."""
2775 # Circular imports.
2776 from maasserver.dns.zonegenerator import get_dns_server_address
2777
2778 gateways = self.get_default_gateways()
2779
2780 # Try first to use DNS servers from default gateway subnets.
2781 if gateways.ipv4 is not None:
2782 subnet = Subnet.objects.get(id=gateways.ipv4.subnet_id)
2783 if subnet.dns_servers is not None and len(subnet.dns_servers) > 0:
2784 # An IPv4 subnet is hosting the default gateway and has DNS
2785 # servers defined. IPv4 DNS servers take first-priority.
2786 return subnet.dns_servers
2787 if gateways.ipv6 is not None:
2788 subnet = Subnet.objects.get(id=gateways.ipv6.subnet_id)
2789 if subnet.dns_servers is not None and len(subnet.dns_servers) > 0:
2790 # An IPv6 subnet is hosting the default gateway and has DNS
2791 # servers defined. IPv6 DNS servers take second-priority.
2792 return subnet.dns_servers
2793
2794 # No default gateway subnet has specific DNS servers defined, so
2795 # use MAAS for the default DNS server.
2796 if gateways.ipv4 is None and gateways.ipv6 is None:
2797 # If there are no default gateways, the default is the MAAS
2798 # region IP address.
2799 maas_dns_server = get_dns_server_address(
2800 rack_controller=self.get_boot_rack_controller())
2801 else:
2802 # Choose an address consistent with the primary address-family
2803 # in use, as indicated by the presence (or not) of a gateway.
2804 # Note that this path is only taken if the MAAS URL is set to
2805 # a hostname, and the hostname resolves to both an IPv4 and an
2806 # IPv6 address.
2807 maas_dns_server = get_dns_server_address(
2808 rack_controller=self.get_boot_rack_controller(),
2809 ipv4=(gateways.ipv4 is not None),
2810 ipv6=(gateways.ipv6 is not None))
2811 return [maas_dns_server]
27572812
2758 def get_boot_purpose(self):2813 def get_boot_purpose(self):
2759 """2814 """
27602815
=== modified file 'src/maasserver/models/tests/test_node.py'
--- src/maasserver/models/tests/test_node.py 2016-06-30 17:03:46 +0000
+++ src/maasserver/models/tests/test_node.py 2016-07-15 00:08:33 +0000
@@ -36,6 +36,7 @@
36from maasserver.enum import (36from maasserver.enum import (
37 FILESYSTEM_GROUP_TYPE,37 FILESYSTEM_GROUP_TYPE,
38 FILESYSTEM_TYPE,38 FILESYSTEM_TYPE,
39 INTERFACE_LINK_TYPE,
39 INTERFACE_TYPE,40 INTERFACE_TYPE,
40 IPADDRESS_TYPE,41 IPADDRESS_TYPE,
41 NODE_PERMISSION,42 NODE_PERMISSION,
@@ -93,6 +94,7 @@
93 NODE_TRANSITIONS,94 NODE_TRANSITIONS,
94)95)
95from maasserver.rpc.testing.fixtures import MockLiveRegionToClusterRPCFixture96from maasserver.rpc.testing.fixtures import MockLiveRegionToClusterRPCFixture
97import maasserver.server_address as server_address_module
96from maasserver.storage_layouts import (98from maasserver.storage_layouts import (
97 StorageLayoutError,99 StorageLayoutError,
98 StorageLayoutMissingBootDiskError,100 StorageLayoutMissingBootDiskError,
@@ -136,6 +138,7 @@
136 commissioning,138 commissioning,
137 disk_erasing,139 disk_erasing,
138)140)
141from netaddr import IPAddress
139from provisioningserver.events import (142from provisioningserver.events import (
140 EVENT_DETAILS,143 EVENT_DETAILS,
141 EVENT_TYPES,144 EVENT_TYPES,
@@ -4303,6 +4306,158 @@
4303 ), node.get_default_gateways())4306 ), node.get_default_gateways())
43044307
43054308
4309class TestGetDefaultDNSServers(MAASServerTestCase):
4310 """Tests for `Node.get_default_dns_servers`."""
4311
4312 def make_Node_with_RackController(
4313 self, ipv4=True, ipv6=True, ipv4_gateway=True, ipv6_gateway=True,
4314 ipv4_subnet_dns=None, ipv6_subnet_dns=None):
4315 ipv4_subnet_dns = [] if ipv4_subnet_dns is None else ipv4_subnet_dns
4316 ipv6_subnet_dns = [] if ipv6_subnet_dns is None else ipv6_subnet_dns
4317 rack_v4 = None
4318 rack_v6 = None
4319 fabric = factory.make_Fabric()
4320 vlan = fabric.get_default_vlan()
4321 if ipv4:
4322 gateway_ip = None if ipv4_gateway else ""
4323 v4_subnet = factory.make_Subnet(
4324 version=4, vlan=vlan, dns_servers=ipv4_subnet_dns,
4325 gateway_ip=gateway_ip)
4326 if ipv6:
4327 gateway_ip = None if ipv6_gateway else ""
4328 v6_subnet = factory.make_Subnet(
4329 version=6, vlan=vlan, dns_servers=ipv6_subnet_dns,
4330 gateway_ip=gateway_ip)
4331 rack = factory.make_RegionRackController()
4332 vlan.primary_rack = rack
4333 vlan.dhcp_on = True
4334 vlan.save()
4335 # In order to determine the correct IP address per-address-family,
4336 # a name lookup is performed on the hostname part of the URL.
4337 # We need to mock that so we can return whatever IP addresses it
4338 # resolves to.
4339 rack.url = "http://region:5240/MAAS/"
4340 if ipv4:
4341 rack_v4 = factory.pick_ip_in_Subnet(v4_subnet)
4342 if ipv6:
4343 rack_v6 = factory.pick_ip_in_Subnet(v6_subnet)
4344
4345 def get_address(hostname, ip_version=4):
4346 """Mock function to return the IP address of the rack based on the
4347 given address family.
4348 """
4349 if ip_version == 4:
4350 return {IPAddress(rack_v4)} if rack_v4 else set()
4351 elif ip_version == 6:
4352 return {IPAddress(rack_v6)} if rack_v6 else set()
4353
4354 resolve_hostname = self.patch(
4355 server_address_module, 'resolve_hostname')
4356 resolve_hostname.side_effect = get_address
4357 rack.interface_set.all().delete()
4358 rackif = factory.make_Interface(vlan=vlan, node=rack)
4359 if ipv4:
4360 rackif.link_subnet(INTERFACE_LINK_TYPE.STATIC, v4_subnet, rack_v4)
4361 if ipv6:
4362 rackif.link_subnet(INTERFACE_LINK_TYPE.STATIC, v6_subnet, rack_v6)
4363 rack.boot_interface = rackif
4364 rack.save()
4365 node = factory.make_Node(status=NODE_STATUS.READY, disable_ipv4=False)
4366 nodeif = factory.make_Interface(vlan=vlan, node=node)
4367 if ipv4:
4368 nodeif.link_subnet(INTERFACE_LINK_TYPE.AUTO, v4_subnet)
4369 if ipv6:
4370 nodeif.link_subnet(INTERFACE_LINK_TYPE.AUTO, v6_subnet)
4371 node.boot_interface = nodeif
4372 node.save()
4373 return rack_v4, rack_v6, node
4374
4375 def test__uses_rack_ipv4_if_ipv4_only_with_no_gateway(self):
4376 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4377 ipv4=True, ipv4_gateway=False, ipv6=False, ipv6_gateway=False)
4378 self.assertThat(node.get_default_dns_servers(), Equals([rack_v4]))
4379
4380 def test__uses_rack_ipv4_if_ipv4_only_with_no_gateway_v4_dns(self):
4381 ipv4_subnet_dns = factory.make_ip_address(ipv6=False)
4382 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4383 ipv4=True, ipv4_gateway=False, ipv6=False, ipv6_gateway=False,
4384 ipv4_subnet_dns=[ipv4_subnet_dns])
4385 self.assertThat(
4386 node.get_default_dns_servers(), Equals([rack_v4]))
4387
4388 def test__uses_rack_ipv6_if_ipv6_only_with_no_gateway_v6_dns(self):
4389 ipv6_subnet_dns = factory.make_ip_address(ipv6=True)
4390 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4391 ipv4=False, ipv4_gateway=False, ipv6=True, ipv6_gateway=False,
4392 ipv6_subnet_dns=[ipv6_subnet_dns])
4393 self.assertThat(node.get_default_dns_servers(), Equals([rack_v6]))
4394
4395 def test__uses_rack_ipv4_if_dual_stack_with_no_gateway(self):
4396 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4397 ipv4=True, ipv4_gateway=False, ipv6=True, ipv6_gateway=False)
4398 self.assertThat(node.get_default_dns_servers(), Equals([rack_v4]))
4399
4400 def test__uses_rack_ipv4_if_dual_stack_with_ipv4_gateway(self):
4401 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4402 ipv4=True, ipv4_gateway=True, ipv6=True, ipv6_gateway=False)
4403 self.assertThat(node.get_default_dns_servers(), Equals([rack_v4]))
4404
4405 def test__uses_subnet_ipv4_if_dual_stack_with_ipv4_gateway_with_dns(self):
4406 ipv4_subnet_dns = factory.make_ip_address(ipv6=False)
4407 ipv6_subnet_dns = factory.make_ip_address(ipv6=True)
4408 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4409 ipv4=True, ipv4_gateway=True, ipv6=True, ipv6_gateway=False,
4410 ipv4_subnet_dns=[ipv4_subnet_dns],
4411 ipv6_subnet_dns=[ipv6_subnet_dns])
4412 self.assertThat(
4413 node.get_default_dns_servers(), Equals([ipv4_subnet_dns]))
4414
4415 def test__uses_rack_ipv6_if_dual_stack_with_ipv6_gateway(self):
4416 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4417 ipv4=True, ipv4_gateway=False, ipv6=True, ipv6_gateway=True)
4418 self.assertThat(node.get_default_dns_servers(), Equals([rack_v6]))
4419
4420 def test__uses_subnet_ipv6_if_dual_stack_with_ipv6_gateway(self):
4421 ipv4_subnet_dns = factory.make_ip_address(ipv6=False)
4422 ipv6_subnet_dns = factory.make_ip_address(ipv6=True)
4423 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4424 ipv4=True, ipv4_gateway=False, ipv6=True, ipv6_gateway=True,
4425 ipv4_subnet_dns=[ipv4_subnet_dns],
4426 ipv6_subnet_dns=[ipv6_subnet_dns])
4427 self.assertThat(
4428 node.get_default_dns_servers(), Equals([ipv6_subnet_dns]))
4429
4430 def test__uses_rack_ipv4_if_ipv4_with_ipv4_gateway(self):
4431 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4432 ipv4=True, ipv4_gateway=True, ipv6=False, ipv6_gateway=False)
4433 self.assertThat(node.get_default_dns_servers(), Equals([rack_v4]))
4434
4435 def test__uses_subnet_ipv4_if_ipv4_stack_with_ipv4_gateway_and_dns(self):
4436 ipv4_subnet_dns = factory.make_ip_address(ipv6=False)
4437 ipv6_subnet_dns = factory.make_ip_address(ipv6=True)
4438 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4439 ipv4=True, ipv4_gateway=True, ipv6=False, ipv6_gateway=False,
4440 ipv4_subnet_dns=[ipv4_subnet_dns],
4441 ipv6_subnet_dns=[ipv6_subnet_dns])
4442 self.assertThat(
4443 node.get_default_dns_servers(), Equals([ipv4_subnet_dns]))
4444
4445 def test__uses_rack_ipv6_if_ipv6_with_ipv6_gateway(self):
4446 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4447 ipv4=False, ipv4_gateway=False, ipv6=True, ipv6_gateway=True)
4448 self.assertThat(node.get_default_dns_servers(), Equals([rack_v6]))
4449
4450 def test__uses_subnet_ipv6_if_ipv6_with_ipv6_gateway_and_dns(self):
4451 ipv4_subnet_dns = factory.make_ip_address(ipv6=False)
4452 ipv6_subnet_dns = factory.make_ip_address(ipv6=True)
4453 rack_v4, rack_v6, node = self.make_Node_with_RackController(
4454 ipv4=False, ipv4_gateway=False, ipv6=True, ipv6_gateway=True,
4455 ipv4_subnet_dns=[ipv4_subnet_dns],
4456 ipv6_subnet_dns=[ipv6_subnet_dns])
4457 self.assertThat(
4458 node.get_default_dns_servers(), Equals([ipv6_subnet_dns]))
4459
4460
4306class TestNode_Start(MAASServerTestCase):4461class TestNode_Start(MAASServerTestCase):
4307 """Tests for Node.start()."""4462 """Tests for Node.start()."""
43084463
43094464
=== modified file 'src/maasserver/preseed_network.py'
--- src/maasserver/preseed_network.py 2016-03-28 13:54:47 +0000
+++ src/maasserver/preseed_network.py 2016-07-15 00:08:33 +0000
@@ -6,10 +6,7 @@
6__all__ = [6__all__ = [
7 ]7 ]
88
9from maasserver.dns.zonegenerator import (9from maasserver.dns.zonegenerator import get_dns_search_paths
10 get_dns_search_paths,
11 get_dns_server_address,
12)
13from maasserver.enum import (10from maasserver.enum import (
14 INTERFACE_TYPE,11 INTERFACE_TYPE,
15 IPADDRESS_FAMILY,12 IPADDRESS_FAMILY,
@@ -24,6 +21,7 @@
24 def __init__(self, node):21 def __init__(self, node):
25 self.node = node22 self.node = node
26 self.gateways = node.get_default_gateways()23 self.gateways = node.get_default_gateways()
24 self.dns_servers = node.get_default_dns_servers()
27 self.gateway_ipv4_set = False25 self.gateway_ipv4_set = False
28 self.gateway_ipv6_set = False26 self.gateway_ipv6_set = False
29 self.operations = {27 self.operations = {
@@ -51,8 +49,7 @@
5149
52 self.network_config.append({50 self.network_config.append({
53 "type": "nameserver",51 "type": "nameserver",
54 "address": get_dns_server_address(52 "address": self.dns_servers,
55 rack_controller=self.node.get_boot_rack_controller()),
56 "search": sorted(get_dns_search_paths()),53 "search": sorted(get_dns_search_paths()),
57 })54 })
5855
5956
=== modified file 'src/maasserver/tests/test_preseed_network.py'
--- src/maasserver/tests/test_preseed_network.py 2016-04-15 23:38:27 +0000
+++ src/maasserver/tests/test_preseed_network.py 2016-07-15 00:08:33 +0000
@@ -8,10 +8,7 @@
8import random8import random
9from textwrap import dedent9from textwrap import dedent
1010
11from maasserver.dns.zonegenerator import (11from maasserver.dns.zonegenerator import get_dns_search_paths
12 get_dns_search_paths,
13 get_dns_server_address,
14)
15from maasserver.enum import (12from maasserver.enum import (
16 INTERFACE_TYPE,13 INTERFACE_TYPE,
17 IPADDRESS_FAMILY,14 IPADDRESS_FAMILY,
@@ -203,8 +200,7 @@
203200
204 def collectDNSConfig(self, node):201 def collectDNSConfig(self, node):
205 config = "- type: nameserver\n address: %s\n search:\n" % (202 config = "- type: nameserver\n address: %s\n search:\n" % (
206 get_dns_server_address(203 repr(node.get_default_dns_servers()))
207 rack_controller=node.get_boot_primary_rack_controller()))
208 dns_searches = sorted(get_dns_search_paths())204 dns_searches = sorted(get_dns_search_paths())
209 for dns_name in dns_searches:205 for dns_name in dns_searches:
210 config += " - %s\n" % dns_name206 config += " - %s\n" % dns_name