This source file includes following definitions.
- get_action_flags
- convert_non_atomic_uuid
- rsc_expand_action
- graph_update_action
- mark_start_blocked
- update_colo_start_chain
- update_action
- shutdown_constraints
- pcmk__order_vs_fence
- get_router_node
- add_node_to_xml_by_id
- add_node_to_xml
- add_maintenance_nodes
- add_maintenance_update
- add_downed_nodes
- should_lock_action
- action2xml
- should_dump_action
- sort_action_id
- check_dump_input
- graph_has_loop
- pcmk__ordering_is_invalid
- deduplicate_inputs
- graph_element_from_action
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13 #include <crm/crm.h>
14 #include <crm/cib.h>
15 #include <crm/msg_xml.h>
16 #include <crm/common/xml.h>
17
18 #include <glib.h>
19
20 #include <pacemaker-internal.h>
21
22 void update_colo_start_chain(pe_action_t *action, pe_working_set_t *data_set);
23 gboolean rsc_update_action(pe_action_t * first, pe_action_t * then, enum pe_ordering type);
24
25 static enum pe_action_flags
26 get_action_flags(pe_action_t * action, pe_node_t * node)
27 {
28 enum pe_action_flags flags = action->flags;
29
30 if (action->rsc) {
31 flags = action->rsc->cmds->action_flags(action, NULL);
32
33 if (pe_rsc_is_clone(action->rsc) && node) {
34
35
36 enum pe_action_flags clone_flags = action->rsc->cmds->action_flags(action, node);
37
38
39
40
41
42
43
44
45
46
47
48 if (!pcmk_is_set(clone_flags, pe_action_runnable)
49 && pcmk_is_set(flags, pe_action_runnable)) {
50
51 pe__set_raw_action_flags(clone_flags, action->rsc->id,
52 pe_action_runnable);
53 }
54 flags = clone_flags;
55 }
56 }
57 return flags;
58 }
59
60 static char *
61 convert_non_atomic_uuid(char *old_uuid, pe_resource_t * rsc, gboolean allow_notify,
62 gboolean free_original)
63 {
64 guint interval_ms = 0;
65 char *uuid = NULL;
66 char *rid = NULL;
67 char *raw_task = NULL;
68 int task = no_action;
69
70 CRM_ASSERT(rsc);
71 pe_rsc_trace(rsc, "Processing %s", old_uuid);
72 if (old_uuid == NULL) {
73 return NULL;
74
75 } else if (strstr(old_uuid, "notify") != NULL) {
76 goto done;
77
78 } else if (rsc->variant < pe_group) {
79 goto done;
80 }
81
82 CRM_ASSERT(parse_op_key(old_uuid, &rid, &raw_task, &interval_ms));
83 if (interval_ms > 0) {
84 goto done;
85 }
86
87 task = text2task(raw_task);
88 switch (task) {
89 case stop_rsc:
90 case start_rsc:
91 case action_notify:
92 case action_promote:
93 case action_demote:
94 break;
95 case stopped_rsc:
96 case started_rsc:
97 case action_notified:
98 case action_promoted:
99 case action_demoted:
100 task--;
101 break;
102 case monitor_rsc:
103 case shutdown_crm:
104 case stonith_node:
105 task = no_action;
106 break;
107 default:
108 crm_err("Unknown action: %s", raw_task);
109 task = no_action;
110 break;
111 }
112
113 if (task != no_action) {
114 if (pcmk_is_set(rsc->flags, pe_rsc_notify) && allow_notify) {
115 uuid = pcmk__notify_key(rid, "confirmed-post", task2text(task + 1));
116
117 } else {
118 uuid = pcmk__op_key(rid, task2text(task + 1), 0);
119 }
120 pe_rsc_trace(rsc, "Converted %s -> %s", old_uuid, uuid);
121 }
122
123 done:
124 if (uuid == NULL) {
125 uuid = strdup(old_uuid);
126 }
127
128 if (free_original) {
129 free(old_uuid);
130 }
131
132 free(raw_task);
133 free(rid);
134 return uuid;
135 }
136
137 static pe_action_t *
138 rsc_expand_action(pe_action_t * action)
139 {
140 gboolean notify = FALSE;
141 pe_action_t *result = action;
142 pe_resource_t *rsc = action->rsc;
143
144 if (rsc == NULL) {
145 return action;
146 }
147
148 if ((rsc->parent == NULL)
149 || (pe_rsc_is_clone(rsc) && (rsc->parent->variant == pe_container))) {
150
151
152
153 notify = pcmk_is_set(rsc->flags, pe_rsc_notify);
154 }
155
156 if (rsc->variant >= pe_group) {
157
158 char *uuid = NULL;
159
160 uuid = convert_non_atomic_uuid(action->uuid, rsc, notify, FALSE);
161 if (uuid) {
162 pe_rsc_trace(rsc, "Converting %s to %s %d", action->uuid, uuid,
163 pcmk_is_set(rsc->flags, pe_rsc_notify));
164 result = find_first_action(rsc->actions, uuid, NULL, NULL);
165 if (result == NULL) {
166 crm_err("Couldn't expand %s to %s in %s", action->uuid, uuid, rsc->id);
167 result = action;
168 }
169 free(uuid);
170 }
171 }
172 return result;
173 }
174
175 static enum pe_graph_flags
176 graph_update_action(pe_action_t * first, pe_action_t * then, pe_node_t * node,
177 enum pe_action_flags first_flags, enum pe_action_flags then_flags,
178 pe_action_wrapper_t *order, pe_working_set_t *data_set)
179 {
180 enum pe_graph_flags changed = pe_graph_none;
181 enum pe_ordering type = order->type;
182 gboolean processed = FALSE;
183
184
185
186 if (pcmk_is_set(type, pe_order_implies_then_on_node)) {
187
188
189
190
191
192
193
194
195
196
197
198
199 pe__clear_order_flags(type, pe_order_implies_then_on_node);
200 pe__set_order_flags(type, pe_order_implies_then);
201 node = first->node;
202 }
203
204 pe__clear_raw_action_flags(first_flags, "first action update",
205 pe_action_pseudo);
206
207 if (type & pe_order_implies_then) {
208 processed = TRUE;
209 if (then->rsc) {
210 changed |= then->rsc->cmds->update_actions(first, then, node,
211 first_flags & pe_action_optional, pe_action_optional,
212 pe_order_implies_then, data_set);
213
214 } else if (!pcmk_is_set(first_flags, pe_action_optional)) {
215 if (update_action_flags(then, pe_action_optional | pe_action_clear, __func__, __LINE__)) {
216 pe__set_graph_flags(changed, first, pe_graph_updated_then);
217 }
218 }
219 if (changed) {
220 pe_rsc_trace(then->rsc, "implies right: %s then %s: changed", first->uuid, then->uuid);
221 } else {
222 crm_trace("implies right: %s then %s %p", first->uuid, then->uuid, then->rsc);
223 }
224 }
225
226 if ((type & pe_order_restart) && then->rsc) {
227 enum pe_action_flags restart = (pe_action_optional | pe_action_runnable);
228
229 processed = TRUE;
230 changed |= then->rsc->cmds->update_actions(first, then, node,
231 first_flags, restart,
232 pe_order_restart, data_set);
233 if (changed) {
234 pe_rsc_trace(then->rsc, "restart: %s then %s: changed", first->uuid, then->uuid);
235 } else {
236 crm_trace("restart: %s then %s", first->uuid, then->uuid);
237 }
238 }
239
240 if (type & pe_order_implies_first) {
241 processed = TRUE;
242 if (first->rsc) {
243 changed |= first->rsc->cmds->update_actions(first, then, node,
244 first_flags, pe_action_optional, pe_order_implies_first,
245 data_set);
246
247 } else if (!pcmk_is_set(first_flags, pe_action_optional)) {
248 pe_rsc_trace(first->rsc, "first unrunnable: %s (%d) then %s (%d)",
249 first->uuid, pcmk_is_set(first_flags, pe_action_optional),
250 then->uuid, pcmk_is_set(then_flags, pe_action_optional));
251 if (update_action_flags(first, pe_action_runnable | pe_action_clear, __func__, __LINE__)) {
252 pe__set_graph_flags(changed, first, pe_graph_updated_first);
253 }
254 }
255
256 if (changed) {
257 pe_rsc_trace(then->rsc, "implies left: %s then %s: changed", first->uuid, then->uuid);
258 } else {
259 crm_trace("implies left: %s (%d) then %s (%d)",
260 first->uuid, pcmk_is_set(first_flags, pe_action_optional),
261 then->uuid, pcmk_is_set(then_flags, pe_action_optional));
262 }
263 }
264
265 if (type & pe_order_promoted_implies_first) {
266 processed = TRUE;
267 if (then->rsc) {
268 changed |= then->rsc->cmds->update_actions(first, then, node,
269 first_flags & pe_action_optional, pe_action_optional,
270 pe_order_promoted_implies_first, data_set);
271 }
272
273 if (changed) {
274 pe_rsc_trace(then->rsc,
275 "implies left when right resource is promoted: "
276 "%s then %s: changed", first->uuid, then->uuid);
277 } else {
278 crm_trace("implies left when right resource is promoted: "
279 "%s then %s", first->uuid, then->uuid);
280 }
281 }
282
283 if (type & pe_order_one_or_more) {
284 processed = TRUE;
285 if (then->rsc) {
286 changed |= then->rsc->cmds->update_actions(first, then, node,
287 first_flags, pe_action_runnable, pe_order_one_or_more,
288 data_set);
289
290 } else if (pcmk_is_set(first_flags, pe_action_runnable)) {
291
292
293 then->runnable_before++;
294
295
296
297 if (then->runnable_before >= then->required_runnable_before) {
298 if (update_action_flags(then, pe_action_runnable, __func__, __LINE__)) {
299 pe__set_graph_flags(changed, first, pe_graph_updated_then);
300 }
301 }
302 }
303 if (changed) {
304 pe_rsc_trace(then->rsc, "runnable_one_or_more: %s then %s: changed", first->uuid,
305 then->uuid);
306 } else {
307 crm_trace("runnable_one_or_more: %s then %s", first->uuid, then->uuid);
308 }
309 }
310
311 if (then->rsc && pcmk_is_set(type, pe_order_probe)) {
312 processed = TRUE;
313
314 if (!pcmk_is_set(first_flags, pe_action_runnable)
315 && (first->rsc->running_on != NULL)) {
316
317 pe_rsc_trace(then->rsc, "Ignoring %s then %s - %s is about to be stopped",
318 first->uuid, then->uuid, first->rsc->id);
319 type = pe_order_none;
320 order->type = pe_order_none;
321
322 } else {
323 pe_rsc_trace(then->rsc, "Enforcing %s then %s", first->uuid, then->uuid);
324 changed |= then->rsc->cmds->update_actions(first, then, node,
325 first_flags, pe_action_runnable, pe_order_runnable_left,
326 data_set);
327 }
328
329 if (changed) {
330 pe_rsc_trace(then->rsc, "runnable: %s then %s: changed", first->uuid, then->uuid);
331 } else {
332 crm_trace("runnable: %s then %s", first->uuid, then->uuid);
333 }
334 }
335
336 if (type & pe_order_runnable_left) {
337 processed = TRUE;
338 if (then->rsc) {
339 changed |= then->rsc->cmds->update_actions(first, then, node,
340 first_flags, pe_action_runnable, pe_order_runnable_left,
341 data_set);
342
343 } else if (!pcmk_is_set(first_flags, pe_action_runnable)) {
344 pe_rsc_trace(then->rsc, "then unrunnable: %s then %s", first->uuid, then->uuid);
345 if (update_action_flags(then, pe_action_runnable | pe_action_clear, __func__, __LINE__)) {
346 pe__set_graph_flags(changed, first, pe_graph_updated_then);
347 }
348 }
349 if (changed) {
350 pe_rsc_trace(then->rsc, "runnable: %s then %s: changed", first->uuid, then->uuid);
351 } else {
352 crm_trace("runnable: %s then %s", first->uuid, then->uuid);
353 }
354 }
355
356 if (type & pe_order_implies_first_migratable) {
357 processed = TRUE;
358 if (then->rsc) {
359 changed |= then->rsc->cmds->update_actions(first, then, node,
360 first_flags, pe_action_optional,
361 pe_order_implies_first_migratable, data_set);
362 }
363 if (changed) {
364 pe_rsc_trace(then->rsc, "optional: %s then %s: changed", first->uuid, then->uuid);
365 } else {
366 crm_trace("optional: %s then %s", first->uuid, then->uuid);
367 }
368 }
369
370 if (type & pe_order_pseudo_left) {
371 processed = TRUE;
372 if (then->rsc) {
373 changed |= then->rsc->cmds->update_actions(first, then, node,
374 first_flags, pe_action_optional, pe_order_pseudo_left,
375 data_set);
376 }
377 if (changed) {
378 pe_rsc_trace(then->rsc, "optional: %s then %s: changed", first->uuid, then->uuid);
379 } else {
380 crm_trace("optional: %s then %s", first->uuid, then->uuid);
381 }
382 }
383
384 if (type & pe_order_optional) {
385 processed = TRUE;
386 if (then->rsc) {
387 changed |= then->rsc->cmds->update_actions(first, then, node,
388 first_flags, pe_action_runnable, pe_order_optional, data_set);
389 }
390 if (changed) {
391 pe_rsc_trace(then->rsc, "optional: %s then %s: changed", first->uuid, then->uuid);
392 } else {
393 crm_trace("optional: %s then %s", first->uuid, then->uuid);
394 }
395 }
396
397 if (type & pe_order_asymmetrical) {
398 processed = TRUE;
399 if (then->rsc) {
400 changed |= then->rsc->cmds->update_actions(first, then, node,
401 first_flags, pe_action_runnable, pe_order_asymmetrical,
402 data_set);
403 }
404
405 if (changed) {
406 pe_rsc_trace(then->rsc, "asymmetrical: %s then %s: changed", first->uuid, then->uuid);
407 } else {
408 crm_trace("asymmetrical: %s then %s", first->uuid, then->uuid);
409 }
410
411 }
412
413 if ((first->flags & pe_action_runnable) && (type & pe_order_implies_then_printed)
414 && (first_flags & pe_action_optional) == 0) {
415 processed = TRUE;
416 crm_trace("%s implies %s printed", first->uuid, then->uuid);
417 update_action_flags(then, pe_action_print_always, __func__, __LINE__);
418 }
419
420 if (pcmk_is_set(type, pe_order_implies_first_printed)
421 && !pcmk_is_set(then_flags, pe_action_optional)) {
422
423 processed = TRUE;
424 crm_trace("%s implies %s printed", then->uuid, first->uuid);
425 update_action_flags(first, pe_action_print_always, __func__, __LINE__);
426 }
427
428 if ((type & pe_order_implies_then
429 || type & pe_order_implies_first
430 || type & pe_order_restart)
431 && first->rsc
432 && pcmk__str_eq(first->task, RSC_STOP, pcmk__str_casei)
433 && !pcmk_is_set(first->rsc->flags, pe_rsc_managed)
434 && pcmk_is_set(first->rsc->flags, pe_rsc_block)
435 && !pcmk_is_set(first->flags, pe_action_runnable)) {
436
437 if (update_action_flags(then, pe_action_runnable | pe_action_clear, __func__, __LINE__)) {
438 pe__set_graph_flags(changed, first, pe_graph_updated_then);
439 }
440
441 if (changed) {
442 pe_rsc_trace(then->rsc, "unmanaged left: %s then %s: changed", first->uuid, then->uuid);
443 } else {
444 crm_trace("unmanaged left: %s then %s", first->uuid, then->uuid);
445 }
446 }
447
448 if (processed == FALSE) {
449 crm_trace("Constraint 0x%.6x not applicable", type);
450 }
451
452 return changed;
453 }
454
455 static void
456 mark_start_blocked(pe_resource_t *rsc, pe_resource_t *reason,
457 pe_working_set_t *data_set)
458 {
459 GList *gIter = rsc->actions;
460 char *reason_text = crm_strdup_printf("colocation with %s", reason->id);
461
462 for (; gIter != NULL; gIter = gIter->next) {
463 pe_action_t *action = (pe_action_t *) gIter->data;
464
465 if (!pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)) {
466 continue;
467 }
468 if (pcmk_is_set(action->flags, pe_action_runnable)) {
469 pe_action_set_flag_reason(__func__, __LINE__, action, NULL,
470 reason_text, pe_action_runnable, FALSE);
471 update_colo_start_chain(action, data_set);
472 update_action(action, data_set);
473 }
474 }
475 free(reason_text);
476 }
477
478 void
479 update_colo_start_chain(pe_action_t *action, pe_working_set_t *data_set)
480 {
481 GList *gIter = NULL;
482 pe_resource_t *rsc = NULL;
483
484 if (!pcmk_is_set(action->flags, pe_action_runnable)
485 && pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)) {
486
487 rsc = uber_parent(action->rsc);
488 if (rsc->parent) {
489
490
491
492
493
494 rsc = rsc->parent;
495 }
496 }
497
498 if (rsc == NULL || rsc->rsc_cons_lhs == NULL) {
499 return;
500 }
501
502
503
504 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
505 pe_resource_t *child = (pe_resource_t *)gIter->data;
506 pe_action_t *start = find_first_action(child->actions, NULL, RSC_START, NULL);
507 if ((start == NULL) || pcmk_is_set(start->flags, pe_action_runnable)) {
508 return;
509 }
510 }
511
512 for (gIter = rsc->rsc_cons_lhs; gIter != NULL; gIter = gIter->next) {
513 pcmk__colocation_t *colocate_with = (pcmk__colocation_t *) gIter->data;
514
515 if (colocate_with->score == INFINITY) {
516 mark_start_blocked(colocate_with->rsc_lh, action->rsc, data_set);
517 }
518 }
519 }
520
521 gboolean
522 update_action(pe_action_t *then, pe_working_set_t *data_set)
523 {
524 GList *lpc = NULL;
525 enum pe_graph_flags changed = pe_graph_none;
526 int last_flags = then->flags;
527
528 crm_trace("Processing %s (%s %s %s)",
529 then->uuid,
530 pcmk_is_set(then->flags, pe_action_optional)? "optional" : "required",
531 pcmk_is_set(then->flags, pe_action_runnable)? "runnable" : "unrunnable",
532 pcmk_is_set(then->flags, pe_action_pseudo)? "pseudo"
533 : (then->node? then->node->details->uname : ""));
534
535 if (pcmk_is_set(then->flags, pe_action_requires_any)) {
536
537
538
539
540 then->runnable_before = 0;
541
542
543
544
545 if (then->required_runnable_before == 0) {
546 then->required_runnable_before = 1;
547 }
548 pe__clear_action_flags(then, pe_action_runnable);
549
550
551
552
553
554
555
556 }
557
558 for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) {
559 pe_action_wrapper_t *other = (pe_action_wrapper_t *) lpc->data;
560 pe_action_t *first = other->action;
561
562 pe_node_t *then_node = then->node;
563 pe_node_t *first_node = first->node;
564
565 enum pe_action_flags then_flags = 0;
566 enum pe_action_flags first_flags = 0;
567
568 if (first->rsc && first->rsc->variant == pe_group && pcmk__str_eq(first->task, RSC_START, pcmk__str_casei)) {
569 first_node = first->rsc->fns->location(first->rsc, NULL, FALSE);
570 if (first_node) {
571 crm_trace("First: Found node %s for %s", first_node->details->uname, first->uuid);
572 }
573 }
574
575 if (then->rsc && then->rsc->variant == pe_group && pcmk__str_eq(then->task, RSC_START, pcmk__str_casei)) {
576 then_node = then->rsc->fns->location(then->rsc, NULL, FALSE);
577 if (then_node) {
578 crm_trace("Then: Found node %s for %s", then_node->details->uname, then->uuid);
579 }
580 }
581
582 if (pcmk_is_set(other->type, pe_order_same_node)
583 && (first_node != NULL) && (then_node != NULL)
584 && (first_node->details != then_node->details)) {
585
586 crm_trace("Disabled constraint %s on %s -> %s on %s",
587 other->action->uuid, first_node->details->uname,
588 then->uuid, then_node->details->uname);
589 other->type = pe_order_none;
590 continue;
591 }
592
593 pe__clear_graph_flags(changed, then, pe_graph_updated_first);
594
595 if (first->rsc && pcmk_is_set(other->type, pe_order_then_cancels_first)
596 && !pcmk_is_set(then->flags, pe_action_optional)) {
597
598
599
600
601 pe__set_action_flags(other->action, pe_action_optional);
602 if (!strcmp(first->task, CRMD_ACTION_RELOAD_AGENT)) {
603 pe__clear_resource_flags(first->rsc, pe_rsc_reload);
604 }
605 }
606
607 if (first->rsc && then->rsc && (first->rsc != then->rsc)
608 && (is_parent(then->rsc, first->rsc) == FALSE)) {
609 first = rsc_expand_action(first);
610 }
611 if (first != other->action) {
612 crm_trace("Ordering %s after %s instead of %s", then->uuid, first->uuid,
613 other->action->uuid);
614 }
615
616 first_flags = get_action_flags(first, then_node);
617 then_flags = get_action_flags(then, first_node);
618
619 crm_trace("Checking %s (%s %s %s) against %s (%s %s %s) filter=0x%.6x type=0x%.6x",
620 then->uuid,
621 pcmk_is_set(then_flags, pe_action_optional)? "optional" : "required",
622 pcmk_is_set(then_flags, pe_action_runnable)? "runnable" : "unrunnable",
623 pcmk_is_set(then_flags, pe_action_pseudo)? "pseudo"
624 : (then->node? then->node->details->uname : ""),
625 first->uuid,
626 pcmk_is_set(first_flags, pe_action_optional)? "optional" : "required",
627 pcmk_is_set(first_flags, pe_action_runnable)? "runnable" : "unrunnable",
628 pcmk_is_set(first_flags, pe_action_pseudo)? "pseudo"
629 : (first->node? first->node->details->uname : ""),
630 first_flags, other->type);
631
632 if (first == other->action) {
633
634
635
636
637
638
639
640
641
642
643
644
645
646 pe_node_t *node = then->node;
647 changed |= graph_update_action(first, then, node, first_flags,
648 then_flags, other, data_set);
649
650
651
652
653 } else if (order_actions(first, then, other->type)) {
654
655
656
657 pe__set_graph_flags(changed, then,
658 pe_graph_updated_then|pe_graph_disable);
659 }
660
661 if (changed & pe_graph_disable) {
662 crm_trace("Disabled constraint %s -> %s in favor of %s -> %s",
663 other->action->uuid, then->uuid, first->uuid, then->uuid);
664 pe__clear_graph_flags(changed, then, pe_graph_disable);
665 other->type = pe_order_none;
666 }
667
668 if (changed & pe_graph_updated_first) {
669 GList *lpc2 = NULL;
670
671 crm_trace("Updated %s (first %s %s %s), processing dependents ",
672 first->uuid,
673 pcmk_is_set(first->flags, pe_action_optional)? "optional" : "required",
674 pcmk_is_set(first->flags, pe_action_runnable)? "runnable" : "unrunnable",
675 pcmk_is_set(first->flags, pe_action_pseudo)? "pseudo"
676 : (first->node? first->node->details->uname : ""));
677 for (lpc2 = first->actions_after; lpc2 != NULL; lpc2 = lpc2->next) {
678 pe_action_wrapper_t *other = (pe_action_wrapper_t *) lpc2->data;
679
680 update_action(other->action, data_set);
681 }
682 update_action(first, data_set);
683 }
684 }
685
686 if (pcmk_is_set(then->flags, pe_action_requires_any)) {
687 if (last_flags != then->flags) {
688 pe__set_graph_flags(changed, then, pe_graph_updated_then);
689 } else {
690 pe__clear_graph_flags(changed, then, pe_graph_updated_then);
691 }
692 }
693
694 if (changed & pe_graph_updated_then) {
695 crm_trace("Updated %s (then %s %s %s), processing dependents ",
696 then->uuid,
697 pcmk_is_set(then->flags, pe_action_optional)? "optional" : "required",
698 pcmk_is_set(then->flags, pe_action_runnable)? "runnable" : "unrunnable",
699 pcmk_is_set(then->flags, pe_action_pseudo)? "pseudo"
700 : (then->node? then->node->details-> uname : ""));
701
702 if (pcmk_is_set(last_flags, pe_action_runnable)
703 && !pcmk_is_set(then->flags, pe_action_runnable)) {
704 update_colo_start_chain(then, data_set);
705 }
706 update_action(then, data_set);
707 for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) {
708 pe_action_wrapper_t *other = (pe_action_wrapper_t *) lpc->data;
709
710 update_action(other->action, data_set);
711 }
712 }
713
714 return FALSE;
715 }
716
717 gboolean
718 shutdown_constraints(pe_node_t * node, pe_action_t * shutdown_op, pe_working_set_t * data_set)
719 {
720
721
722
723 GList *lpc = NULL;
724
725 for (lpc = data_set->actions; lpc != NULL; lpc = lpc->next) {
726 pe_action_t *action = (pe_action_t *) lpc->data;
727
728 if (action->rsc == NULL || action->node == NULL) {
729 continue;
730 } else if (action->node->details != node->details) {
731 continue;
732 } else if (pcmk_is_set(action->rsc->flags, pe_rsc_maintenance)) {
733 pe_rsc_trace(action->rsc, "Skipping %s: maintenance mode", action->uuid);
734 continue;
735 } else if (node->details->maintenance) {
736 pe_rsc_trace(action->rsc, "Skipping %s: node %s is in maintenance mode",
737 action->uuid, node->details->uname);
738 continue;
739 } else if (!pcmk__str_eq(action->task, RSC_STOP, pcmk__str_casei)) {
740 continue;
741 } else if (!pcmk_any_flags_set(action->rsc->flags,
742 pe_rsc_managed|pe_rsc_block)) {
743
744
745
746 pe_rsc_trace(action->rsc, "Skipping %s: unmanaged", action->uuid);
747 continue;
748 }
749
750 pe_rsc_trace(action->rsc, "Ordering %s before shutdown on %s", action->uuid,
751 node->details->uname);
752 pe__clear_action_flags(action, pe_action_optional);
753 custom_action_order(action->rsc, NULL, action,
754 NULL, strdup(CRM_OP_SHUTDOWN), shutdown_op,
755 pe_order_optional | pe_order_runnable_left, data_set);
756 }
757
758 return TRUE;
759 }
760
761
762
763
764
765
766
767
768
769
770
771
772 void
773 pcmk__order_vs_fence(pe_action_t *stonith_op, pe_working_set_t *data_set)
774 {
775 CRM_CHECK(stonith_op && data_set, return);
776 for (GList *r = data_set->resources; r != NULL; r = r->next) {
777 rsc_stonith_ordering((pe_resource_t *) r->data, stonith_op, data_set);
778 }
779 }
780
781 static pe_node_t *
782 get_router_node(pe_action_t *action)
783 {
784 pe_node_t *began_on = NULL;
785 pe_node_t *ended_on = NULL;
786 bool partial_migration = FALSE;
787 const char *task = action->task;
788
789 if (pcmk__str_eq(task, CRM_OP_FENCE, pcmk__str_casei)
790 || !pe__is_guest_or_remote_node(action->node)) {
791 return NULL;
792 }
793
794 CRM_ASSERT(action->node->details->remote_rsc != NULL);
795
796 began_on = pe__current_node(action->node->details->remote_rsc);
797 ended_on = action->node->details->remote_rsc->allocated_to;
798 if (action->node->details->remote_rsc
799 && (action->node->details->remote_rsc->container == NULL)
800 && action->node->details->remote_rsc->partial_migration_target) {
801 partial_migration = TRUE;
802 }
803
804 if (began_on == NULL) {
805 crm_trace("Routing %s for %s through remote connection's "
806 "next node %s (starting)%s",
807 action->task, (action->rsc? action->rsc->id : "no resource"),
808 (ended_on? ended_on->details->uname : "none"),
809 partial_migration? " (partial migration)" : "");
810 return ended_on;
811 }
812
813 if (ended_on == NULL) {
814 crm_trace("Routing %s for %s through remote connection's "
815 "current node %s (stopping)%s",
816 action->task, (action->rsc? action->rsc->id : "no resource"),
817 (began_on? began_on->details->uname : "none"),
818 partial_migration? " (partial migration)" : "");
819 return began_on;
820 }
821
822 if (began_on->details == ended_on->details) {
823 crm_trace("Routing %s for %s through remote connection's "
824 "current node %s (not moving)%s",
825 action->task, (action->rsc? action->rsc->id : "no resource"),
826 (began_on? began_on->details->uname : "none"),
827 partial_migration? " (partial migration)" : "");
828 return began_on;
829 }
830
831
832
833
834
835
836
837
838 if (pcmk__str_eq(task, "notify", pcmk__str_casei)) {
839 task = g_hash_table_lookup(action->meta, "notify_operation");
840 }
841
842
843
844
845
846
847
848
849
850
851
852
853
854 if (pcmk__strcase_any_of(task, "cancel", "stop", "demote", "migrate_from",
855 "migrate_to", NULL) && !partial_migration) {
856 crm_trace("Routing %s for %s through remote connection's "
857 "current node %s (moving)%s",
858 action->task, (action->rsc? action->rsc->id : "no resource"),
859 (began_on? began_on->details->uname : "none"),
860 partial_migration? " (partial migration)" : "");
861 return began_on;
862 }
863
864
865
866
867
868 crm_trace("Routing %s for %s through remote connection's "
869 "next node %s (moving)%s",
870 action->task, (action->rsc? action->rsc->id : "no resource"),
871 (ended_on? ended_on->details->uname : "none"),
872 partial_migration? " (partial migration)" : "");
873 return ended_on;
874 }
875
876
877
878
879
880
881
882
883 static xmlNode*
884 add_node_to_xml_by_id(const char *id, xmlNode *xml)
885 {
886 xmlNode *node_xml;
887
888 node_xml = create_xml_node(xml, XML_CIB_TAG_NODE);
889 crm_xml_add(node_xml, XML_ATTR_UUID, id);
890
891 return node_xml;
892 }
893
894
895
896
897
898
899
900
901 static void
902 add_node_to_xml(const pe_node_t *node, void *xml)
903 {
904 add_node_to_xml_by_id(node->details->id, (xmlNode *) xml);
905 }
906
907
908
909
910
911
912
913
914 static int
915 add_maintenance_nodes(xmlNode *xml, const pe_working_set_t *data_set)
916 {
917 GList *gIter = NULL;
918 xmlNode *maintenance =
919 xml?create_xml_node(xml, XML_GRAPH_TAG_MAINTENANCE):NULL;
920 int count = 0;
921
922 for (gIter = data_set->nodes; gIter != NULL;
923 gIter = gIter->next) {
924 pe_node_t *node = (pe_node_t *) gIter->data;
925 struct pe_node_shared_s *details = node->details;
926
927 if (!pe__is_guest_or_remote_node(node)) {
928 continue;
929 }
930
931 if (details->maintenance != details->remote_maintenance) {
932 if (maintenance) {
933 crm_xml_add(
934 add_node_to_xml_by_id(node->details->id, maintenance),
935 XML_NODE_IS_MAINTENANCE, details->maintenance?"1":"0");
936 }
937 count++;
938 }
939 }
940 crm_trace("%s %d nodes to adjust maintenance-mode "
941 "to transition", maintenance?"Added":"Counted", count);
942 return count;
943 }
944
945
946
947
948
949
950
951 void
952 add_maintenance_update(pe_working_set_t *data_set)
953 {
954 pe_action_t *action = NULL;
955
956 if (add_maintenance_nodes(NULL, data_set)) {
957 crm_trace("adding maintenance state update pseudo action");
958 action = get_pseudo_op(CRM_OP_MAINTENANCE_NODES, data_set);
959 pe__set_action_flags(action, pe_action_print_always);
960 }
961 }
962
963
964
965
966
967
968
969
970
971
972
973
974
975 static void
976 add_downed_nodes(xmlNode *xml, const pe_action_t *action,
977 const pe_working_set_t *data_set)
978 {
979 CRM_CHECK(xml && action && action->node && data_set, return);
980
981 if (pcmk__str_eq(action->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
982
983
984 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
985 add_node_to_xml_by_id(action->node->details->id, downed);
986
987 } else if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei)) {
988
989
990 const char *fence = g_hash_table_lookup(action->meta, "stonith_action");
991
992 if (pcmk__strcase_any_of(fence, "off", "reboot", NULL)) {
993 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
994 add_node_to_xml_by_id(action->node->details->id, downed);
995 pe_foreach_guest_node(data_set, action->node, add_node_to_xml, downed);
996 }
997
998 } else if (action->rsc && action->rsc->is_remote_node
999 && pcmk__str_eq(action->task, CRMD_ACTION_STOP, pcmk__str_casei)) {
1000
1001
1002
1003
1004 GList *iter;
1005 pe_action_t *input;
1006 gboolean migrating = FALSE;
1007
1008 for (iter = action->actions_before; iter != NULL; iter = iter->next) {
1009 input = ((pe_action_wrapper_t *) iter->data)->action;
1010 if (input->rsc && pcmk__str_eq(action->rsc->id, input->rsc->id, pcmk__str_casei)
1011 && pcmk__str_eq(input->task, CRMD_ACTION_MIGRATED, pcmk__str_casei)) {
1012 migrating = TRUE;
1013 break;
1014 }
1015 }
1016 if (!migrating) {
1017 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
1018 add_node_to_xml_by_id(action->rsc->id, downed);
1019 }
1020 }
1021 }
1022
1023 static bool
1024 should_lock_action(pe_action_t *action)
1025 {
1026
1027 if ((action->rsc->lock_node == NULL) || (action->node == NULL)
1028 || (action->node->details != action->rsc->lock_node->details)) {
1029 return false;
1030 }
1031
1032
1033
1034
1035 if (action->node->details->shutdown && action->task
1036 && strcmp(action->task, RSC_STOP)) {
1037 return false;
1038 }
1039
1040 return true;
1041 }
1042
1043 static xmlNode *
1044 action2xml(pe_action_t * action, gboolean as_input, pe_working_set_t *data_set)
1045 {
1046 gboolean needs_node_info = TRUE;
1047 gboolean needs_maintenance_info = FALSE;
1048 xmlNode *action_xml = NULL;
1049 xmlNode *args_xml = NULL;
1050 #if ENABLE_VERSIONED_ATTRS
1051 pe_rsc_action_details_t *rsc_details = NULL;
1052 #endif
1053
1054 if (action == NULL) {
1055 return NULL;
1056 }
1057
1058 if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei)) {
1059
1060 action_xml = create_xml_node(NULL,
1061 pcmk_is_set(action->flags, pe_action_pseudo)?
1062 XML_GRAPH_TAG_PSEUDO_EVENT :
1063 XML_GRAPH_TAG_CRM_EVENT);
1064
1065 } else if (pcmk__str_eq(action->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
1066 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1067
1068 } else if (pcmk__str_eq(action->task, CRM_OP_CLEAR_FAILCOUNT, pcmk__str_casei)) {
1069 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1070
1071 } else if (pcmk__str_eq(action->task, CRM_OP_LRM_REFRESH, pcmk__str_casei)) {
1072 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1073
1074 } else if (pcmk__str_eq(action->task, CRM_OP_LRM_DELETE, pcmk__str_casei)) {
1075
1076 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1077 crm_xml_add(action_xml, PCMK__XA_MODE, XML_TAG_CIB);
1078
1079
1080
1081
1082 } else if (pcmk_is_set(action->flags, pe_action_pseudo)) {
1083 if (pcmk__str_eq(action->task, CRM_OP_MAINTENANCE_NODES, pcmk__str_casei)) {
1084 needs_maintenance_info = TRUE;
1085 }
1086 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_PSEUDO_EVENT);
1087 needs_node_info = FALSE;
1088
1089 } else {
1090 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
1091
1092 #if ENABLE_VERSIONED_ATTRS
1093 rsc_details = pe_rsc_action_details(action);
1094 #endif
1095 }
1096
1097 crm_xml_add_int(action_xml, XML_ATTR_ID, action->id);
1098 crm_xml_add(action_xml, XML_LRM_ATTR_TASK, action->task);
1099 if (action->rsc != NULL && action->rsc->clone_name != NULL) {
1100 char *clone_key = NULL;
1101 guint interval_ms;
1102
1103 if (pcmk__guint_from_hash(action->meta,
1104 XML_LRM_ATTR_INTERVAL_MS, 0,
1105 &interval_ms) != pcmk_rc_ok) {
1106 interval_ms = 0;
1107 }
1108
1109 if (pcmk__str_eq(action->task, RSC_NOTIFY, pcmk__str_casei)) {
1110 const char *n_type = g_hash_table_lookup(action->meta, "notify_type");
1111 const char *n_task = g_hash_table_lookup(action->meta, "notify_operation");
1112
1113 CRM_CHECK(n_type != NULL, crm_err("No notify type value found for %s", action->uuid));
1114 CRM_CHECK(n_task != NULL,
1115 crm_err("No notify operation value found for %s", action->uuid));
1116 clone_key = pcmk__notify_key(action->rsc->clone_name,
1117 n_type, n_task);
1118
1119 } else if(action->cancel_task) {
1120 clone_key = pcmk__op_key(action->rsc->clone_name,
1121 action->cancel_task, interval_ms);
1122 } else {
1123 clone_key = pcmk__op_key(action->rsc->clone_name,
1124 action->task, interval_ms);
1125 }
1126
1127 CRM_CHECK(clone_key != NULL, crm_err("Could not generate a key for %s", action->uuid));
1128 crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, clone_key);
1129 crm_xml_add(action_xml, "internal_" XML_LRM_ATTR_TASK_KEY, action->uuid);
1130 free(clone_key);
1131
1132 } else {
1133 crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, action->uuid);
1134 }
1135
1136 if (needs_node_info && action->node != NULL) {
1137 pe_node_t *router_node = get_router_node(action);
1138
1139 crm_xml_add(action_xml, XML_LRM_ATTR_TARGET, action->node->details->uname);
1140 crm_xml_add(action_xml, XML_LRM_ATTR_TARGET_UUID, action->node->details->id);
1141 if (router_node) {
1142 crm_xml_add(action_xml, XML_LRM_ATTR_ROUTER_NODE, router_node->details->uname);
1143 }
1144
1145 g_hash_table_insert(action->meta, strdup(XML_LRM_ATTR_TARGET), strdup(action->node->details->uname));
1146 g_hash_table_insert(action->meta, strdup(XML_LRM_ATTR_TARGET_UUID), strdup(action->node->details->id));
1147 }
1148
1149
1150 if (as_input) {
1151 return action_xml;
1152 }
1153
1154 if (action->rsc && !pcmk_is_set(action->flags, pe_action_pseudo)) {
1155 int lpc = 0;
1156 xmlNode *rsc_xml = NULL;
1157 const char *attr_list[] = {
1158 XML_AGENT_ATTR_CLASS,
1159 XML_AGENT_ATTR_PROVIDER,
1160 XML_ATTR_TYPE
1161 };
1162
1163
1164
1165
1166 if (should_lock_action(action)) {
1167 crm_xml_add_ll(action_xml, XML_CONFIG_ATTR_SHUTDOWN_LOCK,
1168 (long long) action->rsc->lock_time);
1169 }
1170
1171
1172
1173 rsc_xml = create_xml_node(action_xml,
1174 crm_element_name(action->rsc->xml));
1175 if (pcmk_is_set(action->rsc->flags, pe_rsc_orphan)
1176 && action->rsc->clone_name) {
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188 crm_debug("Using orphan clone name %s instead of %s", action->rsc->id,
1189 action->rsc->clone_name);
1190 crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->clone_name);
1191 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
1192
1193 } else if (!pcmk_is_set(action->rsc->flags, pe_rsc_unique)) {
1194 const char *xml_id = ID(action->rsc->xml);
1195
1196 crm_debug("Using anonymous clone name %s for %s (aka. %s)", xml_id, action->rsc->id,
1197 action->rsc->clone_name);
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212 crm_xml_add(rsc_xml, XML_ATTR_ID, xml_id);
1213 if (action->rsc->clone_name && !pcmk__str_eq(xml_id, action->rsc->clone_name, pcmk__str_casei)) {
1214 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->clone_name);
1215 } else {
1216 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
1217 }
1218
1219 } else {
1220 CRM_ASSERT(action->rsc->clone_name == NULL);
1221 crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->id);
1222 }
1223
1224 for (lpc = 0; lpc < PCMK__NELEM(attr_list); lpc++) {
1225 crm_xml_add(rsc_xml, attr_list[lpc],
1226 g_hash_table_lookup(action->rsc->meta, attr_list[lpc]));
1227 }
1228 }
1229
1230
1231 args_xml = create_xml_node(NULL, XML_TAG_ATTRS);
1232 crm_xml_add(args_xml, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
1233
1234 g_hash_table_foreach(action->extra, hash2field, args_xml);
1235 if (action->rsc != NULL && action->node) {
1236
1237 GHashTable *params = pe_rsc_params(action->rsc, action->node, data_set);
1238
1239
1240
1241
1242
1243
1244 const char *remote_addr = g_hash_table_lookup(params,
1245 XML_RSC_ATTR_REMOTE_RA_ADDR);
1246
1247 if (pcmk__str_eq(remote_addr, "#uname", pcmk__str_none)) {
1248 GHashTable *base = pe_rsc_params(action->rsc, NULL, data_set);
1249
1250 remote_addr = g_hash_table_lookup(base,
1251 XML_RSC_ATTR_REMOTE_RA_ADDR);
1252 if (remote_addr != NULL) {
1253 g_hash_table_insert(params, strdup(XML_RSC_ATTR_REMOTE_RA_ADDR),
1254 strdup(remote_addr));
1255 }
1256 }
1257
1258 g_hash_table_foreach(params, hash2smartfield, args_xml);
1259
1260 #if ENABLE_VERSIONED_ATTRS
1261 {
1262 xmlNode *versioned_parameters = create_xml_node(NULL, XML_TAG_RSC_VER_ATTRS);
1263
1264 pe_get_versioned_attributes(versioned_parameters, action->rsc,
1265 action->node, data_set);
1266 if (xml_has_children(versioned_parameters)) {
1267 add_node_copy(action_xml, versioned_parameters);
1268 }
1269 free_xml(versioned_parameters);
1270 }
1271 #endif
1272
1273 } else if(action->rsc && action->rsc->variant <= pe_native) {
1274 GHashTable *params = pe_rsc_params(action->rsc, NULL, data_set);
1275
1276 g_hash_table_foreach(params, hash2smartfield, args_xml);
1277
1278 #if ENABLE_VERSIONED_ATTRS
1279 if (xml_has_children(action->rsc->versioned_parameters)) {
1280 add_node_copy(action_xml, action->rsc->versioned_parameters);
1281 }
1282 #endif
1283 }
1284
1285 #if ENABLE_VERSIONED_ATTRS
1286 if (rsc_details) {
1287 if (xml_has_children(rsc_details->versioned_parameters)) {
1288 add_node_copy(action_xml, rsc_details->versioned_parameters);
1289 }
1290
1291 if (xml_has_children(rsc_details->versioned_meta)) {
1292 add_node_copy(action_xml, rsc_details->versioned_meta);
1293 }
1294 }
1295 #endif
1296
1297 g_hash_table_foreach(action->meta, hash2metafield, args_xml);
1298 if (action->rsc != NULL) {
1299 const char *value = g_hash_table_lookup(action->rsc->meta, "external-ip");
1300 pe_resource_t *parent = action->rsc;
1301
1302 while (parent != NULL) {
1303 parent->cmds->append_meta(parent, args_xml);
1304 parent = parent->parent;
1305 }
1306
1307 if(value) {
1308 hash2smartfield((gpointer)"pcmk_external_ip", (gpointer)value, (gpointer)args_xml);
1309 }
1310
1311 if (action->node &&
1312 pe__is_guest_node(action->node)) {
1313 pe_node_t *host = NULL;
1314 enum action_tasks task = text2task(action->task);
1315
1316 if(task == action_notify || task == action_notified) {
1317 const char *n_task = g_hash_table_lookup(action->meta, "notify_operation");
1318 task = text2task(n_task);
1319 }
1320
1321
1322 switch (task) {
1323 case stop_rsc:
1324 case stopped_rsc:
1325 case action_demote:
1326 case action_demoted:
1327 host = pe__current_node(action->node->details->remote_rsc->container);
1328 break;
1329 case start_rsc:
1330 case started_rsc:
1331 case monitor_rsc:
1332 case action_promote:
1333 case action_promoted:
1334 host = action->node->details->remote_rsc->container->allocated_to;
1335 break;
1336 default:
1337 break;
1338 }
1339
1340 if(host) {
1341 hash2metafield((gpointer)XML_RSC_ATTR_TARGET,
1342 (gpointer)g_hash_table_lookup(action->rsc->meta, XML_RSC_ATTR_TARGET), (gpointer)args_xml);
1343 hash2metafield((gpointer) PCMK__ENV_PHYSICAL_HOST,
1344 (gpointer)host->details->uname,
1345 (gpointer)args_xml);
1346 }
1347 }
1348
1349 } else if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei) && action->node) {
1350
1351
1352
1353
1354
1355
1356 g_hash_table_foreach(action->node->details->attrs, hash2metafield, args_xml);
1357 }
1358
1359 sorted_xml(args_xml, action_xml, FALSE);
1360 free_xml(args_xml);
1361
1362
1363 if (needs_node_info && (action->node != NULL)) {
1364 add_downed_nodes(action_xml, action, data_set);
1365 }
1366
1367 if (needs_maintenance_info) {
1368 add_maintenance_nodes(action_xml, data_set);
1369 }
1370
1371 crm_log_xml_trace(action_xml, "dumped action");
1372 return action_xml;
1373 }
1374
1375 static bool
1376 should_dump_action(pe_action_t *action)
1377 {
1378 CRM_CHECK(action != NULL, return false);
1379
1380 if (pcmk_is_set(action->flags, pe_action_dumped)) {
1381 crm_trace("Action %s (%d) already dumped", action->uuid, action->id);
1382 return false;
1383
1384 } else if (pcmk_is_set(action->flags, pe_action_pseudo)
1385 && pcmk__str_eq(action->task, CRM_OP_PROBED, pcmk__str_casei)) {
1386 GList *lpc = NULL;
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403 for (lpc = action->actions_after; lpc != NULL; lpc = lpc->next) {
1404 pe_action_wrapper_t *wrapper = (pe_action_wrapper_t *) lpc->data;
1405
1406 if (!pcmk_is_set(wrapper->action->flags, pe_action_runnable)) {
1407
1408 } else if (!pcmk__str_eq(wrapper->action->task, RSC_START, pcmk__str_casei)) {
1409
1410 } else if (pcmk_is_set(wrapper->action->flags, pe_action_dumped)
1411 || should_dump_action(wrapper->action)) {
1412 crm_trace("Action %s (%d) should be dumped: "
1413 "dependency of %s (%d)",
1414 action->uuid, action->id,
1415 wrapper->action->uuid, wrapper->action->id);
1416 return true;
1417 }
1418 }
1419 }
1420
1421 if (!pcmk_is_set(action->flags, pe_action_runnable)) {
1422 crm_trace("Ignoring action %s (%d): unrunnable",
1423 action->uuid, action->id);
1424 return false;
1425
1426 } else if (pcmk_is_set(action->flags, pe_action_optional)
1427 && !pcmk_is_set(action->flags, pe_action_print_always)) {
1428 crm_trace("Ignoring action %s (%d): optional",
1429 action->uuid, action->id);
1430 return false;
1431
1432
1433 } else if (action->rsc && !pcmk_is_set(action->rsc->flags, pe_rsc_managed)
1434 && !pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)) {
1435
1436 const char *interval_ms_s = g_hash_table_lookup(action->meta,
1437 XML_LRM_ATTR_INTERVAL_MS);
1438
1439
1440 if (pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches)) {
1441 crm_trace("Ignoring action %s (%d): for unmanaged resource (%s)",
1442 action->uuid, action->id, action->rsc->id);
1443 return false;
1444 }
1445 }
1446
1447 if (pcmk_is_set(action->flags, pe_action_pseudo) ||
1448 pcmk__strcase_any_of(action->task, CRM_OP_FENCE, CRM_OP_SHUTDOWN, NULL)) {
1449
1450 return true;
1451 }
1452
1453 if (action->node == NULL) {
1454 pe_err("Skipping action %s (%d) "
1455 "because it was not allocated to a node (bug?)",
1456 action->uuid, action->id);
1457 log_action(LOG_DEBUG, "Unallocated action", action, false);
1458 return false;
1459
1460 } else if (pcmk_is_set(action->flags, pe_action_dc)) {
1461 crm_trace("Action %s (%d) should be dumped: "
1462 "can run on DC instead of %s",
1463 action->uuid, action->id, action->node->details->uname);
1464
1465 } else if (pe__is_guest_node(action->node)
1466 && !action->node->details->remote_requires_reset) {
1467 crm_trace("Action %s (%d) should be dumped: "
1468 "assuming will be runnable on guest node %s",
1469 action->uuid, action->id, action->node->details->uname);
1470
1471 } else if (action->node->details->online == false) {
1472 pe_err("Skipping action %s (%d) "
1473 "because it was scheduled for offline node (bug?)",
1474 action->uuid, action->id);
1475 log_action(LOG_DEBUG, "Action for offline node", action, FALSE);
1476 return false;
1477 #if 0
1478
1479
1480
1481 } else if (action->node->details->unclean == false) {
1482 pe_err("Skipping action %s (%d) "
1483 "because it was scheduled for unclean node (bug?)",
1484 action->uuid, action->id);
1485 log_action(LOG_DEBUG, "Action for unclean node", action, false);
1486 return false;
1487 #endif
1488 }
1489 return true;
1490 }
1491
1492
1493 static gint
1494 sort_action_id(gconstpointer a, gconstpointer b)
1495 {
1496 const pe_action_wrapper_t *action_wrapper2 = (const pe_action_wrapper_t *)a;
1497 const pe_action_wrapper_t *action_wrapper1 = (const pe_action_wrapper_t *)b;
1498
1499 if (a == NULL) {
1500 return 1;
1501 }
1502 if (b == NULL) {
1503 return -1;
1504 }
1505
1506 if (action_wrapper1->action->id > action_wrapper2->action->id) {
1507 return -1;
1508 }
1509
1510 if (action_wrapper1->action->id < action_wrapper2->action->id) {
1511 return 1;
1512 }
1513 return 0;
1514 }
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527 static bool
1528 check_dump_input(pe_action_t *action, pe_action_wrapper_t *input)
1529 {
1530 int type = input->type;
1531
1532 if (input->state == pe_link_dumped) {
1533 return true;
1534 }
1535
1536 pe__clear_order_flags(type, pe_order_implies_first_printed
1537 |pe_order_implies_then_printed
1538 |pe_order_optional);
1539
1540 if (input->type == pe_order_none) {
1541 crm_trace("Ignoring %s (%d) input %s (%d): "
1542 "ordering disabled",
1543 action->uuid, action->id,
1544 input->action->uuid, input->action->id);
1545 return false;
1546
1547 } else if (!pcmk_is_set(input->action->flags, pe_action_runnable)
1548 && (type == pe_order_none)
1549 && !pcmk__str_eq(input->action->uuid, CRM_OP_PROBED, pcmk__str_casei)) {
1550 crm_trace("Ignoring %s (%d) input %s (%d): "
1551 "optional and input unrunnable",
1552 action->uuid, action->id,
1553 input->action->uuid, input->action->id);
1554 return false;
1555
1556 } else if (!pcmk_is_set(input->action->flags, pe_action_runnable)
1557 && pcmk_is_set(input->type, pe_order_one_or_more)) {
1558 crm_trace("Ignoring %s (%d) input %s (%d): "
1559 "one-or-more and input unrunnable",
1560 action->uuid, action->id,
1561 input->action->uuid, input->action->id);
1562 return false;
1563
1564 } else if (pcmk_is_set(action->flags, pe_action_pseudo)
1565 && pcmk_is_set(input->type, pe_order_stonith_stop)) {
1566 crm_trace("Ignoring %s (%d) input %s (%d): "
1567 "stonith stop but action is pseudo",
1568 action->uuid, action->id,
1569 input->action->uuid, input->action->id);
1570 return false;
1571
1572 } else if (pcmk_is_set(input->type, pe_order_implies_first_migratable)
1573 && !pcmk_is_set(input->action->flags, pe_action_runnable)) {
1574 crm_trace("Ignoring %s (%d) input %s (%d): "
1575 "implies input migratable but input unrunnable",
1576 action->uuid, action->id,
1577 input->action->uuid, input->action->id);
1578 return false;
1579
1580 } else if (pcmk_is_set(input->type, pe_order_apply_first_non_migratable)
1581 && pcmk_is_set(input->action->flags, pe_action_migrate_runnable)) {
1582 crm_trace("Ignoring %s (%d) input %s (%d): "
1583 "only if input unmigratable but input unrunnable",
1584 action->uuid, action->id,
1585 input->action->uuid, input->action->id);
1586 return false;
1587
1588 } else if ((input->type == pe_order_optional)
1589 && pcmk_is_set(input->action->flags, pe_action_migrate_runnable)
1590 && pcmk__ends_with(input->action->uuid, "_stop_0")) {
1591 crm_trace("Ignoring %s (%d) input %s (%d): "
1592 "optional but stop in migration",
1593 action->uuid, action->id,
1594 input->action->uuid, input->action->id);
1595 return false;
1596
1597 } else if (input->type == pe_order_load) {
1598 pe_node_t *input_node = input->action->node;
1599
1600
1601
1602 if (action->rsc && pcmk__str_eq(action->task, RSC_MIGRATE, pcmk__str_casei)) {
1603 pe_node_t *allocated = action->rsc->allocated_to;
1604
1605
1606
1607
1608 if ((input_node == NULL) || (allocated == NULL)
1609 || (input_node->details != allocated->details)) {
1610 crm_trace("Ignoring %s (%d) input %s (%d): "
1611 "load ordering node mismatch %s vs %s",
1612 action->uuid, action->id,
1613 input->action->uuid, input->action->id,
1614 (allocated? allocated->details->uname : "<none>"),
1615 (input_node? input_node->details->uname : "<none>"));
1616 input->type = pe_order_none;
1617 return false;
1618 }
1619
1620 } else if ((input_node == NULL) || (action->node == NULL)
1621 || (input_node->details != action->node->details)) {
1622 crm_trace("Ignoring %s (%d) input %s (%d): "
1623 "load ordering node mismatch %s vs %s",
1624 action->uuid, action->id,
1625 input->action->uuid, input->action->id,
1626 (action->node? action->node->details->uname : "<none>"),
1627 (input_node? input_node->details->uname : "<none>"));
1628 input->type = pe_order_none;
1629 return false;
1630
1631 } else if (pcmk_is_set(input->action->flags, pe_action_optional)) {
1632 crm_trace("Ignoring %s (%d) input %s (%d): "
1633 "load ordering input optional",
1634 action->uuid, action->id,
1635 input->action->uuid, input->action->id);
1636 input->type = pe_order_none;
1637 return false;
1638 }
1639
1640 } else if (input->type == pe_order_anti_colocation) {
1641 if (input->action->node && action->node
1642 && (input->action->node->details != action->node->details)) {
1643 crm_trace("Ignoring %s (%d) input %s (%d): "
1644 "anti-colocation node mismatch %s vs %s",
1645 action->uuid, action->id,
1646 input->action->uuid, input->action->id,
1647 action->node->details->uname,
1648 input->action->node->details->uname);
1649 input->type = pe_order_none;
1650 return false;
1651
1652 } else if (pcmk_is_set(input->action->flags, pe_action_optional)) {
1653 crm_trace("Ignoring %s (%d) input %s (%d): "
1654 "anti-colocation input optional",
1655 action->uuid, action->id,
1656 input->action->uuid, input->action->id);
1657 input->type = pe_order_none;
1658 return false;
1659 }
1660
1661 } else if (input->action->rsc
1662 && input->action->rsc != action->rsc
1663 && pcmk_is_set(input->action->rsc->flags, pe_rsc_failed)
1664 && !pcmk_is_set(input->action->rsc->flags, pe_rsc_managed)
1665 && pcmk__ends_with(input->action->uuid, "_stop_0")
1666 && action->rsc && pe_rsc_is_clone(action->rsc)) {
1667 crm_warn("Ignoring requirement that %s complete before %s:"
1668 " unmanaged failed resources cannot prevent clone shutdown",
1669 input->action->uuid, action->uuid);
1670 return false;
1671
1672 } else if (pcmk_is_set(input->action->flags, pe_action_optional)
1673 && !pcmk_any_flags_set(input->action->flags,
1674 pe_action_print_always|pe_action_dumped)
1675 && !should_dump_action(input->action)) {
1676 crm_trace("Ignoring %s (%d) input %s (%d): "
1677 "input optional",
1678 action->uuid, action->id,
1679 input->action->uuid, input->action->id);
1680 return false;
1681 }
1682
1683 crm_trace("%s (%d) input %s (%d) @ %s should be dumped: %s, %s, %s, 0x%.6x",
1684 action->uuid, action->id,
1685 input->action->uuid, input->action->id,
1686 input->action->node? input->action->node->details->uname : "no node",
1687 pcmk_is_set(input->action->flags, pe_action_pseudo)? "pseudo" : "real",
1688 pcmk_is_set(input->action->flags, pe_action_runnable)? "runnable" : "unrunnable",
1689 pcmk_is_set(input->action->flags, pe_action_optional)? "optional" : "required",
1690 input->type);
1691 return true;
1692 }
1693
1694 static bool
1695 graph_has_loop(pe_action_t *init_action, pe_action_t *action,
1696 pe_action_wrapper_t *input)
1697 {
1698 bool has_loop = false;
1699
1700 if (pcmk_is_set(input->action->flags, pe_action_tracking)) {
1701 crm_trace("Breaking tracking loop: %s@%s -> %s@%s (0x%.6x)",
1702 input->action->uuid,
1703 input->action->node? input->action->node->details->uname : "",
1704 action->uuid,
1705 action->node? action->node->details->uname : "",
1706 input->type);
1707 return false;
1708 }
1709
1710
1711 if (!check_dump_input(action, input)) {
1712 return false;
1713 }
1714
1715 if (input->action == init_action) {
1716 crm_debug("Input loop found in %s@%s ->...-> %s@%s",
1717 action->uuid,
1718 action->node? action->node->details->uname : "",
1719 init_action->uuid,
1720 init_action->node? init_action->node->details->uname : "");
1721 return true;
1722 }
1723
1724 pe__set_action_flags(input->action, pe_action_tracking);
1725
1726 crm_trace("Checking inputs of action %s@%s input %s@%s (0x%.6x)"
1727 "for graph loop with %s@%s ",
1728 action->uuid,
1729 action->node? action->node->details->uname : "",
1730 input->action->uuid,
1731 input->action->node? input->action->node->details->uname : "",
1732 input->type,
1733 init_action->uuid,
1734 init_action->node? init_action->node->details->uname : "");
1735
1736
1737 for (GList *iter = input->action->actions_before;
1738 iter != NULL; iter = iter->next) {
1739
1740 if (graph_has_loop(init_action, input->action,
1741 (pe_action_wrapper_t *) iter->data)) {
1742
1743 has_loop = true;
1744 goto done;
1745 }
1746 }
1747
1748 done:
1749 pe__clear_action_flags(input->action, pe_action_tracking);
1750
1751 if (!has_loop) {
1752 crm_trace("No input loop found in %s@%s -> %s@%s (0x%.6x)",
1753 input->action->uuid,
1754 input->action->node? input->action->node->details->uname : "",
1755 action->uuid,
1756 action->node? action->node->details->uname : "",
1757 input->type);
1758 }
1759 return has_loop;
1760 }
1761
1762 bool
1763 pcmk__ordering_is_invalid(pe_action_t *action, pe_action_wrapper_t *input)
1764 {
1765
1766
1767
1768 if (!pcmk_is_set(input->type, pe_order_preserve)
1769 && action->rsc && action->rsc->fillers
1770 && input->action->rsc && input->action->node
1771 && input->action->node->details->remote_rsc
1772 && (input->action->node->details->remote_rsc->container == action->rsc)) {
1773 crm_warn("Invalid ordering constraint between %s and %s",
1774 input->action->rsc->id, action->rsc->id);
1775 return true;
1776 }
1777
1778
1779
1780
1781
1782
1783
1784
1785 if ((input->type == pe_order_load) && action->rsc
1786 && pcmk__str_eq(action->task, RSC_MIGRATE, pcmk__str_casei)
1787 && graph_has_loop(action, action, input)) {
1788 return true;
1789 }
1790
1791 return false;
1792 }
1793
1794
1795 static void
1796 deduplicate_inputs(pe_action_t *action)
1797 {
1798 GList *item = NULL;
1799 GList *next = NULL;
1800 pe_action_wrapper_t *last_input = NULL;
1801
1802 action->actions_before = g_list_sort(action->actions_before,
1803 sort_action_id);
1804 for (item = action->actions_before; item != NULL; item = next) {
1805 pe_action_wrapper_t *input = (pe_action_wrapper_t *) item->data;
1806
1807 next = item->next;
1808 if (last_input && (input->action->id == last_input->action->id)) {
1809 crm_trace("Input %s (%d) duplicate skipped for action %s (%d)",
1810 input->action->uuid, input->action->id,
1811 action->uuid, action->id);
1812
1813
1814
1815
1816
1817 last_input->type |= input->type;
1818 if (input->state == pe_link_dumped) {
1819 last_input->state = pe_link_dumped;
1820 }
1821
1822 free(item->data);
1823 action->actions_before = g_list_delete_link(action->actions_before,
1824 item);
1825 } else {
1826 last_input = input;
1827 input->state = pe_link_not_dumped;
1828 }
1829 }
1830 }
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847 void
1848 graph_element_from_action(pe_action_t *action, pe_working_set_t *data_set)
1849 {
1850 GList *lpc = NULL;
1851 int synapse_priority = 0;
1852 xmlNode *syn = NULL;
1853 xmlNode *set = NULL;
1854 xmlNode *in = NULL;
1855 xmlNode *xml_action = NULL;
1856 pe_action_wrapper_t *input = NULL;
1857
1858
1859
1860
1861 if (!pcmk_is_set(action->flags, pe_action_dedup)) {
1862 deduplicate_inputs(action);
1863 pe__set_action_flags(action, pe_action_dedup);
1864 }
1865
1866 if (should_dump_action(action) == FALSE) {
1867 return;
1868 }
1869
1870 pe__set_action_flags(action, pe_action_dumped);
1871
1872 syn = create_xml_node(data_set->graph, "synapse");
1873 set = create_xml_node(syn, "action_set");
1874 in = create_xml_node(syn, "inputs");
1875
1876 crm_xml_add_int(syn, XML_ATTR_ID, data_set->num_synapse);
1877 data_set->num_synapse++;
1878
1879 if (action->rsc != NULL) {
1880 synapse_priority = action->rsc->priority;
1881 }
1882 if (action->priority > synapse_priority) {
1883 synapse_priority = action->priority;
1884 }
1885 if (synapse_priority > 0) {
1886 crm_xml_add_int(syn, XML_CIB_ATTR_PRIORITY, synapse_priority);
1887 }
1888
1889 xml_action = action2xml(action, FALSE, data_set);
1890 add_node_nocopy(set, crm_element_name(xml_action), xml_action);
1891
1892 for (lpc = action->actions_before; lpc != NULL; lpc = lpc->next) {
1893 input = (pe_action_wrapper_t *) lpc->data;
1894 if (check_dump_input(action, input)) {
1895 xmlNode *input_xml = create_xml_node(in, "trigger");
1896
1897 input->state = pe_link_dumped;
1898 xml_action = action2xml(input->action, TRUE, data_set);
1899 add_node_nocopy(input_xml, crm_element_name(xml_action), xml_action);
1900 }
1901 }
1902 }