Comment from segment deletion check which describes the patch:

Relax check if topology was or is disconnected. Disconnected topology
can contain segments with already deleted servers. Check only if
segments of servers, which can contact this server, and the deleted
server were removed.
This code should handle a case where there was a topology with
a central node(B):  A <-> B <-> C, where A is current server.
After removal of B, topology will be disconnected and removal of
segment B <-> C won't be replicated back to server A, therefore
presence of the segment has to be ignored.

part of: https://fedorahosted.org/freeipa/ticket/5072

patch 883 adds 180s timeout to the check and changes check interval from 1s to 2s.
--
Petr Vobornik
From eab018a0b6f13681088589790a134d1110407396 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Tue, 30 Jun 2015 13:37:31 +0200
Subject: [PATCH] ipa-replica-manage del: add timeout to segment removal check

---
 install/tools/ipa-replica-manage | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index 590babdaf4066398f9ca610e7026dd97fbbf851d..8623524a756a41161a29741ec88bfe47d0c35bf0 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -776,9 +776,17 @@ def del_master_managed(realm, hostname, options):
         if not left and not right:
             print "Agreements deleted"
             break
-        time.sleep(1)
-        if i == 5: # taking too long, something is wrong, report
+        time.sleep(2)
+        if i == 2: # taking too long, something is wrong, report
             print "Waiting for removal of replication agreements"
+        if i > 90:
+            print "Taking too long, skipping"
+            print "Following segments were not deleted:"
+            for s in left:
+                print "  %s" % s['cn'][0]
+            for s in right:
+                print "  %s" % s['cn'][0]
+            break
         i += 1
 
     # Clean RUV
-- 
2.4.3

From ea193fe3a38d28c9493eb2aded89fd4bbd79076e Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Fri, 26 Jun 2015 18:09:19 +0200
Subject: [PATCH] ipa-replica-manage del: relax segment deletement check if
 topology is disconnected

https://fedorahosted.org/freeipa/ticket/5072
---
 install/tools/ipa-replica-manage | 38 ++++++++++++++++++++++++++++++++++----
 ipapython/graph.py               | 11 +++++++++--
 2 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index e680b51b9e4ecba1d9b692abe5fe8ab4917641b8..78e484620503aae2c7c71ab740ee473283494bd0 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -566,7 +566,8 @@ def check_last_link_managed(api, masters, hostname, force):
     """
     Check if 'hostname' is safe to delete.
 
-    :returns: list of errors after future deletion
+    :returns: tuple with lists of current and future errors in topology
+              (current_errors, new_errors)
     """
 
     segments = api.Command.topologysegment_find(u'realm', sizelimit=0).get('result')
@@ -581,7 +582,11 @@ def check_last_link_managed(api, masters, hostname, force):
         print_connect_errors(orig_errors)
 
     # after removal
-    graph.remove_vertex(hostname)
+    try:
+        graph.remove_vertex(hostname)
+    except ValueError:
+        pass  # ignore already deleted master, continue to clean
+
     new_errors = get_topology_connection_errors(graph)
     if new_errors:
         print "WARNING: Topology after removal of %s will be disconnected." % hostname
@@ -596,7 +601,7 @@ def check_last_link_managed(api, masters, hostname, force):
         else:
             print "Forcing removal of %s" % hostname
 
-    return new_errors
+    return (orig_errors, new_errors)
 
 def print_connect_errors(errors):
     for error in errors:
@@ -712,7 +717,7 @@ def del_master_managed(realm, hostname, options):
     masters = api.Command.server_find('', sizelimit=0)['result']
 
     # 3. Check topology
-    check_last_link_managed(api, masters, hostname, options.force)
+    topo_errors = check_last_link_managed(api, masters, hostname, options.force)
 
     # 4. Check that we are not leaving the installation without CA and/or DNS
     #    And pick new CA master.
@@ -738,11 +743,36 @@ def del_master_managed(realm, hostname, options):
     # 7. Clean RUV for the deleted master
     # Wait for topology plugin to delete segments
     i = 0
+    m_cns = [m['cn'][0] for m in masters]  # masters before removal
     while True:
         left = api.Command.topologysegment_find(
             u'realm', iparepltoposegmentleftnode=hostname_u, sizelimit=0)['result']
         right = api.Command.topologysegment_find(
             u'realm', iparepltoposegmentrightnode=hostname_u, sizelimit=0)['result']
+
+        # If the server was already deleted, we can expect that all removals
+        # had been done in previous run and dangling segments were not deleted.
+        if hostname not in m_cns:
+            print "Skipping replication agreement deletion check"
+            break
+
+        # Relax check if topology was or is disconnected. Disconnected topology
+        # can contain segments with already deleted servers. Check only if
+        # segments of servers, which can contact this server, and the deleted
+        # server were removed.
+        # This code should handle a case where there was a topology with
+        # a central node(B):  A <-> B <-> C, where A is current server.
+        # After removal of B, topology will be disconnected and removal of
+        # segment B <-> C won't be replicated back to server A, therefore
+        # presence of the segment has to be ignored.
+        if topo_errors[0] or topo_errors[1]:
+            # use errors after deletion because we don't care if some server
+            # can't contact the deleted one
+            cant_contact_me = [e[0] for e in topo_errors[1] if options.host in e[2]]
+            can_contact_me = set(m_cns) - set(cant_contact_me)
+            left = [s for s in left if s['iparepltoposegmentrightnode'][0] in can_contact_me]
+            right = [s for s in right if s['iparepltoposegmentleftnode'][0] in can_contact_me]
+
         if not left and not right:
             print "Agreements deleted"
             break
diff --git a/ipapython/graph.py b/ipapython/graph.py
index 20b612548018faa6010be2f653060cb9d5ae065d..e27249466889720247258870a99c688be4690a45 100644
--- a/ipapython/graph.py
+++ b/ipapython/graph.py
@@ -29,11 +29,18 @@ class Graph():
         self._adj[tail].append(head)
 
     def remove_edge(self, tail, head):
-        self.edges.remove((tail, head))
+        try:
+            self.edges.remove((tail, head))
+        except KeyError:
+            raise ValueError(
+                "graph does not contain edge: (%s, %s)" % (tail, head))
         self._adj[tail].remove(head)
 
     def remove_vertex(self, vertex):
-        self.vertices.remove(vertex)
+        try:
+            self.vertices.remove(vertex)
+        except KeyError:
+            raise ValueError("graph does not contain vertex: %s" % vertex)
 
         # delete _adjacencies
         del self._adj[vertex]
-- 
2.4.3

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to