summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2016-02-23 14:57:04 +1300
committerAndrew Bartlett <abartlet@samba.org>2016-03-08 01:58:30 +0100
commitc79c1e405d52c5dc54b8f03cd891e47f7ea04497 (patch)
treec0702d7c920258ae407c3e91218f382ae9c0a752 /python
parent13e62b2e350a21beefe871de64900fb78c5385f7 (diff)
downloadsamba-c79c1e405d52c5dc54b8f03cd891e47f7ea04497.tar.gz
dbcheck: Check for and remove duplicate values in attributes
This can happen with three DCs and custom schema, but we test it by just forcing the values directly into the backing tdb. Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Diffstat (limited to 'python')
-rw-r--r--python/samba/dbchecker.py26
1 files changed, 26 insertions, 0 deletions
diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py
index 3a65c089c7c..db0803b7a91 100644
--- a/python/samba/dbchecker.py
+++ b/python/samba/dbchecker.py
@@ -49,6 +49,7 @@ class dbcheck(object):
self.remove_all_unknown_attributes = False
self.remove_all_empty_attributes = False
self.fix_all_normalisation = False
+ self.fix_all_duplicates = False
self.fix_all_DN_GUIDs = False
self.fix_all_binary_dn = False
self.remove_all_deleted_DN_links = False
@@ -292,6 +293,23 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
validate=False):
self.report("Normalised attribute %s" % attrname)
+ def err_duplicate_values(self, dn, attrname, dup_values, values):
+ '''fix attribute normalisation errors'''
+ self.report("ERROR: Duplicate values for attribute '%s' in '%s'" % (attrname, dn))
+ self.report("Values contain a duplicate: [%s]/[%s]!" % (','.join(dup_values), ','.join(values)))
+ if not self.confirm_all("Fix duplicates for '%s' from '%s'?" % (attrname, dn), 'fix_all_duplicates'):
+ self.report("Not fixing attribute '%s'" % attrname)
+ return
+
+ m = ldb.Message()
+ m.dn = dn
+ m[attrname] = ldb.MessageElement(values, ldb.FLAG_MOD_REPLACE, attrname)
+
+ if self.do_modify(m, ["relax:0", "show_recycled:1"],
+ "Failed to remove duplicate value on attribute %s" % attrname,
+ validate=False):
+ self.report("Removed duplicate value on attribute %s" % attrname)
+
def is_deleted_objects_dn(self, dsdb_dn):
'''see if a dsdb_Dn is the special Deleted Objects DN'''
return dsdb_dn.prefix == "B:32:%s:" % dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER
@@ -1447,14 +1465,22 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
# it's some form of DN, do specialised checking on those
error_count += self.check_dn(obj, attrname, syntax_oid)
+ values = set()
# check for incorrectly normalised attributes
for val in obj[attrname]:
+ values.add(str(val))
+
normalised = self.samdb.dsdb_normalise_attributes(self.samdb_schema, attrname, [val])
if len(normalised) != 1 or normalised[0] != val:
self.err_normalise_mismatch(dn, attrname, obj[attrname])
error_count += 1
break
+ if len(obj[attrname]) != len(values):
+ self.err_duplicate_values(dn, attrname, obj[attrname], list(values))
+ error_count += 1
+ break
+
if str(attrname).lower() == "instancetype":
calculated_instancetype = self.calculate_instancetype(dn)
if len(obj["instanceType"]) != 1 or obj["instanceType"][0] != str(calculated_instancetype):