Check for the existence of a replication agreement before deleting it.

When using ipa-replica-manage or ipa-csreplica-manage to delete an
agreement with a host we would try to make a connection to that host
prior to tryign to delete it. This meant that the trying to delete
a host we don't have an agreement with would return a connection
error instead of a "no agreement with host foo" error.

Also display a completed message when an agreement is removed.

https://fedorahosted.org/freeipa/ticket/2048
https://fedorahosted.org/freeipa/ticket/2125
This commit is contained in:
Rob Crittenden 2012-01-16 10:24:15 -05:00 committed by Martin Kosek
parent ce360f37f8
commit 7a1399bee1
3 changed files with 56 additions and 22 deletions

View File

@ -267,12 +267,26 @@ def del_link(realm, replica1, replica2, dirman_passwd, force=False):
repl1.delete_agreement(replica2)
repl1.delete_referral(replica2)
print "Deleted replication agreement from '%s' to '%s'" % (replica1, replica2)
def del_master(realm, hostname, options):
force_del = False
delrepl = None
# 1. Connect to the dogtag DS to be removed.
# 1. Connect to the local dogtag DS server
try:
thisrepl = CSReplicationManager(realm, options.host,
options.dirman_passwd)
except Exception, e:
sys.exit("Failed to connect to server %s: %s" % (options.host, convert_error(e)))
# 2. Ensure we have an agreement with the master
if thisrepl.get_replication_agreement(hostname) is None:
sys.exit("'%s' has no replication agreement for '%s'" % (options.host, hostname))
# 3. Connect to the dogtag DS to be removed.
try:
delrepl = CSReplicationManager(realm, hostname, options.dirman_passwd)
except Exception, e:
@ -283,21 +297,14 @@ def del_master(realm, hostname, options):
print "Unable to connect to replica %s, forcing removal" % hostname
force_del = True
# 2. Connect to the local dogtag DS server
try:
thisrepl = CSReplicationManager(realm, options.host,
options.dirman_passwd)
except Exception, e:
sys.exit("Failed to connect to server %s: %s" % (options.host, convert_error(e)))
# 2. Get list of agreements.
# 4. Get list of agreements.
if delrepl is None:
# server not up, just remove it from this server
replica_names = [options.host]
else:
replica_names = delrepl.find_ipa_replication_agreements()
# 3. Remove each agreement
# 5. Remove each agreement
for r in replica_names:
try:
del_link(realm, r, hostname, options.dirman_passwd, force=True)

View File

@ -272,12 +272,25 @@ def del_link(realm, replica1, replica2, dirman_passwd, force=False):
except Exception, e:
print "Error deleting winsync replica shared info: %s" % str(e)
print "Deleted replication agreement from '%s' to '%s'" % (replica1, replica2)
def del_master(realm, hostname, options):
force_del = False
# 1. Connect to the master to be removed.
# 1. Connect to the local server
try:
thisrepl = replication.ReplicationManager(realm, options.host,
options.dirman_passwd)
except Exception, e:
print "Failed to connect to server %s: %s" % (options.host, str(e))
sys.exit(1)
# 2. Ensure we have an agreement with the master
if thisrepl.get_replication_agreement(hostname) is None:
sys.exit("'%s' has no replication agreement for '%s'" % (options.host, hostname))
# 3. Connect to the master to be removed.
try:
delrepl = replication.ReplicationManager(realm, hostname, options.dirman_passwd)
except Exception, e:
@ -288,14 +301,6 @@ def del_master(realm, hostname, options):
print "Unable to connect to replica %s, forcing removal" % hostname
force_del = True
# 2. Connect to the local server
try:
thisrepl = replication.ReplicationManager(realm, options.host,
options.dirman_passwd)
except Exception, e:
print "Failed to connect to server %s: %s" % (options.host, str(e))
sys.exit(1)
if force_del:
dn = 'cn=masters,cn=ipa,cn=etc,%s' % thisrepl.suffix
res = thisrepl.conn.search_s(dn, ldap.SCOPE_ONELEVEL)
@ -306,21 +311,21 @@ def del_master(realm, hostname, options):
# 2. Get list of agreements.
replica_names = delrepl.find_ipa_replication_agreements()
# 3. Remove each agreement
# 4. Remove each agreement
for r in replica_names:
try:
del_link(realm, r, hostname, options.dirman_passwd, force=True)
except Exception, e:
print "There were issues removing a connection: %s" % str(e)
# 4. Finally clean up the removed replica common entries.
# 5. Finally clean up the removed replica common entries.
try:
thisrepl.replica_cleanup(hostname, realm, force=True)
except Exception, e:
print "Failed to cleanup %s entries: %s" % (hostname, str(e))
print "You may need to manually remove them from the tree"
# 5. And clean up the removed replica DNS entries if any.
# 6. And clean up the removed replica DNS entries if any.
try:
if bindinstance.dns_container_exists(options.host, thisrepl.suffix,
dm_password=options.dirman_passwd):

View File

@ -211,6 +211,28 @@ class ReplicationManager(object):
return res
def get_replication_agreement(self, hostname):
"""
The replication agreements are stored in
cn="$SUFFIX",cn=mapping tree,cn=config
Get the replication agreement for a specific host.
Returns None if not found.
"""
filt = "(&(objectclass=nsds5ReplicationAgreement)(nsDS5ReplicaHost=%s))" % hostname
try:
entry = self.conn.search_s("cn=mapping tree,cn=config",
ldap.SCOPE_SUBTREE, filt)
except ldap.NO_SUCH_OBJECT:
return None
if len(entry) == 0:
return None
else:
return entry[0] # There can be only one
def add_replication_manager(self, conn, dn, pw):
"""
Create a pseudo user to use for replication.