BIND 10 master, updated. 3e19362bc1ba7dc67a87768e2b172c48b32417f5 [master] Merge branch 'trac1333u'
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Nov 17 17:20:41 UTC 2011
The branch, master has been updated
via 3e19362bc1ba7dc67a87768e2b172c48b32417f5 (commit)
via 758ab4461e8792e563ce1e0ad069d53b5e15d8dd (commit)
via b449ad20a4f58eb96aec8cd7dd7bb857bdb5d14b (commit)
from da3e9e54f1374d581d78f1d874ddafd427a622ab (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 3e19362bc1ba7dc67a87768e2b172c48b32417f5
Merge: da3e9e5 758ab44
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Thu Nov 17 09:18:52 2011 -0800
[master] Merge branch 'trac1333u'
-----------------------------------------------------------------------
Summary of changes:
src/lib/python/isc/datasrc/client_inc.cc | 19 +++-
src/lib/python/isc/datasrc/client_python.cc | 22 +++-
src/lib/python/isc/datasrc/tests/datasrc_test.py | 122 +++++++++++++++++++-
.../isc/datasrc/tests/testdata/example.com.sqlite3 | Bin 43008 -> 44032 bytes
4 files changed, 156 insertions(+), 7 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/python/isc/datasrc/client_inc.cc b/src/lib/python/isc/datasrc/client_inc.cc
index 6465bf3..14c0157 100644
--- a/src/lib/python/isc/datasrc/client_inc.cc
+++ b/src/lib/python/isc/datasrc/client_inc.cc
@@ -121,7 +121,7 @@ Return Value(s): Pointer to the iterator.\n\
";
const char* const DataSourceClient_getUpdater_doc = "\
-get_updater(name, replace) -> ZoneUpdater\n\
+get_updater(name, replace, journaling=False) -> ZoneUpdater\n\
\n\
Return an updater to make updates to a specific zone.\n\
\n\
@@ -162,6 +162,22 @@ A data source can be \"read only\" or can prohibit partial updates. In\n\
such cases this method will result in an isc.datasrc.NotImplemented exception\n\
unconditionally or when replace is false).\n\
\n\
+If journaling is True, the data source should store a journal of\n\
+changes. These can be used later on by, for example, IXFR-out.\n\
+However, the parameter is a hint only. It might be unable to store\n\
+them and they would be silently discarded. Or it might need to store\n\
+them no matter what (for example a git-based data source would store\n\
+journal implicitly). When the journaling is True, it requires that the\n\
+following update be formatted as IXFR transfer (SOA to be removed,\n\
+bunch of RRs to be removed, SOA to be added, bunch of RRs to be added,\n\
+and possibly repeated). However, it is not required that the updater\n\
+checks that. If it is False, it must not require so and must accept\n\
+any order of changes.\n\
+\n\
+We don't support erasing the whole zone (by replace being True) and\n\
+saving a journal at the same time. In such situation, isc.datasrc.Error\n\
+is thrown.\n\
+\n\
Exceptions:\n\
isc.datasrc. NotImplemented The underlying data source does not support\n\
updates.\n\
@@ -170,6 +186,7 @@ Exceptions:\n\
Parameters:\n\
name The zone name to be updated\n\
replace Whether to delete existing RRs before making updates\n\
+ journaling The zone updater should store a journal of the changes.\n\
\n\
";
} // unnamed namespace
diff --git a/src/lib/python/isc/datasrc/client_python.cc b/src/lib/python/isc/datasrc/client_python.cc
index 49235a6..5ab1139 100644
--- a/src/lib/python/isc/datasrc/client_python.cc
+++ b/src/lib/python/isc/datasrc/client_python.cc
@@ -129,14 +129,17 @@ PyObject*
DataSourceClient_getUpdater(PyObject* po_self, PyObject* args) {
s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
PyObject *name_obj;
- PyObject *replace_obj;
- if (PyArg_ParseTuple(args, "O!O", &name_type, &name_obj, &replace_obj) &&
- PyBool_Check(replace_obj)) {
- bool replace = (replace_obj != Py_False);
+ PyObject *replace_obj = NULL;
+ PyObject *journaling_obj = Py_False;
+ if (PyArg_ParseTuple(args, "O!O|O", &name_type, &name_obj,
+ &replace_obj, &journaling_obj) &&
+ PyBool_Check(replace_obj) && PyBool_Check(journaling_obj)) {
+ const bool replace = (replace_obj != Py_False);
+ const bool journaling = (journaling_obj == Py_True);
try {
ZoneUpdaterPtr updater =
self->cppobj->getInstance().getUpdater(PyName_ToName(name_obj),
- replace);
+ replace, journaling);
if (!updater) {
return (Py_None);
}
@@ -157,6 +160,15 @@ DataSourceClient_getUpdater(PyObject* po_self, PyObject* args) {
return (NULL);
}
} else {
+ // PyBool_Check doesn't set the error, so we have to set it ourselves.
+ if (replace_obj != NULL && !PyBool_Check(replace_obj)) {
+ PyErr_SetString(PyExc_TypeError, "'replace' for "
+ "DataSourceClient.get_updater must be boolean");
+ }
+ if (!PyBool_Check(journaling_obj)) {
+ PyErr_SetString(PyExc_TypeError, "'journaling' for "
+ "DataSourceClient.get_updater must be boolean");
+ }
return (NULL);
}
}
diff --git a/src/lib/python/isc/datasrc/tests/datasrc_test.py b/src/lib/python/isc/datasrc/tests/datasrc_test.py
index 68e075a..fb4de15 100644
--- a/src/lib/python/isc/datasrc/tests/datasrc_test.py
+++ b/src/lib/python/isc/datasrc/tests/datasrc_test.py
@@ -16,8 +16,9 @@
import isc.log
import isc.datasrc
from isc.datasrc import ZoneFinder
-import isc.dns
+from isc.dns import *
import unittest
+import sqlite3
import os
import shutil
import sys
@@ -565,6 +566,125 @@ class DataSrcUpdater(unittest.TestCase):
self.assertEqual(None, iterator.get_soa())
self.assertEqual(None, iterator.get_next_rrset())
+class JournalWrite(unittest.TestCase):
+ def setUp(self):
+ # Make a fresh copy of the writable database with all original content
+ shutil.copyfile(READ_ZONE_DB_FILE, WRITE_ZONE_DB_FILE)
+ self.dsc = isc.datasrc.DataSourceClient("sqlite3",
+ WRITE_ZONE_DB_CONFIG)
+ self.updater = self.dsc.get_updater(Name("example.com"), False, True)
+
+ def tearDown(self):
+ self.dsc = None
+ self.updater = None
+
+ def check_journal(self, expected_list):
+ # This assumes sqlite3 DB and directly fetches stored data from
+ # the DB file. It should be generalized using ZoneJournalReader
+ # once it's supported.
+ conn = sqlite3.connect(WRITE_ZONE_DB_FILE)
+ cur = conn.cursor()
+ cur.execute('SELECT name, rrtype, ttl, rdata FROM diffs ORDER BY id')
+ actual_list = cur.fetchall()
+ self.assertEqual(len(expected_list), len(actual_list))
+ for (expected, actual) in zip(expected_list, actual_list):
+ self.assertEqual(expected, actual)
+ conn.close()
+
+ def create_soa(self, serial):
+ soa = RRset(Name('example.org'), RRClass.IN(), RRType.SOA(),
+ RRTTL(3600))
+ soa.add_rdata(Rdata(RRType.SOA(), RRClass.IN(),
+ 'ns1.example.org. admin.example.org. ' +
+ str(serial) + ' 3600 1800 2419200 7200'))
+ return soa
+
+ def create_a(self, address):
+ a_rr = RRset(Name('www.example.org'), RRClass.IN(), RRType.A(),
+ RRTTL(3600))
+ a_rr.add_rdata(Rdata(RRType.A(), RRClass.IN(), address))
+ return (a_rr)
+
+ def test_journal_write(self):
+ # This is a straightforward port of the C++ 'journal' test
+ # Note: we add/delete 'out of zone' data (example.org in the
+ # example.com zone for convenience.
+ self.updater.delete_rrset(self.create_soa(1234))
+ self.updater.delete_rrset(self.create_a('192.0.2.2'))
+ self.updater.add_rrset(self.create_soa(1235))
+ self.updater.add_rrset(self.create_a('192.0.2.2'))
+ self.updater.commit()
+
+ expected = []
+ expected.append(("example.org.", "SOA", 3600,
+ "ns1.example.org. admin.example.org. " +
+ "1234 3600 1800 2419200 7200"))
+ expected.append(("www.example.org.", "A", 3600, "192.0.2.2"))
+ expected.append(("example.org.", "SOA", 3600,
+ "ns1.example.org. admin.example.org. " +
+ "1235 3600 1800 2419200 7200"))
+ expected.append(("www.example.org.", "A", 3600, "192.0.2.2"))
+ self.check_journal(expected)
+
+ def test_journal_write_multiple(self):
+ # This is a straightforward port of the C++ 'journalMultiple' test
+ expected = []
+ for i in range(1, 100):
+ self.updater.delete_rrset(self.create_soa(1234 + i - 1))
+ expected.append(("example.org.", "SOA", 3600,
+ "ns1.example.org. admin.example.org. " +
+ str(1234 + i - 1) + " 3600 1800 2419200 7200"))
+ self.updater.add_rrset(self.create_soa(1234 + i))
+ expected.append(("example.org.", "SOA", 3600,
+ "ns1.example.org. admin.example.org. " +
+ str(1234 + i) + " 3600 1800 2419200 7200"))
+ self.updater.commit()
+ self.check_journal(expected)
+
+ def test_journal_write_bad_sequence(self):
+ # This is a straightforward port of the C++ 'journalBadSequence' test
+
+ # Delete A before SOA
+ self.assertRaises(isc.datasrc.Error, self.updater.delete_rrset,
+ self.create_a('192.0.2.1'))
+ # Add before delete
+ self.updater = self.dsc.get_updater(Name("example.com"), False, True)
+ self.assertRaises(isc.datasrc.Error, self.updater.add_rrset,
+ self.create_soa(1234))
+ # Add A before SOA
+ self.updater = self.dsc.get_updater(Name("example.com"), False, True)
+ self.updater.delete_rrset(self.create_soa(1234))
+ self.assertRaises(isc.datasrc.Error, self.updater.add_rrset,
+ self.create_a('192.0.2.1'))
+ # Commit before add
+ self.updater = self.dsc.get_updater(Name("example.com"), False, True)
+ self.updater.delete_rrset(self.create_soa(1234))
+ self.assertRaises(isc.datasrc.Error, self.updater.commit)
+ # Delete two SOAs
+ self.updater = self.dsc.get_updater(Name("example.com"), False, True)
+ self.updater.delete_rrset(self.create_soa(1234))
+ self.assertRaises(isc.datasrc.Error, self.updater.delete_rrset,
+ self.create_soa(1235))
+ # Add two SOAs
+ self.updater = self.dsc.get_updater(Name("example.com"), False, True)
+ self.updater.delete_rrset(self.create_soa(1234))
+ self.updater.add_rrset(self.create_soa(1235))
+ self.assertRaises(isc.datasrc.Error, self.updater.add_rrset,
+ self.create_soa(1236))
+
+ def test_journal_write_onerase(self):
+ self.updater = None
+ self.assertRaises(isc.datasrc.Error, self.dsc.get_updater,
+ Name("example.com"), True, True)
+
+ def test_journal_write_badparam(self):
+ dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
+ self.assertRaises(TypeError, dsc.get_updater, 0, False, True)
+ self.assertRaises(TypeError, dsc.get_updater, Name('example.com'),
+ False, 0)
+ self.assertRaises(TypeError, dsc.get_updater, Name("example.com"),
+ 1, True)
+
if __name__ == "__main__":
isc.log.init("bind10")
isc.log.resetUnitTestRootLogger()
diff --git a/src/lib/python/isc/datasrc/tests/testdata/example.com.sqlite3 b/src/lib/python/isc/datasrc/tests/testdata/example.com.sqlite3
index cc8cfc3..521cf31 100644
Binary files a/src/lib/python/isc/datasrc/tests/testdata/example.com.sqlite3 and b/src/lib/python/isc/datasrc/tests/testdata/example.com.sqlite3 differ
More information about the bind10-changes
mailing list