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