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->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->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 action_tasks first_task = pcmk_action_unspecified;
101 enum action_tasks remapped_task = pcmk_action_unspecified;
102
103
104 if ((strstr(first_uuid, PCMK_ACTION_NOTIFY) != NULL)
105 || (first_rsc->variant < pcmk_rsc_variant_group)) {
106 goto done;
107 }
108
109
110 CRM_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) && (rsc->variant >= pcmk_rsc_variant_group)
185 && (action->uuid != NULL)) {
186 char *uuid = action_uuid_for_ordering(action->uuid, rsc);
187
188 result = find_first_action(rsc->actions, uuid, NULL, NULL);
189 if (result == NULL) {
190 crm_warn("Not remapping %s to %s because %s does not have "
191 "remapped action", action->uuid, uuid, rsc->id);
192 result = action;
193 }
194 free(uuid);
195 }
196 return result;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 static inline uint32_t
219 update(pcmk_resource_t *rsc, pcmk_action_t *first, pcmk_action_t *then,
220 const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type,
221 pcmk_scheduler_t *scheduler)
222 {
223 return rsc->cmds->update_ordered_actions(first, then, node, flags, filter,
224 type, scheduler);
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 static uint32_t
241 update_action_for_ordering_flags(pcmk_action_t *first, pcmk_action_t *then,
242 uint32_t first_flags, uint32_t then_flags,
243 pcmk__related_action_t *order,
244 pcmk_scheduler_t *scheduler)
245 {
246 uint32_t changed = pcmk__updated_none;
247
248
249
250
251
252
253 pcmk_node_t *node = then->node;
254
255 if (pcmk_is_set(order->type, pcmk__ar_first_implies_same_node_then)) {
256
257
258
259
260
261 pcmk__clear_relation_flags(order->type,
262 pcmk__ar_first_implies_same_node_then);
263 pcmk__set_relation_flags(order->type, pcmk__ar_first_implies_then);
264 node = first->node;
265 pcmk__rsc_trace(then->rsc,
266 "%s then %s: mapped "
267 "pcmk__ar_first_implies_same_node_then to "
268 "pcmk__ar_first_implies_then on %s",
269 first->uuid, then->uuid, pcmk__node_name(node));
270 }
271
272 if (pcmk_is_set(order->type, pcmk__ar_first_implies_then)) {
273 if (then->rsc != NULL) {
274 changed |= update(then->rsc, first, then, node,
275 first_flags & pcmk_action_optional,
276 pcmk_action_optional, pcmk__ar_first_implies_then,
277 scheduler);
278 } else if (!pcmk_is_set(first_flags, pcmk_action_optional)
279 && pcmk_is_set(then->flags, pcmk_action_optional)) {
280 pcmk__clear_action_flags(then, pcmk_action_optional);
281 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
282 }
283 pcmk__rsc_trace(then->rsc,
284 "%s then %s: %s after pcmk__ar_first_implies_then",
285 first->uuid, then->uuid,
286 (changed? "changed" : "unchanged"));
287 }
288
289 if (pcmk_is_set(order->type, pcmk__ar_intermediate_stop)
290 && (then->rsc != NULL)) {
291 enum pe_action_flags restart = pcmk_action_optional
292 |pcmk_action_runnable;
293
294 changed |= update(then->rsc, first, then, node, first_flags, restart,
295 pcmk__ar_intermediate_stop, scheduler);
296 pcmk__rsc_trace(then->rsc,
297 "%s then %s: %s after pcmk__ar_intermediate_stop",
298 first->uuid, then->uuid,
299 (changed? "changed" : "unchanged"));
300 }
301
302 if (pcmk_is_set(order->type, pcmk__ar_then_implies_first)) {
303 if (first->rsc != NULL) {
304 changed |= update(first->rsc, first, then, node, first_flags,
305 pcmk_action_optional, pcmk__ar_then_implies_first,
306 scheduler);
307 } else if (!pcmk_is_set(first_flags, pcmk_action_optional)
308 && pcmk_is_set(first->flags, pcmk_action_runnable)) {
309 pcmk__clear_action_flags(first, pcmk_action_runnable);
310 pcmk__set_updated_flags(changed, first, pcmk__updated_first);
311 }
312 pcmk__rsc_trace(then->rsc,
313 "%s then %s: %s after pcmk__ar_then_implies_first",
314 first->uuid, then->uuid,
315 (changed? "changed" : "unchanged"));
316 }
317
318 if (pcmk_is_set(order->type, pcmk__ar_promoted_then_implies_first)) {
319 if (then->rsc != NULL) {
320 changed |= update(then->rsc, first, then, node,
321 first_flags & pcmk_action_optional,
322 pcmk_action_optional,
323 pcmk__ar_promoted_then_implies_first, scheduler);
324 }
325 pcmk__rsc_trace(then->rsc,
326 "%s then %s: %s after "
327 "pcmk__ar_promoted_then_implies_first",
328 first->uuid, then->uuid,
329 (changed? "changed" : "unchanged"));
330 }
331
332 if (pcmk_is_set(order->type, pcmk__ar_min_runnable)) {
333 if (then->rsc != NULL) {
334 changed |= update(then->rsc, first, then, node, first_flags,
335 pcmk_action_runnable, pcmk__ar_min_runnable,
336 scheduler);
337
338 } else if (pcmk_is_set(first_flags, pcmk_action_runnable)) {
339
340 then->runnable_before++;
341
342
343
344
345 if ((then->runnable_before >= then->required_runnable_before)
346 && !pcmk_is_set(then->flags, pcmk_action_runnable)) {
347
348 pcmk__set_action_flags(then, pcmk_action_runnable);
349 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
350 }
351 }
352 pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_min_runnable",
353 first->uuid, then->uuid,
354 (changed? "changed" : "unchanged"));
355 }
356
357 if (pcmk_is_set(order->type, pcmk__ar_nested_remote_probe)
358 && (then->rsc != NULL)) {
359
360 if (!pcmk_is_set(first_flags, pcmk_action_runnable)
361 && (first->rsc != NULL) && (first->rsc->running_on != NULL)) {
362
363 pcmk__rsc_trace(then->rsc,
364 "%s then %s: ignoring because first is stopping",
365 first->uuid, then->uuid);
366 order->type = (enum pe_ordering) pcmk__ar_none;
367 } else {
368 changed |= update(then->rsc, first, then, node, first_flags,
369 pcmk_action_runnable,
370 pcmk__ar_unrunnable_first_blocks, scheduler);
371 }
372 pcmk__rsc_trace(then->rsc,
373 "%s then %s: %s after pcmk__ar_nested_remote_probe",
374 first->uuid, then->uuid,
375 (changed? "changed" : "unchanged"));
376 }
377
378 if (pcmk_is_set(order->type, pcmk__ar_unrunnable_first_blocks)) {
379 if (then->rsc != NULL) {
380 changed |= update(then->rsc, first, then, node, first_flags,
381 pcmk_action_runnable,
382 pcmk__ar_unrunnable_first_blocks, scheduler);
383
384 } else if (!pcmk_is_set(first_flags, pcmk_action_runnable)
385 && pcmk_is_set(then->flags, pcmk_action_runnable)) {
386
387 pcmk__clear_action_flags(then, pcmk_action_runnable);
388 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
389 }
390 pcmk__rsc_trace(then->rsc,
391 "%s then %s: %s after pcmk__ar_unrunnable_first_blocks",
392 first->uuid, then->uuid,
393 (changed? "changed" : "unchanged"));
394 }
395
396 if (pcmk_is_set(order->type, pcmk__ar_unmigratable_then_blocks)) {
397 if (then->rsc != NULL) {
398 changed |= update(then->rsc, first, then, node, first_flags,
399 pcmk_action_optional,
400 pcmk__ar_unmigratable_then_blocks, scheduler);
401 }
402 pcmk__rsc_trace(then->rsc,
403 "%s then %s: %s after "
404 "pcmk__ar_unmigratable_then_blocks",
405 first->uuid, then->uuid,
406 (changed? "changed" : "unchanged"));
407 }
408
409 if (pcmk_is_set(order->type, pcmk__ar_first_else_then)) {
410 if (then->rsc != NULL) {
411 changed |= update(then->rsc, first, then, node, first_flags,
412 pcmk_action_optional, pcmk__ar_first_else_then,
413 scheduler);
414 }
415 pcmk__rsc_trace(then->rsc,
416 "%s then %s: %s after pcmk__ar_first_else_then",
417 first->uuid, then->uuid,
418 (changed? "changed" : "unchanged"));
419 }
420
421 if (pcmk_is_set(order->type, pcmk__ar_ordered)) {
422 if (then->rsc != NULL) {
423 changed |= update(then->rsc, first, then, node, first_flags,
424 pcmk_action_runnable, pcmk__ar_ordered,
425 scheduler);
426 }
427 pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_ordered",
428 first->uuid, then->uuid,
429 (changed? "changed" : "unchanged"));
430 }
431
432 if (pcmk_is_set(order->type, pcmk__ar_asymmetric)) {
433 if (then->rsc != NULL) {
434 changed |= update(then->rsc, first, then, node, first_flags,
435 pcmk_action_runnable, pcmk__ar_asymmetric,
436 scheduler);
437 }
438 pcmk__rsc_trace(then->rsc, "%s then %s: %s after pcmk__ar_asymmetric",
439 first->uuid, then->uuid,
440 (changed? "changed" : "unchanged"));
441 }
442
443 if (pcmk_is_set(first->flags, pcmk_action_runnable)
444 && pcmk_is_set(order->type, pcmk__ar_first_implies_then_graphed)
445 && !pcmk_is_set(first_flags, pcmk_action_optional)) {
446
447 pcmk__rsc_trace(then->rsc, "%s will be in graph because %s is required",
448 then->uuid, first->uuid);
449 pcmk__set_action_flags(then, pcmk_action_always_in_graph);
450
451 }
452
453 if (pcmk_is_set(order->type, pcmk__ar_then_implies_first_graphed)
454 && !pcmk_is_set(then_flags, pcmk_action_optional)) {
455
456 pcmk__rsc_trace(then->rsc, "%s will be in graph because %s is required",
457 first->uuid, then->uuid);
458 pcmk__set_action_flags(first, pcmk_action_always_in_graph);
459
460 }
461
462 if (pcmk_any_flags_set(order->type, pcmk__ar_first_implies_then
463 |pcmk__ar_then_implies_first
464 |pcmk__ar_intermediate_stop)
465 && (first->rsc != NULL)
466 && !pcmk_is_set(first->rsc->flags, pcmk_rsc_managed)
467 && pcmk_is_set(first->rsc->flags, pcmk_rsc_blocked)
468 && !pcmk_is_set(first->flags, pcmk_action_runnable)
469 && pcmk__str_eq(first->task, PCMK_ACTION_STOP, pcmk__str_none)) {
470
471 if (pcmk_is_set(then->flags, pcmk_action_runnable)) {
472 pcmk__clear_action_flags(then, pcmk_action_runnable);
473 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
474 }
475 pcmk__rsc_trace(then->rsc,
476 "%s then %s: %s after checking whether first "
477 "is blocked, unmanaged, unrunnable stop",
478 first->uuid, then->uuid,
479 (changed? "changed" : "unchanged"));
480 }
481
482 return changed;
483 }
484
485
486
487 #define action_type_str(flags) \
488 (pcmk_is_set((flags), pcmk_action_pseudo)? "pseudo-action" : "action")
489
490 #define action_optional_str(flags) \
491 (pcmk_is_set((flags), pcmk_action_optional)? "optional" : "required")
492
493 #define action_runnable_str(flags) \
494 (pcmk_is_set((flags), pcmk_action_runnable)? "runnable" : "unrunnable")
495
496 #define action_node_str(a) \
497 (((a)->node == NULL)? "no node" : (a)->node->details->uname)
498
499
500
501
502
503
504
505
506 void
507 pcmk__update_action_for_orderings(pcmk_action_t *then,
508 pcmk_scheduler_t *scheduler)
509 {
510 GList *lpc = NULL;
511 uint32_t changed = pcmk__updated_none;
512 int last_flags = then->flags;
513
514 pcmk__rsc_trace(then->rsc, "Updating %s %s (%s %s) on %s",
515 action_type_str(then->flags), then->uuid,
516 action_optional_str(then->flags),
517 action_runnable_str(then->flags), action_node_str(then));
518
519 if (pcmk_is_set(then->flags, pcmk_action_min_runnable)) {
520
521
522
523
524
525 then->runnable_before = 0;
526
527 if (then->required_runnable_before == 0) {
528
529
530
531
532 then->required_runnable_before = 1;
533 }
534
535
536
537
538
539 pcmk__clear_action_flags(then, pcmk_action_runnable);
540 }
541
542 for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) {
543 pcmk__related_action_t *other = lpc->data;
544 pcmk_action_t *first = other->action;
545
546 pcmk_node_t *then_node = then->node;
547 pcmk_node_t *first_node = first->node;
548
549 if ((first->rsc != NULL)
550 && pcmk__is_group(first->rsc)
551 && pcmk__str_eq(first->task, PCMK_ACTION_START, pcmk__str_none)) {
552
553 first_node = first->rsc->fns->location(first->rsc, NULL, FALSE);
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->fns->location(then->rsc, NULL, FALSE);
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->type, 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->type = (enum pe_ordering) 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->type, 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->type, 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->type)) {
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->type = (enum pe_ordering) 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 (pcmk_is_set(then->flags, pcmk_action_min_runnable)) {
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 = then->rsc->fns->state(then->rsc, TRUE);
730
731 if ((then_rsc_role == pcmk_role_stopped)
732 && pcmk__str_eq(then->task, PCMK_ACTION_STOP, pcmk__str_none)) {
733
734
735
736 return;
737 } else if ((then_rsc_role >= pcmk_role_started)
738 && pcmk__str_eq(then->task, PCMK_ACTION_START, pcmk__str_none)
739 && pe__rsc_running_on_only(then->rsc, then->node)) {
740
741
742
743 return;
744 }
745 }
746
747
748 clear_action_flag_because(then, pcmk_action_optional, first);
749 clear_action_flag_because(then, pcmk_action_runnable, first);
750 }
751
752
753
754
755
756
757
758
759
760
761
762
763 static void
764 handle_restart_ordering(pcmk_action_t *first, pcmk_action_t *then,
765 uint32_t filter)
766 {
767 const char *reason = NULL;
768
769 CRM_ASSERT(is_primitive_action(first));
770 CRM_ASSERT(is_primitive_action(then));
771
772
773
774
775 if (pcmk_is_set(filter, pcmk_action_optional)
776 && !pcmk_is_set(then->flags, pcmk_action_optional)) {
777 reason = "restart";
778 }
779
780
781
782
783 if (pcmk_is_set(filter, pcmk_action_runnable)
784 && !pcmk_is_set(then->flags, pcmk_action_runnable)
785 && pcmk_is_set(then->rsc->flags, pcmk_rsc_managed)
786 && (first->rsc == then->rsc)) {
787 reason = "stop";
788 }
789
790 if (reason == NULL) {
791 return;
792 }
793
794 pcmk__rsc_trace(first->rsc, "Handling %s -> %s for %s",
795 first->uuid, then->uuid, reason);
796
797
798 if (pcmk_is_set(first->flags, pcmk_action_runnable)) {
799 clear_action_flag_because(first, pcmk_action_optional, then);
800 }
801
802
803 if (!pcmk_is_set(then->flags, pcmk_action_optional)) {
804 clear_action_flag_because(first, pcmk_action_optional, then);
805 }
806
807
808 if (!pcmk_is_set(then->flags, pcmk_action_migratable)) {
809 clear_action_flag_because(first, pcmk_action_migratable, then);
810 }
811
812
813 if (!pcmk_is_set(first->flags, pcmk_action_optional)
814 && !pcmk_is_set(first->flags, pcmk_action_runnable)) {
815 clear_action_flag_because(then, pcmk_action_runnable, first);
816 }
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 uint32_t
842 pcmk__update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then,
843 const pcmk_node_t *node, uint32_t flags,
844 uint32_t filter, uint32_t type,
845 pcmk_scheduler_t *scheduler)
846 {
847 uint32_t changed = pcmk__updated_none;
848 uint32_t then_flags = 0U;
849 uint32_t first_flags = 0U;
850
851 CRM_ASSERT((first != NULL) && (then != NULL) && (scheduler != NULL));
852
853 then_flags = then->flags;
854 first_flags = first->flags;
855 if (pcmk_is_set(type, pcmk__ar_asymmetric)) {
856 handle_asymmetric_ordering(first, then);
857 }
858
859 if (pcmk_is_set(type, pcmk__ar_then_implies_first)
860 && !pcmk_is_set(then_flags, pcmk_action_optional)) {
861
862
863 if (pcmk_is_set(filter, pcmk_action_optional)
864 && !pcmk_is_set(flags, pcmk_action_optional)
865 && pcmk_is_set(first_flags, pcmk_action_optional)) {
866 clear_action_flag_because(first, pcmk_action_optional, then);
867 }
868
869 if (pcmk_is_set(flags, pcmk_action_migratable)
870 && !pcmk_is_set(then->flags, pcmk_action_migratable)) {
871 clear_action_flag_because(first, pcmk_action_migratable, then);
872 }
873 }
874
875 if (pcmk_is_set(type, pcmk__ar_promoted_then_implies_first)
876 && (then->rsc != NULL) && (then->rsc->role == pcmk_role_promoted)
877 && pcmk_is_set(filter, pcmk_action_optional)
878 && !pcmk_is_set(then->flags, pcmk_action_optional)) {
879
880 clear_action_flag_because(first, pcmk_action_optional, then);
881
882 if (pcmk_is_set(first->flags, pcmk_action_migratable)
883 && !pcmk_is_set(then->flags, pcmk_action_migratable)) {
884 clear_action_flag_because(first, pcmk_action_migratable, then);
885 }
886 }
887
888 if (pcmk_is_set(type, pcmk__ar_unmigratable_then_blocks)
889 && pcmk_is_set(filter, pcmk_action_optional)) {
890
891 if (!pcmk_all_flags_set(then->flags, pcmk_action_migratable
892 |pcmk_action_runnable)) {
893 clear_action_flag_because(first, pcmk_action_runnable, then);
894 }
895
896 if (!pcmk_is_set(then->flags, pcmk_action_optional)) {
897 clear_action_flag_because(first, pcmk_action_optional, then);
898 }
899 }
900
901 if (pcmk_is_set(type, pcmk__ar_first_else_then)
902 && pcmk_is_set(filter, pcmk_action_optional)
903 && !pcmk_is_set(first->flags, pcmk_action_runnable)) {
904
905 clear_action_flag_because(then, pcmk_action_migratable, first);
906 pcmk__clear_action_flags(then, pcmk_action_pseudo);
907 }
908
909 if (pcmk_is_set(type, pcmk__ar_unrunnable_first_blocks)
910 && pcmk_is_set(filter, pcmk_action_runnable)
911 && pcmk_is_set(then->flags, pcmk_action_runnable)
912 && !pcmk_is_set(flags, pcmk_action_runnable)) {
913
914 clear_action_flag_because(then, pcmk_action_runnable, first);
915 clear_action_flag_because(then, pcmk_action_migratable, first);
916 }
917
918 if (pcmk_is_set(type, pcmk__ar_first_implies_then)
919 && pcmk_is_set(filter, pcmk_action_optional)
920 && pcmk_is_set(then->flags, pcmk_action_optional)
921 && !pcmk_is_set(flags, pcmk_action_optional)
922 && !pcmk_is_set(first->flags, pcmk_action_migratable)) {
923
924 clear_action_flag_because(then, pcmk_action_optional, first);
925 }
926
927 if (pcmk_is_set(type, pcmk__ar_intermediate_stop)) {
928 handle_restart_ordering(first, then, filter);
929 }
930
931 if (then_flags != then->flags) {
932 pcmk__set_updated_flags(changed, first, pcmk__updated_then);
933 pcmk__rsc_trace(then->rsc,
934 "%s on %s: flags are now %#.6x (was %#.6x) "
935 "because of 'first' %s (%#.6x)",
936 then->uuid, pcmk__node_name(then->node),
937 then->flags, then_flags, first->uuid, first->flags);
938
939 if ((then->rsc != NULL) && (then->rsc->parent != NULL)) {
940
941 pcmk__update_action_for_orderings(then, scheduler);
942 }
943 }
944
945 if (first_flags != first->flags) {
946 pcmk__set_updated_flags(changed, first, pcmk__updated_first);
947 pcmk__rsc_trace(first->rsc,
948 "%s on %s: flags are now %#.6x (was %#.6x) "
949 "because of 'then' %s (%#.6x)",
950 first->uuid, pcmk__node_name(first->node),
951 first->flags, first_flags, then->uuid, then->flags);
952 }
953
954 return changed;
955 }
956
957
958
959
960
961
962
963
964
965 void
966 pcmk__log_action(const char *pre_text, const pcmk_action_t *action,
967 bool details)
968 {
969 const char *node_uname = NULL;
970 const char *node_uuid = NULL;
971 const char *desc = NULL;
972
973 CRM_CHECK(action != NULL, return);
974
975 if (!pcmk_is_set(action->flags, pcmk_action_pseudo)) {
976 if (action->node != NULL) {
977 node_uname = action->node->details->uname;
978 node_uuid = action->node->details->id;
979 } else {
980 node_uname = "<none>";
981 }
982 }
983
984 switch (pcmk_parse_action(action->task)) {
985 case pcmk_action_fence:
986 case pcmk_action_shutdown:
987 if (pcmk_is_set(action->flags, pcmk_action_pseudo)) {
988 desc = "Pseudo ";
989 } else if (pcmk_is_set(action->flags, pcmk_action_optional)) {
990 desc = "Optional ";
991 } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
992 desc = "!!Non-Startable!! ";
993 } else {
994 desc = "(Provisional) ";
995 }
996 crm_trace("%s%s%sAction %d: %s%s%s%s%s%s",
997 ((pre_text == NULL)? "" : pre_text),
998 ((pre_text == NULL)? "" : ": "),
999 desc, action->id, action->uuid,
1000 (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
1001 (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
1002 (node_uuid? ")" : ""));
1003 break;
1004 default:
1005 if (pcmk_is_set(action->flags, pcmk_action_optional)) {
1006 desc = "Optional ";
1007 } else if (pcmk_is_set(action->flags, pcmk_action_pseudo)) {
1008 desc = "Pseudo ";
1009 } else if (!pcmk_is_set(action->flags, pcmk_action_runnable)) {
1010 desc = "!!Non-Startable!! ";
1011 } else {
1012 desc = "(Provisional) ";
1013 }
1014 crm_trace("%s%s%sAction %d: %s %s%s%s%s%s%s",
1015 ((pre_text == NULL)? "" : pre_text),
1016 ((pre_text == NULL)? "" : ": "),
1017 desc, action->id, action->uuid,
1018 (action->rsc? action->rsc->id : "<none>"),
1019 (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
1020 (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
1021 (node_uuid? ")" : ""));
1022 break;
1023 }
1024
1025 if (details) {
1026 const GList *iter = NULL;
1027 const pcmk__related_action_t *other = NULL;
1028
1029 crm_trace("\t\t====== Preceding Actions");
1030 for (iter = action->actions_before; iter != NULL; iter = iter->next) {
1031 other = (const pcmk__related_action_t *) iter->data;
1032 pcmk__log_action("\t\t", other->action, false);
1033 }
1034 crm_trace("\t\t====== Subsequent Actions");
1035 for (iter = action->actions_after; iter != NULL; iter = iter->next) {
1036 other = (const pcmk__related_action_t *) iter->data;
1037 pcmk__log_action("\t\t", other->action, false);
1038 }
1039 crm_trace("\t\t====== End");
1040
1041 } else {
1042 crm_trace("\t\t(before=%d, after=%d)",
1043 g_list_length(action->actions_before),
1044 g_list_length(action->actions_after));
1045 }
1046 }
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 pcmk_action_t *
1057 pcmk__new_shutdown_action(pcmk_node_t *node)
1058 {
1059 char *shutdown_id = NULL;
1060 pcmk_action_t *shutdown_op = NULL;
1061
1062 CRM_ASSERT(node != NULL);
1063
1064 shutdown_id = crm_strdup_printf("%s-%s", PCMK_ACTION_DO_SHUTDOWN,
1065 node->details->uname);
1066
1067 shutdown_op = custom_action(NULL, shutdown_id, PCMK_ACTION_DO_SHUTDOWN,
1068 node, FALSE, node->details->data_set);
1069
1070 pcmk__order_stops_before_shutdown(node, shutdown_op);
1071 pcmk__insert_meta(shutdown_op, PCMK__META_OP_NO_WAIT, PCMK_VALUE_TRUE);
1072 return shutdown_op;
1073 }
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086 static void
1087 add_op_digest_to_xml(const lrmd_event_data_t *op, xmlNode *update)
1088 {
1089 char *digest = NULL;
1090 xmlNode *args_xml = NULL;
1091
1092 if (op->params == NULL) {
1093 return;
1094 }
1095 args_xml = pcmk__xe_create(NULL, PCMK_XE_PARAMETERS);
1096 g_hash_table_foreach(op->params, hash2field, args_xml);
1097 pcmk__filter_op_for_digest(args_xml);
1098 digest = calculate_operation_digest(args_xml, NULL);
1099 crm_xml_add(update, PCMK__XA_OP_DIGEST, digest);
1100 free_xml(args_xml);
1101 free(digest);
1102 }
1103
1104 #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119 xmlNode *
1120 pcmk__create_history_xml(xmlNode *parent, lrmd_event_data_t *op,
1121 const char *caller_version, int target_rc,
1122 const char *node, const char *origin)
1123 {
1124 char *key = NULL;
1125 char *magic = NULL;
1126 char *op_id = NULL;
1127 char *op_id_additional = NULL;
1128 char *local_user_data = NULL;
1129 const char *exit_reason = NULL;
1130
1131 xmlNode *xml_op = NULL;
1132 const char *task = NULL;
1133
1134 CRM_CHECK(op != NULL, return NULL);
1135 crm_trace("Creating history XML for %s-interval %s action for %s on %s "
1136 "(DC version: %s, origin: %s)",
1137 pcmk__readable_interval(op->interval_ms), op->op_type, op->rsc_id,
1138 ((node == NULL)? "no node" : node), caller_version, origin);
1139
1140 task = op->op_type;
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151 if (pcmk__str_any_of(task, PCMK_ACTION_RELOAD, PCMK_ACTION_RELOAD_AGENT,
1152 NULL)) {
1153 if (op->op_status == PCMK_EXEC_DONE) {
1154 task = PCMK_ACTION_START;
1155 } else {
1156 task = PCMK_ACTION_MONITOR;
1157 }
1158 }
1159
1160 key = pcmk__op_key(op->rsc_id, task, op->interval_ms);
1161 if (pcmk__str_eq(task, PCMK_ACTION_NOTIFY, pcmk__str_none)) {
1162 const char *n_type = crm_meta_value(op->params, "notify_type");
1163 const char *n_task = crm_meta_value(op->params, "notify_operation");
1164
1165 CRM_LOG_ASSERT(n_type != NULL);
1166 CRM_LOG_ASSERT(n_task != NULL);
1167 op_id = pcmk__notify_key(op->rsc_id, n_type, n_task);
1168
1169 if (op->op_status != PCMK_EXEC_PENDING) {
1170
1171
1172
1173
1174
1175 lrmd__set_result(op, PCMK_OCF_OK, PCMK_EXEC_DONE, NULL);
1176 }
1177
1178
1179
1180
1181 } else if (pcmk__str_any_of(op->op_type, PCMK_ACTION_MIGRATE_TO,
1182 PCMK_ACTION_MIGRATE_FROM, NULL)) {
1183 op_id = strdup(key);
1184
1185 } else if (did_rsc_op_fail(op, target_rc)) {
1186 op_id = pcmk__op_key(op->rsc_id, "last_failure", 0);
1187 if (op->interval_ms == 0) {
1188
1189
1190
1191 op_id_additional = pcmk__op_key(op->rsc_id, "last", 0);
1192 }
1193 exit_reason = op->exit_reason;
1194
1195 } else if (op->interval_ms > 0) {
1196 op_id = strdup(key);
1197
1198 } else {
1199 op_id = pcmk__op_key(op->rsc_id, "last", 0);
1200 }
1201
1202 again:
1203 xml_op = pcmk__xe_first_child(parent, PCMK__XE_LRM_RSC_OP, PCMK_XA_ID,
1204 op_id);
1205 if (xml_op == NULL) {
1206 xml_op = pcmk__xe_create(parent, PCMK__XE_LRM_RSC_OP);
1207 }
1208
1209 if (op->user_data == NULL) {
1210 crm_debug("Generating fake transition key for: " PCMK__OP_FMT
1211 " %d from %s", op->rsc_id, op->op_type, op->interval_ms,
1212 op->call_id, origin);
1213 local_user_data = pcmk__transition_key(-1, op->call_id, target_rc,
1214 FAKE_TE_ID);
1215 op->user_data = local_user_data;
1216 }
1217
1218 if (magic == NULL) {
1219 magic = crm_strdup_printf("%d:%d;%s", op->op_status, op->rc,
1220 (const char *) op->user_data);
1221 }
1222
1223 crm_xml_add(xml_op, PCMK_XA_ID, op_id);
1224 crm_xml_add(xml_op, PCMK__XA_OPERATION_KEY, key);
1225 crm_xml_add(xml_op, PCMK_XA_OPERATION, task);
1226 crm_xml_add(xml_op, PCMK_XA_CRM_DEBUG_ORIGIN, origin);
1227 crm_xml_add(xml_op, PCMK_XA_CRM_FEATURE_SET, caller_version);
1228 crm_xml_add(xml_op, PCMK__XA_TRANSITION_KEY, op->user_data);
1229 crm_xml_add(xml_op, PCMK__XA_TRANSITION_MAGIC, magic);
1230 crm_xml_add(xml_op, PCMK_XA_EXIT_REASON, pcmk__s(exit_reason, ""));
1231 crm_xml_add(xml_op, PCMK__META_ON_NODE, node);
1232
1233 crm_xml_add_int(xml_op, PCMK__XA_CALL_ID, op->call_id);
1234 crm_xml_add_int(xml_op, PCMK__XA_RC_CODE, op->rc);
1235 crm_xml_add_int(xml_op, PCMK__XA_OP_STATUS, op->op_status);
1236 crm_xml_add_ms(xml_op, PCMK_META_INTERVAL, op->interval_ms);
1237
1238 if (compare_version("2.1", caller_version) <= 0) {
1239 if (op->t_run || op->t_rcchange || op->exec_time || op->queue_time) {
1240 crm_trace("Timing data (" PCMK__OP_FMT
1241 "): last=%u change=%u exec=%u queue=%u",
1242 op->rsc_id, op->op_type, op->interval_ms,
1243 op->t_run, op->t_rcchange, op->exec_time, op->queue_time);
1244
1245 if ((op->interval_ms != 0) && (op->t_rcchange != 0)) {
1246
1247 crm_xml_add_ll(xml_op, PCMK_XA_LAST_RC_CHANGE,
1248 (long long) op->t_rcchange);
1249 } else {
1250 crm_xml_add_ll(xml_op, PCMK_XA_LAST_RC_CHANGE,
1251 (long long) op->t_run);
1252 }
1253
1254 crm_xml_add_int(xml_op, PCMK_XA_EXEC_TIME, op->exec_time);
1255 crm_xml_add_int(xml_op, PCMK_XA_QUEUE_TIME, op->queue_time);
1256 }
1257 }
1258
1259 if (pcmk__str_any_of(op->op_type, PCMK_ACTION_MIGRATE_TO,
1260 PCMK_ACTION_MIGRATE_FROM, NULL)) {
1261
1262
1263
1264 const char *name = PCMK__META_MIGRATE_SOURCE;
1265
1266 crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1267
1268 name = PCMK__META_MIGRATE_TARGET;
1269 crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
1270 }
1271
1272 add_op_digest_to_xml(op, xml_op);
1273
1274 if (op_id_additional) {
1275 free(op_id);
1276 op_id = op_id_additional;
1277 op_id_additional = NULL;
1278 goto again;
1279 }
1280
1281 if (local_user_data) {
1282 free(local_user_data);
1283 op->user_data = NULL;
1284 }
1285 free(magic);
1286 free(op_id);
1287 free(key);
1288 return xml_op;
1289 }
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305 bool
1306 pcmk__action_locks_rsc_to_node(const pcmk_action_t *action)
1307 {
1308
1309 if ((action == NULL) || (action->rsc == NULL)
1310 || !pcmk__same_node(action->node, action->rsc->lock_node)) {
1311 return false;
1312 }
1313
1314
1315
1316
1317 if (action->node->details->shutdown && (action->task != NULL)
1318 && (strcmp(action->task, PCMK_ACTION_STOP) != 0)) {
1319 return false;
1320 }
1321
1322 return true;
1323 }
1324
1325
1326 static gint
1327 sort_action_id(gconstpointer a, gconstpointer b)
1328 {
1329 const pcmk__related_action_t *action_wrapper2 = a;
1330 const pcmk__related_action_t *action_wrapper1 = b;
1331
1332 if (a == NULL) {
1333 return 1;
1334 }
1335 if (b == NULL) {
1336 return -1;
1337 }
1338 if (action_wrapper1->action->id < action_wrapper2->action->id) {
1339 return 1;
1340 }
1341 if (action_wrapper1->action->id > action_wrapper2->action->id) {
1342 return -1;
1343 }
1344 return 0;
1345 }
1346
1347
1348
1349
1350
1351
1352
1353 void
1354 pcmk__deduplicate_action_inputs(pcmk_action_t *action)
1355 {
1356 GList *item = NULL;
1357 GList *next = NULL;
1358 pcmk__related_action_t *last_input = NULL;
1359
1360 action->actions_before = g_list_sort(action->actions_before,
1361 sort_action_id);
1362 for (item = action->actions_before; item != NULL; item = next) {
1363 pcmk__related_action_t *input = item->data;
1364
1365 next = item->next;
1366 if ((last_input != NULL)
1367 && (input->action->id == last_input->action->id)) {
1368 crm_trace("Input %s (%d) duplicate skipped for action %s (%d)",
1369 input->action->uuid, input->action->id,
1370 action->uuid, action->id);
1371
1372
1373
1374
1375
1376 last_input->type |= input->type;
1377 if (input->state == pe_link_dumped) {
1378 last_input->state = pe_link_dumped;
1379 }
1380
1381 free(item->data);
1382 action->actions_before = g_list_delete_link(action->actions_before,
1383 item);
1384 } else {
1385 last_input = input;
1386 input->state = pe_link_not_dumped;
1387 }
1388 }
1389 }
1390
1391
1392
1393
1394
1395
1396
1397 void
1398 pcmk__output_actions(pcmk_scheduler_t *scheduler)
1399 {
1400 pcmk__output_t *out = scheduler->priv;
1401
1402
1403 for (GList *iter = scheduler->actions; iter != NULL; iter = iter->next) {
1404 char *node_name = NULL;
1405 char *task = NULL;
1406 pcmk_action_t *action = (pcmk_action_t *) iter->data;
1407
1408 if (action->rsc != NULL) {
1409 continue;
1410
1411 } else if (pcmk_is_set(action->flags, pcmk_action_optional)) {
1412 continue;
1413 }
1414
1415 if (pcmk__str_eq(action->task, PCMK_ACTION_DO_SHUTDOWN,
1416 pcmk__str_none)) {
1417 task = strdup("Shutdown");
1418
1419 } else if (pcmk__str_eq(action->task, PCMK_ACTION_STONITH,
1420 pcmk__str_none)) {
1421 const char *op = g_hash_table_lookup(action->meta,
1422 PCMK__META_STONITH_ACTION);
1423
1424 task = crm_strdup_printf("Fence (%s)", op);
1425
1426 } else {
1427 continue;
1428 }
1429
1430 if (pcmk__is_guest_or_bundle_node(action->node)) {
1431 const pcmk_resource_t *remote = action->node->details->remote_rsc;
1432
1433 node_name = crm_strdup_printf("%s (resource: %s)",
1434 pcmk__node_name(action->node),
1435 remote->container->id);
1436 } else if (action->node != NULL) {
1437 node_name = crm_strdup_printf("%s", pcmk__node_name(action->node));
1438 }
1439
1440 out->message(out, "node-action", task, node_name, action->reason);
1441
1442 free(node_name);
1443 free(task);
1444 }
1445
1446
1447 for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
1448 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
1449
1450 rsc->cmds->output_actions(rsc);
1451 }
1452 }
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463 static const char *
1464 task_for_digest(const char *task, guint interval_ms)
1465 {
1466
1467
1468
1469 if ((interval_ms == 0)
1470 && pcmk__str_any_of(task, PCMK_ACTION_MONITOR, PCMK_ACTION_MIGRATE_FROM,
1471 PCMK_ACTION_PROMOTE, NULL)) {
1472 task = PCMK_ACTION_START;
1473 }
1474 return task;
1475 }
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494 static bool
1495 only_sanitized_changed(const xmlNode *xml_op,
1496 const pcmk__op_digest_t *digest_data,
1497 const pcmk_scheduler_t *scheduler)
1498 {
1499 const char *digest_secure = NULL;
1500
1501 if (!pcmk_is_set(scheduler->flags, pcmk_sched_sanitized)) {
1502
1503 return false;
1504 }
1505
1506 digest_secure = crm_element_value(xml_op, PCMK__XA_OP_SECURE_DIGEST);
1507
1508 return (digest_data->rc != pcmk__digest_match) && (digest_secure != NULL)
1509 && (digest_data->digest_secure_calc != NULL)
1510 && (strcmp(digest_data->digest_secure_calc, digest_secure) == 0);
1511 }
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522 static void
1523 force_restart(pcmk_resource_t *rsc, const char *task, guint interval_ms,
1524 pcmk_node_t *node)
1525 {
1526 char *key = pcmk__op_key(rsc->id, task, interval_ms);
1527 pcmk_action_t *required = custom_action(rsc, key, task, NULL, FALSE,
1528 rsc->cluster);
1529
1530 pe_action_set_reason(required, "resource definition change", true);
1531 trigger_unfencing(rsc, node, "Device parameters changed", NULL,
1532 rsc->cluster);
1533 }
1534
1535
1536
1537
1538
1539
1540
1541
1542 static void
1543 schedule_reload(gpointer data, gpointer user_data)
1544 {
1545 pcmk_resource_t *rsc = data;
1546 const pcmk_node_t *node = user_data;
1547 pcmk_action_t *reload = NULL;
1548
1549
1550 if (rsc->variant > pcmk_rsc_variant_primitive) {
1551 g_list_foreach(rsc->children, schedule_reload, user_data);
1552 return;
1553 }
1554
1555
1556 if ((node == NULL)
1557 || !pcmk_is_set(rsc->flags, pcmk_rsc_managed)
1558 || pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
1559 pcmk__rsc_trace(rsc, "Skip reload of %s:%s%s %s",
1560 rsc->id,
1561 pcmk_is_set(rsc->flags, pcmk_rsc_managed)? "" : " unmanaged",
1562 pcmk_is_set(rsc->flags, pcmk_rsc_failed)? " failed" : "",
1563 (node == NULL)? "inactive" : node->details->uname);
1564 return;
1565 }
1566
1567
1568
1569
1570 if (pcmk_is_set(rsc->flags, pcmk_rsc_start_pending)) {
1571 pcmk__rsc_trace(rsc,
1572 "%s: preventing agent reload because start pending",
1573 rsc->id);
1574 custom_action(rsc, stop_key(rsc), PCMK_ACTION_STOP, node, FALSE,
1575 rsc->cluster);
1576 return;
1577 }
1578
1579
1580 pcmk__set_rsc_flags(rsc, pcmk_rsc_reload);
1581 reload = custom_action(rsc, reload_key(rsc), PCMK_ACTION_RELOAD_AGENT, node,
1582 FALSE, rsc->cluster);
1583 pe_action_set_reason(reload, "resource definition change", FALSE);
1584
1585
1586 pcmk__new_ordering(NULL, NULL, reload, rsc, stop_key(rsc), NULL,
1587 pcmk__ar_ordered|pcmk__ar_then_cancels_first,
1588 rsc->cluster);
1589 pcmk__new_ordering(NULL, NULL, reload, rsc, demote_key(rsc), NULL,
1590 pcmk__ar_ordered|pcmk__ar_then_cancels_first,
1591 rsc->cluster);
1592 }
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608 bool
1609 pcmk__check_action_config(pcmk_resource_t *rsc, pcmk_node_t *node,
1610 const xmlNode *xml_op)
1611 {
1612 guint interval_ms = 0;
1613 const char *task = NULL;
1614 const pcmk__op_digest_t *digest_data = NULL;
1615
1616 CRM_CHECK((rsc != NULL) && (node != NULL) && (xml_op != NULL),
1617 return false);
1618
1619 task = crm_element_value(xml_op, PCMK_XA_OPERATION);
1620 CRM_CHECK(task != NULL, return false);
1621
1622 crm_element_value_ms(xml_op, PCMK_META_INTERVAL, &interval_ms);
1623
1624
1625 if (interval_ms > 0) {
1626 if (pcmk__find_action_config(rsc, task, interval_ms, false) != NULL) {
1627 pcmk__rsc_trace(rsc,
1628 "%s-interval %s for %s on %s is in configuration",
1629 pcmk__readable_interval(interval_ms), task, rsc->id,
1630 pcmk__node_name(node));
1631 } else if (pcmk_is_set(rsc->cluster->flags,
1632 pcmk_sched_cancel_removed_actions)) {
1633 pcmk__schedule_cancel(rsc,
1634 crm_element_value(xml_op, PCMK__XA_CALL_ID),
1635 task, interval_ms, node, "orphan");
1636 return true;
1637 } else {
1638 pcmk__rsc_debug(rsc, "%s-interval %s for %s on %s is orphaned",
1639 pcmk__readable_interval(interval_ms), task, rsc->id,
1640 pcmk__node_name(node));
1641 return true;
1642 }
1643 }
1644
1645 crm_trace("Checking %s-interval %s for %s on %s for configuration changes",
1646 pcmk__readable_interval(interval_ms), task, rsc->id,
1647 pcmk__node_name(node));
1648 task = task_for_digest(task, interval_ms);
1649 digest_data = rsc_action_digest_cmp(rsc, xml_op, node, rsc->cluster);
1650
1651 if (only_sanitized_changed(xml_op, digest_data, rsc->cluster)) {
1652 if (!pcmk__is_daemon && (rsc->cluster->priv != NULL)) {
1653 pcmk__output_t *out = rsc->cluster->priv;
1654
1655 out->info(out,
1656 "Only 'private' parameters to %s-interval %s for %s "
1657 "on %s changed: %s",
1658 pcmk__readable_interval(interval_ms), task, rsc->id,
1659 pcmk__node_name(node),
1660 crm_element_value(xml_op, PCMK__XA_TRANSITION_MAGIC));
1661 }
1662 return false;
1663 }
1664
1665 switch (digest_data->rc) {
1666 case pcmk__digest_restart:
1667 crm_log_xml_debug(digest_data->params_restart, "params:restart");
1668 force_restart(rsc, task, interval_ms, node);
1669 return true;
1670
1671 case pcmk__digest_unknown:
1672 case pcmk__digest_mismatch:
1673
1674
1675 if (interval_ms > 0) {
1676
1677
1678
1679
1680 crm_log_xml_debug(digest_data->params_all, "params:reschedule");
1681 pcmk__reschedule_recurring(rsc, task, interval_ms, node);
1682
1683 } else if (crm_element_value(xml_op,
1684 PCMK__XA_OP_RESTART_DIGEST) != NULL) {
1685
1686 trigger_unfencing(rsc, node,
1687 "Device parameters changed (reload)", NULL,
1688 rsc->cluster);
1689 crm_log_xml_debug(digest_data->params_all, "params:reload");
1690 schedule_reload((gpointer) rsc, (gpointer) node);
1691
1692 } else {
1693 pcmk__rsc_trace(rsc,
1694 "Restarting %s "
1695 "because agent doesn't support reload",
1696 rsc->id);
1697 crm_log_xml_debug(digest_data->params_restart,
1698 "params:restart");
1699 force_restart(rsc, task, interval_ms, node);
1700 }
1701 return true;
1702
1703 default:
1704 break;
1705 }
1706 return false;
1707 }
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717 static GList *
1718 rsc_history_as_list(const xmlNode *rsc_entry, int *start_index, int *stop_index)
1719 {
1720 GList *ops = NULL;
1721
1722 for (xmlNode *rsc_op = pcmk__xe_first_child(rsc_entry, PCMK__XE_LRM_RSC_OP,
1723 NULL, NULL);
1724 rsc_op != NULL; rsc_op = pcmk__xe_next_same(rsc_op)) {
1725
1726 ops = g_list_prepend(ops, rsc_op);
1727 }
1728 ops = g_list_sort(ops, sort_op_by_callid);
1729 calculate_active_ops(ops, start_index, stop_index);
1730 return ops;
1731 }
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747 static void
1748 process_rsc_history(const xmlNode *rsc_entry, pcmk_resource_t *rsc,
1749 pcmk_node_t *node)
1750 {
1751 int offset = -1;
1752 int stop_index = 0;
1753 int start_index = 0;
1754 GList *sorted_op_list = NULL;
1755
1756 if (pcmk_is_set(rsc->flags, pcmk_rsc_removed)) {
1757 if (pcmk__is_anonymous_clone(pe__const_top_resource(rsc, false))) {
1758 pcmk__rsc_trace(rsc,
1759 "Skipping configuration check "
1760 "for orphaned clone instance %s",
1761 rsc->id);
1762 } else {
1763 pcmk__rsc_trace(rsc,
1764 "Skipping configuration check and scheduling "
1765 "clean-up for orphaned resource %s", rsc->id);
1766 pcmk__schedule_cleanup(rsc, node, false);
1767 }
1768 return;
1769 }
1770
1771 if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
1772 if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, false)) {
1773 pcmk__schedule_cleanup(rsc, node, false);
1774 }
1775 pcmk__rsc_trace(rsc,
1776 "Skipping configuration check for %s "
1777 "because no longer active on %s",
1778 rsc->id, pcmk__node_name(node));
1779 return;
1780 }
1781
1782 pcmk__rsc_trace(rsc, "Checking for configuration changes for %s on %s",
1783 rsc->id, pcmk__node_name(node));
1784
1785 if (pcmk__rsc_agent_changed(rsc, node, rsc_entry, true)) {
1786 pcmk__schedule_cleanup(rsc, node, false);
1787 }
1788
1789 sorted_op_list = rsc_history_as_list(rsc_entry, &start_index, &stop_index);
1790 if (start_index < stop_index) {
1791 return;
1792 }
1793
1794 for (GList *iter = sorted_op_list; iter != NULL; iter = iter->next) {
1795 xmlNode *rsc_op = (xmlNode *) iter->data;
1796 const char *task = NULL;
1797 guint interval_ms = 0;
1798
1799 if (++offset < start_index) {
1800
1801 continue;
1802 }
1803
1804 task = crm_element_value(rsc_op, PCMK_XA_OPERATION);
1805 crm_element_value_ms(rsc_op, PCMK_META_INTERVAL, &interval_ms);
1806
1807 if ((interval_ms > 0)
1808 && (pcmk_is_set(rsc->flags, pcmk_rsc_maintenance)
1809 || node->details->maintenance)) {
1810
1811 pcmk__schedule_cancel(rsc,
1812 crm_element_value(rsc_op, PCMK__XA_CALL_ID),
1813 task, interval_ms, node, "maintenance mode");
1814
1815 } else if ((interval_ms > 0)
1816 || pcmk__strcase_any_of(task, PCMK_ACTION_MONITOR,
1817 PCMK_ACTION_START,
1818 PCMK_ACTION_PROMOTE,
1819 PCMK_ACTION_MIGRATE_FROM, NULL)) {
1820
1821
1822
1823
1824 if (pe__bundle_needs_remote_name(rsc)) {
1825
1826
1827
1828
1829
1830
1831
1832 pe__add_param_check(rsc_op, rsc, node, pcmk__check_active,
1833 rsc->cluster);
1834
1835 } else if (pcmk__check_action_config(rsc, node, rsc_op)
1836 && (pe_get_failcount(node, rsc, NULL, pcmk__fc_effective,
1837 NULL) != 0)) {
1838 pe__clear_failcount(rsc, node, "action definition changed",
1839 rsc->cluster);
1840 }
1841 }
1842 }
1843 g_list_free(sorted_op_list);
1844 }
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859 static void
1860 process_node_history(pcmk_node_t *node, const xmlNode *lrm_rscs)
1861 {
1862 crm_trace("Processing node history for %s", pcmk__node_name(node));
1863 for (const xmlNode *rsc_entry = pcmk__xe_first_child(lrm_rscs,
1864 PCMK__XE_LRM_RESOURCE,
1865 NULL, NULL);
1866 rsc_entry != NULL; rsc_entry = pcmk__xe_next_same(rsc_entry)) {
1867
1868 if (rsc_entry->children != NULL) {
1869 GList *result = pcmk__rscs_matching_id(pcmk__xe_id(rsc_entry),
1870 node->details->data_set);
1871
1872 for (GList *iter = result; iter != NULL; iter = iter->next) {
1873 pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
1874
1875 if (pcmk__is_primitive(rsc)) {
1876 process_rsc_history(rsc_entry, rsc, node);
1877 }
1878 }
1879 g_list_free(result);
1880 }
1881 }
1882 }
1883
1884
1885 #define XPATH_NODE_HISTORY "/" PCMK_XE_CIB "/" PCMK_XE_STATUS \
1886 "/" PCMK__XE_NODE_STATE \
1887 "[@" PCMK_XA_UNAME "='%s']" \
1888 "/" PCMK__XE_LRM "/" PCMK__XE_LRM_RESOURCES
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902 void
1903 pcmk__handle_rsc_config_changes(pcmk_scheduler_t *scheduler)
1904 {
1905 crm_trace("Check resource and action configuration for changes");
1906
1907
1908
1909
1910
1911 for (GList *iter = scheduler->nodes; iter != NULL; iter = iter->next) {
1912 pcmk_node_t *node = (pcmk_node_t *) iter->data;
1913
1914
1915
1916
1917
1918 if (node->details->maintenance
1919 || pcmk__node_available(node, false, false)) {
1920
1921 char *xpath = NULL;
1922 xmlNode *history = NULL;
1923
1924 xpath = crm_strdup_printf(XPATH_NODE_HISTORY, node->details->uname);
1925 history = get_xpath_object(xpath, scheduler->input, LOG_NEVER);
1926 free(xpath);
1927
1928 process_node_history(node, history);
1929 }
1930 }
1931 }