pacemaker  2.1.4-dc6eb4362
Scalable High-Availability cluster resource manager
pcmk_sched_actions.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2022 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU General Public License version 2
7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <stdio.h>
13 #include <sys/param.h>
14 #include <glib.h>
15 
16 #include <crm/lrmd_internal.h>
17 #include <pacemaker-internal.h>
18 #include "libpacemaker_private.h"
19 
20 extern gboolean DeleteRsc(pe_resource_t *rsc, pe_node_t *node,
21  gboolean optional, pe_working_set_t *data_set);
22 
33 static enum pe_action_flags
34 action_flags_for_ordering(pe_action_t *action, pe_node_t *node)
35 {
36  bool runnable = false;
38 
39  // For non-resource actions, return the action flags
40  if (action->rsc == NULL) {
41  return action->flags;
42  }
43 
44  /* For non-clone resources, or a clone action not assigned to a node,
45  * return the flags as determined by the resource method without a node
46  * specified.
47  */
48  flags = action->rsc->cmds->action_flags(action, NULL);
49  if ((node == NULL) || !pe_rsc_is_clone(action->rsc)) {
50  return flags;
51  }
52 
53  /* Otherwise (i.e., for clone resource actions on a specific node), first
54  * remember whether the non-node-specific action is runnable.
55  */
57 
58  // Then recheck the resource method with the node
59  flags = action->rsc->cmds->action_flags(action, node);
60 
61  /* For clones in ordering constraints, the node-specific "runnable" doesn't
62  * matter, just the non-node-specific setting (i.e., is the action runnable
63  * anywhere).
64  *
65  * This applies only to runnable, and only for ordering constraints. This
66  * function shouldn't be used for other types of constraints without
67  * changes. Not very satisfying, but it's logical and appears to work well.
68  */
69  if (runnable && !pcmk_is_set(flags, pe_action_runnable)) {
72  }
73  return flags;
74 }
75 
94 static char *
95 action_uuid_for_ordering(const char *first_uuid, pe_resource_t *first_rsc)
96 {
97  guint interval_ms = 0;
98  char *uuid = NULL;
99  char *rid = NULL;
100  char *first_task_str = NULL;
101  enum action_tasks first_task = no_action;
102  enum action_tasks remapped_task = no_action;
103 
104  // Only non-notify actions for collective resources need remapping
105  if ((strstr(first_uuid, "notify") != NULL)
106  || (first_rsc->variant < pe_group)) {
107  goto done;
108  }
109 
110  // Only non-recurring actions need remapping
111  CRM_ASSERT(parse_op_key(first_uuid, &rid, &first_task_str, &interval_ms));
112  if (interval_ms > 0) {
113  goto done;
114  }
115 
116  first_task = text2task(first_task_str);
117  switch (first_task) {
118  case stop_rsc:
119  case start_rsc:
120  case action_notify:
121  case action_promote:
122  case action_demote:
123  remapped_task = first_task + 1;
124  break;
125  case stopped_rsc:
126  case started_rsc:
127  case action_notified:
128  case action_promoted:
129  case action_demoted:
130  remapped_task = first_task;
131  break;
132  case monitor_rsc:
133  case shutdown_crm:
134  case stonith_node:
135  break;
136  default:
137  crm_err("Unknown action '%s' in ordering", first_task_str);
138  break;
139  }
140 
141  if (remapped_task != no_action) {
142  /* If a (clone) resource has notifications enabled, we want to order
143  * relative to when all notifications have been sent for the remapped
144  * task. Only outermost resources or those in bundles have
145  * notifications.
146  */
147  if (pcmk_is_set(first_rsc->flags, pe_rsc_notify)
148  && ((first_rsc->parent == NULL)
149  || (pe_rsc_is_clone(first_rsc)
150  && (first_rsc->parent->variant == pe_container)))) {
151  uuid = pcmk__notify_key(rid, "confirmed-post",
152  task2text(remapped_task));
153  } else {
154  uuid = pcmk__op_key(rid, task2text(remapped_task), 0);
155  }
156  pe_rsc_trace(first_rsc,
157  "Remapped action UUID %s to %s for ordering purposes",
158  first_uuid, uuid);
159  }
160 
161 done:
162  if (uuid == NULL) {
163  uuid = strdup(first_uuid);
164  CRM_ASSERT(uuid != NULL);
165  }
166  free(first_task_str);
167  free(rid);
168  return uuid;
169 }
170 
187 static pe_action_t *
188 action_for_ordering(pe_action_t *action)
189 {
191  pe_resource_t *rsc = action->rsc;
192 
193  if ((rsc != NULL) && (rsc->variant >= pe_group) && (action->uuid != NULL)) {
194  char *uuid = action_uuid_for_ordering(action->uuid, rsc);
195 
196  result = find_first_action(rsc->actions, uuid, NULL, NULL);
197  if (result == NULL) {
198  crm_warn("Not remapping %s to %s because %s does not have "
199  "remapped action", action->uuid, uuid, rsc->id);
200  result = action;
201  }
202  free(uuid);
203  }
204  return result;
205 }
206 
220 static enum pe_graph_flags
221 update_action_for_ordering_flags(pe_action_t *first, pe_action_t *then,
222  enum pe_action_flags first_flags,
223  enum pe_action_flags then_flags,
224  pe_action_wrapper_t *order,
226 {
227  enum pe_graph_flags changed = pe_graph_none;
228 
229  /* The node will only be used for clones. If interleaved, node will be NULL,
230  * otherwise the ordering scope will be limited to the node. Normally, the
231  * whole 'then' clone should restart if 'first' is restarted, so then->node
232  * is needed.
233  */
234  pe_node_t *node = then->node;
235 
237  /* For unfencing, only instances of 'then' on the same node as 'first'
238  * (the unfencing operation) should restart, so reset node to
239  * first->node, at which point this case is handled like a normal
240  * pe_order_implies_then.
241  */
244  node = first->node;
245  pe_rsc_trace(then->rsc,
246  "%s then %s: mapped pe_order_implies_then_on_node to "
247  "pe_order_implies_then on %s",
248  first->uuid, then->uuid, node->details->uname);
249  }
250 
251  if (pcmk_is_set(order->type, pe_order_implies_then)) {
252  if (then->rsc != NULL) {
253  changed |= then->rsc->cmds->update_actions(first, then, node,
254  first_flags & pe_action_optional,
257  data_set);
258  } else if (!pcmk_is_set(first_flags, pe_action_optional)
259  && pcmk_is_set(then->flags, pe_action_optional)) {
262  }
263  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_implies_then",
264  first->uuid, then->uuid,
265  (changed? "changed" : "unchanged"));
266  }
267 
268  if (pcmk_is_set(order->type, pe_order_restart) && (then->rsc != NULL)) {
270 
271  changed |= then->rsc->cmds->update_actions(first, then, node,
272  first_flags, restart,
274  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_restart",
275  first->uuid, then->uuid,
276  (changed? "changed" : "unchanged"));
277  }
278 
279  if (pcmk_is_set(order->type, pe_order_implies_first)) {
280  if (first->rsc != NULL) {
281  changed |= first->rsc->cmds->update_actions(first, then, node,
282  first_flags,
285  data_set);
286  } else if (!pcmk_is_set(first_flags, pe_action_optional)
287  && pcmk_is_set(first->flags, pe_action_runnable)) {
290  }
291  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_implies_first",
292  first->uuid, then->uuid,
293  (changed? "changed" : "unchanged"));
294  }
295 
297  if (then->rsc != NULL) {
298  changed |= then->rsc->cmds->update_actions(first, then, node,
299  first_flags & pe_action_optional,
302  data_set);
303  }
304  pe_rsc_trace(then->rsc,
305  "%s then %s: %s after pe_order_promoted_implies_first",
306  first->uuid, then->uuid,
307  (changed? "changed" : "unchanged"));
308  }
309 
310  if (pcmk_is_set(order->type, pe_order_one_or_more)) {
311  if (then->rsc != NULL) {
312  changed |= then->rsc->cmds->update_actions(first, then, node,
313  first_flags,
316  data_set);
317 
318  } else if (pcmk_is_set(first_flags, pe_action_runnable)) {
319  // We have another runnable instance of "first"
320  then->runnable_before++;
321 
322  /* Mark "then" as runnable if it requires a certain number of
323  * "before" instances to be runnable, and they now are.
324  */
325  if ((then->runnable_before >= then->required_runnable_before)
326  && !pcmk_is_set(then->flags, pe_action_runnable)) {
327 
330  }
331  }
332  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_one_or_more",
333  first->uuid, then->uuid,
334  (changed? "changed" : "unchanged"));
335  }
336 
337  if (pcmk_is_set(order->type, pe_order_probe) && (then->rsc != NULL)) {
338  if (!pcmk_is_set(first_flags, pe_action_runnable)
339  && (first->rsc->running_on != NULL)) {
340 
341  pe_rsc_trace(then->rsc,
342  "%s then %s: ignoring because first is stopping",
343  first->uuid, then->uuid);
344  order->type = pe_order_none;
345  } else {
346  changed |= then->rsc->cmds->update_actions(first, then, node,
347  first_flags,
350  data_set);
351  }
352  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_probe",
353  first->uuid, then->uuid,
354  (changed? "changed" : "unchanged"));
355  }
356 
357  if (pcmk_is_set(order->type, pe_order_runnable_left)) {
358  if (then->rsc != NULL) {
359  changed |= then->rsc->cmds->update_actions(first, then, node,
360  first_flags,
363  data_set);
364 
365  } else if (!pcmk_is_set(first_flags, pe_action_runnable)
366  && pcmk_is_set(then->flags, pe_action_runnable)) {
367 
370  }
371  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_runnable_left",
372  first->uuid, then->uuid,
373  (changed? "changed" : "unchanged"));
374  }
375 
377  if (then->rsc != NULL) {
378  changed |= then->rsc->cmds->update_actions(first, then, node,
379  first_flags, pe_action_optional,
381  }
382  pe_rsc_trace(then->rsc, "%s then %s: %s after "
383  "pe_order_implies_first_migratable",
384  first->uuid, then->uuid,
385  (changed? "changed" : "unchanged"));
386  }
387 
388  if (pcmk_is_set(order->type, pe_order_pseudo_left)) {
389  if (then->rsc != NULL) {
390  changed |= then->rsc->cmds->update_actions(first, then, node,
391  first_flags,
394  data_set);
395  }
396  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_pseudo_left",
397  first->uuid, then->uuid,
398  (changed? "changed" : "unchanged"));
399  }
400 
401  if (pcmk_is_set(order->type, pe_order_optional)) {
402  if (then->rsc != NULL) {
403  changed |= then->rsc->cmds->update_actions(first, then, node,
404  first_flags,
407  data_set);
408  }
409  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_optional",
410  first->uuid, then->uuid,
411  (changed? "changed" : "unchanged"));
412  }
413 
414  if (pcmk_is_set(order->type, pe_order_asymmetrical)) {
415  if (then->rsc != NULL) {
416  changed |= then->rsc->cmds->update_actions(first, then, node,
417  first_flags,
420  data_set);
421  }
422  pe_rsc_trace(then->rsc, "%s then %s: %s after pe_order_asymmetrical",
423  first->uuid, then->uuid,
424  (changed? "changed" : "unchanged"));
425  }
426 
429  && !pcmk_is_set(first_flags, pe_action_optional)) {
430 
431  pe_rsc_trace(then->rsc, "%s will be in graph because %s is required",
432  then->uuid, first->uuid);
434  // Don't bother marking 'then' as changed just for this
435  }
436 
438  && !pcmk_is_set(then_flags, pe_action_optional)) {
439 
440  pe_rsc_trace(then->rsc, "%s will be in graph because %s is required",
441  first->uuid, then->uuid);
443  // Don't bother marking 'first' as changed just for this
444  }
445 
446  if (pcmk_any_flags_set(order->type, pe_order_implies_then
449  && (first->rsc != NULL)
450  && !pcmk_is_set(first->rsc->flags, pe_rsc_managed)
451  && pcmk_is_set(first->rsc->flags, pe_rsc_block)
453  && pcmk__str_eq(first->task, RSC_STOP, pcmk__str_casei)) {
454 
455  if (pcmk_is_set(then->flags, pe_action_runnable)) {
458  }
459  pe_rsc_trace(then->rsc, "%s then %s: %s after checking whether first "
460  "is blocked, unmanaged, unrunnable stop",
461  first->uuid, then->uuid,
462  (changed? "changed" : "unchanged"));
463  }
464 
465  return changed;
466 }
467 
468 // Convenience macros for logging action properties
469 
470 #define action_type_str(flags) \
471  (pcmk_is_set((flags), pe_action_pseudo)? "pseudo-action" : "action")
472 
473 #define action_optional_str(flags) \
474  (pcmk_is_set((flags), pe_action_optional)? "optional" : "required")
475 
476 #define action_runnable_str(flags) \
477  (pcmk_is_set((flags), pe_action_runnable)? "runnable" : "unrunnable")
478 
479 #define action_node_str(a) \
480  (((a)->node == NULL)? "no node" : (a)->node->details->uname)
481 
489 void
491 {
492  GList *lpc = NULL;
493  enum pe_graph_flags changed = pe_graph_none;
494  int last_flags = then->flags;
495 
496  pe_rsc_trace(then->rsc, "Updating %s %s (%s %s) on %s",
497  action_type_str(then->flags), then->uuid,
498  action_optional_str(then->flags),
500 
502  /* Initialize current known "runnable before" actions. As
503  * update_action_for_ordering_flags() is called for each of then's
504  * before actions, this number will increment as runnable 'first'
505  * actions are encountered.
506  */
507  then->runnable_before = 0;
508 
509  if (then->required_runnable_before == 0) {
510  /* @COMPAT This ordering constraint uses the deprecated
511  * "require-all=false" attribute. Treat it like "clone-min=1".
512  */
513  then->required_runnable_before = 1;
514  }
515 
516  /* The pe_order_one_or_more clause of update_action_for_ordering_flags()
517  * (called below) will reset runnable if appropriate.
518  */
520  }
521 
522  for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) {
523  pe_action_wrapper_t *other = (pe_action_wrapper_t *) lpc->data;
524  pe_action_t *first = other->action;
525 
526  pe_node_t *then_node = then->node;
527  pe_node_t *first_node = first->node;
528 
529  if ((first->rsc != NULL)
530  && (first->rsc->variant == pe_group)
531  && pcmk__str_eq(first->task, RSC_START, pcmk__str_casei)) {
532 
533  first_node = first->rsc->fns->location(first->rsc, NULL, FALSE);
534  if (first_node != NULL) {
535  pe_rsc_trace(first->rsc, "Found node %s for 'first' %s",
536  first_node->details->uname, first->uuid);
537  }
538  }
539 
540  if ((then->rsc != NULL)
541  && (then->rsc->variant == pe_group)
542  && pcmk__str_eq(then->task, RSC_START, pcmk__str_casei)) {
543 
544  then_node = then->rsc->fns->location(then->rsc, NULL, FALSE);
545  if (then_node != NULL) {
546  pe_rsc_trace(then->rsc, "Found node %s for 'then' %s",
547  then_node->details->uname, then->uuid);
548  }
549  }
550 
551  // Disable constraint if it only applies when on same node, but isn't
552  if (pcmk_is_set(other->type, pe_order_same_node)
553  && (first_node != NULL) && (then_node != NULL)
554  && (first_node->details != then_node->details)) {
555 
556  pe_rsc_trace(then->rsc,
557  "Disabled ordering %s on %s then %s on %s: not same node",
558  other->action->uuid, first_node->details->uname,
559  then->uuid, then_node->details->uname);
560  other->type = pe_order_none;
561  continue;
562  }
563 
565 
566  if ((first->rsc != NULL)
568  && !pcmk_is_set(then->flags, pe_action_optional)) {
569 
570  /* 'then' is required, so we must abandon 'first'
571  * (e.g. a required stop cancels any agent reload).
572  */
574  if (!strcmp(first->task, CRMD_ACTION_RELOAD_AGENT)) {
576  }
577  }
578 
579  if ((first->rsc != NULL) && (then->rsc != NULL)
580  && (first->rsc != then->rsc) && !is_parent(then->rsc, first->rsc)) {
581  first = action_for_ordering(first);
582  }
583  if (first != other->action) {
584  pe_rsc_trace(then->rsc, "Ordering %s after %s instead of %s",
585  then->uuid, first->uuid, other->action->uuid);
586  }
587 
588  pe_rsc_trace(then->rsc,
589  "%s (%#.6x) then %s (%#.6x): type=%#.6x node=%s",
590  first->uuid, first->flags, then->uuid, then->flags,
591  other->type, action_node_str(first));
592 
593  if (first == other->action) {
594  /* 'first' was not remapped (e.g. from 'start' to 'running'), which
595  * could mean it is a non-resource action, a primitive resource
596  * action, or already expanded.
597  */
598  enum pe_action_flags first_flags, then_flags;
599 
600  first_flags = action_flags_for_ordering(first, then_node);
601  then_flags = action_flags_for_ordering(then, first_node);
602 
603  changed |= update_action_for_ordering_flags(first, then,
604  first_flags, then_flags,
605  other, data_set);
606 
607  /* 'first' was for a complex resource (clone, group, etc),
608  * create a new dependency if necessary
609  */
610  } else if (order_actions(first, then, other->type)) {
611  /* This was the first time 'first' and 'then' were associated,
612  * start again to get the new actions_before list
613  */
614  pe__set_graph_flags(changed, then,
616  }
617 
618  if (pcmk_is_set(changed, pe_graph_disable)) {
619  pe_rsc_trace(then->rsc,
620  "Disabled ordering %s then %s in favor of %s then %s",
621  other->action->uuid, then->uuid, first->uuid,
622  then->uuid);
623  pe__clear_graph_flags(changed, then, pe_graph_disable);
624  other->type = pe_order_none;
625  }
626 
627  if (pcmk_is_set(changed, pe_graph_updated_first)) {
628  crm_trace("Re-processing %s and its 'after' actions "
629  "because it changed", first->uuid);
630  for (GList *lpc2 = first->actions_after; lpc2 != NULL;
631  lpc2 = lpc2->next) {
632  pe_action_wrapper_t *other = (pe_action_wrapper_t *) lpc2->data;
633 
635  }
637  }
638  }
639 
641  if (last_flags == then->flags) {
643  } else {
645  }
646  }
647 
648  if (pcmk_is_set(changed, pe_graph_updated_then)) {
649  crm_trace("Re-processing %s and its 'after' actions because it changed",
650  then->uuid);
651  if (pcmk_is_set(last_flags, pe_action_runnable)
652  && !pcmk_is_set(then->flags, pe_action_runnable)) {
654  }
656  for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) {
657  pe_action_wrapper_t *other = (pe_action_wrapper_t *) lpc->data;
658 
660  }
661  }
662 }
663 
672 void
673 pcmk__log_action(const char *pre_text, pe_action_t *action, bool details)
674 {
675  const char *node_uname = NULL;
676  const char *node_uuid = NULL;
677  const char *desc = NULL;
678 
679  CRM_CHECK(action != NULL, return);
680 
681  if (!pcmk_is_set(action->flags, pe_action_pseudo)) {
682  if (action->node != NULL) {
683  node_uname = action->node->details->uname;
684  node_uuid = action->node->details->id;
685  } else {
686  node_uname = "<none>";
687  }
688  }
689 
690  switch (text2task(action->task)) {
691  case stonith_node:
692  case shutdown_crm:
693  if (pcmk_is_set(action->flags, pe_action_pseudo)) {
694  desc = "Pseudo ";
695  } else if (pcmk_is_set(action->flags, pe_action_optional)) {
696  desc = "Optional ";
697  } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
698  desc = "!!Non-Startable!! ";
699  } else if (pcmk_is_set(action->flags, pe_action_processed)) {
700  desc = "";
701  } else {
702  desc = "(Provisional) ";
703  }
704  crm_trace("%s%s%sAction %d: %s%s%s%s%s%s",
705  ((pre_text == NULL)? "" : pre_text),
706  ((pre_text == NULL)? "" : ": "),
707  desc, action->id, action->uuid,
708  (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
709  (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
710  (node_uuid? ")" : ""));
711  break;
712  default:
713  if (pcmk_is_set(action->flags, pe_action_optional)) {
714  desc = "Optional ";
715  } else if (pcmk_is_set(action->flags, pe_action_pseudo)) {
716  desc = "Pseudo ";
717  } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
718  desc = "!!Non-Startable!! ";
719  } else if (pcmk_is_set(action->flags, pe_action_processed)) {
720  desc = "";
721  } else {
722  desc = "(Provisional) ";
723  }
724  crm_trace("%s%s%sAction %d: %s %s%s%s%s%s%s",
725  ((pre_text == NULL)? "" : pre_text),
726  ((pre_text == NULL)? "" : ": "),
727  desc, action->id, action->uuid,
728  (action->rsc? action->rsc->id : "<none>"),
729  (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
730  (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
731  (node_uuid? ")" : ""));
732  break;
733  }
734 
735  if (details) {
736  GList *iter = NULL;
737 
738  crm_trace("\t\t====== Preceding Actions");
739  for (iter = action->actions_before; iter != NULL; iter = iter->next) {
740  pe_action_wrapper_t *other = (pe_action_wrapper_t *) iter->data;
741 
742  pcmk__log_action("\t\t", other->action, false);
743  }
744  crm_trace("\t\t====== Subsequent Actions");
745  for (iter = action->actions_after; iter != NULL; iter = iter->next) {
746  pe_action_wrapper_t *other = (pe_action_wrapper_t *) iter->data;
747 
748  pcmk__log_action("\t\t", other->action, false);
749  }
750  crm_trace("\t\t====== End");
751 
752  } else {
753  crm_trace("\t\t(before=%d, after=%d)",
754  g_list_length(action->actions_before),
755  g_list_length(action->actions_after));
756  }
757 }
758 
770 pe_action_t *
772  bool optional, bool runnable)
773 {
774  pe_action_t *action = NULL;
775 
776  CRM_ASSERT((rsc != NULL) && (task != NULL));
777 
778  action = custom_action(rsc, pcmk__op_key(rsc->id, task, 0), task, NULL,
779  optional, TRUE, rsc->cluster);
781  if (runnable) {
783  }
784  return action;
785 }
786 
799 pe_action_t *
800 pcmk__new_cancel_action(pe_resource_t *rsc, const char *task, guint interval_ms,
801  pe_node_t *node)
802 {
803  pe_action_t *cancel_op = NULL;
804  char *key = NULL;
805  char *interval_ms_s = NULL;
806 
807  CRM_ASSERT((rsc != NULL) && (task != NULL) && (node != NULL));
808 
809  // @TODO dangerous if possible to schedule another action with this key
810  key = pcmk__op_key(rsc->id, task, interval_ms);
811 
812  cancel_op = custom_action(rsc, key, RSC_CANCEL, node, FALSE, TRUE,
813  rsc->cluster);
814 
815  pcmk__str_update(&cancel_op->task, RSC_CANCEL);
816  pcmk__str_update(&cancel_op->cancel_task, task);
817 
818  interval_ms_s = crm_strdup_printf("%u", interval_ms);
819  add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, task);
820  add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL_MS, interval_ms_s);
821  free(interval_ms_s);
822 
823  return cancel_op;
824 }
825 
835 pe_action_t *
837 {
838  char *shutdown_id = NULL;
839  pe_action_t *shutdown_op = NULL;
840 
841  CRM_ASSERT((node != NULL) && (data_set != NULL));
842 
843  shutdown_id = crm_strdup_printf("%s-%s", CRM_OP_SHUTDOWN,
844  node->details->uname);
845 
846  shutdown_op = custom_action(NULL, shutdown_id, CRM_OP_SHUTDOWN, node, FALSE,
847  TRUE, data_set);
848 
849  pcmk__order_stops_before_shutdown(node, shutdown_op, data_set);
851  return shutdown_op;
852 }
853 
865 static void
866 add_op_digest_to_xml(lrmd_event_data_t *op, xmlNode *update)
867 {
868  char *digest = NULL;
869  xmlNode *args_xml = NULL;
870 
871  if (op->params == NULL) {
872  return;
873  }
874  args_xml = create_xml_node(NULL, XML_TAG_PARAMS);
875  g_hash_table_foreach(op->params, hash2field, args_xml);
876  pcmk__filter_op_for_digest(args_xml);
877  digest = calculate_operation_digest(args_xml, NULL);
878  crm_xml_add(update, XML_LRM_ATTR_OP_DIGEST, digest);
879  free_xml(args_xml);
880  free(digest);
881 }
882 
883 #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
884 
898 xmlNode *
900  const char *caller_version, int target_rc,
901  const char *node, const char *origin)
902 {
903  char *key = NULL;
904  char *magic = NULL;
905  char *op_id = NULL;
906  char *op_id_additional = NULL;
907  char *local_user_data = NULL;
908  const char *exit_reason = NULL;
909 
910  xmlNode *xml_op = NULL;
911  const char *task = NULL;
912 
913  CRM_CHECK(op != NULL, return NULL);
914  crm_trace("Creating history XML for %s-interval %s action for %s on %s "
915  "(DC version: %s, origin: %s)",
917  ((node == NULL)? "no node" : node), caller_version, origin);
918 
919  task = op->op_type;
920 
921  /* Record a successful agent reload as a start, and a failed one as a
922  * monitor, to make life easier for the scheduler when determining the
923  * current state.
924  *
925  * @COMPAT We should check "reload" here only if the operation was for a
926  * pre-OCF-1.1 resource agent, but we don't know that here, and we should
927  * only ever get results for actions scheduled by us, so we can reasonably
928  * assume any "reload" is actually a pre-1.1 agent reload.
929  */
931  NULL)) {
932  if (op->op_status == PCMK_EXEC_DONE) {
933  task = CRMD_ACTION_START;
934  } else {
935  task = CRMD_ACTION_STATUS;
936  }
937  }
938 
939  key = pcmk__op_key(op->rsc_id, task, op->interval_ms);
940  if (pcmk__str_eq(task, CRMD_ACTION_NOTIFY, pcmk__str_none)) {
941  const char *n_type = crm_meta_value(op->params, "notify_type");
942  const char *n_task = crm_meta_value(op->params, "notify_operation");
943 
944  CRM_LOG_ASSERT(n_type != NULL);
945  CRM_LOG_ASSERT(n_task != NULL);
946  op_id = pcmk__notify_key(op->rsc_id, n_type, n_task);
947 
948  if (op->op_status != PCMK_EXEC_PENDING) {
949  /* Ignore notify errors.
950  *
951  * @TODO It might be better to keep the correct result here, and
952  * ignore it in process_graph_event().
953  */
955  }
956 
957  } else if (did_rsc_op_fail(op, target_rc)) {
958  op_id = pcmk__op_key(op->rsc_id, "last_failure", 0);
959  if (op->interval_ms == 0) {
960  // Ensure 'last' gets updated, in case record-pending is true
961  op_id_additional = pcmk__op_key(op->rsc_id, "last", 0);
962  }
963  exit_reason = op->exit_reason;
964 
965  } else if (op->interval_ms > 0) {
966  op_id = strdup(key);
967 
968  } else {
969  op_id = pcmk__op_key(op->rsc_id, "last", 0);
970  }
971 
972  again:
974  if (xml_op == NULL) {
976  }
977 
978  if (op->user_data == NULL) {
979  crm_debug("Generating fake transition key for: " PCMK__OP_FMT
980  " %d from %s", op->rsc_id, op->op_type, op->interval_ms,
981  op->call_id, origin);
982  local_user_data = pcmk__transition_key(-1, op->call_id, target_rc,
983  FAKE_TE_ID);
984  op->user_data = local_user_data;
985  }
986 
987  if (magic == NULL) {
988  magic = crm_strdup_printf("%d:%d;%s", op->op_status, op->rc,
989  (const char *) op->user_data);
990  }
991 
992  crm_xml_add(xml_op, XML_ATTR_ID, op_id);
993  crm_xml_add(xml_op, XML_LRM_ATTR_TASK_KEY, key);
994  crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task);
995  crm_xml_add(xml_op, XML_ATTR_ORIGIN, origin);
996  crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, caller_version);
998  crm_xml_add(xml_op, XML_ATTR_TRANSITION_MAGIC, magic);
999  crm_xml_add(xml_op, XML_LRM_ATTR_EXIT_REASON, exit_reason == NULL ? "" : exit_reason);
1000  crm_xml_add(xml_op, XML_LRM_ATTR_TARGET, node); /* For context during triage */
1001 
1003  crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op->rc);
1006 
1007  if (compare_version("2.1", caller_version) <= 0) {
1008  if (op->t_run || op->t_rcchange || op->exec_time || op->queue_time) {
1009  crm_trace("Timing data (" PCMK__OP_FMT
1010  "): last=%u change=%u exec=%u queue=%u",
1011  op->rsc_id, op->op_type, op->interval_ms,
1012  op->t_run, op->t_rcchange, op->exec_time, op->queue_time);
1013 
1014  if ((op->interval_ms != 0) && (op->t_rcchange != 0)) {
1015  // Recurring ops may have changed rc after initial run
1017  (long long) op->t_rcchange);
1018  } else {
1020  (long long) op->t_run);
1021  }
1022 
1025  }
1026  }
1027 
1029  /*
1030  * Record migrate_source and migrate_target always for migrate ops.
1031  */
1032  const char *name = XML_LRM_ATTR_MIGRATE_SOURCE;
1033 
1034  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1035 
1037  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1038  }
1039 
1040  add_op_digest_to_xml(op, xml_op);
1041 
1042  if (op_id_additional) {
1043  free(op_id);
1044  op_id = op_id_additional;
1045  op_id_additional = NULL;
1046  goto again;
1047  }
1048 
1049  if (local_user_data) {
1050  free(local_user_data);
1051  op->user_data = NULL;
1052  }
1053  free(magic);
1054  free(op_id);
1055  free(key);
1056  return xml_op;
1057 }
1058 
1073 bool
1075 {
1076  // Only resource actions taking place on resource's lock node are locked
1077  if ((action == NULL) || (action->rsc == NULL)
1078  || (action->rsc->lock_node == NULL) || (action->node == NULL)
1079  || (action->node->details != action->rsc->lock_node->details)) {
1080  return false;
1081  }
1082 
1083  /* During shutdown, only stops are locked (otherwise, another action such as
1084  * a demote would cause the controller to clear the lock)
1085  */
1086  if (action->node->details->shutdown && (action->task != NULL)
1087  && (strcmp(action->task, RSC_STOP) != 0)) {
1088  return false;
1089  }
1090 
1091  return true;
1092 }
1093 
1094 /* lowest to highest */
1095 static gint
1096 sort_action_id(gconstpointer a, gconstpointer b)
1097 {
1098  const pe_action_wrapper_t *action_wrapper2 = (const pe_action_wrapper_t *)a;
1099  const pe_action_wrapper_t *action_wrapper1 = (const pe_action_wrapper_t *)b;
1100 
1101  if (a == NULL) {
1102  return 1;
1103  }
1104  if (b == NULL) {
1105  return -1;
1106  }
1107  if (action_wrapper1->action->id < action_wrapper2->action->id) {
1108  return 1;
1109  }
1110  if (action_wrapper1->action->id > action_wrapper2->action->id) {
1111  return -1;
1112  }
1113  return 0;
1114 }
1115 
1122 void
1124 {
1125  GList *item = NULL;
1126  GList *next = NULL;
1127  pe_action_wrapper_t *last_input = NULL;
1128 
1129  action->actions_before = g_list_sort(action->actions_before,
1130  sort_action_id);
1131  for (item = action->actions_before; item != NULL; item = next) {
1132  pe_action_wrapper_t *input = (pe_action_wrapper_t *) item->data;
1133 
1134  next = item->next;
1135  if ((last_input != NULL)
1136  && (input->action->id == last_input->action->id)) {
1137  crm_trace("Input %s (%d) duplicate skipped for action %s (%d)",
1138  input->action->uuid, input->action->id,
1139  action->uuid, action->id);
1140 
1141  /* For the purposes of scheduling, the ordering flags no longer
1142  * matter, but crm_simulate looks at certain ones when creating a
1143  * dot graph. Combining the flags is sufficient for that purpose.
1144  */
1145  last_input->type |= input->type;
1146  if (input->state == pe_link_dumped) {
1147  last_input->state = pe_link_dumped;
1148  }
1149 
1150  free(item->data);
1151  action->actions_before = g_list_delete_link(action->actions_before,
1152  item);
1153  } else {
1154  last_input = input;
1155  input->state = pe_link_not_dumped;
1156  }
1157  }
1158 }
1159 
1166 void
1168 {
1169  pcmk__output_t *out = data_set->priv;
1170 
1171  // Output node (non-resource) actions
1172  for (GList *iter = data_set->actions; iter != NULL; iter = iter->next) {
1173  char *node_name = NULL;
1174  char *task = NULL;
1175  pe_action_t *action = (pe_action_t *) iter->data;
1176 
1177  if (action->rsc != NULL) {
1178  continue; // Resource actions will be output later
1179 
1180  } else if (pcmk_is_set(action->flags, pe_action_optional)) {
1181  continue; // This action was not scheduled
1182  }
1183 
1184  if (pcmk__str_eq(action->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
1185  task = strdup("Shutdown");
1186 
1187  } else if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei)) {
1188  const char *op = g_hash_table_lookup(action->meta, "stonith_action");
1189 
1190  task = crm_strdup_printf("Fence (%s)", op);
1191 
1192  } else {
1193  continue; // Don't display other node action types
1194  }
1195 
1196  if (pe__is_guest_node(action->node)) {
1197  node_name = crm_strdup_printf("%s (resource: %s)",
1198  action->node->details->uname,
1199  action->node->details->remote_rsc->container->id);
1200  } else if (action->node != NULL) {
1201  node_name = crm_strdup_printf("%s", action->node->details->uname);
1202  }
1203 
1204  out->message(out, "node-action", task, node_name, action->reason);
1205 
1206  free(node_name);
1207  free(task);
1208  }
1209 
1210  // Output resource actions
1211  for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) {
1212  pe_resource_t *rsc = (pe_resource_t *) iter->data;
1213 
1214  rsc->cmds->output_actions(rsc);
1215  }
1216 }
1217 
1229 static void
1230 schedule_cancel(pe_resource_t *rsc, const char *call_id, const char *task,
1231  guint interval_ms, pe_node_t *node, const char *reason)
1232 {
1233  pe_action_t *cancel = NULL;
1234 
1235  CRM_CHECK((rsc != NULL) && (task != NULL)
1236  && (node != NULL) && (reason != NULL),
1237  return);
1238 
1239  crm_info("Recurring %s-interval %s for %s will be stopped on %s: %s",
1240  pcmk__readable_interval(interval_ms), task, rsc->id,
1241  crm_str(node->details->uname), reason);
1242  cancel = pcmk__new_cancel_action(rsc, task, interval_ms, node);
1243  add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id);
1244 
1245  // Cancellations happen after stops
1246  pcmk__new_ordering(rsc, stop_key(rsc), NULL, rsc, NULL, cancel,
1247  pe_order_optional, rsc->cluster);
1248 }
1249 
1260 static bool
1261 action_in_config(pe_resource_t *rsc, const char *task, guint interval_ms)
1262 {
1263  char *key = pcmk__op_key(rsc->id, task, interval_ms);
1264  bool config = (find_rsc_op_entry(rsc, key) != NULL);
1265 
1266  free(key);
1267  return config;
1268 }
1269 
1279 static const char *
1280 task_for_digest(const char *task, guint interval_ms)
1281 {
1282  /* Certain actions need to be compared against the parameters used to start
1283  * the resource.
1284  */
1285  if ((interval_ms == 0)
1287  task = RSC_START;
1288  }
1289  return task;
1290 }
1291 
1309 static bool
1310 only_sanitized_changed(xmlNode *xml_op, const op_digest_cache_t *digest_data,
1312 {
1313  const char *digest_secure = NULL;
1314 
1316  // The scheduler is not being run as a simulation
1317  return false;
1318  }
1319 
1320  digest_secure = crm_element_value(xml_op, XML_LRM_ATTR_SECURE_DIGEST);
1321 
1322  return (digest_data->rc != RSC_DIGEST_MATCH) && (digest_secure != NULL)
1323  && (digest_data->digest_secure_calc != NULL)
1324  && (strcmp(digest_data->digest_secure_calc, digest_secure) == 0);
1325 }
1326 
1336 static void
1337 force_restart(pe_resource_t *rsc, const char *task, guint interval_ms,
1338  pe_node_t *node)
1339 {
1340  char *key = pcmk__op_key(rsc->id, task, interval_ms);
1341  pe_action_t *required = custom_action(rsc, key, task, NULL, FALSE, TRUE,
1342  rsc->cluster);
1343 
1344  pe_action_set_reason(required, "resource definition change", true);
1345  trigger_unfencing(rsc, node, "Device parameters changed", NULL,
1346  rsc->cluster);
1347 }
1348 
1358 static void
1359 reschedule_recurring(pe_resource_t *rsc, const char *task, guint interval_ms,
1360  pe_node_t *node)
1361 {
1362  pe_action_t *op = NULL;
1363 
1364  trigger_unfencing(rsc, node, "Device parameters changed (reschedule)",
1365  NULL, rsc->cluster);
1366  op = custom_action(rsc, pcmk__op_key(rsc->id, task, interval_ms),
1367  task, node, TRUE, TRUE, rsc->cluster);
1369 }
1370 
1378 static void
1379 schedule_reload(pe_resource_t *rsc, pe_node_t *node)
1380 {
1381  pe_action_t *reload = NULL;
1382 
1383  // For collective resources, just call recursively for children
1384  if (rsc->variant > pe_native) {
1385  g_list_foreach(rsc->children, (GFunc) schedule_reload, node);
1386  return;
1387  }
1388 
1389  // Skip the reload in certain situations
1390  if ((node == NULL)
1391  || !pcmk_is_set(rsc->flags, pe_rsc_managed)
1392  || pcmk_is_set(rsc->flags, pe_rsc_failed)) {
1393  pe_rsc_trace(rsc, "Skip reload of %s:%s%s %s",
1394  rsc->id,
1395  pcmk_is_set(rsc->flags, pe_rsc_managed)? "" : " unmanaged",
1396  pcmk_is_set(rsc->flags, pe_rsc_failed)? " failed" : "",
1397  (node == NULL)? "inactive" : node->details->uname);
1398  return;
1399  }
1400 
1401  /* If a resource's configuration changed while a start was pending,
1402  * force a full restart instead of a reload.
1403  */
1404  if (pcmk_is_set(rsc->flags, pe_rsc_start_pending)) {
1405  pe_rsc_trace(rsc, "%s: preventing agent reload because start pending",
1406  rsc->id);
1407  custom_action(rsc, stop_key(rsc), CRMD_ACTION_STOP, node, FALSE, TRUE,
1408  rsc->cluster);
1409  return;
1410  }
1411 
1412  // Schedule the reload
1414  reload = custom_action(rsc, reload_key(rsc), CRMD_ACTION_RELOAD_AGENT, node,
1415  FALSE, TRUE, rsc->cluster);
1416  pe_action_set_reason(reload, "resource definition change", FALSE);
1417 
1418  // Set orderings so that a required stop or demote cancels the reload
1419  pcmk__new_ordering(NULL, NULL, reload, rsc, stop_key(rsc), NULL,
1421  rsc->cluster);
1422  pcmk__new_ordering(NULL, NULL, reload, rsc, demote_key(rsc), NULL,
1424  rsc->cluster);
1425 }
1426 
1441 bool
1443 {
1444  guint interval_ms = 0;
1445  const char *task = NULL;
1446  const op_digest_cache_t *digest_data = NULL;
1447 
1448  CRM_CHECK((rsc != NULL) && (node != NULL) && (xml_op != NULL),
1449  return false);
1450 
1451  task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
1452  CRM_CHECK(task != NULL, return false);
1453 
1454  crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
1455 
1456  // If this is a recurring action, check whether it has been orphaned
1457  if (interval_ms > 0) {
1458  if (action_in_config(rsc, task, interval_ms)) {
1459  pe_rsc_trace(rsc, "%s-interval %s for %s on %s is in configuration",
1460  pcmk__readable_interval(interval_ms), task, rsc->id,
1461  node->details->uname);
1462  } else if (pcmk_is_set(rsc->cluster->flags,
1464  schedule_cancel(rsc,
1466  task, interval_ms, node, "orphan");
1467  return true;
1468  } else {
1469  pe_rsc_debug(rsc, "%s-interval %s for %s on %s is orphaned",
1470  pcmk__readable_interval(interval_ms), task, rsc->id,
1471  node->details->uname);
1472  return true;
1473  }
1474  }
1475 
1476  crm_trace("Checking %s-interval %s for %s on %s for configuration changes",
1477  pcmk__readable_interval(interval_ms), task, rsc->id,
1478  node->details->uname);
1479  task = task_for_digest(task, interval_ms);
1480  digest_data = rsc_action_digest_cmp(rsc, xml_op, node, rsc->cluster);
1481 
1482  if (only_sanitized_changed(xml_op, digest_data, rsc->cluster)) {
1483  if (!pcmk__is_daemon && (rsc->cluster->priv != NULL)) {
1484  pcmk__output_t *out = rsc->cluster->priv;
1485 
1486  out->info(out,
1487  "Only 'private' parameters to %s-interval %s for %s "
1488  "on %s changed: %s",
1489  pcmk__readable_interval(interval_ms), task, rsc->id,
1490  node->details->uname,
1492  }
1493  return false;
1494  }
1495 
1496  switch (digest_data->rc) {
1497  case RSC_DIGEST_RESTART:
1498  crm_log_xml_debug(digest_data->params_restart, "params:restart");
1499  force_restart(rsc, task, interval_ms, node);
1500  return true;
1501 
1502  case RSC_DIGEST_ALL:
1503  case RSC_DIGEST_UNKNOWN:
1504  // Changes that can potentially be handled by an agent reload
1505 
1506  if (interval_ms > 0) {
1507  /* Recurring actions aren't reloaded per se, they are just
1508  * re-scheduled so the next run uses the new parameters.
1509  * The old instance will be cancelled automatically.
1510  */
1511  crm_log_xml_debug(digest_data->params_all, "params:reschedule");
1512  reschedule_recurring(rsc, task, interval_ms, node);
1513 
1514  } else if (crm_element_value(xml_op,
1515  XML_LRM_ATTR_RESTART_DIGEST) != NULL) {
1516  // Agent supports reload, so use it
1517  trigger_unfencing(rsc, node,
1518  "Device parameters changed (reload)", NULL,
1519  rsc->cluster);
1520  crm_log_xml_debug(digest_data->params_all, "params:reload");
1521  schedule_reload(rsc, node);
1522 
1523  } else {
1524  pe_rsc_trace(rsc,
1525  "Restarting %s because agent doesn't support reload",
1526  rsc->id);
1527  crm_log_xml_debug(digest_data->params_restart,
1528  "params:restart");
1529  force_restart(rsc, task, interval_ms, node);
1530  }
1531  return true;
1532 
1533  default:
1534  break;
1535  }
1536  return false;
1537 }
1538 
1548 static GList *
1549 rsc_history_as_list(pe_resource_t *rsc, xmlNode *rsc_entry,
1550  int *start_index, int *stop_index)
1551 {
1552  GList *ops = NULL;
1553 
1554  for (xmlNode *rsc_op = first_named_child(rsc_entry, XML_LRM_TAG_RSC_OP);
1555  rsc_op != NULL; rsc_op = crm_next_same_xml(rsc_op)) {
1556  ops = g_list_prepend(ops, rsc_op);
1557  }
1558  ops = g_list_sort(ops, sort_op_by_callid);
1559  calculate_active_ops(ops, start_index, stop_index);
1560  return ops;
1561 }
1562 
1577 static void
1578 process_rsc_history(xmlNode *rsc_entry, pe_resource_t *rsc, pe_node_t *node)
1579 {
1580  int offset = -1;
1581  int stop_index = 0;
1582  int start_index = 0;
1583  GList *sorted_op_list = NULL;
1584 
1585  if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
1586  if (pe_rsc_is_anon_clone(uber_parent(rsc))) {
1587  pe_rsc_trace(rsc,
1588  "Skipping configuration check "
1589  "for orphaned clone instance %s",
1590  rsc->id);
1591  } else {
1592  pe_rsc_trace(rsc,
1593  "Skipping configuration check and scheduling clean-up "
1594  "for orphaned resource %s", rsc->id);
1595  DeleteRsc(rsc, node, FALSE, rsc->cluster);
1596  }
1597  return;
1598  }
1599 
1600  if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
1601  if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, false)) {
1602  DeleteRsc(rsc, node, FALSE, rsc->cluster);
1603  }
1604  pe_rsc_trace(rsc,
1605  "Skipping configuration check for %s "
1606  "because no longer active on %s",
1607  rsc->id, node->details->uname);
1608  return;
1609  }
1610 
1611  pe_rsc_trace(rsc, "Checking for configuration changes for %s on %s",
1612  rsc->id, node->details->uname);
1613 
1614  if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, true)) {
1615  DeleteRsc(rsc, node, FALSE, rsc->cluster);
1616  }
1617 
1618  sorted_op_list = rsc_history_as_list(rsc, rsc_entry, &start_index,
1619  &stop_index);
1620  if (start_index < stop_index) {
1621  return; // Resource is stopped
1622  }
1623 
1624  for (GList *iter = sorted_op_list; iter != NULL; iter = iter->next) {
1625  xmlNode *rsc_op = (xmlNode *) iter->data;
1626  const char *task = NULL;
1627  guint interval_ms = 0;
1628 
1629  if (++offset < start_index) {
1630  // Skip actions that happened before a start
1631  continue;
1632  }
1633 
1634  task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
1635  crm_element_value_ms(rsc_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
1636 
1637  if ((interval_ms > 0)
1639  || node->details->maintenance)) {
1640  // Maintenance mode cancels recurring operations
1641  schedule_cancel(rsc,
1643  task, interval_ms, node, "maintenance mode");
1644 
1645  } else if ((interval_ms > 0)
1647  RSC_PROMOTE, RSC_MIGRATED, NULL)) {
1648  /* If a resource operation failed, and the operation's definition
1649  * has changed, clear any fail count so they can be retried fresh.
1650  */
1651 
1652  if (pe__bundle_needs_remote_name(rsc, rsc->cluster)) {
1653  /* We haven't allocated resources to nodes yet, so if the
1654  * REMOTE_CONTAINER_HACK is used, we may calculate the digest
1655  * based on the literal "#uname" value rather than the properly
1656  * substituted value. That would mistakenly make the action
1657  * definition appear to have been changed. Defer the check until
1658  * later in this case.
1659  */
1660  pe__add_param_check(rsc_op, rsc, node, pe_check_active,
1661  rsc->cluster);
1662 
1663  } else if (pcmk__check_action_config(rsc, node, rsc_op)
1664  && (pe_get_failcount(node, rsc, NULL, pe_fc_effective,
1665  NULL, rsc->cluster) != 0)) {
1666  pe__clear_failcount(rsc, node, "action definition changed",
1667  rsc->cluster);
1668  }
1669  }
1670  }
1671  g_list_free(sorted_op_list);
1672 }
1673 
1688 static void
1689 process_node_history(pe_node_t *node, xmlNode *lrm_rscs, pe_working_set_t *data_set)
1690 {
1691  crm_trace("Processing history for node %s", node->details->uname);
1692  for (xmlNode *rsc_entry = first_named_child(lrm_rscs, XML_LRM_TAG_RESOURCE);
1693  rsc_entry != NULL; rsc_entry = crm_next_same_xml(rsc_entry)) {
1694 
1695  if (xml_has_children(rsc_entry)) {
1696  GList *result = pcmk__rscs_matching_id(ID(rsc_entry), data_set);
1697 
1698  for (GList *iter = result; iter != NULL; iter = iter->next) {
1699  pe_resource_t *rsc = (pe_resource_t *) iter->data;
1700 
1701  if (rsc->variant == pe_native) {
1702  process_rsc_history(rsc_entry, rsc, node);
1703  }
1704  }
1705  g_list_free(result);
1706  }
1707  }
1708 }
1709 
1710 // XPath to find a node's resource history
1711 #define XPATH_NODE_HISTORY "/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS \
1712  "/" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']" \
1713  "/" XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES
1714 
1727 void
1729 {
1730  crm_trace("Check resource and action configuration for changes");
1731 
1732  /* Rather than iterate through the status section, iterate through the nodes
1733  * and search for the appropriate status subsection for each. This skips
1734  * orphaned nodes and lets us eliminate some cases before searching the XML.
1735  */
1736  for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
1737  pe_node_t *node = (pe_node_t *) iter->data;
1738 
1739  /* Don't bother checking actions for a node that can't run actions ...
1740  * unless it's in maintenance mode, in which case we still need to
1741  * cancel any existing recurring monitors.
1742  */
1743  if (node->details->maintenance || pcmk__node_available(node)) {
1744  char *xpath = NULL;
1745  xmlNode *history = NULL;
1746 
1748  history = get_xpath_object(xpath, data_set->input, LOG_NEVER);
1749  free(xpath);
1750 
1751  process_node_history(node, history, data_set);
1752  }
1753  }
1754 }
enum pe_link_state state
Definition: pe_types.h:547
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:323
void pcmk__output_actions(pe_working_set_t *data_set)
const char * task2text(enum action_tasks task)
Definition: common.c:401
#define RSC_STOP
Definition: crm.h:204
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: operations.c:185
#define CRMD_ACTION_MIGRATED
Definition: crm.h:174
#define pe_flag_stop_action_orphans
Definition: pe_types.h:105
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:21
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:61
const char * user_data
Definition: lrmd.h:209
gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc)
Definition: complex.c:896
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:782
int runnable_before
Definition: pe_types.h:456
const char * rsc_id
Definition: lrmd.h:205
#define CRM_OP_FENCE
Definition: crm.h:145
gboolean DeleteRsc(pe_resource_t *rsc, pe_node_t *node, gboolean optional, pe_working_set_t *data_set)
const char * crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
Create an XML attribute with specified name and unsigned value.
Definition: nvpair.c:453
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:404
void pe__add_param_check(xmlNode *rsc_op, pe_resource_t *rsc, pe_node_t *node, enum pe_check_parameters, pe_working_set_t *data_set)
Definition: remote.c:220
const char * name
Definition: cib.c:24
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:931
int(* message)(pcmk__output_t *out, const char *message_id,...)
G_GNUC_INTERNAL bool pcmk__node_available(const pe_node_t *node)
GList * children
Definition: pe_types.h:391
resource_alloc_functions_t * cmds
Definition: pe_types.h:348
unsigned int queue_time
Definition: lrmd.h:235
G_GNUC_INTERNAL void pcmk__order_stops_before_shutdown(pe_node_t *node, pe_action_t *shutdown_op, pe_working_set_t *data_set)
Internal tracking for transition graph creation.
Definition: pe_types.h:486
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2794
void pcmk__update_action_for_orderings(pe_action_t *then, pe_working_set_t *data_set)
G_GNUC_INTERNAL void pcmk__new_ordering(pe_resource_t *lh_rsc, char *lh_task, pe_action_t *lh_action, pe_resource_t *rh_rsc, char *rh_task, pe_action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set)
enum pe_graph_flags(* update_actions)(pe_action_t *, pe_action_t *, pe_node_t *, enum pe_action_flags, enum pe_action_flags, enum pe_ordering, pe_working_set_t *data_set)
pe_resource_t * rsc
Definition: pe_types.h:424
pe_action_t * pcmk__new_shutdown_action(pe_node_t *node, pe_working_set_t *data_set)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:431
#define reload_key(rsc)
Definition: internal.h:383
char * cancel_task
Definition: pe_types.h:430
#define CRMD_ACTION_NOTIFY
Definition: crm.h:187
#define XML_RSC_OP_T_EXEC
Definition: msg_xml.h:325
#define pe_rsc_notify
Definition: pe_types.h:261
const char * crm_meta_value(GHashTable *hash, const char *field)
Definition: utils.c:461
resource_object_functions_t * fns
Definition: pe_types.h:347
xmlNode * pcmk__xe_match(xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:495
#define XML_LRM_TAG_RESOURCE
Definition: msg_xml.h:270
pe_action_t * pcmk__new_cancel_action(pe_resource_t *rsc, const char *task, guint interval_ms, pe_node_t *node)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:323
#define XML_LRM_ATTR_OP_DIGEST
Definition: msg_xml.h:316
#define pe__clear_graph_flags(graph_flags, gr_action, flags_to_clear)
Definition: internal.h:134
bool pe__bundle_needs_remote_name(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: bundle.c:943
pe_action_t * pcmk__new_rsc_pseudo_action(pe_resource_t *rsc, const char *task, bool optional, bool runnable)
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
Definition: utils.c:1736
unsigned int t_rcchange
Definition: lrmd.h:231
xmlNode * pcmk__create_history_xml(xmlNode *parent, lrmd_event_data_t *op, const char *caller_version, int target_rc, const char *node, const char *origin)
void pcmk__filter_op_for_digest(xmlNode *param_set)
Definition: operations.c:390
enum action_tasks text2task(const char *task)
Definition: common.c:351
GList * actions
Definition: pe_types.h:171
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:210
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
xmlNode * params_restart
Definition: internal.h:483
#define demote_key(rsc)
Definition: internal.h:404
enum ocf_exitcode rc
Definition: lrmd.h:223
#define RSC_START
Definition: crm.h:201
pe_action_t * action
Definition: pe_types.h:548
#define XML_RSC_OP_T_QUEUE
Definition: msg_xml.h:326
#define LOG_NEVER
Definition: logging.h:47
G_GNUC_INTERNAL GList * pcmk__rscs_matching_id(const char *id, pe_working_set_t *data_set)
#define pe__set_raw_action_flags(action_flags, action_name, flags_to_set)
Definition: internal.h:79
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:214
bool pcmk__action_locks_rsc_to_node(const pe_action_t *action)
const char * action
Definition: pcmk_fence.c:29
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:49
GList * resources
Definition: pe_types.h:165
void trigger_unfencing(pe_resource_t *rsc, pe_node_t *node, const char *reason, pe_action_t *dependency, pe_working_set_t *data_set)
Definition: utils.c:2244
unsigned int exec_time
Definition: lrmd.h:233
GList * nodes
Definition: pe_types.h:164
#define XML_ATTR_ORIGIN
Definition: msg_xml.h:130
#define CRMD_ACTION_START
Definition: crm.h:176
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:304
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:303
void pcmk__deduplicate_action_inputs(pe_action_t *action)
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition: pe_types.h:55
#define CRMD_ACTION_STOP
Definition: crm.h:179
void * params
Definition: lrmd.h:242
char * calculate_operation_digest(xmlNode *local_cib, const char *version)
Calculate and return digest of XML operation.
Definition: digest.c:170
#define crm_warn(fmt, args...)
Definition: logging.h:359
#define CRMD_ACTION_RELOAD_AGENT
Definition: crm.h:172
void pe_action_set_reason(pe_action_t *action, const char *reason, bool overwrite)
Definition: utils.c:2349
const char * exit_reason
Definition: lrmd.h:250
pe_action_flags
Definition: pe_types.h:305
#define action_type_str(flags)
char * pcmk__notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
Definition: operations.c:229
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:622
#define action_node_str(a)
#define pe_rsc_failed
Definition: pe_types.h:276
#define crm_debug(fmt, args...)
Definition: logging.h:363
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:913
#define pe_flag_sanitized
Definition: pe_types.h:121
#define pe__clear_order_flags(order_flags, flags_to_clear)
Definition: internal.h:120
G_GNUC_INTERNAL void pcmk__block_colocated_starts(pe_action_t *action, pe_working_set_t *data_set)
#define XML_ATTR_ID
Definition: msg_xml.h:135
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:529
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:146
bool pe__is_guest_node(const pe_node_t *node)
Definition: remote.c:33
#define stop_key(rsc)
Definition: internal.h:378
#define pe_rsc_start_pending
Definition: pe_types.h:278
char * task
Definition: pe_types.h:428
GList * actions_after
Definition: pe_types.h:462
#define pe__clear_action_flags(action, flags_to_clear)
Definition: internal.h:70
void pcmk__log_action(const char *pre_text, pe_action_t *action, bool details)
#define crm_trace(fmt, args...)
Definition: logging.h:364
enum rsc_digest_cmp_val rc
Definition: internal.h:480
char * digest_secure_calc
Definition: internal.h:485
void calculate_active_ops(GList *sorted_op_list, int *start_index, int *stop_index)
Definition: unpack.c:2259
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
GHashTable * meta
Definition: pe_types.h:438
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:122
struct pe_node_shared_s * details
Definition: pe_types.h:252
#define crm_log_xml_debug(xml, text)
Definition: logging.h:371
pe_node_t * node
Definition: pe_types.h:425
bool pcmk__is_daemon
Definition: logging.c:47
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition: utils.c:1906
unsigned long long flags
Definition: pe_types.h:362
const char * uname
Definition: pe_types.h:216
pe_working_set_t * data_set
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1188
#define XML_ATTR_TE_NOWAIT
Definition: msg_xml.h:407
xmlNode * find_rsc_op_entry(pe_resource_t *rsc, const char *key)
Definition: utils.c:1440
void(* output_actions)(pe_resource_t *rsc)
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
Action completed, result is known.
Definition: results.h:308
#define pe__set_graph_flags(graph_flags, gr_action, flags_to_set)
Definition: internal.h:127
GList * actions
Definition: pe_types.h:373
pe_graph_flags
Definition: pe_types.h:297
#define XML_LRM_ATTR_MIGRATE_TARGET
Definition: msg_xml.h:329
#define XML_LRM_ATTR_EXIT_REASON
Definition: msg_xml.h:321
char * uuid
Definition: pe_types.h:429
#define XML_LRM_ATTR_RESTART_DIGEST
Definition: msg_xml.h:319
void free_xml(xmlNode *child)
Definition: xml.c:824
enum pe_obj_types variant
Definition: pe_types.h:345
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:955
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:2028
xmlNode * input
Definition: pe_types.h:144
xmlNode * params_all
Definition: internal.h:481
#define CRM_OP_SHUTDOWN
Definition: crm.h:144
const char * id
Definition: pe_types.h:215
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition: operations.c:45
const char * op_type
Definition: lrmd.h:207
#define CRMD_ACTION_RELOAD
Definition: crm.h:171
const char * crm_xml_add_ll(xmlNode *node, const char *name, long long value)
Create an XML attribute with specified name and long long int value.
Definition: nvpair.c:481
void pcmk__handle_rsc_config_changes(pe_working_set_t *data_set)
unsigned int t_run
Definition: lrmd.h:229
pe_node_t * pe_find_node_id(GList *node_list, const char *id)
Definition: status.c:427
#define XML_ATTR_TRANSITION_KEY
Definition: msg_xml.h:405
#define XML_LRM_ATTR_SECURE_DIGEST
Definition: msg_xml.h:320
#define action_runnable_str(flags)
#define action_optional_str(flags)
G_GNUC_INTERNAL bool pcmk__rsc_agent_changed(pe_resource_t *rsc, pe_node_t *node, const xmlNode *rsc_entry, bool active_on_node)
pcmk__action_result_t result
Definition: pcmk_fence.c:34
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:504
gboolean did_rsc_op_fail(lrmd_event_data_t *event, int target_rc)
Definition: operations.c:437
#define XPATH_NODE_HISTORY
#define crm_err(fmt, args...)
Definition: logging.h:358
#define CRM_ASSERT(expr)
Definition: results.h:42
#define RSC_STATUS
Definition: crm.h:215
Success.
Definition: results.h:162
pe_action_t * pe__clear_failcount(pe_resource_t *rsc, pe_node_t *node, const char *reason, pe_working_set_t *data_set)
Schedule a controller operation to clear a fail count.
Definition: failcounts.c:366
op_digest_cache_t * rsc_action_digest_cmp(pe_resource_t *rsc, xmlNode *xml_op, pe_node_t *node, pe_working_set_t *data_set)
Definition: pe_digest.c:392
void lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, int op_status, const char *exit_reason)
Definition: lrmd_client.c:2356
#define pe_rsc_reload
Definition: pe_types.h:272
#define RSC_PROMOTE
Definition: crm.h:207
xmlNode * input
This structure contains everything that makes up a single output formatter.
int compare_version(const char *version1, const char *version2)
Definition: utils.c:160
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:301
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:315
#define CRMD_ACTION_MIGRATE
Definition: crm.h:173
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:55
#define crm_str(x)
Definition: logging.h:384
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:313
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:118
char * pcmk__transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition: operations.c:296
GList * running_on
Definition: pe_types.h:380
#define pe_rsc_block
Definition: pe_types.h:258
enum pe_action_flags flags
Definition: pe_types.h:433
gboolean maintenance
Definition: pe_types.h:229
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:314
#define pe_rsc_maintenance
Definition: pe_types.h:290
pe_working_set_t * cluster
Definition: pe_types.h:342
Action is in progress.
Definition: results.h:307
const char * pcmk__readable_interval(guint interval_ms)
Definition: iso8601.c:1750
#define RSC_CANCEL
Definition: crm.h:196
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:305
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:271
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:22
#define pe__set_order_flags(order_flags, flags_to_set)
Definition: internal.h:113
#define ID(x)
Definition: msg_xml.h:460
unsigned long long flags
Definition: pe_types.h:153
#define FAKE_TE_ID
const char * parent
Definition: cib.c:25
#define PCMK__OP_FMT
Definition: internal.h:215
#define XML_LRM_ATTR_MIGRATE_SOURCE
Definition: msg_xml.h:328
enum pe_ordering type
Definition: pe_types.h:546
#define XML_TAG_PARAMS
Definition: msg_xml.h:215
#define crm_info(fmt, args...)
Definition: logging.h:361
#define pe_rsc_managed
Definition: pe_types.h:257
#define pe_rsc_orphan
Definition: pe_types.h:256
pe_action_t * find_first_action(GList *input, const char *uuid, const char *task, pe_node_t *on_node)
Definition: utils.c:1541
bool pcmk__check_action_config(pe_resource_t *rsc, pe_node_t *node, xmlNode *xml_op)
uint64_t flags
Definition: remote.c:149
GList * actions_before
Definition: pe_types.h:461
int pe_get_failcount(pe_node_t *node, pe_resource_t *rsc, time_t *last_failure, uint32_t flags, xmlNode *xml_op, pe_working_set_t *data_set)
Definition: failcounts.c:251
int required_runnable_before
Definition: pe_types.h:459
action_tasks
Definition: common.h:61
pe_resource_t * parent
Definition: pe_types.h:343
guint interval_ms
Definition: lrmd.h:216
char * id
Definition: pe_types.h:336
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, pe_node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Create or update an action object.
Definition: utils.c:730
#define RSC_MIGRATED
Definition: crm.h:199
#define CRMD_ACTION_STATUS
Definition: crm.h:190
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2820