Merge ~cgrabowski/maas:backport_fix_dynamic_updates_for_glue_zones_to_3.3 into maas:3.3

Proposed by Christian Grabowski
Status: Merged
Approved by: Alberto Donato
Approved revision: feec45549f83bf7110fe47aaf1d3b666a6c22c6d
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~cgrabowski/maas:backport_fix_dynamic_updates_for_glue_zones_to_3.3
Merge into: maas:3.3
Diff against target: 231 lines (+159/-7)
4 files modified
src/maasserver/dns/tests/test_zonegenerator.py (+44/-0)
src/maasserver/dns/zonegenerator.py (+26/-6)
src/provisioningserver/dns/tests/test_zoneconfig.py (+87/-0)
src/provisioningserver/dns/zoneconfig.py (+2/-1)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Christian Grabowski Approve
Review via email: mp+434708@code.launchpad.net

Commit message

fix adding dynamic updates for reverse glue zones
(cherry picked from commit 654d7968ef00118b3ed8dda9769ec1f578e81339)

To post a comment you must log in.
Revision history for this message
Christian Grabowski (cgrabowski) wrote :

self-approving backport

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

LANDING
-b backport_fix_dynamic_updates_for_glue_zones_to_3.3 lp:~cgrabowski/maas/+git/maas into -b 3.3 lp:~maas-committers/maas

STATUS: FAILED BUILD
LOG: http://maas-ci.internal:8080/job/maas-tester/1643/consoleText

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

