summaryrefslogtreecommitdiffstats
path: root/ipaserver
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2010-12-10 09:48:06 -0500
committerSimo Sorce <ssorce@redhat.com>2010-12-21 17:28:13 -0500
commit1cf67fe8503981b8aca985043bc5a8cd2799a365 (patch)
treeb36aa7612450d407d9737b5d3600d3b987b1c800 /ipaserver
parent5884fdf0f864d67fe7ee48d29f3c023882bc2891 (diff)
downloadfreeipa-1cf67fe8503981b8aca985043bc5a8cd2799a365.tar.gz
freeipa-1cf67fe8503981b8aca985043bc5a8cd2799a365.tar.xz
freeipa-1cf67fe8503981b8aca985043bc5a8cd2799a365.zip
Remove common entries when deleting a master.
Fixes: https://fedorahosted.org/freeipa/ticket/550
Diffstat (limited to 'ipaserver')
-rw-r--r--ipaserver/install/replication.py73
-rw-r--r--ipaserver/ipaldap.py29
-rw-r--r--ipaserver/plugins/ldap2.py7
3 files changed, 106 insertions, 3 deletions
diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py
index f3e007c6..fbe4d2f7 100644
--- a/ipaserver/install/replication.py
+++ b/ipaserver/install/replication.py
@@ -573,3 +573,76 @@ class ReplicationManager:
return WINSYNC
return IPA_REPLICA
+
+ def replica_cleanup(self, replica, realm, force=False):
+
+ err = None
+
+ if replica == self.hostname:
+ raise RuntimeError("Can't cleanup self")
+
+ if not self.suffix or self.suffix == "":
+ self.suffix = util.realm_to_suffix(realm)
+ self.suffix = ipaldap.IPAdmin.normalizeDN(self.suffix)
+
+ # delete master kerberos key and all its svc principals
+ try:
+ filter='(krbprincipalname=*/%s@%s)' % (replica, realm)
+ entries = self.conn.search_s(self.suffix, ldap.SCOPE_SUBTREE,
+ filterstr=filter)
+ if len(entries) != 0:
+ dnset = self.conn.get_dns_sorted_by_length(entries,
+ reverse=True)
+ for dns in dnset:
+ for dn in dns:
+ self.conn.deleteEntry(dn)
+ except ldap.NO_SUCH_OBJECT:
+ pass
+ except errors.NotFound:
+ pass
+ except Exception, e:
+ if not force:
+ raise e
+ else:
+ err = e
+
+ # delete master entry with all active services
+ try:
+ dn = 'cn=%s,cn=masters,cn=ipa,cn=etc,%s' % (replica, self.suffix)
+ entries = self.conn.search_s(dn, ldap.SCOPE_SUBTREE)
+ if len(entries) != 0:
+ dnset = self.conn.get_dns_sorted_by_length(entries,
+ reverse=True)
+ for dns in dnset:
+ for dn in dns:
+ self.conn.deleteEntry(dn)
+ except ldap.NO_SUCH_OBJECT:
+ pass
+ except errors.NotFound:
+ pass
+ except Exception, e:
+ if not force:
+ raise e
+ elif not err:
+ err = e
+
+ try:
+ basedn = 'cn=etc,%s' % self.suffix
+ filter = '(dnaHostname=%s)' % replica
+ entries = self.conn.search_s(basedn, ldap.SCOPE_SUBTREE,
+ filterstr=filter)
+ if len(entries) != 0:
+ for e in entries:
+ self.conn.deleteEntry(e.dn)
+ except ldap.NO_SUCH_OBJECT:
+ pass
+ except errors.NotFound:
+ pass
+ except Exception, e:
+ if force and err:
+ raise err
+ else:
+ raise e
+
+ if err:
+ raise err
diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py
index f7e0f3dd..b1f9f40c 100644
--- a/ipaserver/ipaldap.py
+++ b/ipaserver/ipaldap.py
@@ -640,6 +640,35 @@ class IPAdmin(SimpleLDAPObject):
return ",".join(ary)
normalizeDN = staticmethod(normalizeDN)
+ def get_dns_sorted_by_length(self, entries, reverse=False):
+ """
+ Sorts a list of entries [(dn, entry_attrs)] based on their DN.
+ Entries within the same node are not sorted in any meaningful way.
+ If Reverse is set to True, leaf entries are returned first. This is
+ useful to perform recursive deletes where you need to delete entries
+ starting from the leafs and go up to delete nodes only when all its
+ leafs are removed.
+
+ Returns a "sorted" dict keyed by dn lengths and corresponding list
+ of DNs.
+ {'1': [dn1, dn2, dn3], '2': [dn4, dn5], ..}
+ """
+
+ res = dict()
+
+ for e in entries:
+ sdn = ldap.dn.str2dn(e.dn)
+ l = len(sdn)
+ if not l in res:
+ res[l] = []
+ res[l].append(e.dn)
+
+ keys = res.keys()
+ keys.sort(reverse=reverse)
+
+ return map(res.get, keys)
+
+
def notfound(args):
"""Return a string suitable for displaying as an error when a
search returns no results.
diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index 89c499f0..06a94077 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -506,9 +506,10 @@ class ldap2(CrudBackend, Encoder):
scope=_ldap.SCOPE_SUBTREE, time_limit=None, size_limit=None,
normalize=True):
"""
- Return a list of entries [(dn, entry_attrs)] matching specified
- search parameters followed by truncated flag. If the truncated flag is
- True, search hit a server limit and its results are incomplete.
+ Return a list of entries and indication of whteher the results where
+ truncated ([(dn, entry_attrs)], truncated) matching specified search
+ parameters followed by truncated flag. If the truncated flag is True,
+ search hit a server limit and its results are incomplete.
Keyword arguments:
attrs_list -- list of attributes to return, all if None (default None)