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