Merge ~ltrager/maas:lp1847537_2 into maas:master

Proposed by Lee Trager
Status: Merged
Approved by: Lee Trager
Approved revision: 374b1e48f4979f3ea699b38de10be7c36dc7a7f2
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~ltrager/maas:lp1847537_2
Merge into: maas:master
Diff against target: 925 lines (+402/-78)
12 files modified
src/maasserver/api/discoveries.py (+1/-3)
src/maasserver/api/tests/test_tag.py (+2/-0)
src/maasserver/dhcp.py (+8/-8)
src/maasserver/models/node.py (+44/-4)
src/maasserver/models/tests/test_node.py (+26/-4)
src/maasserver/preseed_network.py (+48/-12)
src/maasserver/testing/factory.py (+25/-19)
src/maasserver/tests/test_dhcp.py (+127/-17)
src/maasserver/tests/test_preseed_network.py (+76/-8)
src/maasserver/triggers/system.py (+3/-2)
src/maasserver/triggers/tests/test_system_listener.py (+39/-1)
src/maasserver/websockets/handlers/tests/test_controller.py (+3/-0)
Reviewer Review Type Date Requested Status
Adam Collard (community) Approve
MAAS Lander Approve
Review via email: mp+375861@code.launchpad.net

Commit message

LP: #1847537 - Don't include DNS in V1 DHCP only config, make static config and dhcpd.conf respect allow_dns

V2 network configuration specifies DNS information per interface while V1
specifies DNS information globally. MAAS always included DNS information for
V1 config due to the global config while V2 config never included DNS
information as it is configured per interface. Now if all interfaces are
being configured with DHCP global DNS information will be omitted from V1
config so the machine gets its DNS information from the DHCP server.

The MAAS DHCP configuration generator and V2 static config now respects the
allow_dns field. Users can now use MAAS provided DNS, specify DNS servers, or
use both. Changing the allow_dns field will now reconfigure the DHCP server.

Description of the change

How DNS servers are configured before and after this patch can be seen at:

https://docs.google.com/spreadsheets/d/1Uw_ZgA5ulxa3RbxEMC0KjeodulSsWIUQhP8uTl3TiD4/edit#gid=0

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp1847537_2 lp:~ltrager/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/6995/console
COMMIT: f0cfc7067a406793823b9f6ed3df22d51ad33bdd

review: Needs Fixing
~ltrager/maas:lp1847537_2 updated
972b18a... by Lee Trager

Merge branch 'master' into lp1847537_2

835c795... by Lee Trager

Fix lint

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp1847537_2 lp:~ltrager/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/6997/console
COMMIT: 835c795bdca9e6a42ed0997a9ad1cbe2d40b3595

review: Needs Fixing
Revision history for this message
Adam Collard (adam-collard) :
~ltrager/maas:lp1847537_2 updated
60b901b... by Lee Trager

Merge branch 'master' into lp1847537_2

7d72620... by Lee Trager

adam-collard fixes

fb74d4d... by Lee Trager

Fix failing tests

374b1e4... by Lee Trager

Remove unneeded distinct

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp1847537_2 lp:~ltrager/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 374b1e48f4979f3ea699b38de10be7c36dc7a7f2

review: Approve
Revision history for this message
Adam Collard (adam-collard) wrote :

Looks good, +1

