Merge ~cgrabowski/maas:fix_dns_tx_serialization into maas:master

Proposed by Christian Grabowski
Status: Merged
Approved by: Christian Grabowski
Approved revision: d161385a8d3f045786adc9de3089895b853d07af
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~cgrabowski/maas:fix_dns_tx_serialization
Merge into: maas:master
Diff against target: 244 lines (+130/-15)
5 files modified
src/maasserver/region_controller.py (+17/-0)
src/maasserver/tests/test_region_controller.py (+20/-0)
src/maasserver/triggers/system.py (+16/-11)
src/maasserver/triggers/testing.py (+4/-4)
src/maasserver/triggers/tests/test_system.py (+73/-0)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Alexsander de Souza Approve
Review via email: mp+441964@code.launchpad.net

Commit message

skip checking serial if a newer one exists

update interface+ip trigger to ignore controllers handled in other trigger

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

UNIT TESTS
-b fix_dns_tx_serialization lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/2403/console
COMMIT: 139936def8b8cb1e50fd2c1fa45e959995f80054

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

UNIT TESTS
-b fix_dns_tx_serialization lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/2404/console
COMMIT: 7bc0cde0ab971840e75efed644f7256e9c0df177

review: Needs Fixing
Revision history for this message
Alexsander de Souza (alexsander-souza) wrote :

+1

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

UNIT TESTS
-b fix_dns_tx_serialization lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/2405/console
COMMIT: d161385a8d3f045786adc9de3089895b853d07af

review: Needs Fixing
Revision history for this message
Christian Grabowski (cgrabowski) wrote :

jenkins: !test

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

UNIT TESTS
-b fix_dns_tx_serialization lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/2406/console
COMMIT: d161385a8d3f045786adc9de3089895b853d07af

review: Needs Fixing
Revision history for this message
Christian Grabowski (cgrabowski) wrote :

jenkins: !test

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

