summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--install/updates/10-bind-schema.update2
-rw-r--r--ipaserver/install/ldapupdate.py52
2 files changed, 52 insertions, 2 deletions
diff --git a/install/updates/10-bind-schema.update b/install/updates/10-bind-schema.update
index 0edbad204..3c43c8ec7 100644
--- a/install/updates/10-bind-schema.update
+++ b/install/updates/10-bind-schema.update
@@ -75,4 +75,6 @@ add:objectClasses:
MUST idnsName
MAY managedBy
X-ORIGIN 'IPA v3' )
+
+dn: cn=schema
replace:objectClasses:( 2.16.840.1.113730.3.8.6.1 NAME 'idnsZone' DESC 'Zone class' SUP idnsRecord STRUCTURAL MUST ( idnsZoneActive $$ idnsSOAmName $$ idnsSOArName $$ idnsSOAserial $$ idnsSOArefresh $$ idnsSOAretry $$ idnsSOAexpire $$ idnsSOAminimum ) MAY idnsUpdatePolicy )::( 2.16.840.1.113730.3.8.6.1 NAME 'idnsZone' DESC 'Zone class' SUP idnsRecord STRUCTURAL MUST ( idnsName $$ idnsZoneActive $$ idnsSOAmName $$ idnsSOArName $$ idnsSOAserial $$ idnsSOArefresh $$ idnsSOAretry $$ idnsSOAexpire $$ idnsSOAminimum ) MAY ( idnsUpdatePolicy $$ idnsAllowQuery $$ idnsAllowTransfer $$ idnsAllowSyncPTR $$ idnsForwardPolicy $$ idnsForwarders ) )
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index d673ad57d..111769ffe 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -35,6 +35,7 @@ from ipalib import errors
from ipalib import api
from ipapython.dn import DN
import ldap
+from ldap.schema.models import ObjectClass
from ipapython.ipa_log_manager import *
import krbV
import platform
@@ -546,6 +547,28 @@ class LDAPUpdate:
entry_values = []
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
+ objectclass_replacement = False
+ if action == "replace" and entry.dn == DN(('cn', 'schema')) and \
+ attr.lower() == "objectclasses":
+ objectclass_replacement = True
+ oid_index = {}
+ # build the OID index for replacing
+ for objectclass in entry_values:
+ try:
+ objectclass_object = ObjectClass(str(objectclass))
+ except Exception, e:
+ self.error('replace: cannot parse ObjectClass "%s": %s',
+ objectclass, e)
+ continue
+ # In a corner case, there may be more representations of
+ # the same objectclass due to the previous updates
+ # We want to replace them all
+ oid_index.setdefault(objectclass_object.oid, []).append(objectclass)
+
for update_value in update_values:
if action == 'remove':
self.debug("remove: '%s' from %s, current value %s", update_value, attr, entry_values)
@@ -601,7 +624,28 @@ class LDAPUpdate:
except ValueError:
raise BadSyntax, "bad syntax in replace, needs to be in the format old::new in %s" % update_value
try:
- entry_values.remove(old)
+ if objectclass_replacement:
+ try:
+ objectclass_old = ObjectClass(str(old))
+ except Exception, e:
+ self.error('replace: cannot parse replaced ObjectClass "%s": %s',
+ old, e)
+ continue
+ replaced_values = []
+ for objectclass in oid_index.get(objectclass_old.oid, []):
+ objectclass_object = ObjectClass(str(objectclass))
+ if str(objectclass_old).lower() == str(objectclass_object).lower():
+ # compare normalized values
+ replaced_values.append(objectclass)
+ self.debug('replace: replace ObjectClass "%s" with "%s"',
+ old, new)
+ if not replaced_values:
+ self.debug('replace: no match for replaced ObjectClass "%s"', 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', entry_values)
entry.setValues(attr, entry_values)
@@ -728,7 +772,11 @@ class LDAPUpdate:
updated = False
changes = self.conn.generateModList(entry.origDataDict(), entry.toDict())
if (entry.dn == DN(('cn', 'schema'))):
- updated = self.is_schema_updated(entry.toDict())
+ d = dict()
+ e = entry.toDict()
+ for k,v in e.items():
+ d[k] = [str(x) for x in v]
+ updated = self.is_schema_updated(d)
else:
if len(changes) >= 1:
updated = True