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;
}