Blame SOURCES/shutdown-lock-08.patch

af918f
From 3f19b4333897a0392e8a5efc4742732b8e6f0efb Mon Sep 17 00:00:00 2001
af918f
From: Ken Gaillot <kgaillot@redhat.com>
af918f
Date: Tue, 14 Jan 2020 12:53:39 -0600
af918f
Subject: [PATCH 08/10] Low: controller: allow CRM_OP_LRM_DELETE to clear CIB
af918f
 only
af918f
af918f
Normally, CRM_OP_LRM_DELETE is relayed to the affected node's controller, which
af918f
clears the resource from the executor and CIB as well the its own bookkeeping.
af918f
af918f
Now, we want to be able to use it to clear shutdown locks for nodes that are
af918f
down. Let it take a new "mode" attribute, and if it is "cib", clear the
af918f
resource from the CIB locally without relaying the operation or doing anything
af918f
else.
af918f
---
af918f
 crmd/lrm.c             |  4 ++-
af918f
 crmd/messages.c        | 97 ++++++++++++++++++++++++++++++++++++++++++++++++--
af918f
 crmd/te_actions.c      |  7 ++++
af918f
 include/crm_internal.h |  2 ++
af918f
 4 files changed, 106 insertions(+), 4 deletions(-)
af918f
af918f
diff --git a/crmd/lrm.c b/crmd/lrm.c
af918f
index 9156ab8..bdf7b94 100644
af918f
--- a/crmd/lrm.c
af918f
+++ b/crmd/lrm.c
af918f
@@ -1764,7 +1764,9 @@ do_lrm_invoke(long long action,
af918f
     crm_trace("LRM %s command from %s", crm_op, from_sys);
af918f
 
af918f
     if (safe_str_eq(crm_op, CRM_OP_LRM_DELETE)) {
af918f
-        crm_rsc_delete = TRUE; // Only crm_resource uses this op
af918f
+        if (safe_str_neq(from_sys, CRM_SYSTEM_TENGINE)) {
af918f
+            crm_rsc_delete = TRUE; // from crm_resource
af918f
+        }
af918f
         operation = CRMD_ACTION_DELETE;
af918f
 
af918f
     } else if (safe_str_eq(crm_op, CRM_OP_LRM_FAIL)) {
af918f
diff --git a/crmd/messages.c b/crmd/messages.c
af918f
index f1599ab..8839d65 100644
af918f
--- a/crmd/messages.c
af918f
+++ b/crmd/messages.c
af918f
@@ -430,6 +430,14 @@ relay_message(xmlNode * msg, gboolean originated_locally)
af918f
 
af918f
     } else if (safe_str_eq(fsa_our_uname, host_to)) {
af918f
         is_local = 1;
af918f
+    } else if (is_for_crm && safe_str_eq(task, CRM_OP_LRM_DELETE)) {
af918f
+        xmlNode *msg_data = get_message_xml(msg, F_CRM_DATA);
af918f
+        const char *mode = crm_element_value(msg_data, PCMK__XA_MODE);
af918f
+
af918f
+        if (safe_str_eq(mode, XML_TAG_CIB)) {
af918f
+            // Local delete of an offline node's resource history
af918f
+            is_local = 1;
af918f
+        }
af918f
     }
af918f
 
af918f
     if (is_for_dc || is_for_dcib || is_for_te) {
af918f
@@ -669,6 +677,86 @@ handle_failcount_op(xmlNode * stored_msg)
af918f
     return I_NULL;
af918f
 }
af918f
 
af918f
+static enum crmd_fsa_input
af918f
+handle_lrm_delete(xmlNode *stored_msg)
af918f
+{
af918f
+    const char *mode = NULL;
af918f
+    xmlNode *msg_data = get_message_xml(stored_msg, F_CRM_DATA);
af918f
+
af918f
+    CRM_CHECK(msg_data != NULL, return I_NULL);
af918f
+
af918f
+    /* CRM_OP_LRM_DELETE has two distinct modes. The default behavior is to
af918f
+     * relay the operation to the affected node, which will unregister the
af918f
+     * resource from the local executor, clear the resource's history from the
af918f
+     * CIB, and do some bookkeeping in the controller.
af918f
+     *
af918f
+     * However, if the affected node is offline, the client will specify
af918f
+     * mode="cib" which means the controller receiving the operation should
af918f
+     * clear the resource's history from the CIB and nothing else. This is used
af918f
+     * to clear shutdown locks.
af918f
+     */
af918f
+    mode = crm_element_value(msg_data, PCMK__XA_MODE);
af918f
+    if ((mode == NULL) || strcmp(mode, XML_TAG_CIB)) {
af918f
+        // Relay to affected node
af918f
+        crm_xml_add(stored_msg, F_CRM_SYS_TO, CRM_SYSTEM_LRMD);
af918f
+        return I_ROUTER;
af918f
+
af918f
+    } else {
af918f
+        // Delete CIB history locally (compare with do_lrm_delete())
af918f
+        const char *from_sys = NULL;
af918f
+        const char *user_name = NULL;
af918f
+        const char *rsc_id = NULL;
af918f
+        const char *node = NULL;
af918f
+        xmlNode *rsc_xml = NULL;
af918f
+        int rc = pcmk_rc_ok;
af918f
+
af918f
+        rsc_xml = first_named_child(msg_data, XML_CIB_TAG_RESOURCE);
af918f
+        CRM_CHECK(rsc_xml != NULL, return I_NULL);
af918f
+
af918f
+        rsc_id = ID(rsc_xml);
af918f
+        from_sys = crm_element_value(stored_msg, F_CRM_SYS_FROM);
af918f
+        node = crm_element_value(msg_data, XML_LRM_ATTR_TARGET);
af918f
+#if ENABLE_ACL
af918f
+        user_name = crm_acl_get_set_user(stored_msg, F_CRM_USER, NULL);
af918f
+#endif
af918f
+        crm_debug("Handling " CRM_OP_LRM_DELETE " for %s on %s locally%s%s "
af918f
+                  "(clearing CIB resource history only)", rsc_id, node,
af918f
+                  (user_name? " for user " : ""), (user_name? user_name : ""));
af918f
+#if ENABLE_ACL
af918f
+        rc = controld_delete_resource_history(rsc_id, node, user_name,
af918f
+                                              cib_dryrun|cib_sync_call);
af918f
+#endif
af918f
+        if (rc == pcmk_rc_ok) {
af918f
+            rc = controld_delete_resource_history(rsc_id, node, user_name,
af918f
+                                                  crmd_cib_smart_opt());
af918f
+        }
af918f
+
af918f
+        // Notify client if not from graph (compare with notify_deleted())
af918f
+        if (from_sys && strcmp(from_sys, CRM_SYSTEM_TENGINE)) {
af918f
+            lrmd_event_data_t *op = NULL;
af918f
+            const char *from_host = crm_element_value(stored_msg,
af918f
+                                                      F_CRM_HOST_FROM);
af918f
+            const char *transition = crm_element_value(msg_data,
af918f
+                                                       XML_ATTR_TRANSITION_KEY);
af918f
+
af918f
+            crm_info("Notifying %s on %s that %s was%s deleted",
af918f
+                     from_sys, (from_host? from_host : "local node"), rsc_id,
af918f
+                     ((rc == pcmk_rc_ok)? "" : " not"));
af918f
+            op = lrmd_new_event(rsc_id, CRMD_ACTION_DELETE, 0);
af918f
+            op->type = lrmd_event_exec_complete;
af918f
+            op->user_data = strdup(transition? transition : FAKE_TE_ID);
af918f
+            op->params = crm_str_table_new();
af918f
+            g_hash_table_insert(op->params, strdup(XML_ATTR_CRM_VERSION),
af918f
+                                strdup(CRM_FEATURE_SET));
af918f
+            controld_rc2event(op, rc);
af918f
+            controld_ack_event_directly(from_host, from_sys, NULL, op, rsc_id);
af918f
+            lrmd_free_event(op);
af918f
+            controld_trigger_delete_refresh(from_sys, rsc_id);
af918f
+        }
af918f
+        return I_NULL;
af918f
+    }
af918f
+}
af918f
+
af918f
 /*!
af918f
  * \brief Handle a CRM_OP_REMOTE_STATE message by updating remote peer cache
af918f
  *
af918f
@@ -902,9 +990,12 @@ handle_request(xmlNode * stored_msg, enum crmd_fsa_cause cause)
af918f
         crm_debug("Raising I_JOIN_RESULT: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID));
af918f
         return I_JOIN_RESULT;
af918f
 
af918f
-    } else if (strcmp(op, CRM_OP_LRM_DELETE) == 0
af918f
-               || strcmp(op, CRM_OP_LRM_FAIL) == 0
af918f
-               || strcmp(op, CRM_OP_LRM_REFRESH) == 0 || strcmp(op, CRM_OP_REPROBE) == 0) {
af918f
+    } else if (strcmp(op, CRM_OP_LRM_DELETE) == 0) {
af918f
+        return handle_lrm_delete(stored_msg);
af918f
+
af918f
+    } else if ((strcmp(op, CRM_OP_LRM_FAIL) == 0)
af918f
+               || (strcmp(op, CRM_OP_LRM_REFRESH) == 0)
af918f
+               || (strcmp(op, CRM_OP_REPROBE) == 0)) {
af918f
 
af918f
         crm_xml_add(stored_msg, F_CRM_SYS_TO, CRM_SYSTEM_LRMD);
af918f
         return I_ROUTER;
af918f
diff --git a/crmd/te_actions.c b/crmd/te_actions.c
af918f
index 19bb199..ec92df2 100644
af918f
--- a/crmd/te_actions.c
af918f
+++ b/crmd/te_actions.c
af918f
@@ -239,6 +239,13 @@ te_crm_command(crm_graph_t * graph, crm_action_t * action)
af918f
 
af918f
     if (!router_node) {
af918f
         router_node = on_node;
af918f
+        if (safe_str_eq(task, CRM_OP_LRM_DELETE)) {
af918f
+            const char *mode = crm_element_value(action->xml, PCMK__XA_MODE);
af918f
+
af918f
+            if (safe_str_eq(mode, XML_TAG_CIB)) {
af918f
+                router_node = fsa_our_uname;
af918f
+            }
af918f
+        }
af918f
     }
af918f
 
af918f
     CRM_CHECK(on_node != NULL && strlen(on_node) != 0,
af918f
diff --git a/include/crm_internal.h b/include/crm_internal.h
af918f
index 0adeb7b..7656bf5 100644
af918f
--- a/include/crm_internal.h
af918f
+++ b/include/crm_internal.h
af918f
@@ -260,6 +260,8 @@ long crm_read_pidfile(const char *filename);
af918f
 #  define ATTRD_OP_SYNC_RESPONSE "sync-response"
af918f
 #  define ATTRD_OP_CLEAR_FAILURE "clear-failure"
af918f
 
af918f
+#  define PCMK__XA_MODE             "mode"
af918f
+
af918f
 #  define PCMK_ENV_PHYSICAL_HOST "physical_host"
af918f
 
af918f
 
af918f
-- 
af918f
1.8.3.1
af918f