s4:dsdb Split schema loading and schema data management
authorAndrew Bartlett <abartlet@samba.org>
Thu, 22 Oct 2009 04:54:57 +0000 (15:54 +1100)
committerAndrew Tridgell <tridge@samba.org>
Fri, 23 Oct 2009 04:41:00 +0000 (15:41 +1100)
By splitting the module this way, we can load the schema at startup, after
the partitions module is operational, but we leave the 'mess with details of
entries in the partitions' module to operate only on the partitions module.

Loading the schema later allows us to set the @ATTRIBUTES correctly on all
the databases.

Andrew Bartlett

source4/dsdb/samdb/ldb_modules/config.mk
source4/dsdb/samdb/ldb_modules/schema_data.c [moved from source4/dsdb/samdb/ldb_modules/schema_fsmo.c with 64% similarity]
source4/dsdb/samdb/ldb_modules/schema_load.c [new file with mode: 0644]
source4/scripting/python/samba/provision.py

index 40e37a47fc86d5ed3482fd572bf7ebdf756dc22b..c75e4a6489e86ab7c7ad49bfee1407d68929e2ee 100644 (file)
@@ -46,16 +46,28 @@ ldb_dsdb_cache_OBJ_FILES = \
                $(dsdbsrcdir)/samdb/ldb_modules/dsdb_cache.o
 
 ################################################
-# Start MODULE ldb_schema_fsmo
-[MODULE::ldb_schema_fsmo]
+# Start MODULE ldb_schema_load
+[MODULE::ldb_schema_load]
 SUBSYSTEM = LIBLDB
 PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS DSDB_MODULE_HELPERS
-INIT_FUNCTION = LDB_MODULE(schema_fsmo)
-# End MODULE ldb_schema_fsmo
+INIT_FUNCTION = LDB_MODULE(schema_load)
+# End MODULE ldb_schema_load
 ################################################
 
-ldb_schema_fsmo_OBJ_FILES = \
-               $(dsdbsrcdir)/samdb/ldb_modules/schema_fsmo.o
+ldb_schema_load_OBJ_FILES = \
+               $(dsdbsrcdir)/samdb/ldb_modules/schema_load.o
+
+################################################
+# Start MODULE ldb_schema_data
+[MODULE::ldb_schema_data]
+SUBSYSTEM = LIBLDB
+PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS DSDB_MODULE_HELPERS
+INIT_FUNCTION = LDB_MODULE(schema_data)
+# End MODULE ldb_schema_data
+################################################
+
+ldb_schema_data_OBJ_FILES = \
+               $(dsdbsrcdir)/samdb/ldb_modules/schema_data.o
 
 ################################################
 # Start MODULE ldb_naming_fsmo
