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