Merge ~ltrager/maas:lp1881133 into maas:master

Proposed by Lee Trager
Status: Superseded
Proposed branch: ~ltrager/maas:lp1881133
Merge into: maas:master
Diff against target: 149 lines (+63/-30)
2 files modified
src/maasserver/preseed_network.py (+41/-30)
src/maasserver/tests/test_preseed_network.py (+22/-0)
Reviewer Review Type Date Requested Status
MAAS Lander Pending
MAAS Maintainers Pending
Review via email: mp+388089@code.launchpad.net

Commit message

LP: #1881133 - Always include rack controller IPs for DNS servers.

MAAS was only including the configured URL for controllers which did not
always include all rack controllers the VLAN is configured to use. This
would also sometimes include the region controller's IP even when the
machine is unable to directly access the rack controller.

To post a comment you must log in.

There was an error fetching revisions from git servers. Please try again in a few minutes. If the problem persists, contact Launchpad support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/preseed_network.py b/src/maasserver/preseed_network.py
2index f8a782f..c13f2a3 100644
3--- a/src/maasserver/preseed_network.py
4+++ b/src/maasserver/preseed_network.py
5@@ -8,7 +8,7 @@ __all__ = []
6 from collections import defaultdict, OrderedDict
7 from operator import attrgetter
8
9-from netaddr import IPNetwork
10+from netaddr import IPAddress, IPNetwork
11 import yaml
12
13 from maasserver.dns.zonegenerator import (
14@@ -22,7 +22,7 @@ from maasserver.enum import (
15 IPADDRESS_TYPE,
16 NODE_STATUS,
17 )
18-from maasserver.models import Interface
19+from maasserver.models import Interface, StaticIPAddress
20 from maasserver.models.staticroute import StaticRoute
21 from provisioningserver.utils.netplan import (
22 get_netplan_bond_parameters,
23@@ -362,40 +362,42 @@ class InterfaceConfiguration:
24 v1_subnet_operation if version == 1 else v2_config,
25 version,
26 )
27- if (
28- subnet.dns_servers is not None
29- and len(subnet.dns_servers) > 0
30- ):
31+
32+ if "dns_nameservers" not in v1_subnet_operation:
33 v1_subnet_operation["dns_nameservers"] = []
34 v1_subnet_operation[
35 "dns_search"
36 ] = self.node_config.default_search_list
37- if "nameservers" not in v2_config:
38- v2_config["nameservers"] = v2_nameservers
39- v2_config["nameservers"][
40- "search"
41- ] = self.node_config.default_search_list
42- if "addresses" not in v2_nameservers:
43- v2_nameservers["addresses"] = []
44- for rack in {
45+ if "nameservers" not in v2_config:
46+ v2_config["nameservers"] = v2_nameservers
47+ v2_config["nameservers"][
48+ "search"
49+ ] = self.node_config.default_search_list
50+ if "addresses" not in v2_nameservers:
51+ v2_nameservers["addresses"] = []
52+
53+ for ip in StaticIPAddress.objects.filter(
54+ interface__node__in=[
55 subnet.vlan.primary_rack,
56 subnet.vlan.secondary_rack,
57- }:
58- if rack is None:
59- continue
60- for ip in get_dns_server_addresses(
61- rack_controller=rack,
62- ipv4=(subnet.get_ip_version() == 4),
63- ipv6=(subnet.get_ip_version() == 6),
64- include_alternates=True,
65- ):
66- if ip.is_loopback():
67- continue
68- ip_str = str(ip)
69- v1_subnet_operation["dns_nameservers"].append(
70- ip_str
71- )
72- v2_nameservers["addresses"].append(ip_str)
73+ ],
74+ subnet__vlan=subnet.vlan,
75+ alloc_type__in=[
76+ IPADDRESS_TYPE.AUTO,
77+ IPADDRESS_TYPE.STICKY,
78+ ],
79+ ).exclude(ip=None):
80+ if (
81+ IPAddress(ip.get_ip()).version
82+ == subnet.get_ip_version()
83+ and ip.get_ip() not in v2_nameservers["addresses"]
84+ ):
85+ v1_subnet_operation["dns_nameservers"].append(
86+ ip.ip
87+ )
88+ v2_nameservers["addresses"].append(ip.ip)
89+
90+ if subnet.dns_servers:
91 v1_subnet_operation[
92 "dns_nameservers"
93 ] += subnet.dns_servers
94@@ -408,6 +410,14 @@ class InterfaceConfiguration:
95 matching_subnet_routes, version=version
96 )
97 v1_subnet_operation["routes"] = routes
98+
99+ # Delete if no DNS servers were added.
100+ if len(v1_subnet_operation["dns_nameservers"]) == 0:
101+ del v1_subnet_operation["dns_nameservers"]
102+ del v1_subnet_operation["dns_search"]
103+ if len(v2_nameservers["addresses"]) == 0:
104+ del v2_config["nameservers"]
105+
106 if dhcp_type:
107 v1_config.append({"type": dhcp_type})
108 if dhcp_type == "dhcp":
109@@ -416,6 +426,7 @@ class InterfaceConfiguration:
110 v2_config.update({"dhcp4": True})
111 elif dhcp_type == "dhcp6":
112 v2_config.update({"dhcp6": True})
113+
114 if version == 1:
115 return v1_config
116 elif version == 2:
117diff --git a/src/maasserver/tests/test_preseed_network.py b/src/maasserver/tests/test_preseed_network.py
118index bc49c79..c19283a 100644
119--- a/src/maasserver/tests/test_preseed_network.py
120+++ b/src/maasserver/tests/test_preseed_network.py
121@@ -1739,6 +1739,28 @@ class TestNetplan(MAASServerTestCase):
122 }
123 self.expectThat(v1, Equals(expected_v1))
124
125+ def test_dns_includes_rack_controllers(self):
126+ # Regression test for LP:1881133
127+ vlan = factory.make_VLAN()
128+ subnet = factory.make_Subnet(dns_servers=[], vlan=vlan)
129+ rack = factory.make_RackController(subnet=subnet)
130+ rack_iface = rack.interface_set.first()
131+ rack_ip = factory.make_StaticIPAddress(
132+ subnet=subnet, interface=rack_iface
133+ )
134+ vlan.primary_rack = rack
135+ vlan.save()
136+ node = factory.make_Node_with_Interface_on_Subnet(
137+ status=NODE_STATUS.DEPLOYING, subnet=subnet
138+ )
139+ iface = node.interface_set.first()
140+ factory.make_StaticIPAddress(subnet=subnet, interface=iface)
141+ v2 = self._render_netplan_dict(node)
142+ self.assertDictEqual(
143+ {"search": ["maas"], "addresses": [rack_ip.ip]},
144+ v2["network"]["ethernets"][iface.name]["nameservers"],
145+ )
146+
147 def test_commissioning_dhcp_config(self):
148 # Verifies dhcp config is given when commissioning has run
149 # or just run and no AUTOIP has been acquired.

Subscribers

People subscribed via source and target branches