Merge ~ltrager/maas:lp1847537_2.6 into maas:2.6

Proposed by Lee Trager
Status: Merged
Approved by: Lee Trager
Approved revision: 4006ff2024eb4638b2b1de10cc314126dc0f9577
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~ltrager/maas:lp1847537_2.6
Merge into: maas:2.6
Diff against target: 258 lines (+157/-16)
6 files modified
src/maasserver/dns/tests/test_zonegenerator.py (+12/-1)
src/maasserver/dns/zonegenerator.py (+17/-5)
src/maasserver/models/node.py (+18/-3)
src/maasserver/models/tests/test_node.py (+6/-0)
src/maasserver/preseed_network.py (+12/-7)
src/maasserver/tests/test_preseed_network.py (+92/-0)
Reviewer Review Type Date Requested Status
Lee Trager (community) Approve
Review via email: mp+375166@code.launchpad.net

Commit message

Backport of ad87cfa LP: #1847537 - Respect the allow_dns field when generating V1 network config.

To post a comment you must log in.
Revision history for this message
Lee Trager (ltrager) wrote :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/dns/tests/test_zonegenerator.py b/src/maasserver/dns/tests/test_zonegenerator.py
2index f10aec4..757a8a4 100644
3--- a/src/maasserver/dns/tests/test_zonegenerator.py
4+++ b/src/maasserver/dns/tests/test_zonegenerator.py
5@@ -1,4 +1,4 @@
6-# Copyright 2014-2016 Canonical Ltd. This software is licensed under the
7+# Copyright 2014-2019 Canonical Ltd. This software is licensed under the
8 # GNU Affero General Public License version 3 (see the file LICENSE).
9
10 """Tests for `ZoneGenerator` and supporting cast."""
11@@ -131,6 +131,17 @@ class TestGetDNSServerAddress(MAASServerTestCase):
12 self.expectThat(ip, Equals(result))
13 self.expectThat(resolver, MockAnyCall(hostname, 0))
14
15+ def test_get_dns_server_address_ignores_unallowed_dns(self):
16+ # Regression test for LP:1847537
17+ subnet = factory.make_Subnet(cidr="10.0.0.0/24", allow_dns=False)
18+ ip = factory.make_StaticIPAddress(subnet=subnet)
19+ resolver = self.patch(server_address, "resolve_hostname")
20+ resolver.return_value = {IPAddress(ip.ip)}
21+ rack_controller = factory.make_RackController(
22+ subnet=subnet, url="http://%s" % ip.ip
23+ )
24+ self.assertIsNone(get_dns_server_address(rack_controller))
25+
26
27 class TestGetDNSSearchPaths(MAASServerTestCase):
28
29diff --git a/src/maasserver/dns/zonegenerator.py b/src/maasserver/dns/zonegenerator.py
30index 054c5b4..6713382 100644
31--- a/src/maasserver/dns/zonegenerator.py
32+++ b/src/maasserver/dns/zonegenerator.py
33@@ -1,4 +1,4 @@
34-# Copyright 2014-2016 Canonical Ltd. This software is licensed under the
35+# Copyright 2014-2019 Canonical Ltd. This software is licensed under the
36 # GNU Affero General Public License version 3 (see the file LICENSE).
37
38 """DNS zone generator."""
39@@ -118,7 +118,10 @@ def get_dns_server_address(rack_controller=None, ipv4=True, ipv6=True):
40
41 """
42 iplist = get_dns_server_addresses(rack_controller, ipv4, ipv6)
43- return min(iplist).format()
44+ if iplist:
45+ return min(iplist).format()
46+ else:
47+ return None
48
49
50 def get_dns_server_addresses(
51@@ -157,13 +160,22 @@ def get_dns_server_addresses(
52 "local_config_set --maas-url' command."
53 % e.strerror)
54
55- non_loop = [ip for ip in iplist if not ip.is_loopback()]
56+ # LP:1847537 - Filter out MAAS DNS servers running on subnets which do not
57+ # allow DNS to be provided from MAAS.
58+ filtered_list = [
59+ ip
60+ for ip in iplist
61+ if getattr(
62+ Subnet.objects.get_best_subnet_for_ip(ip), "allow_dns", True
63+ )
64+ ]
65+ non_loop = [ip for ip in filtered_list if not ip.is_loopback()]
66 if len(non_loop) > 0:
67 return non_loop
68 else:
69- for ip in iplist:
70+ for ip in filtered_list:
71 warn_loopback(ip)
72- return iplist
73+ return filtered_list
74
75
76 def get_dns_search_paths():
77diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py
78index 316b751..c33d630 100644
79--- a/src/maasserver/models/node.py
80+++ b/src/maasserver/models/node.py
81@@ -4151,9 +4151,24 @@ class Node(CleanSave, TimestampedModel):
82 # Get the routable addresses between the node and all rack controllers,
83 # when the rack proxy should be used (default).
84 routable_addrs_map = {}
85- if Config.objects.get_config('use_rack_proxy'):
86- routable_addrs_map = get_routable_address_map(
87- RackController.objects.all(), self)
88+ if Config.objects.get_config("use_rack_proxy"):
89+ # LP:1847537 - Filter out MAAS DNS servers running on subnets
90+ # which do not allow DNS to be provided from MAAS.
91+ routable_addrs_map = {}
92+ for node, addresses in get_routable_address_map(
93+ RackController.objects.all(), self
94+ ).items():
95+ filtered_addresses = [
96+ address
97+ for address in addresses
98+ if getattr(
99+ Subnet.objects.get_best_subnet_for_ip(address),
100+ "allow_dns",
101+ True,
102+ )
103+ ]
104+ if filtered_addresses:
105+ routable_addrs_map[node] = filtered_addresses
106
107 # No default gateway subnet has specific DNS servers defined, so
108 # use MAAS for the default DNS server.
109diff --git a/src/maasserver/models/tests/test_node.py b/src/maasserver/models/tests/test_node.py
110index a1739bd..194abe2 100644
111--- a/src/maasserver/models/tests/test_node.py
112+++ b/src/maasserver/models/tests/test_node.py
113@@ -6922,6 +6922,12 @@ class TestGetDefaultDNSServers(MAASServerTestCase):
114 self.assertItemsEqual(
115 node.get_default_dns_servers(), rack_ips)
116
117+ def test__ignores_dns_servers_on_unallowed_subnets(self):
118+ # Regression test for LP:1847537
119+ rack_v4, rack_v6, node = self.make_Node_with_RackController()
120+ Subnet.objects.update(allow_dns=False)
121+ self.assertThat(node.get_default_dns_servers(), Equals([]))
122+
123
124 class TestNode_Start(MAASTransactionServerTestCase):
125 """Tests for Node.start()."""
126diff --git a/src/maasserver/preseed_network.py b/src/maasserver/preseed_network.py
127index c91b74b..d3f50d1 100644
128--- a/src/maasserver/preseed_network.py
129+++ b/src/maasserver/preseed_network.py
130@@ -567,13 +567,18 @@ class NodeNetworkConfiguration:
131 if not self.addr_family_present[6]:
132 self.addr_family_present[4] = True
133 self.default_dns_servers = self.node.get_default_dns_servers(
134- ipv4=self.addr_family_present[4], ipv6=self.addr_family_present[6],
135- default_region_ip=default_source_ip)
136- self.v1_config.append({
137- "type": "nameserver",
138- "address": self.default_dns_servers,
139- "search": self.default_search_list,
140- })
141+ ipv4=self.addr_family_present[4],
142+ ipv6=self.addr_family_present[6],
143+ default_region_ip=default_source_ip,
144+ )
145+ if self.default_dns_servers:
146+ self.v1_config.append(
147+ {
148+ "type": "nameserver",
149+ "address": self.default_dns_servers,
150+ "search": self.default_search_list,
151+ }
152+ )
153 if version == 1:
154 network_config = {
155 "network": {
156diff --git a/src/maasserver/tests/test_preseed_network.py b/src/maasserver/tests/test_preseed_network.py
157index c45b04b..e5db3cc 100644
158--- a/src/maasserver/tests/test_preseed_network.py
159+++ b/src/maasserver/tests/test_preseed_network.py
160@@ -1149,6 +1149,98 @@ class TestNetplan(MAASServerTestCase):
161 }
162 self.expectThat(v1, Equals(expected_v1))
163
164+ def test__multiple_ethernet_interfaces_without_dns(self):
165+ node = factory.make_Node()
166+ vlan = factory.make_VLAN()
167+ subnet = factory.make_Subnet(
168+ cidr="10.0.0.0/24",
169+ gateway_ip="10.0.0.1",
170+ dns_servers=["10.0.0.2"],
171+ allow_dns=False,
172+ )
173+ subnet2 = factory.make_Subnet(
174+ cidr="10.0.1.0/24",
175+ gateway_ip="10.0.1.1",
176+ dns_servers=["10.0.1.2"],
177+ allow_dns=False,
178+ )
179+ eth0 = factory.make_Interface(
180+ node=node, name="eth0", mac_address="00:01:02:03:04:05", vlan=vlan
181+ )
182+ eth1 = factory.make_Interface(
183+ node=node, name="eth1", mac_address="02:01:02:03:04:05"
184+ )
185+ node.boot_interface = eth0
186+ node.save()
187+ factory.make_StaticIPAddress(
188+ interface=eth0,
189+ subnet=subnet,
190+ ip="10.0.0.4",
191+ alloc_type=IPADDRESS_TYPE.DHCP,
192+ )
193+ factory.make_StaticIPAddress(
194+ interface=eth1,
195+ subnet=subnet2,
196+ ip="10.0.1.4",
197+ alloc_type=IPADDRESS_TYPE.DHCP,
198+ )
199+ # Make sure we know when and where the default DNS server will be used.
200+ get_default_dns_servers_mock = self.patch(
201+ node, "get_default_dns_servers"
202+ )
203+ get_default_dns_servers_mock.return_value = []
204+ netplan = self._render_netplan_dict(node)
205+ expected_netplan = {
206+ "network": OrderedDict(
207+ [
208+ ("version", 2),
209+ (
210+ "ethernets",
211+ {
212+ "eth0": {
213+ "match": {"macaddress": "00:01:02:03:04:05"},
214+ "mtu": 1500,
215+ "set-name": "eth0",
216+ "dhcp4": True,
217+ },
218+ "eth1": {
219+ "match": {"macaddress": "02:01:02:03:04:05"},
220+ "mtu": 1500,
221+ "set-name": "eth1",
222+ "dhcp4": True,
223+ },
224+ },
225+ ),
226+ ]
227+ )
228+ }
229+ self.expectThat(netplan, Equals(expected_netplan))
230+ v1 = self._render_v1_dict(node)
231+ expected_v1 = {
232+ "network": {
233+ "version": 1,
234+ "config": [
235+ {
236+ "id": "eth0",
237+ "mac_address": "00:01:02:03:04:05",
238+ "mtu": 1500,
239+ "name": "eth0",
240+ "subnets": [{"type": "dhcp4"}],
241+ "type": "physical",
242+ },
243+ {
244+ "id": "eth1",
245+ "mac_address": "02:01:02:03:04:05",
246+ "mtu": 1500,
247+ "name": "eth1",
248+ "subnets": [{"type": "dhcp4"}],
249+ "type": "physical",
250+ },
251+ ],
252+ }
253+ }
254+ self.expectThat(v1, Equals(expected_v1))
255+
256 def test__ha__default_dns(self):
257 node = factory.make_Node()
258 mock_get_source_address = self.patch(

Subscribers

People subscribed via source and target branches