review: Approve
Revision history for this message
Adam Collard (adam-collard) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/maasserver/api/discoveries.py b/src/maasserver/api/discoveries.py
index 92a768c..d632f2c 100644
--- a/src/maasserver/api/discoveries.py
+++ b/src/maasserver/api/discoveries.py
@@ -452,9 +452,7 @@ def scan_all_rack_networks(
452 kwargs["scan_all"] = scan_all452 kwargs["scan_all"] = scan_all
453 if cidrs is not None:453 if cidrs is not None:
454 kwargs["cidrs"] = cidrs454 kwargs["cidrs"] = cidrs
455 controllers = list(455 controllers = set(RackController.objects.filter_by_subnet_cidrs(cidrs))
456 RackController.objects.filter_by_subnet_cidrs(cidrs)
457 )
458 if ping is not None:456 if ping is not None:
459 kwargs["force_ping"] = ping457 kwargs["force_ping"] = ping
460 if threads is not None:458 if threads is not None:
diff --git a/src/maasserver/api/tests/test_tag.py b/src/maasserver/api/tests/test_tag.py
index f762c31..8c458f5 100644
--- a/src/maasserver/api/tests/test_tag.py
+++ b/src/maasserver/api/tests/test_tag.py
@@ -7,6 +7,7 @@ __all__ = []
77
8import http.client8import http.client
9import json9import json
10from unittest import skip
10from unittest.mock import ANY, call11from unittest.mock import ANY, call
1112
12from django.conf import settings13from django.conf import settings
@@ -370,6 +371,7 @@ class TestTagAPI(APITestCase.ForUser):
370 [rack.system_id], [r["system_id"] for r in parsed_result]371 [rack.system_id], [r["system_id"] for r in parsed_result]
371 )372 )
372373
374 @skip("XXX: ltrager 2919-11-29 bug=1854546")
373 def test_GET_rack_controllers_query_count(self):375 def test_GET_rack_controllers_query_count(self):
374 # Patch middleware so it does not affect query counting.376 # Patch middleware so it does not affect query counting.
375 self.patch(377 self.patch(
diff --git a/src/maasserver/dhcp.py b/src/maasserver/dhcp.py
index aaf3e2a..d9b9299 100644
--- a/src/maasserver/dhcp.py
+++ b/src/maasserver/dhcp.py
@@ -1,4 +1,4 @@
1# Copyright 2012-2016 Canonical Ltd. This software is licensed under the1# Copyright 2012-2019 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""DHCP management module."""4"""DHCP management module."""
@@ -435,13 +435,13 @@ def make_subnet_config(
435 the output from `get_ntp_server_addresses_for_rack`.435 the output from `get_ntp_server_addresses_for_rack`.
436 """436 """
437 ip_network = subnet.get_ipnetwork()437 ip_network = subnet.get_ipnetwork()
438 if subnet.dns_servers is not None and len(subnet.dns_servers) > 0:438 dns_servers = []
439 # Replace MAAS DNS with the servers defined on the subnet.439 if subnet.allow_dns and default_dns_servers:
440 dns_servers = [IPAddress(server) for server in subnet.dns_servers]440 # If the MAAS DNS server is enabled make sure that is used first.
441 elif default_dns_servers is not None and len(default_dns_servers) > 0:441 dns_servers += default_dns_servers
442 dns_servers = default_dns_servers442 if subnet.dns_servers:
443 else:443 # Add DNS user defined DNS servers
444 dns_servers = []444 dns_servers += [IPAddress(server) for server in subnet.dns_servers]
445 if subnets_dhcp_snippets is None:445 if subnets_dhcp_snippets is None:
446 subnets_dhcp_snippets = []446 subnets_dhcp_snippets = []
447447
diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py
index d087f37..c0bd761 100644
--- a/src/maasserver/models/node.py
+++ b/src/maasserver/models/node.py
@@ -4903,16 +4903,56 @@ class Node(CleanSave, TimestampedModel):
4903 # Try first to use DNS servers from default gateway subnets.4903 # Try first to use DNS servers from default gateway subnets.
4904 if ipv4 and gateways.ipv4 is not None:4904 if ipv4 and gateways.ipv4 is not None:
4905 subnet = Subnet.objects.get(id=gateways.ipv4.subnet_id)4905 subnet = Subnet.objects.get(id=gateways.ipv4.subnet_id)
4906 if subnet.dns_servers is not None and len(subnet.dns_servers) > 0:4906 if subnet.dns_servers:
4907 rack_dns = []
4908 for rack in {
4909 self.get_boot_primary_rack_controller(),
4910 self.get_boot_secondary_rack_controller(),
4911 }:
4912 if rack is None:
4913 continue
4914 rack_dns += [
4915 str(ip)
4916 for ip in get_dns_server_addresses(
4917 rack_controller=rack,
4918 ipv4=True,
4919 ipv6=False,
4920 include_alternates=True,
4921 default_region_ip=default_region_ip,
4922 )
4923 if not ip.is_loopback()
4924 ]
4907 # An IPv4 subnet is hosting the default gateway and has DNS4925 # An IPv4 subnet is hosting the default gateway and has DNS
4908 # servers defined. IPv4 DNS servers take first-priority.4926 # servers defined. IPv4 DNS servers take first-priority.
4909 return list(OrderedDict.fromkeys(subnet.dns_servers))4927 return list(
4928 OrderedDict.fromkeys(rack_dns + subnet.dns_servers)
4929 )
4910 if ipv6 and gateways.ipv6 is not None:4930 if ipv6 and gateways.ipv6 is not None:
4911 subnet = Subnet.objects.get(id=gateways.ipv6.subnet_id)4931 subnet = Subnet.objects.get(id=gateways.ipv6.subnet_id)
4912 if subnet.dns_servers is not None and len(subnet.dns_servers) > 0:4932 if subnet.dns_servers:
4933 rack_dns = []
4934 for rack in {
4935 self.get_boot_primary_rack_controller(),
4936 self.get_boot_secondary_rack_controller(),
4937 }:
4938 if rack is None:
4939 continue
4940 rack_dns += [
4941 str(ip)
4942 for ip in get_dns_server_addresses(
4943 rack_controller=rack,
4944 ipv4=False,
4945 ipv6=True,
4946 include_alternates=True,
4947 default_region_ip=default_region_ip,
4948 )
4949 if not ip.is_loopback()
4950 ]
4913 # An IPv6 subnet is hosting the default gateway and has DNS4951 # An IPv6 subnet is hosting the default gateway and has DNS
4914 # servers defined. IPv6 DNS servers take second-priority.4952 # servers defined. IPv6 DNS servers take second-priority.
4915 return list(OrderedDict.fromkeys(subnet.dns_servers))4953 return list(
4954 OrderedDict.fromkeys(rack_dns + subnet.dns_servers)
4955 )
49164956
4917 # Get the routable addresses between the node and all rack controllers,4957 # Get the routable addresses between the node and all rack controllers,
4918 # when the rack proxy should be used (default).4958 # when the rack proxy should be used (default).
diff --git a/src/maasserver/models/tests/test_node.py b/src/maasserver/models/tests/test_node.py
index e98fa74..81382f9 100644
--- a/src/maasserver/models/tests/test_node.py
+++ b/src/maasserver/models/tests/test_node.py
@@ -7971,7 +7971,7 @@ class TestGetDefaultDNSServers(MAASServerTestCase):
7971 ipv6_subnet_dns=[ipv6_subnet_dns],7971 ipv6_subnet_dns=[ipv6_subnet_dns],
7972 )7972 )
7973 self.assertThat(7973 self.assertThat(
7974 node.get_default_dns_servers(), Equals([ipv4_subnet_dns])7974 node.get_default_dns_servers(), Equals([rack_v4, ipv4_subnet_dns])
7975 )7975 )
79767976
7977 def test__uses_rack_ipv6_if_dual_stack_with_ipv6_gateway(self):7977 def test__uses_rack_ipv6_if_dual_stack_with_ipv6_gateway(self):
@@ -7992,7 +7992,7 @@ class TestGetDefaultDNSServers(MAASServerTestCase):
7992 ipv6_subnet_dns=[ipv6_subnet_dns],7992 ipv6_subnet_dns=[ipv6_subnet_dns],
7993 )7993 )
7994 self.assertThat(7994 self.assertThat(
7995 node.get_default_dns_servers(), Equals([ipv6_subnet_dns])7995 node.get_default_dns_servers(), Equals([rack_v6, ipv6_subnet_dns])
7996 )7996 )
79977997
7998 def test__uses_rack_ipv4_if_ipv4_with_ipv4_gateway(self):7998 def test__uses_rack_ipv4_if_ipv4_with_ipv4_gateway(self):
@@ -8013,7 +8013,7 @@ class TestGetDefaultDNSServers(MAASServerTestCase):
8013 ipv6_subnet_dns=[ipv6_subnet_dns],8013 ipv6_subnet_dns=[ipv6_subnet_dns],
8014 )8014 )
8015 self.assertThat(8015 self.assertThat(
8016 node.get_default_dns_servers(), Equals([ipv4_subnet_dns])8016 node.get_default_dns_servers(), Equals([rack_v4, ipv4_subnet_dns])
8017 )8017 )
80188018
8019 def test__uses_rack_ipv6_if_ipv6_with_ipv6_gateway(self):8019 def test__uses_rack_ipv6_if_ipv6_with_ipv6_gateway(self):
@@ -8034,7 +8034,7 @@ class TestGetDefaultDNSServers(MAASServerTestCase):
8034 ipv6_subnet_dns=[ipv6_subnet_dns],8034 ipv6_subnet_dns=[ipv6_subnet_dns],
8035 )8035 )
8036 self.assertThat(8036 self.assertThat(
8037 node.get_default_dns_servers(), Equals([ipv6_subnet_dns])8037 node.get_default_dns_servers(), Equals([rack_v6, ipv6_subnet_dns])
8038 )8038 )
80398039
8040 def test__uses_other_routeable_rack_controllers_ipv4(self):8040 def test__uses_other_routeable_rack_controllers_ipv4(self):
@@ -8083,6 +8083,28 @@ class TestGetDefaultDNSServers(MAASServerTestCase):
8083 Subnet.objects.update(allow_dns=False)8083 Subnet.objects.update(allow_dns=False)
8084 self.assertThat(node.get_default_dns_servers(), Equals([]))8084 self.assertThat(node.get_default_dns_servers(), Equals([]))
80858085
8086 def test__uses_subnet_ipv4_dns_only(self):
8087 # Regression test for LP:1847537
8088 ipv4_subnet_dns = factory.make_ip_address(ipv6=False)
8089 rack_v4, rack_v6, node = self.make_Node_with_RackController(
8090 ipv6=False, ipv4_subnet_dns=[ipv4_subnet_dns]
8091 )
8092 Subnet.objects.update(allow_dns=False)
8093 self.assertItemsEqual(
8094 node.get_default_dns_servers(), [ipv4_subnet_dns]
8095 )
8096
8097 def test__uses_subnet_ipv6_dns_only(self):
8098 # Regression test for LP:1847537
8099 ipv6_subnet_dns = factory.make_ipv6_address()
8100 rack_v4, rack_v6, node = self.make_Node_with_RackController(
8101 ipv4=False, ipv6_subnet_dns=[ipv6_subnet_dns]
8102 )
8103 Subnet.objects.update(allow_dns=False)
8104 self.assertItemsEqual(
8105 node.get_default_dns_servers(), [ipv6_subnet_dns]
8106 )
8107
80868108
8087class TestNode_Start(MAASTransactionServerTestCase):8109class TestNode_Start(MAASTransactionServerTestCase):
8088 """Tests for Node.start()."""8110 """Tests for Node.start()."""
diff --git a/src/maasserver/preseed_network.py b/src/maasserver/preseed_network.py
index e29aca6..fedabde 100644
--- a/src/maasserver/preseed_network.py
+++ b/src/maasserver/preseed_network.py
@@ -11,7 +11,10 @@ from operator import attrgetter
11from netaddr import IPNetwork11from netaddr import IPNetwork
12import yaml12import yaml
1313
14from maasserver.dns.zonegenerator import get_dns_search_paths14from maasserver.dns.zonegenerator import (
15 get_dns_search_paths,
16 get_dns_server_addresses,
17)
15from maasserver.enum import (18from maasserver.enum import (
16 BRIDGE_TYPE,19 BRIDGE_TYPE,
17 INTERFACE_TYPE,20 INTERFACE_TYPE,
@@ -334,9 +337,7 @@ class InterfaceConfiguration:
334 subnet.dns_servers is not None337 subnet.dns_servers is not None
335 and len(subnet.dns_servers) > 0338 and len(subnet.dns_servers) > 0
336 ):339 ):
337 v1_subnet_operation[340 v1_subnet_operation["dns_nameservers"] = []
338 "dns_nameservers"
339 ] = subnet.dns_servers
340 v1_subnet_operation[341 v1_subnet_operation[
341 "dns_search"342 "dns_search"
342 ] = self.node_config.default_search_list343 ] = self.node_config.default_search_list
@@ -347,9 +348,30 @@ class InterfaceConfiguration:
347 ] = self.node_config.default_search_list348 ] = self.node_config.default_search_list
348 if "addresses" not in v2_nameservers:349 if "addresses" not in v2_nameservers:
349 v2_nameservers["addresses"] = []350 v2_nameservers["addresses"] = []
350 v2_nameservers["addresses"].extend(351 for rack in {
351 [server for server in subnet.dns_servers]352 subnet.vlan.primary_rack,
352 )353 subnet.vlan.secondary_rack,
354 }:
355 if rack is None:
356 continue
357 for ip in get_dns_server_addresses(
358 rack_controller=rack,
359 ipv4=(subnet.get_ip_version() == 4),
360 ipv6=(subnet.get_ip_version() == 6),
361 include_alternates=True,
362 ):
363 if ip.is_loopback():
364 continue
365 ip_str = str(ip)
366 v1_subnet_operation["dns_nameservers"].append(
367 ip_str
368 )
369 v2_nameservers["addresses"].append(ip_str)
370 v1_subnet_operation[
371 "dns_nameservers"
372 ] += subnet.dns_servers
373 v2_nameservers["addresses"] += subnet.dns_servers
374
353 matching_subnet_routes = self._get_matching_routes(subnet)375 matching_subnet_routes = self._get_matching_routes(subnet)
354 if len(matching_subnet_routes) > 0 and version == 1:376 if len(matching_subnet_routes) > 0 and version == 1:
355 # For the v1 YAML, the list of routes is rendered377 # For the v1 YAML, the list of routes is rendered
@@ -615,7 +637,24 @@ class NodeNetworkConfiguration:
615 ipv6=self.addr_family_present[6],637 ipv6=self.addr_family_present[6],
616 default_region_ip=default_source_ip,638 default_region_ip=default_source_ip,
617 )639 )
618 if self.default_dns_servers:640 # LP:1847537 - V1 network config only allows global DNS configuration
641 # while V1 allows DNS configuration per interface. If interfaces are
642 # only being manually configured or use DHCP do not include DNS servers
643 # in the configuration. The DHCP server will provide them.
644 dhcp_only = True
645 for i in self.v1_config:
646 for subnet in i.get("subnets", []):
647 if subnet.get("type", "manual") not in [
648 "manual",
649 "dhcp",
650 "dhcp4",
651 "dhcp6",
652 ]:
653 dhcp_only = False
654 break
655 if not dhcp_only:
656 break
657 if self.default_dns_servers and not dhcp_only:
619 self.v1_config.append(658 self.v1_config.append(
620 {659 {
621 "type": "nameserver",660 "type": "nameserver",
@@ -655,10 +694,7 @@ class NodeNetworkConfiguration:
655 """694 """
656 # See also:695 # See also:
657 # https://git.launchpad.net/cloud-init/commit/?id=d29eeccd696 # https://git.launchpad.net/cloud-init/commit/?id=d29eeccd
658 if (697 if len(self.default_dns_servers) > 0:
659 len(self.default_dns_servers) > 0
660 or len(self.default_search_list) > 0
661 ):
662 v2_default_nameservers = {}698 v2_default_nameservers = {}
663 if len(self.default_search_list) > 0:699 if len(self.default_search_list) > 0:
664 v2_default_nameservers.update(700 v2_default_nameservers.update(
diff --git a/src/maasserver/testing/factory.py b/src/maasserver/testing/factory.py
index 59391e6..ef2a825 100644
--- a/src/maasserver/testing/factory.py
+++ b/src/maasserver/testing/factory.py
@@ -312,7 +312,7 @@ class Factory(maastesting.factory.Factory):
312 vlan=None,312 vlan=None,
313 fabric=None,313 fabric=None,
314 owner_data={},314 owner_data={},
315 **kwargs315 **kwargs,
316 ):316 ):
317 if hostname is None:317 if hostname is None:
318 hostname = self.make_string(20)318 hostname = self.make_string(20)
@@ -428,7 +428,7 @@ class Factory(maastesting.factory.Factory):
428 with_empty_script_sets=False,428 with_empty_script_sets=False,
429 bmc=None,429 bmc=None,
430 ephemeral_deploy=False,430 ephemeral_deploy=False,
431 **kwargs431 **kwargs,
432 ):432 ):
433 """Make a :class:`Node`.433 """Make a :class:`Node`.
434434
@@ -479,7 +479,7 @@ class Factory(maastesting.factory.Factory):
479 bmc=bmc,479 bmc=bmc,
480 hardware_uuid=hardware_uuid,480 hardware_uuid=hardware_uuid,
481 ephemeral_deploy=ephemeral_deploy,481 ephemeral_deploy=ephemeral_deploy,
482 **kwargs482 **kwargs,
483 )483 )
484 if bmc is None:484 if bmc is None:
485 # These setters will overwrite the BMC, so don't use them if the485 # These setters will overwrite the BMC, so don't use them if the
@@ -610,7 +610,7 @@ class Factory(maastesting.factory.Factory):
610 owner=owner,610 owner=owner,
611 with_dhcp_rack_primary=False,611 with_dhcp_rack_primary=False,
612 with_dhcp_rack_secondary=False,612 with_dhcp_rack_secondary=False,
613 **kwargs613 **kwargs,
614 )614 )
615 if last_image_sync is undefined:615 if last_image_sync is undefined:
616 node.last_image_sync = timezone.now() - timedelta(616 node.last_image_sync = timezone.now() - timedelta(
@@ -661,7 +661,7 @@ class Factory(maastesting.factory.Factory):
661 power_type=power_type,661 power_type=power_type,
662 power_parameters=power_parameters,662 power_parameters=power_parameters,
663 ip_address=ip_address,663 ip_address=ip_address,
664 **kwargs664 **kwargs,
665 )665 )
666 bmc.save()666 bmc.save()
667 return bmc667 return bmc
@@ -703,7 +703,7 @@ class Factory(maastesting.factory.Factory):
703 power_type=pod_type,703 power_type=pod_type,
704 power_parameters=parameters,704 power_parameters=parameters,
705 ip_address=ip_address,705 ip_address=ip_address,
706 **kwargs706 **kwargs,
707 )707 )
708 pod.save()708 pod.save()
709 return pod709 return pod
@@ -790,7 +790,7 @@ class Factory(maastesting.factory.Factory):
790 name=None,790 name=None,
791 address_ttl=None,791 address_ttl=None,
792 no_ip_addresses=False,792 no_ip_addresses=False,
793 **kwargs793 **kwargs,
794 ):794 ):
795 if "name" in kwargs:795 if "name" in kwargs:
796 name = kwargs["name"]796 name = kwargs["name"]
@@ -842,7 +842,7 @@ class Factory(maastesting.factory.Factory):
842 recommission=None,842 recommission=None,
843 for_hardware=None,843 for_hardware=None,
844 apply_configured_networking=False,844 apply_configured_networking=False,
845 **kwargs845 **kwargs,
846 ):846 ):
847 if for_hardware is None:847 if for_hardware is None:
848 for_hardware = []848 for_hardware = []
@@ -888,7 +888,7 @@ class Factory(maastesting.factory.Factory):
888 recommission=recommission,888 recommission=recommission,
889 for_hardware=for_hardware,889 for_hardware=for_hardware,
890 apply_configured_networking=apply_configured_networking,890 apply_configured_networking=apply_configured_networking,
891 **kwargs891 **kwargs,
892 )892 )
893893
894 def make_ScriptSet(self, last_ping=None, node=None, result_type=None):894 def make_ScriptSet(self, last_ping=None, node=None, result_type=None):
@@ -917,7 +917,7 @@ class Factory(maastesting.factory.Factory):
917 started=None,917 started=None,
918 ended=None,918 ended=None,
919 suppressed=False,919 suppressed=False,
920 **kwargs920 **kwargs,
921 ):921 ):
922 if script_set is None:922 if script_set is None:
923 if script is not None:923 if script is not None:
@@ -989,7 +989,7 @@ class Factory(maastesting.factory.Factory):
989 started=started,989 started=started,
990 ended=ended,990 ended=ended,
991 suppressed=suppressed,991 suppressed=suppressed,
992 **kwargs992 **kwargs,
993 )993 )
994994
995 def make_MAC(self):995 def make_MAC(self):
@@ -1013,7 +1013,7 @@ class Factory(maastesting.factory.Factory):
1013 link_connected=True,1013 link_connected=True,
1014 interface_speed=None,1014 interface_speed=None,
1015 link_speed=None,1015 link_speed=None,
1016 **kwargs1016 **kwargs,
1017 ):1017 ):
1018 """Create a Node that has a Interface which is on a Subnet.1018 """Create a Node that has a Interface which is on a Subnet.
10191019
@@ -1067,6 +1067,10 @@ class Factory(maastesting.factory.Factory):
1067 NODE_STATUS.NEW,1067 NODE_STATUS.NEW,
1068 NODE_STATUS.COMMISSIONING,1068 NODE_STATUS.COMMISSIONING,
1069 NODE_STATUS.FAILED_COMMISSIONING,1069 NODE_STATUS.FAILED_COMMISSIONING,
1070 ] or node.node_type in [
1071 NODE_TYPE.RACK_CONTROLLER,
1072 NODE_TYPE.REGION_CONTROLLER,
1073 NODE_TYPE.REGION_AND_RACK_CONTROLLER,
1070 ]1074 ]
1071 if should_have_default_link_configuration:1075 if should_have_default_link_configuration:
1072 self.make_StaticIPAddress(1076 self.make_StaticIPAddress(
@@ -1152,7 +1156,7 @@ class Factory(maastesting.factory.Factory):
1152 dnsresource=None,1156 dnsresource=None,
1153 cidr=None,1157 cidr=None,
1154 hostname=None,1158 hostname=None,
1155 **kwargs1159 **kwargs,
1156 ):1160 ):
1157 """Create and return a StaticIPAddress model object.1161 """Create and return a StaticIPAddress model object.
11581162
@@ -1207,7 +1211,7 @@ class Factory(maastesting.factory.Factory):
1207 ip=ip,1211 ip=ip,
1208 alloc_type=IPADDRESS_TYPE.DISCOVERED,1212 alloc_type=IPADDRESS_TYPE.DISCOVERED,
1209 subnet=subnet,1213 subnet=subnet,
1210 **kwargs1214 **kwargs,
1211 )1215 )
1212 ipaddress.save()1216 ipaddress.save()
1213 ip = None1217 ip = None
@@ -1348,6 +1352,7 @@ class Factory(maastesting.factory.Factory):
1348 managed=True,1352 managed=True,
1349 space=RANDOM_OR_NONE,1353 space=RANDOM_OR_NONE,
1350 description=None,1354 description=None,
1355 **kwargs,
1351 ):1356 ):
1352 if name is None:1357 if name is None:
1353 name = factory.make_name("name")1358 name = factory.make_name("name")
@@ -1380,6 +1385,7 @@ class Factory(maastesting.factory.Factory):
1380 allow_proxy=allow_proxy,1385 allow_proxy=allow_proxy,
1381 managed=managed,1386 managed=managed,
1382 description="",1387 description="",
1388 **kwargs,
1383 )1389 )
1384 subnet.save()1390 subnet.save()
1385 if subnet.vlan.space != space and space not in (undefined, None):1391 if subnet.vlan.space != space and space not in (undefined, None):
@@ -1810,7 +1816,7 @@ class Factory(maastesting.factory.Factory):
1810 with_static_range=True,1816 with_static_range=True,
1811 dns_servers=None,1817 dns_servers=None,
1812 with_router=True,1818 with_router=True,
1813 **kwargs1819 **kwargs,
1814 ):1820 ):
1815 if cidr is not None:1821 if cidr is not None:
1816 network = IPNetwork(cidr)1822 network = IPNetwork(cidr)
@@ -1839,7 +1845,7 @@ class Factory(maastesting.factory.Factory):
1839 cidr=str(network),1845 cidr=str(network),
1840 gateway_ip=str(router_address),1846 gateway_ip=str(router_address),
1841 dns_servers=dns_servers,1847 dns_servers=dns_servers,
1842 **kwargs1848 **kwargs,
1843 )1849 )
1844 # Create a "dynamic range" for this Subnet.1850 # Create a "dynamic range" for this Subnet.
1845 if with_dynamic_range:1851 if with_dynamic_range:
@@ -3012,7 +3018,7 @@ class Factory(maastesting.factory.Factory):
3012 components=None,3018 components=None,
3013 disabled_pockets=None,3019 disabled_pockets=None,
3014 disabled_components=None,3020 disabled_components=None,
3015 **kwargs3021 **kwargs,
3016 ):3022 ):
3017 if name is None:3023 if name is None:
3018 name = self.make_name("name")3024 name = self.make_name("name")
@@ -3035,7 +3041,7 @@ class Factory(maastesting.factory.Factory):
3035 key=key,3041 key=key,
3036 default=default,3042 default=default,
3037 disabled_components=disabled_components,3043 disabled_components=disabled_components,
3038 **kwargs3044 **kwargs,
3039 )3045 )
30403046
3041 def make_Notification(3047 def make_Notification(
@@ -3047,7 +3053,7 @@ class Factory(maastesting.factory.Factory):
3047 users=False,3053 users=False,
3048 admins=False,3054 admins=False,
3049 context=None,3055 context=None,
3050 category=None3056 category=None,
3051 ):3057 ):
30523058
3053 if context is None:3059 if context is None:
diff --git a/src/maasserver/tests/test_dhcp.py b/src/maasserver/tests/test_dhcp.py
index e60cbdb..6a1924a 100644
--- a/src/maasserver/tests/test_dhcp.py
+++ b/src/maasserver/tests/test_dhcp.py
@@ -1,4 +1,4 @@
1# Copyright 2012-2016 Canonical Ltd. This software is licensed under the1# Copyright 2012-2019 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Tests for DHCP management."""4"""Tests for DHCP management."""
@@ -1280,14 +1280,13 @@ class TestMakeSubnetConfig(MAASServerTestCase):
1280 )1280 )
1281 self.expectThat(config["ntp_servers"], Equals([a2.ip, a1.ip]))1281 self.expectThat(config["ntp_servers"], Equals([a2.ip, a1.ip]))
12821282
1283 def test__overrides_ipv4_dns_from_subnet(self):1283 def test__ipv4_dns_from_subnet(self):
1284 rack_controller = factory.make_RackController(interface=False)1284 rack_controller = factory.make_RackController(interface=False)
1285 vlan = factory.make_VLAN()1285 vlan = factory.make_VLAN()
1286 subnet = factory.make_Subnet(vlan=vlan, version=4)1286 subnet = factory.make_Subnet(
1287 maas_dns = factory.make_ipv4_address()1287 vlan=vlan, version=4, dns_servers=["8.8.8.8", "8.8.4.4"]
1288 subnet_dns_servers = ["8.8.8.8", "8.8.4.4"]1288 )
1289 subnet.dns_servers = subnet_dns_servers1289 maas_dns = IPAddress(factory.make_ipv4_address())
1290 subnet.save()
1291 factory.make_Interface(1290 factory.make_Interface(
1292 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller1291 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller
1293 )1292 )
@@ -1298,17 +1297,71 @@ class TestMakeSubnetConfig(MAASServerTestCase):
1298 )1297 )
1299 self.assertThat(1298 self.assertThat(
1300 config["dns_servers"],1299 config["dns_servers"],
1301 Equals([IPAddress(addr) for addr in subnet_dns_servers]),1300 Equals([maas_dns, IPAddress("8.8.8.8"), IPAddress("8.8.4.4")]),
1302 )1301 )
13031302
1304 def test__overrides_ipv6_dns_from_subnet(self):1303 def test__ipv4_rack_dns_from_subnet(self):
1305 rack_controller = factory.make_RackController(interface=False)1304 rack_controller = factory.make_RackController(interface=False)
1306 vlan = factory.make_VLAN()1305 vlan = factory.make_VLAN()
1307 subnet = factory.make_Subnet(vlan=vlan, version=6)1306 subnet = factory.make_Subnet(vlan=vlan, version=4, dns_servers=[])
1308 maas_dns = factory.make_ipv6_address()1307 maas_dns = IPAddress(factory.make_ipv4_address())
1309 subnet_dns_servers = ["2001:db8::1", "2001:db8::2"]1308 factory.make_Interface(
1310 subnet.dns_servers = subnet_dns_servers1309 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller
1311 subnet.save()1310 )
1311 ntp_servers = [factory.make_name("ntp")]
1312 default_domain = Domain.objects.get_default_domain()
1313 config = dhcp.make_subnet_config(
1314 rack_controller, subnet, [maas_dns], ntp_servers, default_domain
1315 )
1316 self.assertThat(config["dns_servers"], Equals([maas_dns]))
1317
1318 def test__ipv4_user_dns_from_subnet(self):
1319 rack_controller = factory.make_RackController(interface=False)
1320 vlan = factory.make_VLAN()
1321 subnet = factory.make_Subnet(
1322 vlan=vlan,
1323 version=4,
1324 allow_dns=False,
1325 dns_servers=["8.8.8.8", "8.8.4.4"],
1326 )
1327 maas_dns = IPAddress(factory.make_ipv4_address())
1328 factory.make_Interface(
1329 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller
1330 )
1331 ntp_servers = [factory.make_name("ntp")]
1332 default_domain = Domain.objects.get_default_domain()
1333 config = dhcp.make_subnet_config(
1334 rack_controller, subnet, [maas_dns], ntp_servers, default_domain
1335 )
1336 self.assertThat(
1337 config["dns_servers"],
1338 Equals([IPAddress("8.8.8.8"), IPAddress("8.8.4.4")]),
1339 )
1340
1341 def test__ipv4_no_dns_from_subnet(self):
1342 rack_controller = factory.make_RackController(interface=False)
1343 vlan = factory.make_VLAN()
1344 subnet = factory.make_Subnet(
1345 vlan=vlan, version=4, allow_dns=False, dns_servers=[]
1346 )
1347 maas_dns = IPAddress(factory.make_ipv4_address())
1348 factory.make_Interface(
1349 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller
1350 )
1351 ntp_servers = [factory.make_name("ntp")]
1352 default_domain = Domain.objects.get_default_domain()
1353 config = dhcp.make_subnet_config(
1354 rack_controller, subnet, [maas_dns], ntp_servers, default_domain
1355 )
1356 self.assertThat(config["dns_servers"], Equals([]))
1357
1358 def test__ipv6_dns_from_subnet(self):
1359 rack_controller = factory.make_RackController(interface=False)
1360 vlan = factory.make_VLAN()
1361 subnet = factory.make_Subnet(
1362 vlan=vlan, version=6, dns_servers=["2001:db8::1", "2001:db8::2"]
1363 )
1364 maas_dns = IPAddress(factory.make_ipv6_address())
1312 factory.make_Interface(1365 factory.make_Interface(
1313 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller1366 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller
1314 )1367 )
@@ -1319,8 +1372,65 @@ class TestMakeSubnetConfig(MAASServerTestCase):
1319 )1372 )
1320 self.assertThat(1373 self.assertThat(
1321 config["dns_servers"],1374 config["dns_servers"],
1322 Equals([IPAddress(addr) for addr in subnet_dns_servers]),1375 Equals(
1376 [maas_dns, IPAddress("2001:db8::1"), IPAddress("2001:db8::2")]
1377 ),
1378 )
1379
1380 def test__ipv6_rack_dns_from_subnet(self):
1381 rack_controller = factory.make_RackController(interface=False)
1382 vlan = factory.make_VLAN()
1383 subnet = factory.make_Subnet(vlan=vlan, version=6, dns_servers=[])
1384 maas_dns = IPAddress(factory.make_ipv6_address())
1385 factory.make_Interface(
1386 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller
1387 )
1388 ntp_servers = [factory.make_name("ntp")]
1389 default_domain = Domain.objects.get_default_domain()
1390 config = dhcp.make_subnet_config(
1391 rack_controller, subnet, [maas_dns], ntp_servers, default_domain
1392 )
1393 self.assertThat(config["dns_servers"], Equals([maas_dns]))
1394
1395 def test__ipv6_user_dns_from_subnet(self):
1396 rack_controller = factory.make_RackController(interface=False)
1397 vlan = factory.make_VLAN()
1398 subnet = factory.make_Subnet(
1399 vlan=vlan,
1400 version=6,
1401 allow_dns=False,
1402 dns_servers=["2001:db8::1", "2001:db8::2"],
1403 )
1404 maas_dns = IPAddress(factory.make_ipv6_address())
1405 factory.make_Interface(
1406 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller
1407 )
1408 ntp_servers = [factory.make_name("ntp")]
1409 default_domain = Domain.objects.get_default_domain()
1410 config = dhcp.make_subnet_config(
1411 rack_controller, subnet, [maas_dns], ntp_servers, default_domain
1412 )
1413 self.assertThat(
1414 config["dns_servers"],
1415 Equals([IPAddress("2001:db8::1"), IPAddress("2001:db8::2")]),
1416 )
1417
1418 def test__ipv6_no_dns_from_subnet(self):
1419 rack_controller = factory.make_RackController(interface=False)
1420 vlan = factory.make_VLAN()
1421 subnet = factory.make_Subnet(
1422 vlan=vlan, version=6, allow_dns=False, dns_servers=[]
1423 )
1424 maas_dns = IPAddress(factory.make_ipv6_address())
1425 factory.make_Interface(
1426 INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller
1427 )
1428 ntp_servers = [factory.make_name("ntp")]
1429 default_domain = Domain.objects.get_default_domain()
1430 config = dhcp.make_subnet_config(
1431 rack_controller, subnet, [maas_dns], ntp_servers, default_domain
1323 )1432 )
1433 self.assertThat(config["dns_servers"], Equals([]))
13241434
1325 def test__sets_domain_name_from_passed_domain(self):1435 def test__sets_domain_name_from_passed_domain(self):
1326 rack_controller = factory.make_RackController(interface=False)1436 rack_controller = factory.make_RackController(interface=False)
@@ -1928,7 +2038,7 @@ class TestGetDHCPConfigureFor(MAASServerTestCase):
1928 secondary_rack=secondary_rack,2038 secondary_rack=secondary_rack,
1929 )2039 )
1930 ha_subnet = factory.make_ipv4_Subnet_with_IPRanges(2040 ha_subnet = factory.make_ipv4_Subnet_with_IPRanges(
1931 vlan=ha_vlan, dns_servers=["127.0.0.1"]2041 vlan=ha_vlan, allow_dns=False, dns_servers=["127.0.0.1"]
1932 )2042 )
1933 ha_network = ha_subnet.get_ipnetwork()2043 ha_network = ha_subnet.get_ipnetwork()
1934 ha_dhcp_snippets = [2044 ha_dhcp_snippets = [
@@ -1952,7 +2062,7 @@ class TestGetDHCPConfigureFor(MAASServerTestCase):
1952 interface=secondary_interface,2062 interface=secondary_interface,
1953 )2063 )
1954 other_subnet = factory.make_ipv4_Subnet_with_IPRanges(2064 other_subnet = factory.make_ipv4_Subnet_with_IPRanges(
1955 vlan=ha_vlan, dns_servers=["127.0.0.1"]2065 vlan=ha_vlan, allow_dns=False, dns_servers=["127.0.0.1"]
1956 )2066 )
1957 other_network = other_subnet.get_ipnetwork()2067 other_network = other_subnet.get_ipnetwork()
1958 other_dhcp_snippets = [2068 other_dhcp_snippets = [
diff --git a/src/maasserver/tests/test_preseed_network.py b/src/maasserver/tests/test_preseed_network.py
index 3320f85..12ee825 100644
--- a/src/maasserver/tests/test_preseed_network.py
+++ b/src/maasserver/tests/test_preseed_network.py
@@ -9,7 +9,7 @@ from collections import OrderedDict
9import random9import random
10from textwrap import dedent10from textwrap import dedent
1111
12from netaddr import IPAddress, IPNetwork12from netaddr import IPAddress
13from testtools import ExpectedException13from testtools import ExpectedException
14from testtools.matchers import (14from testtools.matchers import (
15 ContainsDict,15 ContainsDict,
@@ -37,6 +37,7 @@ from maasserver.preseed_network import (
37)37)
38from maasserver.testing.factory import factory38from maasserver.testing.factory import factory
39from maasserver.testing.testcase import MAASServerTestCase39from maasserver.testing.testcase import MAASServerTestCase
40from provisioningserver.utils.network import get_source_address
4041
4142
42class AssertNetworkConfigMixin:43class AssertNetworkConfigMixin:
@@ -291,8 +292,23 @@ class AssertNetworkConfigMixin:
291 return ret292 return ret
292293
293 def collect_dns_config(self, node, ipv4=True, ipv6=True):294 def collect_dns_config(self, node, ipv4=True, ipv6=True):
295 gateways = node.get_default_gateways()
296 if ipv4 and gateways.ipv4 is not None:
297 dest_ip = gateways.ipv4.gateway_ip
298 elif ipv6 and gateways.ipv6 is not None:
299 dest_ip = gateways.ipv6.gateway_ip
300 else:
301 dest_ip = None
302 if dest_ip is not None:
303 default_source_ip = get_source_address(dest_ip)
304 else:
305 default_source_ip = None
294 config = "- type: nameserver\n address: %s\n search:\n" % (306 config = "- type: nameserver\n address: %s\n search:\n" % (
295 repr(node.get_default_dns_servers(ipv4=ipv4, ipv6=ipv6))307 repr(
308 node.get_default_dns_servers(
309 ipv4=ipv4, ipv6=ipv6, default_region_ip=default_source_ip
310 )
311 )
296 )312 )
297 domain_name = node.domain.name313 domain_name = node.domain.name
298 dns_searches = self.get_dns_search_list(domain_name)314 dns_searches = self.get_dns_search_list(domain_name)
@@ -460,11 +476,13 @@ class TestDHCPNetworkLayout(MAASServerTestCase, AssertNetworkConfigMixin):
460 scenarios = (("ipv4", {"ip_version": 4}), ("ipv6", {"ip_version": 6}))476 scenarios = (("ipv4", {"ip_version": 4}), ("ipv6", {"ip_version": 6}))
461477
462 def test__dhcp_configurations_rendered(self):478 def test__dhcp_configurations_rendered(self):
479 subnet = factory.make_Subnet(
480 version=self.ip_version, allow_dns=True, dns_servers=["8.8.8.8"]
481 )
463 node = factory.make_Node_with_Interface_on_Subnet(482 node = factory.make_Node_with_Interface_on_Subnet(
464 ip_version=self.ip_version483 ip_version=self.ip_version, subnet=subnet
465 )484 )
466 iface = node.interface_set.first()485 iface = node.interface_set.first()
467 subnet = iface.vlan.subnet_set.first()
468 factory.make_StaticIPAddress(486 factory.make_StaticIPAddress(
469 ip=None,487 ip=None,
470 alloc_type=IPADDRESS_TYPE.DHCP,488 alloc_type=IPADDRESS_TYPE.DHCP,
@@ -480,9 +498,59 @@ class TestDHCPNetworkLayout(MAASServerTestCase, AssertNetworkConfigMixin):
480 resolve_hostname.return_value = {IPAddress("::1")}498 resolve_hostname.return_value = {IPAddress("::1")}
481 config = compose_curtin_network_config(node)499 config = compose_curtin_network_config(node)
482 config_yaml = yaml.safe_load(config[0])500 config_yaml = yaml.safe_load(config[0])
483 self.assertThat(501 self.assertDictEqual(
484 config_yaml["network"]["config"][0]["subnets"][0]["type"],502 {
485 Equals("dhcp" + str(IPNetwork(subnet.cidr).version)),503 "version": 1,
504 "config": [
505 {
506 "id": iface.name,
507 "mac_address": iface.mac_address.raw,
508 "mtu": iface.get_effective_mtu(),
509 "name": iface.name,
510 "type": "physical",
511 "subnets": [
512 {
513 "type": "dhcp4"
514 if self.ip_version == 4
515 else "dhcp6"
516 }
517 ],
518 }
519 ],
520 },
521 config_yaml["network"],
522 )
523
524 def test__dhcp_configurations_rendered_includes_dns_with_static(self):
525 subnet = factory.make_Subnet(
526 version=self.ip_version, allow_dns=True, dns_servers=["8.8.8.8"]
527 )
528 node = factory.make_Node_with_Interface_on_Subnet(
529 ip_version=self.ip_version, subnet=subnet
530 )
531 iface = node.interface_set.first()
532 factory.make_StaticIPAddress(
533 ip=None,
534 alloc_type=IPADDRESS_TYPE.DHCP,
535 interface=iface,
536 subnet=subnet,
537 )
538 # Interface with sticky IP.
539 factory.make_Interface(
540 node=node, subnet=subnet, ip=subnet.get_next_ip_for_allocation()
541 )
542 # Patch resolve_hostname() to return the appropriate network version
543 # IP address for MAAS hostname.
544 resolve_hostname = self.patch(server_address, "resolve_hostname")
545 if self.ip_version == 4:
546 resolve_hostname.return_value = {IPAddress("127.0.0.1")}
547 else:
548 resolve_hostname.return_value = {IPAddress("::1")}
549 config = compose_curtin_network_config(node)
550 config_yaml = yaml.safe_load(config[0])
551 self.assertDictEqual(
552 {"address": ["8.8.8.8"], "search": ["maas"], "type": "nameserver"},
553 config_yaml["network"]["config"][2],
486 )554 )
487555
488556
@@ -1655,7 +1723,7 @@ class TestNetplan(MAASServerTestCase):
1655 "previous_status": NODE_STATUS.COMMISSIONING,1723 "previous_status": NODE_STATUS.COMMISSIONING,
1656 },1724 },
1657 ]1725 ]
1658 )1726 ),
1659 )1727 )
1660 node.set_initial_networking_configuration()1728 node.set_initial_networking_configuration()
1661 v2 = self._render_netplan_dict(node)1729 v2 = self._render_netplan_dict(node)
diff --git a/src/maasserver/triggers/system.py b/src/maasserver/triggers/system.py
index 4b9564c..a673c3c 100644
--- a/src/maasserver/triggers/system.py
+++ b/src/maasserver/triggers/system.py
@@ -1,4 +1,4 @@
1# Copyright 2016 Canonical Ltd. This software is licensed under the1# Copyright 2016-2019 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""4"""
@@ -456,7 +456,8 @@ DHCP_SUBNET_UPDATE = dedent(
456 (OLD.gateway_ip IS NULL AND NEW.gateway_ip IS NOT NULL) OR456 (OLD.gateway_ip IS NULL AND NEW.gateway_ip IS NOT NULL) OR
457 (OLD.gateway_ip IS NOT NULL AND NEW.gateway_ip IS NULL) OR457 (OLD.gateway_ip IS NOT NULL AND NEW.gateway_ip IS NULL) OR
458 host(OLD.gateway_ip) != host(NEW.gateway_ip) OR458 host(OLD.gateway_ip) != host(NEW.gateway_ip) OR
459 OLD.dns_servers != NEW.dns_servers THEN459 OLD.dns_servers != NEW.dns_servers OR
460 OLD.allow_dns != NEW.allow_dns THEN
460 -- Network has changed update alert DHCP if enabled.461 -- Network has changed update alert DHCP if enabled.
461 SELECT * INTO vlan462 SELECT * INTO vlan
462 FROM maasserver_vlan WHERE id = NEW.vlan_id;463 FROM maasserver_vlan WHERE id = NEW.vlan_id;
diff --git a/src/maasserver/triggers/tests/test_system_listener.py b/src/maasserver/triggers/tests/test_system_listener.py
index a63cd56..36e91e8 100644
--- a/src/maasserver/triggers/tests/test_system_listener.py
+++ b/src/maasserver/triggers/tests/test_system_listener.py
@@ -1,4 +1,4 @@
1# Copyright 2016 Canonical Ltd. This software is licensed under the1# Copyright 2016-2019 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Use the `PostgresListenerService` to test all of the triggers from for4"""Use the `PostgresListenerService` to test all of the triggers from for
@@ -1814,6 +1814,44 @@ class TestDHCPSubnetListener(
18141814
1815 @wait_for_reactor1815 @wait_for_reactor
1816 @inlineCallbacks1816 @inlineCallbacks
1817 def test_sends_message_for_vlan_when_allow_dns_changes(self):
1818 yield deferToDatabase(register_system_triggers)
1819 primary_rack = yield deferToDatabase(self.create_rack_controller)
1820 secondary_rack = yield deferToDatabase(self.create_rack_controller)
1821 vlan = yield deferToDatabase(
1822 self.create_vlan,
1823 {
1824 "dhcp_on": True,
1825 "primary_rack": primary_rack,
1826 "secondary_rack": secondary_rack,
1827 },
1828 )
1829 subnet = yield deferToDatabase(self.create_subnet, {"vlan": vlan})
1830
1831 primary_dv = DeferredValue()
1832 secondary_dv = DeferredValue()
1833 listener = self.make_listener_without_delay()
1834 listener.register(
1835 "sys_dhcp_%s" % primary_rack.id, lambda *args: primary_dv.set(args)
1836 )
1837 listener.register(
1838 "sys_dhcp_%s" % secondary_rack.id,
1839 lambda *args: secondary_dv.set(args),
1840 )
1841 yield listener.startService()
1842 try:
1843 yield deferToDatabase(
1844 self.update_subnet,
1845 subnet.id,
1846 {"allow_dns": not subnet.allow_dns},
1847 )
1848 yield primary_dv.get(timeout=2)
1849 yield secondary_dv.get(timeout=2)
1850 finally:
1851 yield listener.stopService()
1852
1853 @wait_for_reactor
1854 @inlineCallbacks
1817 def test_sends_message_for_vlan_when_subnet_deleted(self):1855 def test_sends_message_for_vlan_when_subnet_deleted(self):
1818 yield deferToDatabase(register_system_triggers)1856 yield deferToDatabase(register_system_triggers)
1819 primary_rack = yield deferToDatabase(self.create_rack_controller)1857 primary_rack = yield deferToDatabase(self.create_rack_controller)
diff --git a/src/maasserver/websockets/handlers/tests/test_controller.py b/src/maasserver/websockets/handlers/tests/test_controller.py
index d0916ad..1b94e39 100644
--- a/src/maasserver/websockets/handlers/tests/test_controller.py
+++ b/src/maasserver/websockets/handlers/tests/test_controller.py
@@ -5,6 +5,8 @@
55
6__all__ = []6__all__ = []
77
8from unittest import skip
9
8from fixtures import EnvironmentVariableFixture10from fixtures import EnvironmentVariableFixture
9from testscenarios import multiply_scenarios11from testscenarios import multiply_scenarios
10from testtools.matchers import ContainsDict, Equals12from testtools.matchers import ContainsDict, Equals
@@ -117,6 +119,7 @@ class TestControllerHandler(MAASServerTestCase):
117 "Number of queries has changed; make sure this is expected.",119 "Number of queries has changed; make sure this is expected.",
118 )120 )
119121
122 @skip("XXX: ltrager 2919-11-29 bug=1854546")
120 def test_get_num_queries_is_the_expected_number(self):123 def test_get_num_queries_is_the_expected_number(self):
121 owner = factory.make_admin()124 owner = factory.make_admin()
122 node = factory.make_RegionRackController(owner=owner)125 node = factory.make_RegionRackController(owner=owner)

Subscribers

People subscribed via source and target branches