1 /*
2 * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
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
get_action_flags(action_t * action,node_t * node)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 /* We only care about activity on $node */
46 enum pe_action_flags clone_flags = action->rsc->cmds->action_flags(action, node);
47
48 /* Go to great lengths to ensure the correct value for pe_action_runnable...
49 *
50 * If we are a clone, then for _ordering_ constraints, it's only relevant
51 * if we are runnable _anywhere_.
52 *
53 * This only applies to _runnable_ though, and only for ordering constraints.
54 * If this function is ever used during colocation, then we'll need additional logic
55 *
56 * Not very satisfying, but it's logical and appears to work well.
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 *
convert_non_atomic_uuid(char * old_uuid,resource_t * rsc,gboolean allow_notify,gboolean free_original)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; /* no conversion */
86
87 } else if (rsc->variant < pe_group) {
88 goto done; /* no conversion */
89 }
90
91 CRM_ASSERT(parse_op_key(old_uuid, &rid, &raw_task, &interval));
92 if (interval > 0) {
93 goto done; /* no conversion */
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 *
rsc_expand_action(action_t * action)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 /* Only outermost resources have notification actions.
160 * The exception is those in bundles.
161 */
162 notify = is_set(rsc->flags, pe_rsc_notify);
163 }
164
165 if (rsc->variant >= pe_group) {
166 /* Expand 'start' -> 'started' */
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
graph_update_action(action_t * first,action_t * then,node_t * node,enum pe_action_flags first_flags,enum pe_action_flags then_flags,action_wrapper_t * order)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 /* TODO: Do as many of these in parallel as possible */
194
195 if(is_set(type, pe_order_implies_then_on_node)) {
196 /* Normally we want the _whole_ 'then' clone to
197 * restart if 'first' is restarted, so then->node is
198 * needed.
199 *
200 * However for unfencing, we want to limit this to
201 * instances on the same node as 'first' (the
202 * unfencing operation), so first->node is supplied.
203 *
204 * Swap the node, from then on we can can treat it
205 * like any other 'pe_order_implies_then'
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 /* alright. a "first" action is considered runnable, incremente
299 * the 'runnable_before' counter */
300 then->runnable_before++;
301
302 /* if the runnable before count for then exceeds the required number
303 * of "before" runnable actions... mark then as runnable */
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__); /* don't care about changed */
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__); /* don't care about changed */
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
mark_start_blocked(resource_t * rsc,resource_t * reason)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
update_colo_start_chain(action_t * action)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 /* For bundles, uber_parent() returns the clone/master, not the
489 * bundle, so the existence of rsc->parent implies this is a bundle.
490 * In this case, we need the bundle resource, so that we can check
491 * if all containers are stopped/stopping.
492 */
493 rsc = rsc->parent;
494 }
495 }
496
497 if (rsc == NULL || rsc->rsc_cons_lhs == NULL) {
498 return;
499 }
500
501 /* if rsc has children, all the children need to have start set to
502 * unrunnable before we follow the colo chain for the parent. */
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
update_action(action_t * then)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 /* initialize current known runnable before actions to 0
535 * from here as graph_update_action is called for each of
536 * then's before actions, this number will increment as
537 * runnable 'first' actions are encountered */
538 then->runnable_before = 0;
539
540 /* for backwards compatibility with previous options that use
541 * the 'requires_any' flag, initialize required to 1 if it is
542 * not set. */
543 if (then->required_runnable_before == 0) {
544 then->required_runnable_before = 1;
545 }
546 pe_clear_action_bit(then, pe_action_runnable);
547 /* We are relying on the pe_order_one_or_more clause of
548 * graph_update_action(), called as part of the:
549 *
550 * 'if (first == other->action)'
551 *
552 * block below, to set this back if appropriate
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 /* Disable constraint if it only applies when on same node, but isn't */
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 /* 'then' is required, so we must abandon 'first'
596 * (e.g. a required stop cancels any reload).
597 * Only used with reload actions as 'first'.
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 * 'first' was not expanded (e.g. from 'start' to 'running'), which could mean it:
631 * - has no associated resource,
632 * - was a primitive,
633 * - was pre-expanded (e.g. 'running' instead of 'start')
634 *
635 * The third argument here to graph_update_action() is a node which is used under two conditions:
636 * - Interleaving, in which case first->node and
637 * then->node are equal (and NULL)
638 * - If 'then' is a clone, to limit the scope of the
639 * constraint to instances on the supplied node
640 *
641 */
642 node_t *node = then->node;
643 changed |= graph_update_action(first, then, node, first_flags, then_flags, other);
644
645 /* 'first' was for a complex resource (clone, group, etc),
646 * create a new dependency if necessary
647 */
648 } else if (order_actions(first, then, other->type)) {
649 /* This was the first time 'first' and 'then' were associated,
650 * start again to get the new actions_before list
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
shutdown_constraints(node_t * node,action_t * shutdown_op,pe_working_set_t * data_set)713 shutdown_constraints(node_t * node, action_t * shutdown_op, pe_working_set_t * data_set)
714 {
715 /* add the stop to the before lists so it counts as a pre-req
716 * for the shutdown
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 * If another action depends on this one, we may still end up blocking
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 * \internal
758 * \brief Order all actions appropriately relative to a fencing operation
759 *
760 * Ensure start operations of affected resources are ordered after fencing,
761 * imply stop and demote operations of affected resources by marking them as
762 * pseudo-actions, etc.
763 *
764 * \param[in] node Node to be fenced
765 * \param[in] stonith_op Fencing operation
766 * \param[in,out] data_set Working set of cluster
767 */
768 gboolean
stonith_constraints(node_t * node,action_t * stonith_op,pe_working_set_t * data_set)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 *
get_router_node(action_t * action)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 bool partial_migration = FALSE;
787 const char *task = action->task;
788
789 if (safe_str_eq(task, CRM_OP_FENCE) || is_remote_node(action->node) == FALSE) {
790 return NULL;
791 }
792
793 CRM_ASSERT(action->node->details->remote_rsc != NULL);
794
795 began_on = pe__current_node(action->node->details->remote_rsc);
796 ended_on = action->node->details->remote_rsc->allocated_to;
797 if (action->node->details->remote_rsc
798 && (action->node->details->remote_rsc->container == NULL)
799 && action->node->details->remote_rsc->partial_migration_target) {
800 partial_migration = TRUE;
801 }
802
803 /* if there is only one location to choose from,
804 * this is easy. Check for those conditions first */
805 if (!began_on || !ended_on) {
806 /* remote rsc is either shutting down or starting up */
807 return began_on ? began_on : ended_on;
808 } else if (began_on->details == ended_on->details) {
809 /* remote rsc didn't move nodes. */
810 return began_on;
811 }
812
813 /* If we have get here, we know the remote resource
814 * began on one node and is moving to another node.
815 *
816 * This means some actions will get routed through the cluster
817 * node the connection rsc began on, and others are routed through
818 * the cluster node the connection rsc ends up on.
819 *
820 * 1. stop, demote, migrate actions of resources living in the remote
821 * node _MUST_ occur _BEFORE_ the connection can move (these actions
822 * are all required before the remote rsc stop action can occur.) In
823 * this case, we know these actions have to be routed through the initial
824 * cluster node the connection resource lived on before the move takes place.
825 * The exception is a partial migration of a (non-guest) remote
826 * connection resource; in that case, all actions (even these) will be
827 * ordered after the connection's pseudo-start on the migration target,
828 * so the target is the router node.
829 *
830 * 2. Everything else (start, promote, monitor, probe, refresh, clear failcount
831 * delete ....) must occur after the resource starts on the node it is
832 * moving to.
833 */
834
835 if (safe_str_eq(task, "notify")) {
836 task = g_hash_table_lookup(action->meta, "notify_operation");
837 }
838
839 /* 1. before connection rsc moves. */
840 if ((safe_str_eq(task, "stop") ||
841 safe_str_eq(task, "demote") ||
842 safe_str_eq(task, "migrate_from") ||
843 safe_str_eq(task, "migrate_to")) && !partial_migration) {
844
845 router_node = began_on;
846
847 /* 2. after connection rsc moves. */
848 } else {
849 router_node = ended_on;
850 }
851 return router_node;
852 }
853
854 /*!
855 * \internal
856 * \brief Add an XML node tag for a specified ID
857 *
858 * \param[in] id Node UUID to add
859 * \param[in,out] xml Parent XML tag to add to
860 */
861 static xmlNode*
add_node_to_xml_by_id(const char * id,xmlNode * xml)862 add_node_to_xml_by_id(const char *id, xmlNode *xml)
863 {
864 xmlNode *node_xml;
865
866 node_xml = create_xml_node(xml, XML_CIB_TAG_NODE);
867 crm_xml_add(node_xml, XML_ATTR_UUID, id);
868
869 return node_xml;
870 }
871
872 /*!
873 * \internal
874 * \brief Add an XML node tag for a specified node
875 *
876 * \param[in] node Node to add
877 * \param[in,out] xml XML to add node to
878 */
879 static void
add_node_to_xml(const node_t * node,void * xml)880 add_node_to_xml(const node_t *node, void *xml)
881 {
882 add_node_to_xml_by_id(node->details->id, (xmlNode *) xml);
883 }
884
885 /*!
886 * \internal
887 * \brief Add XML with nodes that need an update of their maintenance state
888 *
889 * \param[in,out] xml Parent XML tag to add to
890 * \param[in] data_set Working set for cluster
891 */
892 static int
add_maintenance_nodes(xmlNode * xml,const pe_working_set_t * data_set)893 add_maintenance_nodes(xmlNode *xml, const pe_working_set_t *data_set)
894 {
895 GListPtr gIter = NULL;
896 xmlNode *maintenance =
897 xml?create_xml_node(xml, XML_GRAPH_TAG_MAINTENANCE):NULL;
898 int count = 0;
899
900 for (gIter = data_set->nodes; gIter != NULL;
901 gIter = gIter->next) {
902 node_t *node = (node_t *) gIter->data;
903 struct node_shared_s *details = node->details;
904
905 if (!(is_remote_node(node))) {
906 continue; /* just remote nodes need to know atm */
907 }
908
909 if (details->maintenance != details->remote_maintenance) {
910 if (maintenance) {
911 crm_xml_add(
912 add_node_to_xml_by_id(node->details->id, maintenance),
913 XML_NODE_IS_MAINTENANCE, details->maintenance?"1":"0");
914 }
915 count++;
916 }
917 }
918 crm_trace("%s %d nodes to adjust maintenance-mode "
919 "to transition", maintenance?"Added":"Counted", count);
920 return count;
921 }
922
923 /*!
924 * \internal
925 * \brief Add pseudo action with nodes needing maintenance state update
926 *
927 * \param[in,out] data_set Working set for cluster
928 */
929 void
add_maintenance_update(pe_working_set_t * data_set)930 add_maintenance_update(pe_working_set_t *data_set)
931 {
932 action_t *action = NULL;
933
934 if (add_maintenance_nodes(NULL, data_set)) {
935 crm_trace("adding maintenance state update pseudo action");
936 action = get_pseudo_op(CRM_OP_MAINTENANCE_NODES, data_set);
937 set_bit(action->flags, pe_action_print_always);
938 }
939 }
940
941 /*!
942 * \internal
943 * \brief Add XML with nodes that an action is expected to bring down
944 *
945 * If a specified action is expected to bring any nodes down, add an XML block
946 * with their UUIDs. When a node is lost, this allows the crmd to determine
947 * whether it was expected.
948 *
949 * \param[in,out] xml Parent XML tag to add to
950 * \param[in] action Action to check for downed nodes
951 * \param[in] data_set Working set for cluster
952 */
953 static void
add_downed_nodes(xmlNode * xml,const action_t * action,const pe_working_set_t * data_set)954 add_downed_nodes(xmlNode *xml, const action_t *action,
955 const pe_working_set_t *data_set)
956 {
957 CRM_CHECK(xml && action && action->node && data_set, return);
958
959 if (safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
960
961 /* Shutdown makes the action's node down */
962 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
963 add_node_to_xml_by_id(action->node->details->id, downed);
964
965 } else if (safe_str_eq(action->task, CRM_OP_FENCE)) {
966
967 /* Fencing makes the action's node and any hosted guest nodes down */
968 const char *fence = g_hash_table_lookup(action->meta, "stonith_action");
969
970 if (safe_str_eq(fence, "off") || safe_str_eq(fence, "reboot")) {
971 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
972 add_node_to_xml_by_id(action->node->details->id, downed);
973 pe_foreach_guest_node(data_set, action->node, add_node_to_xml, downed);
974 }
975
976 } else if (action->rsc && action->rsc->is_remote_node
977 && safe_str_eq(action->task, CRMD_ACTION_STOP)) {
978
979 /* Stopping a remote connection resource makes connected node down,
980 * unless it's part of a migration
981 */
982 GListPtr iter;
983 action_t *input;
984 gboolean migrating = FALSE;
985
986 for (iter = action->actions_before; iter != NULL; iter = iter->next) {
987 input = ((action_wrapper_t *) iter->data)->action;
988 if (input->rsc && safe_str_eq(action->rsc->id, input->rsc->id)
989 && safe_str_eq(input->task, CRMD_ACTION_MIGRATED)) {
990 migrating = TRUE;
991 break;
992 }
993 }
994 if (!migrating) {
995 xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
996 add_node_to_xml_by_id(action->rsc->id, downed);
997 }
998 }
999 }
1000
1001 static xmlNode *
action2xml(action_t * action,gboolean as_input,pe_working_set_t * data_set)1002 action2xml(action_t * action, gboolean as_input, pe_working_set_t *data_set)
1003 {
1004 gboolean needs_node_info = TRUE;
1005 gboolean needs_maintenance_info = FALSE;
1006 xmlNode *action_xml = NULL;
1007 xmlNode *args_xml = NULL;
1008 #if ENABLE_VERSIONED_ATTRS
1009 pe_rsc_action_details_t *rsc_details = NULL;
1010 #endif
1011
1012 if (action == NULL) {
1013 return NULL;
1014 }
1015
1016 if (safe_str_eq(action->task, CRM_OP_FENCE)) {
1017 /* All fences need node info; guest node fences are pseudo-events */
1018 action_xml = create_xml_node(NULL,
1019 is_set(action->flags, pe_action_pseudo)?
1020 XML_GRAPH_TAG_PSEUDO_EVENT :
1021 XML_GRAPH_TAG_CRM_EVENT);
1022
1023 } else if (safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
1024 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1025
1026 } else if (safe_str_eq(action->task, CRM_OP_CLEAR_FAILCOUNT)) {
1027 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1028
1029 } else if (safe_str_eq(action->task, CRM_OP_LRM_REFRESH)) {
1030 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1031
1032 /* } else if(safe_str_eq(action->task, RSC_PROBED)) { */
1033 /* action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); */
1034
1035 } else if (is_set(action->flags, pe_action_pseudo)) {
1036 if (safe_str_eq(action->task, CRM_OP_MAINTENANCE_NODES)) {
1037 needs_maintenance_info = TRUE;
1038 }
1039 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_PSEUDO_EVENT);
1040 needs_node_info = FALSE;
1041
1042 } else {
1043 action_xml = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
1044 #if ENABLE_VERSIONED_ATTRS
1045 rsc_details = pe_rsc_action_details(action);
1046 #endif
1047 }
1048
1049 crm_xml_add_int(action_xml, XML_ATTR_ID, action->id);
1050 crm_xml_add(action_xml, XML_LRM_ATTR_TASK, action->task);
1051 if (action->rsc != NULL && action->rsc->clone_name != NULL) {
1052 char *clone_key = NULL;
1053 const char *interval_s = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL);
1054 int interval = crm_parse_int(interval_s, "0");
1055
1056 if (safe_str_eq(action->task, RSC_NOTIFY)) {
1057 const char *n_type = g_hash_table_lookup(action->meta, "notify_type");
1058 const char *n_task = g_hash_table_lookup(action->meta, "notify_operation");
1059
1060 CRM_CHECK(n_type != NULL, crm_err("No notify type value found for %s", action->uuid));
1061 CRM_CHECK(n_task != NULL,
1062 crm_err("No notify operation value found for %s", action->uuid));
1063 clone_key = generate_notify_key(action->rsc->clone_name, n_type, n_task);
1064
1065 } else if(action->cancel_task) {
1066 clone_key = generate_op_key(action->rsc->clone_name, action->cancel_task, interval);
1067 } else {
1068 clone_key = generate_op_key(action->rsc->clone_name, action->task, interval);
1069 }
1070
1071 CRM_CHECK(clone_key != NULL, crm_err("Could not generate a key for %s", action->uuid));
1072 crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, clone_key);
1073 crm_xml_add(action_xml, "internal_" XML_LRM_ATTR_TASK_KEY, action->uuid);
1074 free(clone_key);
1075
1076 } else {
1077 crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, action->uuid);
1078 }
1079
1080 if (needs_node_info && action->node != NULL) {
1081 node_t *router_node = get_router_node(action);
1082
1083 crm_xml_add(action_xml, XML_LRM_ATTR_TARGET, action->node->details->uname);
1084 crm_xml_add(action_xml, XML_LRM_ATTR_TARGET_UUID, action->node->details->id);
1085 if (router_node) {
1086 crm_xml_add(action_xml, XML_LRM_ATTR_ROUTER_NODE, router_node->details->uname);
1087 }
1088
1089 g_hash_table_insert(action->meta, strdup(XML_LRM_ATTR_TARGET), strdup(action->node->details->uname));
1090 g_hash_table_insert(action->meta, strdup(XML_LRM_ATTR_TARGET_UUID), strdup(action->node->details->id));
1091 }
1092
1093 /* No details if this action is only being listed in the inputs section */
1094 if (as_input) {
1095 return action_xml;
1096 }
1097
1098 if (action->rsc && is_not_set(action->flags, pe_action_pseudo)) {
1099 int lpc = 0;
1100 xmlNode *rsc_xml = NULL;
1101 const char *attr_list[] = {
1102 XML_AGENT_ATTR_CLASS,
1103 XML_AGENT_ATTR_PROVIDER,
1104 XML_ATTR_TYPE
1105 };
1106
1107 // List affected resource
1108
1109 rsc_xml = create_xml_node(action_xml,
1110 crm_element_name(action->rsc->xml));
1111 if (is_set(action->rsc->flags, pe_rsc_orphan)
1112 && action->rsc->clone_name) {
1113 /* Do not use the 'instance free' name here as that
1114 * might interfere with the instance we plan to keep.
1115 * Ie. if there are more than two named /anonymous/
1116 * instances on a given node, we need to make sure the
1117 * command goes to the right one.
1118 *
1119 * Keep this block, even when everyone is using
1120 * 'instance free' anonymous clone names - it means
1121 * we'll do the right thing if anyone toggles the
1122 * unique flag to 'off'
1123 */
1124 crm_debug("Using orphan clone name %s instead of %s", action->rsc->id,
1125 action->rsc->clone_name);
1126 crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->clone_name);
1127 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
1128
1129 } else if (is_not_set(action->rsc->flags, pe_rsc_unique)) {
1130 const char *xml_id = ID(action->rsc->xml);
1131
1132 crm_debug("Using anonymous clone name %s for %s (aka. %s)", xml_id, action->rsc->id,
1133 action->rsc->clone_name);
1134
1135 /* ID is what we'd like client to use
1136 * ID_LONG is what they might know it as instead
1137 *
1138 * ID_LONG is only strictly needed /here/ during the
1139 * transition period until all nodes in the cluster
1140 * are running the new software /and/ have rebooted
1141 * once (meaning that they've only ever spoken to a DC
1142 * supporting this feature).
1143 *
1144 * If anyone toggles the unique flag to 'on', the
1145 * 'instance free' name will correspond to an orphan
1146 * and fall into the clause above instead
1147 */
1148 crm_xml_add(rsc_xml, XML_ATTR_ID, xml_id);
1149 if (action->rsc->clone_name && safe_str_neq(xml_id, action->rsc->clone_name)) {
1150 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->clone_name);
1151 } else {
1152 crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
1153 }
1154
1155 } else {
1156 CRM_ASSERT(action->rsc->clone_name == NULL);
1157 crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->id);
1158 }
1159
1160 for (lpc = 0; lpc < DIMOF(attr_list); lpc++) {
1161 crm_xml_add(rsc_xml, attr_list[lpc],
1162 g_hash_table_lookup(action->rsc->meta, attr_list[lpc]));
1163 }
1164 }
1165
1166 /* List any attributes in effect */
1167 args_xml = create_xml_node(NULL, XML_TAG_ATTRS);
1168 crm_xml_add(args_xml, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
1169
1170 g_hash_table_foreach(action->extra, hash2field, args_xml);
1171 if (action->rsc != NULL && action->node) {
1172 GHashTable *p = crm_str_table_new();
1173
1174 get_rsc_attributes(p, action->rsc, action->node, data_set);
1175 g_hash_table_foreach(p, hash2smartfield, args_xml);
1176 g_hash_table_destroy(p);
1177
1178 #if ENABLE_VERSIONED_ATTRS
1179 {
1180 xmlNode *versioned_parameters = create_xml_node(NULL, XML_TAG_RSC_VER_ATTRS);
1181
1182 pe_get_versioned_attributes(versioned_parameters, action->rsc,
1183 action->node, data_set);
1184 if (xml_has_children(versioned_parameters)) {
1185 add_node_copy(action_xml, versioned_parameters);
1186 }
1187 free_xml(versioned_parameters);
1188 }
1189 #endif
1190
1191 } else if(action->rsc && action->rsc->variant <= pe_native) {
1192 g_hash_table_foreach(action->rsc->parameters, hash2smartfield, args_xml);
1193
1194 #if ENABLE_VERSIONED_ATTRS
1195 if (xml_has_children(action->rsc->versioned_parameters)) {
1196 add_node_copy(action_xml, action->rsc->versioned_parameters);
1197 }
1198 #endif
1199 }
1200
1201 #if ENABLE_VERSIONED_ATTRS
1202 if (rsc_details) {
1203 if (xml_has_children(rsc_details->versioned_parameters)) {
1204 add_node_copy(action_xml, rsc_details->versioned_parameters);
1205 }
1206
1207 if (xml_has_children(rsc_details->versioned_meta)) {
1208 add_node_copy(action_xml, rsc_details->versioned_meta);
1209 }
1210 }
1211 #endif
1212
1213 g_hash_table_foreach(action->meta, hash2metafield, args_xml);
1214 if (action->rsc != NULL) {
1215 int isolated = 0;
1216 const char *value = g_hash_table_lookup(action->rsc->meta, "external-ip");
1217 resource_t *parent = action->rsc;
1218
1219 while (parent != NULL) {
1220 isolated |= parent->isolation_wrapper ? 1 : 0;
1221 parent->cmds->append_meta(parent, args_xml);
1222 parent = parent->parent;
1223 }
1224
1225 if (isolated && action->node) {
1226 char *nodeattr = crm_meta_name(XML_RSC_ATTR_ISOLATION_HOST);
1227 crm_xml_add(args_xml, nodeattr, action->node->details->uname);
1228 free(nodeattr);
1229 }
1230
1231 if(value) {
1232 hash2smartfield((gpointer)"pcmk_external_ip", (gpointer)value, (gpointer)args_xml);
1233 }
1234
1235 if(is_container_remote_node(action->node)) {
1236 pe_node_t *host = NULL;
1237 enum action_tasks task = text2task(action->task);
1238
1239 if(task == action_notify || task == action_notified) {
1240 const char *n_task = g_hash_table_lookup(action->meta, "notify_operation");
1241 task = text2task(n_task);
1242 }
1243
1244 // Differentiate between up and down actions
1245 switch (task) {
1246 case stop_rsc:
1247 case stopped_rsc:
1248 case action_demote:
1249 case action_demoted:
1250 host = pe__current_node(action->node->details->remote_rsc->container);
1251 break;
1252 case start_rsc:
1253 case started_rsc:
1254 case monitor_rsc:
1255 case action_promote:
1256 case action_promoted:
1257 host = action->node->details->remote_rsc->container->allocated_to;
1258 break;
1259 default:
1260 break;
1261 }
1262
1263 if(host) {
1264 hash2metafield((gpointer)XML_RSC_ATTR_TARGET,
1265 (gpointer)g_hash_table_lookup(action->rsc->meta, XML_RSC_ATTR_TARGET), (gpointer)args_xml);
1266 hash2metafield((gpointer)PCMK_ENV_PHYSICAL_HOST, (gpointer)host->details->uname, (gpointer)args_xml);
1267 }
1268 }
1269
1270 } else if (safe_str_eq(action->task, CRM_OP_FENCE) && action->node) {
1271 /* Pass the node's attributes as meta-attributes.
1272 *
1273 * @TODO: Determine whether it is still necessary to do this. It was
1274 * added in 33d99707, probably for the libfence-based implementation in
1275 * c9a90bd, which is no longer used.
1276 */
1277 g_hash_table_foreach(action->node->details->attrs, hash2metafield, args_xml);
1278 }
1279
1280 sorted_xml(args_xml, action_xml, FALSE);
1281 free_xml(args_xml);
1282
1283 /* List any nodes this action is expected to make down */
1284 if (needs_node_info && (action->node != NULL)) {
1285 add_downed_nodes(action_xml, action, data_set);
1286 }
1287
1288 if (needs_maintenance_info) {
1289 add_maintenance_nodes(action_xml, data_set);
1290 }
1291
1292 crm_log_xml_trace(action_xml, "dumped action");
1293 return action_xml;
1294 }
1295
1296 static gboolean
should_dump_action(action_t * action)1297 should_dump_action(action_t * action)
1298 {
1299 CRM_CHECK(action != NULL, return FALSE);
1300
1301 if (is_set(action->flags, pe_action_dumped)) {
1302 crm_trace("action %d (%s) was already dumped", action->id, action->uuid);
1303 return FALSE;
1304
1305 } else if (is_set(action->flags, pe_action_pseudo) && safe_str_eq(action->task, CRM_OP_PROBED)) {
1306 GListPtr lpc = NULL;
1307
1308 /* This is a horrible but convenient hack
1309 *
1310 * It mimimizes the number of actions with unsatisfied inputs
1311 * (i.e. not included in the graph)
1312 *
1313 * This in turn, means we can be more concise when printing
1314 * aborted/incomplete graphs.
1315 *
1316 * It also makes it obvious which node is preventing
1317 * probe_complete from running (presumably because it is only
1318 * partially up)
1319 *
1320 * For these reasons we tolerate such perversions
1321 */
1322
1323 for (lpc = action->actions_after; lpc != NULL; lpc = lpc->next) {
1324 action_wrapper_t *wrapper = (action_wrapper_t *) lpc->data;
1325
1326 if (is_not_set(wrapper->action->flags, pe_action_runnable)) {
1327 /* Only interested in runnable operations */
1328 } else if (safe_str_neq(wrapper->action->task, RSC_START)) {
1329 /* Only interested in start operations */
1330 } else if (is_set(wrapper->action->flags, pe_action_dumped)) {
1331 crm_trace("action %d (%s) dependency of %s",
1332 action->id, action->uuid, wrapper->action->uuid);
1333 return TRUE;
1334
1335 } else if (should_dump_action(wrapper->action)) {
1336 crm_trace("action %d (%s) dependency of %s",
1337 action->id, action->uuid, wrapper->action->uuid);
1338 return TRUE;
1339 }
1340 }
1341 }
1342
1343 if (is_set(action->flags, pe_action_runnable) == FALSE) {
1344 crm_trace("action %d (%s) was not runnable", action->id, action->uuid);
1345 return FALSE;
1346
1347 } else if (is_set(action->flags, pe_action_optional)
1348 && is_set(action->flags, pe_action_print_always) == FALSE) {
1349 crm_trace("action %d (%s) was optional", action->id, action->uuid);
1350 return FALSE;
1351
1352 } else if (action->rsc != NULL && is_not_set(action->rsc->flags, pe_rsc_managed)) {
1353 const char *interval = NULL;
1354
1355 interval = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL);
1356
1357 /* make sure probes and recurring monitors go through */
1358 if (safe_str_neq(action->task, RSC_STATUS) && interval == NULL) {
1359 crm_trace("action %d (%s) was for an unmanaged resource (%s)",
1360 action->id, action->uuid, action->rsc->id);
1361 return FALSE;
1362 }
1363 }
1364
1365 if (is_set(action->flags, pe_action_pseudo)
1366 || safe_str_eq(action->task, CRM_OP_FENCE)
1367 || safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
1368 /* skip the next checks */
1369 return TRUE;
1370 }
1371
1372 if (action->node == NULL) {
1373 pe_err("action %d (%s) was not allocated", action->id, action->uuid);
1374 log_action(LOG_DEBUG, "Unallocated action", action, FALSE);
1375 return FALSE;
1376
1377 } else if(is_container_remote_node(action->node) && action->node->details->remote_requires_reset == FALSE) {
1378 crm_trace("Assuming action %s for %s will be runnable", action->uuid, action->node->details->uname);
1379
1380 } else if (action->node->details->online == FALSE) {
1381 pe_err("action %d was (%s) scheduled for offline node", action->id, action->uuid);
1382 log_action(LOG_DEBUG, "Action for offline node", action, FALSE);
1383 return FALSE;
1384 #if 0
1385 /* but this would also affect resources that can be safely
1386 * migrated before a fencing op
1387 */
1388 } else if (action->node->details->unclean == FALSE) {
1389 pe_err("action %d was (%s) scheduled for unclean node", action->id, action->uuid);
1390 log_action(LOG_DEBUG, "Action for unclean node", action, FALSE);
1391 return FALSE;
1392 #endif
1393 }
1394 return TRUE;
1395 }
1396
1397 /* lowest to highest */
1398 static gint
sort_action_id(gconstpointer a,gconstpointer b)1399 sort_action_id(gconstpointer a, gconstpointer b)
1400 {
1401 const action_wrapper_t *action_wrapper2 = (const action_wrapper_t *)a;
1402 const action_wrapper_t *action_wrapper1 = (const action_wrapper_t *)b;
1403
1404 if (a == NULL) {
1405 return 1;
1406 }
1407 if (b == NULL) {
1408 return -1;
1409 }
1410
1411 if (action_wrapper1->action->id > action_wrapper2->action->id) {
1412 return -1;
1413 }
1414
1415 if (action_wrapper1->action->id < action_wrapper2->action->id) {
1416 return 1;
1417 }
1418 return 0;
1419 }
1420
1421 static gboolean
check_dump_input(int last_action,action_t * action,action_wrapper_t * wrapper)1422 check_dump_input(int last_action, action_t * action, action_wrapper_t * wrapper)
1423 {
1424 int type = wrapper->type;
1425
1426 if (wrapper->state == pe_link_dumped) {
1427 return TRUE;
1428
1429 } else if (wrapper->state == pe_link_dup) {
1430 return FALSE;
1431 }
1432
1433 type &= ~pe_order_implies_first_printed;
1434 type &= ~pe_order_implies_then_printed;
1435 type &= ~pe_order_optional;
1436
1437 if (is_not_set(type, pe_order_preserve)
1438 && action->rsc && action->rsc->fillers
1439 && wrapper->action->rsc && wrapper->action->node
1440 && wrapper->action->node->details->remote_rsc
1441 && (wrapper->action->node->details->remote_rsc->container == action->rsc)) {
1442 /* This prevents user-defined ordering constraints between resources
1443 * running in a guest node and the resource that defines that node.
1444 */
1445 crm_warn("Invalid ordering constraint between %s and %s",
1446 wrapper->action->rsc->id, action->rsc->id);
1447 wrapper->type = pe_order_none;
1448 return FALSE;
1449 }
1450
1451 if (last_action == wrapper->action->id) {
1452 crm_trace("Input (%d) %s duplicated for %s",
1453 wrapper->action->id, wrapper->action->uuid, action->uuid);
1454 wrapper->state = pe_link_dup;
1455 return FALSE;
1456
1457 } else if (wrapper->type == pe_order_none) {
1458 crm_trace("Input (%d) %s suppressed for %s",
1459 wrapper->action->id, wrapper->action->uuid, action->uuid);
1460 return FALSE;
1461
1462 } else if (is_set(wrapper->action->flags, pe_action_runnable) == FALSE
1463 && type == pe_order_none && safe_str_neq(wrapper->action->uuid, CRM_OP_PROBED)) {
1464 crm_trace("Input (%d) %s optional (ordering) for %s",
1465 wrapper->action->id, wrapper->action->uuid, action->uuid);
1466 return FALSE;
1467
1468 } else if (is_set(wrapper->action->flags, pe_action_runnable) == FALSE
1469 && is_set(type, pe_order_one_or_more)) {
1470 crm_trace("Input (%d) %s optional (one-or-more) for %s",
1471 wrapper->action->id, wrapper->action->uuid, action->uuid);
1472 return FALSE;
1473
1474 } else if (is_set(action->flags, pe_action_pseudo)
1475 && (wrapper->type & pe_order_stonith_stop)) {
1476 crm_trace("Input (%d) %s suppressed for %s",
1477 wrapper->action->id, wrapper->action->uuid, action->uuid);
1478 return FALSE;
1479
1480 } else if ((wrapper->type & pe_order_implies_first_migratable) && (is_set(wrapper->action->flags, pe_action_runnable) == FALSE)) {
1481 return FALSE;
1482
1483 } else if ((wrapper->type & pe_order_apply_first_non_migratable)
1484 && (is_set(wrapper->action->flags, pe_action_migrate_runnable))) {
1485 return FALSE;
1486
1487 } else if ((wrapper->type == pe_order_optional)
1488 && crm_ends_with(wrapper->action->uuid, "_stop_0")
1489 && is_set(wrapper->action->flags, pe_action_migrate_runnable)) {
1490
1491 /* for optional only ordering, ordering is not preserved for
1492 * a stop action that is actually involved with a migration. */
1493 return FALSE;
1494
1495 } else if (wrapper->type == pe_order_load) {
1496 crm_trace("check load filter %s.%s -> %s.%s",
1497 wrapper->action->uuid,
1498 wrapper->action->node ? wrapper->action->node->details->uname : "", action->uuid,
1499 action->node ? action->node->details->uname : "");
1500
1501 if (action->rsc && safe_str_eq(action->task, RSC_MIGRATE)) {
1502 /* Remove the orders like the following if not relevant:
1503 * "load_stopped_node2" -> "rscA_migrate_to node1"
1504 * which were created also from: pengine/native.c: MigrateRsc()
1505 * order_actions(other, then, other_w->type);
1506 */
1507
1508 /* For migrate_to ops, we care about where it has been
1509 * allocated to, not where the action will be executed
1510 */
1511 if (wrapper->action->node == NULL || action->rsc->allocated_to == NULL
1512 || wrapper->action->node->details != action->rsc->allocated_to->details) {
1513 /* Check if the actions are for the same node, ignore otherwise */
1514 crm_trace("load filter - migrate");
1515 wrapper->type = pe_order_none;
1516 return FALSE;
1517 }
1518
1519 } else if (wrapper->action->node == NULL || action->node == NULL
1520 || wrapper->action->node->details != action->node->details) {
1521 /* Check if the actions are for the same node, ignore otherwise */
1522 crm_trace("load filter - node");
1523 wrapper->type = pe_order_none;
1524 return FALSE;
1525
1526 } else if (is_set(wrapper->action->flags, pe_action_optional)) {
1527 /* Check if the pre-req is optional, ignore if so */
1528 crm_trace("load filter - optional");
1529 wrapper->type = pe_order_none;
1530 return FALSE;
1531 }
1532
1533 } else if (wrapper->type == pe_order_anti_colocation) {
1534 crm_trace("check anti-colocation filter %s.%s -> %s.%s",
1535 wrapper->action->uuid,
1536 wrapper->action->node ? wrapper->action->node->details->uname : "",
1537 action->uuid,
1538 action->node ? action->node->details->uname : "");
1539
1540 if (wrapper->action->node && action->node
1541 && wrapper->action->node->details != action->node->details) {
1542 /* Check if the actions are for the same node, ignore otherwise */
1543 crm_trace("anti-colocation filter - node");
1544 wrapper->type = pe_order_none;
1545 return FALSE;
1546
1547 } else if (is_set(wrapper->action->flags, pe_action_optional)) {
1548 /* Check if the pre-req is optional, ignore if so */
1549 crm_trace("anti-colocation filter - optional");
1550 wrapper->type = pe_order_none;
1551 return FALSE;
1552 }
1553
1554 } else if (wrapper->action->rsc
1555 && wrapper->action->rsc != action->rsc
1556 && is_set(wrapper->action->rsc->flags, pe_rsc_failed)
1557 && is_not_set(wrapper->action->rsc->flags, pe_rsc_managed)
1558 && crm_ends_with(wrapper->action->uuid, "_stop_0")
1559 && action->rsc && pe_rsc_is_clone(action->rsc)) {
1560 crm_warn("Ignoring requirement that %s complete before %s:"
1561 " unmanaged failed resources cannot prevent clone shutdown",
1562 wrapper->action->uuid, action->uuid);
1563 return FALSE;
1564
1565 } else if (is_set(wrapper->action->flags, pe_action_dumped)
1566 || should_dump_action(wrapper->action)) {
1567 crm_trace("Input (%d) %s should be dumped for %s", wrapper->action->id,
1568 wrapper->action->uuid, action->uuid);
1569 goto dump;
1570
1571 #if 0
1572 } else if (is_set(wrapper->action->flags, pe_action_runnable)
1573 && is_set(wrapper->action->flags, pe_action_pseudo)
1574 && wrapper->action->rsc->variant != pe_native) {
1575 crm_crit("Input (%d) %s should be dumped for %s",
1576 wrapper->action->id, wrapper->action->uuid, action->uuid);
1577 goto dump;
1578 #endif
1579 } else if (is_set(wrapper->action->flags, pe_action_optional) == TRUE
1580 && is_set(wrapper->action->flags, pe_action_print_always) == FALSE) {
1581 crm_trace("Input (%d) %s optional for %s", wrapper->action->id,
1582 wrapper->action->uuid, action->uuid);
1583 crm_trace("Input (%d) %s n=%p p=%d r=%d o=%d a=%d f=0x%.6x",
1584 wrapper->action->id, wrapper->action->uuid, wrapper->action->node,
1585 is_set(wrapper->action->flags, pe_action_pseudo),
1586 is_set(wrapper->action->flags, pe_action_runnable),
1587 is_set(wrapper->action->flags, pe_action_optional),
1588 is_set(wrapper->action->flags, pe_action_print_always), wrapper->type);
1589 return FALSE;
1590
1591 }
1592
1593 dump:
1594 return TRUE;
1595 }
1596
1597 static gboolean
graph_has_loop(action_t * init_action,action_t * action,action_wrapper_t * wrapper)1598 graph_has_loop(action_t * init_action, action_t * action, action_wrapper_t * wrapper)
1599 {
1600 GListPtr lpc = NULL;
1601 gboolean has_loop = FALSE;
1602
1603 if (is_set(wrapper->action->flags, pe_action_tracking)) {
1604 crm_trace("Breaking tracking loop: %s.%s -> %s.%s (0x%.6x)",
1605 wrapper->action->uuid,
1606 wrapper->action->node ? wrapper->action->node->details->uname : "",
1607 action->uuid,
1608 action->node ? action->node->details->uname : "",
1609 wrapper->type);
1610 return FALSE;
1611 }
1612
1613 if (check_dump_input(-1, action, wrapper) == FALSE) {
1614 return FALSE;
1615 }
1616
1617 /* If there's any order like:
1618 * "rscB_stop node2"-> "load_stopped_node2" -> "rscA_migrate_to node1"
1619 * rscA is being migrated from node1 to node2,
1620 * while rscB is being migrated from node2 to node1.
1621 * There will be potential graph loop.
1622 * Break the order "load_stopped_node2" -> "rscA_migrate_to node1".
1623 */
1624
1625 crm_trace("Checking graph loop: %s.%s -> %s.%s (0x%.6x)",
1626 wrapper->action->uuid,
1627 wrapper->action->node ? wrapper->action->node->details->uname : "",
1628 action->uuid,
1629 action->node ? action->node->details->uname : "",
1630 wrapper->type);
1631
1632 if (wrapper->action == init_action) {
1633 crm_debug("Found graph loop: %s.%s ->...-> %s.%s",
1634 action->uuid,
1635 action->node ? action->node->details->uname : "",
1636 init_action->uuid,
1637 init_action->node ? init_action->node->details->uname : "");
1638
1639 return TRUE;
1640 }
1641
1642 set_bit(wrapper->action->flags, pe_action_tracking);
1643
1644 for (lpc = wrapper->action->actions_before; lpc != NULL; lpc = lpc->next) {
1645 action_wrapper_t *wrapper_before = (action_wrapper_t *) lpc->data;
1646
1647 if (graph_has_loop(init_action, wrapper->action, wrapper_before)) {
1648 has_loop = TRUE;
1649 goto done;
1650 }
1651 }
1652
1653 done:
1654 pe_clear_action_bit(wrapper->action, pe_action_tracking);
1655
1656 return has_loop;
1657 }
1658
1659 static gboolean
should_dump_input(int last_action,action_t * action,action_wrapper_t * wrapper)1660 should_dump_input(int last_action, action_t * action, action_wrapper_t * wrapper)
1661 {
1662 wrapper->state = pe_link_not_dumped;
1663
1664 if (check_dump_input(last_action, action, wrapper) == FALSE) {
1665 return FALSE;
1666 }
1667
1668 if (wrapper->type == pe_order_load
1669 && action->rsc
1670 && safe_str_eq(action->task, RSC_MIGRATE)) {
1671 crm_trace("Checking graph loop - load migrate: %s.%s -> %s.%s",
1672 wrapper->action->uuid,
1673 wrapper->action->node ? wrapper->action->node->details->uname : "",
1674 action->uuid,
1675 action->node ? action->node->details->uname : "");
1676
1677 if (graph_has_loop(action, action, wrapper)) {
1678 /* Remove the orders like the following if they are introducing any graph loops:
1679 * "load_stopped_node2" -> "rscA_migrate_to node1"
1680 * which were created also from: pengine/native.c: MigrateRsc()
1681 * order_actions(other, then, other_w->type);
1682 */
1683 crm_debug("Breaking graph loop - load migrate: %s.%s -> %s.%s",
1684 wrapper->action->uuid,
1685 wrapper->action->node ? wrapper->action->node->details->uname : "",
1686 action->uuid,
1687 action->node ? action->node->details->uname : "");
1688
1689 wrapper->type = pe_order_none;
1690 return FALSE;
1691 }
1692 }
1693
1694 crm_trace("Input (%d) %s n=%p p=%d r=%d o=%d a=%d f=0x%.6x dumped for %s",
1695 wrapper->action->id,
1696 wrapper->action->uuid,
1697 wrapper->action->node,
1698 is_set(wrapper->action->flags, pe_action_pseudo),
1699 is_set(wrapper->action->flags, pe_action_runnable),
1700 is_set(wrapper->action->flags, pe_action_optional),
1701 is_set(wrapper->action->flags, pe_action_print_always), wrapper->type, action->uuid);
1702 return TRUE;
1703 }
1704
1705 void
graph_element_from_action(action_t * action,pe_working_set_t * data_set)1706 graph_element_from_action(action_t * action, pe_working_set_t * data_set)
1707 {
1708 GListPtr lpc = NULL;
1709 int last_action = -1;
1710 int synapse_priority = 0;
1711 xmlNode *syn = NULL;
1712 xmlNode *set = NULL;
1713 xmlNode *in = NULL;
1714 xmlNode *input = NULL;
1715 xmlNode *xml_action = NULL;
1716
1717 if (should_dump_action(action) == FALSE) {
1718 return;
1719 }
1720
1721 set_bit(action->flags, pe_action_dumped);
1722
1723 syn = create_xml_node(data_set->graph, "synapse");
1724 set = create_xml_node(syn, "action_set");
1725 in = create_xml_node(syn, "inputs");
1726
1727 crm_xml_add_int(syn, XML_ATTR_ID, data_set->num_synapse);
1728 data_set->num_synapse++;
1729
1730 if (action->rsc != NULL) {
1731 synapse_priority = action->rsc->priority;
1732 }
1733 if (action->priority > synapse_priority) {
1734 synapse_priority = action->priority;
1735 }
1736 if (synapse_priority > 0) {
1737 crm_xml_add_int(syn, XML_CIB_ATTR_PRIORITY, synapse_priority);
1738 }
1739
1740 xml_action = action2xml(action, FALSE, data_set);
1741 add_node_nocopy(set, crm_element_name(xml_action), xml_action);
1742
1743 action->actions_before = g_list_sort(action->actions_before, sort_action_id);
1744
1745 for (lpc = action->actions_before; lpc != NULL; lpc = lpc->next) {
1746 action_wrapper_t *wrapper = (action_wrapper_t *) lpc->data;
1747
1748 if (should_dump_input(last_action, action, wrapper) == FALSE) {
1749 continue;
1750 }
1751
1752 wrapper->state = pe_link_dumped;
1753 CRM_CHECK(last_action < wrapper->action->id,;
1754 );
1755 last_action = wrapper->action->id;
1756 input = create_xml_node(in, "trigger");
1757
1758 xml_action = action2xml(wrapper->action, TRUE, data_set);
1759 add_node_nocopy(input, crm_element_name(xml_action), xml_action);
1760 }
1761 }
1762