mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 06:25:34 +00:00
[2380] Merge branch 'master' into trac2380
This commit is contained in:
@@ -368,7 +368,7 @@ public:
|
|||||||
/// \return The number of zones known to this datasource
|
/// \return The number of zones known to this datasource
|
||||||
virtual unsigned int getZoneCount() const;
|
virtual unsigned int getZoneCount() const;
|
||||||
|
|
||||||
/// \brief Create a zone in the database
|
/// \brief Create a zone in the data source
|
||||||
///
|
///
|
||||||
/// Creates a new (empty) zone in the data source backend, which
|
/// Creates a new (empty) zone in the data source backend, which
|
||||||
/// can subsequently be filled with data (through getUpdater()).
|
/// can subsequently be filled with data (through getUpdater()).
|
||||||
|
@@ -88,6 +88,35 @@ Return Value(s): A tuple containing a result value and a ZoneFinder object or\n\
|
|||||||
None\n\
|
None\n\
|
||||||
";
|
";
|
||||||
|
|
||||||
|
const char* const DataSourceClient_createZone_doc = "\
|
||||||
|
create_zone(name) -> bool\n\
|
||||||
|
\n\
|
||||||
|
Create a zone in the data source.\n\
|
||||||
|
\n\
|
||||||
|
Creates a new (empty) zone in the data source backend, which can\n\
|
||||||
|
subsequently be filled with data (through get_updater()).\n\
|
||||||
|
\n\
|
||||||
|
Note: This is a tentative API, and this method is likely to change or\n\
|
||||||
|
be removed in the near future. For that reason, it currently provides\n\
|
||||||
|
a default implementation that throws NotImplemented.\n\
|
||||||
|
\n\
|
||||||
|
Apart from the two exceptions mentioned below, in theory this call can\n\
|
||||||
|
throw anything, depending on the implementation of the datasource\n\
|
||||||
|
backend.\n\
|
||||||
|
\n\
|
||||||
|
Exceptions:\n\
|
||||||
|
NotImplemented If the datasource backend does not support direct\n\
|
||||||
|
zone creation.\n\
|
||||||
|
DataSourceError If something goes wrong in the data source while\n\
|
||||||
|
creating the zone.\n\
|
||||||
|
\n\
|
||||||
|
Parameters:\n\
|
||||||
|
name The (fully qualified) name of the zone to create\n\
|
||||||
|
\n\
|
||||||
|
Return Value(s): True if the zone was added, False if it already\n\
|
||||||
|
existed\n\
|
||||||
|
";
|
||||||
|
|
||||||
const char* const DataSourceClient_getIterator_doc = "\
|
const char* const DataSourceClient_getIterator_doc = "\
|
||||||
get_iterator(name, separate_rrs=False) -> ZoneIterator\n\
|
get_iterator(name, separate_rrs=False) -> ZoneIterator\n\
|
||||||
\n\
|
\n\
|
||||||
|
@@ -91,6 +91,37 @@ DataSourceClient_findZone(PyObject* po_self, PyObject* args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
DataSourceClient_createZone(PyObject* po_self, PyObject* args) {
|
||||||
|
s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
|
||||||
|
PyObject* name;
|
||||||
|
if (PyArg_ParseTuple(args, "O!", &name_type, &name)) {
|
||||||
|
try {
|
||||||
|
if (self->client->createZone(PyName_ToName(name))) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
} else {
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
} catch (const DataSourceError& dse) {
|
||||||
|
PyErr_SetString(getDataSourceException("Error"), dse.what());
|
||||||
|
return (NULL);
|
||||||
|
} catch (const isc::NotImplemented& ni) {
|
||||||
|
PyErr_SetString(getDataSourceException("NotImplemented"),
|
||||||
|
ni.what());
|
||||||
|
return (NULL);
|
||||||
|
} catch (const std::exception& exc) {
|
||||||
|
PyErr_SetString(getDataSourceException("Error"), exc.what());
|
||||||
|
return (NULL);
|
||||||
|
} catch (...) {
|
||||||
|
PyErr_SetString(getDataSourceException("Error"),
|
||||||
|
"Unexpected exception");
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
DataSourceClient_getIterator(PyObject* po_self, PyObject* args) {
|
DataSourceClient_getIterator(PyObject* po_self, PyObject* args) {
|
||||||
s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
|
s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
|
||||||
@@ -230,6 +261,8 @@ DataSourceClient_getJournalReader(PyObject* po_self, PyObject* args) {
|
|||||||
PyMethodDef DataSourceClient_methods[] = {
|
PyMethodDef DataSourceClient_methods[] = {
|
||||||
{ "find_zone", DataSourceClient_findZone, METH_VARARGS,
|
{ "find_zone", DataSourceClient_findZone, METH_VARARGS,
|
||||||
DataSourceClient_findZone_doc },
|
DataSourceClient_findZone_doc },
|
||||||
|
{ "create_zone", DataSourceClient_createZone, METH_VARARGS,
|
||||||
|
DataSourceClient_createZone_doc },
|
||||||
{ "get_iterator",
|
{ "get_iterator",
|
||||||
DataSourceClient_getIterator, METH_VARARGS,
|
DataSourceClient_getIterator, METH_VARARGS,
|
||||||
DataSourceClient_getIterator_doc },
|
DataSourceClient_getIterator_doc },
|
||||||
|
@@ -634,6 +634,53 @@ class DataSrcUpdater(unittest.TestCase):
|
|||||||
self.assertEqual(None, iterator.get_soa())
|
self.assertEqual(None, iterator.get_soa())
|
||||||
self.assertEqual(None, iterator.get_next_rrset())
|
self.assertEqual(None, iterator.get_next_rrset())
|
||||||
|
|
||||||
|
def test_create_zone_args(self):
|
||||||
|
dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, dsc.create_zone)
|
||||||
|
self.assertRaises(TypeError, dsc.create_zone, 1)
|
||||||
|
self.assertRaises(TypeError, dsc.create_zone, None)
|
||||||
|
self.assertRaises(TypeError, dsc.create_zone, "foo.")
|
||||||
|
self.assertRaises(TypeError, dsc.create_zone,
|
||||||
|
isc.dns.Name("example.org"), 1)
|
||||||
|
|
||||||
|
def test_create_zone(self):
|
||||||
|
dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
|
||||||
|
# Note, using example.org here, which should not exist
|
||||||
|
zone_name = isc.dns.Name("example.org")
|
||||||
|
self.assertIsNone(dsc.get_updater(zone_name, True))
|
||||||
|
self.assertRaises(isc.datasrc.Error, dsc.get_iterator, zone_name)
|
||||||
|
|
||||||
|
self.assertTrue(dsc.create_zone(zone_name))
|
||||||
|
|
||||||
|
# should exist now, we should be able to get an updater
|
||||||
|
# and currently it should be empty
|
||||||
|
self.assertIsNotNone(dsc.get_updater(zone_name, True))
|
||||||
|
iterator = dsc.get_iterator(zone_name)
|
||||||
|
self.assertEqual(None, iterator.get_soa())
|
||||||
|
self.assertEqual(None, iterator.get_next_rrset())
|
||||||
|
|
||||||
|
# Trying to create it again should return False
|
||||||
|
self.assertFalse(dsc.create_zone(zone_name))
|
||||||
|
|
||||||
|
def test_create_zone_locked(self):
|
||||||
|
zone_name = isc.dns.Name("example.org")
|
||||||
|
dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
|
||||||
|
updater = dsc.get_updater(isc.dns.Name("example.com"), True)
|
||||||
|
|
||||||
|
# Should fail since db is locked
|
||||||
|
self.assertRaises(isc.datasrc.Error, dsc.create_zone, zone_name)
|
||||||
|
|
||||||
|
# Cancel updater, then create should succeed
|
||||||
|
updater = None
|
||||||
|
self.assertTrue(dsc.create_zone(zone_name))
|
||||||
|
|
||||||
|
def test_create_zone_not_implemented(self):
|
||||||
|
mem_cfg = '{ "type": "memory", "class": "IN", "zones": [] }';
|
||||||
|
dsc = isc.datasrc.DataSourceClient("memory", mem_cfg)
|
||||||
|
self.assertRaises(isc.datasrc.NotImplemented, dsc.create_zone,
|
||||||
|
isc.dns.Name("example.com"))
|
||||||
|
|
||||||
class JournalWrite(unittest.TestCase):
|
class JournalWrite(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# Make a fresh copy of the writable database with all original content
|
# Make a fresh copy of the writable database with all original content
|
||||||
|
Reference in New Issue
Block a user