BIND 10 trac1457, updated. 11af4fd1af04140c9e64aff58efc5f6661a41cf0 [1457] collect prerequisite RRset rrs
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Jun 1 10:03:07 UTC 2012
The branch, trac1457 has been updated
via 11af4fd1af04140c9e64aff58efc5f6661a41cf0 (commit)
from bc9715b080230f432420a7796d8ec2c5029e889e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 11af4fd1af04140c9e64aff58efc5f6661a41cf0
Author: Jelte Jansen <jelte at isc.org>
Date: Fri Jun 1 12:02:47 2012 +0200
[1457] collect prerequisite RRset rrs
Or, more specifically:
- set PRESERVE_ORDER in the update message parsing
- collect rrsets with the same name and type (and class, but that is true by reaching this part of the code), for the exact-rrset-match prerequisite
- check the list of collected rrsets explicitely (as proposed in the RFC)
Setting PRESERVE_ORDER does break the NS-at-apex special case handling though;
and we need additional functionality in diff to fix that;
- separated and disable the related test
- added a comment to __ns_deleter_helper that this method currently does NOT do
what it is supposed to do
-----------------------------------------------------------------------
Summary of changes:
src/lib/python/isc/ddns/session.py | 55 +++++++++++++++---
src/lib/python/isc/ddns/tests/session_tests.py | 74 ++++++++++++++++++++----
2 files changed, 112 insertions(+), 17 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/python/isc/ddns/session.py b/src/lib/python/isc/ddns/session.py
index 29abf0f..0713dd1 100644
--- a/src/lib/python/isc/ddns/session.py
+++ b/src/lib/python/isc/ddns/session.py
@@ -95,6 +95,34 @@ def convert_rrset_class(rrset, rrclass):
new_rrset.add_rdata(isc.dns.Rdata(rrset.get_type(), rrclass, wire))
return new_rrset
+def collect_rrsets(collection, rrset):
+ '''
+ Helper function to collect similar rrsets.
+ Collect all rrsets with the same name, class, and type
+ collection is the currently collected list of RRsets,
+ rrset is the RRset to add;
+ if an RRset with the same name, class and type as the
+ given rrset exists in the collection, its rdata fields
+ are added to that RRset. Otherwise, the rrset is added
+ to the given collection.
+ TTL is ignored.
+ This method does not check rdata contents for duplicate
+ values.
+
+ The collection and its rrsets are modified in-place,
+ this method does not return anything.
+ '''
+ found = False
+ for existing_rrset in collection:
+ if existing_rrset.get_name() == rrset.get_name() and\
+ existing_rrset.get_class() == rrset.get_class() and\
+ existing_rrset.get_type() == rrset.get_type():
+ for rdata in rrset.get_rdata():
+ existing_rrset.add_rdata(rdata)
+ found = True
+ if not found:
+ collection.append(rrset)
+
class UpdateSession:
'''Protocol handling for a single dynamic update request.
@@ -335,6 +363,10 @@ class UpdateSession:
Returns a dns Rcode signaling either no error (Rcode.NOERROR())
or that one of the prerequisites failed (any other Rcode).
'''
+
+ # Temporary array to store exact-match RRsets
+ exact_match_rrsets = []
+
for rrset in self.__message.get_section(SECTION_PREREQUISITE):
# First check if the name is in the zone
if not self.__check_in_zone(rrset):
@@ -401,13 +433,7 @@ class UpdateSession:
RRsetFormatter(rrset))
return Rcode.FORMERR()
else:
- if not self.__prereq_rrset_exists_value(rrset):
- rcode = Rcode.NXRRSET()
- logger.info(LIBDDNS_PREREQ_RRSET_EXISTS_VAL_FAILED,
- ClientFormatter(self.__client_addr),
- ZoneFormatter(self.__zname, self.__zclass),
- RRsetFormatter(rrset), rcode)
- return rcode
+ collect_rrsets(exact_match_rrsets, rrset)
else:
logger.info(LIBDDNS_PREREQ_FORMERR_CLASS,
ClientFormatter(self.__client_addr),
@@ -415,6 +441,15 @@ class UpdateSession:
RRsetFormatter(rrset))
return Rcode.FORMERR()
+ for collected_rrset in exact_match_rrsets:
+ if not self.__prereq_rrset_exists_value(collected_rrset):
+ rcode = Rcode.NXRRSET()
+ logger.info(LIBDDNS_PREREQ_RRSET_EXISTS_VAL_FAILED,
+ ClientFormatter(self.__client_addr),
+ ZoneFormatter(self.__zname, self.__zclass),
+ RRsetFormatter(collected_rrset), rcode)
+ return rcode
+
# All prerequisites are satisfied
return Rcode.NOERROR()
@@ -578,6 +613,12 @@ class UpdateSession:
may never be removed (and any action that would do so
should be ignored).
'''
+ # NOTE: This method is currently bad: it WILL delete all
+ # NS rrsets in a number of cases.
+ # We need an extension to our diff.py to handle this correctly
+ # (see ticket #2016)
+ # The related test is currently disabled. When this is fixed,
+ # enable that test again.
result, orig_rrset, _ = self.__finder.find(rrset.get_name(),
rrset.get_type(),
ZoneFinder.NO_WILDCARD |
diff --git a/src/lib/python/isc/ddns/tests/session_tests.py b/src/lib/python/isc/ddns/tests/session_tests.py
index 00d9b07..8c44f7b 100644
--- a/src/lib/python/isc/ddns/tests/session_tests.py
+++ b/src/lib/python/isc/ddns/tests/session_tests.py
@@ -54,7 +54,7 @@ def create_update_msg(zones=[TEST_ZONE_RECORD], prerequisites=[],
# re-read the created data in the parse mode
msg.clear(Message.PARSE)
- msg.from_wire(renderer.get_data())
+ msg.from_wire(renderer.get_data(), Message.PRESERVE_ORDER)
return renderer.get_data(), msg
@@ -233,6 +233,46 @@ class SessionTest(unittest.TestCase):
self.assertRaises(DNSMessageFORMERR, convert_rrset_class,
rrset, RRClass.IN())
+ def test_collect_rrsets(self):
+ '''
+ Tests the 'rrset collector' method, which collects rrsets
+ with the same name and type
+ '''
+ collected = []
+
+ collect_rrsets(collected, create_rrset("a.example.org", RRClass.IN(),
+ RRType.A(), 0, [ "192.0.2.1" ]))
+ # Same name and class, different type
+ collect_rrsets(collected, create_rrset("a.example.org", RRClass.IN(),
+ RRType.TXT(), 0, [ "one" ]))
+ collect_rrsets(collected, create_rrset("a.example.org", RRClass.IN(),
+ RRType.A(), 0, [ "192.0.2.2" ]))
+ collect_rrsets(collected, create_rrset("a.example.org", RRClass.IN(),
+ RRType.TXT(), 0, [ "two" ]))
+ # Same class and type as an existing one, different name
+ collect_rrsets(collected, create_rrset("b.example.org", RRClass.IN(),
+ RRType.A(), 0, [ "192.0.2.3" ]))
+ # Same name and type as an existing one, different class
+ collect_rrsets(collected, create_rrset("a.example.org", RRClass.CH(),
+ RRType.TXT(), 0, [ "one" ]))
+ collect_rrsets(collected, create_rrset("b.example.org", RRClass.IN(),
+ RRType.A(), 0, [ "192.0.2.4" ]))
+ collect_rrsets(collected, create_rrset("a.example.org", RRClass.CH(),
+ RRType.TXT(), 0, [ "two" ]))
+
+ strings = [ rrset.to_text() for rrset in collected ]
+ # note + vs , in this list
+ expected = ['a.example.org. 0 IN A 192.0.2.1\n' +
+ 'a.example.org. 0 IN A 192.0.2.2\n',
+ 'a.example.org. 0 IN TXT "one"\n' +
+ 'a.example.org. 0 IN TXT "two"\n',
+ 'b.example.org. 0 IN A 192.0.2.3\n' +
+ 'b.example.org. 0 IN A 192.0.2.4\n',
+ 'a.example.org. 0 CH TXT "one"\n' +
+ 'a.example.org. 0 CH TXT "two"\n']
+
+ self.assertEqual(expected, strings)
+
def __prereq_helper(self, method, expected, rrset):
'''Calls the given method with self.__datasrc_client
and the given rrset, and compares the return value.
@@ -505,15 +545,6 @@ class SessionTest(unittest.TestCase):
name_not_in_use_no = create_rrset("www.example.org", RRClass.NONE(),
RRType.ANY(), 0)
- # Create an UPDATE with all 5 'yes' prereqs
- data, update = create_update_msg([TEST_ZONE_RECORD],
- [
- rrset_exists_yes,
- rrset_does_not_exist_yes,
- name_in_use_yes,
- name_not_in_use_yes,
- rrset_exists_value_yes,
- ])
# check 'no' result codes
self.check_prerequisite_result(Rcode.NXRRSET(),
[ rrset_exists_no ])
@@ -527,6 +558,23 @@ class SessionTest(unittest.TestCase):
[ name_not_in_use_no ])
# the 'yes' codes should result in ok
+ # individually
+ self.check_prerequisite_result(Rcode.NOERROR(),
+ [ rrset_exists_yes ] )
+ self.check_prerequisite_result(Rcode.NOERROR(),
+ [ rrset_exists_value_yes ])
+ self.check_prerequisite_result(Rcode.NOERROR(),
+ [ rrset_does_not_exist_yes ])
+ self.check_prerequisite_result(Rcode.NOERROR(),
+ [ name_in_use_yes ])
+ self.check_prerequisite_result(Rcode.NOERROR(),
+ [ name_not_in_use_yes ])
+ self.check_prerequisite_result(Rcode.NOERROR(),
+ [ rrset_exists_value_1,
+ rrset_exists_value_2,
+ rrset_exists_value_3])
+
+ # and together
self.check_prerequisite_result(Rcode.NOERROR(),
[ rrset_exists_yes,
rrset_exists_value_yes,
@@ -1071,8 +1119,14 @@ class SessionTest(unittest.TestCase):
RRType.NS(),
orig_ns_rrset)
+ def DISABLED_test_update_apex_special_case_ns_rrset(self):
# If we delete the NS at the apex specifically, it should still
# keep one record
+ self.__initialize_update_rrsets()
+ # When we are done, we should have a reduced NS rrset
+ short_ns_rrset = create_rrset("example.org", TEST_RRCLASS,
+ RRType.NS(), 3600,
+ [ "ns3.example.org." ])
self.check_full_handle_result(Rcode.NOERROR(),
[ self.rrset_update_del_rrset_ns ])
self.__check_inzone_data(isc.datasrc.ZoneFinder.SUCCESS,
More information about the bind10-changes
mailing list