File bsc#1181744-0001-Low-fenced-Remove-relayed-stonith-operation.-Fix-CLB-1.1.patch of Package pacemaker.19778

From cae1b8d6357f6516358c77982524d4d96bf5cd58 Mon Sep 17 00:00:00 2001
From: Klaus Wenninger <klaus.wenninger@aon.at>
Date: Fri, 8 May 2020 18:22:02 +0200
Subject: [PATCH] Low: fenced: Remove relayed stonith operation.(Fix:CLBZ#5401)

---
 fencing/commands.c             | 60 ++++++++++++++++++++++++++++++++--
 fencing/remote.c               | 22 ++++++++++++-
 include/crm/fencing/internal.h |  1 +
 3 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/fencing/commands.c b/fencing/commands.c
index 8dfb1d6b4..1040af759 100644
--- a/fencing/commands.c
+++ b/fencing/commands.c
@@ -2509,6 +2509,55 @@ stonith_send_reply(xmlNode * reply, int call_options, const char *remote_peer,
     }
 }
 
+static void
+remove_relay_op(xmlNode * request)
+{
+    xmlNode *dev = get_xpath_object("//@" F_STONITH_ACTION, request, LOG_TRACE);
+    const char *relay_op_id = NULL;
+    const char *op_id = NULL;
+    const char *client_name = NULL;
+    const char *target = NULL;
+    remote_fencing_op_t *relay_op = NULL;
+
+    if (dev) {
+        target = crm_element_value(dev, F_STONITH_TARGET);
+    }
+
+    relay_op_id = crm_element_value(request, F_STONITH_REMOTE_OP_ID_RELAY);
+    op_id = crm_element_value(request, F_STONITH_REMOTE_OP_ID);
+    client_name = crm_element_value(request, F_STONITH_CLIENTNAME);
+
+    /* Delete RELAY operation. */
+    if (relay_op_id && target && safe_str_eq(target, stonith_our_uname)) {
+        relay_op = g_hash_table_lookup(stonith_remote_op_list, relay_op_id);
+
+        if (relay_op) {
+            GHashTableIter iter;
+            remote_fencing_op_t *list_op = NULL;
+            g_hash_table_iter_init(&iter, stonith_remote_op_list);
+
+            /* If the operation to be deleted is registered as a duplicate, delete the registration. */
+            while (g_hash_table_iter_next(&iter, NULL, (void **)&list_op)) {
+                GListPtr dup_iter = NULL;
+                if (list_op != relay_op) {
+                    for (dup_iter = list_op->duplicates; dup_iter != NULL; dup_iter = dup_iter->next) {
+                        remote_fencing_op_t *other = dup_iter->data;
+                        if (other == relay_op) {
+                            other->duplicates = g_list_remove(other->duplicates, relay_op);
+                            break;
+                        }
+                    }
+                }
+            }
+            crm_info("Delete the relay op : %s - %s of %s for %s.(replaced by op : %s - %s of %s for %s)",
+                  relay_op->id, relay_op->action, relay_op->target, relay_op->client_name,
+                  op_id, relay_op->action, target, client_name);
+
+            g_hash_table_remove(stonith_remote_op_list, relay_op_id);
+        }
+    }
+}
+
 static int
 handle_request(crm_client_t * client, uint32_t id, uint32_t flags, xmlNode * request,
                const char *remote_peer)
