This source file includes following definitions.
- action_flags_for_ordering
- action_uuid_for_ordering
- action_for_ordering
- update
- update_action_for_ordering_flags
- pcmk__update_action_for_orderings
- is_primitive_action
- handle_asymmetric_ordering
- handle_restart_ordering
- pcmk__update_ordered_actions
- pcmk__log_action
- pcmk__new_shutdown_action
- add_op_digest_to_xml
- pcmk__create_history_xml
- pcmk__action_locks_rsc_to_node
- sort_action_id
- pcmk__deduplicate_action_inputs
- pcmk__output_actions
- task_for_digest
- only_sanitized_changed
- force_restart
- schedule_reload
- pcmk__check_action_config
- rsc_history_as_list
- process_rsc_history
- process_node_history
- pcmk__handle_rsc_config_changes
1
2
3
4
5
6
7
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 <crm/common/scheduler_internal.h>
18 #include <pacemaker-internal.h>
19 #include "libpacemaker_private.h"
20
21
22
23
24
25
26
27
28
29
30
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
38 if (action->rsc == NULL) {
39 return action->flags;
40 }
41
42
43
44
45
46 flags = action->rsc->priv->cmds->action_flags(action, NULL);
47 if ((node == NULL) || !pcmk__is_clone(action->rsc)) {
48 return flags;
49 }
50
51
52
53
54 runnable = pcmk_is_set(flags, pcmk__action_runnable);
55
56
57 flags = action->rsc->priv->cmds->action_flags(action, node);
58
59
60
61
62
63
64
65
66
67 if (runnable && !pcmk_is_set(flags, pcmk__action_runnable)) {
68 pcmk__set_raw_action_flags(flags, action->rsc->id,
69 pcmk__action_runnable);
70 }
71 return flags;
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 static char *
93 action_uuid_for_ordering(const char *first_uuid,
94 const pcmk_resource_t *first_rsc)
95 {
96 guint interval_ms = 0;
97 char *uuid = NULL;
98 char *rid = NULL;
99 char *first_task_str = NULL;
100 enum pcmk__action_type first_task = pcmk__action_unspecified;
101 enum pcmk__action_type remapped_task = pcmk__action_unspecified;
102
103
104 if ((strstr(first_uuid, PCMK_ACTION_NOTIFY) != NULL)
105 || (first_rsc->priv->variant < pcmk__rsc_variant_group)) {
106 goto done;
107 }
108
109
110 pcmk__assert(parse_op_key(first_uuid, &rid, &first_task_str, &interval_ms));
111 if (interval_ms > 0) {
112 goto done;
113 }
114
115 first_task = pcmk__parse_action(first_task_str);
116 switch (first_task) {
117 case pcmk__action_stop:
118 case pcmk__action_start:
119 case pcmk__action_notify:
120 case pcmk__action_promote:
121 case pcmk__action_demote:
122 remapped_task = first_task + 1;
123 break;
124 case pcmk__action_stopped:
125 case pcmk__action_started:
126 case pcmk__action_notified:
127 case pcmk__action_promoted:
128 case pcmk__action_demoted:
129 remapped_task = first_task;
130 break;
131 case pcmk__action_monitor:
132 case pcmk__action_shutdown:
133 case pcmk__action_fence:
134 break;
135 default:
136 crm_err("Unknown action '%s' in ordering", first_task_str);
137 break;
138 }
139
140 if (remapped_task != pcmk__action_unspecified) {
141
142
143
144 if (pcmk_is_set(first_rsc->flags, pcmk__rsc_notify)
145 && (pcmk__is_clone(first_rsc) || pcmk__is_bundled(first_rsc))) {
146 uuid = pcmk__notify_key(rid, "confirmed-post",
147 pcmk__action_text(remapped_task));
148 } else {
149 uuid = pcmk__op_key(rid, pcmk__action_text(remapped_task), 0);
150 }
151 pcmk__rsc_trace(first_rsc,
152 "Remapped action UUID %s to %s for ordering purposes",
153 first_uuid, uuid);
154 }
155
156 done:
157 free(first_task_str);
158 free(rid);
159 return (uuid != NULL)? uuid : pcmk__str_copy(first_uuid);
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 static pcmk_action_t *
179 action_for_ordering(pcmk_action_t *action)
180 {
181 pcmk_action_t *result = action;
182 pcmk_resource_t *rsc = action->rsc;
183
184 if (rsc == NULL) {
185 return result;
186 }
187
188 if ((rsc->priv->variant >= pcmk__rsc_variant_group)
189 && (action->uuid != NULL)) {
190 char *uuid = action_uuid_for_ordering(action->uuid, rsc);
191
192 result = find_first_action(rsc->priv->actions, uuid, NULL, NULL);
193 if (result == NULL) {
194 crm_warn("Not remapping %s to %s because %s does not have "
195 "remapped action", action->uuid, uuid, rsc->id);
196 result = action;
197 }
198 free(uuid);
199 }
200 return result;
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222 static inline uint32_t
223 update(pcmk_resource_t *rsc, pcmk_action_t *first, pcmk_action_t *then,
224 const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type,
225 pcmk_scheduler_t *scheduler)
226 {
227 return rsc->priv->cmds->update_ordered_actions(first, then, node, flags,
228 filter, type, scheduler);
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244 static uint32_t
245 update_action_for_ordering_flags(pcmk_action_t *first, pcmk_action_t *then,
246 uint32_t first_flags, uint32_t then_flags,
247 pcmk__related_action_t *order,
248 pcmk_scheduler_t *scheduler)
249 {
250 uint32_t changed = pcmk__updated_none;
251
252
253
254
255
256
257 pcmk_node_t *node = then->node;
258
259 if (pcmk_is_set(order->flags, pcmk__ar_first_implies_same_node_then)) {
260
261
262
263
264
265 pcmk__clear_relation_flags(order->flags,
266 pcmk__ar_first_implies_same_node_then);
267 pcmk__set_relation_flags(order->flags, pcmk__ar_first_implies_then);
268 node = first->node;
269 pcmk__rsc_trace(then->rsc,
270 "%s then %s: mapped "
271 "pcmk__ar_first_implies_same_node_then to "
272 "pcmk__ar_first_implies_then on %s",
273 first->uuid, then->uuid, pcmk__node_name(node));
274 }
275
276 if (pcmk_is_set(order->flags, pcmk__ar_first_implies_then)) {
277 if (then->rsc != NULL) {
278 changed |= update(then->rsc, first, then, node,
279 first_flags & pcmk__action_optional,
280 pcmk__action_optional,
281 pcmk__ar_first_implies_then, scheduler);
282 } else if (!pcmk_is_set(first_flags, pcmk__action_optional)
283 && pcmk_is_set(then->flags, pcmk__action_optional)) {
284 pcmk__clear_action_flags(then, pcmk__action_optional);
285 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
286 }
287 pcmk__rsc_trace(then->rsc,
288 "%s then %s: %s after pcmk__ar_first_implies_then",
289 first->uuid, then->uuid,
290 (changed? "changed" : "unchanged"));
291 }
292
293 if (pcmk_is_set(order->flags, pcmk__ar_intermediate_stop)
294 && (then->rsc != NULL)) {
295 enum pcmk__action_flags restart = pcmk__action_optional
296 |pcmk__action_runnable;
297
298 changed |= update(then->rsc, first, then, node, first_flags, restart,
299 pcmk__ar_intermediate_stop, scheduler);
300 pcmk__rsc_trace(then->rsc,
301 "%s then %s: %s after pcmk__ar_intermediate_stop",
302 first->uuid, then->uuid,
303 (changed? "changed" : "unchanged"));
304 }
305
306 if (pcmk_is_set(order->flags, pcmk__ar_then_implies_first)) {
307 if (first->rsc != NULL) {
308 changed |= update(first->rsc, first, then, node, first_flags,
309 pcmk__action_optional,
310 pcmk__ar_then_implies_first, scheduler);
311 } else if (!pcmk_is_set(first_flags, pcmk__action_optional)
312 && pcmk_is_set(first->flags, pcmk__action_runnable)) {
313 pcmk__clear_action_flags(first, pcmk__action_runnable);
314 pcmk__set_updated_flags(changed, first, pcmk__updated_first);
315 }
316 pcmk__rsc_trace(then->rsc,
317 "%s then %s: %s after pcmk__ar_then_implies_first",
318 first->uuid, then->uuid,
319 (changed? "changed" : "unchanged"));
320 }
321
322 if (pcmk_is_set(order->flags, pcmk__ar_promoted_then_implies_first)) {
323 if (then->rsc != NULL) {
324 changed |= update(then->rsc, first, then, node,
325 first_flags & pcmk__action_optional,
326 pcmk__action_optional,
327 pcmk__ar_promoted_then_implies_first, scheduler);
328 }
329 pcmk__rsc_trace(then->rsc,
330 "%s then %s: %s after "
331 "pcmk__ar_promoted_then_implies_first",
332 first->uuid, then->uuid,
333 (changed? "changed" : "unchanged"));
334 }
335
336 if (pcmk_is_set(order->flags, pcmk__ar_min_runnable)) {
337 if (then->rsc != NULL) {
338 changed |= update(then->rsc, first, then, node, first_flags,
339 pcmk__action_runnable, pcmk__ar_min_runnable,
340 scheduler);
341
342 } else if (pcmk_is_set(first_flags, pcmk__action_runnable)) {
343
344 then->runnable_before++;
345
346
347
348
349 if ((then->runnable_before >= then->required_runnable_before)
350 && !pcmk_is_set(then->flags, pcmk__action_runnable)) {
351
352 pcmk__set_action_flags(then, pcmk__action_runnable);
353 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
354 }
355 }
356 pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_min_runnable",
357 first->uuid, then->uuid,
358 (changed? "changed" : "unchanged"));
359 }
360
361 if (pcmk_is_set(order->flags, pcmk__ar_nested_remote_probe)
362 && (then->rsc != NULL)) {
363
364 if (!pcmk_is_set(first_flags, pcmk__action_runnable)
365 && (first->rsc != NULL)
366 && (first->rsc->priv->active_nodes != NULL)) {
367
368 pcmk__rsc_trace(then->rsc,
369 "%s then %s: ignoring because first is stopping",
370 first->uuid, then->uuid);
371 order->flags = pcmk__ar_none;
372 } else {
373 changed |= update(then->rsc, first, then, node, first_flags,
374 pcmk__action_runnable,
375 pcmk__ar_unrunnable_first_blocks, scheduler);
376 }
377 pcmk__rsc_trace(then->rsc,
378 "%s then %s: %s after pcmk__ar_nested_remote_probe",
379 first->uuid, then->uuid,
380 (changed? "changed" : "unchanged"));
381 }
382
383 if (pcmk_is_set(order->flags, pcmk__ar_unrunnable_first_blocks)) {
384 if (then->rsc != NULL) {
385 changed |= update(then->rsc, first, then, node, first_flags,
386 pcmk__action_runnable,
387 pcmk__ar_unrunnable_first_blocks, scheduler);
388
389 } else if (!pcmk_is_set(first_flags, pcmk__action_runnable)
390 && pcmk_is_set(then->flags, pcmk__action_runnable)) {
391
392 pcmk__clear_action_flags(then, pcmk__action_runnable);
393 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
394 }
395 pcmk__rsc_trace(then->rsc,
396 "%s then %s: %s after pcmk__ar_unrunnable_first_blocks",
397 first->uuid, then->uuid,
398 (changed? "changed" : "unchanged"));
399 }
400
401 if (pcmk_is_set(order->flags, pcmk__ar_unmigratable_then_blocks)) {
402 if (then->rsc != NULL) {
403 changed |= update(then->rsc, first, then, node, first_flags,
404 pcmk__action_optional,
405 pcmk__ar_unmigratable_then_blocks, scheduler);
406 }
407 pcmk__rsc_trace(then->rsc,
408 "%s then %s: %s after "
409 "pcmk__ar_unmigratable_then_blocks",
410 first->uuid, then->uuid,
411 (changed? "changed" : "unchanged"));
412 }
413
414 if (pcmk_is_set(order->flags, pcmk__ar_first_else_then)) {
415 if (then->rsc != NULL) {
416 changed |= update(then->rsc, first, then, node, first_flags,
417 pcmk__action_optional, pcmk__ar_first_else_then,
418 scheduler);
419 }
420 pcmk__rsc_trace(then->rsc,
421 "%s then %s: %s after pcmk__ar_first_else_then",
422 first->uuid, then->uuid,
423 (changed? "changed" : "unchanged"));
424 }
425
426 if (pcmk_is_set(order->flags, pcmk__ar_ordered)) {
427 if (then->rsc != NULL) {
428 changed |= update(then->rsc, first, then, node, first_flags,
429 pcmk__action_runnable, pcmk__ar_ordered,
430 scheduler);
431 }
432 pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_ordered",
433 first->uuid, then->uuid,
434 (changed? "changed" : "unchanged"));
435 }
436
437 if (pcmk_is_set(order->flags, pcmk__ar_asymmetric)) {
438 if (then->rsc != NULL) {
439 changed |= update(then->rsc, first, then, node, first_flags,
440 pcmk__action_runnable, pcmk__ar_asymmetric,
441 scheduler);
442 }
443 pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_asymmetric",
444 first->uuid, then->uuid,
445 (changed? "changed" : "unchanged"));
446 }
447
448 if (pcmk_is_set(first->flags, pcmk__action_runnable)
449 && pcmk_is_set(order->flags, pcmk__ar_first_implies_then_graphed)
450 && !pcmk_is_set(first_flags, pcmk__action_optional)) {
451
452 pcmk__rsc_trace(then->rsc, "%s will be in graph because %s is required",
453 then->uuid, first->uuid);
454 pcmk__set_action_flags(then, pcmk__action_always_in_graph);
455
456 }
457
458 if (pcmk_is_set(order->flags, pcmk__ar_then_implies_first_graphed)
459 && !pcmk_is_set(then_flags, pcmk__action_optional)) {
460
461 pcmk__rsc_trace(then->rsc, "%s will be in graph because %s is required",
462 first->uuid, then->uuid);
463 pcmk__set_action_flags(first, pcmk__action_always_in_graph);
464
465 }
466
467 if (pcmk_any_flags_set(order->flags, pcmk__ar_first_implies_then
468 |pcmk__ar_then_implies_first
469 |pcmk__ar_intermediate_stop)
470 && (first->rsc != NULL)
471 && !pcmk_is_set(first->rsc->flags, pcmk__rsc_managed)
472 && pcmk_is_set(first->rsc->flags, pcmk__rsc_blocked)
473 && !pcmk_is_set(first->flags, pcmk__action_runnable)
474 && pcmk__str_eq(first->task, PCMK_ACTION_STOP, pcmk__str_none)) {
475
476 if (pcmk_is_set(then->flags, pcmk__action_runnable)) {
477 pcmk__clear_action_flags(then, pcmk__action_runnable);
478 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
479 }
480 pcmk__rsc_trace(then->rsc,
481 "%s then %s: %s after checking whether first "
482 "is blocked, unmanaged, unrunnable stop",
483 first->uuid, then->uuid,
484 (changed? "changed" : "unchanged"));
485 }
486
487 return changed;
488 }
489
490
491
492 #define action_type_str(flags) \
493 (pcmk_is_set((flags), pcmk__action_pseudo)? "pseudo-action" : "action")
494
495 #define action_optional_str(flags) \
496 (pcmk_is_set((flags), pcmk__action_optional)? "optional" : "required")
497
498 #define action_runnable_str(flags) \
499 (pcmk_is_set((flags), pcmk__action_runnable)? "runnable" : "unrunnable")
500
501 #define action_node_str(a) \
502 (((a)->node == NULL)? "no node" : (a)->node->priv->name)
503
504
505
506
507
508
509
510
511 void
512 pcmk__update_action_for_orderings(pcmk_action_t *then,
513 pcmk_scheduler_t *scheduler)
514 {
515 GList *lpc = NULL;
516 uint32_t changed = pcmk__updated_none;
517 int last_flags = then->flags;
518
519 pcmk__rsc_trace(then->rsc, "Updating %s %s (%s %s) on %s",
520 action_type_str(then->flags), then->uuid,
521 action_optional_str(then->flags),
522 action_runnable_str(then->flags), action_node_str(then));
523
524 if (then->required_runnable_before > 0) {
525
526
527
528
529
530 then->runnable_before = 0;
531
532
533
534
535
536 pcmk__clear_action_flags(then, pcmk__action_runnable);
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 const uint32_t target = pcmk__rsc_node_assigned;
547
548 if ((first->rsc != NULL)
549 && pcmk__is_group(first->rsc)
550 && pcmk__str_eq(first->task, PCMK_ACTION_START, pcmk__str_none)) {
551
552 first_node = first->rsc->priv->fns->location(first->rsc, NULL,
553 target);
554 if (first_node != NULL) {
555 pcmk__rsc_trace(first->rsc, "Found %s for 'first' %s",
556 pcmk__node_name(first_node), first->uuid);
557 }
558 }
559
560 if (pcmk__is_group(then->rsc)
561 && pcmk__str_eq(then->task, PCMK_ACTION_START, pcmk__str_none)) {
562
563 then_node = then->rsc->priv->fns->location(then->rsc, NULL, target);
564 if (then_node != NULL) {
565 pcmk__rsc_trace(then->rsc, "Found %s for 'then' %s",
566 pcmk__node_name(then_node), then->uuid);
567 }
568 }
569
570
571 if (pcmk_is_set(other->flags, pcmk__ar_if_on_same_node)
572 && (first_node != NULL) && (then_node != NULL)
573 && !pcmk__same_node(first_node, then_node)) {
574
575 pcmk__rsc_trace(then->rsc,
576 "Disabled ordering %s on %s then %s on %s: "
577 "not same node",
578 other->action->uuid, pcmk__node_name(first_node),
579 then->uuid, pcmk__node_name(then_node));
580 other->flags = pcmk__ar_none;
581 continue;
582 }
583
584 pcmk__clear_updated_flags(changed, then, pcmk__updated_first);
585
586 if ((first->rsc != NULL)
587 && pcmk_is_set(other->flags, pcmk__ar_then_cancels_first)
588 && !pcmk_is_set(then->flags, pcmk__action_optional)) {
589
590
591
592
593 pcmk__set_action_flags(other->action, pcmk__action_optional);
594 if (!strcmp(first->task, PCMK_ACTION_RELOAD_AGENT)) {
595 pcmk__clear_rsc_flags(first->rsc, pcmk__rsc_reload);
596 }
597 }
598
599 if ((first->rsc != NULL) && (then->rsc != NULL)
600 && (first->rsc != then->rsc) && !is_parent(then->rsc, first->rsc)) {
601 first = action_for_ordering(first);
602 }
603 if (first != other->action) {
604 pcmk__rsc_trace(then->rsc, "Ordering %s after %s instead of %s",
605 then->uuid, first->uuid, other->action->uuid);
606 }
607
608 pcmk__rsc_trace(then->rsc,
609 "%s (%#.6x) then %s (%#.6x): type=%#.6x node=%s",
610 first->uuid, first->flags, then->uuid, then->flags,
611 other->flags, action_node_str(first));
612
613 if (first == other->action) {
614
615
616
617
618 uint32_t first_flags, then_flags;
619
620 first_flags = action_flags_for_ordering(first, then_node);
621 then_flags = action_flags_for_ordering(then, first_node);
622
623 changed |= update_action_for_ordering_flags(first, then,
624 first_flags, then_flags,
625 other, scheduler);
626
627
628
629
630 } else if (order_actions(first, then, other->flags)) {
631
632
633
634 pcmk__set_updated_flags(changed, then, pcmk__updated_then);
635 pcmk__rsc_trace(then->rsc,
636 "Disabled ordering %s then %s in favor of %s "
637 "then %s",
638 other->action->uuid, then->uuid, first->uuid,
639 then->uuid);
640 other->flags = pcmk__ar_none;
641 }
642
643
644 if (pcmk_is_set(changed, pcmk__updated_first)) {
645 crm_trace("Re-processing %s and its 'after' actions "
646 "because it changed", first->uuid);
647 for (GList *lpc2 = first->actions_after; lpc2 != NULL;
648 lpc2 = lpc2->next) {
649 pcmk__related_action_t *other = lpc2->data;
650
651 pcmk__update_action_for_orderings(other->action, scheduler);
652 }
653 pcmk__update_action_for_orderings(first, scheduler);
654 }
655 }
656
657 if (then->required_runnable_before > 0) {
658 if (last_flags == then->flags) {
659 pcmk__clear_updated_flags(changed, then, pcmk__updated_then);
660 } else {
661 pcmk__set_updated_flags(changed, then, pcmk__updated_then);
662 }
663 }
664
665 if (pcmk_is_set(changed, pcmk__updated_then)) {
666 crm_trace("Re-processing %s and its 'after' actions because it changed",
667 then->uuid);
668 if (pcmk_is_set(last_flags, pcmk__action_runnable)
669 && !pcmk_is_set(then->flags, pcmk__action_runnable)) {
670 pcmk__block_colocation_dependents(then);
671 }
672 pcmk__update_action_for_orderings(then, scheduler);
673 for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) {
674 pcmk__related_action_t *other = lpc->data;
675
676 pcmk__update_action_for_orderings(other->action, scheduler);
677 }
678 }
679 }
680
681 static inline bool
682 is_primitive_action(const pcmk_action_t *action)
683 {
684 return (action != NULL) && pcmk__is_primitive(action->rsc);
685 }
686
687
688
689
690
691
692
693
694
695 #define clear_action_flag_because(action, flag, reason) do { \
696 if (pcmk_is_set((action)->flags, (flag))) { \
697 pcmk__clear_action_flags(action, flag); \
698 if ((action)->rsc != (reason)->rsc) { \
699 char *reason_text = pe__action2reason((reason), (flag)); \
700 pe_action_set_reason((action), reason_text, false); \
701 free(reason_text); \
702 } \
703 } \
704 } while (0)
705
706
707
708
709
710
711
712
713
714
715
716 static void
717 handle_asymmetric_ordering(const pcmk_action_t *first, pcmk_action_t *then)
718 {
719
720
721
722 if ((then->rsc == NULL)
723 || pcmk_is_set(first->flags, pcmk__action_runnable)) {
724 return;
725 }
726
727
728 if (pcmk_is_set(then->flags, pcmk__action_optional)) {
729 enum rsc_role_e then_rsc_role;
730
731 then_rsc_role = then->rsc->priv->fns->state(then->rsc, TRUE);
732
733 if ((then_rsc_role == pcmk_role_stopped)
734 && pcmk__str_eq(then->task, PCMK_ACTION_STOP, pcmk__str_none)) {
735
736
737
738 return;
739 } else if ((then_rsc_role >= pcmk_role_started)
740 && pcmk__str_eq(then->task, PCMK_ACTION_START, pcmk__str_none)
741 && pe__rsc_running_on_only(then->rsc, then->node)) {
742
743
744
745 return;
746 }
747 }
748
749
750 clear_action_flag_because(then, pcmk__action_optional, first);
751 clear_action_flag_because(then, pcmk__action_runnable, first);
752 }
753
754
755
756
757
758
759
760
761
762
763
764
765 static void
766 handle_restart_ordering(pcmk_action_t *first, pcmk_action_t *then,
767 uint32_t filter)
768 {
769 const char *reason = NULL;
770
771 pcmk__assert(is_primitive_action(first) && is_primitive_action(then));
772
773
774
775
776 if (pcmk_is_set(filter, pcmk__action_optional)
777 && !pcmk_is_set(then->flags, pcmk__action_optional)) {
778 reason = "restart";
779 }
780
781
782
783
784 if (pcmk_is_set(filter, pcmk__action_runnable)
785 && !pcmk_is_set(then->flags, pcmk__action_runnable)
786 && pcmk_is_set(then->rsc->flags, pcmk__rsc_managed)
787 && (first->rsc == then->rsc)) {
788 reason = "stop";
789 }
790
791 if (reason == NULL) {
792 return;
793 }
794
795 pcmk__rsc_trace(first->rsc, "Handling %s -> %s for %s",
796 first->uuid, then->uuid, reason);
797
798
799 if (pcmk_is_set(first->flags, pcmk__action_runnable)) {
800 clear_action_flag_because(first, pcmk__action_optional, then);
801 }
802
803
804 if (!pcmk_is_set(then->flags, pcmk__action_optional)) {
805 clear_action_flag_because(first, pcmk__action_optional, then);
806 }
807
808
809 if (!pcmk_is_set(then->flags, pcmk__action_migratable)) {
810 clear_action_flag_because(first, pcmk__action_migratable, then);
811 }
812
813
814 if (!pcmk_is_set(first->flags, pcmk__action_optional)
815 && !pcmk_is_set(first->flags, pcmk__action_runnable)) {
816 clear_action_flag_because(then, pcmk__action_runnable, first);
817 }
818 }
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842 uint32_t
843 pcmk__update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then,
844 const pcmk_node_t *node, uint32_t flags,
845 uint32_t filter, uint32_t type,
846 pcmk_scheduler_t *scheduler)
847 {
848 uint32_t changed = pcmk__updated_none;
849 uint32_t then_flags = 0U;
850 uint32_t first_flags = 0U;
851
852 pcmk__assert((first != NULL) && (then != NULL) && (scheduler != NULL));
853
854 then_flags = then->flags;
855 first_flags = first->flags;
856 if (pcmk_is_set(type, pcmk__ar_asymmetric)) {
857 handle_asymmetric_ordering(first, then);
858 }
859
860 if (pcmk_is_set(type, pcmk__ar_then_implies_first)
861 && !pcmk_is_set(then_flags, pcmk__action_optional)) {
862
863
864 if (pcmk_is_set(filter, pcmk__action_optional)
865 && !pcmk_is_set(flags, pcmk__action_optional)
866 && pcmk_is_set(first_flags, pcmk__action_optional)) {
867 clear_action_flag_because(first, pcmk__action_optional, then);
868 }
869
870 if (pcmk_is_set(flags, pcmk__action_migratable)
871 && !pcmk_is_set(then->flags, pcmk__action_migratable)) {
872 clear_action_flag_because(first, pcmk__action_migratable, then);
873 }
874 }
875
876 if (pcmk_is_set(type, pcmk__ar_promoted_then_implies_first)
877 && (then->rsc != NULL)
878 && (then->rsc->priv->orig_role == pcmk_role_promoted)
879 && pcmk_is_set(filter, pcmk__action_optional)
880 && !pcmk_is_set(then->flags, pcmk__action_optional)) {
881
882 clear_action_flag_because(first, pcmk__action_optional, then);
883
884 if (pcmk_is_set(first->flags, pcmk__action_migratable)
885 && !pcmk_is_set(then->flags, pcmk__action_migratable)) {
886 clear_action_flag_because(first, pcmk__action_migratable, then);
887 }
888 }
889
890 if (pcmk_is_set(type, pcmk__ar_unmigratable_then_blocks)
891 && pcmk_is_set(filter, pcmk__action_optional)) {
892
893 if (!pcmk_all_flags_set(then->flags, pcmk__action_migratable
894 |pcmk__action_runnable)) {
895 clear_action_flag_because(first, pcmk__action_runnable, then);
896 }
897
898 if (!pcmk_is_set(then->flags, pcmk__action_optional)) {
899 clear_action_flag_because(first, pcmk__action_optional, then);
900 }
901 }
902
903 if (pcmk_is_set(type, pcmk__ar_first_else_then)
904 && pcmk_is_set(filter, pcmk__action_optional)
905 && !pcmk_is_set(first->flags, pcmk__action_runnable)) {
906
907 clear_action_flag_because(then, pcmk__action_migratable, first);
908 pcmk__clear_action_flags(then, pcmk__action_pseudo);
909 }
910
911 if (pcmk_is_set(type, pcmk__ar_unrunnable_first_blocks)
912 && pcmk_is_set(filter, pcmk__action_runnable)
913 && pcmk_is_set(then->flags, pcmk__action_runnable)
914 && !pcmk_is_set(flags, pcmk__action_runnable)) {
915
916 clear_action_flag_because(then, pcmk__action_runnable, first);
917 clear_action_flag_because(then, pcmk__action_migratable, first);
918 }
919
920 if (pcmk_is_set(type, pcmk__ar_first_implies_then)
921 && pcmk_is_set(filter, pcmk__action_optional)
922 && pcmk_is_set(then->flags, pcmk__action_optional)
923 && !pcmk_is_set(flags, pcmk__action_optional)
924 && !pcmk_is_set(first->flags, pcmk__action_migratable)) {
925
926 clear_action_flag_because(then, pcmk__action_optional, first);
927 }
928
929 if (pcmk_is_set(type, pcmk__ar_intermediate_stop)) {
930 handle_restart_ordering(first, then, filter);
931 }
932
933 if (then_flags != then->flags) {
934 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
935 pcmk__rsc_trace(then->rsc,
936 "%s on %s: flags are now %#.6x (was %#.6x) "
937 "because of 'first' %s (%#.6x)",
938 then->uuid, pcmk__node_name(then->node),
939 then->flags, then_flags, first->uuid, first->flags);
940
941 if ((then->rsc != NULL) && (then->rsc->priv->parent != NULL)) {
942
943 pcmk__update_action_for_orderings(then, scheduler);
944 }
945 }
946
947 if (first_flags != first->flags) {
948 pcmk__set_updated_flags(changed, first, pcmk__updated_first);
949 pcmk__rsc_trace(first->rsc,
950 "%s on %s: flags are now %#.6x (was %#.6x) "
951 "because of 'then' %s (%#.6x)",
952 first->uuid, pcmk__node_name(first->node),
953 first->flags, first_flags, then->uuid, then->flags);
954 }
955
956 return changed;
957 }
958
959
960
961
962
963
964
965
966
967 void
968 pcmk__log_action(const char *pre_text, const pcmk_action_t *action,
969 bool details)
970 {
971 const char *node_uname = NULL;
972 const char *node_uuid = NULL;
973 const char *desc = NULL;
974
975 CRM_CHECK(action != NULL, return);
976
977 if (!pcmk_is_set(action->flags, pcmk__action_pseudo)) {
978 if (action->node != NULL) {
979 node_uname = action->node->priv->name;
980 node_uuid = action->node->priv->id;
981 } else {
982 node_uname = "<none>";
983 }
984 }
985
986 switch (pcmk__parse_action(action->task)) {
987 case pcmk__action_fence:
988 case pcmk__action_shutdown:
989 if (pcmk_is_set(action->flags, pcmk__action_pseudo)) {
990 desc = "Pseudo ";
991 } else if (pcmk_is_set(action->flags, pcmk__action_optional)) {
992 desc = "Optional ";
993 } else if (!pcmk_is_set(action->flags, pcmk__action_runnable)) {
994 desc = "!!Non-Startable!! ";
995 } else {
996 desc = "(Provisional) ";
997 }
998 crm_trace("%s%s%sAction %d: %s%s%s%s%s%s",
999 ((pre_text == NULL)? "" : pre_text),
1000 ((pre_text == NULL)? "" : ": "),
1001 desc, action->id, action->uuid,
1002 (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
1003 (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
1004 (node_uuid? ")" : ""));
1005 break;
1006 default:
1007 if (pcmk_is_set(action->flags, pcmk__action_optional)) {
1008 desc = "Optional ";
1009 } else if (pcmk_is_set(action->flags, pcmk__action_pseudo)) {
1010 desc = "Pseudo ";
1011 } else if (!pcmk_is_set(action->flags, pcmk__action_runnable)) {
1012 desc = "!!Non-Startable!! ";
1013 } else {
1014 desc = "(Provisional) ";
1015 }
1016 crm_trace("%s%s%sAction %d: %s %s%s%s%s%s%s",
1017 ((pre_text == NULL)? "" : pre_text),
1018 ((pre_text == NULL)? "" : ": "),
1019 desc, action->id, action->uuid,
1020 (action->rsc? action->rsc->id : "<none>"),
1021 (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
1022 (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
1023 (node_uuid? ")" : ""));
1024 break;
1025 }
1026
1027 if (details) {
1028 const GList *iter = NULL;
1029 const pcmk__related_action_t *other = NULL;
1030
1031 crm_trace("\t\t====== Preceding Actions");
1032 for (iter = action->actions_before; iter != NULL; iter = iter->next) {
1033 other = (const pcmk__related_action_t *) iter->data;
1034 pcmk__log_action("\t\t", other->action, false);
1035 }
1036 crm_trace("\t\t====== Subsequent Actions");
1037 for (iter = action->actions_after; iter != NULL; iter = iter->next) {
1038 other = (const pcmk__related_action_t *) iter->data;
1039 pcmk__log_action("\t\t", other->action, false);
1040 }
1041 crm_trace("\t\t====== End");
1042
1043 } else {
1044 crm_trace("\t\t(before=%d, after=%d)",
1045 g_list_length(action->actions_before),
1046 g_list_length(action->actions_after));
1047 }
1048 }
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058 pcmk_action_t *
1059 pcmk__new_shutdown_action(pcmk_node_t *node)
1060 {
1061 char *shutdown_id = NULL;
1062 pcmk_action_t *shutdown_op = NULL;
1063
1064 pcmk__assert(node != NULL);
1065
1066 shutdown_id = crm_strdup_printf("%s-%s", PCMK_ACTION_DO_SHUTDOWN,
1067 node->priv->name);
1068
1069 shutdown_op = custom_action(NULL, shutdown_id, PCMK_ACTION_DO_SHUTDOWN,
1070 node, FALSE, node->priv->scheduler);
1071
1072 pcmk__order_stops_before_shutdown(node, shutdown_op);
1073 pcmk__insert_meta(shutdown_op, PCMK__META_OP_NO_WAIT, PCMK_VALUE_TRUE);
1074 return shutdown_op;
1075 }
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088 static void
1089 add_op_digest_to_xml(const lrmd_event_data_t *op, xmlNode *update)
1090 {
1091 char *digest = NULL;
1092 xmlNode *args_xml = NULL;
1093
1094 if (op->params == NULL) {
1095 return;
1096 }
1097 args_xml = pcmk__xe_create(NULL, PCMK_XE_PARAMETERS);
1098 g_hash_table_foreach(op->params, hash2field, args_xml);
1099 pcmk__filter_op_for_digest(args_xml);
1100 digest = pcmk__digest_operation(args_xml);
1101 crm_xml_add(update, PCMK__XA_OP_DIGEST, digest);
1102 pcmk__xml_free(args_xml);
1103 free(digest);
1104 }
1105
1106 #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121 xmlNode *
1122 pcmk__create_history_xml(xmlNode *parent, lrmd_event_data_t *op,
1123 const char *caller_version, int target_rc,
1124 const char *node, const char *origin)
1125 {
1126 char *key = NULL;
1127 char *magic = NULL;
1128 char *op_id = NULL;
1129 char *op_id_additional = NULL;
1130 char *local_user_data = NULL;
1131 const char *exit_reason = NULL;
1132
1133 xmlNode *xml_op = NULL;
1134 const char *task = NULL;
1135
1136 CRM_CHECK(op != NULL, return NULL);
1137 crm_trace("Creating history XML for %s-interval %s action for %s on %s "
1138 "(DC version: %s, origin: %s)",
1139 pcmk__readable_interval(op->interval_ms), op->op_type, op->rsc_id,
1140 ((node == NULL)? "no node" : node), caller_version, origin);
1141
1142 task = op->op_type;
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 if (pcmk__str_any_of(task, PCMK_ACTION_RELOAD, PCMK_ACTION_RELOAD_AGENT,
1154 NULL)) {
1155 if (op->op_status == PCMK_EXEC_DONE) {
1156 task = PCMK_ACTION_START;
1157 } else {
1158 task = PCMK_ACTION_MONITOR;
1159 }
1160 }
1161
1162 key = pcmk__op_key(op->rsc_id, task, op->interval_ms);
1163 if (pcmk__str_eq(task, PCMK_ACTION_NOTIFY, pcmk__str_none)) {
1164 const char *n_type = crm_meta_value(op->params, "notify_type");
1165 const char *n_task = crm_meta_value(op->params, "notify_operation");
1166
1167 CRM_LOG_ASSERT(n_type != NULL);
1168 CRM_LOG_ASSERT(n_task != NULL);
1169 op_id = pcmk__notify_key(op->rsc_id, n_type, n_task);
1170
1171 if (op->op_status != PCMK_EXEC_PENDING) {
1172
1173
1174
1175
1176
1177 lrmd__set_result(op, PCMK_OCF_OK, PCMK_EXEC_DONE, NULL);
1178 }
1179
1180
1181
1182
1183 } else if (pcmk__str_any_of(op->op_type, PCMK_ACTION_MIGRATE_TO,
1184 PCMK_ACTION_MIGRATE_FROM, NULL)) {
1185 op_id = strdup(key);
1186
1187 } else if (did_rsc_op_fail(op, target_rc)) {
1188 op_id = pcmk__op_key(op->rsc_id, "last_failure", 0);
1189 if (op->interval_ms == 0) {
1190
1191
1192
1193 op_id_additional = pcmk__op_key(op->rsc_id, "last", 0);
1194 }
1195 exit_reason = op->exit_reason;
1196
1197 } else if (op->interval_ms > 0) {
1198 op_id = strdup(key);
1199
1200 } else {
1201 op_id = pcmk__op_key(op->rsc_id, "last", 0);
1202 }
1203
1204 again:
1205 xml_op = pcmk__xe_first_child(parent, PCMK__XE_LRM_RSC_OP, PCMK_XA_ID,
1206 op_id);
1207 if (xml_op == NULL) {
1208 xml_op = pcmk__xe_create(parent, PCMK__XE_LRM_RSC_OP);
1209 }
1210
1211 if (op->user_data == NULL) {
1212 crm_debug("Generating fake transition key for: " PCMK__OP_FMT
1213 " %d from %s", op->rsc_id, op->op_type, op->interval_ms,
1214 op->call_id, origin);
1215 local_user_data = pcmk__transition_key(-1, op->call_id, target_rc,
1216 FAKE_TE_ID);
1217 op->user_data = local_user_data;
1218 }
1219
1220 if (magic == NULL) {
1221 magic = crm_strdup_printf("%d:%d;%s", op->op_status, op->rc,
1222 (const char *) op->user_data);
1223 }
1224
1225 crm_xml_add(xml_op, PCMK_XA_ID, op_id);
1226 crm_xml_add(xml_op, PCMK__XA_OPERATION_KEY, key);
1227 crm_xml_add(xml_op, PCMK_XA_OPERATION, task);
1228 crm_xml_add(xml_op, PCMK_XA_CRM_DEBUG_ORIGIN, origin);
1229 crm_xml_add(xml_op, PCMK_XA_CRM_FEATURE_SET, caller_version);
1230 crm_xml_add(xml_op, PCMK__XA_TRANSITION_KEY, op->user_data);
1231 crm_xml_add(xml_op, PCMK__XA_TRANSITION_MAGIC, magic);
1232 crm_xml_add(xml_op, PCMK_XA_EXIT_REASON, pcmk__s(exit_reason, ""));
1233 crm_xml_add(xml_op, PCMK__META_ON_NODE, node);
1234
1235 crm_xml_add_int(xml_op, PCMK__XA_CALL_ID, op->call_id);
1236 crm_xml_add_int(xml_op, PCMK__XA_RC_CODE, op->rc);
1237 crm_xml_add_int(xml_op, PCMK__XA_OP_STATUS, op->op_status);
1238 crm_xml_add_ms(xml_op, PCMK_META_INTERVAL, op->interval_ms);
1239
1240 if ((op->t_run > 0) || (op->t_rcchange > 0) || (op->exec_time > 0)
1241 || (op->queue_time > 0)) {
1242
1243 crm_trace("Timing data (" PCMK__OP_FMT "): "
1244 "last=%lld change=%lld exec=%u queue=%u",
1245 op->rsc_id, op->op_type, op->interval_ms,
1246 (long long) op->t_run, (long long) op->t_rcchange,
1247 op->exec_time, op->queue_time);
1248
1249 if ((op->interval_ms > 0) && (op->t_rcchange > 0)) {
1250
1251 crm_xml_add_ll(xml_op, PCMK_XA_LAST_RC_CHANGE,
1252 (long long) op->t_rcchange);
1253 } else {
1254 crm_xml_add_ll(xml_op, PCMK_XA_LAST_RC_CHANGE,
1255 (long long) op->t_run);
1256 }
1257
1258 crm_xml_add_int(xml_op, PCMK_XA_EXEC_TIME, op->exec_time);
1259 crm_xml_add_int(xml_op, PCMK_XA_QUEUE_TIME, op->queue_time);
1260 }
1261
1262 if (pcmk__str_any_of(op->op_type, PCMK_ACTION_MIGRATE_TO,
1263 PCMK_ACTION_MIGRATE_FROM, NULL)) {
1264
1265
1266
1267 const char *name = PCMK__META_MIGRATE_SOURCE;
1268
1269 crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1270
1271 name = PCMK__META_MIGRATE_TARGET;
1272 crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1273 }
1274
1275 add_op_digest_to_xml(op, xml_op);
1276
1277 if (op_id_additional) {
1278 free(op_id);
1279 op_id = op_id_additional;
1280 op_id_additional = NULL;
1281 goto again;
1282 }
1283
1284 if (local_user_data) {
1285 free(local_user_data);
1286 op->user_data = NULL;
1287 }
1288 free(magic);
1289 free(op_id);
1290 free(key);
1291 return xml_op;
1292 }
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308 bool
1309 pcmk__action_locks_rsc_to_node(const pcmk_action_t *action)
1310 {
1311
1312 if ((action == NULL) || (action->rsc == NULL)
1313 || !pcmk__same_node(action->node, action->rsc->priv->lock_node)) {
1314 return false;
1315 }
1316
1317
1318
1319
1320 if (action->node->details->shutdown && (action->task != NULL)
1321 && (strcmp(action->task, PCMK_ACTION_STOP) != 0)) {
1322 return false;
1323 }
1324
1325 return true;
1326 }
1327
1328
1329 static gint
1330 sort_action_id(gconstpointer a, gconstpointer b)
1331 {
1332 const pcmk__related_action_t *action_wrapper2 = a;
1333 const pcmk__related_action_t *action_wrapper1 = b;
1334
1335 if (a == NULL) {
1336 return 1;
1337 }
1338 if (b == NULL) {
1339 return -1;
1340 }
1341 if (action_wrapper1->action->id < action_wrapper2->action->id) {
1342 return 1;
1343 }
1344 if (action_wrapper1->action->id > action_wrapper2->action->id) {
1345 return -1;
1346 }
1347 return 0;
1348 }
1349
1350
1351
1352
1353
1354
1355
1356 void
1357 pcmk__deduplicate_action_inputs(pcmk_action_t *action)
1358 {
1359 GList *item = NULL;
1360 GList *next = NULL;
1361 pcmk__related_action_t *last_input = NULL;
1362
1363 action->actions_before = g_list_sort(action->actions_before,
1364 sort_action_id);
1365 for (item = action->actions_before; item != NULL; item = next) {
1366 pcmk__related_action_t *input = item->data;
1367
1368 next = item->next;
1369 if ((last_input != NULL)
1370 && (input->action->id == last_input->action->id)) {
1371 crm_trace("Input %s (%d) duplicate skipped for action %s (%d)",
1372 input->action->uuid, input->action->id,
1373 action->uuid, action->id);
1374
1375
1376
1377
1378
1379 pcmk__set_relation_flags(last_input->flags, input->flags);
1380 if (input->graphed) {
1381 last_input->graphed = true;
1382 }
1383
1384 free(item->data);
1385 action->actions_before = g_list_delete_link(action->actions_before,
1386 item);
1387 } else {
1388 last_input = input;
1389 input->graphed = false;
1390 }
1391 }
1392 }
1393
1394
1395
1396
1397
1398
1399
1400 void
1401 pcmk__output_actions(pcmk_scheduler_t *scheduler)
1402 {
1403 pcmk__output_t *out = scheduler->priv->out;
1404
1405
1406 for (GList *iter = scheduler->priv->actions;
1407 iter != NULL; iter = iter->next) {
1408
1409 char *node_name = NULL;
1410 char *task = NULL;
1411 pcmk_action_t *action = (pcmk_action_t *) iter->data;
1412
1413 if (action->rsc != NULL) {
1414 continue;
1415
1416 } else if (pcmk_is_set(action->flags, pcmk__action_optional)) {
1417 continue;
1418 }
1419
1420 if (pcmk__str_eq(action->task, PCMK_ACTION_DO_SHUTDOWN,
1421 pcmk__str_none)) {
1422 task = strdup("Shutdown");
1423
1424 } else if (pcmk__str_eq(action->task, PCMK_ACTION_STONITH,
1425 pcmk__str_none)) {
1426 const char *op = g_hash_table_lookup(action->meta,
1427 PCMK__META_STONITH_ACTION);
1428
1429 task = crm_strdup_printf("Fence (%s)", op);
1430
1431 } else {
1432 continue;
1433 }
1434
1435 if (pcmk__is_guest_or_bundle_node(action->node)) {
1436 const pcmk_resource_t *remote = action->node->priv->remote;
1437
1438 node_name = crm_strdup_printf("%s (resource: %s)",
1439 pcmk__node_name(action->node),
1440 remote->priv->launcher->id);
1441 } else if (action->node != NULL) {
1442 node_name = crm_strdup_printf("%s", pcmk__node_name(action->node));
1443 }
1444
1445 out->message(out, "node-action", task, node_name, action->reason);
1446
1447 free(node_name);
1448 free(task);
1449 }
1450
1451
1452 for (GList *iter = scheduler->priv->resources;
1453 iter != NULL; iter = iter->next) {
1454
1455 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
1456
1457 rsc->priv->cmds->output_actions(rsc);
1458 }
1459 }
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470 static const char *
1471 task_for_digest(const char *task, guint interval_ms)
1472 {
1473
1474
1475
1476 if ((interval_ms == 0)
1477 && pcmk__str_any_of(task, PCMK_ACTION_MONITOR, PCMK_ACTION_MIGRATE_FROM,
1478 PCMK_ACTION_PROMOTE, NULL)) {
1479 task = PCMK_ACTION_START;
1480 }
1481 return task;
1482 }
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501 static bool
1502 only_sanitized_changed(const xmlNode *xml_op,
1503 const pcmk__op_digest_t *digest_data,
1504 const pcmk_scheduler_t *scheduler)
1505 {
1506 const char *digest_secure = NULL;
1507
1508 if (!pcmk_is_set(scheduler->flags, pcmk__sched_sanitized)) {
1509
1510 return false;
1511 }
1512
1513 digest_secure = crm_element_value(xml_op, PCMK__XA_OP_SECURE_DIGEST);
1514
1515 return (digest_data->rc != pcmk__digest_match) && (digest_secure != NULL)
1516 && (digest_data->digest_secure_calc != NULL)
1517 && (strcmp(digest_data->digest_secure_calc, digest_secure) == 0);
1518 }
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529 static void
1530 force_restart(pcmk_resource_t *rsc, const char *task, guint interval_ms,
1531 pcmk_node_t *node)
1532 {
1533 char *key = pcmk__op_key(rsc->id, task, interval_ms);
1534 pcmk_action_t *required = custom_action(rsc, key, task, NULL, FALSE,
1535 rsc->priv->scheduler);
1536
1537 pe_action_set_reason(required, "resource definition change", true);
1538 trigger_unfencing(rsc, node, "Device parameters changed", NULL,
1539 rsc->priv->scheduler);
1540 }
1541
1542
1543
1544
1545
1546
1547
1548
1549 static void
1550 schedule_reload(gpointer data, gpointer user_data)
1551 {
1552 pcmk_resource_t *rsc = data;
1553 const pcmk_node_t *node = user_data;
1554
1555 pcmk_action_t *reload = NULL;
1556
1557
1558 if (rsc->priv->variant > pcmk__rsc_variant_primitive) {
1559 g_list_foreach(rsc->priv->children, schedule_reload, user_data);
1560 return;
1561 }
1562
1563
1564 if ((node == NULL)
1565 || !pcmk_is_set(rsc->flags, pcmk__rsc_managed)
1566 || pcmk_is_set(rsc->flags, pcmk__rsc_failed)) {
1567 pcmk__rsc_trace(rsc, "Skip reload of %s:%s%s %s",
1568 rsc->id,
1569 pcmk_is_set(rsc->flags, pcmk__rsc_managed)? "" : " unmanaged",
1570 pcmk_is_set(rsc->flags, pcmk__rsc_failed)? " failed" : "",
1571 (node == NULL)? "inactive" : node->priv->name);
1572 return;
1573 }
1574
1575
1576
1577
1578 if (pcmk_is_set(rsc->flags, pcmk__rsc_start_pending)) {
1579 pcmk__rsc_trace(rsc,
1580 "%s: preventing agent reload because start pending",
1581 rsc->id);
1582 custom_action(rsc, stop_key(rsc), PCMK_ACTION_STOP, node, FALSE,
1583 rsc->priv->scheduler);
1584 return;
1585 }
1586
1587
1588 pcmk__set_rsc_flags(rsc, pcmk__rsc_reload);
1589 reload = custom_action(rsc, reload_key(rsc), PCMK_ACTION_RELOAD_AGENT, node,
1590 FALSE, rsc->priv->scheduler);
1591 pe_action_set_reason(reload, "resource definition change", FALSE);
1592
1593
1594 pcmk__new_ordering(NULL, NULL, reload, rsc, stop_key(rsc), NULL,
1595 pcmk__ar_ordered|pcmk__ar_then_cancels_first,
1596 rsc->priv->scheduler);
1597 pcmk__new_ordering(NULL, NULL, reload, rsc, demote_key(rsc), NULL,
1598 pcmk__ar_ordered|pcmk__ar_then_cancels_first,
1599 rsc->priv->scheduler);
1600 }
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616 bool
1617 pcmk__check_action_config(pcmk_resource_t *rsc, pcmk_node_t *node,
1618 const xmlNode *xml_op)
1619 {
1620 guint interval_ms = 0;
1621 const char *task = NULL;
1622 const pcmk__op_digest_t *digest_data = NULL;
1623
1624 CRM_CHECK((rsc != NULL) && (node != NULL) && (xml_op != NULL),
1625 return false);
1626
1627 task = crm_element_value(xml_op, PCMK_XA_OPERATION);
1628 CRM_CHECK(task != NULL, return false);
1629
1630 crm_element_value_ms(xml_op, PCMK_META_INTERVAL, &interval_ms);
1631
1632
1633 if (interval_ms > 0) {
1634 if (pcmk__find_action_config(rsc, task, interval_ms, false) != NULL) {
1635 pcmk__rsc_trace(rsc,
1636 "%s-interval %s for %s on %s is in configuration",
1637 pcmk__readable_interval(interval_ms), task, rsc->id,
1638 pcmk__node_name(node));
1639 } else if (pcmk_is_set(rsc->priv->scheduler->flags,
1640 pcmk__sched_cancel_removed_actions)) {
1641 pcmk__schedule_cancel(rsc,
1642 crm_element_value(xml_op, PCMK__XA_CALL_ID),
1643 task, interval_ms, node, "orphan");
1644 return true;
1645 } else {
1646 pcmk__rsc_debug(rsc, "%s-interval %s for %s on %s is orphaned",
1647 pcmk__readable_interval(interval_ms), task, rsc->id,
1648 pcmk__node_name(node));
1649 return true;
1650 }
1651 }
1652
1653 crm_trace("Checking %s-interval %s for %s on %s for configuration changes",
1654 pcmk__readable_interval(interval_ms), task, rsc->id,
1655 pcmk__node_name(node));
1656 task = task_for_digest(task, interval_ms);
1657 digest_data = rsc_action_digest_cmp(rsc, xml_op, node,
1658 rsc->priv->scheduler);
1659
1660 if (only_sanitized_changed(xml_op, digest_data, rsc->priv->scheduler)) {
1661 if (!pcmk__is_daemon && (rsc->priv->scheduler->priv->out != NULL)) {
1662 pcmk__output_t *out = rsc->priv->scheduler->priv->out;
1663
1664 out->info(out,
1665 "Only 'private' parameters to %s-interval %s for %s "
1666 "on %s changed: %s",
1667 pcmk__readable_interval(interval_ms), task, rsc->id,
1668 pcmk__node_name(node),
1669 crm_element_value(xml_op, PCMK__XA_TRANSITION_MAGIC));
1670 }
1671 return false;
1672 }
1673
1674 switch (digest_data->rc) {
1675 case pcmk__digest_restart:
1676 crm_log_xml_debug(digest_data->params_restart, "params:restart");
1677 force_restart(rsc, task, interval_ms, node);
1678 return true;
1679
1680 case pcmk__digest_unknown:
1681 case pcmk__digest_mismatch:
1682
1683
1684 if (interval_ms > 0) {
1685
1686
1687
1688
1689 crm_log_xml_debug(digest_data->params_all, "params:reschedule");
1690 pcmk__reschedule_recurring(rsc, task, interval_ms, node);
1691
1692 } else if (crm_element_value(xml_op,
1693 PCMK__XA_OP_RESTART_DIGEST) != NULL) {
1694
1695 trigger_unfencing(rsc, node,
1696 "Device parameters changed (reload)", NULL,
1697 rsc->priv->scheduler);
1698 crm_log_xml_debug(digest_data->params_all, "params:reload");
1699 schedule_reload((gpointer) rsc, (gpointer) node);
1700
1701 } else {
1702 pcmk__rsc_trace(rsc,
1703 "Restarting %s "
1704 "because agent doesn't support reload",
1705 rsc->id);
1706 crm_log_xml_debug(digest_data->params_restart,
1707 "params:restart");
1708 force_restart(rsc, task, interval_ms, node);
1709 }
1710 return true;
1711
1712 default:
1713 break;
1714 }
1715 return false;
1716 }
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726 static GList *
1727 rsc_history_as_list(const xmlNode *rsc_entry, int *start_index, int *stop_index)
1728 {
1729 GList *ops = NULL;
1730
1731 for (xmlNode *rsc_op = pcmk__xe_first_child(rsc_entry, PCMK__XE_LRM_RSC_OP,
1732 NULL, NULL);
1733 rsc_op != NULL; rsc_op = pcmk__xe_next(rsc_op, PCMK__XE_LRM_RSC_OP)) {
1734
1735 ops = g_list_prepend(ops, rsc_op);
1736 }
1737 ops = g_list_sort(ops, sort_op_by_callid);
1738 calculate_active_ops(ops, start_index, stop_index);
1739 return ops;
1740 }
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756 static void
1757 process_rsc_history(const xmlNode *rsc_entry, pcmk_resource_t *rsc,
1758 pcmk_node_t *node)
1759 {
1760 int offset = -1;
1761 int stop_index = 0;
1762 int start_index = 0;
1763 GList *sorted_op_list = NULL;
1764
1765 if (pcmk_is_set(rsc->flags, pcmk__rsc_removed)) {
1766 if (pcmk__is_anonymous_clone(pe__const_top_resource(rsc, false))) {
1767 pcmk__rsc_trace(rsc,
1768 "Skipping configuration check "
1769 "for orphaned clone instance %s",
1770 rsc->id);
1771 } else {
1772 pcmk__rsc_trace(rsc,
1773 "Skipping configuration check and scheduling "
1774 "clean-up for orphaned resource %s", rsc->id);
1775 pcmk__schedule_cleanup(rsc, node, false);
1776 }
1777 return;
1778 }
1779
1780 if (pe_find_node_id(rsc->priv->active_nodes,
1781 node->priv->id) == NULL) {
1782 if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, false)) {
1783 pcmk__schedule_cleanup(rsc, node, false);
1784 }
1785 pcmk__rsc_trace(rsc,
1786 "Skipping configuration check for %s "
1787 "because no longer active on %s",
1788 rsc->id, pcmk__node_name(node));
1789 return;
1790 }
1791
1792 pcmk__rsc_trace(rsc, "Checking for configuration changes for %s on %s",
1793 rsc->id, pcmk__node_name(node));
1794
1795 if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, true)) {
1796 pcmk__schedule_cleanup(rsc, node, false);
1797 }
1798
1799 sorted_op_list = rsc_history_as_list(rsc_entry, &start_index, &stop_index);
1800 if (start_index < stop_index) {
1801 return;
1802 }
1803
1804 for (GList *iter = sorted_op_list; iter != NULL; iter = iter->next) {
1805 xmlNode *rsc_op = (xmlNode *) iter->data;
1806 const char *task = NULL;
1807 guint interval_ms = 0;
1808
1809 if (++offset < start_index) {
1810
1811 continue;
1812 }
1813
1814 task = crm_element_value(rsc_op, PCMK_XA_OPERATION);
1815 crm_element_value_ms(rsc_op, PCMK_META_INTERVAL, &interval_ms);
1816
1817 if ((interval_ms > 0)
1818 && (pcmk_is_set(rsc->flags, pcmk__rsc_maintenance)
1819 || node->details->maintenance)) {
1820
1821 pcmk__schedule_cancel(rsc,
1822 crm_element_value(rsc_op, PCMK__XA_CALL_ID),
1823 task, interval_ms, node, "maintenance mode");
1824
1825 } else if ((interval_ms > 0)
1826 || pcmk__strcase_any_of(task, PCMK_ACTION_MONITOR,
1827 PCMK_ACTION_START,
1828 PCMK_ACTION_PROMOTE,
1829 PCMK_ACTION_MIGRATE_FROM, NULL)) {
1830
1831
1832
1833
1834 if (pe__bundle_needs_remote_name(rsc)) {
1835
1836
1837
1838
1839
1840
1841
1842 pe__add_param_check(rsc_op, rsc, node, pcmk__check_active,
1843 rsc->priv->scheduler);
1844
1845 } else if (pcmk__check_action_config(rsc, node, rsc_op)
1846 && (pe_get_failcount(node, rsc, NULL, pcmk__fc_effective,
1847 NULL) != 0)) {
1848 pe__clear_failcount(rsc, node, "action definition changed",
1849 rsc->priv->scheduler);
1850 }
1851 }
1852 }
1853 g_list_free(sorted_op_list);
1854 }
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869 static void
1870 process_node_history(pcmk_node_t *node, const xmlNode *lrm_rscs)
1871 {
1872 crm_trace("Processing node history for %s", pcmk__node_name(node));
1873 for (const xmlNode *rsc_entry = pcmk__xe_first_child(lrm_rscs,
1874 PCMK__XE_LRM_RESOURCE,
1875 NULL, NULL);
1876 rsc_entry != NULL;
1877 rsc_entry = pcmk__xe_next(rsc_entry, PCMK__XE_LRM_RESOURCE)) {
1878
1879 if (rsc_entry->children != NULL) {
1880 GList *result = pcmk__rscs_matching_id(pcmk__xe_id(rsc_entry),
1881 node->priv->scheduler);
1882
1883 for (GList *iter = result; iter != NULL; iter = iter->next) {
1884 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
1885
1886 if (pcmk__is_primitive(rsc)) {
1887 process_rsc_history(rsc_entry, rsc, node);
1888 }
1889 }
1890 g_list_free(result);
1891 }
1892 }
1893 }
1894
1895
1896 #define XPATH_NODE_HISTORY "/" PCMK_XE_CIB "/" PCMK_XE_STATUS \
1897 "/" PCMK__XE_NODE_STATE \
1898 "[@" PCMK_XA_UNAME "='%s']" \
1899 "/" PCMK__XE_LRM "/" PCMK__XE_LRM_RESOURCES
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913 void
1914 pcmk__handle_rsc_config_changes(pcmk_scheduler_t *scheduler)
1915 {
1916 crm_trace("Check resource and action configuration for changes");
1917
1918
1919
1920
1921
1922 for (GList *iter = scheduler->nodes; iter != NULL; iter = iter->next) {
1923 pcmk_node_t *node = (pcmk_node_t *) iter->data;
1924
1925
1926
1927
1928
1929 if (node->details->maintenance
1930 || pcmk__node_available(node, false, false)) {
1931
1932 char *xpath = NULL;
1933 xmlNode *history = NULL;
1934
1935 xpath = crm_strdup_printf(XPATH_NODE_HISTORY, node->priv->name);
1936 history = get_xpath_object(xpath, scheduler->input, LOG_NEVER);
1937 free(xpath);
1938
1939 process_node_history(node, history);
1940 }
1941 }
1942 }