On 10/30/2015 03:38 PM, Petr Vobornik wrote:
On 10/30/2015 03:26 PM, Martin Babinsky wrote:
patch for https://fedorahosted.org/freeipa/ticket/5309

The ticket itself is about connectivity checks in topology suffixes, but
there is a code (install/tools/ipa-replica-manage starting at line 788
after applying my patch) which monitors whether the segments pointing
to/from the deleted host are already deleted.

These checks are currently hardcoded for 'realm' prefix, should we
generalize them as well or is it a part of other effort?


Could be separate patch but yes.
Ok I have included it in the attached patch so that both of these operations are performed for all suffixes.

--
Martin^3 Babinsky
From 356fbe7c3f542938b87f50c864c28de8b65a9b36 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 30 Oct 2015 13:59:03 +0100
Subject: [PATCH] check for disconnected topology and deleted agreements for
 all suffices

The code in ipa-replica-manage which checks for disconnected topology and
deleted agreements during node removal was generalized so that it now performs
these checks for all suffixes to which the node belongs.

https://fedorahosted.org/freeipa/ticket/5309
---
 install/tools/ipa-replica-manage | 87 ++++++++++++++++++++++++++++++----------
 1 file changed, 66 insertions(+), 21 deletions(-)

diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index 1350590b625e5dcab36abbcef75fe5eafc5f7123..f754d699e89785666dd35386a2fbb1a6017f5d1f 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -569,7 +569,7 @@ def check_last_link(delrepl, realm, dirman_passwd, force):
     else:
         return None
 
-def check_last_link_managed(api, masters, hostname, force):
+def check_last_link_managed(api, hostname, masters, suffix_name, force):
     """
     Check if 'hostname' is safe to delete.
 
@@ -577,13 +577,31 @@ def check_last_link_managed(api, masters, hostname, force):
               (current_errors, new_errors)
     """
 
-    segments = api.Command.topologysegment_find(u'realm', sizelimit=0).get('result')
-    graph = create_topology_graph(masters, segments)
+    suffix = api.Command.topologysuffix_show(suffix_name)['result']
+    suffix_members = []
+    for m in masters:
+        if suffix['iparepltopoconfroot'][0] in m['iparepltopomanagedsuffix']:
+            suffix_members.append(m)
+
+    member_cns = {member['cn'][0] for member in suffix_members}
+
+    if hostname not in member_cns:
+        print(
+            "'{}' is not a part of topology suffix '{}'".format(
+                hostname, suffix_name
+            )
+        )
+        print("Not checking connectivity")
+        return [], []
+
+    segments = api.Command.topologysegment_find(suffix_name, sizelimit=0).get('result')
+    graph = create_topology_graph(suffix_members, segments)
 
     # check topology before removal
     orig_errors = get_topology_connection_errors(graph)
     if orig_errors:
-        print("Current topology is disconnected:")
+        print("Current topology in suffix '{}' is disconnected:".format(
+            suffix_name))
         print("Changes are not replicated to all servers and data are probably inconsistent.")
         print("You need to add segments to reconnect the topology.")
         print_connect_errors(orig_errors)
@@ -596,7 +614,8 @@ def check_last_link_managed(api, masters, hostname, force):
 
     new_errors = get_topology_connection_errors(graph)
     if new_errors:
-        print("WARNING: Topology after removal of %s will be disconnected." % hostname)
+        print("WARNING: Removal of '{}' will lead to disconnected topology "
+              "in suffix '{}'".format(hostname, suffix_name))
         print("Changes will not be replicated to all servers and data will become inconsistent.")
         print("You need to add segments to prevent disconnection of the topology.")
         print("Errors in topology after removal:")
@@ -724,8 +743,22 @@ def del_master_managed(realm, hostname, options):
     # 2. Get all masters
     masters = api.Command.server_find('', sizelimit=0)['result']
 
-    # 3. Check topology
-    topo_errors = check_last_link_managed(api, masters, hostname, options.force)
+    # 3. Check topology connectivity in all suffices
+    suffices = api.Command.topologysuffix_find('', sizelimit=0)['result']
+    suffix_names = [s['cn'][0] for s in suffices]
+    # initialize the error tuple here and extend it by errors found in each
+    # suffix
+    topo_errors = ([], [])
+
+    for suffix_name in suffix_names:
+        print("Checking connectivity in topology suffix '{}'".format(
+            suffix_name))
+
+        suffix_errors = check_last_link_managed(
+            api, hostname, masters, suffix_name, options.force)
+
+        topo_errors[0].extend(suffix_errors[0])
+        topo_errors[1].extend(suffix_errors[1])
 
     # 4. Check that we are not leaving the installation without CA and/or DNS
     #    And pick new CA master.
@@ -750,17 +783,30 @@ 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
+    for suffix_name in suffix_names:
+        check_deleted_segments(hostname_u, suffix_name, m_cns, topo_errors,
+                               options.host)
+
+    # Clean RUV is handled by the topolgy plugin
+
+    # 8. And clean up the removed replica DNS entries if any.
+    cleanup_server_dns_entries(realm, hostname, thisrepl.suffix, options)
+
+
+def check_deleted_segments(hostname, suffix_name, master_cns, topo_errors,
+                           starting_host):
+    print("Checking for deleted segments in suffix '{}'".format(suffix_name))
+    i = 0
     while True:
         left = api.Command.topologysegment_find(
-            u'realm', iparepltoposegmentleftnode=hostname_u, sizelimit=0)['result']
+            suffix_name, iparepltoposegmentleftnode=hostname, sizelimit=0)['result']
         right = api.Command.topologysegment_find(
-            u'realm', iparepltoposegmentrightnode=hostname_u, sizelimit=0)['result']
+            suffix_name, iparepltoposegmentrightnode=hostname, 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:
+        if hostname not in master_cns:
             print("Skipping replication agreement deletion check")
             break
 
@@ -774,12 +820,15 @@ def del_master_managed(realm, hostname, options):
         # 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]
+            # 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 starting_host in e[2]]
+            can_contact_me = set(master_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")
@@ -797,10 +846,6 @@ def del_master_managed(realm, hostname, options):
             break
         i += 1
 
-    # Clean RUV is handled by the topolgy plugin
-
-    # 8. And clean up the removed replica DNS entries if any.
-    cleanup_server_dns_entries(realm, hostname, thisrepl.suffix, options)
 
 def del_master_direct(realm, hostname, options):
     """
-- 
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