summaryrefslogtreecommitdiffstats
path: root/ipaserver/install/ldapupdate.py
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-09-14 16:12:58 -0400
committerJason Gerard DeRose <jderose@redhat.com>2009-10-05 13:25:42 -0600
commite62bbab37a50fe024977798eb194cbe74bcd3587 (patch)
tree2fa47dea5f8648a1752745d98a59b0b1db78f219 /ipaserver/install/ldapupdate.py
parentaa7792a00035c7b7a37726f07a08824d8a4334f8 (diff)
downloadfreeipa-e62bbab37a50fe024977798eb194cbe74bcd3587.tar.gz
freeipa-e62bbab37a50fe024977798eb194cbe74bcd3587.tar.xz
freeipa-e62bbab37a50fe024977798eb194cbe74bcd3587.zip
Let the updater delete entries and add small test harness
In order to run the tests you must put your DM password into ~/.ipa/.dmpw Some tests are expected to generate errors. Don't let any ERROR messages from the updater fool you, watch the pass/fail of the nosetests.
Diffstat (limited to 'ipaserver/install/ldapupdate.py')
-rw-r--r--ipaserver/install/ldapupdate.py55
1 files changed, 49 insertions, 6 deletions
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index d4d1f2157..01a8d78be 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -122,7 +122,7 @@ class LDAPUpdate:
else:
return ""
- def __template_str(self, s):
+ def _template_str(self, s):
try:
return ipautil.template_str(s, self.sub_dict)
except KeyError, e:
@@ -199,7 +199,7 @@ class LDAPUpdate:
def parse_update_file(self, data, all_updates, dn_list):
"""Parse the update file into a dictonary of lists and apply the update
for each DN in the file."""
- valid_keywords = ["default", "add", "remove", "only"]
+ valid_keywords = ["default", "add", "remove", "only", "deleteentry"]
update = {}
d = ""
index = ""
@@ -219,12 +219,12 @@ class LDAPUpdate:
update = {}
dn = line[3:].strip()
- update['dn'] = self.__template_str(dn)
+ update['dn'] = self._template_str(dn)
else:
if dn is None:
raise BadSyntax, "dn is not defined in the update"
- line = self.__template_str(line)
+ line = self._template_str(line)
if line.startswith(' '):
v = d[len(d) - 1]
v = v + line[1:]
@@ -271,7 +271,7 @@ class LDAPUpdate:
# randomness for good measure.
self.sub_dict['TIME'] = int(time.time()) + r.randint(0,10000)
- cn = self.__template_str("indextask_$TIME")
+ cn = self._template_str("indextask_$TIME")
dn = "cn=%s, cn=index, cn=tasks, cn=config" % cn
e = ipaldap.Entry(dn)
@@ -368,7 +368,7 @@ class LDAPUpdate:
"""updates is a list of changes to apply
entry is the thing to apply them to
- returns the modified entry
+ Returns the modified entry
"""
if not updates:
return entry
@@ -416,6 +416,9 @@ class LDAPUpdate:
only[k] = True
entry.setValues(k, e)
logging.debug('only: updated value %s', e)
+ elif utype == 'deleteentry':
+ # skip this update type, it occurs in __delete_entries()
+ return None
self.print_entity(entry)
@@ -436,6 +439,7 @@ class LDAPUpdate:
logging.debug(a + ": ")
for l in value:
logging.debug("\t" + l)
+
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
@@ -489,6 +493,9 @@ class LDAPUpdate:
# Bring this entry up to date
entry = self.__apply_updates(update.get('updates'), entry)
+ if entry is None:
+ # It might be None if it is just deleting an entry
+ return
self.print_entity(entry, "Final value")
@@ -500,6 +507,7 @@ class LDAPUpdate:
try:
if self.live_run:
self.conn.addEntry(entry.dn, entry.toTupleList())
+ self.modified = True
except Exception, e:
logging.error("Add failure %s", e)
else:
@@ -533,6 +541,34 @@ class LDAPUpdate:
self.modified = True
return
+ def __delete_record(self, updates):
+ """
+ Run through all the updates again looking for any that should be
+ deleted.
+
+ This must use a reversed list so that the longest entries are
+ considered first so we don't end up trying to delete a parent
+ and child in the wrong order.
+ """
+ dn = updates['dn']
+ updates = updates['updates']
+ for u in updates:
+ # We already do syntax-parsing so this is safe
+ (utype, k, values) = u.split(':',2)
+
+ if utype == 'deleteentry':
+ try:
+ if self.live_run:
+ self.conn.deleteEntry(dn)
+ self.modified = True
+ except errors.NotFound, e:
+ logging.info("Deleting non-existant entry %s", e)
+ self.modified = True
+ except errors.DatabaseError, e:
+ logging.error("Delete failed: %s", e)
+
+ return
+
def get_all_files(self, root, recursive=False):
"""Get all update files"""
f = []
@@ -566,11 +602,18 @@ class LDAPUpdate:
(all_updates, dn_list) = self.parse_update_file(data, all_updates, dn_list)
+ # For adds and updates we want to apply updates from shortest
+ # to greatest length of the DN. For deletes we want the reverse.
sortedkeys = dn_list.keys()
sortedkeys.sort()
for k in sortedkeys:
for dn in dn_list[k]:
self.__update_record(all_updates[dn])
+
+ sortedkeys.reverse()
+ for k in sortedkeys:
+ for dn in dn_list[k]:
+ self.__delete_record(all_updates[dn])
finally:
if self.conn: self.conn.unbind()