s4:provision Pass in the invoication ID and NTDS Settings DN to Schema()
authorAndrew Bartlett <abartlet@samba.org>
Tue, 20 Apr 2010 01:48:51 +0000 (11:48 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 20 Apr 2010 02:11:18 +0000 (12:11 +1000)
By putting these values into the cache on the LDB, this reduces some
of the noise in provision, particularly with the LDAP backend.

Andrew Bartlett

source4/dsdb/common/util.c
source4/dsdb/pydsdb.c
source4/dsdb/samdb/ldb_modules/samba_dsdb.c
source4/scripting/python/samba/provision.py
source4/scripting/python/samba/samdb.py
source4/scripting/python/samba/schema.py

index 66a0b0f87d6554e51b772f9782c682aeab9f5746..30cb5c5c99cdde898277b4fef47f33baad4ff3f9 100644 (file)
@@ -1173,6 +1173,43 @@ failed:
        return false;
 }
 
+bool samdb_set_ntds_settings_dn(struct ldb_context *ldb, struct ldb_dn *ntds_settings_dn_in)
+{
+       TALLOC_CTX *tmp_ctx;
+       struct ldb_dn *ntds_settings_dn_new;
+       struct ldb_dn *ntds_settings_dn_old;
+
+       /* see if we have a cached copy */
+       ntds_settings_dn_old = talloc_get_type(ldb_get_opaque(ldb, 
+                                                             "cache.ntds_settings_dn"), struct ldb_dn);
+
+       tmp_ctx = talloc_new(ldb);
+       if (tmp_ctx == NULL) {
+               goto failed;
+       }
+
+       ntds_settings_dn_new = ldb_dn_copy(tmp_ctx, ntds_settings_dn_in);
+       if (!ntds_settings_dn_new) {
+               goto failed;
+       }
+
+       /* cache the domain_sid in the ldb */
+       if (ldb_set_opaque(ldb, "cache.ntds_settings_dn", ntds_settings_dn_new) != LDB_SUCCESS) {
+               goto failed;
+       }
+
+       talloc_steal(ldb, ntds_settings_dn_new);
+       talloc_free(tmp_ctx);
+       talloc_free(ntds_settings_dn_old);
+
+       return true;
+
+failed:
+       DEBUG(1,("Failed to set our NTDS Settings DN in the ldb!\n"));
+       talloc_free(tmp_ctx);
+       return false;
+}
+
 /* Obtain the short name of the flexible single master operator
  * (FSMO), such as the PDC Emulator */
 const char *samdb_result_fsmo_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
@@ -1207,7 +1244,7 @@ struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
        struct ldb_dn *settings_dn;
 
        /* see if we have a cached copy */
-       settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "cache.settings_dn");
+       settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "cache.ntds_settings_dn");
        if (settings_dn) {
                return settings_dn;
        }
index 88c62086f3dad01cc5da8ee390f5acdab78a894a..45f8b6e1cafa609dac016d2d12364d8bc3b430e4 100644 (file)
@@ -127,6 +127,38 @@ static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
        Py_RETURN_NONE;
 }
 