similarity index 64%
rename from source4/dsdb/samdb/ldb_modules/schema_fsmo.c
rename to source4/dsdb/samdb/ldb_modules/schema_data.c
index 2b6606c147a58371e572cbc2111df2ed46ff0d15..675cae3dc71277362d8b4568865f4a1523ac0cf6 100644 (file)
@@ -1,8 +1,7 @@
 /* 
    Unix SMB/CIFS mplementation.
 
-   The module that handles the Schema FSMO Role Owner
-   checkings, it also loads the dsdb_schema.
+   The module that handles the Schema checkings and dynamic attributes
    
    Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
@@ -81,131 +80,42 @@ static const struct {
        }
 };
 
-struct schema_fsmo_private_data {
+struct schema_data_private_data {
        struct ldb_dn *aggregate_dn;
+       struct ldb_dn *schema_dn;
 };
 
-struct schema_fsmo_search_data {
+struct schema_data_search_data {
        struct ldb_module *module;
        struct ldb_request *req;
 
        const struct dsdb_schema *schema;
 };
 
-/*
-  Given an LDB module (pointing at the schema DB), and the DN, set the populated schema
-*/
-
-static int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_module *module,
-                                     struct smb_iconv_convenience *iconv_convenience, 
-                                     struct ldb_dn *schema_dn,
-                                     struct dsdb_schema **schema) 
-{
-       TALLOC_CTX *tmp_ctx;
-       char *error_string;
-       int ret;
-       struct ldb_context *ldb = ldb_module_get_ctx(module);
-       struct ldb_result *schema_res;
-       struct ldb_result *a_res;
-       struct ldb_result *c_res;
-       static const char *schema_attrs[] = {
-               "prefixMap",
-               "schemaInfo",
-               "fSMORoleOwner",
-               NULL
-       };
-       unsigned flags;
-
-       tmp_ctx = talloc_new(mem_ctx);
-       if (!tmp_ctx) {
-               ldb_oom(ldb);
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       /* we don't want to trace the schema load */
-       flags = ldb_get_flags(ldb);
-       ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
-
-       /*
-        * setup the prefix mappings and schema info
-        */
-       ret = dsdb_module_search_dn(module, tmp_ctx, &schema_res,
-                                   schema_dn, schema_attrs);
-       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
-               goto failed;
-       } else if (ret != LDB_SUCCESS) {
-               ldb_asprintf_errstring(ldb, 
-                                      "dsdb_schema: failed to search the schema head: %s",
-                                      ldb_errstring(ldb));
-               goto failed;
-       }
-
-       /*
-        * load the attribute definitions
-        */
-       ret = dsdb_module_search(module, tmp_ctx, &a_res,
-                                schema_dn, LDB_SCOPE_ONELEVEL, NULL,
-                                "(objectClass=attributeSchema)");
-       if (ret != LDB_SUCCESS) {
-               ldb_asprintf_errstring(ldb, 
-                                      "dsdb_schema: failed to search attributeSchema objects: %s",
-                                      ldb_errstring(ldb));
-               goto failed;
-       }
-
-       /*
-        * load the objectClass definitions
-        */
-       ret = dsdb_module_search(module, tmp_ctx, &c_res,
-                                schema_dn, LDB_SCOPE_ONELEVEL, NULL,
-                                "(objectClass=classSchema)");
-       if (ret != LDB_SUCCESS) {
-               ldb_asprintf_errstring(ldb, 
-                                      "dsdb_schema: failed to search attributeSchema objects: %s",
-                                      ldb_errstring(ldb));
-               goto failed;
-       }
-
-       ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
-                                          lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
-                                          schema_res, a_res, c_res, schema, &error_string);
-       if (ret != LDB_SUCCESS) {
-               ldb_asprintf_errstring(ldb, 
-                                                   "dsdb_schema load failed: %s",
-                                                   error_string);
-               goto failed;
-       }
-       talloc_steal(mem_ctx, *schema);
-
-failed:
-       if (flags & LDB_FLG_ENABLE_TRACING) {
-               flags = ldb_get_flags(ldb);
-               ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
-       }
-       talloc_free(tmp_ctx);
-       return ret;
-}      
-
-
-static int schema_fsmo_init(struct ldb_module *module)
+static int schema_data_init(struct ldb_module *module)
 {
        struct ldb_context *ldb;
        TALLOC_CTX *mem_ctx;
        struct ldb_dn *schema_dn;
        struct dsdb_schema *schema;
        int ret;
-       struct schema_fsmo_private_data *data;
+       struct schema_data_private_data *data;
+
+       ret = ldb_next_init(module);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
 
        ldb = ldb_module_get_ctx(module);
        schema_dn = samdb_schema_dn(ldb);
        if (!schema_dn) {
                ldb_reset_err_string(ldb);
                ldb_debug(ldb, LDB_DEBUG_WARNING,
-                         "schema_fsmo_init: no schema dn present: (skip schema loading)\n");
-               return ldb_next_init(module);
+                         "schema_data_init: no schema dn present: (skip schema loading)\n");
+               return LDB_SUCCESS;
        }
 
