pacemaker  2.0.2-debe490
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcmk_sched_graph.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU General Public License version 2
5  * or later (GPLv2+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #include <sys/param.h>
11 #include <crm/crm.h>
12 #include <crm/cib.h>
13 #include <crm/msg_xml.h>
14 #include <crm/common/xml.h>
15 
16 #include <glib.h>
17 
18 #include <pacemaker-internal.h>
19 
21 gboolean rsc_update_action(action_t * first, action_t * then, enum pe_ordering type);
22 
23 static enum pe_action_flags
24 get_action_flags(action_t * action, node_t * node)
25 {
26  enum pe_action_flags flags = action->flags;
27 
28  if (action->rsc) {
29  flags = action->rsc->cmds->action_flags(action, NULL);
30 
31  if (pe_rsc_is_clone(action->rsc) && node) {
32 
33  /* We only care about activity on $node */
34  enum pe_action_flags clone_flags = action->rsc->cmds->action_flags(action, node);
35 
36  /* Go to great lengths to ensure the correct value for pe_action_runnable...
37  *
38  * If we are a clone, then for _ordering_ constraints, it's only relevant
39  * if we are runnable _anywhere_.
40  *
41  * This only applies to _runnable_ though, and only for ordering constraints.
42  * If this function is ever used during colocation, then we'll need additional logic
43  *
44  * Not very satisfying, but it's logical and appears to work well.
45  */
46  if (is_not_set(clone_flags, pe_action_runnable)
47  && is_set(flags, pe_action_runnable)) {
48  pe_rsc_trace(action->rsc, "Fixing up runnable flag for %s", action->uuid);
49  set_bit(clone_flags, pe_action_runnable);
50  }
51  flags = clone_flags;
52  }
53  }
54  return flags;
55 }
56 
57 static char *
58 convert_non_atomic_uuid(char *old_uuid, resource_t * rsc, gboolean allow_notify,
59  gboolean free_original)
60 {
61  guint interval_ms = 0;
62  char *uuid = NULL;
63  char *rid = NULL;
64  char *raw_task = NULL;
65  int task = no_action;
66 
67  CRM_ASSERT(rsc);
68  pe_rsc_trace(rsc, "Processing %s", old_uuid);
69  if (old_uuid == NULL) {
70  return NULL;
71 
72  } else if (strstr(old_uuid, "notify") != NULL) {
73  goto done; /* no conversion */
74 
75  } else if (rsc->variant < pe_group) {
76  goto done; /* no conversion */
77  }
78 
79  CRM_ASSERT(parse_op_key(old_uuid, &rid, &raw_task, &interval_ms));
80  if (interval_ms > 0) {
81  goto done; /* no conversion */
82  }
83 
84  task = text2task(raw_task);
85  switch (task) {
86  case stop_rsc:
87  case start_rsc:
88  case action_notify:
89  case action_promote:
90  case action_demote:
91  break;
92  case stopped_rsc:
93  case started_rsc:
94  case action_notified:
95  case action_promoted:
96  case action_demoted:
97  task--;
98  break;
99  case monitor_rsc:
100  case shutdown_crm:
101  case stonith_node:
102  task = no_action;
103  break;
104  default:
105  crm_err("Unknown action: %s", raw_task);
106  task = no_action;
107  break;
108  }
109 
110  if (task != no_action) {
111  if (is_set(rsc->flags, pe_rsc_notify) && allow_notify) {
112  uuid = generate_notify_key(rid, "confirmed-post", task2text(task + 1));
113 
114  } else {
115  uuid = generate_op_key(rid, task2text(task + 1), 0);
116  }
117  pe_rsc_trace(rsc, "Converted %s -> %s", old_uuid, uuid);
118  }
119 
120  done:
121  if (uuid == NULL) {
122  uuid = strdup(old_uuid);
123  }
124 
125  if (free_original) {
126  free(old_uuid);
127  }
128 
129  free(raw_task);
130  free(rid);
131  return uuid;
132 }
133 
134 static action_t *
135 rsc_expand_action(action_t * action)
136 {
137  gboolean notify = FALSE;
138  action_t *result = action;
139  resource_t *rsc = action->rsc;
140 
141  if (rsc == NULL) {
142  return action;
143  }
144 
145  if ((rsc->parent == NULL)
146  || (pe_rsc_is_clone(rsc) && (rsc->parent->variant == pe_container))) {
147  /* Only outermost resources have notification actions.
148  * The exception is those in bundles.
149  */
150  notify = is_set(rsc->flags, pe_rsc_notify);
151  }
152 
153  if (rsc->variant >= pe_group) {
154  /* Expand 'start' -> 'started' */
155  char *uuid = NULL;
156 
157  uuid = convert_non_atomic_uuid(action->uuid, rsc, notify, FALSE);
158  if (uuid) {
159  pe_rsc_trace(rsc, "Converting %s to %s %d", action->uuid, uuid,
160  is_set(rsc->flags, pe_rsc_notify));
161  result = find_first_action(rsc->actions, uuid, NULL, NULL);
162  if (result == NULL) {
163  crm_err("Couldn't expand %s to %s in %s", action->uuid, uuid, rsc->id);
164  result = action;
165  }
166  free(uuid);
167  }
168  }
169  return result;
170 }
171 
172 static enum pe_graph_flags
173 graph_update_action(action_t * first, action_t * then, node_t * node,
174  enum pe_action_flags first_flags, enum pe_action_flags then_flags,
175  action_wrapper_t *order, pe_working_set_t *data_set)
176 {
177  enum pe_graph_flags changed = pe_graph_none;
178  enum pe_ordering type = order->type;
179  gboolean processed = FALSE;
180 
181  /* TODO: Do as many of these in parallel as possible */
182 
183  if(is_set(type, pe_order_implies_then_on_node)) {
184  /* Normally we want the _whole_ 'then' clone to
185  * restart if 'first' is restarted, so then->node is
186  * needed.
187  *
188  * However for unfencing, we want to limit this to
189  * instances on the same node as 'first' (the
190  * unfencing operation), so first->node is supplied.
191  *
192  * Swap the node, from then on we can can treat it
193  * like any other 'pe_order_implies_then'
194  */
195 
198  node = first->node;
199  }
200 
201  clear_bit(first_flags, pe_action_pseudo);
202 
203  if (type & pe_order_implies_then) {
204  processed = TRUE;
205  if (then->rsc) {
206  changed |= then->rsc->cmds->update_actions(first, then, node,
207  first_flags & pe_action_optional, pe_action_optional,
208  pe_order_implies_then, data_set);
209 
210  } else if (is_set(first_flags, pe_action_optional) == FALSE) {
211  if (update_action_flags(then, pe_action_optional | pe_action_clear, __FUNCTION__, __LINE__)) {
212  changed |= pe_graph_updated_then;
213  }
214  }
215  if (changed) {
216  pe_rsc_trace(then->rsc, "implies right: %s then %s: changed", first->uuid, then->uuid);
217  } else {
218  crm_trace("implies right: %s then %s %p", first->uuid, then->uuid, then->rsc);
219  }
220  }
221 
222  if ((type & pe_order_restart) && then->rsc) {
224 
225  processed = TRUE;
226  changed |= then->rsc->cmds->update_actions(first, then, node,
227  first_flags, restart,
228  pe_order_restart, data_set);
229  if (changed) {
230  pe_rsc_trace(then->rsc, "restart: %s then %s: changed", first->uuid, then->uuid);
231  } else {
232  crm_trace("restart: %s then %s", first->uuid, then->uuid);
233  }
234  }
235 
236  if (type & pe_order_implies_first) {
237  processed = TRUE;
238  if (first->rsc) {
239  changed |= first->rsc->cmds->update_actions(first, then, node,
240  first_flags, pe_action_optional, pe_order_implies_first,
241  data_set);
242 
243  } else if (is_set(first_flags, pe_action_optional) == FALSE) {
244  pe_rsc_trace(first->rsc, "first unrunnable: %s (%d) then %s (%d)",
245  first->uuid, is_set(first_flags, pe_action_optional),
246  then->uuid, is_set(then_flags, pe_action_optional));
247  if (update_action_flags(first, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__)) {
248  changed |= pe_graph_updated_first;
249  }
250  }
251 
252  if (changed) {
253  pe_rsc_trace(then->rsc, "implies left: %s then %s: changed", first->uuid, then->uuid);
254  } else {
255  crm_trace("implies left: %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  }
259  }
260 
261  if (type & pe_order_implies_first_master) {
262  processed = TRUE;
263  if (then->rsc) {
264  changed |= then->rsc->cmds->update_actions(first, then, node,
265  first_flags & pe_action_optional, pe_action_optional,
266  pe_order_implies_first_master, data_set);
267  }
268 
269  if (changed) {
270  pe_rsc_trace(then->rsc,
271  "implies left when right rsc is Master role: %s then %s: changed",
272  first->uuid, then->uuid);
273  } else {
274  crm_trace("implies left when right rsc is Master role: %s then %s", first->uuid,
275  then->uuid);
276  }
277  }
278 
279  if (type & pe_order_one_or_more) {
280  processed = TRUE;
281  if (then->rsc) {
282  changed |= then->rsc->cmds->update_actions(first, then, node,
283  first_flags, pe_action_runnable, pe_order_one_or_more,
284  data_set);
285 
286  } else if (is_set(first_flags, pe_action_runnable)) {
287  /* alright. a "first" action is considered runnable, incremente
288  * the 'runnable_before' counter */
289  then->runnable_before++;
290 
291  /* if the runnable before count for then exceeds the required number
292  * of "before" runnable actions... mark then as runnable */
293  if (then->runnable_before >= then->required_runnable_before) {
294  if (update_action_flags(then, pe_action_runnable, __FUNCTION__, __LINE__)) {
295  changed |= pe_graph_updated_then;
296  }
297  }
298  }
299  if (changed) {
300  pe_rsc_trace(then->rsc, "runnable_one_or_more: %s then %s: changed", first->uuid,
301  then->uuid);
302  } else {
303  crm_trace("runnable_one_or_more: %s then %s", first->uuid, then->uuid);
304  }
305  }
306 
307  if (then->rsc && is_set(type, pe_order_probe)) {
308  processed = TRUE;
309 
310  if (is_not_set(first_flags, pe_action_runnable) && first->rsc->running_on != NULL) {
311  pe_rsc_trace(then->rsc, "Ignoring %s then %s - %s is about to be stopped",
312  first->uuid, then->uuid, first->rsc->id);
313  type = pe_order_none;
314  order->type = pe_order_none;
315 
316  } else {
317  pe_rsc_trace(then->rsc, "Enforcing %s then %s", first->uuid, then->uuid);
318  changed |= then->rsc->cmds->update_actions(first, then, node,
320  data_set);
321  }
322 
323  if (changed) {
324  pe_rsc_trace(then->rsc, "runnable: %s then %s: changed", first->uuid, then->uuid);
325  } else {
326  crm_trace("runnable: %s then %s", first->uuid, then->uuid);
327  }
328  }
329 
330  if (type & pe_order_runnable_left) {
331  processed = TRUE;
332  if (then->rsc) {
333  changed |= then->rsc->cmds->update_actions(first, then, node,
334  first_flags, pe_action_runnable, pe_order_runnable_left,
335  data_set);
336 
337  } else if (is_set(first_flags, pe_action_runnable) == FALSE) {
338  pe_rsc_trace(then->rsc, "then unrunnable: %s then %s", first->uuid, then->uuid);
339  if (update_action_flags(then, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__)) {
340  changed |= pe_graph_updated_then;
341  }
342  }
343  if (changed) {
344  pe_rsc_trace(then->rsc, "runnable: %s then %s: changed", first->uuid, then->uuid);
345  } else {
346  crm_trace("runnable: %s then %s", first->uuid, then->uuid);
347  }
348  }
349 
351  processed = TRUE;
352  if (then->rsc) {
353  changed |= then->rsc->cmds->update_actions(first, then, node,
354  first_flags, pe_action_optional,
355  pe_order_implies_first_migratable, data_set);
356  }
357  if (changed) {
358  pe_rsc_trace(then->rsc, "optional: %s then %s: changed", first->uuid, then->uuid);
359  } else {
360  crm_trace("optional: %s then %s", first->uuid, then->uuid);
361  }
362  }
363 
364  if (type & pe_order_pseudo_left) {
365  processed = TRUE;
366  if (then->rsc) {
367  changed |= then->rsc->cmds->update_actions(first, then, node,
368  first_flags, pe_action_optional, pe_order_pseudo_left,
369  data_set);
370  }
371  if (changed) {
372  pe_rsc_trace(then->rsc, "optional: %s then %s: changed", first->uuid, then->uuid);
373  } else {
374  crm_trace("optional: %s then %s", first->uuid, then->uuid);
375  }
376  }
377 
378  if (type & pe_order_optional) {
379  processed = TRUE;
380  if (then->rsc) {
381  changed |= then->rsc->cmds->update_actions(first, then, node,
382  first_flags, pe_action_runnable, pe_order_optional, data_set);
383  }
384  if (changed) {
385  pe_rsc_trace(then->rsc, "optional: %s then %s: changed", first->uuid, then->uuid);
386  } else {
387  crm_trace("optional: %s then %s", first->uuid, then->uuid);
388  }
389  }
390 
391  if (type & pe_order_asymmetrical) {
392  processed = TRUE;
393  if (then->rsc) {
394  changed |= then->rsc->cmds->update_actions(first, then, node,
395  first_flags, pe_action_runnable, pe_order_asymmetrical,
396  data_set);
397  }
398 
399  if (changed) {
400  pe_rsc_trace(then->rsc, "asymmetrical: %s then %s: changed", first->uuid, then->uuid);
401  } else {
402  crm_trace("asymmetrical: %s then %s", first->uuid, then->uuid);
403  }
404 
405  }
406 
407  if ((first->flags & pe_action_runnable) && (type & pe_order_implies_then_printed)
408  && (first_flags & pe_action_optional) == 0) {
409  processed = TRUE;
410  crm_trace("%s implies %s printed", first->uuid, then->uuid);
411  update_action_flags(then, pe_action_print_always, __FUNCTION__, __LINE__); /* don't care about changed */
412  }
413 
414  if (is_set(type, pe_order_implies_first_printed) && is_set(then_flags, pe_action_optional) == FALSE) {
415  processed = TRUE;
416  crm_trace("%s implies %s printed", then->uuid, first->uuid);
417  update_action_flags(first, pe_action_print_always, __FUNCTION__, __LINE__); /* don't care about changed */
418  }
419 
420  if ((type & pe_order_implies_then
421  || type & pe_order_implies_first
422  || type & pe_order_restart)
423  && first->rsc
424  && safe_str_eq(first->task, RSC_STOP)
425  && is_not_set(first->rsc->flags, pe_rsc_managed)
426  && is_set(first->rsc->flags, pe_rsc_block)
427  && is_not_set(first->flags, pe_action_runnable)) {
428 
429  if (update_action_flags(then, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__)) {
430  changed |= pe_graph_updated_then;
431  }
432 
433  if (changed) {
434  pe_rsc_trace(then->rsc, "unmanaged left: %s then %s: changed", first->uuid, then->uuid);
435  } else {
436  crm_trace("unmanaged left: %s then %s", first->uuid, then->uuid);
437  }
438  }
439 
440  if (processed == FALSE) {
441  crm_trace("Constraint 0x%.6x not applicable", type);
442  }
443 
444  return changed;
445 }
446 
447 static void
448 mark_start_blocked(pe_resource_t *rsc, pe_resource_t *reason,
449  pe_working_set_t *data_set)
450 {
451  GListPtr gIter = rsc->actions;
452  char *reason_text = crm_strdup_printf("colocation with %s", reason->id);
453 
454  for (; gIter != NULL; gIter = gIter->next) {
455  action_t *action = (action_t *) gIter->data;
456 
457  if (safe_str_neq(action->task, RSC_START)) {
458  continue;
459  }
460  if (is_set(action->flags, pe_action_runnable)) {
461  pe_action_set_flag_reason(__FUNCTION__, __LINE__, action, NULL, reason_text, pe_action_runnable, FALSE);
462  update_colo_start_chain(action, data_set);
463  update_action(action, data_set);
464  }
465  }
466  free(reason_text);
467 }
468 
469 void
471 {
472  GListPtr gIter = NULL;
473  resource_t *rsc = NULL;
474 
475  if (is_not_set(action->flags, pe_action_runnable) && safe_str_eq(action->task, RSC_START)) {
476  rsc = uber_parent(action->rsc);
477  if (rsc->parent) {
478  /* For bundles, uber_parent() returns the clone/master, not the
479  * bundle, so the existence of rsc->parent implies this is a bundle.
480  * In this case, we need the bundle resource, so that we can check
481  * if all containers are stopped/stopping.
482  */
483  rsc = rsc->parent;
484  }
485  }
486 
487  if (rsc == NULL || rsc->rsc_cons_lhs == NULL) {
488  return;
489  }
490 
491  /* if rsc has children, all the children need to have start set to
492  * unrunnable before we follow the colo chain for the parent. */
493  for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
494  resource_t *child = (resource_t *)gIter->data;
495  action_t *start = find_first_action(child->actions, NULL, RSC_START, NULL);
496  if (start == NULL || is_set(start->flags, pe_action_runnable)) {
497  return;
498  }
499  }
500 
501  for (gIter = rsc->rsc_cons_lhs; gIter != NULL; gIter = gIter->next) {
502  rsc_colocation_t *colocate_with = (rsc_colocation_t *)gIter->data;
503  if (colocate_with->score == INFINITY) {
504  mark_start_blocked(colocate_with->rsc_lh, action->rsc, data_set);
505  }
506  }
507 }
508 
509 gboolean
511 {
512  GListPtr lpc = NULL;
513  enum pe_graph_flags changed = pe_graph_none;
514  int last_flags = then->flags;
515 
516  crm_trace("Processing %s (%s %s %s)",
517  then->uuid,
518  is_set(then->flags, pe_action_optional) ? "optional" : "required",
519  is_set(then->flags, pe_action_runnable) ? "runnable" : "unrunnable",
520  is_set(then->flags,
521  pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->uname : "");
522 
523  if (is_set(then->flags, pe_action_requires_any)) {
524  /* initialize current known runnable before actions to 0
525  * from here as graph_update_action is called for each of
526  * then's before actions, this number will increment as
527  * runnable 'first' actions are encountered */
528  then->runnable_before = 0;
529 
530  /* for backwards compatibility with previous options that use
531  * the 'requires_any' flag, initialize required to 1 if it is
532  * not set. */
533  if (then->required_runnable_before == 0) {
534  then->required_runnable_before = 1;
535  }
537  /* We are relying on the pe_order_one_or_more clause of
538  * graph_update_action(), called as part of the:
539  *
540  * 'if (first == other->action)'
541  *
542  * block below, to set this back if appropriate
543  */
544  }
545 
546  for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) {
547  action_wrapper_t *other = (action_wrapper_t *) lpc->data;
548  action_t *first = other->action;
549 
550  node_t *then_node = then->node;
551  node_t *first_node = first->node;
552 
553  enum pe_action_flags then_flags = 0;
554  enum pe_action_flags first_flags = 0;
555 
556  if (first->rsc && first->rsc->variant == pe_group && safe_str_eq(first->task, RSC_START)) {
557  first_node = first->rsc->fns->location(first->rsc, NULL, FALSE);
558  if (first_node) {
559  crm_trace("First: Found node %s for %s", first_node->details->uname, first->uuid);
560  }
561  }
562 
563  if (then->rsc && then->rsc->variant == pe_group && safe_str_eq(then->task, RSC_START)) {
564  then_node = then->rsc->fns->location(then->rsc, NULL, FALSE);
565  if (then_node) {
566  crm_trace("Then: Found node %s for %s", then_node->details->uname, then->uuid);
567  }
568  }
569  /* Disable constraint if it only applies when on same node, but isn't */
570  if (is_set(other->type, pe_order_same_node) && first_node && then_node
571  && (first_node->details != then_node->details)) {
572 
573  crm_trace("Disabled constraint %s on %s -> %s on %s",
574  other->action->uuid, first_node->details->uname,
575  then->uuid, then_node->details->uname);
576  other->type = pe_order_none;
577  continue;
578  }
579 
581 
582  if (first->rsc && is_set(other->type, pe_order_then_cancels_first)
583  && is_not_set(then->flags, pe_action_optional)) {
584 
585  /* 'then' is required, so we must abandon 'first'
586  * (e.g. a required stop cancels any reload).
587  * Only used with reload actions as 'first'.
588  */
589  set_bit(other->action->flags, pe_action_optional);
590  clear_bit(first->rsc->flags, pe_rsc_reload);
591  }
592 
593  if (first->rsc && then->rsc && (first->rsc != then->rsc)
594  && (is_parent(then->rsc, first->rsc) == FALSE)) {
595  first = rsc_expand_action(first);
596  }
597  if (first != other->action) {
598  crm_trace("Ordering %s after %s instead of %s", then->uuid, first->uuid,
599  other->action->uuid);
600  }
601 
602  first_flags = get_action_flags(first, then_node);
603  then_flags = get_action_flags(then, first_node);
604 
605  crm_trace("Checking %s (%s %s %s) against %s (%s %s %s) filter=0x%.6x type=0x%.6x",
606  then->uuid,
607  is_set(then_flags, pe_action_optional) ? "optional" : "required",
608  is_set(then_flags, pe_action_runnable) ? "runnable" : "unrunnable",
609  is_set(then_flags,
610  pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->
611  uname : "", first->uuid, is_set(first_flags,
612  pe_action_optional) ? "optional" : "required",
613  is_set(first_flags, pe_action_runnable) ? "runnable" : "unrunnable",
614  is_set(first_flags,
615  pe_action_pseudo) ? "pseudo" : first->node ? first->node->details->
616  uname : "", first_flags, other->type);
617 
618  if (first == other->action) {
619  /*
620  * 'first' was not expanded (e.g. from 'start' to 'running'), which could mean it:
621  * - has no associated resource,
622  * - was a primitive,
623  * - was pre-expanded (e.g. 'running' instead of 'start')
624  *
625  * The third argument here to graph_update_action() is a node which is used under two conditions:
626  * - Interleaving, in which case first->node and
627  * then->node are equal (and NULL)
628  * - If 'then' is a clone, to limit the scope of the
629  * constraint to instances on the supplied node
630  *
631  */
632  node_t *node = then->node;
633  changed |= graph_update_action(first, then, node, first_flags,
634  then_flags, other, data_set);
635 
636  /* 'first' was for a complex resource (clone, group, etc),
637  * create a new dependency if necessary
638  */
639  } else if (order_actions(first, then, other->type)) {
640  /* This was the first time 'first' and 'then' were associated,
641  * start again to get the new actions_before list
642  */
644  }
645 
646  if (changed & pe_graph_disable) {
647  crm_trace("Disabled constraint %s -> %s in favor of %s -> %s",
648  other->action->uuid, then->uuid, first->uuid, then->uuid);
649  clear_bit(changed, pe_graph_disable);
650  other->type = pe_order_none;
651  }
652 
653  if (changed & pe_graph_updated_first) {
654  GListPtr lpc2 = NULL;
655 
656  crm_trace("Updated %s (first %s %s %s), processing dependents ",
657  first->uuid,
658  is_set(first->flags, pe_action_optional) ? "optional" : "required",
659  is_set(first->flags, pe_action_runnable) ? "runnable" : "unrunnable",
660  is_set(first->flags,
661  pe_action_pseudo) ? "pseudo" : first->node ? first->node->details->
662  uname : "");
663  for (lpc2 = first->actions_after; lpc2 != NULL; lpc2 = lpc2->next) {
664  action_wrapper_t *other = (action_wrapper_t *) lpc2->data;
665 
666  update_action(other->action, data_set);
667  }
668  update_action(first, data_set);
669  }
670  }
671 
672  if (is_set(then->flags, pe_action_requires_any)) {
673  if (last_flags != then->flags) {
674  changed |= pe_graph_updated_then;
675  } else {
677  }
678  }
679 
680  if (changed & pe_graph_updated_then) {
681  crm_trace("Updated %s (then %s %s %s), processing dependents ",
682  then->uuid,
683  is_set(then->flags, pe_action_optional) ? "optional" : "required",
684  is_set(then->flags, pe_action_runnable) ? "runnable" : "unrunnable",
685  is_set(then->flags,
686  pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->
687  uname : "");
688 
689  if (is_set(last_flags, pe_action_runnable) && is_not_set(then->flags, pe_action_runnable)) {
690  update_colo_start_chain(then, data_set);
691  }
692  update_action(then, data_set);
693  for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) {
694  action_wrapper_t *other = (action_wrapper_t *) lpc->data;
695 
696  update_action(other->action, data_set);
697  }
698  }
699 
700  return FALSE;
701 }
702 
703 gboolean
704 shutdown_constraints(node_t * node, action_t * shutdown_op, pe_working_set_t * data_set)
705 {
706  /* add the stop to the before lists so it counts as a pre-req
707  * for the shutdown
708  */
709  GListPtr lpc = NULL;
710 
711  for (lpc = data_set->actions; lpc != NULL; lpc = lpc->next) {
712  action_t *action = (action_t *) lpc->data;
713 
714  if (action->rsc == NULL || action->node == NULL) {
715  continue;
716  } else if (action->node->details != node->details) {
717  continue;
718  } else if (is_set(action->rsc->flags, pe_rsc_maintenance)) {
719  pe_rsc_trace(action->rsc, "Skipping %s: maintenance mode", action->uuid);
720  continue;
721  } else if (node->details->maintenance) {
722  pe_rsc_trace(action->rsc, "Skipping %s: node %s is in maintenance mode",
723  action->uuid, node->details->uname);
724  continue;
725  } else if (safe_str_neq(action->task, RSC_STOP)) {
726  continue;
727  } else if (is_not_set(action->rsc->flags, pe_rsc_managed)
728  && is_not_set(action->rsc->flags, pe_rsc_block)) {
729  /*
730  * If another action depends on this one, we may still end up blocking
731  */
732  pe_rsc_trace(action->rsc, "Skipping %s: unmanaged", action->uuid);
733  continue;
734  }
735 
736  pe_rsc_trace(action->rsc, "Ordering %s before shutdown on %s", action->uuid,
737  node->details->uname);
738  pe_clear_action_bit(action, pe_action_optional);
739  custom_action_order(action->rsc, NULL, action,
740  NULL, strdup(CRM_OP_SHUTDOWN), shutdown_op,
741  pe_order_optional | pe_order_runnable_left, data_set);
742  }
743 
744  return TRUE;
745 }
746 
759 gboolean
760 stonith_constraints(node_t * node, action_t * stonith_op, pe_working_set_t * data_set)
761 {
762  GListPtr r = NULL;
763 
764  CRM_CHECK(stonith_op != NULL, return FALSE);
765  for (r = data_set->resources; r != NULL; r = r->next) {
766  rsc_stonith_ordering((resource_t *) r->data, stonith_op, data_set);
767  }
768  return TRUE;
769 }
770 
771 static node_t *
772 get_router_node(action_t *action)
773 {
774  node_t *began_on = NULL;
775  node_t *ended_on = NULL;
776  node_t *router_node = NULL;
777  bool partial_migration = FALSE;
778  const char *task = action->task;
779 
780  if (safe_str_eq(task, CRM_OP_FENCE)
781  || !pe__is_guest_or_remote_node(action->node)) {
782  return NULL;
783  }
784 
785  CRM_ASSERT(action->node->details->remote_rsc != NULL);
786 
787  began_on = pe__current_node(action->node->details->remote_rsc);
788  ended_on = action->node->details->remote_rsc->allocated_to;
789  if (action->node->details->remote_rsc
790  && (action->node->details->remote_rsc->container == NULL)
792  partial_migration = TRUE;
793  }
794 
795  /* if there is only one location to choose from,
796  * this is easy. Check for those conditions first */
797  if (!began_on || !ended_on) {
798  /* remote rsc is either shutting down or starting up */
799  return began_on ? began_on : ended_on;
800  } else if (began_on->details == ended_on->details) {
801  /* remote rsc didn't move nodes. */
802  return began_on;
803  }
804 
805  /* If we have get here, we know the remote resource
806  * began on one node and is moving to another node.
807  *
808  * This means some actions will get routed through the cluster
809  * node the connection rsc began on, and others are routed through
810  * the cluster node the connection rsc ends up on.
811  *
812  * 1. stop, demote, migrate actions of resources living in the remote
813  * node _MUST_ occur _BEFORE_ the connection can move (these actions
814  * are all required before the remote rsc stop action can occur.) In
815  * this case, we know these actions have to be routed through the initial
816  * cluster node the connection resource lived on before the move takes place.
817  * The exception is a partial migration of a (non-guest) remote
818  * connection resource; in that case, all actions (even these) will be
819  * ordered after the connection's pseudo-start on the migration target,
820  * so the target is the router node.
821  *
822  * 2. Everything else (start, promote, monitor, probe, refresh, clear failcount
823  * delete ....) must occur after the resource starts on the node it is
824  * moving to.
825  */
826 
827  if (safe_str_eq(task, "notify")) {
828  task = g_hash_table_lookup(action->meta, "notify_operation");
829  }
830 
831  /* 1. before connection rsc moves. */
832  if ((safe_str_eq(task, "stop") ||
833  safe_str_eq(task, "demote") ||
834  safe_str_eq(task, "migrate_from") ||
835  safe_str_eq(task, "migrate_to")) && !partial_migration) {
836 
837  router_node = began_on;
838 
839  /* 2. after connection rsc moves. */
840  } else {
841  router_node = ended_on;
842  }
843  return router_node;
844 }
845 
853 static xmlNode*
854 add_node_to_xml_by_id(const char *id, xmlNode *xml)
855 {
856  xmlNode *node_xml;
857 
858  node_xml = create_xml_node(xml, XML_CIB_TAG_NODE);
859  crm_xml_add(node_xml, XML_ATTR_UUID, id);
860 
861  return node_xml;
862 }
863 
871 static void
872 add_node_to_xml(const node_t *node, void *xml)
873 {
874  add_node_to_xml_by_id(node->details->id, (xmlNode *) xml);
875 }
876 
884 static int
885 add_maintenance_nodes(xmlNode *xml, const pe_working_set_t *data_set)
886 {
887  GListPtr gIter = NULL;
888  xmlNode *maintenance =
890  int count = 0;
891 
892  for (gIter = data_set->nodes; gIter != NULL;
893  gIter = gIter->next) {
894  node_t *node = (node_t *) gIter->data;
895  struct pe_node_shared_s *details = node->details;
896 
897  if (!pe__is_guest_or_remote_node(node)) {
898  continue; /* just remote nodes need to know atm */
899  }
900 
901  if (details->maintenance != details->remote_maintenance) {
902  if (maintenance) {
903  crm_xml_add(
904  add_node_to_xml_by_id(node->details->id, maintenance),
905  XML_NODE_IS_MAINTENANCE, details->maintenance?"1":"0");
906  }
907  count++;
908  }
909  }
910  crm_trace("%s %d nodes to adjust maintenance-mode "
911  "to transition", maintenance?"Added":"Counted", count);
912  return count;
913 }
914 
921 void
923 {
924  action_t *action = NULL;
925 
926  if (add_maintenance_nodes(NULL, data_set)) {
927  crm_trace("adding maintenance state update pseudo action");
928  action = get_pseudo_op(CRM_OP_MAINTENANCE_NODES, data_set);
930  }
931 }
932 
945 static void
946 add_downed_nodes(xmlNode *xml, const action_t *action,
947  const pe_working_set_t *data_set)
948 {
949  CRM_CHECK(xml && action && action->node && data_set, return);
950 
951  if (safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
952 
953  /* Shutdown makes the action's node down */
954  xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
955  add_node_to_xml_by_id(action->node->details->id, downed);
956 
957  } else if (safe_str_eq(action->task, CRM_OP_FENCE)) {
958 
959  /* Fencing makes the action's node and any hosted guest nodes down */
960  const char *fence = g_hash_table_lookup(action->meta, "stonith_action");
961 
962  if (safe_str_eq(fence, "off") || safe_str_eq(fence, "reboot")) {
963  xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
964  add_node_to_xml_by_id(action->node->details->id, downed);
965  pe_foreach_guest_node(data_set, action->node, add_node_to_xml, downed);
966  }
967 
968  } else if (action->rsc && action->rsc->is_remote_node
969  && safe_str_eq(action->task, CRMD_ACTION_STOP)) {
970 
971  /* Stopping a remote connection resource makes connected node down,
972  * unless it's part of a migration
973  */
974  GListPtr iter;
975  action_t *input;
976  gboolean migrating = FALSE;
977 
978  for (iter = action->actions_before; iter != NULL; iter = iter->next) {
979  input = ((action_wrapper_t *) iter->data)->action;
980  if (input->rsc && safe_str_eq(action->rsc->id, input->rsc->id)
981  && safe_str_eq(input->task, CRMD_ACTION_MIGRATED)) {
982  migrating = TRUE;
983  break;
984  }
985  }
986  if (!migrating) {
987  xmlNode *downed = create_xml_node(xml, XML_GRAPH_TAG_DOWNED);
988  add_node_to_xml_by_id(action->rsc->id, downed);
989  }
990  }
991 }
992 
993 static xmlNode *
994 action2xml(action_t * action, gboolean as_input, pe_working_set_t *data_set)
995 {
996  gboolean needs_node_info = TRUE;
997  gboolean needs_maintenance_info = FALSE;
998  xmlNode *action_xml = NULL;
999  xmlNode *args_xml = NULL;
1000 #if ENABLE_VERSIONED_ATTRS
1001  pe_rsc_action_details_t *rsc_details = NULL;
1002 #endif
1003 
1004  if (action == NULL) {
1005  return NULL;
1006  }
1007 
1008  if (safe_str_eq(action->task, CRM_OP_FENCE)) {
1009  /* All fences need node info; guest node fences are pseudo-events */
1010  action_xml = create_xml_node(NULL,
1011  is_set(action->flags, pe_action_pseudo)?
1014 
1015  } else if (safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
1016  action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1017 
1018  } else if (safe_str_eq(action->task, CRM_OP_CLEAR_FAILCOUNT)) {
1019  action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1020 
1021  } else if (safe_str_eq(action->task, CRM_OP_LRM_REFRESH)) {
1022  action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT);
1023 
1024 /* } else if(safe_str_eq(action->task, RSC_PROBED)) { */
1025 /* action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); */
1026 
1027  } else if (is_set(action->flags, pe_action_pseudo)) {
1028  if (safe_str_eq(action->task, CRM_OP_MAINTENANCE_NODES)) {
1029  needs_maintenance_info = TRUE;
1030  }
1031  action_xml = create_xml_node(NULL, XML_GRAPH_TAG_PSEUDO_EVENT);
1032  needs_node_info = FALSE;
1033 
1034  } else {
1035  action_xml = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
1036 #if ENABLE_VERSIONED_ATTRS
1037  rsc_details = pe_rsc_action_details(action);
1038 #endif
1039  }
1040 
1041  crm_xml_add_int(action_xml, XML_ATTR_ID, action->id);
1042  crm_xml_add(action_xml, XML_LRM_ATTR_TASK, action->task);
1043  if (action->rsc != NULL && action->rsc->clone_name != NULL) {
1044  char *clone_key = NULL;
1045  const char *interval_ms_s = g_hash_table_lookup(action->meta,
1047  guint interval_ms = crm_parse_ms(interval_ms_s);
1048 
1049  if (safe_str_eq(action->task, RSC_NOTIFY)) {
1050  const char *n_type = g_hash_table_lookup(action->meta, "notify_type");
1051  const char *n_task = g_hash_table_lookup(action->meta, "notify_operation");
1052 
1053  CRM_CHECK(n_type != NULL, crm_err("No notify type value found for %s", action->uuid));
1054  CRM_CHECK(n_task != NULL,
1055  crm_err("No notify operation value found for %s", action->uuid));
1056  clone_key = generate_notify_key(action->rsc->clone_name, n_type, n_task);
1057 
1058  } else if(action->cancel_task) {
1059  clone_key = generate_op_key(action->rsc->clone_name,
1060  action->cancel_task, interval_ms);
1061  } else {
1062  clone_key = generate_op_key(action->rsc->clone_name,
1063  action->task, interval_ms);
1064  }
1065 
1066  CRM_CHECK(clone_key != NULL, crm_err("Could not generate a key for %s", action->uuid));
1067  crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, clone_key);
1068  crm_xml_add(action_xml, "internal_" XML_LRM_ATTR_TASK_KEY, action->uuid);
1069  free(clone_key);
1070 
1071  } else {
1072  crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, action->uuid);
1073  }
1074 
1075  if (needs_node_info && action->node != NULL) {
1076  node_t *router_node = get_router_node(action);
1077 
1078  crm_xml_add(action_xml, XML_LRM_ATTR_TARGET, action->node->details->uname);
1079  crm_xml_add(action_xml, XML_LRM_ATTR_TARGET_UUID, action->node->details->id);
1080  if (router_node) {
1081  crm_xml_add(action_xml, XML_LRM_ATTR_ROUTER_NODE, router_node->details->uname);
1082  }
1083 
1084  g_hash_table_insert(action->meta, strdup(XML_LRM_ATTR_TARGET), strdup(action->node->details->uname));
1085  g_hash_table_insert(action->meta, strdup(XML_LRM_ATTR_TARGET_UUID), strdup(action->node->details->id));
1086  }
1087 
1088  /* No details if this action is only being listed in the inputs section */
1089  if (as_input) {
1090  return action_xml;
1091  }
1092 
1093  /* List affected resource */
1094  if (action->rsc) {
1095  if (is_set(action->flags, pe_action_pseudo) == FALSE) {
1096  int lpc = 0;
1097 
1098  xmlNode *rsc_xml = create_xml_node(action_xml, crm_element_name(action->rsc->xml));
1099 
1100  const char *attr_list[] = {
1104  };
1105 
1106  if (is_set(action->rsc->flags, pe_rsc_orphan) && action->rsc->clone_name) {
1107  /* Do not use the 'instance free' name here as that
1108  * might interfere with the instance we plan to keep.
1109  * Ie. if there are more than two named /anonymous/
1110  * instances on a given node, we need to make sure the
1111  * command goes to the right one.
1112  *
1113  * Keep this block, even when everyone is using
1114  * 'instance free' anonymous clone names - it means
1115  * we'll do the right thing if anyone toggles the
1116  * unique flag to 'off'
1117  */
1118  crm_debug("Using orphan clone name %s instead of %s", action->rsc->id,
1119  action->rsc->clone_name);
1120  crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->clone_name);
1121  crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
1122 
1123  } else if (is_not_set(action->rsc->flags, pe_rsc_unique)) {
1124  const char *xml_id = ID(action->rsc->xml);
1125 
1126  crm_debug("Using anonymous clone name %s for %s (aka. %s)", xml_id, action->rsc->id,
1127  action->rsc->clone_name);
1128 
1129  /* ID is what we'd like client to use
1130  * ID_LONG is what they might know it as instead
1131  *
1132  * ID_LONG is only strictly needed /here/ during the
1133  * transition period until all nodes in the cluster
1134  * are running the new software /and/ have rebooted
1135  * once (meaning that they've only ever spoken to a DC
1136  * supporting this feature).
1137  *
1138  * If anyone toggles the unique flag to 'on', the
1139  * 'instance free' name will correspond to an orphan
1140  * and fall into the clause above instead
1141  */
1142  crm_xml_add(rsc_xml, XML_ATTR_ID, xml_id);
1143  if (action->rsc->clone_name && safe_str_neq(xml_id, action->rsc->clone_name)) {
1144  crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->clone_name);
1145  } else {
1146  crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id);
1147  }
1148 
1149  } else {
1150  CRM_ASSERT(action->rsc->clone_name == NULL);
1151  crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->id);
1152  }
1153 
1154  for (lpc = 0; lpc < DIMOF(attr_list); lpc++) {
1155  crm_xml_add(rsc_xml, attr_list[lpc],
1156  g_hash_table_lookup(action->rsc->meta, attr_list[lpc]));
1157  }
1158  }
1159  }
1160 
1161  /* List any attributes in effect */
1162  args_xml = create_xml_node(NULL, XML_TAG_ATTRS);
1164 
1165  g_hash_table_foreach(action->extra, hash2field, args_xml);
1166  if (action->rsc != NULL && action->node) {
1167  GHashTable *p = crm_str_table_new();
1168 
1169  get_rsc_attributes(p, action->rsc, action->node, data_set);
1170  g_hash_table_foreach(p, hash2smartfield, args_xml);
1171  g_hash_table_destroy(p);
1172 
1173 #if ENABLE_VERSIONED_ATTRS
1174  {
1175  xmlNode *versioned_parameters = create_xml_node(NULL, XML_TAG_RSC_VER_ATTRS);
1176 
1177  pe_get_versioned_attributes(versioned_parameters, action->rsc,
1178  action->node, data_set);
1179  if (xml_has_children(versioned_parameters)) {
1180  add_node_copy(action_xml, versioned_parameters);
1181  }
1182  free_xml(versioned_parameters);
1183  }
1184 #endif
1185 
1186  } else if(action->rsc && action->rsc->variant <= pe_native) {
1187  g_hash_table_foreach(action->rsc->parameters, hash2smartfield, args_xml);
1188 
1189 #if ENABLE_VERSIONED_ATTRS
1190  if (xml_has_children(action->rsc->versioned_parameters)) {
1191  add_node_copy(action_xml, action->rsc->versioned_parameters);
1192  }
1193 #endif
1194  }
1195 
1196 #if ENABLE_VERSIONED_ATTRS
1197  if (rsc_details) {
1198  if (xml_has_children(rsc_details->versioned_parameters)) {
1199  add_node_copy(action_xml, rsc_details->versioned_parameters);
1200  }
1201 
1202  if (xml_has_children(rsc_details->versioned_meta)) {
1203  add_node_copy(action_xml, rsc_details->versioned_meta);
1204  }
1205  }
1206 #endif
1207 
1208  g_hash_table_foreach(action->meta, hash2metafield, args_xml);
1209  if (action->rsc != NULL) {
1210  const char *value = g_hash_table_lookup(action->rsc->meta, "external-ip");
1211  resource_t *parent = action->rsc;
1212 
1213  while (parent != NULL) {
1214  parent->cmds->append_meta(parent, args_xml);
1215  parent = parent->parent;
1216  }
1217 
1218  if(value) {
1219  hash2smartfield((gpointer)"pcmk_external_ip", (gpointer)value, (gpointer)args_xml);
1220  }
1221 
1222  if (pe__is_guest_node(action->node)) {
1223  pe_node_t *host = NULL;
1224  enum action_tasks task = text2task(action->task);
1225 
1226  if(task == action_notify || task == action_notified) {
1227  const char *n_task = g_hash_table_lookup(action->meta, "notify_operation");
1228  task = text2task(n_task);
1229  }
1230 
1231  // Differentiate between up and down actions
1232  switch (task) {
1233  case stop_rsc:
1234  case stopped_rsc:
1235  case action_demote:
1236  case action_demoted:
1237  host = pe__current_node(action->node->details->remote_rsc->container);
1238  break;
1239  case start_rsc:
1240  case started_rsc:
1241  case monitor_rsc:
1242  case action_promote:
1243  case action_promoted:
1244  host = action->node->details->remote_rsc->container->allocated_to;
1245  break;
1246  default:
1247  break;
1248  }
1249 
1250  if(host) {
1252  (gpointer)g_hash_table_lookup(action->rsc->meta, XML_RSC_ATTR_TARGET), (gpointer)args_xml);
1253  hash2metafield((gpointer)PCMK_ENV_PHYSICAL_HOST, (gpointer)host->details->uname, (gpointer)args_xml);
1254  }
1255  }
1256 
1257  } else if (safe_str_eq(action->task, CRM_OP_FENCE) && action->node) {
1258  /* Pass the node's attributes as meta-attributes.
1259  *
1260  * @TODO: Determine whether it is still necessary to do this. It was
1261  * added in 33d99707, probably for the libfence-based implementation in
1262  * c9a90bd, which is no longer used.
1263  */
1264  g_hash_table_foreach(action->node->details->attrs, hash2metafield, args_xml);
1265  }
1266 
1267  sorted_xml(args_xml, action_xml, FALSE);
1268  free_xml(args_xml);
1269 
1270  /* List any nodes this action is expected to make down */
1271  if (needs_node_info && (action->node != NULL)) {
1272  add_downed_nodes(action_xml, action, data_set);
1273  }
1274 
1275  if (needs_maintenance_info) {
1276  add_maintenance_nodes(action_xml, data_set);
1277  }
1278 
1279  crm_log_xml_trace(action_xml, "dumped action");
1280  return action_xml;
1281 }
1282 
1283 static gboolean
1284 should_dump_action(action_t * action)
1285 {
1286  CRM_CHECK(action != NULL, return FALSE);
1287 
1288  if (is_set(action->flags, pe_action_dumped)) {
1289  crm_trace("action %d (%s) was already dumped", action->id, action->uuid);
1290  return FALSE;
1291 
1292  } else if (is_set(action->flags, pe_action_pseudo) && safe_str_eq(action->task, CRM_OP_PROBED)) {
1293  GListPtr lpc = NULL;
1294 
1295  /* This is a horrible but convenient hack
1296  *
1297  * It mimimizes the number of actions with unsatisfied inputs
1298  * (i.e. not included in the graph)
1299  *
1300  * This in turn, means we can be more concise when printing
1301  * aborted/incomplete graphs.
1302  *
1303  * It also makes it obvious which node is preventing
1304  * probe_complete from running (presumably because it is only
1305  * partially up)
1306  *
1307  * For these reasons we tolerate such perversions
1308  */
1309 
1310  for (lpc = action->actions_after; lpc != NULL; lpc = lpc->next) {
1311  action_wrapper_t *wrapper = (action_wrapper_t *) lpc->data;
1312 
1313  if (is_not_set(wrapper->action->flags, pe_action_runnable)) {
1314  /* Only interested in runnable operations */
1315  } else if (safe_str_neq(wrapper->action->task, RSC_START)) {
1316  /* Only interested in start operations */
1317  } else if (is_set(wrapper->action->flags, pe_action_dumped)) {
1318  crm_trace("action %d (%s) dependency of %s",
1319  action->id, action->uuid, wrapper->action->uuid);
1320  return TRUE;
1321 
1322  } else if (should_dump_action(wrapper->action)) {
1323  crm_trace("action %d (%s) dependency of %s",
1324  action->id, action->uuid, wrapper->action->uuid);
1325  return TRUE;
1326  }
1327  }
1328  }
1329 
1330  if (is_set(action->flags, pe_action_runnable) == FALSE) {
1331  crm_trace("action %d (%s) was not runnable", action->id, action->uuid);
1332  return FALSE;
1333 
1334  } else if (is_set(action->flags, pe_action_optional)
1335  && is_set(action->flags, pe_action_print_always) == FALSE) {
1336  crm_trace("action %d (%s) was optional", action->id, action->uuid);
1337  return FALSE;
1338 
1339  // Monitors should be dumped even for unmanaged resources
1340  } else if (action->rsc && is_not_set(action->rsc->flags, pe_rsc_managed)
1341  && safe_str_neq(action->task, RSC_STATUS)) {
1342 
1343  const char *interval_ms_s = g_hash_table_lookup(action->meta,
1345 
1346  // Cancellation of recurring monitors should still be dumped
1347  if ((interval_ms_s == NULL) || !strcmp(interval_ms_s, "0")) {
1348  crm_trace("action %d (%s) was for an unmanaged resource (%s)",
1349  action->id, action->uuid, action->rsc->id);
1350  return FALSE;
1351  }
1352  }
1353 
1354  if (is_set(action->flags, pe_action_pseudo)
1355  || safe_str_eq(action->task, CRM_OP_FENCE)
1356  || safe_str_eq(action->task, CRM_OP_SHUTDOWN)) {
1357  /* skip the next checks */
1358  return TRUE;
1359  }
1360 
1361  if (action->node == NULL) {
1362  pe_err("action %d (%s) was not allocated", action->id, action->uuid);
1363  log_action(LOG_DEBUG, "Unallocated action", action, FALSE);
1364  return FALSE;
1365 
1366  } else if (pe__is_guest_node(action->node)
1367  && !action->node->details->remote_requires_reset) {
1368  crm_trace("Assuming action %s for %s will be runnable", action->uuid, action->node->details->uname);
1369 
1370  } else if (action->node->details->online == FALSE) {
1371  pe_err("action %d was (%s) scheduled for offline node", action->id, action->uuid);
1372  log_action(LOG_DEBUG, "Action for offline node", action, FALSE);
1373  return FALSE;
1374 #if 0
1375  /* but this would also affect resources that can be safely
1376  * migrated before a fencing op
1377  */
1378  } else if (action->node->details->unclean == FALSE) {
1379  pe_err("action %d was (%s) scheduled for unclean node", action->id, action->uuid);
1380  log_action(LOG_DEBUG, "Action for unclean node", action, FALSE);
1381  return FALSE;
1382 #endif
1383  }
1384  return TRUE;
1385 }
1386 
1387 /* lowest to highest */
1388 static gint
1389 sort_action_id(gconstpointer a, gconstpointer b)
1390 {
1391  const action_wrapper_t *action_wrapper2 = (const action_wrapper_t *)a;
1392  const action_wrapper_t *action_wrapper1 = (const action_wrapper_t *)b;
1393 
1394  if (a == NULL) {
1395  return 1;
1396  }
1397  if (b == NULL) {
1398  return -1;
1399  }
1400 
1401  if (action_wrapper1->action->id > action_wrapper2->action->id) {
1402  return -1;
1403  }
1404 
1405  if (action_wrapper1->action->id < action_wrapper2->action->id) {
1406  return 1;
1407  }
1408  return 0;
1409 }
1410 
1411 static gboolean
1412 check_dump_input(int last_action, action_t * action, action_wrapper_t * wrapper)
1413 {
1414  int type = wrapper->type;
1415 
1416  if (wrapper->state == pe_link_dumped) {
1417  return TRUE;
1418 
1419  } else if (wrapper->state == pe_link_dup) {
1420  return FALSE;
1421  }
1422 
1424  type &= ~pe_order_implies_then_printed;
1425  type &= ~pe_order_optional;
1426 
1427  if (is_not_set(type, pe_order_preserve)
1428  && action->rsc && action->rsc->fillers
1429  && wrapper->action->rsc && wrapper->action->node
1430  && wrapper->action->node->details->remote_rsc
1431  && (wrapper->action->node->details->remote_rsc->container == action->rsc)) {
1432  /* This prevents user-defined ordering constraints between resources
1433  * running in a guest node and the resource that defines that node.
1434  */
1435  crm_warn("Invalid ordering constraint between %s and %s",
1436  wrapper->action->rsc->id, action->rsc->id);
1437  wrapper->type = pe_order_none;
1438  return FALSE;
1439  }
1440 
1441  if (last_action == wrapper->action->id) {
1442  crm_trace("Input (%d) %s duplicated for %s",
1443  wrapper->action->id, wrapper->action->uuid, action->uuid);
1444  wrapper->state = pe_link_dup;
1445  return FALSE;
1446 
1447  } else if (wrapper->type == pe_order_none) {
1448  crm_trace("Input (%d) %s suppressed for %s",
1449  wrapper->action->id, wrapper->action->uuid, action->uuid);
1450  return FALSE;
1451 
1452  } else if (is_set(wrapper->action->flags, pe_action_runnable) == FALSE
1453  && type == pe_order_none && safe_str_neq(wrapper->action->uuid, CRM_OP_PROBED)) {
1454  crm_trace("Input (%d) %s optional (ordering) for %s",
1455  wrapper->action->id, wrapper->action->uuid, action->uuid);
1456  return FALSE;
1457 
1458  } else if (is_set(wrapper->action->flags, pe_action_runnable) == FALSE
1459  && is_set(type, pe_order_one_or_more)) {
1460  crm_trace("Input (%d) %s optional (one-or-more) for %s",
1461  wrapper->action->id, wrapper->action->uuid, action->uuid);
1462  return FALSE;
1463 
1464  } else if (is_set(action->flags, pe_action_pseudo)
1465  && (wrapper->type & pe_order_stonith_stop)) {
1466  crm_trace("Input (%d) %s suppressed for %s",
1467  wrapper->action->id, wrapper->action->uuid, action->uuid);
1468  return FALSE;
1469 
1470  } else if ((wrapper->type & pe_order_implies_first_migratable) && (is_set(wrapper->action->flags, pe_action_runnable) == FALSE)) {
1471  return FALSE;
1472 
1473  } else if ((wrapper->type & pe_order_apply_first_non_migratable)
1474  && (is_set(wrapper->action->flags, pe_action_migrate_runnable))) {
1475  return FALSE;
1476 
1477  } else if ((wrapper->type == pe_order_optional)
1478  && crm_ends_with(wrapper->action->uuid, "_stop_0")
1479  && is_set(wrapper->action->flags, pe_action_migrate_runnable)) {
1480 
1481  /* for optional only ordering, ordering is not preserved for
1482  * a stop action that is actually involved with a migration. */
1483  return FALSE;
1484 
1485  } else if (wrapper->type == pe_order_load) {
1486  crm_trace("check load filter %s.%s -> %s.%s",
1487  wrapper->action->uuid,
1488  wrapper->action->node ? wrapper->action->node->details->uname : "", action->uuid,
1489  action->node ? action->node->details->uname : "");
1490 
1491  if (action->rsc && safe_str_eq(action->task, RSC_MIGRATE)) {
1492  /* Remove the orders like the following if not relevant:
1493  * "load_stopped_node2" -> "rscA_migrate_to node1"
1494  * which were created also from: sched_native.c: MigrateRsc()
1495  * order_actions(other, then, other_w->type);
1496  */
1497 
1498  /* For migrate_to ops, we care about where it has been
1499  * allocated to, not where the action will be executed
1500  */
1501  if (wrapper->action->node == NULL || action->rsc->allocated_to == NULL
1502  || wrapper->action->node->details != action->rsc->allocated_to->details) {
1503  /* Check if the actions are for the same node, ignore otherwise */
1504  crm_trace("load filter - migrate");
1505  wrapper->type = pe_order_none;
1506  return FALSE;
1507  }
1508 
1509  } else if (wrapper->action->node == NULL || action->node == NULL
1510  || wrapper->action->node->details != action->node->details) {
1511  /* Check if the actions are for the same node, ignore otherwise */
1512  crm_trace("load filter - node");
1513  wrapper->type = pe_order_none;
1514  return FALSE;
1515 
1516  } else if (is_set(wrapper->action->flags, pe_action_optional)) {
1517  /* Check if the pre-req is optional, ignore if so */
1518  crm_trace("load filter - optional");
1519  wrapper->type = pe_order_none;
1520  return FALSE;
1521  }
1522 
1523  } else if (wrapper->type == pe_order_anti_colocation) {
1524  crm_trace("check anti-colocation filter %s.%s -> %s.%s",
1525  wrapper->action->uuid,
1526  wrapper->action->node ? wrapper->action->node->details->uname : "",
1527  action->uuid,
1528  action->node ? action->node->details->uname : "");
1529 
1530  if (wrapper->action->node && action->node
1531  && wrapper->action->node->details != action->node->details) {
1532  /* Check if the actions are for the same node, ignore otherwise */
1533  crm_trace("anti-colocation filter - node");
1534  wrapper->type = pe_order_none;
1535  return FALSE;
1536 
1537  } else if (is_set(wrapper->action->flags, pe_action_optional)) {
1538  /* Check if the pre-req is optional, ignore if so */
1539  crm_trace("anti-colocation filter - optional");
1540  wrapper->type = pe_order_none;
1541  return FALSE;
1542  }
1543 
1544  } else if (wrapper->action->rsc
1545  && wrapper->action->rsc != action->rsc
1546  && is_set(wrapper->action->rsc->flags, pe_rsc_failed)
1547  && is_not_set(wrapper->action->rsc->flags, pe_rsc_managed)
1548  && crm_ends_with(wrapper->action->uuid, "_stop_0")
1549  && action->rsc && pe_rsc_is_clone(action->rsc)) {
1550  crm_warn("Ignoring requirement that %s complete before %s:"
1551  " unmanaged failed resources cannot prevent clone shutdown",
1552  wrapper->action->uuid, action->uuid);
1553  return FALSE;
1554 
1555  } else if (is_set(wrapper->action->flags, pe_action_dumped)
1556  || should_dump_action(wrapper->action)) {
1557  crm_trace("Input (%d) %s should be dumped for %s", wrapper->action->id,
1558  wrapper->action->uuid, action->uuid);
1559  goto dump;
1560 
1561 #if 0
1562  } else if (is_set(wrapper->action->flags, pe_action_runnable)
1563  && is_set(wrapper->action->flags, pe_action_pseudo)
1564  && wrapper->action->rsc->variant != pe_native) {
1565  crm_crit("Input (%d) %s should be dumped for %s",
1566  wrapper->action->id, wrapper->action->uuid, action->uuid);
1567  goto dump;
1568 #endif
1569  } else if (is_set(wrapper->action->flags, pe_action_optional) == TRUE
1570  && is_set(wrapper->action->flags, pe_action_print_always) == FALSE) {
1571  crm_trace("Input (%d) %s optional for %s", wrapper->action->id,
1572  wrapper->action->uuid, action->uuid);
1573  crm_trace("Input (%d) %s n=%p p=%d r=%d o=%d a=%d f=0x%.6x",
1574  wrapper->action->id, wrapper->action->uuid, wrapper->action->node,
1575  is_set(wrapper->action->flags, pe_action_pseudo),
1576  is_set(wrapper->action->flags, pe_action_runnable),
1577  is_set(wrapper->action->flags, pe_action_optional),
1578  is_set(wrapper->action->flags, pe_action_print_always), wrapper->type);
1579  return FALSE;
1580 
1581  }
1582 
1583  dump:
1584  return TRUE;
1585 }
1586 
1587 static gboolean
1588 graph_has_loop(action_t * init_action, action_t * action, action_wrapper_t * wrapper)
1589 {
1590  GListPtr lpc = NULL;
1591  gboolean has_loop = FALSE;
1592 
1593  if (is_set(wrapper->action->flags, pe_action_tracking)) {
1594  crm_trace("Breaking tracking loop: %s.%s -> %s.%s (0x%.6x)",
1595  wrapper->action->uuid,
1596  wrapper->action->node ? wrapper->action->node->details->uname : "",
1597  action->uuid,
1598  action->node ? action->node->details->uname : "",
1599  wrapper->type);
1600  return FALSE;
1601  }
1602 
1603  if (check_dump_input(-1, action, wrapper) == FALSE) {
1604  return FALSE;
1605  }
1606 
1607  /* If there's any order like:
1608  * "rscB_stop node2"-> "load_stopped_node2" -> "rscA_migrate_to node1"
1609  * rscA is being migrated from node1 to node2,
1610  * while rscB is being migrated from node2 to node1.
1611  * There will be potential graph loop.
1612  * Break the order "load_stopped_node2" -> "rscA_migrate_to node1".
1613  */
1614 
1615  crm_trace("Checking graph loop: %s.%s -> %s.%s (0x%.6x)",
1616  wrapper->action->uuid,
1617  wrapper->action->node ? wrapper->action->node->details->uname : "",
1618  action->uuid,
1619  action->node ? action->node->details->uname : "",
1620  wrapper->type);
1621 
1622  if (wrapper->action == init_action) {
1623  crm_debug("Found graph loop: %s.%s ->...-> %s.%s",
1624  action->uuid,
1625  action->node ? action->node->details->uname : "",
1626  init_action->uuid,
1627  init_action->node ? init_action->node->details->uname : "");
1628 
1629  return TRUE;
1630  }
1631 
1632  set_bit(wrapper->action->flags, pe_action_tracking);
1633 
1634  for (lpc = wrapper->action->actions_before; lpc != NULL; lpc = lpc->next) {
1635  action_wrapper_t *wrapper_before = (action_wrapper_t *) lpc->data;
1636 
1637  if (graph_has_loop(init_action, wrapper->action, wrapper_before)) {
1638  has_loop = TRUE;
1639  goto done;
1640  }
1641  }
1642 
1643 done:
1645 
1646  return has_loop;
1647 }
1648 
1649 static gboolean
1650 should_dump_input(int last_action, action_t * action, action_wrapper_t * wrapper)
1651 {
1652  wrapper->state = pe_link_not_dumped;
1653 
1654  if (check_dump_input(last_action, action, wrapper) == FALSE) {
1655  return FALSE;
1656  }
1657 
1658  if (wrapper->type == pe_order_load
1659  && action->rsc
1660  && safe_str_eq(action->task, RSC_MIGRATE)) {
1661  crm_trace("Checking graph loop - load migrate: %s.%s -> %s.%s",
1662  wrapper->action->uuid,
1663  wrapper->action->node ? wrapper->action->node->details->uname : "",
1664  action->uuid,
1665  action->node ? action->node->details->uname : "");
1666 
1667  if (graph_has_loop(action, action, wrapper)) {
1668  /* Remove the orders like the following if they are introducing any graph loops:
1669  * "load_stopped_node2" -> "rscA_migrate_to node1"
1670  * which were created also from: sched_native.c: MigrateRsc()
1671  * order_actions(other, then, other_w->type);
1672  */
1673  crm_debug("Breaking graph loop - load migrate: %s.%s -> %s.%s",
1674  wrapper->action->uuid,
1675  wrapper->action->node ? wrapper->action->node->details->uname : "",
1676  action->uuid,
1677  action->node ? action->node->details->uname : "");
1678 
1679  wrapper->type = pe_order_none;
1680  return FALSE;
1681  }
1682  }
1683 
1684  crm_trace("Input (%d) %s n=%p p=%d r=%d o=%d a=%d f=0x%.6x dumped for %s",
1685  wrapper->action->id,
1686  wrapper->action->uuid,
1687  wrapper->action->node,
1688  is_set(wrapper->action->flags, pe_action_pseudo),
1689  is_set(wrapper->action->flags, pe_action_runnable),
1690  is_set(wrapper->action->flags, pe_action_optional),
1691  is_set(wrapper->action->flags, pe_action_print_always), wrapper->type, action->uuid);
1692  return TRUE;
1693 }
1694 
1695 void
1697 {
1698  GListPtr lpc = NULL;
1699  int last_action = -1;
1700  int synapse_priority = 0;
1701  xmlNode *syn = NULL;
1702  xmlNode *set = NULL;
1703  xmlNode *in = NULL;
1704  xmlNode *input = NULL;
1705  xmlNode *xml_action = NULL;
1706 
1707  if (should_dump_action(action) == FALSE) {
1708  return;
1709  }
1710 
1711  set_bit(action->flags, pe_action_dumped);
1712 
1713  syn = create_xml_node(data_set->graph, "synapse");
1714  set = create_xml_node(syn, "action_set");
1715  in = create_xml_node(syn, "inputs");
1716 
1717  crm_xml_add_int(syn, XML_ATTR_ID, data_set->num_synapse);
1718  data_set->num_synapse++;
1719 
1720  if (action->rsc != NULL) {
1721  synapse_priority = action->rsc->priority;
1722  }
1723  if (action->priority > synapse_priority) {
1724  synapse_priority = action->priority;
1725  }
1726  if (synapse_priority > 0) {
1727  crm_xml_add_int(syn, XML_CIB_ATTR_PRIORITY, synapse_priority);
1728  }
1729 
1730  xml_action = action2xml(action, FALSE, data_set);
1731  add_node_nocopy(set, crm_element_name(xml_action), xml_action);
1732 
1733  action->actions_before = g_list_sort(action->actions_before, sort_action_id);
1734 
1735  for (lpc = action->actions_before; lpc != NULL; lpc = lpc->next) {
1736  action_wrapper_t *wrapper = (action_wrapper_t *) lpc->data;
1737 
1738  if (should_dump_input(last_action, action, wrapper) == FALSE) {
1739  continue;
1740  }
1741 
1742  wrapper->state = pe_link_dumped;
1743  CRM_CHECK(last_action < wrapper->action->id,;
1744  );
1745  last_action = wrapper->action->id;
1746  input = create_xml_node(in, "trigger");
1747 
1748  xml_action = action2xml(wrapper->action, TRUE, data_set);
1749  add_node_nocopy(input, crm_element_name(xml_action), xml_action);
1750  }
1751 }
#define XML_ATTR_ID_LONG
Definition: msg_xml.h:98
enum pe_link_state state
Definition: pe_types.h:482
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:156
char uname[MAX_NAME]
Definition: internal.h:87
GListPtr nodes
Definition: pe_types.h:133
const char * task2text(enum action_tasks task)
Definition: common.c:276
#define RSC_STOP
Definition: crm.h:177
enum pe_action_flags(* action_flags)(action_t *, node_t *)
A dumping ground.
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: operations.c:47
#define CRMD_ACTION_MIGRATED
Definition: crm.h:147
GHashTable * attrs
Definition: pe_types.h:204
#define crm_crit(fmt, args...)
Definition: logging.h:239
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:157
#define INFINITY
Definition: crm.h:73
gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc)
Definition: complex.c:729
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:615
int runnable_before
Definition: pe_types.h:397
#define CRM_OP_FENCE
Definition: crm.h:119
#define XML_GRAPH_TAG_MAINTENANCE
Definition: msg_xml.h:293
int priority
Definition: pe_types.h:363
pe_resource_t * container
Definition: pe_types.h:343
#define XML_ATTR_TYPE
Definition: msg_xml.h:99
resource_alloc_functions_t * cmds
Definition: pe_types.h:296
xmlNode * xml
Definition: pe_types.h:286
pe_resource_t * rsc
Definition: pe_types.h:365
void add_maintenance_update(pe_working_set_t *data_set)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:383
#define CRM_FEATURE_SET
Definition: crm.h:32
pe_resource_t * remote_rsc
Definition: pe_types.h:200
char * cancel_task
Definition: pe_types.h:371
GHashTable * meta
Definition: pe_types.h:336
#define pe_rsc_unique
Definition: pe_types.h:223
#define pe_rsc_notify
Definition: pe_types.h:222
#define XML_TAG_ATTRS
Definition: msg_xml.h:165
resource_object_functions_t * fns
Definition: pe_types.h:295
void pe_action_set_flag_reason(const char *function, long line, pe_action_t *action, pe_action_t *reason, const char *text, enum pe_action_flags flags, bool overwrite)
Definition: utils.c:2345
GHashTable * parameters
Definition: pe_types.h:337
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:275
gboolean pe__is_guest_or_remote_node(pe_node_t *node)
Definition: remote.c:58
#define XML_GRAPH_TAG_RSC_OP
Definition: msg_xml.h:289
GListPtr fillers
Definition: pe_types.h:344
enum pe_graph_flags(* update_actions)(pe_action_t *, pe_action_t *, pe_node_t *, enum pe_action_flags, enum pe_action_flags, enum pe_ordering, pe_working_set_t *data_set)
GListPtr resources
Definition: pe_types.h:134
#define XML_NODE_IS_MAINTENANCE
Definition: msg_xml.h:244
AIS_Host host
Definition: internal.h:86
enum action_tasks text2task(const char *task)
Definition: common.c:224
#define XML_GRAPH_TAG_CRM_EVENT
Definition: msg_xml.h:291
#define clear_bit(word, bit)
Definition: crm_internal.h:168
pe_node_t * partial_migration_target
Definition: pe_types.h:327
#define RSC_START
Definition: crm.h:174
action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
Definition: utils.c:1828
pe_node_t * allocated_to
Definition: pe_types.h:326
pe_action_t * action
Definition: pe_types.h:483
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Add hash table entry to XML as (possibly legacy) name/value.
Definition: nvpair.c:581
#define XML_GRAPH_TAG_DOWNED
Definition: msg_xml.h:292
#define XML_RSC_ATTR_TARGET
Definition: msg_xml.h:182
gboolean remote_requires_reset
Definition: pe_types.h:194
GListPtr actions_before
Definition: pe_types.h:402
#define RSC_NOTIFY
Definition: crm.h:185
#define RSC_MIGRATE
Definition: crm.h:171
#define XML_GRAPH_TAG_PSEUDO_EVENT
Definition: msg_xml.h:290
GHashTable * extra
Definition: pe_types.h:380
#define PCMK_ENV_PHYSICAL_HOST
Definition: crm_internal.h:214
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:235
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:261
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:260
#define CRM_OP_LRM_REFRESH
Definition: crm.h:123
#define CRMD_ACTION_STOP
Definition: crm.h:152
#define CRM_OP_CLEAR_FAILCOUNT
Definition: crm.h:129
void pe_foreach_guest_node(const pe_working_set_t *data_set, const node_t *host, void(*helper)(const node_t *, void *), void *user_data)
Definition: remote.c:115
#define crm_warn(fmt, args...)
Definition: logging.h:241
#define set_bit(word, bit)
Definition: crm_internal.h:167
pe_action_flags
Definition: pe_types.h:258
#define pe_rsc_failed
Definition: pe_types.h:234
gboolean pe__is_guest_node(pe_node_t *node)
Definition: remote.c:47
#define crm_debug(fmt, args...)
Definition: logging.h:245
void log_action(unsigned int log_level, const char *pre_text, action_t *action, gboolean details)
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:746
#define XML_ATTR_ID
Definition: msg_xml.h:96
char * task
Definition: pe_types.h:369
gboolean update_action(pe_action_t *action, pe_working_set_t *data_set)
#define crm_trace(fmt, args...)
Definition: logging.h:246
action_t * find_first_action(GListPtr input, const char *uuid, const char *task, node_t *on_node)
Definition: utils.c:1398
GHashTable * meta
Definition: pe_types.h:379
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:1868
struct pe_node_shared_s * details
Definition: pe_types.h:213
GListPtr running_on
Definition: pe_types.h:329
pe_node_t * node
Definition: pe_types.h:366
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:230
unsigned long long flags
Definition: pe_types.h:311
const char * uname
Definition: pe_types.h:179
GListPtr actions
Definition: pe_types.h:140
Wrappers for and extensions to libxml2.
char * generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
Definition: operations.c:128
char * clone_name
Definition: pe_types.h:285
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1890
pe_graph_flags
Definition: pe_types.h:250
gboolean rsc_update_action(action_t *first, action_t *then, enum pe_ordering type)
GListPtr rsc_cons_lhs
Definition: pe_types.h:319
char * uuid
Definition: pe_types.h:370
#define XML_LRM_ATTR_ROUTER_NODE
Definition: msg_xml.h:268
#define XML_TAG_RSC_VER_ATTRS
Definition: msg_xml.h:166
void free_xml(xmlNode *child)
Definition: xml.c:2014
enum pe_obj_types variant
Definition: pe_types.h:293
gboolean xml_has_children(const xmlNode *root)
Definition: xml.c:3206
#define XML_CIB_TAG_NODE
Definition: msg_xml.h:159
void graph_element_from_action(action_t *action, pe_working_set_t *data_set)
GListPtr actions
Definition: pe_types.h:322
#define CRM_OP_SHUTDOWN
Definition: crm.h:118
const char * id
Definition: pe_types.h:178
gboolean crm_ends_with(const char *s, const char *match)
Definition: strings.c:309
#define CRM_OP_MAINTENANCE_NODES
Definition: crm.h:134
xmlNode * sorted_xml(xmlNode *input, xmlNode *parent, gboolean recursive)
Definition: xml.c:4123
#define XML_LRM_ATTR_TARGET_UUID
Definition: msg_xml.h:263
#define XML_ATTR_UUID
Definition: msg_xml.h:119
guint crm_parse_ms(const char *text)
Definition: strings.c:143
void update_colo_start_chain(pe_action_t *action, pe_working_set_t *data_set)
void get_rsc_attributes(GHashTable *meta_hash, pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Definition: complex.c:127
resource_t * rsc_lh
gboolean is_remote_node
Definition: pe_types.h:314
GListPtr children
Definition: pe_types.h:340
gboolean update_action_flags(action_t *action, enum pe_action_flags flags, const char *source, int line)
#define crm_err(fmt, args...)
Definition: logging.h:240
#define CRM_ASSERT(expr)
Definition: results.h:42
#define RSC_STATUS
Definition: crm.h:188
Cluster Configuration.
#define pe_rsc_reload
Definition: pe_types.h:231
#define pe_clear_action_bit(action, bit)
Definition: internal.h:25
GListPtr actions_after
Definition: pe_types.h:403
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:258
#define DIMOF(a)
Definition: crm.h:35
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry, as meta-attribute name.
Definition: nvpair.c:643
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:79
#define pe_rsc_block
Definition: pe_types.h:219
enum pe_action_flags flags
Definition: pe_types.h:374
gboolean maintenance
Definition: pe_types.h:192
#define CRM_OP_PROBED
Definition: crm.h:127
#define pe_rsc_maintenance
Definition: pe_types.h:243
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition: pe_types.h:52
int add_node_nocopy(xmlNode *parent, const char *name, xmlNode *child)
Definition: xml.c:1882
int custom_action_order(resource_t *lh_rsc, char *lh_task, action_t *lh_action, resource_t *rh_rsc, char *rh_task, action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set)
gboolean stonith_constraints(node_t *node, action_t *stonith_op, pe_working_set_t *data_set)
#define crm_log_xml_trace(xml, text)
Definition: logging.h:254
void rsc_stonith_ordering(resource_t *rsc, action_t *stonith_op, pe_working_set_t *data_set)
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:262
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:18
#define ID(x)
Definition: msg_xml.h:414
#define pe_err(fmt...)
Definition: internal.h:20
#define safe_str_eq(a, b)
Definition: util.h:59
gboolean order_actions(action_t *lh_action, action_t *rh_action, enum pe_ordering order)
Definition: utils.c:1776
enum pe_ordering type
Definition: pe_types.h:481
gboolean unclean
Definition: pe_types.h:187
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
GList * GListPtr
Definition: crm.h:192
#define pe_rsc_managed
Definition: pe_types.h:218
#define pe_rsc_orphan
Definition: pe_types.h:217
char * generate_op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key.
Definition: operations.c:39
gboolean shutdown_constraints(node_t *node, action_t *shutdown_op, pe_working_set_t *data_set)
pe_ordering
Definition: pe_types.h:437
void(* append_meta)(resource_t *rsc, xmlNode *xml)
gboolean online
Definition: pe_types.h:183
uint64_t flags
Definition: remote.c:148
int required_runnable_before
Definition: pe_types.h:400
action_tasks
Definition: common.h:57
pe_resource_t * parent
Definition: pe_types.h:291
enum crm_ais_msg_types type
Definition: internal.h:85
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:229
xmlNode * graph
Definition: pe_types.h:152
char * id
Definition: pe_types.h:284