File bug-1003565_pacemaker-crmd-record-pending-op.patch of Package pacemaker.3577

commit 5519c94ec6eb6efa249506c9c1cb310474687f19
Author: Gao,Yan <ygao@suse.com>
Date:   Thu Oct 6 15:40:41 2016 +0200

    Fix: crmd: cl#5185 - Record pending operations in the CIB before they are performed
    
    Although we had the assurance of CPG, there was the race condition that
    the peer received the lrm_invoke request from the DC, got the operation
    performed, returned and updated into the CIB very fast, even before
    the pending operation was injected into the CIB. The late pending
    operation would override the real result of the operation and get
    stalled in the CIB, which would basically tell the wrong state of the
    resource.
    
    The idea of this fix is to record the pending operation from the node
    where the operation will be performed rather than from the DC, and right
    before it's performed, to avoid the race condition.

diff --git a/crmd/lrm.c b/crmd/lrm.c
index 144233d..e12df4b 100644
--- a/crmd/lrm.c
+++ b/crmd/lrm.c
@@ -2017,6 +2017,44 @@ stop_recurring_actions(gpointer key, gpointer value, gpointer user_data)
 }
 
 static void
+record_pending_op(const char *node_name, lrmd_rsc_info_t *rsc, lrmd_event_data_t *op)
+{
+    CRM_CHECK(node_name != NULL, return);
+    CRM_CHECK(rsc != NULL, return);
+    CRM_CHECK(op != NULL, return);
+
+    if (op->op_type == NULL
+        || safe_str_eq(op->op_type, CRMD_ACTION_CANCEL)
+        || safe_str_eq(op->op_type, CRMD_ACTION_DELETE)) {
+        return;
+    }
+
+    if (op->params == NULL) {
+        return;
+
+    } else {
+        const char *record_pending = crm_meta_value(op->params, XML_OP_ATTR_PENDING);
+
+        if (record_pending == NULL || crm_is_true(record_pending) == FALSE) {
+            return;
+         }
+    }
+
+    op->call_id = -1;
+    op->op_status = PCMK_LRM_OP_PENDING;
+    op->rc = PCMK_OCF_UNKNOWN;
+
+    op->t_run = time(NULL);
+    op->t_rcchange = op->t_run;
+
+    /* write a "pending" entry to the CIB, inhibit notification */
+    crm_debug("Recording pending op %s_%s_%d on %s in the CIB",
+              op->rsc_id, op->op_type, op->interval, node_name);
+
+    do_update_resource(node_name, rsc, op);
+}
+
+static void
 do_lrm_rsc_op(lrm_state_t * lrm_state, lrmd_rsc_info_t * rsc, const char *operation, xmlNode * msg,
               xmlNode * request)
 {
@@ -2103,6 +2141,8 @@ do_lrm_rsc_op(lrm_state_t * lrm_state, lrmd_rsc_info_t * rsc, const char *operat
         return;
     }
 
+    record_pending_op(lrm_state->node_name, rsc, op);
+
     op_id = generate_op_key(rsc->id, op->op_type, op->interval);
 
     if (op->interval > 0) {
diff --git a/crmd/te_actions.c b/crmd/te_actions.c
index 99ecd5a..c971273 100644
--- a/crmd/te_actions.c
+++ b/crmd/te_actions.c
@@ -491,15 +491,6 @@ te_rsc_command(crm_graph_t * graph, crm_action_t * action)
         te_start_action_timer(graph, action);
     }
 
-    value = crm_meta_value(action->params, XML_OP_ATTR_PENDING);
-    if (crm_is_true(value)
-        && safe_str_neq(task, CRMD_ACTION_CANCEL)
-        && safe_str_neq(task, CRMD_ACTION_DELETE)) {
-        /* write a "pending" entry to the CIB, inhibit notification */
-        crm_debug("Recording pending op %s in the CIB", task_uuid);
-        cib_action_update(action, PCMK_LRM_OP_PENDING, PCMK_OCF_UNKNOWN);
-    }
-
     return TRUE;
 }
 
openSUSE Build Service is sponsored by