-       data = talloc(module, struct schema_fsmo_private_data);
+       data = talloc(module, struct schema_data_private_data);
        if (data == NULL) {
                ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
@@ -218,50 +128,13 @@ static int schema_fsmo_init(struct ldb_module *module)
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       ldb_module_set_private(module, data);
-
-       if (dsdb_get_schema(ldb)) {
-               return ldb_next_init(module);
-       }
-
-       mem_ctx = talloc_new(module);
-       if (!mem_ctx) {
-               ldb_oom(ldb);
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       ret = dsdb_schema_from_schema_dn(mem_ctx, module,
-                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
-                                        schema_dn, &schema);
-
-       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
-               ldb_reset_err_string(ldb);
-               ldb_debug(ldb, LDB_DEBUG_WARNING,
-                         "schema_fsmo_init: no schema head present: (skip schema loading)\n");
-               talloc_free(mem_ctx);
-               return ldb_next_init(module);
-       }
-
-       if (ret != LDB_SUCCESS) {
-               talloc_free(mem_ctx);
-               return ret;
-       }
-
-       /* dsdb_set_schema() steal schema into the ldb_context */
-       ret = dsdb_set_schema(ldb, schema);
-       if (ret != LDB_SUCCESS) {
-               ldb_debug_set(ldb, LDB_DEBUG_FATAL,
-                             "schema_fsmo_init: dsdb_set_schema() failed: %d:%s",
-                             ret, ldb_strerror(ret));
-               talloc_free(mem_ctx);
-               return ret;
-       }
+       data->schema_dn = schema_dn;
 
-       talloc_free(mem_ctx);
-       return ldb_next_init(module);
+       ldb_module_set_private(module, data);
+       return LDB_SUCCESS;
 }
 
-static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
+static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
 {
        struct ldb_context *ldb;
        struct dsdb_schema *schema;
@@ -291,7 +164,7 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
 
        if (!schema->fsmo.we_are_master) {
                ldb_debug_set(ldb, LDB_DEBUG_ERROR,
-                         "schema_fsmo_add: we are not master: reject request\n");
+                         "schema_data_add: we are not master: reject request\n");
                return LDB_ERR_UNWILLING_TO_PERFORM;
        }
 
@@ -318,7 +191,7 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
                return ldb_next_request(module, req);
        } else if (!W_ERROR_EQUAL(WERR_DS_NO_MSDS_INTID, status)) {
                ldb_debug_set(ldb, LDB_DEBUG_ERROR,
-                         "schema_fsmo_add: failed to map %s[%s]: %s\n",
+                         "schema_data_add: failed to map %s[%s]: %s\n",
                          oid_attr, oid, win_errstr(status));
                return LDB_ERR_UNWILLING_TO_PERFORM;
        }
@@ -326,7 +199,7 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
        status = dsdb_create_prefix_mapping(ldb, schema, oid);
        if (!W_ERROR_IS_OK(status)) {
                ldb_debug_set(ldb, LDB_DEBUG_ERROR,
-                         "schema_fsmo_add: failed to create prefix mapping for %s[%s]: %s\n",
+                         "schema_data_add: failed to create prefix mapping for %s[%s]: %s\n",
                          oid_attr, oid, win_errstr(status));
                return LDB_ERR_UNWILLING_TO_PERFORM;
        }
@@ -334,67 +207,6 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
        return ldb_next_request(module, req);
 }
 
