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