+static PyObject *py_samdb_set_ntds_settings_dn(PyLdbObject *self, PyObject *args)
+{ 
+       PyObject *py_ldb, *py_ntds_settings_dn;
+       struct ldb_context *ldb;
+       struct ldb_dn *ntds_settings_dn;
+       TALLOC_CTX *tmp_ctx;
+       bool ret;
+
+       if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_ntds_settings_dn))
+               return NULL;
+       
+       PyErr_LDB_OR_RAISE(py_ldb, ldb);
+
+       tmp_ctx = talloc_new(NULL);
+       if (tmp_ctx == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       if (!PyObject_AsDn(tmp_ctx, py_ntds_settings_dn, ldb, &ntds_settings_dn)) {
+               return NULL;
+       }
+
+       ret = samdb_set_ntds_settings_dn(ldb, ntds_settings_dn);
+       talloc_free(tmp_ctx);
+       if (!ret) {
+               PyErr_SetString(PyExc_RuntimeError, "set_ntds_settings_dn failed");
+               return NULL;
+       } 
+       Py_RETURN_NONE;
+}
+
 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
 { 
        PyObject *py_ldb;
@@ -356,6 +388,10 @@ static PyMethodDef py_dsdb_methods[] = {
                "Get SID of domain in use." },
        { "samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id,
                METH_VARARGS, "get the NTDS invocation ID GUID as a string"},
+       { "samdb_set_ntds_settings_dn", (PyCFunction)py_samdb_set_ntds_settings_dn,
+               METH_VARARGS,
+               "samdb_set_ntds_settings_dn(samdb, ntds_settings_dn)\n"
+               "Set NTDS Settings DN for this LDB (allows it to be set before the DB fully exists)." },
        { "dsdb_get_oid_from_attid", (PyCFunction)py_dsdb_get_oid_from_attid,
                METH_VARARGS, NULL },
        { "dsdb_set_ntds_invocation_id",
index 8f7e5407c7915f760891b41f8acc9e25c6440c30..0e635de8ed5b33da43d4e852a77d430d533c76f4 100644 (file)
@@ -185,11 +185,11 @@ static int samba_dsdb_init(struct ldb_module *module)
                                             "kludge_acl",
                                             "schema_load",
                                             "instancetype",
-                                            "rdn_name",
                                             NULL };
 
        const char **link_modules;
        static const char *tdb_modules_list[] = {
+               "rdn_name",
                "subtree_delete",
                "repl_meta_data",
                "subtree_rename",
index f2004878c1cf2d6040974111a6bb50d298c1652a..0757a72556ce0dd7782bfd10ba455ba73eadcd96 100644 (file)
@@ -871,10 +871,9 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
     if schema is None:
         schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn)
 
-    # Load the database, but importantly, use Ldb not SamDB as we don't want to
-    # load the global schema
-    samdb = Ldb(session_info=session_info, 
-                credentials=provision_backend.credentials, lp=lp)
+    # Load the database, but don's load the global schema and don't connect quite yet
+    samdb = SamDB(session_info=session_info, url=None, auto_connect=False,
+                  credentials=provision_backend.credentials, lp=lp, global_schema=False)
 
     message("Pre-loading the Samba 4 and AD schema")
 
@@ -901,6 +900,7 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
 
         samdb.set_domain_sid(str(domainsid))
         samdb.set_invocation_id(invocationid)
+        samdb.set_ntds_settings_dn("CN=NTDS Settings,%s" % names.serverdn)
 
         message("Adding DomainDN: %s" % names.domaindn)
 
@@ -1236,7 +1236,7 @@ def provision(setup_dir, message, session_info,
 
     ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
  
-    schema = Schema(setup_path, domainsid, schemadn=names.schemadn,
+    schema = Schema(setup_path, domainsid, invocationid=invocationid, schemadn=names.schemadn,
                     serverdn=names.serverdn)
     
     if backend_type == "ldb":
index d41b3ec637860eef52f93b6e33d44f084fa87444..dd3824db0c22112ca53eec943070a9e2bac4d67d 100644 (file)
@@ -37,9 +37,11 @@ class SamDB(samba.Ldb):
     """The SAM database."""
 
     def __init__(self, url=None, lp=None, modules_dir=None, session_info=None,
-                 credentials=None, flags=0, options=None, global_schema=True):
+                 credentials=None, flags=0, options=None, global_schema=True, auto_connect=True):
         self.lp = lp
-        if url is None:
+        if not auto_connect:
+            url = None
+        elif url is None and lp is not None:
             url = lp.get("sam database")
 
         super(SamDB, self).__init__(url=url, lp=lp, modules_dir=modules_dir,
@@ -50,7 +52,10 @@ class SamDB(samba.Ldb):
             dsdb.dsdb_set_global_schema(self)
 
     def connect(self, url=None, flags=0, options=None):
-        super(SamDB, self).connect(url=self.lp.private_path(url), flags=flags,
+        if self.lp is not None:
+            url = self.lp.private_path(url)
+
+        super(SamDB, self).connect(url=url, flags=flags,
                 options=options)
 
     def domain_dn(self):
@@ -261,6 +266,15 @@ accountExpires: %u
         "Get the invocation_id id"
         return dsdb.samdb_ntds_invocation_id(self)
 
+    def set_ntds_settings_dn(self, ntds_settings_dn):
+        """Set the NTDS Settings DN, as would be returned on the dsServiceName rootDSE attribute
+
+        This allows the DN to be set before the database fully exists
+
+        :param ntds_settings_dn: The new DN to use
+        """
+        dsdb.samdb_set_ntds_settings_dn(self, ntds_settings_dn)
+
     invocation_id = property(get_invocation_id, set_invocation_id)
 
     domain_sid = property(get_domain_sid, set_domain_sid)
index 092dfe6719d1c267588c473953df1b4a7dbe4aa1..1777c6559ca65f2439167dce8b9e44621d0244ab 100644 (file)
@@ -26,6 +26,7 @@ from base64 import b64encode
 from ms_schema import read_ms_schema
 from samba.dcerpc import security
 from samba import read_and_sub_file, substitute_var, check_all_substituted
+from samba.samdb import SamDB
 from samba import Ldb
 from samba.ndr import ndr_pack
 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL
@@ -52,7 +53,7 @@ def get_schema_descriptor(domain_sid):
    
 class Schema(object):
 
-    def __init__(self, setup_path, domain_sid, schemadn=None,
+    def __init__(self, setup_path, domain_sid, invocationid=None, schemadn=None,
                  serverdn=None, files=None, prefixmap=None):
         """Load schema for the SamDB from the AD schema files and samba4_schema.ldif
         
@@ -65,7 +66,12 @@ class Schema(object):
         """
 
         self.schemadn = schemadn
-        self.ldb = Ldb()
+        self.ldb = SamDB(global_schema=False)
+        if serverdn is not None:
+            self.ldb.set_ntds_settings_dn("CN=NTDS Settings,%s" % serverdn)
+        if invocationid is not None:
+            self.ldb.set_invocation_id(invocationid)
+
         self.schema_data = read_ms_schema(
             setup_path('ad-schema/MS-AD_Schema_2K8_R2_Attributes.txt'),
             setup_path('ad-schema/MS-AD_Schema_2K8_R2_Classes.txt'))
@@ -100,7 +106,7 @@ class Schema(object):
         self.ldb.set_schema_from_ldif(prefixmap_ldif, self.schema_data)
 
     def write_to_tmp_ldb(self, schemadb_path):
-        self.ldb.connect(schemadb_path)
+        self.ldb.connect(url=schemadb_path)
         self.ldb.transaction_start()
         try:
             self.ldb.add_ldif("""dn: @ATTRIBUTES