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

Reply via email to