-static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req)
-{
-       struct ldb_context *ldb;
-       struct ldb_dn *schema_dn;
-       struct dsdb_schema *schema;
-       int ret;
-       TALLOC_CTX *mem_ctx;
-
-       ldb = ldb_module_get_ctx(module);
-
-       if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
-               return ldb_next_request(module, req);
-       }
-       
-       schema_dn = samdb_schema_dn(ldb);
-       if (!schema_dn) {
-               ldb_reset_err_string(ldb);
-               ldb_debug(ldb, LDB_DEBUG_WARNING,
-                         "schema_fsmo_extended: no schema dn present: (skip schema loading)\n");
-               return ldb_next_request(module, req);
-       }
-       
-       mem_ctx = talloc_new(module);
-       if (!mem_ctx) {
-               ldb_oom(ldb);
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-       
-       ret = dsdb_schema_from_schema_dn(mem_ctx, module,
-                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
-                                        schema_dn, &schema);
-
-       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
-               ldb_reset_err_string(ldb);
-               ldb_debug(ldb, LDB_DEBUG_WARNING,
-                         "schema_fsmo_extended: no schema head present: (skip schema loading)\n");
-               talloc_free(mem_ctx);
-               return ldb_next_request(module, req);
-       }
-
-       if (ret != LDB_SUCCESS) {
-               talloc_free(mem_ctx);
-               return ldb_next_request(module, req);
-       }
-
-       /* Replace the old schema*/
-       ret = dsdb_set_schema(ldb, schema);
-       if (ret != LDB_SUCCESS) {
-               ldb_debug_set(ldb, LDB_DEBUG_FATAL,
-                             "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s",
-                             ret, ldb_strerror(ret));
-               talloc_free(mem_ctx);
-               return ret;
-       }
-
-       dsdb_make_schema_global(ldb);
-
-       talloc_free(mem_ctx);
-       return LDB_SUCCESS;
-}
-
 static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
                                  const struct dsdb_schema *schema) 
 {
@@ -533,15 +345,15 @@ static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_messag
 /* Add objectClasses, attributeTypes and dITContentRules from the
    schema object (they are not stored in the database)
  */
-static int schema_fsmo_search_callback(struct ldb_request *req, struct ldb_reply *ares)
+static int schema_data_search_callback(struct ldb_request *req, struct ldb_reply *ares)
 {
        struct ldb_context *ldb;
-       struct schema_fsmo_search_data *ac;
-       struct schema_fsmo_private_data *mc;
+       struct schema_data_search_data *ac;
+       struct schema_data_private_data *mc;
        int i, ret;
 
-       ac = talloc_get_type(req->context, struct schema_fsmo_search_data);
-       mc = talloc_get_type(ldb_module_get_private(ac->module), struct schema_fsmo_private_data);
+       ac = talloc_get_type(req->context, struct schema_data_search_data);
+       mc = talloc_get_type(ldb_module_get_private(ac->module), struct schema_data_private_data);
        ldb = ldb_module_get_ctx(ac->module);
 
        if (!ares) {
@@ -567,7 +379,8 @@ static int schema_fsmo_search_callback(struct ldb_request *req, struct ldb_reply
                                        }
                                }
                        }
-               } else {
+               } else if ((ldb_dn_compare_base(mc->schema_dn, ares->message->dn) == 0)
+                          && (ldb_dn_compare(mc->schema_dn, ares->message->dn) != 0)) {
                        for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
                                if (!generated_attrs[i].aggregate &&
                                    ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
@@ -596,11 +409,11 @@ static int schema_fsmo_search_callback(struct ldb_request *req, struct ldb_reply
 }
 
 /* search */
-static int schema_fsmo_search(struct ldb_module *module, struct ldb_request *req)
+static int schema_data_search(struct ldb_module *module, struct ldb_request *req)
 {
        struct ldb_context *ldb = ldb_module_get_ctx(module);
        int i, ret;
-       struct schema_fsmo_search_data *search_context;
+       struct schema_data_search_data *search_context;
        struct ldb_request *down_req;
        struct dsdb_schema *schema = dsdb_get_schema(ldb);
 
@@ -619,7 +432,7 @@ static int schema_fsmo_search(struct ldb_module *module, struct ldb_request *req
                return ldb_next_request(module, req);
        }
 
-       search_context = talloc(req, struct schema_fsmo_search_data);
+       search_context = talloc(req, struct schema_data_search_data);
        if (!search_context) {
                ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
@@ -635,7 +448,7 @@ static int schema_fsmo_search(struct ldb_module *module, struct ldb_request *req
                                        req->op.search.tree,
                                        req->op.search.attrs,
                                        req->controls,
-                                       search_context, schema_fsmo_search_callback,
+                                       search_context, schema_data_search_callback,
                                        req);
        if (ret != LDB_SUCCESS) {
                return LDB_ERR_OPERATIONS_ERROR;
@@ -645,10 +458,9 @@ static int schema_fsmo_search(struct ldb_module *module, struct ldb_request *req
 }
 
 
-_PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = {
-       .name           = "schema_fsmo",
-       .init_context   = schema_fsmo_init,
-       .add            = schema_fsmo_add,
-       .extended       = schema_fsmo_extended,
-       .search         = schema_fsmo_search
+_PUBLIC_ const struct ldb_module_ops ldb_schema_data_module_ops = {
+       .name           = "schema_data",
+       .init_context   = schema_data_init,
+       .add            = schema_data_add,
+       .search         = schema_data_search
 };
diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c
new file mode 100644 (file)
index 0000000..62c941d
--- /dev/null
@@ -0,0 +1,258 @@
+/* 
+   Unix SMB/CIFS mplementation.
+
+   The module that handles the Schema FSMO Role Owner
+   checkings, it also loads the dsdb_schema.
+   
+   Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
+    
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   
+*/
+
+#include "includes.h"
+#include "ldb_module.h"
+#include "dsdb/samdb/samdb.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_drsuapi.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "param/param.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+
+/*
+  Given an LDB module (pointing at the schema DB), and the DN, set the populated schema
+*/
+
+static int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_module *module,
+                                     struct smb_iconv_convenience *iconv_convenience, 
+                                     struct ldb_dn *schema_dn,
+                                     struct dsdb_schema **schema) 
+{
+       TALLOC_CTX *tmp_ctx;
+       char *error_string;
+       int ret;
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
+       struct ldb_result *schema_res;
+       struct ldb_result *a_res;
+       struct ldb_result *c_res;
+       static const char *schema_attrs[] = {
+               "prefixMap",
+               "schemaInfo",
+               "fSMORoleOwner",
+               NULL
+       };
+       unsigned flags;
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (!tmp_ctx) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       /* we don't want to trace the schema load */
+       flags = ldb_get_flags(ldb);
+       ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
+
+       /*
+        * setup the prefix mappings and schema info
+        */
+       ret = dsdb_module_search_dn(module, tmp_ctx, &schema_res,
+                                   schema_dn, schema_attrs);
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               goto failed;
+       } else if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(ldb, 
+                                      "dsdb_schema: failed to search the schema head: %s",
+                                      ldb_errstring(ldb));
+               goto failed;
+       }
+
+       /*
+        * load the attribute definitions
+        */
+       ret = dsdb_module_search(module, tmp_ctx, &a_res,
+                                schema_dn, LDB_SCOPE_ONELEVEL, NULL,
+                                "(objectClass=attributeSchema)");
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(ldb, 
+                                      "dsdb_schema: failed to search attributeSchema objects: %s",
+                                      ldb_errstring(ldb));
+               goto failed;
+       }
+
+       /*
+        * load the objectClass definitions
+        */
+       ret = dsdb_module_search(module, tmp_ctx, &c_res,
+                                schema_dn, LDB_SCOPE_ONELEVEL, NULL,
+                                "(objectClass=classSchema)");
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(ldb, 
+                                      "dsdb_schema: failed to search attributeSchema objects: %s",
+                                      ldb_errstring(ldb));
+               goto failed;
+       }
+
+       ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
+                                          lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+                                          schema_res, a_res, c_res, schema, &error_string);
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(ldb, 
+                                                   "dsdb_schema load failed: %s",
+                                                   error_string);
+               goto failed;
+       }
+       talloc_steal(mem_ctx, *schema);
+
+failed:
+       if (flags & LDB_FLG_ENABLE_TRACING) {
+               flags = ldb_get_flags(ldb);
+               ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
+       }
+       talloc_free(tmp_ctx);
+       return ret;
+}      
+
+
+static int schema_load_init(struct ldb_module *module)
+{
+       struct ldb_context *ldb;
+       TALLOC_CTX *mem_ctx;
+       struct ldb_dn *schema_dn;
+       struct dsdb_schema *schema;
+       int ret;
+
+       ret = ldb_next_init(module);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       ldb = ldb_module_get_ctx(module);
+       schema_dn = samdb_schema_dn(ldb);
+       if (!schema_dn) {
+               ldb_reset_err_string(ldb);
+               ldb_debug(ldb, LDB_DEBUG_WARNING,
+                         "schema_load_init: no schema dn present: (skip schema loading)\n");
+               return LDB_SUCCESS;
+       }
+
+       if (dsdb_get_schema(ldb)) {
+               return LDB_SUCCESS;
+       }
+
+       mem_ctx = talloc_new(module);
+       if (!mem_ctx) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       ret = dsdb_schema_from_schema_dn(mem_ctx, module,
+                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+                                        schema_dn, &schema);
+
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               ldb_reset_err_string(ldb);
+               ldb_debug(ldb, LDB_DEBUG_WARNING,
+                         "schema_load_init: no schema head present: (skip schema loading)\n");
+               talloc_free(mem_ctx);
+               return LDB_SUCCESS;
+       }
+
+       if (ret != LDB_SUCCESS) {
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       /* dsdb_set_schema() steal schema into the ldb_context */
+       ret = dsdb_set_schema(ldb, schema);
+       if (ret != LDB_SUCCESS) {
+               ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+                             "schema_load_init: dsdb_set_schema() failed: %d:%s",
+                             ret, ldb_strerror(ret));
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       talloc_free(mem_ctx);
+       return LDB_SUCCESS;
+}
+
+static int schema_load_extended(struct ldb_module *module, struct ldb_request *req)
+{
+       struct ldb_context *ldb;
+       struct ldb_dn *schema_dn;
+       struct dsdb_schema *schema;
+       int ret;
+       TALLOC_CTX *mem_ctx;
+
+       ldb = ldb_module_get_ctx(module);
+
+       if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
+               return ldb_next_request(module, req);
+       }
+       
+       schema_dn = samdb_schema_dn(ldb);
+       if (!schema_dn) {
+               ldb_reset_err_string(ldb);
+               ldb_debug(ldb, LDB_DEBUG_WARNING,
+                         "schema_load_extended: no schema dn present: (skip schema loading)\n");
+               return ldb_next_request(module, req);
+       }
+       
+       mem_ctx = talloc_new(module);
+       if (!mem_ctx) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       ret = dsdb_schema_from_schema_dn(mem_ctx, module,
+                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+                                        schema_dn, &schema);
+
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               ldb_reset_err_string(ldb);
+               ldb_debug(ldb, LDB_DEBUG_WARNING,
+                         "schema_load_extended: no schema head present: (skip schema loading)\n");
+               talloc_free(mem_ctx);
+               return ldb_next_request(module, req);
+       }
+
+       if (ret != LDB_SUCCESS) {
+               talloc_free(mem_ctx);
+               return ldb_next_request(module, req);
+       }
+
+       /* Replace the old schema*/
+       ret = dsdb_set_schema(ldb, schema);
+       if (ret != LDB_SUCCESS) {
+               ldb_debug_set(ldb, LDB_DEBUG_FATAL,
+                             "schema_load_extended: dsdb_set_schema() failed: %d:%s",
+                             ret, ldb_strerror(ret));
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       dsdb_make_schema_global(ldb);
+
+       talloc_free(mem_ctx);
+       return LDB_SUCCESS;
+}
+
+
+_PUBLIC_ const struct ldb_module_ops ldb_schema_load_module_ops = {
+       .name           = "schema_load",
+       .init_context   = schema_load_init,
+       .extended       = schema_load_extended,
+};
index f3011521d41971277f279eb2813f4c84b2cd9a62..4df1188156f701d4d9e748734114bdb1a88959c7 100644 (file)
@@ -678,8 +678,9 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
                     "linked_attributes",
                     "extended_dn_out_ldb"]
     modules_list2 = ["show_deleted",
+                     "schema_load",
                      "new_partition",
-                    "partition"]
+                     "partition"]
     ldap_backend_line = "# No LDAP backend"
     if ldap_backend is not None:
         ldap_backend_line = "ldapBackend: %s" % ldap_backend.ldapi_uri
@@ -712,7 +713,7 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
                 "SCHEMADN_MOD2": ",objectguid",
                 "CONFIGDN": ldb.Dn(schema.ldb, names.configdn).get_casefold(),
                 "DOMAINDN": ldb.Dn(schema.ldb, names.domaindn).get_casefold(),
-                "SCHEMADN_MOD": "schema_fsmo",
+                "SCHEMADN_MOD": "schema_data",
                 "CONFIGDN_MOD": "naming_fsmo",
                 "DOMAINDN_MOD": "pdc_fsmo",
                 "MODULES_LIST": ",".join(modules_list),