UNIT TESTS
-b fix_dns_tx_serialization lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: d161385a8d3f045786adc9de3089895b853d07af

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/maasserver/region_controller.py b/src/maasserver/region_controller.py
index de5e1e8..1c8e014 100644
--- a/src/maasserver/region_controller.py
+++ b/src/maasserver/region_controller.py
@@ -101,6 +101,7 @@ class RegionControllerService(Service):
101 self._queued_updates = []101 self._queued_updates = []
102 self._dns_update_in_progress = False102 self._dns_update_in_progress = False
103 self._dns_requires_full_reload = True103 self._dns_requires_full_reload = True
104 self._dns_latest_serial = None
104 self.postgresListener = postgresListener105 self.postgresListener = postgresListener
105 self.dnsResolver = Resolver(106 self.dnsResolver = Resolver(
106 resolv=None,107 resolv=None,
@@ -232,6 +233,16 @@ class RegionControllerService(Service):
232 self._dns_update_in_progress = False233 self._dns_update_in_progress = False
233 return d234 return d
234235
236 def _set_latest_serial(result):
237 if result:
238 (serial, _, _) = result
239 if (
240 not self._dns_latest_serial
241 or self._dns_latest_serial < serial
242 ):
243 self._dns_latest_serial = serial
244 return result
245
235 defers = []246 defers = []
236 if self.needsDNSUpdate:247 if self.needsDNSUpdate:
237 self.needsDNSUpdate = False248 self.needsDNSUpdate = False
@@ -244,6 +255,7 @@ class RegionControllerService(Service):
244 requires_reload=self._dns_requires_full_reload,255 requires_reload=self._dns_requires_full_reload,
245 )256 )
246 d.addCallback(_clear_dynamic_dns_updates)257 d.addCallback(_clear_dynamic_dns_updates)
258 d.addCallback(_set_latest_serial)
247 d.addCallback(self._checkSerial)259 d.addCallback(self._checkSerial)
248 d.addCallback(self._logDNSReload)260 d.addCallback(self._logDNSReload)
249 # Order here matters, first needsDNSUpdate is set then pass the261 # Order here matters, first needsDNSUpdate is set then pass the
@@ -284,6 +296,11 @@ class RegionControllerService(Service):
284 if result is None:296 if result is None:
285 return None297 return None
286 serial, reloaded, domain_names = result298 serial, reloaded, domain_names = result
299
300 # check that there is not a newer serial we should query instead
301 if self._dns_latest_serial and self._dns_latest_serial > serial:
302 return result
303
287 if not reloaded:304 if not reloaded:
288 raise DNSReloadError(305 raise DNSReloadError(
289 "Failed to reload DNS; timeout or rdnc command failed."306 "Failed to reload DNS; timeout or rdnc command failed."
diff --git a/src/maasserver/tests/test_region_controller.py b/src/maasserver/tests/test_region_controller.py
index e5a1f09..1a9ee32 100644
--- a/src/maasserver/tests/test_region_controller.py
+++ b/src/maasserver/tests/test_region_controller.py
@@ -163,6 +163,11 @@ class TestRegionControllerService(MAASServerTestCase):
163 mock_dns_update_all_zones = self.patch(163 mock_dns_update_all_zones = self.patch(
164 region_controller, "dns_update_all_zones"164 region_controller, "dns_update_all_zones"
165 )165 )
166 mock_dns_update_all_zones.returnValue = (
167 random.randint(1, 1000),
168 True,
169 [factory.make_name("domain") for _ in range(3)],
170 )
166 service.startProcessing()171 service.startProcessing()
167 yield service.processingDefer172 yield service.processingDefer
168 mock_dns_update_all_zones.assert_called_once()173 mock_dns_update_all_zones.assert_called_once()
@@ -947,3 +952,18 @@ class TestRegionControllerServiceTransactional(MAASTransactionServerTestCase):
947 call(dynamic_updates=expected_updates, requires_reload=False),952 call(dynamic_updates=expected_updates, requires_reload=False),
948 ]953 ]
949 )954 )
955
956 @wait_for_reactor
957 @inlineCallbacks
958 def test_check_serial_is_skipped_if_a_newer_serial_exists(self):
959 domain = yield deferToDatabase(factory.make_Domain)
960 update_result = (random.randint(0, 10), True, [domain.name])
961 service = RegionControllerService(sentinel.listener)
962
963 query = self.patch(service.dnsResolver, "lookupAuthority")
964
965 service._dns_latest_serial = update_result[0] + 1
966
967 yield service._checkSerial(update_result)
968
969 query.assert_not_called()
diff --git a/src/maasserver/triggers/system.py b/src/maasserver/triggers/system.py
index c6313f9..3c38339 100644
--- a/src/maasserver/triggers/system.py
+++ b/src/maasserver/triggers/system.py
@@ -2061,6 +2061,7 @@ def render_dns_dynamic_update_interface_static_ip_address(op):
2061 CREATE OR REPLACE FUNCTION sys_dns_updates_interface_ip_{op}()2061 CREATE OR REPLACE FUNCTION sys_dns_updates_interface_ip_{op}()
2062 RETURNS trigger as $$2062 RETURNS trigger as $$
2063 DECLARE2063 DECLARE
2064 node_type int;
2064 current_hostname text;2065 current_hostname text;
2065 domain text;2066 domain text;
2066 iface_name text;2067 iface_name text;
@@ -2070,26 +2071,30 @@ def render_dns_dynamic_update_interface_static_ip_address(op):
2070 ASSERT TG_WHEN = 'AFTER', 'May only run as an AFTER trigger';2071 ASSERT TG_WHEN = 'AFTER', 'May only run as an AFTER trigger';
2071 ASSERT TG_LEVEL <> 'STATEMENT', 'Should not be used as a STATEMENT level trigger', TG_NAME;2072 ASSERT TG_LEVEL <> 'STATEMENT', 'Should not be used as a STATEMENT level trigger', TG_NAME;
2072 IF (TG_OP = 'INSERT' AND TG_LEVEL = 'ROW') THEN2073 IF (TG_OP = 'INSERT' AND TG_LEVEL = 'ROW') THEN
2073 SELECT iface.name, node.hostname, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, domain, address_ttl2074 SELECT iface.name, node.hostname, node.node_type, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, node_type, domain, address_ttl
2074 FROM maasserver_interface AS iface2075 FROM maasserver_interface AS iface
2075 JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id2076 JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id
2076 JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=NEW.interface_id;2077 JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=NEW.interface_id;
2077 SELECT host(ip) INTO ip_addr FROM maasserver_staticipaddress WHERE id=NEW.staticipaddress_id;2078 SELECT host(ip) INTO ip_addr FROM maasserver_staticipaddress WHERE id=NEW.staticipaddress_id;
2078 PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || current_hostname || ' A ' || address_ttl || ' ' || ip_addr);2079 IF (node_type={NODE_TYPE.MACHINE} OR node_type={NODE_TYPE.DEVICE}) THEN
2079 PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || address_ttl || ' ' || ip_addr);2080 PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || current_hostname || ' A ' || address_ttl || ' ' || ip_addr);
2081 PERFORM pg_notify('sys_dns_updates', 'INSERT ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || address_ttl || ' ' || ip_addr);
2082 END IF;
2080 ELSIF (TG_OP = 'DELETE' AND TG_LEVEL = 'ROW') THEN2083 ELSIF (TG_OP = 'DELETE' AND TG_LEVEL = 'ROW') THEN
2081 IF EXISTS(SELECT id FROM maasserver_interface WHERE id=OLD.interface_id) THEN2084 IF EXISTS(SELECT id FROM maasserver_interface WHERE id=OLD.interface_id) THEN
2082 SELECT iface.name, node.hostname, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, domain, address_ttl2085 SELECT iface.name, node.hostname, node.node_type, domain_tbl.name, COALESCE(domain_tbl.ttl, 0) INTO iface_name, current_hostname, node_type, domain, address_ttl
2083 FROM maasserver_interface AS iface2086 FROM maasserver_interface AS iface
2084 JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id2087 JOIN maasserver_node AS node ON iface.node_config_id = node.current_config_id
2085 JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=OLD.interface_id;2088 JOIN maasserver_domain AS domain_tbl ON domain_tbl.id=node.domain_id WHERE iface.id=OLD.interface_id;
2086 IF EXISTS(SELECT id FROM maasserver_staticipaddress WHERE id=OLD.staticipaddress_id) THEN2089 IF (node_type={NODE_TYPE.MACHINE} OR node_type={NODE_TYPE.DEVICE}) THEN
2087 SELECT host(ip) INTO ip_addr FROM maasserver_staticipaddress WHERE id=OLD.staticipaddress_id;2090 IF EXISTS(SELECT id FROM maasserver_staticipaddress WHERE id=OLD.staticipaddress_id) THEN
2088 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || current_hostname || ' A ' || ip_addr);2091 SELECT host(ip) INTO ip_addr FROM maasserver_staticipaddress WHERE id=OLD.staticipaddress_id;
2089 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || ip_addr);2092 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || current_hostname || ' A ' || ip_addr);
2090 ELSE2093 PERFORM pg_notify('sys_dns_updates', 'DELETE ' || domain || ' ' || iface_name || '.' || current_hostname || ' A ' || ip_addr);
2091 PERFORM pg_notify('sys_dns_updates', 'DELETE-IFACE-IP ' || domain || ' ' || current_hostname || ' A ' || OLD.interface_id);2094 ELSE
2092 PERFORM pg_notify('sys_dns_updates', 'DELETE-IFACE-IP ' || domain || ' ' || current_hostname || ' AAAA ' || OLD.interface_id);2095 PERFORM pg_notify('sys_dns_updates', 'DELETE-IFACE-IP ' || domain || ' ' || current_hostname || ' A ' || OLD.interface_id);
2096 PERFORM pg_notify('sys_dns_updates', 'DELETE-IFACE-IP ' || domain || ' ' || current_hostname || ' AAAA ' || OLD.interface_id);
2097 END IF;
2093 END IF;2098 END IF;
2094 END IF;2099 END IF;
2095 END IF;2100 END IF;
diff --git a/src/maasserver/triggers/testing.py b/src/maasserver/triggers/testing.py
index 3e6fa68..30d0979 100644
--- a/src/maasserver/triggers/testing.py
+++ b/src/maasserver/triggers/testing.py
@@ -965,13 +965,13 @@ class NotifyHelperMixin:
965965
966 @inlineCallbacks966 @inlineCallbacks
967 def listen(self, channel, msg):967 def listen(self, channel, msg):
968 if msg:968 if msg and channel in self.channel_queues:
969 yield self.channel_queues[channel].put(msg)969 yield self.channel_queues[channel].put(msg)
970970
971 @inlineCallbacks
972 def get_notify(self, channel):971 def get_notify(self, channel):
973 msg = yield self.channel_queues[channel].get()972 if channel in self.channel_queues:
974 return msg973 return self.channel_queues[channel].get()
974 return None
975975
976 def start_reading(self):976 def start_reading(self):
977 for channel in self.channels:977 for channel in self.channels:
diff --git a/src/maasserver/triggers/tests/test_system.py b/src/maasserver/triggers/tests/test_system.py
index ce7398e..675fe89 100644
--- a/src/maasserver/triggers/tests/test_system.py
+++ b/src/maasserver/triggers/tests/test_system.py
@@ -540,6 +540,79 @@ class TestSysDNSUpdates(
540540
541 @wait_for_reactor541 @wait_for_reactor
542 @inlineCallbacks542 @inlineCallbacks
543 def test_dns_dynamic_update_interface_static_ip_address_ignores_controllers(
544 self,
545 ):
546 listener = self.make_listener_without_delay()
547 yield self.set_service(listener)
548 yield deferToDatabase(
549 self.register_trigger,
550 "maasserver_interface_ip_addresses",
551 "sys_dns_updates",
552 ops=("delete",),
553 trigger="sys_dns_updates_interface_ip_delete",
554 )
555 vlan = yield deferToDatabase(self.create_vlan)
556 subnet1 = yield deferToDatabase(
557 self.create_subnet, params={"vlan": vlan}
558 )
559 subnet2 = yield deferToDatabase(
560 self.create_subnet, params={"vlan": vlan}
561 )
562 node1 = yield deferToDatabase(
563 self.create_node_with_interface,
564 params={
565 "node_type": NODE_TYPE.RACK_CONTROLLER,
566 "subnet": subnet1,
567 "status": NODE_STATUS.DEPLOYED,
568 },
569 )
570 node2 = yield deferToDatabase(
571 self.create_node_with_interface,
572 params={"subnet": subnet2, "status": NODE_STATUS.DEPLOYED},
573 )
574 domain = yield deferToDatabase(Domain.objects.get_default_domain)
575 iface1 = yield deferToDatabase(
576 lambda: node1.current_config.interface_set.first()
577 )
578 iface2 = yield deferToDatabase(
579 lambda: node2.current_config.interface_set.first()
580 )
581 ip1 = yield deferToDatabase(
582 lambda: self.create_staticipaddress(
583 params={
584 "ip": subnet1.get_next_ip_for_allocation()[0],
585 "interface": iface1,
586 "subnet": subnet1,
587 }
588 )
589 )
590 ip2 = yield deferToDatabase(
591 lambda: self.create_staticipaddress(
592 params={
593 "ip": subnet2.get_next_ip_for_allocation()[0],
594 "interface": iface2,
595 "subnet": subnet2,
596 }
597 )
598 )
599 self.start_reading()
600 try:
601 yield deferToDatabase(iface1.unlink_ip_address, ip1)
602 yield deferToDatabase(iface2.unlink_ip_address, ip2)
603 expected_msgs = (
604 f"DELETE {domain.name} {node2.hostname} A {ip2.ip}",
605 f"DELETE {domain.name} {iface2.name}.{node2.hostname} A {ip2.ip}",
606 )
607 for exp in expected_msgs:
608 msg = yield self.get_notify("sys_dns_updates")
609 self.assertEqual(msg, exp)
610 finally:
611 self.stop_reading()
612 yield self.postgres_listener_service.stopService()
613
614 @wait_for_reactor
615 @inlineCallbacks
543 def test_dns_dynamc_update_ip_update(self):616 def test_dns_dynamc_update_ip_update(self):
544 listener = self.make_listener_without_delay()617 listener = self.make_listener_without_delay()
545 yield self.set_service(listener)618 yield self.set_service(listener)

Subscribers

People subscribed via source and target branches