python: Add binding for dsdb_garbage_collect_tombstones()
authorAndrew Bartlett <abartlet@samba.org>
Mon, 18 Jul 2016 01:11:10 +0000 (13:11 +1200)
committerGarming Sam <garming@samba.org>
Thu, 1 Sep 2016 03:49:15 +0000 (05:49 +0200)
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
python/samba/samdb.py
source4/dsdb/pydsdb.c
source4/dsdb/wscript_build

index e12465d28b65234b291a91a4e4e6d4a972415b9a..3d7ea3ee666b3fb5c03ee9183ae48bb474002a7b 100644 (file)
@@ -949,3 +949,17 @@ accountExpires: %u
         is removed, this routine will put a tombstone in the record.
         '''
         return dsdb_dns.replace_by_dn(self, dn, new_records)
+
+    def garbage_collect_tombstones(self, dn, current_time,
+                                   tombstone_lifetime=None):
+        '''garbage_collect_tombstones(lp, samdb, [dn], current_time, tombstone_lifetime)
+        -> (num_objects_expunged, num_links_expunged)'''
+
+
+        if tombstone_lifetime is None:
+            return dsdb._dsdb_garbage_collect_tombstones(self, dn,
+                                                         current_time)
+        else:
+            return dsdb._dsdb_garbage_collect_tombstones(self, dn,
+                                                         current_time,
+                                                         tombstone_lifetime)
index 1fe8c13e6e551112e9d0e7c9411d01fc2db4dff6..0df52ad5f24e0a2df08c21fbab9a21bdb2b689ed 100644 (file)
@@ -28,6 +28,9 @@
 #include "auth/kerberos/kerberos.h"
 #include "librpc/rpc/pyrpc_util.h"
 #include "lib/policy/policy.h"
+#include "param/pyparam.h"
+#include "lib/util/dlinklist.h"
+#include "dsdb/kcc/garbage_collect_tombstones.h"
 
 void initdsdb(void);
 
@@ -1075,6 +1078,97 @@ static PyObject *py_dsdb_am_pdc(PyObject *self, PyObject *args)
        return PyBool_FromLong(am_pdc);
 }
 
+static PyObject *py_dsdb_garbage_collect_tombstones(PyObject *self, PyObject *args)
+{
+       PyObject *py_ldb, *py_list_dn;
+       struct ldb_context *ldb = NULL;
+        Py_ssize_t i;
+        Py_ssize_t length;
+       long long _current_time, _tombstone_lifetime = LLONG_MAX;
+       uint32_t tombstone_lifetime32;
+       struct dsdb_ldb_dn_list_node *part = NULL;
+       time_t current_time, tombstone_lifetime;
+       TALLOC_CTX *mem_ctx = NULL;
+       NTSTATUS status;
+       unsigned int num_objects_removed = 0;
+       unsigned int num_links_removed = 0;
+
+       if (!PyArg_ParseTuple(args, "OOL|L", &py_ldb,
+                             &py_list_dn, &_current_time, &_tombstone_lifetime)) {
+               return NULL;
+       }
+
+
+       PyErr_LDB_OR_RAISE(py_ldb, ldb);
+
+       mem_ctx = talloc_new(ldb);
+       if (mem_ctx == NULL) {
+               return PyErr_NoMemory();
+       }
+
+       current_time = _current_time;
+
+       if (_tombstone_lifetime == LLONG_MAX) {
+               int ret = dsdb_tombstone_lifetime(ldb, &tombstone_lifetime32);
+               if (ret != LDB_SUCCESS) {
+                       PyErr_Format(PyExc_RuntimeError,
+                                    "Failed to get tombstone lifetime: %s",
+                                    ldb_errstring(ldb));
+                       TALLOC_FREE(mem_ctx);
+                       return NULL;
+               }
+               tombstone_lifetime = tombstone_lifetime32;
+       } else {
+               tombstone_lifetime = _tombstone_lifetime;
+       }
+
+       if (!PyList_Check(py_list_dn)) {
+               PyErr_SetString(PyExc_TypeError, "A list of DNs were expected");
+               TALLOC_FREE(mem_ctx);
+               return NULL;
+       }
+
+       length = PyList_GET_SIZE(py_list_dn);
+
+       for (i = 0; i < length; i++) {
+               char *part_str = PyString_AsString(PyList_GetItem(py_list_dn, i));
+               struct ldb_dn *p;
+               struct dsdb_ldb_dn_list_node *node;
+
+               if (part_str == NULL) {
+                       TALLOC_FREE(mem_ctx);
+                       return PyErr_NoMemory();
+               }
+
+               p = ldb_dn_new(mem_ctx, ldb, part_str);
+               if (p == NULL) {
+                       PyErr_Format(PyExc_RuntimeError, "Failed to parse DN %s", part_str);
+                       TALLOC_FREE(mem_ctx);
+                       return NULL;
+               }
+               node = talloc_zero(mem_ctx, struct dsdb_ldb_dn_list_node);
+               node->dn = p;
+
+               DLIST_ADD_END(part, node);
+       }
+
+       status = dsdb_garbage_collect_tombstones(mem_ctx, ldb,
+                                                part, current_time,
+                                                tombstone_lifetime,
+                                                &num_objects_removed,
+                                                &num_links_removed);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_SetNTSTATUS(status);
+               return NULL;
+       }
+
+       TALLOC_FREE(mem_ctx);
+
+       return Py_BuildValue("(II)", num_objects_removed,
+                           num_links_removed);
+}
+
 
 static PyMethodDef py_dsdb_methods[] = {
        { "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
@@ -1141,6 +1235,9 @@ static PyMethodDef py_dsdb_methods[] = {
        { "_dsdb_get_wellknown_dn", (PyCFunction)py_dsdb_get_wellknown_dn, METH_VARARGS, NULL },
        { "_dsdb_DsReplicaAttribute", (PyCFunction)py_dsdb_DsReplicaAttribute, METH_VARARGS, NULL },
        { "_dsdb_normalise_attributes", (PyCFunction)py_dsdb_normalise_attributes, METH_VARARGS, NULL },
+       { "_dsdb_garbage_collect_tombstones", (PyCFunction)py_dsdb_garbage_collect_tombstones, METH_VARARGS,
+               "_dsdb_kcc_check_deleted(samdb, [dn], current_time, tombstone_lifetime)"
+               " -> (num_objects_expunged, num_links_expunged)" },
        { NULL }
 };
 
index 7ea9e27353e79b128656c9e0fbe683dc0a77807a..d569ea63a512835c1cfe9ec5af01c708b3a0aaa2 100755 (executable)
@@ -67,6 +67,6 @@ bld.SAMBA_PYTHON('python_dsdb',
        # the dependency on dcerpc here is because gensec
        # depends on dcerpc but the waf circular dependency finder
        # removes it so we end up with unresolved symbols.
-       deps='samdb pyldb-util dcerpc com_err pyrpc_util pyparam_util',
+       deps='samdb pyldb-util dcerpc com_err pyrpc_util pyparam_util dsdb_garbage_collect_tombstones',
        realname='samba/dsdb.so'
        )