pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
pcmk_sched_actions.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2023 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>
18 #include <pacemaker-internal.h>
19 #include "libpacemaker_private.h"
20 
31 static uint32_t
32 action_flags_for_ordering(pcmk_action_t *action, const pcmk_node_t *node)
33 {
34  bool runnable = false;
35  uint32_t flags;
36 
37  // For non-resource actions, return the action flags
38  if (action->rsc == NULL) {
39  return action->flags;
40  }
41 
42  /* For non-clone resources, or a clone action not assigned to a node,
43  * return the flags as determined by the resource method without a node
44  * specified.
45  */
46  flags = action->rsc->cmds->action_flags(action, NULL);
47  if ((node == NULL) || !pe_rsc_is_clone(action->rsc)) {
48  return flags;
49  }
50 
51  /* Otherwise (i.e., for clone resource actions on a specific node), first
52  * remember whether the non-node-specific action is runnable.
53  */
55 
56  // Then recheck the resource method with the node
57  flags = action->rsc->cmds->action_flags(action, node);
58 
59  /* For clones in ordering constraints, the node-specific "runnable" doesn't
60  * matter, just the non-node-specific setting (i.e., is the action runnable
61  * anywhere).
62  *
63  * This applies only to runnable, and only for ordering constraints. This
64  * function shouldn't be used for other types of constraints without
65  * changes. Not very satisfying, but it's logical and appears to work well.
66  */
67  if (runnable && !pcmk_is_set(flags, pcmk_action_runnable)) {
69  }
70  return flags;
71 }
72 
91 static char *
92 action_uuid_for_ordering(const char *first_uuid,
93  const pcmk_resource_t *first_rsc)
94 {
95  guint interval_ms = 0;
96  char *uuid = NULL;
97  char *rid = NULL;
98  char *first_task_str = NULL;
99  enum action_tasks first_task = pcmk_action_unspecified;
100  enum action_tasks remapped_task = pcmk_action_unspecified;
101 
102  // Only non-notify actions for collective resources need remapping
103  if ((strstr(first_uuid, PCMK_ACTION_NOTIFY) != NULL)
104  || (first_rsc->variant < pcmk_rsc_variant_group)) {
105  goto done;
106  }
107 
108  // Only non-recurring actions need remapping
109  CRM_ASSERT(parse_op_key(first_uuid, &rid, &first_task_str, &interval_ms));
110  if (interval_ms > 0) {
111  goto done;
112  }
113 
114  first_task = text2task(first_task_str);
115  switch (first_task) {
116  case pcmk_action_stop:
117  case pcmk_action_start:
118  case pcmk_action_notify:
119  case pcmk_action_promote:
120  case pcmk_action_demote:
121  remapped_task = first_task + 1;
122  break;
123  case pcmk_action_stopped:
124  case pcmk_action_started:
127  case pcmk_action_demoted:
128  remapped_task = first_task;
129  break;
130  case pcmk_action_monitor:
132  case pcmk_action_fence:
133  break;
134  default:
135  crm_err("Unknown action '%s' in ordering", first_task_str);
136  break;
137  }
138 
139  if (remapped_task != pcmk_action_unspecified) {
140  /* If a clone or bundle has notifications enabled, the ordering will be
141  * relative to when notifications have been sent for the remapped task.
142  */
143  if (pcmk_is_set(first_rsc->flags, pcmk_rsc_notify)
144  && (pe_rsc_is_clone(first_rsc) || pe_rsc_is_bundled(first_rsc))) {
145  uuid = pcmk__notify_key(rid, "confirmed-post",
146  task2text(remapped_task));
147  } else {
148  uuid = pcmk__op_key(rid, task2text(remapped_task), 0);
149  }
150  pe_rsc_trace(first_rsc,
151  "Remapped action UUID %s to %s for ordering purposes",
152  first_uuid, uuid);
153  }
154 
155 done:
156  if (uuid == NULL) {
157  uuid = strdup(first_uuid);
158  CRM_ASSERT(uuid != NULL);
159  }
160  free(first_task_str);
161  free(rid);
162  return uuid;
163 }
164 
181 static pcmk_action_t *
182 action_for_ordering(pcmk_action_t *action)
183 {
185  pcmk_resource_t *rsc = action->rsc;
186 
187  if ((rsc != NULL) && (rsc->variant >= pcmk_rsc_variant_group)
188  && (action->uuid != NULL)) {
189  char *uuid = action_uuid_for_ordering(action->uuid, rsc);
190 
191  result = find_first_action(rsc->actions, uuid, NULL, NULL);
192  if (result == NULL) {
193  crm_warn("Not remapping %s to %s because %s does not have "
194  "remapped action", action->uuid, uuid, rsc->id);
195  result = action;
196  }
197  free(uuid);
198  }
199  return result;
200 }
201 
221 static inline uint32_t
222 update(pcmk_resource_t *rsc, pcmk_action_t *first, pcmk_action_t *then,
223  const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type,
225 {
226  return rsc->cmds->update_ordered_actions(first, then, node, flags, filter,
227  type, scheduler);
228 }
229 
243 static uint32_t
244 update_action_for_ordering_flags(pcmk_action_t *first, pcmk_action_t *then,
245  uint32_t first_flags, uint32_t then_flags,
246  pcmk__related_action_t *order,
248 {
249  uint32_t changed = pcmk__updated_none;
250 
251  /* The node will only be used for clones. If interleaved, node will be NULL,
252  * otherwise the ordering scope will be limited to the node. Normally, the
253  * whole 'then' clone should restart if 'first' is restarted, so then->node
254  * is needed.
255  */
256  pcmk_node_t *node = then->node;
257 
259  /* For unfencing, only instances of 'then' on the same node as 'first'
260  * (the unfencing operation) should restart, so reset node to
261  * first->node, at which point this case is handled like a normal
262  * pcmk__ar_first_implies_then.
263  */
267  node = first->node;
268  pe_rsc_trace(then->rsc,
269  "%s then %s: mapped pcmk__ar_first_implies_same_node_then "
270  "to pcmk__ar_first_implies_then on %s",
271  first->uuid, then->uuid, pe__node_name(node));
272  }
273 
275  if (then->rsc != NULL) {
276  changed |= update(then->rsc, first, then, node,
277  first_flags & pcmk_action_optional,
279  scheduler);
280  } else if (!pcmk_is_set(first_flags, pcmk_action_optional)
284  }
285  pe_rsc_trace(then->rsc,
286  "%s then %s: %s after pcmk__ar_first_implies_then",
287  first->uuid, then->uuid,
288  (changed? "changed" : "unchanged"));
289  }
290 
292  && (then->rsc != NULL)) {
295 
296  changed |= update(then->rsc, first, then, node, first_flags, restart,
298  pe_rsc_trace(then->rsc,
299  "%s then %s: %s after pcmk__ar_intermediate_stop",
300  first->uuid, then->uuid,
301  (changed? "changed" : "unchanged"));
302  }
303 
305  if (first->rsc != NULL) {
306  changed |= update(first->rsc, first, then, node, first_flags,
308  scheduler);
309  } else if (!pcmk_is_set(first_flags, pcmk_action_optional)
310  && pcmk_is_set(first->flags, pcmk_action_runnable)) {
313  }
314  pe_rsc_trace(then->rsc,
315  "%s then %s: %s after pcmk__ar_then_implies_first",
316  first->uuid, then->uuid,
317  (changed? "changed" : "unchanged"));
318  }
319 
321  if (then->rsc != NULL) {
322  changed |= update(then->rsc, first, then, node,
323  first_flags & pcmk_action_optional,
326  }
327  pe_rsc_trace(then->rsc,
328  "%s then %s: %s after pcmk__ar_promoted_then_implies_first",
329  first->uuid, then->uuid,
330  (changed? "changed" : "unchanged"));
331  }
332 
333  if (pcmk_is_set(order->type, pcmk__ar_min_runnable)) {
334  if (then->rsc != NULL) {
335  changed |= update(then->rsc, first, then, node, first_flags,
337  scheduler);
338 
339  } else if (pcmk_is_set(first_flags, pcmk_action_runnable)) {
340  // We have another runnable instance of "first"
341  then->runnable_before++;
342 
343  /* Mark "then" as runnable if it requires a certain number of
344  * "before" instances to be runnable, and they now are.
345  */
346  if ((then->runnable_before >= then->required_runnable_before)
347  && !pcmk_is_set(then->flags, pcmk_action_runnable)) {
348 
351  }
352  }
353  pe_rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_min_runnable",
354  first->uuid, then->uuid,
355  (changed? "changed" : "unchanged"));
356  }
357 
359  && (then->rsc != NULL)) {
360 
361  if (!pcmk_is_set(first_flags, pcmk_action_runnable)
362  && (first->rsc != NULL) && (first->rsc->running_on != NULL)) {
363 
364  pe_rsc_trace(then->rsc,
365  "%s then %s: ignoring because first is stopping",
366  first->uuid, then->uuid);
367  order->type = (enum pe_ordering) pcmk__ar_none;
368  } else {
369  changed |= update(then->rsc, first, then, node, first_flags,
372  }
373  pe_rsc_trace(then->rsc,
374  "%s then %s: %s after pcmk__ar_nested_remote_probe",
375  first->uuid, then->uuid,
376  (changed? "changed" : "unchanged"));
377  }
378 
380  if (then->rsc != NULL) {
381  changed |= update(then->rsc, first, then, node, first_flags,
384 
385  } else if (!pcmk_is_set(first_flags, pcmk_action_runnable)
387 
390  }
391  pe_rsc_trace(then->rsc,
392  "%s then %s: %s after pcmk__ar_unrunnable_first_blocks",
393  first->uuid, then->uuid,
394  (changed? "changed" : "unchanged"));
395  }
396 
398  if (then->rsc != NULL) {
399  changed |= update(then->rsc, first, then, node, first_flags,
402  }
403  pe_rsc_trace(then->rsc, "%s then %s: %s after "
404  "pcmk__ar_unmigratable_then_blocks",
405  first->uuid, then->uuid,
406  (changed? "changed" : "unchanged"));
407  }
408 
410  if (then->rsc != NULL) {
411  changed |= update(then->rsc, first, then, node, first_flags,
413  scheduler);
414  }
415  pe_rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_first_else_then",
416  first->uuid, then->uuid,
417  (changed? "changed" : "unchanged"));
418  }
419 
420  if (pcmk_is_set(order->type, pcmk__ar_ordered)) {
421  if (then->rsc != NULL) {
422  changed |= update(then->rsc, first, then, node, first_flags,
424  scheduler);
425  }
426  pe_rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_ordered",
427  first->uuid, then->uuid,
428  (changed? "changed" : "unchanged"));
429  }
430 
431  if (pcmk_is_set(order->type, pcmk__ar_asymmetric)) {
432  if (then->rsc != NULL) {
433  changed |= update(then->rsc, first, then, node, first_flags,
435  scheduler);
436  }
437  pe_rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_asymmetric",
438  first->uuid, then->uuid,
439  (changed? "changed" : "unchanged"));
440  }
441 
444  && !pcmk_is_set(first_flags, pcmk_action_optional)) {
445 
446  pe_rsc_trace(then->rsc, "%s will be in graph because %s is required",
447  then->uuid, first->uuid);
449  // Don't bother marking 'then' as changed just for this
450  }
451 
453  && !pcmk_is_set(then_flags, pcmk_action_optional)) {
454 
455  pe_rsc_trace(then->rsc, "%s will be in graph because %s is required",
456  first->uuid, then->uuid);
458  // Don't bother marking 'first' as changed just for this
459  }
460 
461  if (pcmk_any_flags_set(order->type, pcmk__ar_first_implies_then
464  && (first->rsc != NULL)
465  && !pcmk_is_set(first->rsc->flags, pcmk_rsc_managed)
468  && pcmk__str_eq(first->task, PCMK_ACTION_STOP, pcmk__str_none)) {
469 
470  if (pcmk_is_set(then->flags, pcmk_action_runnable)) {
473  }
474  pe_rsc_trace(then->rsc, "%s then %s: %s after checking whether first "
475  "is blocked, unmanaged, unrunnable stop",
476  first->uuid, then->uuid,
477  (changed? "changed" : "unchanged"));
478  }
479 
480  return changed;
481 }
482 
483 // Convenience macros for logging action properties
484 
485 #define action_type_str(flags) \
486  (pcmk_is_set((flags), pcmk_action_pseudo)? "pseudo-action" : "action")
487 
488 #define action_optional_str(flags) \
489  (pcmk_is_set((flags), pcmk_action_optional)? "optional" : "required")
490 
491 #define action_runnable_str(flags) \
492  (pcmk_is_set((flags), pcmk_action_runnable)? "runnable" : "unrunnable")
493 
494 #define action_node_str(a) \
495  (((a)->node == NULL)? "no node" : (a)->node->details->uname)
496 
504 void
507 {
508  GList *lpc = NULL;
509  uint32_t changed = pcmk__updated_none;
510  int last_flags = then->flags;
511 
512  pe_rsc_trace(then->rsc, "Updating %s %s (%s %s) on %s",
513  action_type_str(then->flags), then->uuid,
514  action_optional_str(then->flags),
516 
518  /* Initialize current known "runnable before" actions. As
519  * update_action_for_ordering_flags() is called for each of then's
520  * before actions, this number will increment as runnable 'first'
521  * actions are encountered.
522  */
523  then->runnable_before = 0;
524 
525  if (then->required_runnable_before == 0) {
526  /* @COMPAT This ordering constraint uses the deprecated
527  * "require-all=false" attribute. Treat it like "clone-min=1".
528  */
529  then->required_runnable_before = 1;
530  }
531 
532  /* The pcmk__ar_min_runnable clause of
533  * update_action_for_ordering_flags() (called below)
534  * will reset runnable if appropriate.
535  */
537  }
538 
539  for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) {
540  pcmk__related_action_t *other = lpc->data;
541  pcmk_action_t *first = other->action;
542 
543  pcmk_node_t *then_node = then->node;
544  pcmk_node_t *first_node = first->node;
545 
546  if ((first->rsc != NULL)
547  && (first->rsc->variant == pcmk_rsc_variant_group)
548  && pcmk__str_eq(first->task, PCMK_ACTION_START, pcmk__str_none)) {
549 
550  first_node = first->rsc->fns->location(first->rsc, NULL, FALSE);
551  if (first_node != NULL) {
552  pe_rsc_trace(first->rsc, "Found %s for 'first' %s",
553  pe__node_name(first_node), first->uuid);
554  }
555  }
556 
557  if ((then->rsc != NULL)
558  && (then->rsc->variant == pcmk_rsc_variant_group)
559  && pcmk__str_eq(then->task, PCMK_ACTION_START, pcmk__str_none)) {
560 
561  then_node = then->rsc->fns->location(then->rsc, NULL, FALSE);
562  if (then_node != NULL) {
563  pe_rsc_trace(then->rsc, "Found %s for 'then' %s",
564  pe__node_name(then_node), then->uuid);
565  }
566  }
567 
568  // Disable constraint if it only applies when on same node, but isn't
570  && (first_node != NULL) && (then_node != NULL)
571  && !pe__same_node(first_node, then_node)) {
572 
573  pe_rsc_trace(then->rsc,
574  "Disabled ordering %s on %s then %s on %s: "
575  "not same node",
576  other->action->uuid, pe__node_name(first_node),
577  then->uuid, pe__node_name(then_node));
578  other->type = (enum pe_ordering) pcmk__ar_none;
579  continue;
580  }
581 
583 
584  if ((first->rsc != NULL)
586  && !pcmk_is_set(then->flags, pcmk_action_optional)) {
587 
588  /* 'then' is required, so we must abandon 'first'
589  * (e.g. a required stop cancels any agent reload).
590  */
592  if (!strcmp(first->task, PCMK_ACTION_RELOAD_AGENT)) {
594  }
595  }
596 
597  if ((first->rsc != NULL) && (then->rsc != NULL)
598  && (first->rsc != then->rsc) && !is_parent(then->rsc, first->rsc)) {
599  first = action_for_ordering(first);
600  }
601  if (first != other->action) {
602  pe_rsc_trace(then->rsc, "Ordering %s after %s instead of %s",
603  then->uuid, first->uuid, other->action->uuid);
604  }
605 
606  pe_rsc_trace(then->rsc,
607  "%s (%#.6x) then %s (%#.6x): type=%#.6x node=%s",
608  first->uuid, first->flags, then->uuid, then->flags,
609  other->type, action_node_str(first));
610 
611  if (first == other->action) {
612  /* 'first' was not remapped (e.g. from 'start' to 'running'), which
613  * could mean it is a non-resource action, a primitive resource
614  * action, or already expanded.
615  */
616  uint32_t first_flags, then_flags;
617 
618  first_flags = action_flags_for_ordering(first, then_node);
619  then_flags = action_flags_for_ordering(then, first_node);
620 
621  changed |= update_action_for_ordering_flags(first, then,
622  first_flags, then_flags,
623  other, scheduler);
624 
625  /* 'first' was for a complex resource (clone, group, etc),
626  * create a new dependency if necessary
627  */
628  } else if (order_actions(first, then, other->type)) {
629  /* This was the first time 'first' and 'then' were associated,
630  * start again to get the new actions_before list
631  */
633  pe_rsc_trace(then->rsc,
634  "Disabled ordering %s then %s in favor of %s then %s",
635  other->action->uuid, then->uuid, first->uuid,
636  then->uuid);
637  other->type = (enum pe_ordering) pcmk__ar_none;
638  }
639 
640 
641  if (pcmk_is_set(changed, pcmk__updated_first)) {
642  crm_trace("Re-processing %s and its 'after' actions "
643  "because it changed", first->uuid);
644  for (GList *lpc2 = first->actions_after; lpc2 != NULL;
645  lpc2 = lpc2->next) {
646  pcmk__related_action_t *other = lpc2->data;
647 
649  }
651  }
652  }
653 
655  if (last_flags == then->flags) {
657  } else {
659  }
660  }
661 
662  if (pcmk_is_set(changed, pcmk__updated_then)) {
663  crm_trace("Re-processing %s and its 'after' actions because it changed",
664  then->uuid);
665  if (pcmk_is_set(last_flags, pcmk_action_runnable)
666  && !pcmk_is_set(then->flags, pcmk_action_runnable)) {
668  }
670  for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) {
671  pcmk__related_action_t *other = lpc->data;
672 
674  }
675  }
676 }
677 
678 static inline bool
679 is_primitive_action(const pcmk_action_t *action)
680 {
681  return (action != NULL) && (action->rsc != NULL)
682  && (action->rsc->variant == pcmk_rsc_variant_primitive);
683 }
684 
693 #define clear_action_flag_because(action, flag, reason) do { \
694  if (pcmk_is_set((action)->flags, (flag))) { \
695  pe__clear_action_flags(action, flag); \
696  if ((action)->rsc != (reason)->rsc) { \
697  char *reason_text = pe__action2reason((reason), (flag)); \
698  pe_action_set_reason((action), reason_text, false); \
699  free(reason_text); \
700  } \
701  } \
702  } while (0)
703 
714 static void
715 handle_asymmetric_ordering(const pcmk_action_t *first, pcmk_action_t *then)
716 {
717  /* Only resource actions after an unrunnable 'first' action need updates for
718  * asymmetric ordering.
719  */
720  if ((then->rsc == NULL)
721  || pcmk_is_set(first->flags, pcmk_action_runnable)) {
722  return;
723  }
724 
725  // Certain optional 'then' actions are unaffected by unrunnable 'first'
726  if (pcmk_is_set(then->flags, pcmk_action_optional)) {
727  enum rsc_role_e then_rsc_role = then->rsc->fns->state(then->rsc, TRUE);
728 
729  if ((then_rsc_role == pcmk_role_stopped)
730  && pcmk__str_eq(then->task, PCMK_ACTION_STOP, pcmk__str_none)) {
731  /* If 'then' should stop after 'first' but is already stopped, the
732  * ordering is irrelevant.
733  */
734  return;
735  } else if ((then_rsc_role >= pcmk_role_started)
736  && pcmk__str_eq(then->task, PCMK_ACTION_START, pcmk__str_none)
737  && pe__rsc_running_on_only(then->rsc, then->node)) {
738  /* Similarly if 'then' should start after 'first' but is already
739  * started on a single node.
740  */
741  return;
742  }
743  }
744 
745  // 'First' can't run, so 'then' can't either
748 }
749 
761 static void
762 handle_restart_ordering(pcmk_action_t *first, pcmk_action_t *then,
763  uint32_t filter)
764 {
765  const char *reason = NULL;
766 
767  CRM_ASSERT(is_primitive_action(first));
768  CRM_ASSERT(is_primitive_action(then));
769 
770  // We need to update the action in two cases:
771 
772  // ... if 'then' is required
773  if (pcmk_is_set(filter, pcmk_action_optional)
774  && !pcmk_is_set(then->flags, pcmk_action_optional)) {
775  reason = "restart";
776  }
777 
778  /* ... if 'then' is unrunnable action on same resource (if a resource
779  * should restart but can't start, we still want to stop)
780  */
781  if (pcmk_is_set(filter, pcmk_action_runnable)
784  && (first->rsc == then->rsc)) {
785  reason = "stop";
786  }
787 
788  if (reason == NULL) {
789  return;
790  }
791 
792  pe_rsc_trace(first->rsc, "Handling %s -> %s for %s",
793  first->uuid, then->uuid, reason);
794 
795  // Make 'first' required if it is runnable
796  if (pcmk_is_set(first->flags, pcmk_action_runnable)) {
798  }
799 
800  // Make 'first' required if 'then' is required
801  if (!pcmk_is_set(then->flags, pcmk_action_optional)) {
803  }
804 
805  // Make 'first' unmigratable if 'then' is unmigratable
808  }
809 
810  // Make 'then' unrunnable if 'first' is required but unrunnable
812  && !pcmk_is_set(first->flags, pcmk_action_runnable)) {
814  }
815 }
816 
839 uint32_t
841  const pcmk_node_t *node, uint32_t flags,
842  uint32_t filter, uint32_t type,
844 {
845  uint32_t changed = pcmk__updated_none;
846  uint32_t then_flags = 0U;
847  uint32_t first_flags = 0U;
848 
849  CRM_ASSERT((first != NULL) && (then != NULL) && (scheduler != NULL));
850 
851  then_flags = then->flags;
852  first_flags = first->flags;
854  handle_asymmetric_ordering(first, then);
855  }
856 
858  && !pcmk_is_set(then_flags, pcmk_action_optional)) {
859  // Then is required, and implies first should be, too
860 
861  if (pcmk_is_set(filter, pcmk_action_optional)
863  && pcmk_is_set(first_flags, pcmk_action_optional)) {
865  }
866 
870  }
871  }
872 
874  && (then->rsc != NULL) && (then->rsc->role == pcmk_role_promoted)
876  && !pcmk_is_set(then->flags, pcmk_action_optional)) {
877 
879 
883  }
884  }
885 
887  && pcmk_is_set(filter, pcmk_action_optional)) {
888 
889  if (!pcmk_all_flags_set(then->flags, pcmk_action_migratable
892  }
893 
894  if (!pcmk_is_set(then->flags, pcmk_action_optional)) {
896  }
897  }
898 
901  && !pcmk_is_set(first->flags, pcmk_action_runnable)) {
902 
905  }
906 
911 
914  }
915 
921 
923  }
924 
926  handle_restart_ordering(first, then, filter);
927  }
928 
929  if (then_flags != then->flags) {
931  pe_rsc_trace(then->rsc,
932  "%s on %s: flags are now %#.6x (was %#.6x) "
933  "because of 'first' %s (%#.6x)",
934  then->uuid, pe__node_name(then->node),
935  then->flags, then_flags, first->uuid, first->flags);
936 
937  if ((then->rsc != NULL) && (then->rsc->parent != NULL)) {
938  // Required to handle "X_stop then X_start" for cloned groups
940  }
941  }
942 
943  if (first_flags != first->flags) {
945  pe_rsc_trace(first->rsc,
946  "%s on %s: flags are now %#.6x (was %#.6x) "
947  "because of 'then' %s (%#.6x)",
948  first->uuid, pe__node_name(first->node),
949  first->flags, first_flags, then->uuid, then->flags);
950  }
951 
952  return changed;
953 }
954 
963 void
964 pcmk__log_action(const char *pre_text, const pcmk_action_t *action,
965  bool details)
966 {
967  const char *node_uname = NULL;
968  const char *node_uuid = NULL;
969  const char *desc = NULL;
970 
971  CRM_CHECK(action != NULL, return);
972 
973  if (!pcmk_is_set(action->flags, pcmk_action_pseudo)) {
974  if (action->node != NULL) {
975  node_uname = action->node->details->uname;
976  node_uuid = action->node->details->id;
977  } else {
978  node_uname = "<none>";
979  }
980  }
981 
982  switch (text2task(action->task)) {
983  case pcmk_action_fence:
985  if (pcmk_is_set(action->flags, pcmk_action_pseudo)) {
986  desc = "Pseudo ";
987  } else if (pcmk_is_set(action->flags, pcmk_action_optional)) {
988  desc = "Optional ";
989  } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
990  desc = "!!Non-Startable!! ";
991  } else {
992  desc = "(Provisional) ";
993  }
994  crm_trace("%s%s%sAction %d: %s%s%s%s%s%s",
995  ((pre_text == NULL)? "" : pre_text),
996  ((pre_text == NULL)? "" : ": "),
997  desc, action->id, action->uuid,
998  (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
999  (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
1000  (node_uuid? ")" : ""));
1001  break;
1002  default:
1003  if (pcmk_is_set(action->flags, pcmk_action_optional)) {
1004  desc = "Optional ";
1005  } else if (pcmk_is_set(action->flags, pcmk_action_pseudo)) {
1006  desc = "Pseudo ";
1007  } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
1008  desc = "!!Non-Startable!! ";
1009  } else {
1010  desc = "(Provisional) ";
1011  }
1012  crm_trace("%s%s%sAction %d: %s %s%s%s%s%s%s",
1013  ((pre_text == NULL)? "" : pre_text),
1014  ((pre_text == NULL)? "" : ": "),
1015  desc, action->id, action->uuid,
1016  (action->rsc? action->rsc->id : "<none>"),
1017  (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
1018  (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
1019  (node_uuid? ")" : ""));
1020  break;
1021  }
1022 
1023  if (details) {
1024  const GList *iter = NULL;
1025  const pcmk__related_action_t *other = NULL;
1026 
1027  crm_trace("\t\t====== Preceding Actions");
1028  for (iter = action->actions_before; iter != NULL; iter = iter->next) {
1029  other = (const pcmk__related_action_t *) iter->data;
1030  pcmk__log_action("\t\t", other->action, false);
1031  }
1032  crm_trace("\t\t====== Subsequent Actions");
1033  for (iter = action->actions_after; iter != NULL; iter = iter->next) {
1034  other = (const pcmk__related_action_t *) iter->data;
1035  pcmk__log_action("\t\t", other->action, false);
1036  }
1037  crm_trace("\t\t====== End");
1038 
1039  } else {
1040  crm_trace("\t\t(before=%d, after=%d)",
1041  g_list_length(action->actions_before),
1042  g_list_length(action->actions_after));
1043  }
1044 }
1045 
1054 pcmk_action_t *
1056 {
1057  char *shutdown_id = NULL;
1058  pcmk_action_t *shutdown_op = NULL;
1059 
1060  CRM_ASSERT(node != NULL);
1061 
1062  shutdown_id = crm_strdup_printf("%s-%s", PCMK_ACTION_DO_SHUTDOWN,
1063  node->details->uname);
1064 
1065  shutdown_op = custom_action(NULL, shutdown_id, PCMK_ACTION_DO_SHUTDOWN,
1066  node, FALSE, node->details->data_set);
1067 
1068  pcmk__order_stops_before_shutdown(node, shutdown_op);
1070  return shutdown_op;
1071 }
1072 
1084 static void
1085 add_op_digest_to_xml(const lrmd_event_data_t *op, xmlNode *update)
1086 {
1087  char *digest = NULL;
1088  xmlNode *args_xml = NULL;
1089 
1090  if (op->params == NULL) {
1091  return;
1092  }
1093  args_xml = create_xml_node(NULL, XML_TAG_PARAMS);
1094  g_hash_table_foreach(op->params, hash2field, args_xml);
1095  pcmk__filter_op_for_digest(args_xml);
1096  digest = calculate_operation_digest(args_xml, NULL);
1097  crm_xml_add(update, XML_LRM_ATTR_OP_DIGEST, digest);
1098  free_xml(args_xml);
1099  free(digest);
1100 }
1101 
1102 #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
1103 
1117 xmlNode *
1119  const char *caller_version, int target_rc,
1120  const char *node, const char *origin)
1121 {
1122  char *key = NULL;
1123  char *magic = NULL;
1124  char *op_id = NULL;
1125  char *op_id_additional = NULL;
1126  char *local_user_data = NULL;
1127  const char *exit_reason = NULL;
1128 
1129  xmlNode *xml_op = NULL;
1130  const char *task = NULL;
1131 
1132  CRM_CHECK(op != NULL, return NULL);
1133  crm_trace("Creating history XML for %s-interval %s action for %s on %s "
1134  "(DC version: %s, origin: %s)",
1136  ((node == NULL)? "no node" : node), caller_version, origin);
1137 
1138  task = op->op_type;
1139 
1140  /* Record a successful agent reload as a start, and a failed one as a
1141  * monitor, to make life easier for the scheduler when determining the
1142  * current state.
1143  *
1144  * @COMPAT We should check "reload" here only if the operation was for a
1145  * pre-OCF-1.1 resource agent, but we don't know that here, and we should
1146  * only ever get results for actions scheduled by us, so we can reasonably
1147  * assume any "reload" is actually a pre-1.1 agent reload.
1148  */
1150  NULL)) {
1151  if (op->op_status == PCMK_EXEC_DONE) {
1152  task = PCMK_ACTION_START;
1153  } else {
1154  task = PCMK_ACTION_MONITOR;
1155  }
1156  }
1157 
1158  key = pcmk__op_key(op->rsc_id, task, op->interval_ms);
1159  if (pcmk__str_eq(task, PCMK_ACTION_NOTIFY, pcmk__str_none)) {
1160  const char *n_type = crm_meta_value(op->params, "notify_type");
1161  const char *n_task = crm_meta_value(op->params, "notify_operation");
1162 
1163  CRM_LOG_ASSERT(n_type != NULL);
1164  CRM_LOG_ASSERT(n_task != NULL);
1165  op_id = pcmk__notify_key(op->rsc_id, n_type, n_task);
1166 
1167  if (op->op_status != PCMK_EXEC_PENDING) {
1168  /* Ignore notify errors.
1169  *
1170  * @TODO It might be better to keep the correct result here, and
1171  * ignore it in process_graph_event().
1172  */
1174  }
1175 
1176  /* Migration history is preserved separately, which usually matters for
1177  * multiple nodes and is important for future cluster transitions.
1178  */
1180  PCMK_ACTION_MIGRATE_FROM, NULL)) {
1181  op_id = strdup(key);
1182 
1183  } else if (did_rsc_op_fail(op, target_rc)) {
1184  op_id = pcmk__op_key(op->rsc_id, "last_failure", 0);
1185  if (op->interval_ms == 0) {
1186  // Ensure 'last' gets updated, in case record-pending is true
1187  op_id_additional = pcmk__op_key(op->rsc_id, "last", 0);
1188  }
1189  exit_reason = op->exit_reason;
1190 
1191  } else if (op->interval_ms > 0) {
1192  op_id = strdup(key);
1193 
1194  } else {
1195  op_id = pcmk__op_key(op->rsc_id, "last", 0);
1196  }
1197 
1198  again:
1200  if (xml_op == NULL) {
1202  }
1203 
1204  if (op->user_data == NULL) {
1205  crm_debug("Generating fake transition key for: " PCMK__OP_FMT
1206  " %d from %s", op->rsc_id, op->op_type, op->interval_ms,
1207  op->call_id, origin);
1208  local_user_data = pcmk__transition_key(-1, op->call_id, target_rc,
1209  FAKE_TE_ID);
1210  op->user_data = local_user_data;
1211  }
1212 
1213  if (magic == NULL) {
1214  magic = crm_strdup_printf("%d:%d;%s", op->op_status, op->rc,
1215  (const char *) op->user_data);
1216  }
1217 
1218  crm_xml_add(xml_op, XML_ATTR_ID, op_id);
1219  crm_xml_add(xml_op, XML_LRM_ATTR_TASK_KEY, key);
1220  crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task);
1221  crm_xml_add(xml_op, XML_ATTR_ORIGIN, origin);
1222  crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, caller_version);
1224  crm_xml_add(xml_op, XML_ATTR_TRANSITION_MAGIC, magic);
1225  crm_xml_add(xml_op, XML_LRM_ATTR_EXIT_REASON, pcmk__s(exit_reason, ""));
1226  crm_xml_add(xml_op, XML_LRM_ATTR_TARGET, node); // For context during triage
1227 
1229  crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op->rc);
1232 
1233  if (compare_version("2.1", caller_version) <= 0) {
1234  if (op->t_run || op->t_rcchange || op->exec_time || op->queue_time) {
1235  crm_trace("Timing data (" PCMK__OP_FMT
1236  "): last=%u change=%u exec=%u queue=%u",
1237  op->rsc_id, op->op_type, op->interval_ms,
1238  op->t_run, op->t_rcchange, op->exec_time, op->queue_time);
1239 
1240  if ((op->interval_ms != 0) && (op->t_rcchange != 0)) {
1241  // Recurring ops may have changed rc after initial run
1243  (long long) op->t_rcchange);
1244  } else {
1246  (long long) op->t_run);
1247  }
1248 
1251  }
1252  }
1253 
1255  PCMK_ACTION_MIGRATE_FROM, NULL)) {
1256  /*
1257  * Record migrate_source and migrate_target always for migrate ops.
1258  */
1259  const char *name = XML_LRM_ATTR_MIGRATE_SOURCE;
1260 
1261  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1262 
1264  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1265  }
1266 
1267  add_op_digest_to_xml(op, xml_op);
1268 
1269  if (op_id_additional) {
1270  free(op_id);
1271  op_id = op_id_additional;
1272  op_id_additional = NULL;
1273  goto again;
1274  }
1275 
1276  if (local_user_data) {
1277  free(local_user_data);
1278  op->user_data = NULL;
1279  }
1280  free(magic);
1281  free(op_id);
1282  free(key);
1283  return xml_op;
1284 }
1285 
1300 bool
1302 {
1303  // Only resource actions taking place on resource's lock node are locked
1304  if ((action == NULL) || (action->rsc == NULL)
1305  || !pe__same_node(action->node, action->rsc->lock_node)) {
1306  return false;
1307  }
1308 
1309  /* During shutdown, only stops are locked (otherwise, another action such as
1310  * a demote would cause the controller to clear the lock)
1311  */
1312  if (action->node->details->shutdown && (action->task != NULL)
1313  && (strcmp(action->task, PCMK_ACTION_STOP) != 0)) {
1314  return false;
1315  }
1316 
1317  return true;
1318 }
1319 
1320 /* lowest to highest */
1321 static gint
1322 sort_action_id(gconstpointer a, gconstpointer b)
1323 {
1324  const pcmk__related_action_t *action_wrapper2 = a;
1325  const pcmk__related_action_t *action_wrapper1 = b;
1326 
1327  if (a == NULL) {
1328  return 1;
1329  }
1330  if (b == NULL) {
1331  return -1;
1332  }
1333  if (action_wrapper1->action->id < action_wrapper2->action->id) {
1334  return 1;
1335  }
1336  if (action_wrapper1->action->id > action_wrapper2->action->id) {
1337  return -1;
1338  }
1339  return 0;
1340 }
1341 
1348 void
1350 {
1351  GList *item = NULL;
1352  GList *next = NULL;
1353  pcmk__related_action_t *last_input = NULL;
1354 
1355  action->actions_before = g_list_sort(action->actions_before,
1356  sort_action_id);
1357  for (item = action->actions_before; item != NULL; item = next) {
1358  pcmk__related_action_t *input = item->data;
1359 
1360  next = item->next;
1361  if ((last_input != NULL)
1362  && (input->action->id == last_input->action->id)) {
1363  crm_trace("Input %s (%d) duplicate skipped for action %s (%d)",
1364  input->action->uuid, input->action->id,
1365  action->uuid, action->id);
1366 
1367  /* For the purposes of scheduling, the ordering flags no longer
1368  * matter, but crm_simulate looks at certain ones when creating a
1369  * dot graph. Combining the flags is sufficient for that purpose.
1370  */
1371  last_input->type |= input->type;
1372  if (input->state == pe_link_dumped) {
1373  last_input->state = pe_link_dumped;
1374  }
1375 
1376  free(item->data);
1377  action->actions_before = g_list_delete_link(action->actions_before,
1378  item);
1379  } else {
1380  last_input = input;
1381  input->state = pe_link_not_dumped;
1382  }
1383  }
1384 }
1385 
1392 void
1394 {
1395  pcmk__output_t *out = scheduler->priv;
1396 
1397  // Output node (non-resource) actions
1398  for (GList *iter = scheduler->actions; iter != NULL; iter = iter->next) {
1399  char *node_name = NULL;
1400  char *task = NULL;
1401  pcmk_action_t *action = (pcmk_action_t *) iter->data;
1402 
1403  if (action->rsc != NULL) {
1404  continue; // Resource actions will be output later
1405 
1406  } else if (pcmk_is_set(action->flags, pcmk_action_optional)) {
1407  continue; // This action was not scheduled
1408  }
1409 
1410  if (pcmk__str_eq(action->task, PCMK_ACTION_DO_SHUTDOWN,
1411  pcmk__str_none)) {
1412  task = strdup("Shutdown");
1413 
1414  } else if (pcmk__str_eq(action->task, PCMK_ACTION_STONITH,
1415  pcmk__str_none)) {
1416  const char *op = g_hash_table_lookup(action->meta,
1417  "stonith_action");
1418 
1419  task = crm_strdup_printf("Fence (%s)", op);
1420 
1421  } else {
1422  continue; // Don't display other node action types
1423  }
1424 
1425  if (pe__is_guest_node(action->node)) {
1426  const pcmk_resource_t *remote = action->node->details->remote_rsc;
1427 
1428  node_name = crm_strdup_printf("%s (resource: %s)",
1429  pe__node_name(action->node),
1430  remote->container->id);
1431  } else if (action->node != NULL) {
1432  node_name = crm_strdup_printf("%s", pe__node_name(action->node));
1433  }
1434 
1435  out->message(out, "node-action", task, node_name, action->reason);
1436 
1437  free(node_name);
1438  free(task);
1439  }
1440 
1441  // Output resource actions
1442  for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
1443  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
1444 
1445  rsc->cmds->output_actions(rsc);
1446  }
1447 }
1448 
1458 static const char *
1459 task_for_digest(const char *task, guint interval_ms)
1460 {
1461  /* Certain actions need to be compared against the parameters used to start
1462  * the resource.
1463  */
1464  if ((interval_ms == 0)
1466  PCMK_ACTION_PROMOTE, NULL)) {
1467  task = PCMK_ACTION_START;
1468  }
1469  return task;
1470 }
1471 
1489 static bool
1490 only_sanitized_changed(const xmlNode *xml_op,
1491  const op_digest_cache_t *digest_data,
1492  const pcmk_scheduler_t *scheduler)
1493 {
1494  const char *digest_secure = NULL;
1495 
1497  // The scheduler is not being run as a simulation
1498  return false;
1499  }
1500 
1501  digest_secure = crm_element_value(xml_op, XML_LRM_ATTR_SECURE_DIGEST);
1502 
1503  return (digest_data->rc != pcmk__digest_match) && (digest_secure != NULL)
1504  && (digest_data->digest_secure_calc != NULL)
1505  && (strcmp(digest_data->digest_secure_calc, digest_secure) == 0);
1506 }
1507 
1517 static void
1518 force_restart(pcmk_resource_t *rsc, const char *task, guint interval_ms,
1519  pcmk_node_t *node)
1520 {
1521  char *key = pcmk__op_key(rsc->id, task, interval_ms);
1522  pcmk_action_t *required = custom_action(rsc, key, task, NULL, FALSE,
1523  rsc->cluster);
1524 
1525  pe_action_set_reason(required, "resource definition change", true);
1526  trigger_unfencing(rsc, node, "Device parameters changed", NULL,
1527  rsc->cluster);
1528 }
1529 
1537 static void
1538 schedule_reload(gpointer data, gpointer user_data)
1539 {
1540  pcmk_resource_t *rsc = data;
1541  const pcmk_node_t *node = user_data;
1542  pcmk_action_t *reload = NULL;
1543 
1544  // For collective resources, just call recursively for children
1545  if (rsc->variant > pcmk_rsc_variant_primitive) {
1546  g_list_foreach(rsc->children, schedule_reload, user_data);
1547  return;
1548  }
1549 
1550  // Skip the reload in certain situations
1551  if ((node == NULL)
1553  || pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
1554  pe_rsc_trace(rsc, "Skip reload of %s:%s%s %s",
1555  rsc->id,
1556  pcmk_is_set(rsc->flags, pcmk_rsc_managed)? "" : " unmanaged",
1557  pcmk_is_set(rsc->flags, pcmk_rsc_failed)? " failed" : "",
1558  (node == NULL)? "inactive" : node->details->uname);
1559  return;
1560  }
1561 
1562  /* If a resource's configuration changed while a start was pending,
1563  * force a full restart instead of a reload.
1564  */
1566  pe_rsc_trace(rsc, "%s: preventing agent reload because start pending",
1567  rsc->id);
1568  custom_action(rsc, stop_key(rsc), PCMK_ACTION_STOP, node, FALSE,
1569  rsc->cluster);
1570  return;
1571  }
1572 
1573  // Schedule the reload
1575  reload = custom_action(rsc, reload_key(rsc), PCMK_ACTION_RELOAD_AGENT, node,
1576  FALSE, rsc->cluster);
1577  pe_action_set_reason(reload, "resource definition change", FALSE);
1578 
1579  // Set orderings so that a required stop or demote cancels the reload
1580  pcmk__new_ordering(NULL, NULL, reload, rsc, stop_key(rsc), NULL,
1582  rsc->cluster);
1583  pcmk__new_ordering(NULL, NULL, reload, rsc, demote_key(rsc), NULL,
1585  rsc->cluster);
1586 }
1587 
1602 bool
1604  const xmlNode *xml_op)
1605 {
1606  guint interval_ms = 0;
1607  const char *task = NULL;
1608  const op_digest_cache_t *digest_data = NULL;
1609 
1610  CRM_CHECK((rsc != NULL) && (node != NULL) && (xml_op != NULL),
1611  return false);
1612 
1613  task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
1614  CRM_CHECK(task != NULL, return false);
1615 
1616  crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
1617 
1618  // If this is a recurring action, check whether it has been orphaned
1619  if (interval_ms > 0) {
1620  if (pcmk__find_action_config(rsc, task, interval_ms, false) != NULL) {
1621  pe_rsc_trace(rsc, "%s-interval %s for %s on %s is in configuration",
1622  pcmk__readable_interval(interval_ms), task, rsc->id,
1623  pe__node_name(node));
1624  } else if (pcmk_is_set(rsc->cluster->flags,
1627  crm_element_value(xml_op,
1629  task, interval_ms, node, "orphan");
1630  return true;
1631  } else {
1632  pe_rsc_debug(rsc, "%s-interval %s for %s on %s is orphaned",
1633  pcmk__readable_interval(interval_ms), task, rsc->id,
1634  pe__node_name(node));
1635  return true;
1636  }
1637  }
1638 
1639  crm_trace("Checking %s-interval %s for %s on %s for configuration changes",
1640  pcmk__readable_interval(interval_ms), task, rsc->id,
1641  pe__node_name(node));
1642  task = task_for_digest(task, interval_ms);
1643  digest_data = rsc_action_digest_cmp(rsc, xml_op, node, rsc->cluster);
1644 
1645  if (only_sanitized_changed(xml_op, digest_data, rsc->cluster)) {
1646  if (!pcmk__is_daemon && (rsc->cluster->priv != NULL)) {
1647  pcmk__output_t *out = rsc->cluster->priv;
1648 
1649  out->info(out,
1650  "Only 'private' parameters to %s-interval %s for %s "
1651  "on %s changed: %s",
1652  pcmk__readable_interval(interval_ms), task, rsc->id,
1653  pe__node_name(node),
1655  }
1656  return false;
1657  }
1658 
1659  switch (digest_data->rc) {
1660  case pcmk__digest_restart:
1661  crm_log_xml_debug(digest_data->params_restart, "params:restart");
1662  force_restart(rsc, task, interval_ms, node);
1663  return true;
1664 
1665  case pcmk__digest_unknown:
1666  case pcmk__digest_mismatch:
1667  // Changes that can potentially be handled by an agent reload
1668 
1669  if (interval_ms > 0) {
1670  /* Recurring actions aren't reloaded per se, they are just
1671  * re-scheduled so the next run uses the new parameters.
1672  * The old instance will be cancelled automatically.
1673  */
1674  crm_log_xml_debug(digest_data->params_all, "params:reschedule");
1675  pcmk__reschedule_recurring(rsc, task, interval_ms, node);
1676 
1677  } else if (crm_element_value(xml_op,
1678  XML_LRM_ATTR_RESTART_DIGEST) != NULL) {
1679  // Agent supports reload, so use it
1680  trigger_unfencing(rsc, node,
1681  "Device parameters changed (reload)", NULL,
1682  rsc->cluster);
1683  crm_log_xml_debug(digest_data->params_all, "params:reload");
1684  schedule_reload((gpointer) rsc, (gpointer) node);
1685 
1686  } else {
1687  pe_rsc_trace(rsc,
1688  "Restarting %s "
1689  "because agent doesn't support reload", rsc->id);
1690  crm_log_xml_debug(digest_data->params_restart,
1691  "params:restart");
1692  force_restart(rsc, task, interval_ms, node);
1693  }
1694  return true;
1695 
1696  default:
1697  break;
1698  }
1699  return false;
1700 }
1701 
1710 static GList *
1711 rsc_history_as_list(const xmlNode *rsc_entry, int *start_index, int *stop_index)
1712 {
1713  GList *ops = NULL;
1714 
1715  for (xmlNode *rsc_op = first_named_child(rsc_entry, XML_LRM_TAG_RSC_OP);
1716  rsc_op != NULL; rsc_op = crm_next_same_xml(rsc_op)) {
1717  ops = g_list_prepend(ops, rsc_op);
1718  }
1719  ops = g_list_sort(ops, sort_op_by_callid);
1720  calculate_active_ops(ops, start_index, stop_index);
1721  return ops;
1722 }
1723 
1738 static void
1739 process_rsc_history(const xmlNode *rsc_entry, pcmk_resource_t *rsc,
1740  pcmk_node_t *node)
1741 {
1742  int offset = -1;
1743  int stop_index = 0;
1744  int start_index = 0;
1745  GList *sorted_op_list = NULL;
1746 
1747  if (pcmk_is_set(rsc->flags, pcmk_rsc_removed)) {
1748  if (pe_rsc_is_anon_clone(pe__const_top_resource(rsc, false))) {
1749  pe_rsc_trace(rsc,
1750  "Skipping configuration check "
1751  "for orphaned clone instance %s",
1752  rsc->id);
1753  } else {
1754  pe_rsc_trace(rsc,
1755  "Skipping configuration check and scheduling clean-up "
1756  "for orphaned resource %s", rsc->id);
1757  pcmk__schedule_cleanup(rsc, node, false);
1758  }
1759  return;
1760  }
1761 
1762  if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
1763  if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, false)) {
1764  pcmk__schedule_cleanup(rsc, node, false);
1765  }
1766  pe_rsc_trace(rsc,
1767  "Skipping configuration check for %s "
1768  "because no longer active on %s",
1769  rsc->id, pe__node_name(node));
1770  return;
1771  }
1772 
1773  pe_rsc_trace(rsc, "Checking for configuration changes for %s on %s",
1774  rsc->id, pe__node_name(node));
1775 
1776  if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, true)) {
1777  pcmk__schedule_cleanup(rsc, node, false);
1778  }
1779 
1780  sorted_op_list = rsc_history_as_list(rsc_entry, &start_index, &stop_index);
1781  if (start_index < stop_index) {
1782  return; // Resource is stopped
1783  }
1784 
1785  for (GList *iter = sorted_op_list; iter != NULL; iter = iter->next) {
1786  xmlNode *rsc_op = (xmlNode *) iter->data;
1787  const char *task = NULL;
1788  guint interval_ms = 0;
1789 
1790  if (++offset < start_index) {
1791  // Skip actions that happened before a start
1792  continue;
1793  }
1794 
1795  task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
1796  crm_element_value_ms(rsc_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
1797 
1798  if ((interval_ms > 0)
1800  || node->details->maintenance)) {
1801  // Maintenance mode cancels recurring operations
1803  crm_element_value(rsc_op,
1805  task, interval_ms, node, "maintenance mode");
1806 
1807  } else if ((interval_ms > 0)
1811  PCMK_ACTION_MIGRATE_FROM, NULL)) {
1812  /* If a resource operation failed, and the operation's definition
1813  * has changed, clear any fail count so they can be retried fresh.
1814  */
1815 
1816  if (pe__bundle_needs_remote_name(rsc)) {
1817  /* We haven't assigned resources to nodes yet, so if the
1818  * REMOTE_CONTAINER_HACK is used, we may calculate the digest
1819  * based on the literal "#uname" value rather than the properly
1820  * substituted value. That would mistakenly make the action
1821  * definition appear to have been changed. Defer the check until
1822  * later in this case.
1823  */
1824  pe__add_param_check(rsc_op, rsc, node, pcmk__check_active,
1825  rsc->cluster);
1826 
1827  } else if (pcmk__check_action_config(rsc, node, rsc_op)
1828  && (pe_get_failcount(node, rsc, NULL, pcmk__fc_effective,
1829  NULL) != 0)) {
1830  pe__clear_failcount(rsc, node, "action definition changed",
1831  rsc->cluster);
1832  }
1833  }
1834  }
1835  g_list_free(sorted_op_list);
1836 }
1837 
1851 static void
1852 process_node_history(pcmk_node_t *node, const xmlNode *lrm_rscs)
1853 {
1854  crm_trace("Processing node history for %s", pe__node_name(node));
1855  for (const xmlNode *rsc_entry = first_named_child(lrm_rscs,
1857  rsc_entry != NULL; rsc_entry = crm_next_same_xml(rsc_entry)) {
1858 
1859  if (rsc_entry->children != NULL) {
1860  GList *result = pcmk__rscs_matching_id(ID(rsc_entry),
1861  node->details->data_set);
1862 
1863  for (GList *iter = result; iter != NULL; iter = iter->next) {
1864  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
1865 
1866  if (rsc->variant == pcmk_rsc_variant_primitive) {
1867  process_rsc_history(rsc_entry, rsc, node);
1868  }
1869  }
1870  g_list_free(result);
1871  }
1872  }
1873 }
1874 
1875 // XPath to find a node's resource history
1876 #define XPATH_NODE_HISTORY "/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS \
1877  "/" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']" \
1878  "/" XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES
1879 
1892 void
1894 {
1895  crm_trace("Check resource and action configuration for changes");
1896 
1897  /* Rather than iterate through the status section, iterate through the nodes
1898  * and search for the appropriate status subsection for each. This skips
1899  * orphaned nodes and lets us eliminate some cases before searching the XML.
1900  */
1901  for (GList *iter = scheduler->nodes; iter != NULL; iter = iter->next) {
1902  pcmk_node_t *node = (pcmk_node_t *) iter->data;
1903 
1904  /* Don't bother checking actions for a node that can't run actions ...
1905  * unless it's in maintenance mode, in which case we still need to
1906  * cancel any existing recurring monitors.
1907  */
1908  if (node->details->maintenance
1909  || pcmk__node_available(node, false, false)) {
1910 
1911  char *xpath = NULL;
1912  xmlNode *history = NULL;
1913 
1915  history = get_xpath_object(xpath, scheduler->input, LOG_NEVER);
1916  free(xpath);
1917 
1918  process_node_history(node, history);
1919  }
1920  }
1921 }
pcmk_assignment_methods_t * cmds
Resource assignment methods.
Definition: resources.h:417
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
Definition: complex.c:962
enum pe_link_state state
Definition: actions.h:383
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:238
Whether resource has clone notifications enabled.
Definition: resources.h:115
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:326
Demoted.
Definition: actions.h:98
const char * task2text(enum action_tasks task)
Definition: common.c:405
Relation applies only if actions are on same node.
void trigger_unfencing(pcmk_resource_t *rsc, pcmk_node_t *node, const char *reason, pcmk_action_t *dependency, pcmk_scheduler_t *scheduler)
Definition: utils.c:581
&#39;then&#39; is runnable (and migratable) only if &#39;first&#39; is runnable
pcmk_scheduler_t * cluster
Cluster that resource is part of.
Definition: resources.h:412
void(* output_actions)(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__schedule_cleanup(pcmk_resource_t *rsc, const pcmk_node_t *node, bool optional)
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:36
char data[0]
Definition: cpg.c:55
void pcmk__filter_op_for_digest(xmlNode *param_set)
Definition: actions.c:344
Whether action should not be executed.
Definition: actions.h:244
User-configured asymmetric ordering.
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, int current)
List nodes where a resource (or any of its children) is.
Definition: resources.h:339
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:76
const char * user_data
Definition: lrmd_events.h:45
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:700
int runnable_before
For Pacemaker use only.
Definition: actions.h:420
xmlNode * pcmk__xe_match(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:429
const char * rsc_id
Definition: lrmd_events.h:41
Monitor.
Definition: actions.h:81
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:371
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:415
G_GNUC_INTERNAL void pcmk__new_ordering(pcmk_resource_t *first_rsc, char *first_task, pcmk_action_t *first_action, pcmk_resource_t *then_rsc, char *then_task, pcmk_action_t *then_action, uint32_t flags, pcmk_scheduler_t *sched)
Stopped.
Definition: roles.h:29
const char * name
Definition: cib.c:26
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:933
int(* message)(pcmk__output_t *out, const char *message_id,...)
#define clear_action_flag_because(action, flag, reason)
pcmk_action_t * action
Definition: actions.h:385
enum rsc_role_e role
Resource&#39;s current role.
Definition: resources.h:468
#define PCMK__OP_FMT
printf-style format to create operation key from resource, action, interval
Notify.
Definition: actions.h:91
GList * children
Resource&#39;s child resources, if any.
Definition: resources.h:475
enum pcmk__digest_result rc
Definition: internal.h:455
unsigned int queue_time
Definition: lrmd_events.h:81
void pcmk__deduplicate_action_inputs(pcmk_action_t *action)
gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, uint32_t flags)
Definition: utils.c:450
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2484
enum rsc_role_e(* state)(const pcmk_resource_t *rsc, gboolean current)
Get resource&#39;s current or assigned role.
Definition: resources.h:327
pe_ordering
Definition: actions.h:346
If &#39;first&#39; is unrunnable, &#39;then&#39; becomes a real, unmigratable action.
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:349
#define reload_key(rsc)
Definition: internal.h:383
Implementation of pcmk_action_t.
Definition: actions.h:390
void pcmk__handle_rsc_config_changes(pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL bool pcmk__rsc_agent_changed(pcmk_resource_t *rsc, pcmk_node_t *node, const xmlNode *rsc_entry, bool active_on_node)
#define PCMK_ACTION_MONITOR
Definition: actions.h:59
#define XML_RSC_OP_T_EXEC
Definition: msg_xml.h:327
const char * crm_meta_value(GHashTable *hash, const char *field)
Definition: utils.c:490
G_GNUC_INTERNAL void pcmk__block_colocation_dependents(pcmk_action_t *action)
Whether resource, its node, or entire cluster is in maintenance mode.
Definition: resources.h:181
op_digest_cache_t * rsc_action_digest_cmp(pcmk_resource_t *rsc, const xmlNode *xml_op, pcmk_node_t *node, pcmk_scheduler_t *scheduler)
Definition: pe_digest.c:389
#define XML_LRM_TAG_RESOURCE
Definition: msg_xml.h:278
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:302
#define XML_LRM_ATTR_OP_DIGEST
Definition: msg_xml.h:319
void pe_action_set_reason(pcmk_action_t *action, const char *reason, bool overwrite)
Definition: pe_actions.c:1639
#define PCMK_ACTION_MIGRATE_TO
Definition: actions.h:58
#define PCMK_ACTION_DO_SHUTDOWN
Definition: actions.h:51
Promoted.
Definition: roles.h:32
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
Definition: pe_actions.c:1815
unsigned int t_rcchange
Definition: lrmd_events.h:75
action_tasks
Possible actions (including some pseudo-actions)
Definition: actions.h:79
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)
enum action_tasks text2task(const char *task)
Definition: common.c:360
GList * actions
Scheduled actions.
Definition: scheduler.h:204
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:222
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
If &#39;first&#39; is required, &#39;then&#39; action for instance on same node is.
#define PCMK_ACTION_RELOAD
Definition: actions.h:68
xmlNode * params_restart
Definition: internal.h:458
Group resource.
Definition: resources.h:35
pcmk_action_t * pe__clear_failcount(pcmk_resource_t *rsc, const pcmk_node_t *node, const char *reason, pcmk_scheduler_t *scheduler)
Schedule a controller operation to clear a fail count.
Definition: failcounts.c:453
enum crm_ais_msg_types type
Definition: cpg.c:48
int id
Counter to identify action.
Definition: actions.h:391
#define demote_key(rsc)
Definition: internal.h:394
enum ocf_exitcode rc
Definition: lrmd_events.h:63
pcmk_scheduler_t * data_set
Cluster that node is part of.
Definition: nodes.h:126
pcmk_resource_t * container
Resource containing this one, if any.
Definition: resources.h:480
#define XML_RSC_OP_T_QUEUE
Definition: msg_xml.h:328
Implementation of pcmk_scheduler_t.
Definition: scheduler.h:172
#define LOG_NEVER
Definition: logging.h:48
#define pe__set_raw_action_flags(action_flags, action_name, flags_to_set)
Definition: internal.h:94
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:211
int pe_get_failcount(const pcmk_node_t *node, pcmk_resource_t *rsc, time_t *last_failure, uint32_t flags, const xmlNode *xml_op)
Definition: failcounts.c:360
G_GNUC_INTERNAL bool pcmk__node_available(const pcmk_node_t *node, bool consider_score, bool consider_guest)
const char * action
Definition: pcmk_fence.c:30
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:64
GList * resources
Resources in cluster.
Definition: scheduler.h:196
unsigned int exec_time
Definition: lrmd_events.h:78
GList * nodes
Nodes in cluster.
Definition: scheduler.h:195
#define XML_ATTR_ORIGIN
Definition: msg_xml.h:151
Notify completed.
Definition: actions.h:92
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:307
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:306
bool pcmk__check_action_config(pcmk_resource_t *rsc, pcmk_node_t *node, const xmlNode *xml_op)
#define PCMK_ACTION_RELOAD_AGENT
Definition: actions.h:69
gboolean did_rsc_op_fail(lrmd_event_data_t *event, int target_rc)
Definition: actions.c:391
pcmk_resource_t * parent
Resource&#39;s parent resource, if any.
Definition: resources.h:413
char * calculate_operation_digest(xmlNode *local_cib, const char *version)
Calculate and return digest of XML operation.
Definition: digest.c:150
#define crm_warn(fmt, args...)
Definition: logging.h:382
G_GNUC_INTERNAL GList * pcmk__rscs_matching_id(const char *id, const pcmk_scheduler_t *scheduler)
char * pcmk__transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition: actions.c:250
const char * exit_reason
Definition: lrmd_events.h:96
#define action_type_str(flags)
Promote.
Definition: actions.h:94
pcmk_node_t * node
Node to execute action on, if any.
Definition: actions.h:401
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:540
#define action_node_str(a)
Implementation of pcmk_resource_t.
Definition: resources.h:399
#define crm_debug(fmt, args...)
Definition: logging.h:386
Actions are ordered (optionally, if no other flags are set)
#define pe__clear_order_flags(order_flags, flags_to_clear)
Definition: internal.h:135
Demote.
Definition: actions.h:97
Primitive resource.
Definition: resources.h:34
#define XML_ATTR_ID
Definition: msg_xml.h:156
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:447
pcmk_node_t * pe_find_node_id(const GList *node_list, const char *id)
Find a node by ID in a list of nodes.
Definition: status.c:448
uint32_t pcmk__update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:167
#define stop_key(rsc)
Definition: internal.h:378
G_GNUC_INTERNAL void pcmk__schedule_cancel(pcmk_resource_t *rsc, const char *call_id, const char *task, guint interval_ms, const pcmk_node_t *node, const char *reason)
char * task
Action name.
Definition: actions.h:403
Whether resource is considered failed.
Definition: resources.h:151
GList * actions_after
For Pacemaker use only.
Definition: actions.h:431
#define pe__clear_action_flags(action, flags_to_clear)
Definition: internal.h:85
#define crm_trace(fmt, args...)
Definition: logging.h:387
void pcmk__update_action_for_orderings(pcmk_action_t *then, pcmk_scheduler_t *scheduler)
void * priv
For Pacemaker use only.
Definition: scheduler.h:229
char * digest_secure_calc
Definition: internal.h:460
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
GHashTable * meta
Meta-attributes relevant to action.
Definition: actions.h:414
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:99
struct pe_node_shared_s * details
Basic node information.
Definition: nodes.h:134
bool pe__bundle_needs_remote_name(pcmk_resource_t *rsc)
Definition: bundle.c:920
#define crm_log_xml_debug(xml, text)
Definition: logging.h:394
#define PCMK_ACTION_START
Definition: actions.h:71
bool pcmk__is_daemon
Definition: logging.c:47
unsigned long long flags
Group of enum pcmk_rsc_flags.
Definition: resources.h:429
const char * uname
Node name in cluster.
Definition: nodes.h:68
#define XML_ATTR_TE_NOWAIT
Definition: msg_xml.h:418
rsc_role_e
Definition: roles.h:27
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:638
Action completed, result is known.
Definition: results.h:318
#define PCMK_ACTION_STOP
Definition: actions.h:74
GList * actions
Definition: resources.h:447
#define PCMK_ACTION_STONITH
Definition: actions.h:73
#define pcmk__clear_updated_flags(au_flags, action, flags_to_clear)
pe_action_flags
Action scheduling flags.
Definition: actions.h:233
#define XML_LRM_ATTR_MIGRATE_TARGET
Definition: msg_xml.h:331
Shut down node.
Definition: actions.h:100
#define XML_LRM_ATTR_EXIT_REASON
Definition: msg_xml.h:324
char * uuid
Action key.
Definition: actions.h:404
#define XML_LRM_ATTR_RESTART_DIGEST
Definition: msg_xml.h:322
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition: actions.c:42
void free_xml(xmlNode *child)
Definition: xml.c:783
Whether resource is blocked from further action.
Definition: resources.h:109
Implementation of pcmk_node_t.
Definition: nodes.h:130
enum pe_obj_types variant
Resource variant.
Definition: resources.h:414
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:957
xmlNode * input
CIB XML.
Definition: scheduler.h:175
Fence node.
Definition: actions.h:101
xmlNode * params_all
Definition: internal.h:456
Whether resource has pending start action in history.
Definition: resources.h:160
const char * id
Node ID at the cluster layer.
Definition: nodes.h:67
const char * op_type
Definition: lrmd_events.h:43
Whether sensitive resource attributes have been masked.
Definition: scheduler.h:146
pcmk_action_t * custom_action(pcmk_resource_t *rsc, char *key, const char *task, const pcmk_node_t *on_node, gboolean optional, pcmk_scheduler_t *scheduler)
Create or update an action object.
Definition: pe_actions.c:1117
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:399
unsigned int t_run
Definition: lrmd_events.h:72
Unspecified or unknown action.
Definition: actions.h:80
#define XML_ATTR_TRANSITION_KEY
Definition: msg_xml.h:416
#define XML_LRM_ATTR_SECURE_DIGEST
Definition: msg_xml.h:323
#define action_runnable_str(flags)
bool pe__is_guest_node(const pcmk_node_t *node)
Definition: remote.c:33
#define action_optional_str(flags)
xmlNode * pcmk__find_action_config(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, bool include_disabled)
Definition: pe_actions.c:129
char * pcmk__notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
Definition: actions.c:183
If &#39;then&#39; is required, &#39;first&#39; must be added to the transition graph.
pcmk__action_result_t result
Definition: pcmk_fence.c:35
Whether action is runnable.
Definition: actions.h:241
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:508
pcmk_rsc_methods_t * fns
Resource object methods.
Definition: resources.h:416
G_GNUC_INTERNAL void pcmk__reschedule_recurring(pcmk_resource_t *rsc, const char *task, guint interval_ms, pcmk_node_t *node)
#define XPATH_NODE_HISTORY
pcmk_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pcmk_node_t *on_node)
Definition: pe_actions.c:1486
#define pcmk__set_updated_flags(au_flags, action, flags_to_set)
#define crm_err(fmt, args...)
Definition: logging.h:381
pcmk_scheduler_t * scheduler
Whether action does not require invoking an agent.
Definition: actions.h:238
#define CRM_ASSERT(expr)
Definition: results.h:42
Success.
Definition: results.h:170
If &#39;first&#39; is required and runnable, &#39;then&#39; must be in graph.
void lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, int op_status, const char *exit_reason)
Definition: lrmd_client.c:2506
xmlNode * input
Whether action should be added to transition graph even if optional.
Definition: actions.h:247
#define PCMK_ACTION_MIGRATE_FROM
Definition: actions.h:57
Started.
Definition: roles.h:30
void calculate_active_ops(const GList *sorted_op_list, int *start_index, int *stop_index)
Definition: unpack.c:2532
This structure contains everything that makes up a single output formatter.
int compare_version(const char *version1, const char *version2)
Definition: utils.c:189
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: actions.c:96
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:304
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:318
gboolean is_parent(pcmk_resource_t *child, pcmk_resource_t *rsc)
Definition: complex.c:919
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:70
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:316
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:140
If &#39;then&#39; action becomes required, &#39;first&#39; becomes optional.
#define PCMK_ACTION_PROMOTE
Definition: actions.h:65
GList * running_on
Nodes where resource may be active.
Definition: resources.h:460
enum pe_action_flags flags
Group of enum pe_action_flags.
Definition: actions.h:409
gboolean maintenance
Whether in maintenance mode.
Definition: nodes.h:81
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:317
uint32_t(* update_ordered_actions)(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
Whether a reload action has been scheduled for resource.
Definition: resources.h:142
Start completed.
Definition: actions.h:89
Action is in progress.
Definition: results.h:317
Whether action is allowed to be part of a live migration.
Definition: actions.h:253
bool pcmk__action_locks_rsc_to_node(const pcmk_action_t *action)
const char * pcmk__readable_interval(guint interval_ms)
Definition: iso8601.c:1926
pcmk_action_t * pcmk__new_shutdown_action(pcmk_node_t *node)
pcmk_resource_t * rsc
Resource to apply action to, if any.
Definition: actions.h:400
Stop completed.
Definition: actions.h:86
G_GNUC_INTERNAL void pcmk__order_stops_before_shutdown(pcmk_node_t *node, pcmk_action_t *shutdown_op)
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:308
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:279
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:37
#define pe__set_order_flags(order_flags, flags_to_set)
Definition: internal.h:128
#define ID(x)
Definition: msg_xml.h:474
unsigned long long flags
Group of enum pcmk_scheduler_flags.
Definition: scheduler.h:183
#define FAKE_TE_ID
const char * parent
Definition: cib.c:27
bool pe__rsc_running_on_only(const pcmk_resource_t *rsc, const pcmk_node_t *node)
Definition: utils.c:754
#define XML_LRM_ATTR_MIGRATE_SOURCE
Definition: msg_xml.h:330
Whether resource is managed.
Definition: resources.h:106
Promoted.
Definition: actions.h:95
enum pe_ordering type
Definition: actions.h:380
&#39;then&#39; action is runnable if certain number of &#39;first&#39; instances are
void pe__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc, pcmk_node_t *node, enum pcmk__check_parameters, pcmk_scheduler_t *scheduler)
Definition: remote.c:225
void pcmk__log_action(const char *pre_text, const pcmk_action_t *action, bool details)
Whether resource has been removed from the configuration.
Definition: resources.h:103
#define XML_TAG_PARAMS
Definition: msg_xml.h:230
uint64_t flags
Definition: remote.c:215
GList * actions_before
For Pacemaker use only.
Definition: actions.h:430
int required_runnable_before
Definition: actions.h:427
#define PCMK_ACTION_NOTIFY
Definition: actions.h:61
No relation (compare with equality rather than bit set)
char * id
Resource ID in configuration.
Definition: resources.h:400
void pcmk__output_actions(pcmk_scheduler_t *scheduler)
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2510