Merge ~ddstreet/maas:lp1896684 into maas:master
- Git
- lp:~ddstreet/maas
- lp1896684
- Merge into master
Status: | Merged |
---|---|
Approved by: | Lee Trager |
Approved revision: | b60e8e96657ffce7939970ad8a911042888114cc |
Merge reported by: | MAAS Lander |
Merged at revision: | not available |
Proposed branch: | ~ddstreet/maas:lp1896684 |
Merge into: | maas:master |
Diff against target: |
364 lines (+158/-43) 6 files modified
src/maasserver/dhcp.py (+13/-1) src/maasserver/models/node.py (+6/-11) src/maasserver/models/tests/test_node.py (+20/-0) src/maasserver/preseed_network.py (+26/-21) src/maasserver/tests/test_dhcp.py (+44/-10) src/maasserver/tests/test_preseed_network.py (+49/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lee Trager (community) | Approve | ||
MAAS Lander | Approve | ||
Dan Streetman (community) | Needs Resubmitting | ||
Review via email: mp+391198@code.launchpad.net |
Commit message
LP: #1896684 - If no subnet gateway, only use in-subnet dns addresses
If DHCP is not providing any gateway, it should not provide any
DNS server addresses that aren't directly reachable.
Similarly, if the network preseed is not configuring any gateway,
it should not provide per-interface DNS server addresses, nor default
dns server addresses, that aren't directly reachable.
Only apply rack DNS server address if subnet.allow_dns == True
Description of the change
Dan Streetman (ddstreet) wrote : | # |
> STATUS: FAILED
> LOG: http://
I'm not able to access this CI test system to see the logs.
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: FAILED
LOG: http://
COMMIT: 99132e5871c0a99
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: SUCCESS
COMMIT: fdc4a764ddd4305
Lee Trager (ltrager) wrote : | # |
Thanks for finding and fixing this!
This seems to fix the bug for static IP address, have you tested DHCP? Looking at the code[1] I think its correct but it would be good to verify. Couple of other things
1. This needs commit message to land. It should start with "LP: #1896684 - "
2. Unit tests need to be added to ensure we don't regress this.
3. One comment inline below.
[1] https:/
- bae3958... by Dan Streetman
-
LP: #1896684 - If no subnet gateway, only use in-subnet dns addresses
If DHCP is not providing any gateway, it should not provide any
DNS server addresses that aren't directly reachable.Similarly, if the network preseed is not configuring any gateway,
it should not provide per-interface DNS server addresses, nor default
dns server addresses, that aren't directly reachable.
Dan Streetman (ddstreet) wrote : | # |
> Thanks for finding and fixing this!
>
> This seems to fix the bug for static IP address, have you tested DHCP? Looking
> at the code[1] I think its correct but it would be good to verify.
It does look like it needed a change, i included that in the latest patch
> Couple of
> other things
>
> 1. This needs commit message to land. It should start with "LP: #1896684 - "
ok, done
> 2. Unit tests need to be added to ensure we don't regress this.
if these changes look ok to you, i'll work on adding unit tests for them
> 3. One comment inline below.
response inline (with the old diff) - basically i'm confused as to why there's a in-vlan restriction but no in-subnet restriction, without a gateway (or defined route) a node can't access a separate subnet, even if it's in the same vlan. and with a gateway (or defined route), there's no need for the separate subnet to be in the same vlan.
>
>
> [1] https:/
Dan Streetman (ddstreet) : | # |
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: FAILED
LOG: http://
COMMIT: f5485d47b0aef19
Lee Trager (ltrager) wrote : | # |
That looks good but this still needs unit tests. Also LaunchPad requires the commit message be added on LaunchPad, it doesn't automatically take whats in git.
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: FAILED
LOG: http://
COMMIT: 692f3ca6b93e20f
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: FAILED
LOG: http://
COMMIT: 44003e8d41e3681
- b60e8e9... by Dan Streetman
-
add unit tests
Dan Streetman (ddstreet) wrote : | # |
updated commits, and added test cases...let's see if it passes jenkins
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: FAILED
LOG: http://
COMMIT: d74a74e14352697
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: FAILED
LOG: http://
COMMIT: 82b401ad22dd329
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: SUCCESS
COMMIT: 5e806d38e90f341
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: SUCCESS
COMMIT: b60e8e96657ffce
Lee Trager (ltrager) wrote : | # |
LGTM! Thanks for the fix!
Preview Diff
1 | diff --git a/src/maasserver/dhcp.py b/src/maasserver/dhcp.py |
2 | index 848ff1b..05e9f7a 100644 |
3 | --- a/src/maasserver/dhcp.py |
4 | +++ b/src/maasserver/dhcp.py |
5 | @@ -438,7 +438,15 @@ def make_subnet_config( |
6 | dns_servers = [] |
7 | if subnet.allow_dns and default_dns_servers: |
8 | # If the MAAS DNS server is enabled make sure that is used first. |
9 | - dns_servers += default_dns_servers |
10 | + if subnet.gateway_ip: |
11 | + dns_servers += default_dns_servers |
12 | + else: |
13 | + # if there is no gateway, only provide in-subnet dns servers |
14 | + dns_servers += [ |
15 | + ipaddress |
16 | + for ipaddress in default_dns_servers |
17 | + if ipaddress in ip_network |
18 | + ] |
19 | if subnet.dns_servers: |
20 | # Add DNS user defined DNS servers |
21 | dns_servers += [IPAddress(server) for server in subnet.dns_servers] |
22 | @@ -557,6 +565,10 @@ def get_default_dns_servers(rack_controller, subnet, use_rack_proxy=True): |
23 | :param use_rack_proxy: Whether to proxy DNS through the rack controller |
24 | or not. |
25 | """ |
26 | + if not subnet.allow_dns: |
27 | + # This subnet isn't allowed to use region or rack addresses for dns |
28 | + return [] |
29 | + |
30 | ip_version = subnet.get_ip_version() |
31 | default_region_ip = get_source_address(subnet.get_ipnetwork()) |
32 | try: |
33 | diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py |
34 | index d3e40c2..4882eec 100644 |
35 | --- a/src/maasserver/models/node.py |
36 | +++ b/src/maasserver/models/node.py |
37 | @@ -4937,6 +4937,8 @@ class Node(CleanSave, TimestampedModel): |
38 | if ipv4 and gateways.ipv4 is not None: |
39 | subnet = Subnet.objects.get(id=gateways.ipv4.subnet_id) |
40 | if subnet.dns_servers: |
41 | + if not subnet.allow_dns: |
42 | + return subnet.dns_servers |
43 | rack_dns = [] |
44 | for rack in { |
45 | self.get_boot_primary_rack_controller(), |
46 | @@ -4963,6 +4965,8 @@ class Node(CleanSave, TimestampedModel): |
47 | if ipv6 and gateways.ipv6 is not None: |
48 | subnet = Subnet.objects.get(id=gateways.ipv6.subnet_id) |
49 | if subnet.dns_servers: |
50 | + if not subnet.allow_dns: |
51 | + return subnet.dns_servers |
52 | rack_dns = [] |
53 | for rack in { |
54 | self.get_boot_primary_rack_controller(), |
55 | @@ -5009,18 +5013,9 @@ class Node(CleanSave, TimestampedModel): |
56 | if filtered_addresses: |
57 | routable_addrs_map[node] = filtered_addresses |
58 | |
59 | - # No default gateway subnet has specific DNS servers defined, so |
60 | - # use MAAS for the default DNS server. |
61 | if gateways.ipv4 is None and gateways.ipv6 is None: |
62 | - # If there are no default gateways, the default is the MAAS |
63 | - # region IP address. |
64 | - maas_dns_servers = get_dns_server_addresses( |
65 | - rack_controller=self.get_boot_rack_controller(), |
66 | - ipv4=ipv4, |
67 | - ipv6=ipv6, |
68 | - include_alternates=True, |
69 | - default_region_ip=default_region_ip, |
70 | - ) |
71 | + # node with no gateway can only use routable addrs |
72 | + maas_dns_servers = [] |
73 | routable_addrs_map = { |
74 | node: [ |
75 | address |
76 | diff --git a/src/maasserver/models/tests/test_node.py b/src/maasserver/models/tests/test_node.py |
77 | index 33339a7..b6ac6a4 100644 |
78 | --- a/src/maasserver/models/tests/test_node.py |
79 | +++ b/src/maasserver/models/tests/test_node.py |
80 | @@ -8203,6 +8203,26 @@ class TestGetDefaultDNSServers(MAASServerTestCase): |
81 | node.get_default_dns_servers(), [ipv6_subnet_dns] |
82 | ) |
83 | |
84 | + def test_ignores_other_unroutable_rack_controllers_ipv4(self): |
85 | + # Regression test for LP:1896684 |
86 | + rack_v4, rack_v6, node = self.make_Node_with_RackController( |
87 | + ipv4=True, ipv4_gateway=False, ipv6=False, ipv6_gateway=False |
88 | + ) |
89 | + vlan = node.boot_interface.vlan |
90 | + rack = vlan.primary_rack |
91 | + rackif = rack.interface_set.first() |
92 | + rack_ips = [rack_v4] |
93 | + for _ in range(3): |
94 | + subnet = factory.make_Subnet(vlan=vlan, version=4) |
95 | + ip = factory.make_StaticIPAddress(subnet=subnet, interface=rackif) |
96 | + rack_ips.append(ip.ip) |
97 | + rack.save() |
98 | + resolve_hostname = self.patch(server_address, "resolve_hostname") |
99 | + resolve_hostname.side_effect = lambda hostname, version: set( |
100 | + map(IPAddress, rack_ips) |
101 | + ) |
102 | + self.assertItemsEqual(node.get_default_dns_servers(), [rack_v4]) |
103 | + |
104 | |
105 | class TestNode_Start(MAASTransactionServerTestCase): |
106 | """Tests for Node.start().""" |
107 | diff --git a/src/maasserver/preseed_network.py b/src/maasserver/preseed_network.py |
108 | index 8188603..395f3b3 100644 |
109 | --- a/src/maasserver/preseed_network.py |
110 | +++ b/src/maasserver/preseed_network.py |
111 | @@ -373,32 +373,37 @@ class InterfaceConfiguration: |
112 | if "addresses" not in v2_nameservers: |
113 | v2_nameservers["addresses"] = [] |
114 | |
115 | - for ip in StaticIPAddress.objects.filter( |
116 | - interface__node__in=[ |
117 | - subnet.vlan.primary_rack, |
118 | - subnet.vlan.secondary_rack, |
119 | - ], |
120 | - subnet__vlan=subnet.vlan, |
121 | - alloc_type__in=[ |
122 | - IPADDRESS_TYPE.AUTO, |
123 | - IPADDRESS_TYPE.STICKY, |
124 | - ], |
125 | - ).exclude(ip=None): |
126 | - if ( |
127 | - IPAddress(ip.get_ip()).version |
128 | - == subnet.get_ip_version() |
129 | - and ip.get_ip() not in v2_nameservers["addresses"] |
130 | - ): |
131 | + if subnet.allow_dns: |
132 | + for ip in StaticIPAddress.objects.filter( |
133 | + interface__node__in=[ |
134 | + subnet.vlan.primary_rack, |
135 | + subnet.vlan.secondary_rack, |
136 | + ], |
137 | + subnet__vlan=subnet.vlan, |
138 | + alloc_type__in=[ |
139 | + IPADDRESS_TYPE.AUTO, |
140 | + IPADDRESS_TYPE.STICKY, |
141 | + ], |
142 | + ).exclude(ip=None): |
143 | + if ip.ip in v2_nameservers["addresses"]: |
144 | + continue |
145 | + ip_address = IPAddress(ip.ip) |
146 | + if ip_address.version != subnet.get_ip_version(): |
147 | + continue |
148 | + if not subnet.gateway_ip: |
149 | + if ip_address not in subnet.get_ipnetwork(): |
150 | + # without gateway, only use in-subnet addrs |
151 | + continue |
152 | v1_subnet_operation["dns_nameservers"].append( |
153 | ip.ip |
154 | ) |
155 | v2_nameservers["addresses"].append(ip.ip) |
156 | |
157 | - if subnet.dns_servers: |
158 | - v1_subnet_operation[ |
159 | - "dns_nameservers" |
160 | - ] += subnet.dns_servers |
161 | - v2_nameservers["addresses"] += subnet.dns_servers |
162 | + for ip in subnet.dns_servers: |
163 | + if ip in v2_nameservers["addresses"]: |
164 | + continue |
165 | + v1_subnet_operation["dns_nameservers"].append(ip) |
166 | + v2_nameservers["addresses"].append(ip) |
167 | |
168 | if len(matching_subnet_routes) > 0 and version == 1: |
169 | # For the v1 YAML, the list of routes is rendered |
170 | diff --git a/src/maasserver/tests/test_dhcp.py b/src/maasserver/tests/test_dhcp.py |
171 | index d53f8bb..f445146 100644 |
172 | --- a/src/maasserver/tests/test_dhcp.py |
173 | +++ b/src/maasserver/tests/test_dhcp.py |
174 | @@ -1158,7 +1158,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
175 | config = dhcp.make_subnet_config( |
176 | rack_controller, |
177 | subnet, |
178 | - [factory.make_name("dns")], |
179 | + [factory.make_ipv4_address()], |
180 | [factory.make_name("ntp")], |
181 | default_domain, |
182 | search_list=default_domain.name, |
183 | @@ -1457,7 +1457,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
184 | config = dhcp.make_subnet_config( |
185 | rack_controller, |
186 | subnet, |
187 | - [factory.make_name("dns")], |
188 | + [factory.make_ipv4_address()], |
189 | [factory.make_name("ntp")], |
190 | default_domain, |
191 | ) |
192 | @@ -1474,7 +1474,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
193 | config = dhcp.make_subnet_config( |
194 | rack_controller, |
195 | subnet, |
196 | - [factory.make_name("dns")], |
197 | + [factory.make_ipv4_address()], |
198 | [factory.make_name("ntp")], |
199 | default_domain, |
200 | ) |
201 | @@ -1495,7 +1495,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
202 | config = dhcp.make_subnet_config( |
203 | rack_controller, |
204 | subnet, |
205 | - [factory.make_name("dns")], |
206 | + [factory.make_ipv4_address()], |
207 | [factory.make_name("ntp")], |
208 | default_domain, |
209 | ) |
210 | @@ -1518,7 +1518,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
211 | config = dhcp.make_subnet_config( |
212 | rack_controller, |
213 | subnet, |
214 | - [factory.make_name("dns")], |
215 | + [factory.make_ipv4_address()], |
216 | [factory.make_name("ntp")], |
217 | default_domain, |
218 | search_list=search_list, |
219 | @@ -1546,7 +1546,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
220 | config = dhcp.make_subnet_config( |
221 | rack_controller, |
222 | subnet, |
223 | - [factory.make_name("dns")], |
224 | + [factory.make_ipv6_address()], |
225 | [factory.make_name("ntp")], |
226 | default_domain, |
227 | search_list=search_list, |
228 | @@ -1581,7 +1581,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
229 | config = dhcp.make_subnet_config( |
230 | rack_controller, |
231 | subnet, |
232 | - [factory.make_name("dns")], |
233 | + [factory.make_ipv4_address()], |
234 | [factory.make_name("ntp")], |
235 | default_domain, |
236 | ) |
237 | @@ -1609,7 +1609,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
238 | config = dhcp.make_subnet_config( |
239 | rack_controller, |
240 | subnet, |
241 | - [factory.make_name("dns")], |
242 | + [factory.make_ipv4_address()], |
243 | [factory.make_name("ntp")], |
244 | default_domain, |
245 | failover_peer=failover_peer, |
246 | @@ -1643,7 +1643,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
247 | config = dhcp.make_subnet_config( |
248 | rack_controller, |
249 | subnet, |
250 | - [factory.make_name("dns")], |
251 | + [factory.make_ipv4_address()], |
252 | [factory.make_name("ntp")], |
253 | default_domain, |
254 | ) |
255 | @@ -1664,7 +1664,7 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
256 | config = dhcp.make_subnet_config( |
257 | rack_controller, |
258 | subnet, |
259 | - [factory.make_name("dns")], |
260 | + [factory.make_ipv4_address()], |
261 | [factory.make_name("ntp")], |
262 | default_domain, |
263 | subnets_dhcp_snippets=dhcp_snippets, |
264 | @@ -1681,6 +1681,40 @@ class TestMakeSubnetConfig(MAASServerTestCase): |
265 | config["dhcp_snippets"], |
266 | ) |
267 | |
268 | + def test_subnet_without_gateway_restricts_nameservers(self): |
269 | + network1 = IPNetwork("10.9.8.0/24") |
270 | + network2 = IPNetwork("10.9.9.0/24") |
271 | + rackip1 = "10.9.8.1" |
272 | + rackip2 = "10.9.9.1" |
273 | + rack_controller = factory.make_RackController(interface=False) |
274 | + vlan = factory.make_VLAN() |
275 | + subnet1 = factory.make_Subnet(cidr=str(network1.cidr), vlan=vlan) |
276 | + subnet2 = factory.make_Subnet( |
277 | + cidr=str(network2.cidr), vlan=vlan, gateway_ip=None |
278 | + ) |
279 | + factory.make_Interface( |
280 | + INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=rack_controller |
281 | + ) |
282 | + default_domain = Domain.objects.get_default_domain() |
283 | + config = dhcp.make_subnet_config( |
284 | + rack_controller, |
285 | + subnet1, |
286 | + [rackip1, rackip2], |
287 | + [factory.make_name("ntp")], |
288 | + default_domain, |
289 | + ) |
290 | + self.assertIn(rackip1, config["dns_servers"]) |
291 | + self.assertIn(rackip2, config["dns_servers"]) |
292 | + config = dhcp.make_subnet_config( |
293 | + rack_controller, |
294 | + subnet2, |
295 | + [rackip1, rackip2], |
296 | + [factory.make_name("ntp")], |
297 | + default_domain, |
298 | + ) |
299 | + self.assertNotIn(rackip1, config["dns_servers"]) |
300 | + self.assertIn(rackip2, config["dns_servers"]) |
301 | + |
302 | |
303 | class TestMakeHostsForSubnet(MAASServerTestCase): |
304 | def tests__returns_defined_hosts(self): |
305 | diff --git a/src/maasserver/tests/test_preseed_network.py b/src/maasserver/tests/test_preseed_network.py |
306 | index c19283a..279c203 100644 |
307 | --- a/src/maasserver/tests/test_preseed_network.py |
308 | +++ b/src/maasserver/tests/test_preseed_network.py |
309 | @@ -1761,6 +1761,55 @@ class TestNetplan(MAASServerTestCase): |
310 | v2["network"]["ethernets"][iface.name]["nameservers"], |
311 | ) |
312 | |
313 | + def test_allow_dns_false_does_not_include_rack_controllers(self): |
314 | + # Regression test for LP:1896684 |
315 | + vlan = factory.make_VLAN() |
316 | + nameserver = "1.1.1.1" |
317 | + subnet = factory.make_Subnet( |
318 | + dns_servers=[nameserver], vlan=vlan, allow_dns=False |
319 | + ) |
320 | + rack = factory.make_RackController(subnet=subnet) |
321 | + rack_iface = rack.interface_set.first() |
322 | + factory.make_StaticIPAddress(subnet=subnet, interface=rack_iface) |
323 | + vlan.primary_rack = rack |
324 | + vlan.save() |
325 | + node = factory.make_Node_with_Interface_on_Subnet( |
326 | + status=NODE_STATUS.DEPLOYING, subnet=subnet |
327 | + ) |
328 | + iface = node.interface_set.first() |
329 | + factory.make_StaticIPAddress(subnet=subnet, interface=iface) |
330 | + v2 = self._render_netplan_dict(node) |
331 | + self.assertDictEqual( |
332 | + {"search": ["maas"], "addresses": [nameserver]}, |
333 | + v2["network"]["ethernets"][iface.name]["nameservers"], |
334 | + ) |
335 | + |
336 | + def test_no_gateway_does_not_include_unroutable_controllers(self): |
337 | + # Regression test for LP:1896684 |
338 | + vlan = factory.make_VLAN() |
339 | + subnet1 = factory.make_Subnet( |
340 | + dns_servers=[], vlan=vlan, version=4, gateway_ip=None |
341 | + ) |
342 | + subnet2 = factory.make_Subnet(dns_servers=[], vlan=vlan, version=4) |
343 | + rack = factory.make_RackController(subnet=subnet1) |
344 | + rack_iface = rack.interface_set.first() |
345 | + rack_ip1 = factory.make_StaticIPAddress( |
346 | + subnet=subnet1, interface=rack_iface |
347 | + ) |
348 | + factory.make_StaticIPAddress(subnet=subnet2, interface=rack_iface) |
349 | + vlan.primary_rack = rack |
350 | + vlan.save() |
351 | + node = factory.make_Node_with_Interface_on_Subnet( |
352 | + status=NODE_STATUS.DEPLOYING, subnet=subnet1 |
353 | + ) |
354 | + iface = node.interface_set.first() |
355 | + factory.make_StaticIPAddress(subnet=subnet1, interface=iface) |
356 | + v2 = self._render_netplan_dict(node) |
357 | + self.assertDictEqual( |
358 | + {"search": ["maas"], "addresses": [rack_ip1.ip]}, |
359 | + v2["network"]["ethernets"][iface.name]["nameservers"], |
360 | + ) |
361 | + |
362 | def test_commissioning_dhcp_config(self): |
363 | # Verifies dhcp config is given when commissioning has run |
364 | # or just run and no AUTOIP has been acquired. |
UNIT TESTS
-b lp1896684 lp:~ddstreet/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: FAILED maas-ci. internal: 8080/job/ maas/job/ branch- tester/ 8418/console 159a34678f824f5 9651750e5b
LOG: http://
COMMIT: 69acdb0067cf0a7