pacemaker  2.1.0-7c3f660
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
utils.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2021 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 #include <crm/crm.h>
12 #include <crm/msg_xml.h>
13 #include <crm/common/xml.h>
15 #include <crm/common/util.h>
16 
17 #include <glib.h>
18 #include <stdbool.h>
19 
20 #include <crm/pengine/rules.h>
21 #include <crm/pengine/internal.h>
22 #include "pe_status_private.h"
23 
24 extern bool pcmk__is_daemon;
25 
26 extern xmlNode *get_object_root(const char *object_type, xmlNode * the_root);
27 void print_str_str(gpointer key, gpointer value, gpointer user_data);
28 gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
29 static void unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * container,
30  pe_working_set_t * data_set, guint interval_ms);
31 static xmlNode *find_rsc_op_entry_helper(pe_resource_t * rsc, const char *key,
32  gboolean include_disabled);
33 
34 #if ENABLE_VERSIONED_ATTRS
35 pe_rsc_action_details_t *
36 pe_rsc_action_details(pe_action_t *action)
37 {
38  pe_rsc_action_details_t *details;
39 
40  CRM_CHECK(action != NULL, return NULL);
41 
42  if (action->action_details == NULL) {
43  action->action_details = calloc(1, sizeof(pe_rsc_action_details_t));
44  CRM_CHECK(action->action_details != NULL, return NULL);
45  }
46 
47  details = (pe_rsc_action_details_t *) action->action_details;
48  if (details->versioned_parameters == NULL) {
49  details->versioned_parameters = create_xml_node(NULL,
51  }
52  if (details->versioned_meta == NULL) {
53  details->versioned_meta = create_xml_node(NULL, XML_TAG_OP_VER_META);
54  }
55  return details;
56 }
57 
58 static void
59 pe_free_rsc_action_details(pe_action_t *action)
60 {
61  pe_rsc_action_details_t *details;
62 
63  if ((action == NULL) || (action->action_details == NULL)) {
64  return;
65  }
66 
67  details = (pe_rsc_action_details_t *) action->action_details;
68 
69  if (details->versioned_parameters) {
70  free_xml(details->versioned_parameters);
71  }
72  if (details->versioned_meta) {
73  free_xml(details->versioned_meta);
74  }
75 
76  action->action_details = NULL;
77 }
78 #endif
79 
89 bool
91 {
92  if (pe__is_guest_node(node)) {
93  /* Guest nodes are fenced by stopping their container resource. We can
94  * do that if the container's host is either online or fenceable.
95  */
97 
98  for (GList *n = rsc->running_on; n != NULL; n = n->next) {
99  pe_node_t *container_node = n->data;
100 
101  if (!container_node->details->online
102  && !pe_can_fence(data_set, container_node)) {
103  return false;
104  }
105  }
106  return true;
107 
108  } else if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
109  return false; /* Turned off */
110 
111  } else if (!pcmk_is_set(data_set->flags, pe_flag_have_stonith_resource)) {
112  return false; /* No devices */
113 
114  } else if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
115  return true;
116 
117  } else if (data_set->no_quorum_policy == no_quorum_ignore) {
118  return true;
119 
120  } else if(node == NULL) {
121  return false;
122 
123  } else if(node->details->online) {
124  crm_notice("We can fence %s without quorum because they're in our membership", node->details->uname);
125  return true;
126  }
127 
128  crm_trace("Cannot fence %s", node->details->uname);
129  return false;
130 }
131 
141 pe_node_t *
142 pe__copy_node(const pe_node_t *this_node)
143 {
144  pe_node_t *new_node = NULL;
145 
146  CRM_ASSERT(this_node != NULL);
147 
148  new_node = calloc(1, sizeof(pe_node_t));
149  CRM_ASSERT(new_node != NULL);
150 
151  new_node->rsc_discover_mode = this_node->rsc_discover_mode;
152  new_node->weight = this_node->weight;
153  new_node->fixed = this_node->fixed;
154  new_node->details = this_node->details;
155 
156  return new_node;
157 }
158 
159 /* any node in list1 or list2 and not in the other gets a score of -INFINITY */
160 void
161 node_list_exclude(GHashTable * hash, GList *list, gboolean merge_scores)
162 {
163  GHashTable *result = hash;
164  pe_node_t *other_node = NULL;
165  GList *gIter = list;
166 
167  GHashTableIter iter;
168  pe_node_t *node = NULL;
169 
170  g_hash_table_iter_init(&iter, hash);
171  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
172 
173  other_node = pe_find_node_id(list, node->details->id);
174  if (other_node == NULL) {
175  node->weight = -INFINITY;
176  } else if (merge_scores) {
177  node->weight = pe__add_scores(node->weight, other_node->weight);
178  }
179  }
180 
181  for (; gIter != NULL; gIter = gIter->next) {
182  pe_node_t *node = (pe_node_t *) gIter->data;
183 
184  other_node = pe_hash_table_lookup(result, node->details->id);
185 
186  if (other_node == NULL) {
187  pe_node_t *new_node = pe__copy_node(node);
188 
189  new_node->weight = -INFINITY;
190  g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
191  }
192  }
193 }
194 
203 GHashTable *
205 {
206  GHashTable *result = NULL;
207 
208  result = pcmk__strkey_table(NULL, free);
209  for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
210  pe_node_t *new_node = pe__copy_node((pe_node_t *) gIter->data);
211 
212  g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
213  }
214  return result;
215 }
216 
217 gint
218 sort_node_uname(gconstpointer a, gconstpointer b)
219 {
220  return pcmk__numeric_strcasecmp(((const pe_node_t *) a)->details->uname,
221  ((const pe_node_t *) b)->details->uname);
222 }
223 
232 static void
233 pe__output_node_weights(pe_resource_t *rsc, const char *comment,
234  GHashTable *nodes, pe_working_set_t *data_set)
235 {
236  pcmk__output_t *out = data_set->priv;
237  char score[128]; // Stack-allocated since this is called frequently
238 
239  // Sort the nodes so the output is consistent for regression tests
240  GList *list = g_list_sort(g_hash_table_get_values(nodes), sort_node_uname);
241 
242  for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
243  pe_node_t *node = (pe_node_t *) gIter->data;
244 
245  score2char_stack(node->weight, score, sizeof(score));
246  out->message(out, "node-weight", rsc, comment, node->details->uname, score);
247  }
248  g_list_free(list);
249 }
250 
262 static void
263 pe__log_node_weights(const char *file, const char *function, int line,
264  pe_resource_t *rsc, const char *comment, GHashTable *nodes)
265 {
266  GHashTableIter iter;
267  pe_node_t *node = NULL;
268  char score[128]; // Stack-allocated since this is called frequently
269 
270  // Don't waste time if we're not tracing at this point
271  pcmk__log_else(LOG_TRACE, return);
272 
273  g_hash_table_iter_init(&iter, nodes);
274  while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
275  score2char_stack(node->weight, score, sizeof(score));
276  if (rsc) {
277  qb_log_from_external_source(function, file,
278  "%s: %s allocation score on %s: %s",
279  LOG_TRACE, line, 0,
280  comment, rsc->id,
281  node->details->uname, score);
282  } else {
283  qb_log_from_external_source(function, file, "%s: %s = %s",
284  LOG_TRACE, line, 0,
285  comment, node->details->uname,
286  score);
287  }
288  }
289 }
290 
303 void
304 pe__show_node_weights_as(const char *file, const char *function, int line,
305  bool to_log, pe_resource_t *rsc, const char *comment,
306  GHashTable *nodes, pe_working_set_t *data_set)
307 {
308  if (rsc != NULL && pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
309  // Don't show allocation scores for orphans
310  return;
311  }
312  if (nodes == NULL) {
313  // Nothing to show
314  return;
315  }
316 
317  if (to_log) {
318  pe__log_node_weights(file, function, line, rsc, comment, nodes);
319  } else {
320  pe__output_node_weights(rsc, comment, nodes, data_set);
321  }
322 
323  // If this resource has children, repeat recursively for each
324  if (rsc && rsc->children) {
325  for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
326  pe_resource_t *child = (pe_resource_t *) gIter->data;
327 
328  pe__show_node_weights_as(file, function, line, to_log, child,
329  comment, child->allowed_nodes, data_set);
330  }
331  }
332 }
333 
334 gint
335 sort_rsc_index(gconstpointer a, gconstpointer b)
336 {
337  const pe_resource_t *resource1 = (const pe_resource_t *)a;
338  const pe_resource_t *resource2 = (const pe_resource_t *)b;
339 
340  if (a == NULL && b == NULL) {
341  return 0;
342  }
343  if (a == NULL) {
344  return 1;
345  }
346  if (b == NULL) {
347  return -1;
348  }
349 
350  if (resource1->sort_index > resource2->sort_index) {
351  return -1;
352  }
353 
354  if (resource1->sort_index < resource2->sort_index) {
355  return 1;
356  }
357 
358  return 0;
359 }
360 
361 gint
362 sort_rsc_priority(gconstpointer a, gconstpointer b)
363 {
364  const pe_resource_t *resource1 = (const pe_resource_t *)a;
365  const pe_resource_t *resource2 = (const pe_resource_t *)b;
366 
367  if (a == NULL && b == NULL) {
368  return 0;
369  }
370  if (a == NULL) {
371  return 1;
372  }
373  if (b == NULL) {
374  return -1;
375  }
376 
377  if (resource1->priority > resource2->priority) {
378  return -1;
379  }
380 
381  if (resource1->priority < resource2->priority) {
382  return 1;
383  }
384 
385  return 0;
386 }
387 
388 static enum pe_quorum_policy
389 effective_quorum_policy(pe_resource_t *rsc, pe_working_set_t *data_set)
390 {
391  enum pe_quorum_policy policy = data_set->no_quorum_policy;
392 
393  if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
394  policy = no_quorum_ignore;
395 
396  } else if (data_set->no_quorum_policy == no_quorum_demote) {
397  switch (rsc->role) {
398  case RSC_ROLE_PROMOTED:
399  case RSC_ROLE_UNPROMOTED:
400  if (rsc->next_role > RSC_ROLE_UNPROMOTED) {
402  "no-quorum-policy=demote");
403  }
404  policy = no_quorum_ignore;
405  break;
406  default:
407  policy = no_quorum_stop;
408  break;
409  }
410  }
411  return policy;
412 }
413 
414 pe_action_t *
415 custom_action(pe_resource_t * rsc, char *key, const char *task,
416  pe_node_t * on_node, gboolean optional, gboolean save_action,
417  pe_working_set_t * data_set)
418 {
419  pe_action_t *action = NULL;
420  GList *possible_matches = NULL;
421 
422  CRM_CHECK(key != NULL, return NULL);
423  CRM_CHECK(task != NULL, free(key); return NULL);
424 
425  if (save_action && rsc != NULL) {
426  possible_matches = find_actions(rsc->actions, key, on_node);
427  } else if(save_action) {
428 #if 0
429  action = g_hash_table_lookup(data_set->singletons, key);
430 #else
431  /* More expensive but takes 'node' into account */
432  possible_matches = find_actions(data_set->actions, key, on_node);
433 #endif
434  }
435 
436  if(data_set->singletons == NULL) {
437  data_set->singletons = pcmk__strkey_table(NULL, NULL);
438  }
439 
440  if (possible_matches != NULL) {
441  if (pcmk__list_of_multiple(possible_matches)) {
442  pe_warn("Action %s for %s on %s exists %d times",
443  task, rsc ? rsc->id : "<NULL>",
444  on_node ? on_node->details->uname : "<NULL>", g_list_length(possible_matches));
445  }
446 
447  action = g_list_nth_data(possible_matches, 0);
448  pe_rsc_trace(rsc, "Found action %d: %s for %s (%s) on %s",
449  action->id, task, (rsc? rsc->id : "no resource"),
450  action->uuid,
451  (on_node? on_node->details->uname : "no node"));
452  g_list_free(possible_matches);
453  }
454 
455  if (action == NULL) {
456  if (save_action) {
457  pe_rsc_trace(rsc, "Creating action %d (%s): %s for %s (%s) on %s",
458  data_set->action_id,
459  (optional? "optional" : "required"),
460  task, (rsc? rsc->id : "no resource"), key,
461  (on_node? on_node->details->uname : "no node"));
462  }
463 
464  action = calloc(1, sizeof(pe_action_t));
465  if (save_action) {
466  action->id = data_set->action_id++;
467  } else {
468  action->id = 0;
469  }
470  action->rsc = rsc;
471  action->task = strdup(task);
472  if (on_node) {
473  action->node = pe__copy_node(on_node);
474  }
475  action->uuid = strdup(key);
476 
477  if (pcmk__str_eq(task, CRM_OP_LRM_DELETE, pcmk__str_casei)) {
478  // Resource history deletion for a node can be done on the DC
480  }
481 
483  if (optional) {
485  } else {
487  }
488 
489  action->extra = pcmk__strkey_table(free, free);
490  action->meta = pcmk__strkey_table(free, free);
491 
492  if (save_action) {
493  data_set->actions = g_list_prepend(data_set->actions, action);
494  if(rsc == NULL) {
495  g_hash_table_insert(data_set->singletons, action->uuid, action);
496  }
497  }
498 
499  if (rsc != NULL) {
500  guint interval_ms = 0;
501 
502  action->op_entry = find_rsc_op_entry_helper(rsc, key, TRUE);
503  parse_op_key(key, NULL, NULL, &interval_ms);
504 
505  unpack_operation(action, action->op_entry, rsc->container, data_set,
506  interval_ms);
507 
508  if (save_action) {
509  rsc->actions = g_list_prepend(rsc->actions, action);
510  }
511  }
512  }
513 
514  if (!optional && pcmk_is_set(action->flags, pe_action_optional)) {
516  }
517 
518  if (rsc != NULL) {
519  enum action_tasks a_task = text2task(action->task);
520  enum pe_quorum_policy quorum_policy = effective_quorum_policy(rsc, data_set);
521  int warn_level = LOG_TRACE;
522 
523  if (save_action) {
524  warn_level = LOG_WARNING;
525  }
526 
528  && action->node != NULL && action->op_entry != NULL) {
529  pe_rule_eval_data_t rule_data = {
530  .node_hash = action->node->details->attrs,
531  .role = RSC_ROLE_UNKNOWN,
532  .now = data_set->now,
533  .match_data = NULL,
534  .rsc_data = NULL,
535  .op_data = NULL
536  };
537 
540  &rule_data, action->extra, NULL,
541  FALSE, data_set);
542  }
543 
544  if (pcmk_is_set(action->flags, pe_action_pseudo)) {
545  /* leave untouched */
546 
547  } else if (action->node == NULL) {
548  pe_rsc_trace(rsc, "%s is unrunnable (unallocated)",
549  action->uuid);
551 
552  } else if (!pcmk_is_set(rsc->flags, pe_rsc_managed)
553  && g_hash_table_lookup(action->meta,
554  XML_LRM_ATTR_INTERVAL_MS) == NULL) {
555  pe_rsc_debug(rsc, "%s on %s is optional (%s is unmanaged)",
556  action->uuid, action->node->details->uname, rsc->id);
558  //pe__clear_action_flags(action, pe_action_runnable);
559 
560  } else if (!pcmk_is_set(action->flags, pe_action_dc)
561  && !(action->node->details->online)
562  && (!pe__is_guest_node(action->node)
563  || action->node->details->remote_requires_reset)) {
565  do_crm_log(warn_level,
566  "%s on %s is unrunnable (node is offline)",
567  action->uuid, action->node->details->uname);
568  if (pcmk_is_set(action->rsc->flags, pe_rsc_managed)
569  && save_action && a_task == stop_rsc
570  && action->node->details->unclean == FALSE) {
571  pe_fence_node(data_set, action->node, "resource actions are unrunnable", FALSE);
572  }
573 
574  } else if (!pcmk_is_set(action->flags, pe_action_dc)
575  && action->node->details->pending) {
577  do_crm_log(warn_level,
578  "Action %s on %s is unrunnable (node is pending)",
579  action->uuid, action->node->details->uname);
580 
581  } else if (action->needs == rsc_req_nothing) {
582  pe_action_set_reason(action, NULL, TRUE);
583  if (pe__is_guest_node(action->node)
584  && !pe_can_fence(data_set, action->node)) {
585  /* An action that requires nothing usually does not require any
586  * fencing in order to be runnable. However, there is an
587  * exception: an action cannot be completed if it is on a guest
588  * node whose host is unclean and cannot be fenced.
589  */
590  pe_rsc_debug(rsc, "%s on %s is unrunnable "
591  "(node's host cannot be fenced)",
592  action->uuid, action->node->details->uname);
594  } else {
595  pe_rsc_trace(rsc, "%s on %s does not require fencing or quorum",
596  action->uuid, action->node->details->uname);
598  }
599 #if 0
600  /*
601  * No point checking this
602  * - if we don't have quorum we can't stonith anyway
603  */
604  } else if (action->needs == rsc_req_stonith) {
605  crm_trace("Action %s requires only stonith", action->uuid);
606  action->runnable = TRUE;
607 #endif
608  } else if (quorum_policy == no_quorum_stop) {
609  pe_rsc_debug(rsc, "%s on %s is unrunnable (no quorum)",
610  action->uuid, action->node->details->uname);
611  pe_action_set_flag_reason(__func__, __LINE__, action, NULL,
612  "no quorum", pe_action_runnable, TRUE);
613 
614  } else if (quorum_policy == no_quorum_freeze) {
615  if (rsc->fns->active(rsc, TRUE) == FALSE || rsc->next_role > rsc->role) {
616  pe_rsc_debug(rsc, "%s on %s is unrunnable (no quorum)",
617  action->uuid, action->node->details->uname);
618  pe_action_set_flag_reason(__func__, __LINE__, action, NULL,
619  "quorum freeze", pe_action_runnable,
620  TRUE);
621  }
622 
623  } else {
624  //pe_action_set_reason(action, NULL, TRUE);
626  }
627 
628  if (save_action) {
629  switch (a_task) {
630  case stop_rsc:
632  break;
633  case start_rsc:
635  if (pcmk_is_set(action->flags, pe_action_runnable)) {
637  }
638  break;
639  default:
640  break;
641  }
642  }
643  }
644 
645  free(key);
646  return action;
647 }
648 
649 static bool
650 valid_stop_on_fail(const char *value)
651 {
652  return !pcmk__strcase_any_of(value, "standby", "demote", "stop", NULL);
653 }
654 
655 static const char *
656 unpack_operation_on_fail(pe_action_t * action)
657 {
658 
659  const char *name = NULL;
660  const char *role = NULL;
661  const char *on_fail = NULL;
662  const char *interval_spec = NULL;
663  const char *enabled = NULL;
664  const char *value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ON_FAIL);
665 
666  if (pcmk__str_eq(action->task, CRMD_ACTION_STOP, pcmk__str_casei)
667  && !valid_stop_on_fail(value)) {
668 
669  pcmk__config_err("Resetting '" XML_OP_ATTR_ON_FAIL "' for %s stop "
670  "action to default value because '%s' is not "
671  "allowed for stop", action->rsc->id, value);
672  return NULL;
673 
674  } else if (pcmk__str_eq(action->task, CRMD_ACTION_DEMOTE, pcmk__str_casei) && !value) {
675  // demote on_fail defaults to monitor value for promoted role if present
676  xmlNode *operation = NULL;
677 
678  CRM_CHECK(action->rsc != NULL, return NULL);
679 
680  for (operation = pcmk__xe_first_child(action->rsc->ops_xml);
681  (operation != NULL) && (value == NULL);
682  operation = pcmk__xe_next(operation)) {
683 
684  if (!pcmk__str_eq((const char *)operation->name, "op", pcmk__str_none)) {
685  continue;
686  }
687  name = crm_element_value(operation, "name");
688  role = crm_element_value(operation, "role");
689  on_fail = crm_element_value(operation, XML_OP_ATTR_ON_FAIL);
690  enabled = crm_element_value(operation, "enabled");
691  interval_spec = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
692  if (!on_fail) {
693  continue;
694  } else if (enabled && !crm_is_true(enabled)) {
695  continue;
696  } else if (!pcmk__str_eq(name, "monitor", pcmk__str_casei)
699  NULL)) {
700  continue;
701  } else if (crm_parse_interval_spec(interval_spec) == 0) {
702  continue;
703  } else if (pcmk__str_eq(on_fail, "demote", pcmk__str_casei)) {
704  continue;
705  }
706 
707  value = on_fail;
708  }
709  } else if (pcmk__str_eq(action->task, CRM_OP_LRM_DELETE, pcmk__str_casei)) {
710  value = "ignore";
711 
712  } else if (pcmk__str_eq(value, "demote", pcmk__str_casei)) {
713  name = crm_element_value(action->op_entry, "name");
714  role = crm_element_value(action->op_entry, "role");
715  interval_spec = crm_element_value(action->op_entry,
717 
718  if (!pcmk__str_eq(name, CRMD_ACTION_PROMOTE, pcmk__str_casei)
719  && (!pcmk__str_eq(name, CRMD_ACTION_STATUS, pcmk__str_casei)
722  || (crm_parse_interval_spec(interval_spec) == 0))) {
723  pcmk__config_err("Resetting '" XML_OP_ATTR_ON_FAIL "' for %s %s "
724  "action to default value because 'demote' is not "
725  "allowed for it", action->rsc->id, name);
726  return NULL;
727  }
728  }
729 
730  return value;
731 }
732 
733 static xmlNode *
734 find_min_interval_mon(pe_resource_t * rsc, gboolean include_disabled)
735 {
736  guint interval_ms = 0;
737  guint min_interval_ms = G_MAXUINT;
738  const char *name = NULL;
739  const char *value = NULL;
740  const char *interval_spec = NULL;
741  xmlNode *op = NULL;
742  xmlNode *operation = NULL;
743 
744  for (operation = pcmk__xe_first_child(rsc->ops_xml);
745  operation != NULL;
746  operation = pcmk__xe_next(operation)) {
747 
748  if (pcmk__str_eq((const char *)operation->name, "op", pcmk__str_none)) {
749  name = crm_element_value(operation, "name");
750  interval_spec = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
751  value = crm_element_value(operation, "enabled");
752  if (!include_disabled && value && crm_is_true(value) == FALSE) {
753  continue;
754  }
755 
756  if (!pcmk__str_eq(name, RSC_STATUS, pcmk__str_casei)) {
757  continue;
758  }
759 
760  interval_ms = crm_parse_interval_spec(interval_spec);
761 
762  if (interval_ms && (interval_ms < min_interval_ms)) {
763  min_interval_ms = interval_ms;
764  op = operation;
765  }
766  }
767  }
768 
769  return op;
770 }
771 
772 static int
773 unpack_start_delay(const char *value, GHashTable *meta)
774 {
775  int start_delay = 0;
776 
777  if (value != NULL) {
778  start_delay = crm_get_msec(value);
779 
780  if (start_delay < 0) {
781  start_delay = 0;
782  }
783 
784  if (meta) {
785  g_hash_table_replace(meta, strdup(XML_OP_ATTR_START_DELAY),
786  pcmk__itoa(start_delay));
787  }
788  }
789 
790  return start_delay;
791 }
792 
793 // true if value contains valid, non-NULL interval origin for recurring op
794 static bool
795 unpack_interval_origin(const char *value, xmlNode *xml_obj, guint interval_ms,
796  crm_time_t *now, long long *start_delay)
797 {
798  long long result = 0;
799  guint interval_sec = interval_ms / 1000;
800  crm_time_t *origin = NULL;
801 
802  // Ignore unspecified values and non-recurring operations
803  if ((value == NULL) || (interval_ms == 0) || (now == NULL)) {
804  return false;
805  }
806 
807  // Parse interval origin from text
808  origin = crm_time_new(value);
809  if (origin == NULL) {
810  pcmk__config_err("Ignoring '" XML_OP_ATTR_ORIGIN "' for operation "
811  "'%s' because '%s' is not valid",
812  (ID(xml_obj)? ID(xml_obj) : "(missing ID)"), value);
813  return false;
814  }
815 
816  // Get seconds since origin (negative if origin is in the future)
817  result = crm_time_get_seconds(now) - crm_time_get_seconds(origin);
818  crm_time_free(origin);
819 
820  // Calculate seconds from closest interval to now
821  result = result % interval_sec;
822 
823  // Calculate seconds remaining until next interval
824  result = ((result <= 0)? 0 : interval_sec) - result;
825  crm_info("Calculated a start delay of %llds for operation '%s'",
826  result,
827  (ID(xml_obj)? ID(xml_obj) : "(unspecified)"));
828 
829  if (start_delay != NULL) {
830  *start_delay = result * 1000; // milliseconds
831  }
832  return true;
833 }
834 
835 static int
836 unpack_timeout(const char *value)
837 {
838  int timeout_ms = crm_get_msec(value);
839 
840  if (timeout_ms < 0) {
842  }
843  return timeout_ms;
844 }
845 
846 int
847 pe_get_configured_timeout(pe_resource_t *rsc, const char *action, pe_working_set_t *data_set)
848 {
849  xmlNode *child = NULL;
850  GHashTable *action_meta = NULL;
851  const char *timeout_spec = NULL;
852  int timeout_ms = 0;
853 
854  pe_rule_eval_data_t rule_data = {
855  .node_hash = NULL,
856  .role = RSC_ROLE_UNKNOWN,
857  .now = data_set->now,
858  .match_data = NULL,
859  .rsc_data = NULL,
860  .op_data = NULL
861  };
862 
863  for (child = first_named_child(rsc->ops_xml, XML_ATTR_OP);
864  child != NULL; child = crm_next_same_xml(child)) {
865  if (pcmk__str_eq(action, crm_element_value(child, XML_NVPAIR_ATTR_NAME),
866  pcmk__str_casei)) {
867  timeout_spec = crm_element_value(child, XML_ATTR_TIMEOUT);
868  break;
869  }
870  }
871 
872  if (timeout_spec == NULL && data_set->op_defaults) {
873  action_meta = pcmk__strkey_table(free, free);
875  &rule_data, action_meta, NULL, FALSE, data_set);
876  timeout_spec = g_hash_table_lookup(action_meta, XML_ATTR_TIMEOUT);
877  }
878 
879  // @TODO check meta-attributes (including versioned meta-attributes)
880  // @TODO maybe use min-interval monitor timeout as default for monitors
881 
882  timeout_ms = crm_get_msec(timeout_spec);
883  if (timeout_ms < 0) {
885  }
886 
887  if (action_meta != NULL) {
888  g_hash_table_destroy(action_meta);
889  }
890  return timeout_ms;
891 }
892 
893 #if ENABLE_VERSIONED_ATTRS
894 static void
895 unpack_versioned_meta(xmlNode *versioned_meta, xmlNode *xml_obj,
896  guint interval_ms, crm_time_t *now)
897 {
898  xmlNode *attrs = NULL;
899  xmlNode *attr = NULL;
900 
901  for (attrs = pcmk__xe_first_child(versioned_meta); attrs != NULL;
902  attrs = pcmk__xe_next(attrs)) {
903 
904  for (attr = pcmk__xe_first_child(attrs); attr != NULL;
905  attr = pcmk__xe_next(attr)) {
906 
907  const char *name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME);
908  const char *value = crm_element_value(attr, XML_NVPAIR_ATTR_VALUE);
909 
910  if (pcmk__str_eq(name, XML_OP_ATTR_START_DELAY, pcmk__str_casei)) {
911  int start_delay = unpack_start_delay(value, NULL);
912 
913  crm_xml_add_int(attr, XML_NVPAIR_ATTR_VALUE, start_delay);
914  } else if (pcmk__str_eq(name, XML_OP_ATTR_ORIGIN, pcmk__str_casei)) {
915  long long start_delay = 0;
916 
917  if (unpack_interval_origin(value, xml_obj, interval_ms, now,
918  &start_delay)) {
921  crm_xml_add_ll(attr, XML_NVPAIR_ATTR_VALUE, start_delay);
922  }
923  } else if (pcmk__str_eq(name, XML_ATTR_TIMEOUT, pcmk__str_casei)) {
924  int timeout_ms = unpack_timeout(value);
925 
926  crm_xml_add_int(attr, XML_NVPAIR_ATTR_VALUE, timeout_ms);
927  }
928  }
929  }
930 }
931 #endif
932 
946 static void
947 unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * container,
948  pe_working_set_t * data_set, guint interval_ms)
949 {
950  int timeout_ms = 0;
951  const char *value = NULL;
952  bool is_probe = pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)
953  && (interval_ms == 0);
954 #if ENABLE_VERSIONED_ATTRS
955  pe_rsc_action_details_t *rsc_details = NULL;
956 #endif
957 
958  pe_rsc_eval_data_t rsc_rule_data = {
960  .provider = crm_element_value(action->rsc->xml, XML_AGENT_ATTR_PROVIDER),
961  .agent = crm_element_value(action->rsc->xml, XML_EXPR_ATTR_TYPE)
962  };
963 
964  pe_op_eval_data_t op_rule_data = {
965  .op_name = action->task,
966  .interval = interval_ms
967  };
968 
969  pe_rule_eval_data_t rule_data = {
970  .node_hash = NULL,
971  .role = RSC_ROLE_UNKNOWN,
972  .now = data_set->now,
973  .match_data = NULL,
974  .rsc_data = &rsc_rule_data,
975  .op_data = &op_rule_data
976  };
977 
978  CRM_CHECK(action && action->rsc, return);
979 
980  // Cluster-wide <op_defaults> <meta_attributes>
982  action->meta, NULL, FALSE, data_set);
983 
984  // Determine probe default timeout differently
985  if (is_probe) {
986  xmlNode *min_interval_mon = find_min_interval_mon(action->rsc, FALSE);
987 
988  if (min_interval_mon) {
989  value = crm_element_value(min_interval_mon, XML_ATTR_TIMEOUT);
990  if (value) {
991  crm_trace("\t%s: Setting default timeout to minimum-interval "
992  "monitor's timeout '%s'", action->uuid, value);
993  g_hash_table_replace(action->meta, strdup(XML_ATTR_TIMEOUT),
994  strdup(value));
995  }
996  }
997  }
998 
999  if (xml_obj) {
1000  xmlAttrPtr xIter = NULL;
1001 
1002  // <op> <meta_attributes> take precedence over defaults
1003  pe__unpack_dataset_nvpairs(xml_obj, XML_TAG_META_SETS, &rule_data,
1004  action->meta, NULL, TRUE, data_set);
1005 
1006 #if ENABLE_VERSIONED_ATTRS
1007  rsc_details = pe_rsc_action_details(action);
1008 
1009  pe_eval_versioned_attributes(data_set->input, xml_obj,
1010  XML_TAG_ATTR_SETS, &rule_data,
1011  rsc_details->versioned_parameters,
1012  NULL);
1013  pe_eval_versioned_attributes(data_set->input, xml_obj,
1014  XML_TAG_META_SETS, &rule_data,
1015  rsc_details->versioned_meta,
1016  NULL);
1017 #endif
1018 
1019  /* Anything set as an <op> XML property has highest precedence.
1020  * This ensures we use the name and interval from the <op> tag.
1021  */
1022  for (xIter = xml_obj->properties; xIter; xIter = xIter->next) {
1023  const char *prop_name = (const char *)xIter->name;
1024  const char *prop_value = crm_element_value(xml_obj, prop_name);
1025 
1026  g_hash_table_replace(action->meta, strdup(prop_name), strdup(prop_value));
1027  }
1028  }
1029 
1030  g_hash_table_remove(action->meta, "id");
1031 
1032  // Normalize interval to milliseconds
1033  if (interval_ms > 0) {
1034  g_hash_table_replace(action->meta, strdup(XML_LRM_ATTR_INTERVAL),
1035  crm_strdup_printf("%u", interval_ms));
1036  } else {
1037  g_hash_table_remove(action->meta, XML_LRM_ATTR_INTERVAL);
1038  }
1039 
1040  /*
1041  * Timeout order of precedence:
1042  * 1. pcmk_monitor_timeout (if rsc has pcmk_ra_cap_fence_params
1043  * and task is start or a probe; pcmk_monitor_timeout works
1044  * by default for a recurring monitor)
1045  * 2. explicit op timeout on the primitive
1046  * 3. default op timeout
1047  * a. if probe, then min-interval monitor's timeout
1048  * b. else, in XML_CIB_TAG_OPCONFIG
1049  * 4. CRM_DEFAULT_OP_TIMEOUT_S
1050  *
1051  * #1 overrides general rule of <op> XML property having highest
1052  * precedence.
1053  */
1054  if (pcmk_is_set(pcmk_get_ra_caps(rsc_rule_data.standard),
1056  && (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)
1057  || is_probe)) {
1058 
1059  GHashTable *params = pe_rsc_params(action->rsc, action->node, data_set);
1060 
1061  value = g_hash_table_lookup(params, "pcmk_monitor_timeout");
1062 
1063  if (value) {
1064  crm_trace("\t%s: Setting timeout to pcmk_monitor_timeout '%s', "
1065  "overriding default", action->uuid, value);
1066  g_hash_table_replace(action->meta, strdup(XML_ATTR_TIMEOUT),
1067  strdup(value));
1068  }
1069  }
1070 
1071  // Normalize timeout to positive milliseconds
1072  value = g_hash_table_lookup(action->meta, XML_ATTR_TIMEOUT);
1073  timeout_ms = unpack_timeout(value);
1074  g_hash_table_replace(action->meta, strdup(XML_ATTR_TIMEOUT),
1075  pcmk__itoa(timeout_ms));
1076 
1077  if (!pcmk__strcase_any_of(action->task, RSC_START, RSC_PROMOTE, NULL)) {
1078  action->needs = rsc_req_nothing;
1079  value = "nothing (not start or promote)";
1080 
1081  } else if (pcmk_is_set(action->rsc->flags, pe_rsc_needs_fencing)) {
1082  action->needs = rsc_req_stonith;
1083  value = "fencing";
1084 
1085  } else if (pcmk_is_set(action->rsc->flags, pe_rsc_needs_quorum)) {
1086  action->needs = rsc_req_quorum;
1087  value = "quorum";
1088 
1089  } else {
1090  action->needs = rsc_req_nothing;
1091  value = "nothing";
1092  }
1093  pe_rsc_trace(action->rsc, "%s requires %s", action->uuid, value);
1094 
1095  value = unpack_operation_on_fail(action);
1096 
1097  if (value == NULL) {
1098 
1099  } else if (pcmk__str_eq(value, "block", pcmk__str_casei)) {
1100  action->on_fail = action_fail_block;
1101  g_hash_table_insert(action->meta, strdup(XML_OP_ATTR_ON_FAIL), strdup("block"));
1102  value = "block"; // The above could destroy the original string
1103 
1104  } else if (pcmk__str_eq(value, "fence", pcmk__str_casei)) {
1105  action->on_fail = action_fail_fence;
1106  value = "node fencing";
1107 
1108  if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1109  pcmk__config_err("Resetting '" XML_OP_ATTR_ON_FAIL "' for "
1110  "operation '%s' to 'stop' because 'fence' is not "
1111  "valid when fencing is disabled", action->uuid);
1112  action->on_fail = action_fail_stop;
1113  action->fail_role = RSC_ROLE_STOPPED;
1114  value = "stop resource";
1115  }
1116 
1117  } else if (pcmk__str_eq(value, "standby", pcmk__str_casei)) {
1118  action->on_fail = action_fail_standby;
1119  value = "node standby";
1120 
1121  } else if (pcmk__strcase_any_of(value, "ignore", "nothing", NULL)) {
1122  action->on_fail = action_fail_ignore;
1123  value = "ignore";
1124 
1125  } else if (pcmk__str_eq(value, "migrate", pcmk__str_casei)) {
1126  action->on_fail = action_fail_migrate;
1127  value = "force migration";
1128 
1129  } else if (pcmk__str_eq(value, "stop", pcmk__str_casei)) {
1130  action->on_fail = action_fail_stop;
1131  action->fail_role = RSC_ROLE_STOPPED;
1132  value = "stop resource";
1133 
1134  } else if (pcmk__str_eq(value, "restart", pcmk__str_casei)) {
1135  action->on_fail = action_fail_recover;
1136  value = "restart (and possibly migrate)";
1137 
1138  } else if (pcmk__str_eq(value, "restart-container", pcmk__str_casei)) {
1139  if (container) {
1141  value = "restart container (and possibly migrate)";
1142 
1143  } else {
1144  value = NULL;
1145  }
1146 
1147  } else if (pcmk__str_eq(value, "demote", pcmk__str_casei)) {
1148  action->on_fail = action_fail_demote;
1149  value = "demote instance";
1150 
1151  } else {
1152  pe_err("Resource %s: Unknown failure type (%s)", action->rsc->id, value);
1153  value = NULL;
1154  }
1155 
1156  /* defaults */
1157  if (value == NULL && container) {
1159  value = "restart container (and possibly migrate) (default)";
1160 
1161  /* For remote nodes, ensure that any failure that results in dropping an
1162  * active connection to the node results in fencing of the node.
1163  *
1164  * There are only two action failures that don't result in fencing.
1165  * 1. probes - probe failures are expected.
1166  * 2. start - a start failure indicates that an active connection does not already
1167  * exist. The user can set op on-fail=fence if they really want to fence start
1168  * failures. */
1169  } else if (((value == NULL) || !pcmk_is_set(action->rsc->flags, pe_rsc_managed))
1170  && pe__resource_is_remote_conn(action->rsc, data_set)
1171  && !(pcmk__str_eq(action->task, CRMD_ACTION_STATUS, pcmk__str_casei)
1172  && (interval_ms == 0))
1173  && !pcmk__str_eq(action->task, CRMD_ACTION_START, pcmk__str_casei)) {
1174 
1175  if (!pcmk_is_set(action->rsc->flags, pe_rsc_managed)) {
1176  action->on_fail = action_fail_stop;
1177  action->fail_role = RSC_ROLE_STOPPED;
1178  value = "stop unmanaged remote node (enforcing default)";
1179 
1180  } else {
1181  if (pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1182  value = "fence remote node (default)";
1183  } else {
1184  value = "recover remote node connection (default)";
1185  }
1186 
1187  if (action->rsc->remote_reconnect_ms) {
1188  action->fail_role = RSC_ROLE_STOPPED;
1189  }
1191  }
1192 
1193  } else if (value == NULL && pcmk__str_eq(action->task, CRMD_ACTION_STOP, pcmk__str_casei)) {
1194  if (pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1195  action->on_fail = action_fail_fence;
1196  value = "resource fence (default)";
1197 
1198  } else {
1199  action->on_fail = action_fail_block;
1200  value = "resource block (default)";
1201  }
1202 
1203  } else if (value == NULL) {
1204  action->on_fail = action_fail_recover;
1205  value = "restart (and possibly migrate) (default)";
1206  }
1207 
1208  pe_rsc_trace(action->rsc, "%s failure handling: %s",
1209  action->uuid, value);
1210 
1211  value = NULL;
1212  if (xml_obj != NULL) {
1213  value = g_hash_table_lookup(action->meta, "role_after_failure");
1214  if (value) {
1216  "Support for role_after_failure is deprecated and will be removed in a future release");
1217  }
1218  }
1219  if (value != NULL && action->fail_role == RSC_ROLE_UNKNOWN) {
1220  action->fail_role = text2role(value);
1221  }
1222  /* defaults */
1223  if (action->fail_role == RSC_ROLE_UNKNOWN) {
1224  if (pcmk__str_eq(action->task, CRMD_ACTION_PROMOTE, pcmk__str_casei)) {
1225  action->fail_role = RSC_ROLE_UNPROMOTED;
1226  } else {
1227  action->fail_role = RSC_ROLE_STARTED;
1228  }
1229  }
1230  pe_rsc_trace(action->rsc, "%s failure results in: %s",
1231  action->uuid, role2text(action->fail_role));
1232 
1233  value = g_hash_table_lookup(action->meta, XML_OP_ATTR_START_DELAY);
1234  if (value) {
1235  unpack_start_delay(value, action->meta);
1236  } else {
1237  long long start_delay = 0;
1238 
1239  value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN);
1240  if (unpack_interval_origin(value, xml_obj, interval_ms, data_set->now,
1241  &start_delay)) {
1242  g_hash_table_replace(action->meta, strdup(XML_OP_ATTR_START_DELAY),
1243  crm_strdup_printf("%lld", start_delay));
1244  }
1245  }
1246 
1247 #if ENABLE_VERSIONED_ATTRS
1248  unpack_versioned_meta(rsc_details->versioned_meta, xml_obj, interval_ms,
1249  data_set->now);
1250 #endif
1251 }
1252 
1253 static xmlNode *
1254 find_rsc_op_entry_helper(pe_resource_t * rsc, const char *key, gboolean include_disabled)
1255 {
1256  guint interval_ms = 0;
1257  gboolean do_retry = TRUE;
1258  char *local_key = NULL;
1259  const char *name = NULL;
1260  const char *value = NULL;
1261  const char *interval_spec = NULL;
1262  char *match_key = NULL;
1263  xmlNode *op = NULL;
1264  xmlNode *operation = NULL;
1265 
1266  retry:
1267  for (operation = pcmk__xe_first_child(rsc->ops_xml); operation != NULL;
1268  operation = pcmk__xe_next(operation)) {
1269 
1270  if (pcmk__str_eq((const char *)operation->name, "op", pcmk__str_none)) {
1271  name = crm_element_value(operation, "name");
1272  interval_spec = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
1273  value = crm_element_value(operation, "enabled");
1274  if (!include_disabled && value && crm_is_true(value) == FALSE) {
1275  continue;
1276  }
1277 
1278  interval_ms = crm_parse_interval_spec(interval_spec);
1279  match_key = pcmk__op_key(rsc->id, name, interval_ms);
1280  if (pcmk__str_eq(key, match_key, pcmk__str_casei)) {
1281  op = operation;
1282  }
1283  free(match_key);
1284 
1285  if (rsc->clone_name) {
1286  match_key = pcmk__op_key(rsc->clone_name, name, interval_ms);
1287  if (pcmk__str_eq(key, match_key, pcmk__str_casei)) {
1288  op = operation;
1289  }
1290  free(match_key);
1291  }
1292 
1293  if (op != NULL) {
1294  free(local_key);
1295  return op;
1296  }
1297  }
1298  }
1299 
1300  free(local_key);
1301  if (do_retry == FALSE) {
1302  return NULL;
1303  }
1304 
1305  do_retry = FALSE;
1306  if (strstr(key, CRMD_ACTION_MIGRATE) || strstr(key, CRMD_ACTION_MIGRATED)) {
1307  local_key = pcmk__op_key(rsc->id, "migrate", 0);
1308  key = local_key;
1309  goto retry;
1310 
1311  } else if (strstr(key, "_notify_")) {
1312  local_key = pcmk__op_key(rsc->id, "notify", 0);
1313  key = local_key;
1314  goto retry;
1315  }
1316 
1317  return NULL;
1318 }
1319 
1320 xmlNode *
1321 find_rsc_op_entry(pe_resource_t * rsc, const char *key)
1322 {
1323  return find_rsc_op_entry_helper(rsc, key, FALSE);
1324 }
1325 
1326 /*
1327  * Used by the HashTable for-loop
1328  */
1329 void
1330 print_str_str(gpointer key, gpointer value, gpointer user_data)
1331 {
1332  crm_trace("%s%s %s ==> %s",
1333  user_data == NULL ? "" : (char *)user_data,
1334  user_data == NULL ? "" : ": ", (char *)key, (char *)value);
1335 }
1336 
1337 void
1339 {
1340  if (action == NULL) {
1341  return;
1342  }
1343  g_list_free_full(action->actions_before, free); /* pe_action_wrapper_t* */
1344  g_list_free_full(action->actions_after, free); /* pe_action_wrapper_t* */
1345  if (action->extra) {
1346  g_hash_table_destroy(action->extra);
1347  }
1348  if (action->meta) {
1349  g_hash_table_destroy(action->meta);
1350  }
1351 #if ENABLE_VERSIONED_ATTRS
1352  if (action->rsc) {
1353  pe_free_rsc_action_details(action);
1354  }
1355 #endif
1356  free(action->cancel_task);
1357  free(action->reason);
1358  free(action->task);
1359  free(action->uuid);
1360  free(action->node);
1361  free(action);
1362 }
1363 
1364 GList *
1365 find_recurring_actions(GList *input, pe_node_t * not_on_node)
1366 {
1367  const char *value = NULL;
1368  GList *result = NULL;
1369  GList *gIter = input;
1370 
1371  CRM_CHECK(input != NULL, return NULL);
1372 
1373  for (; gIter != NULL; gIter = gIter->next) {
1374  pe_action_t *action = (pe_action_t *) gIter->data;
1375 
1376  value = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL_MS);
1377  if (value == NULL) {
1378  /* skip */
1379  } else if (pcmk__str_eq(value, "0", pcmk__str_casei)) {
1380  /* skip */
1381  } else if (pcmk__str_eq(CRMD_ACTION_CANCEL, action->task, pcmk__str_casei)) {
1382  /* skip */
1383  } else if (not_on_node == NULL) {
1384  crm_trace("(null) Found: %s", action->uuid);
1385  result = g_list_prepend(result, action);
1386 
1387  } else if (action->node == NULL) {
1388  /* skip */
1389  } else if (action->node->details != not_on_node->details) {
1390  crm_trace("Found: %s", action->uuid);
1391  result = g_list_prepend(result, action);
1392  }
1393  }
1394 
1395  return result;
1396 }
1397 
1398 enum action_tasks
1399 get_complex_task(pe_resource_t * rsc, const char *name, gboolean allow_non_atomic)
1400 {
1401  enum action_tasks task = text2task(name);
1402 
1403  if (rsc == NULL) {
1404  return task;
1405 
1406  } else if (allow_non_atomic == FALSE || rsc->variant == pe_native) {
1407  switch (task) {
1408  case stopped_rsc:
1409  case started_rsc:
1410  case action_demoted:
1411  case action_promoted:
1412  crm_trace("Folding %s back into its atomic counterpart for %s", name, rsc->id);
1413  return task - 1;
1414  default:
1415  break;
1416  }
1417  }
1418  return task;
1419 }
1420 
1421 pe_action_t *
1422 find_first_action(GList *input, const char *uuid, const char *task, pe_node_t * on_node)
1423 {
1424  GList *gIter = NULL;
1425 
1426  CRM_CHECK(uuid || task, return NULL);
1427 
1428  for (gIter = input; gIter != NULL; gIter = gIter->next) {
1429  pe_action_t *action = (pe_action_t *) gIter->data;
1430 
1431  if (uuid != NULL && !pcmk__str_eq(uuid, action->uuid, pcmk__str_casei)) {
1432  continue;
1433 
1434  } else if (task != NULL && !pcmk__str_eq(task, action->task, pcmk__str_casei)) {
1435  continue;
1436 
1437  } else if (on_node == NULL) {
1438  return action;
1439 
1440  } else if (action->node == NULL) {
1441  continue;
1442 
1443  } else if (on_node->details == action->node->details) {
1444  return action;
1445  }
1446  }
1447 
1448  return NULL;
1449 }
1450 
1451 GList *
1452 find_actions(GList *input, const char *key, const pe_node_t *on_node)
1453 {
1454  GList *gIter = input;
1455  GList *result = NULL;
1456 
1457  CRM_CHECK(key != NULL, return NULL);
1458 
1459  for (; gIter != NULL; gIter = gIter->next) {
1460  pe_action_t *action = (pe_action_t *) gIter->data;
1461 
1462  if (!pcmk__str_eq(key, action->uuid, pcmk__str_casei)) {
1463  crm_trace("%s does not match action %s", key, action->uuid);
1464  continue;
1465 
1466  } else if (on_node == NULL) {
1467  crm_trace("Action %s matches (ignoring node)", key);
1468  result = g_list_prepend(result, action);
1469 
1470  } else if (action->node == NULL) {
1471  crm_trace("Action %s matches (unallocated, assigning to %s)",
1472  key, on_node->details->uname);
1473 
1474  action->node = pe__copy_node(on_node);
1475  result = g_list_prepend(result, action);
1476 
1477  } else if (on_node->details == action->node->details) {
1478  crm_trace("Action %s on %s matches", key, on_node->details->uname);
1479  result = g_list_prepend(result, action);
1480 
1481  } else {
1482  crm_trace("Action %s on node %s does not match requested node %s",
1483  key, action->node->details->uname,
1484  on_node->details->uname);
1485  }
1486  }
1487 
1488  return result;
1489 }
1490 
1491 GList *
1492 find_actions_exact(GList *input, const char *key, const pe_node_t *on_node)
1493 {
1494  GList *result = NULL;
1495 
1496  CRM_CHECK(key != NULL, return NULL);
1497 
1498  if (on_node == NULL) {
1499  crm_trace("Not searching for action %s because node not specified",
1500  key);
1501  return NULL;
1502  }
1503 
1504  for (GList *gIter = input; gIter != NULL; gIter = gIter->next) {
1505  pe_action_t *action = (pe_action_t *) gIter->data;
1506 
1507  if (action->node == NULL) {
1508  crm_trace("Skipping comparison of %s vs action %s without node",
1509  key, action->uuid);
1510 
1511  } else if (!pcmk__str_eq(key, action->uuid, pcmk__str_casei)) {
1512  crm_trace("Desired action %s doesn't match %s", key, action->uuid);
1513 
1514  } else if (!pcmk__str_eq(on_node->details->id, action->node->details->id, pcmk__str_casei)) {
1515  crm_trace("Action %s desired node ID %s doesn't match %s",
1516  key, on_node->details->id, action->node->details->id);
1517 
1518  } else {
1519  crm_trace("Action %s matches", key);
1520  result = g_list_prepend(result, action);
1521  }
1522  }
1523 
1524  return result;
1525 }
1526 
1539 GList *
1541  const char *task, bool require_node)
1542 {
1543  GList *result = NULL;
1544  char *key = pcmk__op_key(rsc->id, task, 0);
1545 
1546  if (require_node) {
1547  result = find_actions_exact(rsc->actions, key, node);
1548  } else {
1549  result = find_actions(rsc->actions, key, node);
1550  }
1551  free(key);
1552  return result;
1553 }
1554 
1555 static void
1556 resource_node_score(pe_resource_t * rsc, pe_node_t * node, int score, const char *tag)
1557 {
1558  pe_node_t *match = NULL;
1559 
1560  if ((rsc->exclusive_discover || (node->rsc_discover_mode == pe_discover_never))
1561  && pcmk__str_eq(tag, "symmetric_default", pcmk__str_casei)) {
1562  /* This string comparision may be fragile, but exclusive resources and
1563  * exclusive nodes should not have the symmetric_default constraint
1564  * applied to them.
1565  */
1566  return;
1567 
1568  } else if (rsc->children) {
1569  GList *gIter = rsc->children;
1570 
1571  for (; gIter != NULL; gIter = gIter->next) {
1572  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
1573 
1574  resource_node_score(child_rsc, node, score, tag);
1575  }
1576  }
1577 
1578  pe_rsc_trace(rsc, "Setting %s for %s on %s: %d", tag, rsc->id, node->details->uname, score);
1579  match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
1580  if (match == NULL) {
1581  match = pe__copy_node(node);
1582  g_hash_table_insert(rsc->allowed_nodes, (gpointer) match->details->id, match);
1583  }
1584  match->weight = pe__add_scores(match->weight, score);
1585 }
1586 
1587 void
1588 resource_location(pe_resource_t * rsc, pe_node_t * node, int score, const char *tag,
1589  pe_working_set_t * data_set)
1590 {
1591  if (node != NULL) {
1592  resource_node_score(rsc, node, score, tag);
1593 
1594  } else if (data_set != NULL) {
1595  GList *gIter = data_set->nodes;
1596 
1597  for (; gIter != NULL; gIter = gIter->next) {
1598  pe_node_t *node_iter = (pe_node_t *) gIter->data;
1599 
1600  resource_node_score(rsc, node_iter, score, tag);
1601  }
1602 
1603  } else {
1604  GHashTableIter iter;
1605  pe_node_t *node_iter = NULL;
1606 
1607  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1608  while (g_hash_table_iter_next(&iter, NULL, (void **)&node_iter)) {
1609  resource_node_score(rsc, node_iter, score, tag);
1610  }
1611  }
1612 
1613  if (node == NULL && score == -INFINITY) {
1614  if (rsc->allocated_to) {
1615  crm_info("Deallocating %s from %s", rsc->id, rsc->allocated_to->details->uname);
1616  free(rsc->allocated_to);
1617  rsc->allocated_to = NULL;
1618  }
1619  }
1620 }
1621 
1622 #define sort_return(an_int, why) do { \
1623  free(a_uuid); \
1624  free(b_uuid); \
1625  crm_trace("%s (%d) %c %s (%d) : %s", \
1626  a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \
1627  b_xml_id, b_call_id, why); \
1628  return an_int; \
1629  } while(0)
1630 
1631 gint
1632 sort_op_by_callid(gconstpointer a, gconstpointer b)
1633 {
1634  int a_call_id = -1;
1635  int b_call_id = -1;
1636 
1637  char *a_uuid = NULL;
1638  char *b_uuid = NULL;
1639 
1640  const xmlNode *xml_a = a;
1641  const xmlNode *xml_b = b;
1642 
1643  const char *a_xml_id = crm_element_value(xml_a, XML_ATTR_ID);
1644  const char *b_xml_id = crm_element_value(xml_b, XML_ATTR_ID);
1645 
1646  if (pcmk__str_eq(a_xml_id, b_xml_id, pcmk__str_casei)) {
1647  /* We have duplicate lrm_rsc_op entries in the status
1648  * section which is unlikely to be a good thing
1649  * - we can handle it easily enough, but we need to get
1650  * to the bottom of why it's happening.
1651  */
1652  pe_err("Duplicate lrm_rsc_op entries named %s", a_xml_id);
1653  sort_return(0, "duplicate");
1654  }
1655 
1656  crm_element_value_int(xml_a, XML_LRM_ATTR_CALLID, &a_call_id);
1657  crm_element_value_int(xml_b, XML_LRM_ATTR_CALLID, &b_call_id);
1658 
1659  if (a_call_id == -1 && b_call_id == -1) {
1660  /* both are pending ops so it doesn't matter since
1661  * stops are never pending
1662  */
1663  sort_return(0, "pending");
1664 
1665  } else if (a_call_id >= 0 && a_call_id < b_call_id) {
1666  sort_return(-1, "call id");
1667 
1668  } else if (b_call_id >= 0 && a_call_id > b_call_id) {
1669  sort_return(1, "call id");
1670 
1671  } else if (b_call_id >= 0 && a_call_id == b_call_id) {
1672  /*
1673  * The op and last_failed_op are the same
1674  * Order on last-rc-change
1675  */
1676  time_t last_a = -1;
1677  time_t last_b = -1;
1678 
1681 
1682  crm_trace("rc-change: %lld vs %lld",
1683  (long long) last_a, (long long) last_b);
1684  if (last_a >= 0 && last_a < last_b) {
1685  sort_return(-1, "rc-change");
1686 
1687  } else if (last_b >= 0 && last_a > last_b) {
1688  sort_return(1, "rc-change");
1689  }
1690  sort_return(0, "rc-change");
1691 
1692  } else {
1693  /* One of the inputs is a pending operation
1694  * Attempt to use XML_ATTR_TRANSITION_MAGIC to determine its age relative to the other
1695  */
1696 
1697  int a_id = -1;
1698  int b_id = -1;
1699 
1700  const char *a_magic = crm_element_value(xml_a, XML_ATTR_TRANSITION_MAGIC);
1701  const char *b_magic = crm_element_value(xml_b, XML_ATTR_TRANSITION_MAGIC);
1702 
1703  CRM_CHECK(a_magic != NULL && b_magic != NULL, sort_return(0, "No magic"));
1704  if (!decode_transition_magic(a_magic, &a_uuid, &a_id, NULL, NULL, NULL,
1705  NULL)) {
1706  sort_return(0, "bad magic a");
1707  }
1708  if (!decode_transition_magic(b_magic, &b_uuid, &b_id, NULL, NULL, NULL,
1709  NULL)) {
1710  sort_return(0, "bad magic b");
1711  }
1712  /* try to determine the relative age of the operation...
1713  * some pending operations (e.g. a start) may have been superseded
1714  * by a subsequent stop
1715  *
1716  * [a|b]_id == -1 means it's a shutdown operation and _always_ comes last
1717  */
1718  if (!pcmk__str_eq(a_uuid, b_uuid, pcmk__str_casei) || a_id == b_id) {
1719  /*
1720  * some of the logic in here may be redundant...
1721  *
1722  * if the UUID from the TE doesn't match then one better
1723  * be a pending operation.
1724  * pending operations don't survive between elections and joins
1725  * because we query the LRM directly
1726  */
1727 
1728  if (b_call_id == -1) {
1729  sort_return(-1, "transition + call");
1730 
1731  } else if (a_call_id == -1) {
1732  sort_return(1, "transition + call");
1733  }
1734 
1735  } else if ((a_id >= 0 && a_id < b_id) || b_id == -1) {
1736  sort_return(-1, "transition");
1737 
1738  } else if ((b_id >= 0 && a_id > b_id) || a_id == -1) {
1739  sort_return(1, "transition");
1740  }
1741  }
1742 
1743  /* we should never end up here */
1744  CRM_CHECK(FALSE, sort_return(0, "default"));
1745 
1746 }
1747 
1748 time_t
1750 {
1751  if(data_set) {
1752  if (data_set->now == NULL) {
1753  crm_trace("Recording a new 'now'");
1754  data_set->now = crm_time_new(NULL);
1755  }
1756  return crm_time_get_seconds_since_epoch(data_set->now);
1757  }
1758 
1759  crm_trace("Defaulting to 'now'");
1760  return time(NULL);
1761 }
1762 
1763 gboolean
1765 {
1766  enum rsc_role_e local_role = RSC_ROLE_UNKNOWN;
1767  const char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
1768 
1769  CRM_CHECK(role != NULL, return FALSE);
1770 
1771  if (pcmk__str_eq(value, "started", pcmk__str_null_matches | pcmk__str_casei)
1772  || pcmk__str_eq("default", value, pcmk__str_casei)) {
1773  return FALSE;
1774  }
1775 
1776  local_role = text2role(value);
1777  if (local_role == RSC_ROLE_UNKNOWN) {
1778  pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
1779  "because '%s' is not valid", rsc->id, value);
1780  return FALSE;
1781 
1782  } else if (local_role > RSC_ROLE_STARTED) {
1784  if (local_role > RSC_ROLE_UNPROMOTED) {
1785  /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */
1786  return FALSE;
1787  }
1788 
1789  } else {
1790  pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
1791  "because '%s' only makes sense for promotable "
1792  "clones", rsc->id, value);
1793  return FALSE;
1794  }
1795  }
1796 
1797  *role = local_role;
1798  return TRUE;
1799 }
1800 
1801 gboolean
1802 order_actions(pe_action_t * lh_action, pe_action_t * rh_action, enum pe_ordering order)
1803 {
1804  GList *gIter = NULL;
1805  pe_action_wrapper_t *wrapper = NULL;
1806  GList *list = NULL;
1807 
1808  if (order == pe_order_none) {
1809  return FALSE;
1810  }
1811 
1812  if (lh_action == NULL || rh_action == NULL) {
1813  return FALSE;
1814  }
1815 
1816  crm_trace("Ordering Action %s before %s", lh_action->uuid, rh_action->uuid);
1817 
1818  /* Ensure we never create a dependency on ourselves... it's happened */
1819  CRM_ASSERT(lh_action != rh_action);
1820 
1821  /* Filter dups, otherwise update_action_states() has too much work to do */
1822  gIter = lh_action->actions_after;
1823  for (; gIter != NULL; gIter = gIter->next) {
1824  pe_action_wrapper_t *after = (pe_action_wrapper_t *) gIter->data;
1825 
1826  if (after->action == rh_action && (after->type & order)) {
1827  return FALSE;
1828  }
1829  }
1830 
1831  wrapper = calloc(1, sizeof(pe_action_wrapper_t));
1832  wrapper->action = rh_action;
1833  wrapper->type = order;
1834  list = lh_action->actions_after;
1835  list = g_list_prepend(list, wrapper);
1836  lh_action->actions_after = list;
1837 
1838  wrapper = calloc(1, sizeof(pe_action_wrapper_t));
1839  wrapper->action = lh_action;
1840  wrapper->type = order;
1841  list = rh_action->actions_before;
1842  list = g_list_prepend(list, wrapper);
1843  rh_action->actions_before = list;
1844  return TRUE;
1845 }
1846 
1847 pe_action_t *
1848 get_pseudo_op(const char *name, pe_working_set_t * data_set)
1849 {
1850  pe_action_t *op = NULL;
1851 
1852  if(data_set->singletons) {
1853  op = g_hash_table_lookup(data_set->singletons, name);
1854  }
1855  if (op == NULL) {
1856  op = custom_action(NULL, strdup(name), name, NULL, TRUE, TRUE, data_set);
1858  }
1859 
1860  return op;
1861 }
1862 
1863 void
1865 {
1866  pe_ticket_t *ticket = data;
1867 
1868  if (ticket->state) {
1869  g_hash_table_destroy(ticket->state);
1870  }
1871  free(ticket->id);
1872  free(ticket);
1873 }
1874 
1875 pe_ticket_t *
1876 ticket_new(const char *ticket_id, pe_working_set_t * data_set)
1877 {
1878  pe_ticket_t *ticket = NULL;
1879 
1880  if (pcmk__str_empty(ticket_id)) {
1881  return NULL;
1882  }
1883 
1884  if (data_set->tickets == NULL) {
1885  data_set->tickets = pcmk__strkey_table(free, destroy_ticket);
1886  }
1887 
1888  ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
1889  if (ticket == NULL) {
1890 
1891  ticket = calloc(1, sizeof(pe_ticket_t));
1892  if (ticket == NULL) {
1893  crm_err("Cannot allocate ticket '%s'", ticket_id);
1894  return NULL;
1895  }
1896 
1897  crm_trace("Creaing ticket entry for %s", ticket_id);
1898 
1899  ticket->id = strdup(ticket_id);
1900  ticket->granted = FALSE;
1901  ticket->last_granted = -1;
1902  ticket->standby = FALSE;
1903  ticket->state = pcmk__strkey_table(free, free);
1904 
1905  g_hash_table_insert(data_set->tickets, strdup(ticket->id), ticket);
1906  }
1907 
1908  return ticket;
1909 }
1910 
1912 {
1913  if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
1914  return ID(rsc->xml);
1915  }
1916  return rsc->id;
1917 }
1918 
1919 void
1921 {
1922  pe__clear_resource_flags(rsc, flags);
1923  for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
1924  pe__clear_resource_flags_recursive((pe_resource_t *) gIter->data, flags);
1925  }
1926 }
1927 
1928 void
1930 {
1931  for (GList *lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
1932  pe_resource_t *r = (pe_resource_t *) lpc->data;
1934  }
1935 }
1936 
1937 void
1939 {
1940  pe__set_resource_flags(rsc, flags);
1941  for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
1942  pe__set_resource_flags_recursive((pe_resource_t *) gIter->data, flags);
1943  }
1944 }
1945 
1946 static GList *
1947 find_unfencing_devices(GList *candidates, GList *matches)
1948 {
1949  for (GList *gIter = candidates; gIter != NULL; gIter = gIter->next) {
1950  pe_resource_t *candidate = gIter->data;
1951  const char *provides = g_hash_table_lookup(candidate->meta,
1953  const char *requires = g_hash_table_lookup(candidate->meta, XML_RSC_ATTR_REQUIRES);
1954 
1955  if(candidate->children) {
1956  matches = find_unfencing_devices(candidate->children, matches);
1957  } else if (!pcmk_is_set(candidate->flags, pe_rsc_fence_device)) {
1958  continue;
1959 
1960  } else if (pcmk__str_eq(provides, "unfencing", pcmk__str_casei) || pcmk__str_eq(requires, "unfencing", pcmk__str_casei)) {
1961  matches = g_list_prepend(matches, candidate);
1962  }
1963  }
1964  return matches;
1965 }
1966 
1967 static int
1968 node_priority_fencing_delay(pe_node_t * node, pe_working_set_t * data_set)
1969 {
1970  int member_count = 0;
1971  int online_count = 0;
1972  int top_priority = 0;
1973  int lowest_priority = 0;
1974  GList *gIter = NULL;
1975 
1976  // `priority-fencing-delay` is disabled
1977  if (data_set->priority_fencing_delay <= 0) {
1978  return 0;
1979  }
1980 
1981  /* No need to request a delay if the fencing target is not a normal cluster
1982  * member, for example if it's a remote node or a guest node. */
1983  if (node->details->type != node_member) {
1984  return 0;
1985  }
1986 
1987  // No need to request a delay if the fencing target is in our partition
1988  if (node->details->online) {
1989  return 0;
1990  }
1991 
1992  for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1993  pe_node_t *n = gIter->data;
1994 
1995  if (n->details->type != node_member) {
1996  continue;
1997  }
1998 
1999  member_count ++;
2000 
2001  if (n->details->online) {
2002  online_count++;
2003  }
2004 
2005  if (member_count == 1
2006  || n->details->priority > top_priority) {
2007  top_priority = n->details->priority;
2008  }
2009 
2010  if (member_count == 1
2011  || n->details->priority < lowest_priority) {
2012  lowest_priority = n->details->priority;
2013  }
2014  }
2015 
2016  // No need to delay if we have more than half of the cluster members
2017  if (online_count > member_count / 2) {
2018  return 0;
2019  }
2020 
2021  /* All the nodes have equal priority.
2022  * Any configured corresponding `pcmk_delay_base/max` will be applied. */
2023  if (lowest_priority == top_priority) {
2024  return 0;
2025  }
2026 
2027  if (node->details->priority < top_priority) {
2028  return 0;
2029  }
2030 
2031  return data_set->priority_fencing_delay;
2032 }
2033 
2034 pe_action_t *
2035 pe_fence_op(pe_node_t * node, const char *op, bool optional, const char *reason,
2036  bool priority_delay, pe_working_set_t * data_set)
2037 {
2038  char *op_key = NULL;
2039  pe_action_t *stonith_op = NULL;
2040 
2041  if(op == NULL) {
2042  op = data_set->stonith_action;
2043  }
2044 
2045  op_key = crm_strdup_printf("%s-%s-%s", CRM_OP_FENCE, node->details->uname, op);
2046 
2047  if(data_set->singletons) {
2048  stonith_op = g_hash_table_lookup(data_set->singletons, op_key);
2049  }
2050 
2051  if(stonith_op == NULL) {
2052  stonith_op = custom_action(NULL, op_key, CRM_OP_FENCE, node, TRUE, TRUE, data_set);
2053 
2054  add_hash_param(stonith_op->meta, XML_LRM_ATTR_TARGET, node->details->uname);
2055  add_hash_param(stonith_op->meta, XML_LRM_ATTR_TARGET_UUID, node->details->id);
2056  add_hash_param(stonith_op->meta, "stonith_action", op);
2057 
2058  if (pe__is_guest_or_remote_node(node)
2059  && pcmk_is_set(data_set->flags, pe_flag_enable_unfencing)) {
2060  /* Extra work to detect device changes on remotes
2061  *
2062  * We may do this for all nodes in the future, but for now
2063  * the check_action_definition() based stuff works fine.
2064  */
2065  long max = 1024;
2066  long digests_all_offset = 0;
2067  long digests_secure_offset = 0;
2068 
2069  char *digests_all = calloc(max, sizeof(char));
2070  char *digests_secure = calloc(max, sizeof(char));
2071  GList *matches = find_unfencing_devices(data_set->resources, NULL);
2072 
2073  for (GList *gIter = matches; gIter != NULL; gIter = gIter->next) {
2074  pe_resource_t *match = gIter->data;
2075  const char *agent = g_hash_table_lookup(match->meta,
2076  XML_ATTR_TYPE);
2077  op_digest_cache_t *data = NULL;
2078 
2079  data = pe__compare_fencing_digest(match, agent, node, data_set);
2080  if(data->rc == RSC_DIGEST_ALL) {
2081  optional = FALSE;
2082  crm_notice("Unfencing %s (remote): because the definition of %s changed", node->details->uname, match->id);
2083  if (!pcmk__is_daemon && data_set->priv != NULL) {
2084  pcmk__output_t *out = data_set->priv;
2085  out->info(out, "notice: Unfencing %s (remote): because the definition of %s changed",
2086  node->details->uname, match->id);
2087  }
2088  }
2089 
2090  digests_all_offset += snprintf(
2091  digests_all+digests_all_offset, max-digests_all_offset,
2092  "%s:%s:%s,", match->id, agent, data->digest_all_calc);
2093 
2094  digests_secure_offset += snprintf(
2095  digests_secure+digests_secure_offset, max-digests_secure_offset,
2096  "%s:%s:%s,", match->id, agent, data->digest_secure_calc);
2097  }
2098  g_hash_table_insert(stonith_op->meta,
2099  strdup(XML_OP_ATTR_DIGESTS_ALL),
2100  digests_all);
2101  g_hash_table_insert(stonith_op->meta,
2103  digests_secure);
2104  }
2105 
2106  } else {
2107  free(op_key);
2108  }
2109 
2110  if (data_set->priority_fencing_delay > 0
2111 
2112  /* It's a suitable case where `priority-fencing-delay` applies.
2113  * At least add `priority-fencing-delay` field as an indicator. */
2114  && (priority_delay
2115 
2116  /* Re-calculate priority delay for the suitable case when
2117  * pe_fence_op() is called again by stage6() after node priority has
2118  * been actually calculated with native_add_running() */
2119  || g_hash_table_lookup(stonith_op->meta,
2121 
2122  /* Add `priority-fencing-delay` to the fencing op even if it's 0 for
2123  * the targeting node. So that it takes precedence over any possible
2124  * `pcmk_delay_base/max`.
2125  */
2126  char *delay_s = pcmk__itoa(node_priority_fencing_delay(node, data_set));
2127 
2128  g_hash_table_insert(stonith_op->meta,
2130  delay_s);
2131  }
2132 
2133  if(optional == FALSE && pe_can_fence(data_set, node)) {
2134  pe_action_required(stonith_op, NULL, reason);
2135  } else if(reason && stonith_op->reason == NULL) {
2136  stonith_op->reason = strdup(reason);
2137  }
2138 
2139  return stonith_op;
2140 }
2141 
2142 void
2144  pe_resource_t * rsc, pe_node_t *node, const char *reason, pe_action_t *dependency, pe_working_set_t * data_set)
2145 {
2146  if (!pcmk_is_set(data_set->flags, pe_flag_enable_unfencing)) {
2147  /* No resources require it */
2148  return;
2149 
2150  } else if ((rsc != NULL)
2151  && !pcmk_is_set(rsc->flags, pe_rsc_fence_device)) {
2152  /* Wasn't a stonith device */
2153  return;
2154 
2155  } else if(node
2156  && node->details->online
2157  && node->details->unclean == FALSE
2158  && node->details->shutdown == FALSE) {
2159  pe_action_t *unfence = pe_fence_op(node, "on", FALSE, reason, FALSE, data_set);
2160 
2161  if(dependency) {
2162  order_actions(unfence, dependency, pe_order_optional);
2163  }
2164 
2165  } else if(rsc) {
2166  GHashTableIter iter;
2167 
2168  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
2169  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
2170  if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
2171  trigger_unfencing(rsc, node, reason, dependency, data_set);
2172  }
2173  }
2174  }
2175 }
2176 
2177 gboolean
2178 add_tag_ref(GHashTable * tags, const char * tag_name, const char * obj_ref)
2179 {
2180  pe_tag_t *tag = NULL;
2181  GList *gIter = NULL;
2182  gboolean is_existing = FALSE;
2183 
2184  CRM_CHECK(tags && tag_name && obj_ref, return FALSE);
2185 
2186  tag = g_hash_table_lookup(tags, tag_name);
2187  if (tag == NULL) {
2188  tag = calloc(1, sizeof(pe_tag_t));
2189  if (tag == NULL) {
2190  return FALSE;
2191  }
2192  tag->id = strdup(tag_name);
2193  tag->refs = NULL;
2194  g_hash_table_insert(tags, strdup(tag_name), tag);
2195  }
2196 
2197  for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
2198  const char *existing_ref = (const char *) gIter->data;
2199 
2200  if (pcmk__str_eq(existing_ref, obj_ref, pcmk__str_none)){
2201  is_existing = TRUE;
2202  break;
2203  }
2204  }
2205 
2206  if (is_existing == FALSE) {
2207  tag->refs = g_list_append(tag->refs, strdup(obj_ref));
2208  crm_trace("Added: tag=%s ref=%s", tag->id, obj_ref);
2209  }
2210 
2211  return TRUE;
2212 }
2213 
2214 void pe_action_set_flag_reason(const char *function, long line,
2215  pe_action_t *action, pe_action_t *reason, const char *text,
2216  enum pe_action_flags flags, bool overwrite)
2217 {
2218  bool unset = FALSE;
2219  bool update = FALSE;
2220  const char *change = NULL;
2221 
2222  if (pcmk_is_set(flags, pe_action_runnable)) {
2223  unset = TRUE;
2224  change = "unrunnable";
2225  } else if (pcmk_is_set(flags, pe_action_optional)) {
2226  unset = TRUE;
2227  change = "required";
2228  } else if (pcmk_is_set(flags, pe_action_migrate_runnable)) {
2229  unset = TRUE;
2230  overwrite = TRUE;
2231  change = "unrunnable";
2232  } else if (pcmk_is_set(flags, pe_action_dangle)) {
2233  change = "dangling";
2234  } else if (pcmk_is_set(flags, pe_action_requires_any)) {
2235  change = "required";
2236  } else {
2237  crm_err("Unknown flag change to %x by %s: 0x%s",
2238  flags, action->uuid, (reason? reason->uuid : "0"));
2239  }
2240 
2241  if(unset) {
2242  if (pcmk_is_set(action->flags, flags)) {
2243  pe__clear_action_flags_as(function, line, action, flags);
2244  update = TRUE;
2245  }
2246 
2247  } else {
2248  if (!pcmk_is_set(action->flags, flags)) {
2249  pe__set_action_flags_as(function, line, action, flags);
2250  update = TRUE;
2251  }
2252  }
2253 
2254  if((change && update) || text) {
2255  char *reason_text = NULL;
2256  if(reason == NULL) {
2257  pe_action_set_reason(action, text, overwrite);
2258 
2259  } else if(reason->rsc == NULL) {
2260  reason_text = crm_strdup_printf("%s %s%c %s", change, reason->task, text?':':0, text?text:"");
2261  } else {
2262  reason_text = crm_strdup_printf("%s %s %s%c %s", change, reason->rsc->id, reason->task, text?':':0, text?text:"NA");
2263  }
2264 
2265  if(reason_text && action->rsc != reason->rsc) {
2266  pe_action_set_reason(action, reason_text, overwrite);
2267  }
2268  free(reason_text);
2269  }
2270  }
2271 
2272 void pe_action_set_reason(pe_action_t *action, const char *reason, bool overwrite)
2273 {
2274  if (action->reason != NULL && overwrite) {
2275  pe_rsc_trace(action->rsc, "Changing %s reason from '%s' to '%s'",
2276  action->uuid, action->reason, crm_str(reason));
2277  free(action->reason);
2278  } else if (action->reason == NULL) {
2279  pe_rsc_trace(action->rsc, "Set %s reason to '%s'",
2280  action->uuid, crm_str(reason));
2281  } else {
2282  // crm_assert(action->reason != NULL && !overwrite);
2283  return;
2284  }
2285 
2286  if (reason != NULL) {
2287  action->reason = strdup(reason);
2288  } else {
2289  action->reason = NULL;
2290  }
2291 }
2292 
2305 bool
2307 {
2308  const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
2309 
2310  return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches);
2311 }
2312 
2320 void
2321 pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
2322 {
2323  if ((recheck > get_effective_time(data_set))
2324  && ((data_set->recheck_by == 0)
2325  || (data_set->recheck_by > recheck))) {
2326  data_set->recheck_by = recheck;
2327  }
2328 }
2329 
2334 void
2335 pe__unpack_dataset_nvpairs(xmlNode *xml_obj, const char *set_name,
2336  pe_rule_eval_data_t *rule_data, GHashTable *hash,
2337  const char *always_first, gboolean overwrite,
2338  pe_working_set_t *data_set)
2339 {
2340  crm_time_t *next_change = crm_time_new_undefined();
2341 
2342  pe_eval_nvpairs(data_set->input, xml_obj, set_name, rule_data, hash,
2343  always_first, overwrite, next_change);
2344  if (crm_time_is_defined(next_change)) {
2345  time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
2346 
2347  pe__update_recheck_time(recheck, data_set);
2348  }
2349  crm_time_free(next_change);
2350 }
2351 
2352 bool
2354 {
2355  const char *target_role = NULL;
2356 
2357  CRM_CHECK(rsc != NULL, return false);
2358  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
2359  if (target_role) {
2360  enum rsc_role_e target_role_e = text2role(target_role);
2361 
2362  if ((target_role_e == RSC_ROLE_STOPPED)
2363  || ((target_role_e == RSC_ROLE_UNPROMOTED)
2365  return true;
2366  }
2367  }
2368  return false;
2369 }
2370 
2380 pe_action_t *
2382  pe_working_set_t *data_set)
2383 {
2384  char *key = NULL;
2385 
2386  CRM_ASSERT(rsc && node);
2387  key = pcmk__op_key(rsc->id, CRM_OP_LRM_DELETE, 0);
2388  return custom_action(rsc, key, CRM_OP_LRM_DELETE, node, FALSE, TRUE,
2389  data_set);
2390 }
2391 
2392 bool
2394 {
2395  for (GList *ele = rsc->running_on; ele; ele = ele->next) {
2396  pe_node_t *node = (pe_node_t *) ele->data;
2397  if (pcmk__str_in_list(node_list, node->details->uname)) {
2398  return true;
2399  }
2400  }
2401 
2402  return false;
2403 }
2404 
2405 bool
2407 {
2408  return (rsc->fns->active(rsc, FALSE) && !pe__rsc_running_on_any_node_in_list(rsc, only_node));
2409 }
2410 
2411 GList *
2412 pe__filter_rsc_list(GList *rscs, GList *filter)
2413 {
2414  GList *retval = NULL;
2415 
2416  for (GList *gIter = rscs; gIter; gIter = gIter->next) {
2417  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2418 
2419  /* I think the second condition is safe here for all callers of this
2420  * function. If not, it needs to move into pe__node_text.
2421  */
2422  if (pcmk__str_in_list(filter, rsc_printable_id(rsc)) ||
2423  (rsc->parent && pcmk__str_in_list(filter, rsc_printable_id(rsc->parent)))) {
2424  retval = g_list_prepend(retval, rsc);
2425  }
2426  }
2427 
2428  return retval;
2429 }
2430 
2431 GList *
2432 pe__build_node_name_list(pe_working_set_t *data_set, const char *s) {
2433  GList *nodes = NULL;
2434 
2435  if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
2436  /* Nothing was given so return a list of all node names. Or, '*' was
2437  * given. This would normally fall into the pe__unames_with_tag branch
2438  * where it will return an empty list. Catch it here instead.
2439  */
2440  nodes = g_list_prepend(nodes, strdup("*"));
2441  } else {
2442  pe_node_t *node = pe_find_node(data_set->nodes, s);
2443 
2444  if (node) {
2445  /* The given string was a valid uname for a node. Return a
2446  * singleton list containing just that uname.
2447  */
2448  nodes = g_list_prepend(nodes, strdup(s));
2449  } else {
2450  /* The given string was not a valid uname. It's either a tag or
2451  * it's a typo or something. In the first case, we'll return a
2452  * list of all the unames of the nodes with the given tag. In the
2453  * second case, we'll return a NULL pointer and nothing will
2454  * get displayed.
2455  */
2456  nodes = pe__unames_with_tag(data_set, s);
2457  }
2458  }
2459 
2460  return nodes;
2461 }
2462 
2463 GList *
2464 pe__build_rsc_list(pe_working_set_t *data_set, const char *s) {
2465  GList *resources = NULL;
2466 
2467  if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
2468  resources = g_list_prepend(resources, strdup("*"));
2469  } else {
2472 
2473  if (rsc) {
2474  /* A colon in the name we were given means we're being asked to filter
2475  * on a specific instance of a cloned resource. Put that exact string
2476  * into the filter list. Otherwise, use the printable ID of whatever
2477  * resource was found that matches what was asked for.
2478  */
2479  if (strstr(s, ":") != NULL) {
2480  resources = g_list_prepend(resources, strdup(rsc->id));
2481  } else {
2482  resources = g_list_prepend(resources, strdup(rsc_printable_id(rsc)));
2483  }
2484  } else {
2485  /* The given string was not a valid resource name. It's either
2486  * a tag or it's a typo or something. See build_uname_list for
2487  * more detail.
2488  */
2489  resources = pe__rscs_with_tag(data_set, s);
2490  }
2491  }
2492 
2493  return resources;
2494 }
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition: iso8601.c:117
#define XML_OP_ATTR_ORIGIN
Definition: msg_xml.h:257
#define LOG_TRACE
Definition: logging.h:36
#define pe_rsc_starting
Definition: pe_types.h:271
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:218
#define pe__clear_action_flags_as(function, line, action, flags_to_clear)
Definition: internal.h:102
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:317
pe_node_t * pe_find_node(GList *node_list, const char *uname)
Definition: status.c:434
enum rsc_start_requirement needs
Definition: pe_types.h:419
pe_quorum_policy
Definition: pe_types.h:62
void pe__clear_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
Definition: utils.c:1920
enum pe_quorum_policy no_quorum_policy
Definition: pe_types.h:149
A dumping ground.
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: operations.c:185
GHashTable * pe__node_list2table(GList *list)
Definition: utils.c:204
#define crm_notice(fmt, args...)
Definition: logging.h:352
#define CRMD_ACTION_MIGRATED
Definition: crm.h:174
xmlNode * ops_xml
Definition: pe_types.h:324
pe_resource_t * pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
Definition: status.c:388
bool pe__is_guest_or_remote_node(const pe_node_t *node)
Definition: remote.c:41
GHashTable * attrs
Definition: pe_types.h:234
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:19
gboolean fixed
Definition: pe_types.h:242
char data[0]
Definition: cpg.c:55
#define INFINITY
Definition: crm.h:99
gint sort_rsc_priority(gconstpointer a, gconstpointer b)
Definition: utils.c:362
#define XML_OP_ATTR_DIGESTS_ALL
Definition: msg_xml.h:259
GList * find_recurring_actions(GList *input, pe_node_t *not_on_node)
Definition: utils.c:1365
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:59
gint sort_rsc_index(gconstpointer a, gconstpointer b)
Definition: utils.c:335
#define CRM_OP_FENCE
Definition: crm.h:145
#define XML_EXPR_ATTR_TYPE
Definition: msg_xml.h:342
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:398
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
Definition: iso8601.c:133
GHashTable * state
Definition: pe_types.h:460
#define PCMK_STONITH_PROVIDES
Definition: agents.h:36
pe_resource_t * container
Definition: pe_types.h:379
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:929
void pe_eval_nvpairs(xmlNode *top, xmlNode *xml_obj, const char *set_name, pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *next_change)
Definition: rules.c:605
GList * pe__build_rsc_list(pe_working_set_t *data_set, const char *s)
Definition: utils.c:2464
#define XML_ATTR_TYPE
Definition: msg_xml.h:132
#define XML_CONFIG_ATTR_PRIORITY_FENCING_DELAY
Definition: msg_xml.h:389
struct crm_time_s crm_time_t
Definition: iso8601.h:32
void pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
Definition: utils.c:2321
enum rsc_role_e role
Definition: pe_types.h:369
GList * children
Definition: pe_types.h:376
gboolean standby
Definition: pe_types.h:459
GList * find_actions(GList *input, const char *key, const pe_node_t *on_node)
Definition: utils.c:1452
int priority_fencing_delay
Definition: pe_types.h:190
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
Definition: cib_utils.c:146
xmlNode * op_defaults
Definition: pe_types.h:166
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2790
#define pe_action_required(action, reason, text)
Definition: internal.h:523
xmlNode * xml
Definition: pe_types.h:322
gboolean pcmk__str_in_list(GList *lst, const gchar *s)
Definition: strings.c:881
pe_resource_t * rsc
Definition: pe_types.h:409
enum rsc_role_e next_role
Definition: pe_types.h:370
enum action_fail_response on_fail
Definition: pe_types.h:420
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:432
gboolean exclusive_discover
Definition: pe_types.h:351
#define pcmk__config_err(fmt...)
pe_resource_t * remote_rsc
Definition: pe_types.h:230
char * cancel_task
Definition: pe_types.h:415
long long crm_get_msec(const char *input)
Parse a time+units string and return milliseconds equivalent.
Definition: strings.c:363
GHashTable * meta
Definition: pe_types.h:372
#define pe_rsc_unique
Definition: pe_types.h:254
char * score2char_stack(int score, char *buf, size_t len)
Definition: utils.c:101
resource_object_functions_t * fns
Definition: pe_types.h:331
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:291
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:2214
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:324
pe_node_t * pe__copy_node(const pe_node_t *this_node)
Definition: utils.c:142
#define XML_ATTR_TIMEOUT
Definition: msg_xml.h:123
#define CRMD_ACTION_PROMOTE
Definition: crm.h:182
int(* message)(pcmk__output_t *out, const char *message_id,...)
gboolean pending
Definition: pe_types.h:216
#define XML_NVPAIR_ATTR_NAME
Definition: msg_xml.h:377
void node_list_exclude(GHashTable *list, GList *list2, gboolean merge_scores)
Definition: utils.c:161
#define XML_OP_ATTR_DIGESTS_SECURE
Definition: msg_xml.h:260
char * id
Definition: pe_types.h:464
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
Definition: utils.c:1632
#define RSC_ROLE_PROMOTED_LEGACY_S
Definition: common.h:116
#define pcmk__log_else(level, else_action)
enum action_tasks text2task(const char *task)
Definition: common.c:354
time_t get_effective_time(pe_working_set_t *data_set)
Definition: utils.c:1749
GList * actions
Definition: pe_types.h:164
void resource_location(pe_resource_t *rsc, pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1588
xmlNode * op_entry
Definition: pe_types.h:411
#define RSC_START
Definition: crm.h:201
GHashTable * tickets
Definition: pe_types.h:152
pe_node_t * allocated_to
Definition: pe_types.h:362
#define XML_OP_ATTR_ON_FAIL
Definition: msg_xml.h:254
pe_action_t * action
Definition: pe_types.h:533
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:566
#define pe_flag_have_quorum
Definition: pe_types.h:94
gboolean remote_requires_reset
Definition: pe_types.h:224
char * reason
Definition: pe_types.h:416
void * action_details
Definition: pe_types.h:452
const char * action
Definition: pcmk_fence.c:30
GList * pe__rscs_with_tag(pe_working_set_t *data_set, const char *tag_name)
Definition: tags.c:20
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:47
GList * resources
Definition: pe_types.h:158
void trigger_unfencing(pe_resource_t *rsc, pe_node_t *node, const char *reason, pe_action_t *dependency, pe_working_set_t *data_set)
Definition: utils.c:2143
GHashTable * extra
Definition: pe_types.h:424
GList * nodes
Definition: pe_types.h:157
void pe__unpack_dataset_nvpairs(xmlNode *xml_obj, const char *set_name, pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, pe_working_set_t *data_set)
Definition: utils.c:2335
#define CRMD_ACTION_START
Definition: crm.h:176
GList * pe__filter_rsc_list(GList *rscs, GList *filter)
Definition: utils.c:2412
gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data)
void pe__set_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
Definition: utils.c:1938
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:203
const char * role2text(enum rsc_role_e role)
Definition: common.c:459
#define CRMD_ACTION_STOP
Definition: crm.h:179
#define pe_warn(fmt...)
Definition: internal.h:27
int weight
Definition: pe_types.h:241
guint remote_reconnect_ms
Definition: pe_types.h:344
#define CRMD_ACTION_DEMOTE
Definition: crm.h:184
void pe_action_set_reason(pe_action_t *action, const char *reason, bool overwrite)
Definition: utils.c:2272
#define XML_RSC_ATTR_REQUIRES
Definition: msg_xml.h:240
pe_action_flags
Definition: pe_types.h:291
#define XML_ATTR_OP
Definition: msg_xml.h:134
pe_action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
Definition: utils.c:1848
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:903
#define XML_CIB_ATTR_SHUTDOWN
Definition: msg_xml.h:283
Utility functions.
#define XML_ATTR_ID
Definition: msg_xml.h:129
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:530
bool pe__is_guest_node(const pe_node_t *node)
Definition: remote.c:33
char * digest_all_calc
Definition: internal.h:500
#define pe_warn_once(pe_wo_bit, fmt...)
Definition: internal.h:154
pe_ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
Definition: utils.c:1876
char * task
Definition: pe_types.h:413
#define sort_return(an_int, why)
Definition: utils.c:1622
GList * actions_after
Definition: pe_types.h:447
#define pe__clear_action_flags(action, flags_to_clear)
Definition: internal.h:68
#define crm_trace(fmt, args...)
Definition: logging.h:356
enum action_tasks get_complex_task(pe_resource_t *rsc, const char *name, gboolean allow_non_atomic)
Definition: utils.c:1399
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:159
enum rsc_digest_cmp_val rc
Definition: internal.h:496
void pe_fence_node(pe_working_set_t *data_set, pe_node_t *node, const char *reason, bool priority_delay)
Schedule a fence action for a node.
Definition: unpack.c:97
char * digest_secure_calc
Definition: internal.h:501
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
GHashTable * meta
Definition: pe_types.h:423
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:114
const char * stonith_action
Definition: pe_types.h:143
struct pe_node_shared_s * details
Definition: pe_types.h:244
gboolean get_target_role(pe_resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:1764
#define XML_TAG_OP_VER_META
Definition: msg_xml.h:208
pe_node_t * node
Definition: pe_types.h:410
bool pe__shutdown_requested(pe_node_t *node)
Definition: utils.c:2306
const char * op_name
Definition: common.h:179
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:267
#define pe_rsc_needs_fencing
Definition: pe_types.h:280
bool pcmk__is_daemon
Definition: logging.c:47
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition: utils.c:1802
unsigned long long flags
Definition: pe_types.h:347
const char * uname
Definition: pe_types.h:209
#define pe_rsc_promotable
Definition: pe_types.h:256
GHashTable * pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Get a table of resource parameters.
Definition: complex.c:457
#define XML_TAG_META_SETS
Definition: msg_xml.h:204
Wrappers for and extensions to libxml2.
Internal state tracking when creating graph.
Definition: pe_types.h:315
char * clone_name
Definition: pe_types.h:321
xmlNode * find_rsc_op_entry(pe_resource_t *rsc, const char *key)
Definition: utils.c:1321
gboolean add_tag_ref(GHashTable *tags, const char *tag_name, const char *obj_ref)
Definition: utils.c:2178
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
long long int crm_time_get_seconds_since_epoch(crm_time_t *dt)
Definition: iso8601.c:351
time_t recheck_by
Definition: pe_types.h:187
#define pe_flag_stonith_enabled
Definition: pe_types.h:98
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
Definition: nvpair.c:651
const char * pe_node_attribute_raw(pe_node_t *node, const char *name)
Definition: common.c:635
GList * actions
Definition: pe_types.h:358
#define CRM_DEFAULT_OP_TIMEOUT_S
Definition: util.h:73
time_t last_granted
Definition: pe_types.h:458
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:233
char * uuid
Definition: pe_types.h:414
void free_xml(xmlNode *child)
Definition: xml.c:823
match base name of any clone instance
Definition: pe_types.h:89
enum rsc_role_e text2role(const char *role)
Definition: common.c:488
op_digest_cache_t * pe__compare_fencing_digest(pe_resource_t *rsc, const char *agent, pe_node_t *node, pe_working_set_t *data_set)
Definition: pe_digest.c:520
enum pe_obj_types variant
Definition: pe_types.h:329
xmlNode * input
Definition: pe_types.h:137
int pe_get_configured_timeout(pe_resource_t *rsc, const char *action, pe_working_set_t *data_set)
Definition: utils.c:847
gboolean granted
Definition: pe_types.h:457
#define RSC_ROLE_PROMOTED_S
Definition: common.h:114
int rsc_discover_mode
Definition: pe_types.h:245
const char * id
Definition: pe_types.h:208
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition: operations.c:45
char * id
Definition: pe_types.h:456
#define XML_LRM_ATTR_TARGET_UUID
Definition: msg_xml.h:300
const char * crm_xml_add_ll(xmlNode *node, const char *name, long long value)
Create an XML attribute with specified name and long long int value.
Definition: nvpair.c:482
#define pe_rsc_fence_device
Definition: pe_types.h:255
long long int crm_time_get_seconds(crm_time_t *dt)
Definition: iso8601.c:308
pe_node_t * pe_find_node_id(GList *node_list, const char *id)
Definition: status.c:418
GList * refs
Definition: pe_types.h:465
bool pe_can_fence(pe_working_set_t *data_set, pe_node_t *node)
Definition: utils.c:90
match resource ID or LRM history ID
Definition: pe_types.h:84
GList * pe__build_node_name_list(pe_working_set_t *data_set, const char *s)
Definition: utils.c:2432
bool pcmk__rsc_filtered_by_node(pe_resource_t *rsc, GList *only_node)
Definition: utils.c:2406
const char * standard
Definition: common.h:173
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:610
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:579
int sort_index
Definition: pe_types.h:341
int pe__add_scores(int score1, int score2)
Definition: common.c:516
#define crm_err(fmt, args...)
Definition: logging.h:350
#define CRM_ASSERT(expr)
Definition: results.h:42
void pe__show_node_weights_as(const char *file, const char *function, int line, bool to_log, pe_resource_t *rsc, const char *comment, GHashTable *nodes, pe_working_set_t *data_set)
Definition: utils.c:304
#define RSC_STATUS
Definition: crm.h:215
GHashTable * node_hash
Definition: common.h:184
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition: utils.c:314
const char * rsc_printable_id(pe_resource_t *rsc)
Definition: utils.c:1911
#define RSC_PROMOTE
Definition: crm.h:207
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:93
bool pe__rsc_running_on_any_node_in_list(pe_resource_t *rsc, GList *node_list)
Definition: utils.c:2393
void pe__set_next_role(pe_resource_t *rsc, enum rsc_role_e role, const char *why)
Definition: complex.c:1116
This structure contains everything that makes up a single output formatter.
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:295
void pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
Definition: utils.c:1929
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:309
#define CRMD_ACTION_MIGRATE
Definition: crm.h:173
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:378
enum rsc_role_e fail_role
Definition: pe_types.h:421
gboolean shutdown
Definition: pe_types.h:219
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:53
#define crm_str(x)
Definition: logging.h:376
gboolean decode_transition_magic(const char *magic, char **uuid, int *transition_id, int *action_id, int *op_status, int *op_rc, int *target_rc)
Parse a transition magic string into its constituent parts.
Definition: operations.c:255
#define pe_rsc_stopping
Definition: pe_types.h:272
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition: strings.c:1019
rsc_role_e
Possible roles that a resource can be in.
Definition: common.h:92
GList * running_on
Definition: pe_types.h:365
enum pe_action_flags flags
Definition: pe_types.h:418
#define XML_OP_ATTR_START_DELAY
Definition: msg_xml.h:255
void destroy_ticket(gpointer data)
Definition: utils.c:1864
#define pe_rsc_needs_quorum
Definition: pe_types.h:279
bool pe__resource_is_remote_conn(const pe_resource_t *rsc, const pe_working_set_t *data_set)
Definition: remote.c:17
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition: agents.c:31
gboolean crm_is_true(const char *s)
Definition: strings.c:415
#define pe_flag_have_stonith_resource
Definition: pe_types.h:99
GList * find_actions_exact(GList *input, const char *key, const pe_node_t *on_node)
Definition: utils.c:1492
#define pe_flag_enable_unfencing
Definition: pe_types.h:100
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:299
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:20
gboolean(* active)(pe_resource_t *, gboolean)
Definition: pe_types.h:52
bool pe__resource_is_disabled(pe_resource_t *rsc)
Definition: utils.c:2353
GHashTable * singletons
Definition: pe_types.h:155
#define ID(x)
Definition: msg_xml.h:456
unsigned long long flags
Definition: pe_types.h:146
#define pe_err(fmt...)
Definition: internal.h:22
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
Definition: utils.c:1540
pe_action_t * pe__clear_resource_history(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
Definition: utils.c:2381
void print_str_str(gpointer key, gpointer value, gpointer user_data)
Definition: utils.c:1330
char * name
Definition: pcmk_fence.c:31
GList * pe__unames_with_tag(pe_working_set_t *data_set, const char *tag_name)
Definition: tags.c:51
#define CRM_OP_LRM_DELETE
Definition: crm.h:151
gint sort_node_uname(gconstpointer a, gconstpointer b)
Definition: utils.c:218
enum pe_ordering type
Definition: pe_types.h:531
gboolean unclean
Definition: pe_types.h:217
enum node_type type
Definition: pe_types.h:210
#define CRMD_ACTION_CANCEL
Definition: crm.h:169
crm_time_t * now
Definition: pe_types.h:138
#define crm_info(fmt, args...)
Definition: logging.h:353
#define pe_rsc_managed
Definition: pe_types.h:249
#define pe_rsc_orphan
Definition: pe_types.h:248
pe_action_t * find_first_action(GList *input, const char *uuid, const char *task, pe_node_t *on_node)
Definition: utils.c:1422
pe_ordering
Definition: pe_types.h:482
gboolean online
Definition: pe_types.h:213
uint64_t flags
Definition: remote.c:149
GList * actions_before
Definition: pe_types.h:446
#define XML_TAG_OP_VER_ATTRS
Definition: msg_xml.h:207
action_tasks
Definition: common.h:62
pe_resource_t * parent
Definition: pe_types.h:327
pe_action_t * pe_fence_op(pe_node_t *node, const char *op, bool optional, const char *reason, bool priority_delay, pe_working_set_t *data_set)
Definition: utils.c:2035
void pe_free_action(pe_action_t *action)
Definition: utils.c:1338
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:266
char * id
Definition: pe_types.h:320
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, pe_node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Definition: utils.c:415
GHashTable * allowed_nodes
Definition: pe_types.h:367
#define CRMD_ACTION_STATUS
Definition: crm.h:190
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2816
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:141
#define pe__set_action_flags_as(function, line, action, flags_to_set)
Definition: internal.h:93