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