Remove schema special-casing from the LDAP updater

Now that there's a dedicated schema updater, we do not need the code
in ldapupdate.

https://fedorahosted.org/freeipa/ticket/3454
This commit is contained in:
Petr Viktorin 2013-04-26 15:38:38 +02:00
parent d9a1c09e7c
commit 6381d766ce
2 changed files with 12 additions and 130 deletions

View File

@ -1963,25 +1963,14 @@ class IPAdmin(LDAPClient):
if key in FORCE_REPLACE_ON_UPDATE_ATTRS or is_single_value:
force_replace = True
# You can't remove schema online. An add will automatically
# replace any existing schema.
if old_entry.dn == DN(('cn', 'schema')):
if len(adds) > 0:
if key.lower() == 'attributetypes':
modlist.insert(0, (ldap.MOD_ADD, key, adds))
else:
modlist.append((ldap.MOD_ADD, key, adds))
else:
if adds:
if force_replace:
modlist.append((ldap.MOD_REPLACE, key, adds))
else:
modlist.append((ldap.MOD_ADD, key, adds))
if removes:
if not force_replace:
modlist.append((ldap.MOD_DELETE, key, removes))
elif new_values == []: # delete an empty value
modlist.append((ldap.MOD_DELETE, key, removes))
if adds:
if force_replace:
modlist.append((ldap.MOD_REPLACE, key, adds))
else:
modlist.append((ldap.MOD_ADD, key, adds))
if removes:
if not force_replace or not new_values:
modlist.append((ldap.MOD_DELETE, key, removes))
return modlist

View File

@ -32,12 +32,10 @@ import os
import pwd
import fnmatch
import csv
import inspect
import re
import krbV
import ldap
from ldap.schema.models import ObjectClass, AttributeType
from ipaserver.install import installutils
from ipapython import ipautil, ipaldap
@ -576,36 +574,6 @@ class LDAPUpdate:
else:
entry_values = [entry_values]
# Replacing objectClassess needs a special handling and
# normalization of OC definitions to avoid update failures for
# example when X-ORIGIN is the only difference
schema_update = False
schema_elem_class = None
schema_elem_name = None
if action == "replace" and entry.dn == DN(('cn', 'schema')):
if attr.lower() == "objectclasses":
schema_elem_class = ObjectClass
schema_elem_name = "ObjectClass"
elif attr.lower() == "attributetypes":
schema_elem_class = AttributeType
schema_elem_name = "AttributeType"
if schema_elem_class is not None:
schema_update = True
oid_index = {}
# build the OID index for replacing
for schema_elem in entry_values:
try:
schema_elem_object = schema_elem_class(str(schema_elem))
except Exception, e:
self.error('replace: cannot parse %s "%s": %s',
schema_elem_name, schema_elem, e)
continue
# In a corner case, there may be more representations of
# the same objectclass/attributetype due to the previous updates
# We want to replace them all
oid_index.setdefault(schema_elem_object.oid, []).append(schema_elem)
for update_value in update_values:
if action == 'remove':
self.debug("remove: '%s' from %s, current value %s", safe_output(attr, update_value), attr, safe_output(attr,entry_values))
@ -672,37 +640,6 @@ class LDAPUpdate:
(old, new) = update_value.split('::', 1)
except ValueError:
raise BadSyntax, "bad syntax in replace, needs to be in the format old::new in %s" % update_value
try:
if schema_update:
try:
schema_elem_old = schema_elem_class(str(old))
except Exception, e:
self.error('replace: cannot parse replaced %s "%s": %s',
schema_elem_name, old, e)
continue
replaced_values = []
for schema_elem in oid_index.get(schema_elem_old.oid, []):
schema_elem_object = schema_elem_class(str(schema_elem))
if str(schema_elem_old).lower() == str(schema_elem_object).lower():
# compare normalized values
replaced_values.append(schema_elem)
self.debug('replace: replace %s "%s" with "%s"',
schema_elem_name,
safe_output(attr, old),
safe_output(attr, new))
if not replaced_values:
self.debug('replace: no match for replaced %s "%s"',
schema_elem_name, safe_output(attr, old))
continue
for value in replaced_values:
entry_values.remove(value)
else:
entry_values.remove(old)
entry_values.append(new)
self.debug('replace: updated value %s', safe_output(attr, entry_values))
entry[attr] = entry_values
except ValueError:
self.debug('replace: %s not found, skipping', safe_output(attr, old))
return entry
@ -720,43 +657,6 @@ class LDAPUpdate:
else:
self.debug('%s: %s', a, safe_output(a, value))
def is_schema_updated(self, s):
"""Compare the schema in 's' with the current schema in the DS to
see if anything has changed. This should account for syntax
differences (like added parens that make no difference but are
detected as a change by generateModList()).
This doesn't handle re-ordering of attributes. They are still
detected as changes, so foo $ bar != bar $ foo.
return True if the schema has changed
return False if it has not
"""
signature = inspect.getargspec(ldap.schema.SubSchema.__init__)
if 'check_uniqueness' in signature.args:
s = ldap.schema.SubSchema(s, check_uniqueness=0)
else:
s = ldap.schema.SubSchema(s)
s = s.ldap_entry()
# Get a fresh copy and convert into a SubSchema
n = self._get_entry(DN(('cn', 'schema')))[0]
# Convert IPA data types back to strings
d = dict()
for k,v in n.data.items():
d[k] = [str(x) for x in v]
# Convert to subschema dict
n = ldap.schema.SubSchema(d)
n = n.ldap_entry()
# Are they equal?
if s == n:
return False
else:
return True
def _update_record(self, update):
found = False
@ -823,14 +723,8 @@ class LDAPUpdate:
# Update LDAP
try:
changes = self.conn.generateModList(entry.orig_data, entry)
if (entry.dn == DN(('cn', 'schema'))):
d = dict()
for k,v in entry.items():
d[k] = [str(x) for x in v]
updated = self.is_schema_updated(d)
else:
if len(changes) >= 1:
updated = True
if len(changes) >= 1:
updated = True
safe_changes = []
for (type, attr, values) in changes:
safe_changes.append((type, attr, safe_output(attr, values)))
@ -906,13 +800,12 @@ class LDAPUpdate:
def _run_updates(self, all_updates):
# For adds and updates we want to apply updates from shortest
# to greatest length of the DN. cn=schema must always go first to add
# new objectClasses and attributeTypes
# to greatest length of the DN.
# For deletes we want the reverse
def update_sort_key(dn_update):
dn, update = dn_update
assert isinstance(dn, DN)
return dn != DN(('cn', 'schema')), len(dn)
return len(dn)
sorted_updates = sorted(all_updates.iteritems(), key=update_sort_key)