@@ -2556,6 +2605,10 @@ handle_request(crm_client_t * client, uint32_t id, uint32_t flags, xmlNode * req
         if (remote_peer) {
             create_remote_stonith_op(client_id, request, TRUE); /* Record it for the future notification */
         }
+
+        /* Delete the DC node RELAY operation. */
+        remove_relay_op(request);
+
         stonith_query(request, remote_peer, client_id, call_options);
         return 0;
 
@@ -2636,6 +2689,7 @@ handle_request(crm_client_t * client, uint32_t id, uint32_t flags, xmlNode * req
 
             if (alternate_host && client) {
                 const char *client_id = NULL;
+                remote_fencing_op_t *op = NULL;
 
                 crm_notice("Forwarding complex self fencing request to peer %s", alternate_host);
 
@@ -2645,11 +2699,13 @@ handle_request(crm_client_t * client, uint32_t id, uint32_t flags, xmlNode * req
                     client_id = crm_element_value(request, F_STONITH_CLIENTID);
                 }
 
-                /* Create a record of it, otherwise call_id will be 0 if we need to notify of failures */
-                create_remote_stonith_op(client_id, request, FALSE);
+                /* Create an operation for RELAY and send the ID in the RELAY message. */
+                /* When a QUERY response is received, delete the RELAY operation to avoid the existence of duplicate operations. */
+                op = create_remote_stonith_op(client_id, request, FALSE);
 
                 crm_xml_add(request, F_STONITH_OPERATION, STONITH_OP_RELAY);
                 crm_xml_add(request, F_STONITH_CLIENTID, client->id);
+                crm_xml_add(request, F_STONITH_REMOTE_OP_ID, op->id);
                 send_cluster_message(crm_get_peer(0, alternate_host), crm_msg_stonith_ng, request,
                                      FALSE);
                 rc = -EINPROGRESS;
diff --git a/fencing/remote.c b/fencing/remote.c
index 9658b65d4..184f01eed 100644
--- a/fencing/remote.c
+++ b/fencing/remote.c
@@ -977,6 +977,7 @@ create_remote_stonith_op(const char *client, xmlNode * request, gboolean peer)
     remote_fencing_op_t *op = NULL;
     xmlNode *dev = get_xpath_object("//@" F_STONITH_TARGET, request, LOG_TRACE);
     int call_options = 0;
+    const char *operation = NULL;
 
     init_stonith_remote_op_hash_table(&stonith_remote_op_list);
 
@@ -1027,7 +1028,15 @@ create_remote_stonith_op(const char *client, xmlNode * request, gboolean peer)
         op->client_id = strdup(client);
     }
 
-    op->client_name = crm_element_value_copy(request, F_STONITH_CLIENTNAME);
+    /* For a RELAY operation, set fenced on the client. */
+    operation = crm_element_value(request, F_STONITH_OPERATION);
+
+    if (crm_str_eq(operation, STONITH_OP_RELAY, TRUE)) {
+        op->client_name = crm_strdup_printf("%s.%lu", crm_system_name,
+                                         (unsigned long) getpid());
+    } else {
+        op->client_name = crm_element_value_copy(request, F_STONITH_CLIENTNAME);
+    }
 
     op->target = crm_element_value_copy(dev, F_STONITH_TARGET);
     op->request = copy_xml(request);    /* TODO: Figure out how to avoid this */
@@ -1077,6 +1086,8 @@ initiate_remote_stonith_op(crm_client_t * client, xmlNode * request, gboolean ma
     xmlNode *query = NULL;
     const char *client_id = NULL;
     remote_fencing_op_t *op = NULL;
+    const char *relay_op_id = NULL;
+    const char *operation = NULL;
 
     if (client) {
         client_id = client->id;
@@ -1128,6 +1139,15 @@ initiate_remote_stonith_op(crm_client_t * client, xmlNode * request, gboolean ma
     crm_xml_add(query, F_STONITH_CLIENTNAME, op->client_name);
     crm_xml_add_int(query, F_STONITH_TIMEOUT, op->base_timeout);
 
+    /* In case of RELAY operation, RELAY information is added to the query to delete the original operation of RELAY. */
+    operation = crm_element_value(request, F_STONITH_OPERATION);
+    if (crm_str_eq(operation, STONITH_OP_RELAY, TRUE)) {
+        relay_op_id = crm_element_value(request, F_STONITH_REMOTE_OP_ID);
+        if (relay_op_id) {
+            crm_xml_add(query, F_STONITH_REMOTE_OP_ID_RELAY, relay_op_id);
+        }
+    }
+
     send_cluster_message(NULL, crm_msg_stonith_ng, query, FALSE);
     free_xml(query);
 
diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h
index 63fcb09e7..5220001a2 100644
--- a/include/crm/fencing/internal.h
+++ b/include/crm/fencing/internal.h
@@ -66,6 +66,7 @@ long long stonith__device_parameter_flags(xmlNode *metadata);
 #  define F_STONITH_OPERATION     "st_op"
 #  define F_STONITH_TARGET        "st_target"
 #  define F_STONITH_REMOTE_OP_ID  "st_remote_op"
+#  define F_STONITH_REMOTE_OP_ID_RELAY  "st_remote_op_relay"
 #  define F_STONITH_RC            "st_rc"
 /*! Timeout period per a device execution */
 #  define F_STONITH_TIMEOUT       "st_timeout"
-- 
2.26.2

openSUSE Build Service is sponsored by