Martin Kosek wrote:
On Tue, 2012-02-28 at 16:36 -0500, Rob Crittenden wrote:
Martin Kosek wrote:
On Sat, 2012-02-25 at 17:43 -0500, Rob Crittenden wrote:
This patch does two things:

1. Prompts when deleting a master to make clear that this is irreversible
2. Does not allow a deleted master to be reconnected.

Reconnecting to a deleted master causes all heck to break loose because
we delete principals as part of deletion process. If you reconnect to a
deleted master then we replicate those deletes and the connected master
is now unusable (no principals).

A simple test is:

Install master
Install replica
ipa-replica-manage del replica
ipa-replica-manage connect replica
ipa-server-uninstall -U on replica
re-install replica

The re-install should be successful.


Generally, it looks and works well. I just miss some unattended way to
deleted a replica, from other script for example.

I think we may either re-use --force flag for this purpose or introduce
an --unattended flag.

I also found an issue with S4U2Proxy memberPrincipal added for each
replica. Since the memberPrincipal values for deleted replica are not
removed when a replica is being deleted, ipa-replica-install reports a
(benign) error when it tries to add a duplicate value afterwards. I
filed a ticket for this one:


OK, went with --force.


The approach should be OK, but the patch you included is wrong.


OK, this should be right.

>From 9ce941b7b18e1e9f9b77562f49e6d49537fd5347 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <>
Date: Fri, 24 Feb 2012 18:17:47 -0500
Subject: [PATCH] Warn that deleting replica is irreversible, try to detect

Using ipa-replica-manage del <replica> is irreversible. You can't
turn around and do a connect to it, all heck will break loose. This is
because we clean up all references to the replica when we delete so if
we connect to it again we'll end up deleting all of its principals.

When a connection is deleted then the agreement is removed on both sides.
What isn't removed is the nsDS5ReplicaBindDN so we can use that to
determine if we previously had a connection.
 install/tools/ipa-replica-manage       |   23 +++++++++++++++++++++++
 install/tools/man/ipa-replica-manage.1 |    2 +-
 2 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index da327e5b976b147721b7c5510041df553b4cdbce..f1f5425ca8d4083e7cb11f8d25f327ffb4ab2520 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -29,6 +29,7 @@ from ipaserver.install import bindinstance
 from ipaserver import ipaldap
 from ipapython import version
 from ipalib import api, errors, util
+from ipalib.dn import DN
 from ipapython.ipa_log_manager import *
 CACERT = "/etc/ipa/ca.crt"
@@ -287,6 +288,7 @@ def del_master(realm, hostname, options):
     # 3. If an IPA agreement connect to the master to be removed.
     repltype = thisrepl.get_agreement_type(hostname)
     if repltype == replication.IPA_REPLICA:
+        winsync = False
             delrepl = replication.ReplicationManager(realm, hostname, options.dirman_passwd)
         except Exception, e:
@@ -308,8 +310,17 @@ def del_master(realm, hostname, options):
             replica_names = delrepl.find_ipa_replication_agreements()
         # WINSYNC replica, delete agreement from current host
+        winsync = True
         replica_names = []
+    if not winsync and not options.force:
+        print "Deleting a master is irreversible."
+        print "To reconnect to the remote master you will need to prepare " \
+              "a new replica file"
+        print "and re-install."
+        if not ipautil.user_input("Continue to delete?", False):
+            sys.exit("Deletion aborted")
     # 4. Remove each agreement
     for r in replica_names:
@@ -390,6 +401,18 @@ def add_link(realm, replica1, replica2, dirman_passwd, options):
                                         options.passsync, options.win_subtree,
+        # First see if we already exist on the remote master. If so this was
+        # a previously deleted connection.
+        try:
+            repl2 = replication.ReplicationManager(realm, replica2, dirman_passwd)
+            master_dn = repl2.replica_dn()
+            binddn = str(DN(('krbprincipalname','ldap/%s@%s' % (replica1, api.env.realm)),(api.env.container_service),(api.env.basedn)))
+            master = repl2.conn.getEntry(master_dn, ldap.SCOPE_BASE)
+            binddns = master.getValues('nsDS5ReplicaBindDN')
+            if binddns and binddn in binddns:
+                sys.exit("You cannot connect to a previously deleted master")
+        except errors.NotFound:
+            pass
         repl1.setup_gssapi_replication(replica2, "cn=Directory Manager", dirman_passwd)
     print "Connected '%s' to '%s'" % (replica1, replica2)
diff --git a/install/tools/man/ipa-replica-manage.1 b/install/tools/man/ipa-replica-manage.1
index 8fca50a5a304e6504e5ed8986a2d692eaf440bbc..002c4299896001d666e90cf133e7b0325a2eecda 100644
--- a/install/tools/man/ipa-replica-manage.1
+++ b/install/tools/man/ipa-replica-manage.1
@@ -61,7 +61,7 @@ The Directory Manager password to use for authentication
 Provide additional information
 \fB\-f\fR, \fB\-\-force\fR
-Ignore some types of errors
+Ignore some types of errors, don't prompt when deleting a master
 Bind DN to use with remote server (default is cn=Directory Manager) \- Be careful to quote this value on the command line

Freeipa-devel mailing list

Reply via email to