The branch, master has been updated via c9a6dd5 s4-dbcheck: support the 'none' option for prompts via bce1be3 s4-pycommon: support 'none' as an option in confirm via c6985f1 dbcheck: only use a paged search when checking a ldap database via 5f1c443 dbcheck: check for unknown attributes and offer to remove them via c9497bd s4-pycommon: allow an optional 'all' choice for confirm dialogs via 28dbd8b s4-dsdb: allow removal of unknown attributes if RELAX set from 4e63ac6 ccan: fix configure tests for __builtin_clz etc.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit c9a6dd56e42beafd297f4aefeb4e00ef9a09073a Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 5 13:03:18 2011 +1000 s4-dbcheck: support the 'none' option for prompts Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> Autobuild-User: Andrew Tridgell <tri...@samba.org> Autobuild-Date: Tue Jul 5 08:22:40 CEST 2011 on sn-devel-104 commit bce1be36dca87bea3b1bdbad86a8265fa1d4bed9 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 5 13:02:48 2011 +1000 s4-pycommon: support 'none' as an option in confirm this allows the user to ask for none of the changes of this type Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> commit c6985f1e7ed6f2d4d7e39e3eea7ed714f6c6ae06 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 5 12:44:07 2011 +1000 dbcheck: only use a paged search when checking a ldap database paged searches don't work against a local database (they return only the first N objects) commit 5f1c443a7768a4b610d6a7aff695cb60f91adf2d Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 5 12:42:53 2011 +1000 dbcheck: check for unknown attributes and offer to remove them this asks the user if they want to remove an unknown attribute. You can also choose 'all' which will auto-confirm all questions about removing unknown attributes. commit c9497bd77fd1e3f69b979a1799b7903b07972304 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 5 12:38:31 2011 +1000 s4-pycommon: allow an optional 'all' choice for confirm dialogs when asking the user to confirm an action, allow for an 'all' choice, which will be used to allow the user to confirm all future requests of the same type commit 28dbd8bbc174f5417b9dccea38f296e385f2c378 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 5 12:36:16 2011 +1000 s4-dsdb: allow removal of unknown attributes if RELAX set this allows attributes not known in the schema to be removed if the caller has set the RELAX control. This will be used by dbcheck to allow cleaning of bad attributes from the database ----------------------------------------------------------------------- Summary of changes: source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 12 ++++ source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 11 +++- source4/scripting/python/samba/common.py | 25 ++++++++- source4/scripting/python/samba/dbchecker.py | 57 ++++++++++++++++++- source4/scripting/python/samba/netcmd/dbcheck.py | 2 +- 5 files changed, 98 insertions(+), 9 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c index 5639a7a..302904a 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c @@ -121,6 +121,12 @@ static int attr_handler(struct oc_context *ac) attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, msg->elements[i].name); if (attr == NULL) { + if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) && + ac->req->operation != LDB_ADD) { + /* we allow this for dbcheck to fix + broken attributes */ + goto no_attribute; + } ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' was not found in the schema!", msg->elements[i].name, ldb_dn_get_linearized(msg->dn)); @@ -172,6 +178,7 @@ static int attr_handler(struct oc_context *ac) msg->elements[i].name = attr->lDAPDisplayName; } +no_attribute: if (ac->req->operation == LDB_ADD) { ret = ldb_build_add_req(&child_req, ldb, ac, msg, ac->req->controls, @@ -297,6 +304,11 @@ static int attr_handler2(struct oc_context *ac) attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, msg->elements[i].name); if (attr == NULL) { + if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) { + /* allow this to make it possible for dbcheck + to remove bad attributes */ + continue; + } return ldb_operr(ldb); } diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 9d2e5e2..830c118 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -1042,7 +1042,8 @@ static int replmd_update_rpmd_element(struct ldb_context *ldb, const struct dsdb_schema *schema, uint64_t *seq_num, const struct GUID *our_invocation_id, - NTTIME now) + NTTIME now, + struct ldb_request *req) { uint32_t i; const struct dsdb_attribute *a; @@ -1050,6 +1051,12 @@ static int replmd_update_rpmd_element(struct ldb_context *ldb, a = dsdb_attribute_by_lDAPDisplayName(schema, el->name); if (a == NULL) { + if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) { + /* allow this to make it possible for dbcheck + to remove bad attributes */ + return LDB_SUCCESS; + } + DEBUG(0,(__location__ ": Unable to find attribute %s in schema\n", el->name)); return LDB_ERR_OPERATIONS_ERROR; @@ -1299,7 +1306,7 @@ static int replmd_update_rpmd(struct ldb_module *module, struct ldb_message_element *old_el; old_el = ldb_msg_find_element(res->msgs[0], msg->elements[i].name); ret = replmd_update_rpmd_element(ldb, msg, &msg->elements[i], old_el, &omd, schema, seq_num, - our_invocation_id, now); + our_invocation_id, now, req); if (ret != LDB_SUCCESS) { return ret; } diff --git a/source4/scripting/python/samba/common.py b/source4/scripting/python/samba/common.py index a2a4962..6eeace5 100644 --- a/source4/scripting/python/samba/common.py +++ b/source4/scripting/python/samba/common.py @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -def confirm(msg, forced = False): +def confirm(msg, forced = False, allow_all=False): """confirm an action with the user :param msg: A string to print to the user :param forced: Are the answer forced @@ -27,7 +27,26 @@ def confirm(msg, forced = False): print("%s [YES]" % msg) return True - v = raw_input(msg + ' [y/N] ') - return v.upper() in ['Y', 'YES'] + mapping = { + 'Y': True, + 'YES': True, + '': False, + 'N': False, + 'NO': False, + } + + prompt = '[y/N]' + + if allow_all: + mapping['ALL'] = 'ALL' + mapping['NONE'] = 'NONE' + prompt = '[y/N/all/none]' + + while True: + v = raw_input(msg + ' %s ' % prompt) + v = v.upper() + if v in mapping: + return mapping[v] + print("Unknown response '%s'" % v) diff --git a/source4/scripting/python/samba/dbchecker.py b/source4/scripting/python/samba/dbchecker.py index 88fd0ed..4209a3b 100644 --- a/source4/scripting/python/samba/dbchecker.py +++ b/source4/scripting/python/samba/dbchecker.py @@ -57,6 +57,7 @@ class dbcheck(object): self.fix = fix self.yes = yes self.quiet = quiet + self.remove_all_unknown_attributes = False def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']): '''perform a database check, returning the number of errors found''' @@ -81,13 +82,38 @@ class dbcheck(object): ################################################################ # a local confirm function that obeys the --fix and --yes options - def confirm(self, msg): + def confirm(self, msg, allow_all=False, forced=False): '''confirm a change''' if not self.fix: return False if self.quiet: return self.yes - return common.confirm(msg, forced=self.yes) + if self.yes: + forced = True + return common.confirm(msg, forced=forced, allow_all=allow_all) + + ################################################################ + # a local confirm function with support for 'all' + def confirm_all(self, msg, all_attr): + '''confirm a change with support for "all" ''' + if not self.fix: + return False + if self.quiet: + return self.yes + if getattr(self, all_attr) == 'NONE': + return False + if getattr(self, all_attr) == 'ALL': + forced = True + else: + forced = self.yes + c = common.confirm(msg, forced=forced, allow_all=True) + if c == 'ALL': + setattr(self, all_attr, 'ALL') + return True + if c == 'NONE': + setattr(self, all_attr, 'NONE') + return True + return c ################################################################ @@ -227,6 +253,26 @@ class dbcheck(object): return self.report("Fixed incorrect DN string on attribute %s" % (attrname)) + ################################################################ + # handle an unknown attribute error + def err_unknown_attribute(self, obj, attrname): + '''handle an unknown attribute error''' + self.report("ERROR: unknown attribute '%s' in %s" % (attrname, obj.dn)) + if not self.confirm_all('Remove unknown attribute %s' % attrname, 'remove_all_unknown_attributes'): + self.report("Not removing %s" % attrname) + return + m = ldb.Message() + m.dn = obj.dn + m['old_value'] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, attrname) + if self.verbose: + self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY)) + try: + self.samdb.modify(m, controls=["relax:0"]) + except Exception, msg: + self.report("Failed to remove unknown attribute %s : %s" % (attrname, msg)) + return + self.report("Removed unknown attribute %s" % (attrname)) + ################################################################ # specialised checking for a dn attribute @@ -300,7 +346,12 @@ class dbcheck(object): # get the syntax oid for the attribute, so we can can have # special handling for some specific attribute types - syntax_oid = self.samdb_schema.get_syntax_oid_from_lDAPDisplayName(attrname) + try: + syntax_oid = self.samdb_schema.get_syntax_oid_from_lDAPDisplayName(attrname) + except Exception, msg: + self.err_unknown_attribute(obj, attrname) + error_count += 1 + continue if syntax_oid in [ dsdb.DSDB_SYNTAX_BINARY_DN, dsdb.DSDB_SYNTAX_OR_NAME, dsdb.DSDB_SYNTAX_STRING_DN, ldb.LDB_SYNTAX_DN ]: diff --git a/source4/scripting/python/samba/netcmd/dbcheck.py b/source4/scripting/python/samba/netcmd/dbcheck.py index 3cc50eb..c97942b 100644 --- a/source4/scripting/python/samba/netcmd/dbcheck.py +++ b/source4/scripting/python/samba/netcmd/dbcheck.py @@ -80,7 +80,7 @@ class cmd_dbcheck(Command): search_scope = scope_map[scope] controls = [] - if H is not None: + if H.startswith('ldap'): controls.append('paged_results:1:1000') if cross_ncs: controls.append("search_options:1:2") -- Samba Shared Repository