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