UNIT TESTS
-b backport_fix_dynamic_updates_for_glue_zones_to_3.3 lp:~cgrabowski/maas/+git/maas into -b 3.3 lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: feec45549f83bf7110fe47aaf1d3b666a6c22c6d

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 5a3aee1..598074f 100644
3--- a/src/maasserver/dns/tests/test_zonegenerator.py
4+++ b/src/maasserver/dns/tests/test_zonegenerator.py
5@@ -48,6 +48,7 @@ from maasserver.utils.orm import transactional
6 from maastesting.factory import factory as maastesting_factory
7 from maastesting.fakemethod import FakeMethod
8 from maastesting.matchers import MockAnyCall, MockCalledOnceWith, MockNotCalled
9+from provisioningserver.dns.config import DynamicDNSUpdate
10 from provisioningserver.dns.zoneconfig import (
11 DNSForwardZoneConfig,
12 DNSReverseZoneConfig,
13@@ -510,6 +511,49 @@ class TestZoneGenerator(MAASServerTestCase):
14 }
15 self.assertEqual(expected_map, zones[0]._other_mapping)
16
17+ def test_glue_receives_correct_dynamic_updates(self):
18+ domain = factory.make_Domain()
19+ subnet = factory.make_Subnet(cidr=str(IPNetwork("10/29").cidr))
20+ sip = factory.make_StaticIPAddress(subnet=subnet)
21+ factory.make_Node_with_Interface_on_Subnet(
22+ subnet=subnet, vlan=subnet.vlan, fabric=subnet.vlan.fabric
23+ )
24+ update_rec = factory.make_DNSResource(
25+ name=factory.make_name(), domain=domain, ip_addresses=[sip]
26+ )
27+ updates = [
28+ DynamicDNSUpdate(
29+ operation="INSERT",
30+ name=update_rec.name,
31+ zone=domain.name,
32+ rectype="A",
33+ answer=sip.ip,
34+ )
35+ ]
36+ zones = ZoneGenerator(
37+ domain,
38+ subnet,
39+ serial=random.randint(0, 65535),
40+ dynamic_updates=updates,
41+ ).as_list()
42+ self.assertCountEqual(zones[0]._dynamic_updates, updates)
43+ self.assertCountEqual(
44+ zones[1]._dynamic_updates,
45+ [
46+ DynamicDNSUpdate.as_reverse_record_update(
47+ updates[0], str(IPNetwork("10/29"))
48+ )
49+ ],
50+ )
51+ self.assertCountEqual(
52+ zones[2]._dynamic_updates,
53+ [
54+ DynamicDNSUpdate.as_reverse_record_update(
55+ updates[0], str(IPNetwork("10/24"))
56+ )
57+ ],
58+ )
59+
60 def test_parent_of_default_domain_gets_glue(self):
61 default_domain = Domain.objects.get_default_domain()
62 default_domain.name = "maas.example.com"
63diff --git a/src/maasserver/dns/zonegenerator.py b/src/maasserver/dns/zonegenerator.py
64index ef31cfa..658147f 100644
65--- a/src/maasserver/dns/zonegenerator.py
66+++ b/src/maasserver/dns/zonegenerator.py
67@@ -452,7 +452,9 @@ class ZoneGenerator:
68 glue = set()
69
70 domain_updates = [
71- DynamicDNSUpdate.as_reverse_record_update(update, subnet)
72+ DynamicDNSUpdate.as_reverse_record_update(
73+ update, str(subnet.cidr)
74+ )
75 for update in dynamic_updates
76 if update.answer
77 and update.answer_is_ip
78@@ -476,6 +478,28 @@ class ZoneGenerator:
79 )
80 # Now provide any remaining rfc2317 glue networks.
81 for network, ranges in rfc2317_glue.items():
82+ exclude_set = {
83+ IPNetwork(s.cidr)
84+ for s in subnets
85+ if network in IPNetwork(s.cidr)
86+ }
87+ domain_updates = []
88+ for update in dynamic_updates:
89+ glue_update = True
90+ for exclude_net in exclude_set:
91+ if (
92+ update.answer
93+ and update.answer_is_ip
94+ and IPAddress(update.answer) in exclude_net
95+ ):
96+ glue_update = False
97+ break
98+ if glue_update:
99+ domain_updates.append(
100+ DynamicDNSUpdate.as_reverse_record_update(
101+ update, str(network)
102+ )
103+ )
104 yield DNSReverseZoneConfig(
105 ns_host_name,
106 serial=serial,
107@@ -483,11 +507,7 @@ class ZoneGenerator:
108 network=network,
109 ns_host_name=ns_host_name,
110 rfc2317_ranges=ranges,
111- exclude={
112- IPNetwork(s.cidr)
113- for s in subnets
114- if network in IPNetwork(s.cidr)
115- },
116+ exclude=exclude_set,
117 dynamic_updates=domain_updates,
118 force_config_write=force_config_write,
119 )
120diff --git a/src/provisioningserver/dns/tests/test_zoneconfig.py b/src/provisioningserver/dns/tests/test_zoneconfig.py
121index 948d219..24e18e1 100644
122--- a/src/provisioningserver/dns/tests/test_zoneconfig.py
123+++ b/src/provisioningserver/dns/tests/test_zoneconfig.py
124@@ -967,6 +967,93 @@ class TestDNSReverseZoneConfig(MAASTestCase):
125 stdin=expected_stdin.encode("ascii"),
126 )
127
128+ def test_glue_network_zone_contains_appropriate_dynamic_updates(self):
129+ patch_zone_file_config_path(self)
130+ domain = factory.make_string()
131+ network = IPNetwork("10.0.0.0/26")
132+ glue_network = IPNetwork("10.0.0.0/24")
133+ ip1 = factory.pick_ip_in_network(network)
134+ ip2 = factory.pick_ip_in_network(network)
135+ hostname1 = f"{factory.make_string()}.{domain}"
136+ hostname2 = f"{factory.make_string()}.{domain}"
137+ fwd_updates = [
138+ DynamicDNSUpdate(
139+ operation="INSERT",
140+ zone=domain,
141+ name=hostname1,
142+ rectype="A",
143+ answer=ip1,
144+ ),
145+ DynamicDNSUpdate(
146+ operation="INSERT",
147+ zone=domain,
148+ name=hostname2,
149+ rectype="A",
150+ answer=ip2,
151+ ),
152+ ]
153+ rev_updates = [
154+ DynamicDNSUpdate.as_reverse_record_update(update, str(network))
155+ for update in fwd_updates
156+ ]
157+ zone = DNSReverseZoneConfig(
158+ domain,
159+ serial=random.randint(1, 100),
160+ network=network,
161+ dynamic_updates=rev_updates,
162+ )
163+ glue_rev_updates = [
164+ DynamicDNSUpdate.as_reverse_record_update(
165+ update, str(glue_network)
166+ )
167+ for update in fwd_updates
168+ ]
169+ glue_zone = DNSReverseZoneConfig(
170+ domain,
171+ serial=random.randint(1, 100),
172+ network=glue_network,
173+ dynamic_updates=glue_rev_updates,
174+ )
175+ expected_stdin = "\n".join(
176+ [
177+ "server localhost",
178+ "zone 0-26.0.0.10.in-addr.arpa",
179+ f"update add {IPAddress(ip1).reverse_dns} {zone.default_ttl} PTR {hostname1}",
180+ f"update add {IPAddress(ip2).reverse_dns} {zone.default_ttl} PTR {hostname2}",
181+ f"update add 0-26.0.0.10.in-addr.arpa {zone.default_ttl} SOA 0-26.0.0.10.in-addr.arpa. nobody.example.com. {zone.serial} 600 1800 604800 {zone.default_ttl}",
182+ "send\n",
183+ ]
184+ )
185+ glue_expected_stdin = "\n".join(
186+ [
187+ "server localhost",
188+ "zone 0.0.10.in-addr.arpa",
189+ f"update add {IPAddress(ip1).reverse_dns} {zone.default_ttl} PTR {hostname1}",
190+ f"update add {IPAddress(ip2).reverse_dns} {zone.default_ttl} PTR {hostname2}",
191+ f"update add 0.0.10.in-addr.arpa {glue_zone.default_ttl} SOA 0.0.10.in-addr.arpa. nobody.example.com. {glue_zone.serial} 600 1800 604800 {glue_zone.default_ttl}",
192+ "send\n",
193+ ]
194+ )
195+ run_command = self.patch(actions, "run_command")
196+ glue_zone.write_config()
197+ glue_zone.write_config()
198+ run_command.assert_called_with(
199+ "nsupdate",
200+ "-k",
201+ get_nsupdate_key_path(),
202+ "-v",
203+ stdin=glue_expected_stdin.encode("ascii"),
204+ )
205+ zone.write_config()
206+ zone.write_config()
207+ run_command.assert_called_with(
208+ "nsupdate",
209+ "-k",
210+ get_nsupdate_key_path(),
211+ "-v",
212+ stdin=expected_stdin.encode("ascii"),
213+ )
214+
215
216 class TestDNSReverseZoneConfig_GetGenerateDirectives(MAASTestCase):
217 """Tests for `DNSReverseZoneConfig.get_GENERATE_directives()`."""
218diff --git a/src/provisioningserver/dns/zoneconfig.py b/src/provisioningserver/dns/zoneconfig.py
219index eed539a..3c6e383 100644
220--- a/src/provisioningserver/dns/zoneconfig.py
221+++ b/src/provisioningserver/dns/zoneconfig.py
222@@ -177,7 +177,8 @@ class DomainConfigBase:
223 [
224 update
225 for update in self._dynamic_updates
226- if update.zone == zone_info.zone_name or update.subnet
227+ if update.zone == zone_info.zone_name
228+ or IPNetwork(update.subnet) == zone_info.subnetwork
229 ],
230 serial=self.serial,
231 ttl=self.default_ttl,

Subscribers

People subscribed via source and target branches