pacemaker  1.1.14-70404b0
Scalable High-Availability cluster resource manager
utils.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 #include <crm_internal.h>
19 #include <crm/crm.h>
20 #include <crm/msg_xml.h>
21 #include <crm/common/xml.h>
22 #include <crm/common/util.h>
23 
24 #include <glib.h>
25 
26 #include <crm/pengine/rules.h>
27 #include <crm/pengine/internal.h>
28 
30 
31 extern xmlNode *get_object_root(const char *object_type, xmlNode * the_root);
32 void print_str_str(gpointer key, gpointer value, gpointer user_data);
33 gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
34 void unpack_operation(action_t * action, xmlNode * xml_obj, resource_t * container,
35  pe_working_set_t * data_set);
36 static xmlNode *find_rsc_op_entry_helper(resource_t * rsc, const char *key,
37  gboolean include_disabled);
38 static gboolean is_rsc_baremetal_remote_node(resource_t *rsc, pe_working_set_t * data_set);
39 
40 bool pe_can_fence(pe_working_set_t * data_set, node_t *node)
41 {
42  if(is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
43  return FALSE; /* Turned off */
44 
45  } else if (is_not_set(data_set->flags, pe_flag_have_stonith_resource)) {
46  return FALSE; /* No devices */
47 
48  } else if (is_set(data_set->flags, pe_flag_have_quorum)) {
49  return TRUE;
50 
51  } else if (data_set->no_quorum_policy == no_quorum_ignore) {
52  return TRUE;
53 
54  } else if(node == NULL) {
55  return FALSE;
56 
57  } else if(node->details->online) {
58  crm_notice("We can fence %s without quorum because they're in our membership", node->details->uname);
59  return TRUE;
60  }
61 
62  crm_trace("Cannot fence %s", node->details->uname);
63  return FALSE;
64 }
65 
66 node_t *
67 node_copy(node_t * this_node)
68 {
69  node_t *new_node = NULL;
70 
71  CRM_CHECK(this_node != NULL, return NULL);
72 
73  new_node = calloc(1, sizeof(node_t));
74  CRM_ASSERT(new_node != NULL);
75 
76  crm_trace("Copying %p (%s) to %p", this_node, this_node->details->uname, new_node);
77 
78  new_node->rsc_discover_mode = this_node->rsc_discover_mode;
79  new_node->weight = this_node->weight;
80  new_node->fixed = this_node->fixed;
81  new_node->details = this_node->details;
82 
83  return new_node;
84 }
85 
86 /* any node in list1 or list2 and not in the other gets a score of -INFINITY */
87 void
88 node_list_exclude(GHashTable * hash, GListPtr list, gboolean merge_scores)
89 {
90  GHashTable *result = hash;
91  node_t *other_node = NULL;
92  GListPtr gIter = list;
93 
94  GHashTableIter iter;
95  node_t *node = NULL;
96 
97  g_hash_table_iter_init(&iter, hash);
98  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
99 
100  other_node = pe_find_node_id(list, node->details->id);
101  if (other_node == NULL) {
102  node->weight = -INFINITY;
103  } else if (merge_scores) {
104  node->weight = merge_weights(node->weight, other_node->weight);
105  }
106  }
107 
108  for (; gIter != NULL; gIter = gIter->next) {
109  node_t *node = (node_t *) gIter->data;
110 
111  other_node = pe_hash_table_lookup(result, node->details->id);
112 
113  if (other_node == NULL) {
114  node_t *new_node = node_copy(node);
115 
116  new_node->weight = -INFINITY;
117  g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
118  }
119  }
120 }
121 
122 GHashTable *
124 {
125  GListPtr gIter = list;
126  GHashTable *result = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
127 
128  for (; gIter != NULL; gIter = gIter->next) {
129  node_t *node = (node_t *) gIter->data;
130  node_t *n = node_copy(node);
131 
132  g_hash_table_insert(result, (gpointer) n->details->id, n);
133  }
134 
135  return result;
136 }
137 
138 GListPtr
139 node_list_dup(GListPtr list1, gboolean reset, gboolean filter)
140 {
141  GListPtr result = NULL;
142  GListPtr gIter = list1;
143 
144  for (; gIter != NULL; gIter = gIter->next) {
145  node_t *new_node = NULL;
146  node_t *this_node = (node_t *) gIter->data;
147 
148  if (filter && this_node->weight < 0) {
149  continue;
150  }
151 
152  new_node = node_copy(this_node);
153  if (reset) {
154  new_node->weight = 0;
155  }
156  if (new_node != NULL) {
157  result = g_list_prepend(result, new_node);
158  }
159  }
160 
161  return result;
162 }
163 
164 gint
165 sort_node_uname(gconstpointer a, gconstpointer b)
166 {
167  const node_t *node_a = a;
168  const node_t *node_b = b;
169 
170  return strcmp(node_a->details->uname, node_b->details->uname);
171 }
172 
173 void
174 dump_node_scores_worker(int level, const char *file, const char *function, int line,
175  resource_t * rsc, const char *comment, GHashTable * nodes)
176 {
177  GHashTable *hash = nodes;
178  GHashTableIter iter;
179  node_t *node = NULL;
180 
181  if (rsc) {
182  hash = rsc->allowed_nodes;
183  }
184 
185  if (rsc && is_set(rsc->flags, pe_rsc_orphan)) {
186  /* Don't show the allocation scores for orphans */
187  return;
188  }
189 
190  if (level == 0) {
191  char score[128];
192  int len = sizeof(score);
193  /* For now we want this in sorted order to keep the regression tests happy */
194  GListPtr gIter = NULL;
195  GListPtr list = g_hash_table_get_values(hash);
196 
197  list = g_list_sort(list, sort_node_uname);
198 
199  gIter = list;
200  for (; gIter != NULL; gIter = gIter->next) {
201  node_t *node = (node_t *) gIter->data;
202  /* This function is called a whole lot, use stack allocated score */
203  score2char_stack(node->weight, score, len);
204 
205  if (rsc) {
206  printf("%s: %s allocation score on %s: %s\n",
207  comment, rsc->id, node->details->uname, score);
208  } else {
209  printf("%s: %s = %s\n", comment, node->details->uname, score);
210  }
211  }
212 
213  g_list_free(list);
214 
215  } else if (hash) {
216  char score[128];
217  int len = sizeof(score);
218  g_hash_table_iter_init(&iter, hash);
219  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
220  /* This function is called a whole lot, use stack allocated score */
221  score2char_stack(node->weight, score, len);
222 
223  if (rsc) {
224  do_crm_log_alias(LOG_TRACE, file, function, line,
225  "%s: %s allocation score on %s: %s", comment, rsc->id,
226  node->details->uname, score);
227  } else {
228  do_crm_log_alias(LOG_TRACE, file, function, line + 1, "%s: %s = %s", comment,
229  node->details->uname, score);
230  }
231  }
232  }
233 
234  if (rsc && rsc->children) {
235  GListPtr gIter = NULL;
236 
237  gIter = rsc->children;
238  for (; gIter != NULL; gIter = gIter->next) {
239  resource_t *child = (resource_t *) gIter->data;
240 
241  dump_node_scores_worker(level, file, function, line, child, comment, nodes);
242  }
243  }
244 }
245 
246 static void
247 append_dump_text(gpointer key, gpointer value, gpointer user_data)
248 {
249  char **dump_text = user_data;
250  int len = 0;
251  char *new_text = NULL;
252 
253  len = strlen(*dump_text) + strlen(" ") + strlen(key) + strlen("=") + strlen(value) + 1;
254  new_text = calloc(1, len);
255  sprintf(new_text, "%s %s=%s", *dump_text, (char *)key, (char *)value);
256 
257  free(*dump_text);
258  *dump_text = new_text;
259 }
260 
261 void
262 dump_node_capacity(int level, const char *comment, node_t * node)
263 {
264  int len = 0;
265  char *dump_text = NULL;
266 
267  len = strlen(comment) + strlen(": ") + strlen(node->details->uname) + strlen(" capacity:") + 1;
268  dump_text = calloc(1, len);
269  sprintf(dump_text, "%s: %s capacity:", comment, node->details->uname);
270 
271  g_hash_table_foreach(node->details->utilization, append_dump_text, &dump_text);
272 
273  if (level == 0) {
274  fprintf(stdout, "%s\n", dump_text);
275  } else {
276  crm_trace("%s", dump_text);
277  }
278 
279  free(dump_text);
280 }
281 
282 void
283 dump_rsc_utilization(int level, const char *comment, resource_t * rsc, node_t * node)
284 {
285  int len = 0;
286  char *dump_text = NULL;
287 
288  len = strlen(comment) + strlen(": ") + strlen(rsc->id) + strlen(" utilization on ")
289  + strlen(node->details->uname) + strlen(":") + 1;
290  dump_text = calloc(1, len);
291  sprintf(dump_text, "%s: %s utilization on %s:", comment, rsc->id, node->details->uname);
292 
293  g_hash_table_foreach(rsc->utilization, append_dump_text, &dump_text);
294 
295  if (level == 0) {
296  fprintf(stdout, "%s\n", dump_text);
297  } else {
298  crm_trace("%s", dump_text);
299  }
300 
301  free(dump_text);
302 }
303 
304 gint
305 sort_rsc_index(gconstpointer a, gconstpointer b)
306 {
307  const resource_t *resource1 = (const resource_t *)a;
308  const resource_t *resource2 = (const resource_t *)b;
309 
310  if (a == NULL && b == NULL) {
311  return 0;
312  }
313  if (a == NULL) {
314  return 1;
315  }
316  if (b == NULL) {
317  return -1;
318  }
319 
320  if (resource1->sort_index > resource2->sort_index) {
321  return -1;
322  }
323 
324  if (resource1->sort_index < resource2->sort_index) {
325  return 1;
326  }
327 
328  return 0;
329 }
330 
331 gint
332 sort_rsc_priority(gconstpointer a, gconstpointer b)
333 {
334  const resource_t *resource1 = (const resource_t *)a;
335  const resource_t *resource2 = (const resource_t *)b;
336 
337  if (a == NULL && b == NULL) {
338  return 0;
339  }
340  if (a == NULL) {
341  return 1;
342  }
343  if (b == NULL) {
344  return -1;
345  }
346 
347  if (resource1->priority > resource2->priority) {
348  return -1;
349  }
350 
351  if (resource1->priority < resource2->priority) {
352  return 1;
353  }
354 
355  return 0;
356 }
357 
358 action_t *
359 custom_action(resource_t * rsc, char *key, const char *task,
360  node_t * on_node, gboolean optional, gboolean save_action,
361  pe_working_set_t * data_set)
362 {
363  action_t *action = NULL;
364  GListPtr possible_matches = NULL;
365 
366  CRM_CHECK(key != NULL, return NULL);
367  CRM_CHECK(task != NULL, free(key); return NULL);
368 
369  if (save_action && rsc != NULL) {
370  possible_matches = find_actions(rsc->actions, key, on_node);
371  } else if(save_action) {
372 #if 0
373  action = g_hash_table_lookup(data_set->singletons, key);
374 #else
375  /* More expensive but takes 'node' into account */
376  possible_matches = find_actions(data_set->actions, key, on_node);
377 #endif
378  }
379 
380  if(data_set->singletons == NULL) {
381  data_set->singletons = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, NULL);
382  }
383 
384  if (possible_matches != NULL) {
385  if (g_list_length(possible_matches) > 1) {
386  pe_warn("Action %s for %s on %s exists %d times",
387  task, rsc ? rsc->id : "<NULL>",
388  on_node ? on_node->details->uname : "<NULL>", g_list_length(possible_matches));
389  }
390 
391  action = g_list_nth_data(possible_matches, 0);
392  pe_rsc_trace(rsc, "Found existing action (%d) %s for %s on %s",
393  action->id, task, rsc ? rsc->id : "<NULL>",
394  on_node ? on_node->details->uname : "<NULL>");
395  g_list_free(possible_matches);
396  }
397 
398  if (action == NULL) {
399  if (save_action) {
400  pe_rsc_trace(rsc, "Creating%s action %d: %s for %s on %s %d",
401  optional ? "" : " manditory", data_set->action_id, key,
402  rsc ? rsc->id : "<NULL>", on_node ? on_node->details->uname : "<NULL>", optional);
403  }
404 
405  action = calloc(1, sizeof(action_t));
406  if (save_action) {
407  action->id = data_set->action_id++;
408  } else {
409  action->id = 0;
410  }
411  action->rsc = rsc;
412  CRM_ASSERT(task != NULL);
413  action->task = strdup(task);
414  if (on_node) {
415  action->node = node_copy(on_node);
416  }
417  action->uuid = strdup(key);
418 
420  if (optional) {
421  pe_rsc_trace(rsc, "Set optional on %s", action->uuid);
423  } else {
425  pe_rsc_trace(rsc, "Unset optional on %s", action->uuid);
426  }
427 
428 /*
429  Implied by calloc()...
430  action->actions_before = NULL;
431  action->actions_after = NULL;
432 
433  action->pseudo = FALSE;
434  action->dumped = FALSE;
435  action->processed = FALSE;
436  action->seen_count = 0;
437 */
438 
439  action->extra = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
440 
441  action->meta = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
442 
443  if (save_action) {
444  data_set->actions = g_list_prepend(data_set->actions, action);
445  if(rsc == NULL) {
446  g_hash_table_insert(data_set->singletons, action->uuid, action);
447  }
448  }
449 
450  if (rsc != NULL) {
451  action->op_entry = find_rsc_op_entry_helper(rsc, key, TRUE);
452 
453  unpack_operation(action, action->op_entry, rsc->container, data_set);
454 
455  if (save_action) {
456  rsc->actions = g_list_prepend(rsc->actions, action);
457  }
458  }
459 
460  if (save_action) {
461  pe_rsc_trace(rsc, "Action %d created", action->id);
462  }
463  }
464 
465  if (optional == FALSE) {
466  pe_rsc_trace(rsc, "Unset optional on %s", action->uuid);
468  }
469 
470  if (rsc != NULL) {
471  enum action_tasks a_task = text2task(action->task);
472  int warn_level = LOG_TRACE;
473 
474  if (save_action) {
475  warn_level = LOG_WARNING;
476  }
477 
478  if (is_set(action->flags, pe_action_have_node_attrs) == FALSE
479  && action->node != NULL && action->op_entry != NULL) {
482  action->node->details->attrs,
483  action->extra, NULL, FALSE, data_set->now);
484  }
485 
486  if (is_set(action->flags, pe_action_pseudo)) {
487  /* leave untouched */
488 
489  } else if (action->node == NULL) {
490  pe_rsc_trace(rsc, "Unset runnable on %s", action->uuid);
492 
493  } else if (is_not_set(rsc->flags, pe_rsc_managed)
494  && g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL) == NULL) {
495  crm_debug("Action %s (unmanaged)", action->uuid);
496  pe_rsc_trace(rsc, "Set optional on %s", action->uuid);
498 /* action->runnable = FALSE; */
499 
500  } else if (action->node->details->online == FALSE) {
502  do_crm_log(warn_level, "Action %s on %s is unrunnable (offline)",
503  action->uuid, action->node->details->uname);
504  if (is_set(action->rsc->flags, pe_rsc_managed)
505  && save_action && a_task == stop_rsc) {
506  pe_fence_node(data_set, action->node, "Node is unclean");
507  }
508 
509  } else if (action->node->details->pending) {
511  do_crm_log(warn_level, "Action %s on %s is unrunnable (pending)",
512  action->uuid, action->node->details->uname);
513 
514  } else if (action->needs == rsc_req_nothing) {
515  pe_rsc_trace(rsc, "Action %s does not require anything", action->uuid);
517 #if 0
518  /*
519  * No point checking this
520  * - if we dont have quorum we can't stonith anyway
521  */
522  } else if (action->needs == rsc_req_stonith) {
523  crm_trace("Action %s requires only stonith", action->uuid);
524  action->runnable = TRUE;
525 #endif
526  } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE
527  && data_set->no_quorum_policy == no_quorum_stop) {
529  crm_debug("%s\t%s (cancelled : quorum)", action->node->details->uname, action->uuid);
530 
531  } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE
532  && data_set->no_quorum_policy == no_quorum_freeze) {
533  pe_rsc_trace(rsc, "Check resource is already active: %s %s %s %s", rsc->id, action->uuid, role2text(rsc->next_role), role2text(rsc->role));
534  if (rsc->fns->active(rsc, TRUE) == FALSE || rsc->next_role > rsc->role) {
536  pe_rsc_debug(rsc, "%s\t%s (cancelled : quorum freeze)",
537  action->node->details->uname, action->uuid);
538  }
539 
540  } else {
541  pe_rsc_trace(rsc, "Action %s is runnable", action->uuid);
543  }
544 
545  if (save_action) {
546  switch (a_task) {
547  case stop_rsc:
549  break;
550  case start_rsc:
552  if (is_set(action->flags, pe_action_runnable)) {
554  }
555  break;
556  default:
557  break;
558  }
559  }
560  }
561 
562  free(key);
563  return action;
564 }
565 
566 static const char *
567 unpack_operation_on_fail(action_t * action)
568 {
569 
570  const char *value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ON_FAIL);
571 
572  if (safe_str_eq(action->task, CRMD_ACTION_STOP) && safe_str_eq(value, "standby")) {
573  crm_config_err("on-fail=standby is not allowed for stop actions: %s", action->rsc->id);
574  return NULL;
575  } else if (safe_str_eq(action->task, CRMD_ACTION_DEMOTE) && !value) {
576  /* demote on_fail defaults to master monitor value if present */
577  xmlNode *operation = NULL;
578  const char *name = NULL;
579  const char *role = NULL;
580  const char *on_fail = NULL;
581  const char *interval = NULL;
582  const char *enabled = NULL;
583 
584  CRM_CHECK(action->rsc != NULL, return NULL);
585 
586  for (operation = __xml_first_child(action->rsc->ops_xml);
587  operation && !value; operation = __xml_next_element(operation)) {
588 
589  if (!crm_str_eq((const char *)operation->name, "op", TRUE)) {
590  continue;
591  }
592  name = crm_element_value(operation, "name");
593  role = crm_element_value(operation, "role");
594  on_fail = crm_element_value(operation, XML_OP_ATTR_ON_FAIL);
595  enabled = crm_element_value(operation, "enabled");
596  interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
597  if (!on_fail) {
598  continue;
599  } else if (enabled && !crm_is_true(enabled)) {
600  continue;
601  } else if (safe_str_neq(name, "monitor") || safe_str_neq(role, "Master")) {
602  continue;
603  } else if (crm_get_interval(interval) <= 0) {
604  continue;
605  }
606 
607  value = on_fail;
608  }
609  }
610 
611  return value;
612 }
613 
614 static xmlNode *
615 find_min_interval_mon(resource_t * rsc, gboolean include_disabled)
616 {
617  int number = 0;
618  int min_interval = -1;
619  const char *name = NULL;
620  const char *value = NULL;
621  const char *interval = NULL;
622  xmlNode *op = NULL;
623  xmlNode *operation = NULL;
624 
625  for (operation = __xml_first_child(rsc->ops_xml); operation != NULL;
626  operation = __xml_next_element(operation)) {
627 
628  if (crm_str_eq((const char *)operation->name, "op", TRUE)) {
629  name = crm_element_value(operation, "name");
630  interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
631  value = crm_element_value(operation, "enabled");
632  if (!include_disabled && value && crm_is_true(value) == FALSE) {
633  continue;
634  }
635 
636  if (safe_str_neq(name, RSC_STATUS)) {
637  continue;
638  }
639 
640  number = crm_get_interval(interval);
641  if (number < 0) {
642  continue;
643  }
644 
645  if (min_interval < 0 || number < min_interval) {
646  min_interval = number;
647  op = operation;
648  }
649  }
650  }
651 
652  return op;
653 }
654 
655 void
656 unpack_operation(action_t * action, xmlNode * xml_obj, resource_t * container,
657  pe_working_set_t * data_set)
658 {
659  int value_i = 0;
660  unsigned long long interval = 0;
661  unsigned long long start_delay = 0;
662  char *value_ms = NULL;
663  const char *value = NULL;
664  const char *field = NULL;
665 
666  CRM_CHECK(action->rsc != NULL, return);
667 
669  action->meta, NULL, FALSE, data_set->now);
670 
671  if (xml_obj) {
672  xmlAttrPtr xIter = NULL;
673 
674  for (xIter = xml_obj->properties; xIter; xIter = xIter->next) {
675  const char *prop_name = (const char *)xIter->name;
676  const char *prop_value = crm_element_value(xml_obj, prop_name);
677 
678  g_hash_table_replace(action->meta, strdup(prop_name), strdup(prop_value));
679  }
680  }
681 
683  NULL, action->meta, NULL, FALSE, data_set->now);
684 
686  NULL, action->meta, NULL, FALSE, data_set->now);
687  g_hash_table_remove(action->meta, "id");
688 
689  field = XML_LRM_ATTR_INTERVAL;
690  value = g_hash_table_lookup(action->meta, field);
691  if (value != NULL) {
692  interval = crm_get_interval(value);
693  if (interval > 0) {
694  value_ms = crm_itoa(interval);
695  g_hash_table_replace(action->meta, strdup(field), value_ms);
696 
697  } else {
698  g_hash_table_remove(action->meta, field);
699  }
700  }
701 
702  /* Begin compatability code */
703  value = g_hash_table_lookup(action->meta, "requires");
704 
705  if (safe_str_neq(action->task, RSC_START)
706  && safe_str_neq(action->task, RSC_PROMOTE)) {
707  action->needs = rsc_req_nothing;
708  value = "nothing (not start/promote)";
709 
710  } else if (safe_str_eq(value, "nothing")) {
711  action->needs = rsc_req_nothing;
712 
713  } else if (safe_str_eq(value, "quorum")) {
714  action->needs = rsc_req_quorum;
715 
716  } else if (safe_str_eq(value, "unfencing")) {
717  action->needs = rsc_req_stonith;
719  if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
720  crm_notice("%s requires (un)fencing but fencing is disabled", action->rsc->id);
721  }
722 
723  } else if (is_set(data_set->flags, pe_flag_stonith_enabled)
724  && safe_str_eq(value, "fencing")) {
725  action->needs = rsc_req_stonith;
726  if (is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
727  crm_notice("%s requires fencing but fencing is disabled", action->rsc->id);
728  }
729  /* End compatability code */
730 
731  } else if (is_set(action->rsc->flags, pe_rsc_needs_fencing)) {
732  action->needs = rsc_req_stonith;
733  value = "fencing (resource)";
734 
735  } else if (is_set(action->rsc->flags, pe_rsc_needs_quorum)) {
736  action->needs = rsc_req_quorum;
737  value = "quorum (resource)";
738 
739  } else {
740  action->needs = rsc_req_nothing;
741  value = "nothing (resource)";
742  }
743 
744  pe_rsc_trace(action->rsc, "\tAction %s requires: %s", action->task, value);
745 
746  value = unpack_operation_on_fail(action);
747 
748  if (value == NULL) {
749 
750  } else if (safe_str_eq(value, "block")) {
751  action->on_fail = action_fail_block;
752  g_hash_table_insert(action->meta, strdup(XML_OP_ATTR_ON_FAIL), strdup("block"));
753 
754  } else if (safe_str_eq(value, "fence")) {
755  action->on_fail = action_fail_fence;
756  value = "node fencing";
757 
758  if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) {
759  crm_config_err("Specifying on_fail=fence and" " stonith-enabled=false makes no sense");
760  action->on_fail = action_fail_stop;
761  action->fail_role = RSC_ROLE_STOPPED;
762  value = "stop resource";
763  }
764 
765  } else if (safe_str_eq(value, "standby")) {
766  action->on_fail = action_fail_standby;
767  value = "node standby";
768 
769  } else if (safe_str_eq(value, "ignore")
770  || safe_str_eq(value, "nothing")) {
771  action->on_fail = action_fail_ignore;
772  value = "ignore";
773 
774  } else if (safe_str_eq(value, "migrate")) {
775  action->on_fail = action_fail_migrate;
776  value = "force migration";
777 
778  } else if (safe_str_eq(value, "stop")) {
779  action->on_fail = action_fail_stop;
780  action->fail_role = RSC_ROLE_STOPPED;
781  value = "stop resource";
782 
783  } else if (safe_str_eq(value, "restart")) {
784  action->on_fail = action_fail_recover;
785  value = "restart (and possibly migrate)";
786 
787  } else if (safe_str_eq(value, "restart-container")) {
788  if (container) {
790  value = "restart container (and possibly migrate)";
791 
792  } else {
793  value = NULL;
794  }
795 
796  } else {
797  pe_err("Resource %s: Unknown failure type (%s)", action->rsc->id, value);
798  value = NULL;
799  }
800 
801  /* defaults */
802  if (value == NULL && container) {
804  value = "restart container (and possibly migrate) (default)";
805 
806  /* for barmetal remote nodes, ensure that any failure that results in
807  * dropping an active connection to a remote node results in fencing of
808  * the remote node.
809  *
810  * There are only two action failures that don't result in fencing.
811  * 1. probes - probe failures are expected.
812  * 2. start - a start failure indicates that an active connection does not already
813  * exist. The user can set op on-fail=fence if they really want to fence start
814  * failures. */
815  } else if (value == NULL &&
816  is_rsc_baremetal_remote_node(action->rsc, data_set) &&
817  !(safe_str_eq(action->task, CRMD_ACTION_STATUS) && interval == 0) &&
818  (safe_str_neq(action->task, CRMD_ACTION_START))) {
819 
820  if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
821  value = "fence baremetal remote node (default)";
822  } else {
823  value = "recover baremetal remote node connection (default)";
824  }
825  if (action->rsc->remote_reconnect_interval) {
826  action->fail_role = RSC_ROLE_STOPPED;
827  }
829 
830  } else if (value == NULL && safe_str_eq(action->task, CRMD_ACTION_STOP)) {
831  if (is_set(data_set->flags, pe_flag_stonith_enabled)) {
832  action->on_fail = action_fail_fence;
833  value = "resource fence (default)";
834 
835  } else {
836  action->on_fail = action_fail_block;
837  value = "resource block (default)";
838  }
839 
840  } else if (value == NULL) {
841  action->on_fail = action_fail_recover;
842  value = "restart (and possibly migrate) (default)";
843  }
844 
845  pe_rsc_trace(action->rsc, "\t%s failure handling: %s", action->task, value);
846 
847  value = NULL;
848  if (xml_obj != NULL) {
849  value = g_hash_table_lookup(action->meta, "role_after_failure");
850  }
851  if (value != NULL && action->fail_role == RSC_ROLE_UNKNOWN) {
852  action->fail_role = text2role(value);
853  }
854  /* defaults */
855  if (action->fail_role == RSC_ROLE_UNKNOWN) {
856  if (safe_str_eq(action->task, CRMD_ACTION_PROMOTE)) {
857  action->fail_role = RSC_ROLE_SLAVE;
858  } else {
859  action->fail_role = RSC_ROLE_STARTED;
860  }
861  }
862  pe_rsc_trace(action->rsc, "\t%s failure results in: %s", action->task,
863  role2text(action->fail_role));
864 
865  field = XML_OP_ATTR_START_DELAY;
866  value = g_hash_table_lookup(action->meta, field);
867  if (value != NULL) {
868  value_i = crm_get_msec(value);
869  if (value_i < 0) {
870  value_i = 0;
871  }
872  start_delay = value_i;
873  value_ms = crm_itoa(value_i);
874  g_hash_table_replace(action->meta, strdup(field), value_ms);
875 
876  } else if (interval > 0 && g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN)) {
877  crm_time_t *origin = NULL;
878 
879  value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN);
880  origin = crm_time_new(value);
881 
882  if (origin == NULL) {
883  crm_config_err("Operation %s contained an invalid " XML_OP_ATTR_ORIGIN ": %s",
884  ID(xml_obj), value);
885 
886  } else {
887  crm_time_t *delay = NULL;
888  int rc = crm_time_compare(origin, data_set->now);
889  long long delay_s = 0;
890  int interval_s = (interval / 1000);
891 
892  crm_trace("Origin: %s, interval: %d", value, interval_s);
893 
894  /* If 'origin' is in the future, find the most recent "multiple" that occurred in the past */
895  while(rc > 0) {
896  crm_time_add_seconds(origin, -interval_s);
897  rc = crm_time_compare(origin, data_set->now);
898  }
899 
900  /* Now find the first "multiple" that occurs after 'now' */
901  while (rc < 0) {
902  crm_time_add_seconds(origin, interval_s);
903  rc = crm_time_compare(origin, data_set->now);
904  }
905 
906  delay = crm_time_calculate_duration(origin, data_set->now);
907 
908  crm_time_log(LOG_TRACE, "origin", origin,
911  crm_time_log(LOG_TRACE, "now", data_set->now,
914  crm_time_log(LOG_TRACE, "delay", delay, crm_time_log_duration);
915 
916  delay_s = crm_time_get_seconds(delay);
917 
918  CRM_CHECK(delay_s >= 0, delay_s = 0);
919  start_delay = delay_s * 1000;
920 
921  crm_info("Calculated a start delay of %llds for %s", delay_s, ID(xml_obj));
922  g_hash_table_replace(action->meta, strdup(XML_OP_ATTR_START_DELAY),
923  crm_itoa(start_delay));
924  crm_time_free(origin);
925  crm_time_free(delay);
926  }
927  }
928 
929  field = XML_ATTR_TIMEOUT;
930  value = g_hash_table_lookup(action->meta, field);
931  if (value == NULL && xml_obj == NULL && safe_str_eq(action->task, RSC_STATUS) && interval == 0) {
932  xmlNode *min_interval_mon = find_min_interval_mon(action->rsc, FALSE);
933 
934  if (min_interval_mon) {
935  value = crm_element_value(min_interval_mon, XML_ATTR_TIMEOUT);
936  pe_rsc_trace(action->rsc,
937  "\t%s uses the timeout value '%s' from the minimum interval monitor",
938  action->uuid, value);
939  }
940  }
941  if (value == NULL) {
942  value = pe_pref(data_set->config_hash, "default-action-timeout");
943  }
944  value_i = crm_get_msec(value);
945  if (value_i < 0) {
946  value_i = 0;
947  }
948  value_i += start_delay;
949  value_ms = crm_itoa(value_i);
950  g_hash_table_replace(action->meta, strdup(field), value_ms);
951 }
952 
953 static xmlNode *
954 find_rsc_op_entry_helper(resource_t * rsc, const char *key, gboolean include_disabled)
955 {
956  unsigned long long number = 0;
957  gboolean do_retry = TRUE;
958  char *local_key = NULL;
959  const char *name = NULL;
960  const char *value = NULL;
961  const char *interval = NULL;
962  char *match_key = NULL;
963  xmlNode *op = NULL;
964  xmlNode *operation = NULL;
965 
966  retry:
967  for (operation = __xml_first_child(rsc->ops_xml); operation != NULL;
968  operation = __xml_next_element(operation)) {
969  if (crm_str_eq((const char *)operation->name, "op", TRUE)) {
970  name = crm_element_value(operation, "name");
971  interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
972  value = crm_element_value(operation, "enabled");
973  if (!include_disabled && value && crm_is_true(value) == FALSE) {
974  continue;
975  }
976 
977  number = crm_get_interval(interval);
978  match_key = generate_op_key(rsc->id, name, number);
979  if (safe_str_eq(key, match_key)) {
980  op = operation;
981  }
982  free(match_key);
983 
984  if (rsc->clone_name) {
985  match_key = generate_op_key(rsc->clone_name, name, number);
986  if (safe_str_eq(key, match_key)) {
987  op = operation;
988  }
989  free(match_key);
990  }
991 
992  if (op != NULL) {
993  free(local_key);
994  return op;
995  }
996  }
997  }
998 
999  free(local_key);
1000  if (do_retry == FALSE) {
1001  return NULL;
1002  }
1003 
1004  do_retry = FALSE;
1005  if (strstr(key, CRMD_ACTION_MIGRATE) || strstr(key, CRMD_ACTION_MIGRATED)) {
1006  local_key = generate_op_key(rsc->id, "migrate", 0);
1007  key = local_key;
1008  goto retry;
1009 
1010  } else if (strstr(key, "_notify_")) {
1011  local_key = generate_op_key(rsc->id, "notify", 0);
1012  key = local_key;
1013  goto retry;
1014  }
1015 
1016  return NULL;
1017 }
1018 
1019 xmlNode *
1020 find_rsc_op_entry(resource_t * rsc, const char *key)
1021 {
1022  return find_rsc_op_entry_helper(rsc, key, FALSE);
1023 }
1024 
1025 void
1026 print_node(const char *pre_text, node_t * node, gboolean details)
1027 {
1028  if (node == NULL) {
1029  crm_trace("%s%s: <NULL>", pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": ");
1030  return;
1031  }
1032 
1033  CRM_ASSERT(node->details);
1034  crm_trace("%s%s%sNode %s: (weight=%d, fixed=%s)",
1035  pre_text == NULL ? "" : pre_text,
1036  pre_text == NULL ? "" : ": ",
1037  node->details->online ? "" : "Unavailable/Unclean ",
1038  node->details->uname, node->weight, node->fixed ? "True" : "False");
1039 
1040  if (details) {
1041  char *pe_mutable = strdup("\t\t");
1042  GListPtr gIter = node->details->running_rsc;
1043 
1044  crm_trace("\t\t===Node Attributes");
1045  g_hash_table_foreach(node->details->attrs, print_str_str, pe_mutable);
1046  free(pe_mutable);
1047 
1048  crm_trace("\t\t=== Resources");
1049 
1050  for (; gIter != NULL; gIter = gIter->next) {
1051  resource_t *rsc = (resource_t *) gIter->data;
1052 
1053  print_resource(LOG_DEBUG_4, "\t\t", rsc, FALSE);
1054  }
1055  }
1056 }
1057 
1058 /*
1059  * Used by the HashTable for-loop
1060  */
1061 void
1062 print_str_str(gpointer key, gpointer value, gpointer user_data)
1063 {
1064  crm_trace("%s%s %s ==> %s",
1065  user_data == NULL ? "" : (char *)user_data,
1066  user_data == NULL ? "" : ": ", (char *)key, (char *)value);
1067 }
1068 
1069 void
1070 print_resource(int log_level, const char *pre_text, resource_t * rsc, gboolean details)
1071 {
1072  long options = pe_print_log;
1073 
1074  if (rsc == NULL) {
1075  do_crm_log(log_level - 1, "%s%s: <NULL>",
1076  pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": ");
1077  return;
1078  }
1079  if (details) {
1080  options |= pe_print_details;
1081  }
1082  rsc->fns->print(rsc, pre_text, options, &log_level);
1083 }
1084 
1085 void
1087 {
1088  if (action == NULL) {
1089  return;
1090  }
1091  g_list_free_full(action->actions_before, free); /* action_warpper_t* */
1092  g_list_free_full(action->actions_after, free); /* action_warpper_t* */
1093  if (action->extra) {
1094  g_hash_table_destroy(action->extra);
1095  }
1096  if (action->meta) {
1097  g_hash_table_destroy(action->meta);
1098  }
1099  free(action->cancel_task);
1100  free(action->task);
1101  free(action->uuid);
1102  free(action->node);
1103  free(action);
1104 }
1105 
1106 GListPtr
1108 {
1109  const char *value = NULL;
1110  GListPtr result = NULL;
1111  GListPtr gIter = input;
1112 
1113  CRM_CHECK(input != NULL, return NULL);
1114 
1115  for (; gIter != NULL; gIter = gIter->next) {
1116  action_t *action = (action_t *) gIter->data;
1117 
1118  value = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL);
1119  if (value == NULL) {
1120  /* skip */
1121  } else if (safe_str_eq(value, "0")) {
1122  /* skip */
1123  } else if (safe_str_eq(CRMD_ACTION_CANCEL, action->task)) {
1124  /* skip */
1125  } else if (not_on_node == NULL) {
1126  crm_trace("(null) Found: %s", action->uuid);
1127  result = g_list_prepend(result, action);
1128 
1129  } else if (action->node == NULL) {
1130  /* skip */
1131  } else if (action->node->details != not_on_node->details) {
1132  crm_trace("Found: %s", action->uuid);
1133  result = g_list_prepend(result, action);
1134  }
1135  }
1136 
1137  return result;
1138 }
1139 
1140 enum action_tasks
1141 get_complex_task(resource_t * rsc, const char *name, gboolean allow_non_atomic)
1142 {
1143  enum action_tasks task = text2task(name);
1144 
1145  if (rsc == NULL) {
1146  return task;
1147 
1148  } else if (allow_non_atomic == FALSE || rsc->variant == pe_native) {
1149  switch (task) {
1150  case stopped_rsc:
1151  case started_rsc:
1152  case action_demoted:
1153  case action_promoted:
1154  crm_trace("Folding %s back into its atomic counterpart for %s", name, rsc->id);
1155  return task - 1;
1156  break;
1157  default:
1158  break;
1159  }
1160  }
1161  return task;
1162 }
1163 
1164 action_t *
1165 find_first_action(GListPtr input, const char *uuid, const char *task, node_t * on_node)
1166 {
1167  GListPtr gIter = NULL;
1168 
1169  CRM_CHECK(uuid || task, return NULL);
1170 
1171  for (gIter = input; gIter != NULL; gIter = gIter->next) {
1172  action_t *action = (action_t *) gIter->data;
1173 
1174  if (uuid != NULL && safe_str_neq(uuid, action->uuid)) {
1175  continue;
1176 
1177  } else if (task != NULL && safe_str_neq(task, action->task)) {
1178  continue;
1179 
1180  } else if (on_node == NULL) {
1181  return action;
1182 
1183  } else if (action->node == NULL) {
1184  continue;
1185 
1186  } else if (on_node->details == action->node->details) {
1187  return action;
1188  }
1189  }
1190 
1191  return NULL;
1192 }
1193 
1194 GListPtr
1195 find_actions(GListPtr input, const char *key, node_t * on_node)
1196 {
1197  GListPtr gIter = input;
1198  GListPtr result = NULL;
1199 
1200  CRM_CHECK(key != NULL, return NULL);
1201 
1202  for (; gIter != NULL; gIter = gIter->next) {
1203  action_t *action = (action_t *) gIter->data;
1204 
1205  crm_trace("Matching %s against %s", key, action->uuid);
1206  if (safe_str_neq(key, action->uuid)) {
1207  continue;
1208 
1209  } else if (on_node == NULL) {
1210  result = g_list_prepend(result, action);
1211 
1212  } else if (action->node == NULL) {
1213  /* skip */
1214  crm_trace("While looking for %s action on %s, "
1215  "found an unallocated one. Assigning"
1216  " it to the requested node...", key, on_node->details->uname);
1217 
1218  action->node = node_copy(on_node);
1219  result = g_list_prepend(result, action);
1220 
1221  } else if (on_node->details == action->node->details) {
1222  result = g_list_prepend(result, action);
1223  }
1224  }
1225 
1226  return result;
1227 }
1228 
1229 GListPtr
1230 find_actions_exact(GListPtr input, const char *key, node_t * on_node)
1231 {
1232  GListPtr gIter = input;
1233  GListPtr result = NULL;
1234 
1235  CRM_CHECK(key != NULL, return NULL);
1236 
1237  for (; gIter != NULL; gIter = gIter->next) {
1238  action_t *action = (action_t *) gIter->data;
1239 
1240  crm_trace("Matching %s against %s", key, action->uuid);
1241  if (safe_str_neq(key, action->uuid)) {
1242  crm_trace("Key mismatch: %s vs. %s", key, action->uuid);
1243  continue;
1244 
1245  } else if (on_node == NULL || action->node == NULL) {
1246  crm_trace("on_node=%p, action->node=%p", on_node, action->node);
1247  continue;
1248 
1249  } else if (safe_str_eq(on_node->details->id, action->node->details->id)) {
1250  result = g_list_prepend(result, action);
1251  }
1252  crm_trace("Node mismatch: %s vs. %s", on_node->details->id, action->node->details->id);
1253  }
1254 
1255  return result;
1256 }
1257 
1258 static void
1259 resource_node_score(resource_t * rsc, node_t * node, int score, const char *tag)
1260 {
1261  node_t *match = NULL;
1262 
1263  if (rsc->children) {
1264  GListPtr gIter = rsc->children;
1265 
1266  for (; gIter != NULL; gIter = gIter->next) {
1267  resource_t *child_rsc = (resource_t *) gIter->data;
1268 
1269  resource_node_score(child_rsc, node, score, tag);
1270  }
1271  }
1272 
1273  pe_rsc_trace(rsc, "Setting %s for %s on %s: %d", tag, rsc->id, node->details->uname, score);
1274  match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
1275  if (match == NULL) {
1276  match = node_copy(node);
1277  match->weight = merge_weights(score, node->weight);
1278  g_hash_table_insert(rsc->allowed_nodes, (gpointer) match->details->id, match);
1279  }
1280  match->weight = merge_weights(match->weight, score);
1281 }
1282 
1283 void
1284 resource_location(resource_t * rsc, node_t * node, int score, const char *tag,
1285  pe_working_set_t * data_set)
1286 {
1287  if (node != NULL) {
1288  resource_node_score(rsc, node, score, tag);
1289 
1290  } else if (data_set != NULL) {
1291  GListPtr gIter = data_set->nodes;
1292 
1293  for (; gIter != NULL; gIter = gIter->next) {
1294  node_t *node = (node_t *) gIter->data;
1295 
1296  resource_node_score(rsc, node, score, tag);
1297  }
1298 
1299  } else {
1300  GHashTableIter iter;
1301  node_t *node = NULL;
1302 
1303  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1304  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1305  resource_node_score(rsc, node, score, tag);
1306  }
1307  }
1308 
1309  if (node == NULL && score == -INFINITY) {
1310  if (rsc->allocated_to) {
1311  crm_info("Deallocating %s from %s", rsc->id, rsc->allocated_to->details->uname);
1312  free(rsc->allocated_to);
1313  rsc->allocated_to = NULL;
1314  }
1315  }
1316 }
1317 
1318 #define sort_return(an_int, why) do { \
1319  free(a_uuid); \
1320  free(b_uuid); \
1321  crm_trace("%s (%d) %c %s (%d) : %s", \
1322  a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \
1323  b_xml_id, b_call_id, why); \
1324  return an_int; \
1325  } while(0)
1326 
1327 gint
1328 sort_op_by_callid(gconstpointer a, gconstpointer b)
1329 {
1330  int a_call_id = -1;
1331  int b_call_id = -1;
1332 
1333  char *a_uuid = NULL;
1334  char *b_uuid = NULL;
1335 
1336  const xmlNode *xml_a = a;
1337  const xmlNode *xml_b = b;
1338 
1339  const char *a_xml_id = crm_element_value_const(xml_a, XML_ATTR_ID);
1340  const char *b_xml_id = crm_element_value_const(xml_b, XML_ATTR_ID);
1341 
1342  if (safe_str_eq(a_xml_id, b_xml_id)) {
1343  /* We have duplicate lrm_rsc_op entries in the status
1344  * section which is unliklely to be a good thing
1345  * - we can handle it easily enough, but we need to get
1346  * to the bottom of why its happening.
1347  */
1348  pe_err("Duplicate lrm_rsc_op entries named %s", a_xml_id);
1349  sort_return(0, "duplicate");
1350  }
1351 
1354 
1355  if (a_call_id == -1 && b_call_id == -1) {
1356  /* both are pending ops so it doesn't matter since
1357  * stops are never pending
1358  */
1359  sort_return(0, "pending");
1360 
1361  } else if (a_call_id >= 0 && a_call_id < b_call_id) {
1362  sort_return(-1, "call id");
1363 
1364  } else if (b_call_id >= 0 && a_call_id > b_call_id) {
1365  sort_return(1, "call id");
1366 
1367  } else if (b_call_id >= 0 && a_call_id == b_call_id) {
1368  /*
1369  * The op and last_failed_op are the same
1370  * Order on last-rc-change
1371  */
1372  int last_a = -1;
1373  int last_b = -1;
1374 
1377 
1378  crm_trace("rc-change: %d vs %d", last_a, last_b);
1379  if (last_a >= 0 && last_a < last_b) {
1380  sort_return(-1, "rc-change");
1381 
1382  } else if (last_b >= 0 && last_a > last_b) {
1383  sort_return(1, "rc-change");
1384  }
1385  sort_return(0, "rc-change");
1386 
1387  } else {
1388  /* One of the inputs is a pending operation
1389  * Attempt to use XML_ATTR_TRANSITION_MAGIC to determine its age relative to the other
1390  */
1391 
1392  int a_id = -1;
1393  int b_id = -1;
1394  int dummy = -1;
1395 
1396  const char *a_magic = crm_element_value_const(xml_a, XML_ATTR_TRANSITION_MAGIC);
1397  const char *b_magic = crm_element_value_const(xml_b, XML_ATTR_TRANSITION_MAGIC);
1398 
1399  CRM_CHECK(a_magic != NULL && b_magic != NULL, sort_return(0, "No magic"));
1400  if(!decode_transition_magic(a_magic, &a_uuid, &a_id, &dummy, &dummy, &dummy, &dummy)) {
1401  sort_return(0, "bad magic a");
1402  }
1403  if(!decode_transition_magic(b_magic, &b_uuid, &b_id, &dummy, &dummy, &dummy, &dummy)) {
1404  sort_return(0, "bad magic b");
1405  }
1406  /* try to determine the relative age of the operation...
1407  * some pending operations (ie. a start) may have been superseded
1408  * by a subsequent stop
1409  *
1410  * [a|b]_id == -1 means its a shutdown operation and _always_ comes last
1411  */
1412  if (safe_str_neq(a_uuid, b_uuid) || a_id == b_id) {
1413  /*
1414  * some of the logic in here may be redundant...
1415  *
1416  * if the UUID from the TE doesn't match then one better
1417  * be a pending operation.
1418  * pending operations dont survive between elections and joins
1419  * because we query the LRM directly
1420  */
1421 
1422  if (b_call_id == -1) {
1423  sort_return(-1, "transition + call");
1424 
1425  } else if (a_call_id == -1) {
1426  sort_return(1, "transition + call");
1427  }
1428 
1429  } else if ((a_id >= 0 && a_id < b_id) || b_id == -1) {
1430  sort_return(-1, "transition");
1431 
1432  } else if ((b_id >= 0 && a_id > b_id) || a_id == -1) {
1433  sort_return(1, "transition");
1434  }
1435  }
1436 
1437  /* we should never end up here */
1438  CRM_CHECK(FALSE, sort_return(0, "default"));
1439 
1440 }
1441 
1442 time_t
1444 {
1445  if(data_set) {
1446  if (data_set->now == NULL) {
1447  crm_trace("Recording a new 'now'");
1448  data_set->now = crm_time_new(NULL);
1449  }
1450  return crm_time_get_seconds_since_epoch(data_set->now);
1451  }
1452 
1453  crm_trace("Defaulting to 'now'");
1454  return time(NULL);
1455 }
1456 
1457 struct fail_search {
1458  resource_t *rsc;
1459  pe_working_set_t * data_set;
1460 
1461  int count;
1462  long long last;
1463  char *key;
1464 };
1465 
1466 static void
1467 get_failcount_by_prefix(gpointer key_p, gpointer value, gpointer user_data)
1468 {
1469  struct fail_search *search = user_data;
1470  const char *attr_id = key_p;
1471  const char *match = strstr(attr_id, search->key);
1472  resource_t *parent = NULL;
1473 
1474  if (match == NULL) {
1475  return;
1476  }
1477 
1478  /* we are only incrementing the failcounts here if the rsc
1479  * that matches our prefix has the same uber parent as the rsc we're
1480  * calculating the failcounts for. This prevents false positive matches
1481  * where unrelated resources may have similar prefixes in their names.
1482  *
1483  * search->rsc is already set to be the uber parent. */
1484  parent = uber_parent(pe_find_resource(search->data_set->resources, match));
1485  if (parent == NULL || parent != search->rsc) {
1486  return;
1487  }
1488  if (strstr(attr_id, "last-failure-") == attr_id) {
1489  search->last = crm_int_helper(value, NULL);
1490 
1491  } else if (strstr(attr_id, "fail-count-") == attr_id) {
1492  search->count += char2score(value);
1493  }
1494 }
1495 
1496 int
1497 get_failcount(node_t * node, resource_t * rsc, time_t *last_failure, pe_working_set_t * data_set)
1498 {
1499  return get_failcount_full(node, rsc, last_failure, TRUE, NULL, data_set);
1500 }
1501 
1502 static gboolean
1503 is_matched_failure(const char * rsc_id, xmlNode * conf_op_xml, xmlNode * lrm_op_xml)
1504 {
1505  gboolean matched = FALSE;
1506  const char *conf_op_name = NULL;
1507  int conf_op_interval = 0;
1508  const char *lrm_op_task = NULL;
1509  int lrm_op_interval = 0;
1510  const char *lrm_op_id = NULL;
1511  char *last_failure_key = NULL;
1512 
1513  if (rsc_id == NULL || conf_op_xml == NULL || lrm_op_xml == NULL) {
1514  return FALSE;
1515  }
1516 
1517  conf_op_name = crm_element_value(conf_op_xml, "name");
1518  conf_op_interval = crm_get_msec(crm_element_value(conf_op_xml, "interval"));
1519  lrm_op_task = crm_element_value(lrm_op_xml, XML_LRM_ATTR_TASK);
1520  crm_element_value_int(lrm_op_xml, XML_LRM_ATTR_INTERVAL, &lrm_op_interval);
1521 
1522  if (safe_str_eq(conf_op_name, lrm_op_task) == FALSE
1523  || conf_op_interval != lrm_op_interval) {
1524  return FALSE;
1525  }
1526 
1527  lrm_op_id = ID(lrm_op_xml);
1528  last_failure_key = generate_op_key(rsc_id, "last_failure", 0);
1529 
1530  if (safe_str_eq(last_failure_key, lrm_op_id)) {
1531  matched = TRUE;
1532 
1533  } else {
1534  char *expected_op_key = generate_op_key(rsc_id, conf_op_name, conf_op_interval);
1535 
1536  if (safe_str_eq(expected_op_key, lrm_op_id)) {
1537  int rc = 0;
1538  int target_rc = get_target_rc(lrm_op_xml);
1539 
1540  crm_element_value_int(lrm_op_xml, XML_LRM_ATTR_RC, &rc);
1541  if (rc != target_rc) {
1542  matched = TRUE;
1543  }
1544  }
1545  free(expected_op_key);
1546  }
1547 
1548  free(last_failure_key);
1549  return matched;
1550 }
1551 
1552 static gboolean
1553 block_failure(node_t * node, resource_t * rsc, xmlNode * xml_op, pe_working_set_t * data_set)
1554 {
1555  char *xml_name = clone_strip(rsc->id);
1556  char *xpath = crm_strdup_printf("//primitive[@id='%s']//op[@on-fail='block']", xml_name);
1557  xmlXPathObject *xpathObj = xpath_search(rsc->xml, xpath);
1558  gboolean should_block = FALSE;
1559 
1560  free(xpath);
1561 
1562  if (xpathObj) {
1563  int max = numXpathResults(xpathObj);
1564  int lpc = 0;
1565 
1566  for (lpc = 0; lpc < max; lpc++) {
1567  xmlNode *pref = getXpathResult(xpathObj, lpc);
1568 
1569  if (xml_op) {
1570  should_block = is_matched_failure(xml_name, pref, xml_op);
1571  if (should_block) {
1572  break;
1573  }
1574 
1575  } else {
1576  const char *conf_op_name = NULL;
1577  int conf_op_interval = 0;
1578  char *lrm_op_xpath = NULL;
1579  xmlXPathObject *lrm_op_xpathObj = NULL;
1580 
1581  conf_op_name = crm_element_value(pref, "name");
1582  conf_op_interval = crm_get_msec(crm_element_value(pref, "interval"));
1583 
1584  lrm_op_xpath = crm_strdup_printf("//node_state[@uname='%s']"
1585  "//lrm_resource[@id='%s']"
1586  "/lrm_rsc_op[@operation='%s'][@interval='%d']",
1587  node->details->uname, xml_name,
1588  conf_op_name, conf_op_interval);
1589  lrm_op_xpathObj = xpath_search(data_set->input, lrm_op_xpath);
1590 
1591  free(lrm_op_xpath);
1592 
1593  if (lrm_op_xpathObj) {
1594  int max2 = numXpathResults(lrm_op_xpathObj);
1595  int lpc2 = 0;
1596 
1597  for (lpc2 = 0; lpc2 < max2; lpc2++) {
1598  xmlNode *lrm_op_xml = getXpathResult(lrm_op_xpathObj, lpc2);
1599 
1600  should_block = is_matched_failure(xml_name, pref, lrm_op_xml);
1601  if (should_block) {
1602  break;
1603  }
1604  }
1605  }
1606  freeXpathObject(lrm_op_xpathObj);
1607 
1608  if (should_block) {
1609  break;
1610  }
1611  }
1612  }
1613  }
1614 
1615  free(xml_name);
1616  freeXpathObject(xpathObj);
1617 
1618  return should_block;
1619 }
1620 
1621 int
1622 get_failcount_full(node_t * node, resource_t * rsc, time_t *last_failure,
1623  bool effective, xmlNode * xml_op, pe_working_set_t * data_set)
1624 {
1625  char *key = NULL;
1626  const char *value = NULL;
1627  struct fail_search search = { rsc, data_set, 0, 0, NULL };
1628 
1629  /* Optimize the "normal" case */
1630  key = crm_concat("fail-count", rsc->clone_name ? rsc->clone_name : rsc->id, '-');
1631  value = g_hash_table_lookup(node->details->attrs, key);
1632  search.count = char2score(value);
1633  crm_trace("%s = %s", key, value);
1634  free(key);
1635 
1636  if (value) {
1637  key = crm_concat("last-failure", rsc->clone_name ? rsc->clone_name : rsc->id, '-');
1638  value = g_hash_table_lookup(node->details->attrs, key);
1639  search.last = crm_int_helper(value, NULL);
1640  free(key);
1641 
1642  /* This block is still relevant once we omit anonymous instance numbers
1643  * because stopped clones won't have clone_name set
1644  */
1645  } else if (is_not_set(rsc->flags, pe_rsc_unique)) {
1646  search.rsc = uber_parent(rsc);
1647  search.key = clone_strip(rsc->id);
1648 
1649  g_hash_table_foreach(node->details->attrs, get_failcount_by_prefix, &search);
1650  free(search.key);
1651  search.key = NULL;
1652  }
1653 
1654  if (search.count != 0 && search.last != 0 && last_failure) {
1655  *last_failure = search.last;
1656  }
1657 
1658  if(search.count && rsc->failure_timeout) {
1659  /* Never time-out if blocking failures are configured */
1660  if (block_failure(node, rsc, xml_op, data_set)) {
1661  pe_warn("Setting %s.failure-timeout=%d conflicts with on-fail=block: ignoring timeout", rsc->id, rsc->failure_timeout);
1662  rsc->failure_timeout = 0;
1663 #if 0
1664  /* A good idea? */
1665  } else if (rsc->container == NULL && is_not_set(data_set->flags, pe_flag_stonith_enabled)) {
1666  /* In this case, stop.on-fail defaults to block in unpack_operation() */
1667  rsc->failure_timeout = 0;
1668 #endif
1669  }
1670  }
1671 
1672  if (effective && search.count != 0 && search.last != 0 && rsc->failure_timeout) {
1673  if (search.last > 0) {
1674  time_t now = get_effective_time(data_set);
1675 
1676  if (now > (search.last + rsc->failure_timeout)) {
1677  crm_debug("Failcount for %s on %s has expired (limit was %ds)",
1678  search.rsc->id, node->details->uname, rsc->failure_timeout);
1679  search.count = 0;
1680  }
1681  }
1682  }
1683 
1684  if (search.count != 0) {
1685  char *score = score2char(search.count);
1686 
1687  crm_info("%s has failed %s times on %s", search.rsc->id, score, node->details->uname);
1688  free(score);
1689  }
1690 
1691  return search.count;
1692 }
1693 
1694 /* If it's a resource container, get its failcount plus all the failcounts of the resources within it */
1695 int
1696 get_failcount_all(node_t * node, resource_t * rsc, time_t *last_failure, pe_working_set_t * data_set)
1697 {
1698  int failcount_all = 0;
1699 
1700  failcount_all = get_failcount(node, rsc, last_failure, data_set);
1701 
1702  if (rsc->fillers) {
1703  GListPtr gIter = NULL;
1704 
1705  for (gIter = rsc->fillers; gIter != NULL; gIter = gIter->next) {
1706  resource_t *filler = (resource_t *) gIter->data;
1707  time_t filler_last_failure = 0;
1708 
1709  failcount_all += get_failcount(node, filler, &filler_last_failure, data_set);
1710 
1711  if (last_failure && filler_last_failure > *last_failure) {
1712  *last_failure = filler_last_failure;
1713  }
1714  }
1715 
1716  if (failcount_all != 0) {
1717  char *score = score2char(failcount_all);
1718 
1719  crm_info("Container %s and the resources within it have failed %s times on %s",
1720  rsc->id, score, node->details->uname);
1721  free(score);
1722  }
1723  }
1724 
1725  return failcount_all;
1726 }
1727 
1728 gboolean
1730 {
1731  enum rsc_role_e local_role = RSC_ROLE_UNKNOWN;
1732  const char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
1733 
1734  CRM_CHECK(role != NULL, return FALSE);
1735 
1736  if (value == NULL || safe_str_eq("started", value)
1737  || safe_str_eq("default", value)) {
1738  return FALSE;
1739  }
1740 
1741  local_role = text2role(value);
1742  if (local_role == RSC_ROLE_UNKNOWN) {
1743  crm_config_err("%s: Unknown value for %s: %s", rsc->id, XML_RSC_ATTR_TARGET_ROLE, value);
1744  return FALSE;
1745 
1746  } else if (local_role > RSC_ROLE_STARTED) {
1747  if (uber_parent(rsc)->variant == pe_master) {
1748  if (local_role > RSC_ROLE_SLAVE) {
1749  /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */
1750  return FALSE;
1751  }
1752 
1753  } else {
1754  crm_config_err("%s is not part of a master/slave resource, a %s of '%s' makes no sense",
1755  rsc->id, XML_RSC_ATTR_TARGET_ROLE, value);
1756  return FALSE;
1757  }
1758  }
1759 
1760  *role = local_role;
1761  return TRUE;
1762 }
1763 
1764 gboolean
1765 order_actions(action_t * lh_action, action_t * rh_action, enum pe_ordering order)
1766 {
1767  GListPtr gIter = NULL;
1768  action_wrapper_t *wrapper = NULL;
1769  GListPtr list = NULL;
1770 
1771  if (order == pe_order_none) {
1772  return FALSE;
1773  }
1774 
1775  if (lh_action == NULL || rh_action == NULL) {
1776  return FALSE;
1777  }
1778 
1779  crm_trace("Ordering Action %s before %s", lh_action->uuid, rh_action->uuid);
1780 
1781  /* Ensure we never create a dependency on ourselves... its happened */
1782  CRM_ASSERT(lh_action != rh_action);
1783 
1784  /* Filter dups, otherwise update_action_states() has too much work to do */
1785  gIter = lh_action->actions_after;
1786  for (; gIter != NULL; gIter = gIter->next) {
1787  action_wrapper_t *after = (action_wrapper_t *) gIter->data;
1788 
1789  if (after->action == rh_action && (after->type & order)) {
1790  return FALSE;
1791  }
1792  }
1793 
1794  wrapper = calloc(1, sizeof(action_wrapper_t));
1795  wrapper->action = rh_action;
1796  wrapper->type = order;
1797 
1798  list = lh_action->actions_after;
1799  list = g_list_prepend(list, wrapper);
1800  lh_action->actions_after = list;
1801 
1802  wrapper = NULL;
1803 
1804 /* order |= pe_order_implies_then; */
1805 /* order ^= pe_order_implies_then; */
1806 
1807  wrapper = calloc(1, sizeof(action_wrapper_t));
1808  wrapper->action = lh_action;
1809  wrapper->type = order;
1810  list = rh_action->actions_before;
1811  list = g_list_prepend(list, wrapper);
1812  rh_action->actions_before = list;
1813  return TRUE;
1814 }
1815 
1816 action_t *
1817 get_pseudo_op(const char *name, pe_working_set_t * data_set)
1818 {
1819  action_t *op = NULL;
1820 
1821  if(data_set->singletons) {
1822  op = g_hash_table_lookup(data_set->singletons, name);
1823  }
1824  if (op == NULL) {
1825  op = custom_action(NULL, strdup(name), name, NULL, TRUE, TRUE, data_set);
1828  }
1829 
1830  return op;
1831 }
1832 
1833 void
1835 {
1836  ticket_t *ticket = data;
1837 
1838  if (ticket->state) {
1839  g_hash_table_destroy(ticket->state);
1840  }
1841  free(ticket->id);
1842  free(ticket);
1843 }
1844 
1845 ticket_t *
1846 ticket_new(const char *ticket_id, pe_working_set_t * data_set)
1847 {
1848  ticket_t *ticket = NULL;
1849 
1850  if (ticket_id == NULL || strlen(ticket_id) == 0) {
1851  return NULL;
1852  }
1853 
1854  if (data_set->tickets == NULL) {
1855  data_set->tickets =
1856  g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket);
1857  }
1858 
1859  ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
1860  if (ticket == NULL) {
1861 
1862  ticket = calloc(1, sizeof(ticket_t));
1863  if (ticket == NULL) {
1864  crm_err("Cannot allocate ticket '%s'", ticket_id);
1865  return NULL;
1866  }
1867 
1868  crm_trace("Creaing ticket entry for %s", ticket_id);
1869 
1870  ticket->id = strdup(ticket_id);
1871  ticket->granted = FALSE;
1872  ticket->last_granted = -1;
1873  ticket->standby = FALSE;
1874  ticket->state = g_hash_table_new_full(crm_str_hash, g_str_equal,
1876 
1877  g_hash_table_insert(data_set->tickets, strdup(ticket->id), ticket);
1878  }
1879 
1880  return ticket;
1881 }
1882 
1883 static void
1884 filter_parameters(xmlNode * param_set, const char *param_string, bool need_present)
1885 {
1886  int len = 0;
1887  char *name = NULL;
1888  char *match = NULL;
1889 
1890  if (param_set == NULL) {
1891  return;
1892  }
1893 
1894  if (param_set) {
1895  xmlAttrPtr xIter = param_set->properties;
1896 
1897  while (xIter) {
1898  const char *prop_name = (const char *)xIter->name;
1899 
1900  xIter = xIter->next;
1901  name = NULL;
1902  len = strlen(prop_name) + 3;
1903 
1904  name = malloc(len);
1905  if(name) {
1906  sprintf(name, " %s ", prop_name);
1907  name[len - 1] = 0;
1908  match = strstr(param_string, name);
1909  }
1910 
1911  if (need_present && match == NULL) {
1912  crm_trace("%s not found in %s", prop_name, param_string);
1913  xml_remove_prop(param_set, prop_name);
1914 
1915  } else if (need_present == FALSE && match) {
1916  crm_trace("%s found in %s", prop_name, param_string);
1917  xml_remove_prop(param_set, prop_name);
1918  }
1919  free(name);
1920  }
1921  }
1922 }
1923 
1925 rsc_action_digest_cmp(resource_t * rsc, xmlNode * xml_op, node_t * node,
1926  pe_working_set_t * data_set)
1927 {
1928  op_digest_cache_t *data = NULL;
1929 
1930  GHashTable *local_rsc_params = NULL;
1931 
1932  action_t *action = NULL;
1933  char *key = NULL;
1934 
1935  int interval = 0;
1936  const char *op_id = ID(xml_op);
1937  const char *interval_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL);
1938  const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
1939  const char *digest_all;
1940  const char *digest_restart;
1941  const char *secure_list;
1942  const char *restart_list;
1943  const char *op_version;
1944 
1945  data = g_hash_table_lookup(node->details->digest_cache, op_id);
1946  if (data) {
1947  return data;
1948  }
1949 
1950  data = calloc(1, sizeof(op_digest_cache_t));
1951 
1952  digest_all = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST);
1953  digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
1954 
1955  secure_list = crm_element_value(xml_op, XML_LRM_ATTR_OP_SECURE);
1956  restart_list = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART);
1957 
1958  op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
1959 
1960  /* key is freed in custom_action */
1961  interval = crm_parse_int(interval_s, "0");
1962  key = generate_op_key(rsc->id, task, interval);
1963  action = custom_action(rsc, key, task, node, TRUE, FALSE, data_set);
1964  key = NULL;
1965 
1966  local_rsc_params = g_hash_table_new_full(crm_str_hash, g_str_equal,
1968  get_rsc_attributes(local_rsc_params, rsc, node, data_set);
1969  data->params_all = create_xml_node(NULL, XML_TAG_PARAMS);
1970  g_hash_table_foreach(local_rsc_params, hash2field, data->params_all);
1971  g_hash_table_foreach(action->extra, hash2field, data->params_all);
1972  g_hash_table_foreach(rsc->parameters, hash2field, data->params_all);
1973  g_hash_table_foreach(action->meta, hash2metafield, data->params_all);
1974  filter_action_parameters(data->params_all, op_version);
1975 
1976  data->digest_all_calc = calculate_operation_digest(data->params_all, op_version);
1977 
1978  if (secure_list && is_set(data_set->flags, pe_flag_sanitized)) {
1979  data->params_secure = copy_xml(data->params_all);
1980 
1981  if (secure_list) {
1982  filter_parameters(data->params_secure, secure_list, FALSE);
1983  }
1984  data->digest_secure_calc = calculate_operation_digest(data->params_secure, op_version);
1985  }
1986 
1987  if (digest_restart) {
1988  data->params_restart = copy_xml(data->params_all);
1989 
1990  if (restart_list) {
1991  filter_parameters(data->params_restart, restart_list, TRUE);
1992  }
1994  }
1995 
1996  data->rc = RSC_DIGEST_MATCH;
1997  if (digest_restart && strcmp(data->digest_restart_calc, digest_restart) != 0) {
1998  data->rc = RSC_DIGEST_RESTART;
1999 
2000  } else if (digest_all == NULL) {
2001  /* it is unknown what the previous op digest was */
2002  data->rc = RSC_DIGEST_UNKNOWN;
2003 
2004  } else if (strcmp(digest_all, data->digest_all_calc) != 0) {
2005  data->rc = RSC_DIGEST_ALL;
2006  }
2007 
2008  g_hash_table_insert(node->details->digest_cache, strdup(op_id), data);
2009  g_hash_table_destroy(local_rsc_params);
2010  pe_free_action(action);
2011 
2012  return data;
2013 }
2014 
2015 const char *rsc_printable_id(resource_t *rsc)
2016 {
2017  if (is_not_set(rsc->flags, pe_rsc_unique)) {
2018  return ID(rsc->xml);
2019  }
2020  return rsc->id;
2021 }
2022 
2023 gboolean
2024 is_rsc_baremetal_remote_node(resource_t *rsc, pe_working_set_t * data_set)
2025 {
2026  node_t *node;
2027 
2028  if (rsc == NULL) {
2029  return FALSE;
2030  } else if (rsc->is_remote_node == FALSE) {
2031  return FALSE;
2032  }
2033 
2034  node = pe_find_node(data_set->nodes, rsc->id);
2035  if (node == NULL) {
2036  return FALSE;
2037  }
2038 
2039  return is_baremetal_remote_node(node);
2040 }
2041 
2042 gboolean
2044 {
2045  if (is_remote_node(node) && (node->details->remote_rsc == FALSE || node->details->remote_rsc->container == FALSE)) {
2046  return TRUE;
2047  }
2048  return FALSE;
2049 }
2050 
2051 gboolean
2053 {
2054  if (is_remote_node(node) && (node->details->remote_rsc && node->details->remote_rsc->container)) {
2055  return TRUE;
2056  }
2057  return FALSE;
2058 }
2059 
2060 gboolean
2062 {
2063  if (node && node->details->type == node_remote) {
2064  return TRUE;
2065  }
2066  return FALSE;
2067 }
2068 
2069 resource_t *
2071 {
2072  if (is_set(data_set->flags, pe_flag_have_remote_nodes) == FALSE) {
2073  return NULL;
2074  }
2075 
2076  if (rsc->fillers) {
2077  GListPtr gIter = NULL;
2078  for (gIter = rsc->fillers; gIter != NULL; gIter = gIter->next) {
2079  resource_t *filler = (resource_t *) gIter->data;
2080 
2081  if (filler->is_remote_node) {
2082  return filler;
2083  }
2084  }
2085  }
2086  return NULL;
2087 }
2088 
2089 gboolean
2091 {
2092  const char *class = crm_element_value(xml, XML_AGENT_ATTR_CLASS);
2093  const char *provider = crm_element_value(xml, XML_AGENT_ATTR_PROVIDER);
2094  const char *agent = crm_element_value(xml, XML_ATTR_TYPE);
2095 
2096  if (safe_str_eq(agent, "remote") && safe_str_eq(provider, "pacemaker") && safe_str_eq(class, "ocf")) {
2097  return TRUE;
2098  }
2099  return FALSE;
2100 }
2101 
2102 void
2103 clear_bit_recursive(resource_t * rsc, unsigned long long flag)
2104 {
2105  GListPtr gIter = rsc->children;
2106 
2107  clear_bit(rsc->flags, flag);
2108  for (; gIter != NULL; gIter = gIter->next) {
2109  resource_t *child_rsc = (resource_t *) gIter->data;
2110 
2111  clear_bit_recursive(child_rsc, flag);
2112  }
2113 }
2114 
2115 void
2116 set_bit_recursive(resource_t * rsc, unsigned long long flag)
2117 {
2118  GListPtr gIter = rsc->children;
2119 
2120  set_bit(rsc->flags, flag);
2121  for (; gIter != NULL; gIter = gIter->next) {
2122  resource_t *child_rsc = (resource_t *) gIter->data;
2123 
2124  set_bit_recursive(child_rsc, flag);
2125  }
2126 }
2127 
2128 action_t *
2129 pe_fence_op(node_t * node, const char *op, bool optional, pe_working_set_t * data_set)
2130 {
2131  char *key = NULL;
2132  action_t *stonith_op = NULL;
2133 
2134  if(op == NULL) {
2135  op = data_set->stonith_action;
2136  }
2137 
2138  key = crm_strdup_printf("%s-%s-%s", CRM_OP_FENCE, node->details->uname, op);
2139 
2140  if(data_set->singletons) {
2141  stonith_op = g_hash_table_lookup(data_set->singletons, key);
2142  }
2143 
2144  if(stonith_op == NULL) {
2145  stonith_op = custom_action(NULL, key, CRM_OP_FENCE, node, optional, TRUE, data_set);
2146 
2147  add_hash_param(stonith_op->meta, XML_LRM_ATTR_TARGET, node->details->uname);
2148  add_hash_param(stonith_op->meta, XML_LRM_ATTR_TARGET_UUID, node->details->id);
2149  add_hash_param(stonith_op->meta, "stonith_action", op);
2150  } else {
2151  free(key);
2152  }
2153 
2154  if(optional == FALSE) {
2155  crm_trace("%s is no longer optional", stonith_op->uuid);
2157  }
2158 
2159  return stonith_op;
2160 }
2161 
2162 void
2164  resource_t * rsc, node_t *node, const char *reason, action_t *dependency, pe_working_set_t * data_set)
2165 {
2166  if(is_not_set(data_set->flags, pe_flag_enable_unfencing)) {
2167  /* No resources require it */
2168  return;
2169 
2170  } else if (rsc != NULL && is_not_set(rsc->flags, pe_rsc_fence_device)) {
2171  /* Wasnt a stonith device */
2172  return;
2173 
2174  } else if(node
2175  && node->details->online
2176  && node->details->unclean == FALSE
2177  && node->details->shutdown == FALSE) {
2178  action_t *unfence = pe_fence_op(node, "on", FALSE, data_set);
2179 
2180  crm_notice("Unfencing %s: %s", node->details->uname, reason);
2181  if(dependency) {
2182  order_actions(unfence, dependency, pe_order_optional);
2183  }
2184 
2185  } else if(rsc) {
2186  GHashTableIter iter;
2187 
2188  g_hash_table_iter_init(&iter, rsc->allowed_nodes);
2189  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
2190  if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
2191  trigger_unfencing(rsc, node, reason, dependency, data_set);
2192  }
2193  }
2194  }
2195 }
2196 
2197 gboolean
2198 add_tag_ref(GHashTable * tags, const char * tag_name, const char * obj_ref)
2199 {
2200  tag_t *tag = NULL;
2201  GListPtr gIter = NULL;
2202  gboolean is_existing = FALSE;
2203 
2204  CRM_CHECK(tags && tag_name && obj_ref, return FALSE);
2205 
2206  tag = g_hash_table_lookup(tags, tag_name);
2207  if (tag == NULL) {
2208  tag = calloc(1, sizeof(tag_t));
2209  if (tag == NULL) {
2210  return FALSE;
2211  }
2212  tag->id = strdup(tag_name);
2213  tag->refs = NULL;
2214  g_hash_table_insert(tags, strdup(tag_name), tag);
2215  }
2216 
2217  for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
2218  const char *existing_ref = (const char *) gIter->data;
2219 
2220  if (crm_str_eq(existing_ref, obj_ref, TRUE)){
2221  is_existing = TRUE;
2222  break;
2223  }
2224  }
2225 
2226  if (is_existing == FALSE) {
2227  tag->refs = g_list_append(tag->refs, strdup(obj_ref));
2228  crm_trace("Added: tag=%s ref=%s", tag->id, obj_ref);
2229  }
2230 
2231  return TRUE;
2232 }
#define XML_OP_ATTR_ORIGIN
Definition: msg_xml.h:224
gboolean xml_contains_remote_node(xmlNode *xml)
Definition: utils.c:2090
#define LOG_TRACE
Definition: logging.h:29
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:164
GListPtr nodes
Definition: status.h:100
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:278
const char * uname
Definition: status.h:129
enum rsc_start_requirement needs
Definition: status.h:313
enum pe_ordering type
Definition: status.h:410
A dumping ground.
long long crm_get_msec(const char *input)
Definition: utils.c:739
#define LOG_DEBUG_4
Definition: logging.h:33
action_t * custom_action(resource_t *rsc, char *key, const char *task, node_t *on_node, gboolean optional, gboolean save_action, pe_working_set_t *data_set)
Definition: utils.c:359
void destroy_ticket(gpointer data)
Definition: utils.c:1834
#define crm_notice(fmt, args...)
Definition: logging.h:250
#define CRMD_ACTION_MIGRATED
Definition: crm.h:148
xmlNode * xml
Definition: status.h:242
enum action_tasks get_complex_task(resource_t *rsc, const char *name, gboolean allow_non_atomic)
Definition: utils.c:1141
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:23
#define pe_flag_have_stonith_resource
Definition: status.h:63
void crm_time_add_seconds(crm_time_t *dt, int value)
Definition: iso8601.c:1168
#define INFINITY
Definition: crm.h:77
#define pe_rsc_needs_unfencing
Definition: status.h:204
GHashTable * utilization
Definition: status.h:282
#define CRM_OP_FENCE
Definition: crm.h:114
time_t get_effective_time(pe_working_set_t *data_set)
Definition: utils.c:1443
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:346
GHashTable * node_hash_from_list(GListPtr list)
Definition: utils.c:123
int crm_element_value_const_int(const xmlNode *data, const char *name, int *dest)
Definition: xml.c:4019
#define crm_time_log_timeofday
Definition: iso8601.h:71
#define pe_flag_enable_unfencing
Definition: status.h:64
const char * id
Definition: status.h:128
pe_working_set_t * pe_dataset
Definition: utils.c:29
char * crm_concat(const char *prefix, const char *suffix, char join)
Definition: utils.c:394
void node_list_exclude(GHashTable *hash, GListPtr list, gboolean merge_scores)
Definition: utils.c:88
int weight
Definition: status.h:162
#define XML_ATTR_TYPE
Definition: msg_xml.h:103
int sort_index
Definition: status.h:257
struct crm_time_s crm_time_t
Definition: iso8601.h:37
time_t last_granted
Definition: status.h:354
#define pe_flag_have_remote_nodes
Definition: status.h:75
gboolean is_container_remote_node(node_t *node)
Definition: utils.c:2052
bool pe_can_fence(pe_working_set_t *data_set, node_t *node)
Definition: utils.c:40
#define crm_config_err(fmt...)
Definition: crm_internal.h:290
#define pe_rsc_stopping
Definition: status.h:194
xmlNode * op_defaults
Definition: status.h:109
#define pe_rsc_needs_quorum
Definition: status.h:202
enum action_fail_response on_fail
Definition: status.h:314
#define pe_rsc_orphan
Definition: status.h:171
void g_hash_destroy_str(gpointer data)
Definition: utils.c:578
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
Definition: utils.c:1328
xmlNode * find_rsc_op_entry(resource_t *rsc, const char *key)
Definition: utils.c:1020
char * cancel_task
Definition: status.h:310
GListPtr running_rsc
Definition: status.h:142
enum pe_obj_types variant
Definition: status.h:248
node_t * node_copy(node_t *this_node)
Definition: utils.c:67
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:256
gboolean safe_str_neq(const char *a, const char *b)
Definition: utils.c:659
#define XML_LRM_ATTR_OP_DIGEST
Definition: msg_xml.h:271
gboolean pending
Definition: status.h:134
#define XML_ATTR_TIMEOUT
Definition: msg_xml.h:94
#define CRMD_ACTION_PROMOTE
Definition: crm.h:156
#define XML_LRM_ATTR_OP_RESTART
Definition: msg_xml.h:272
void get_rsc_attributes(GHashTable *meta_hash, resource_t *rsc, node_t *node, pe_working_set_t *data_set)
Definition: complex.c:153
gboolean fixed
Definition: status.h:163
node_t * pe_find_node(GListPtr node_list, const char *uname)
Definition: status.c:298
int get_failcount(node_t *node, resource_t *rsc, time_t *last_failure, pe_working_set_t *data_set)
Definition: utils.c:1497
enum action_tasks text2task(const char *task)
Definition: common.c:225
no_quorum_policy_t no_quorum_policy
Definition: status.h:94
GListPtr find_actions_exact(GListPtr input, const char *key, node_t *on_node)
Definition: utils.c:1230
gboolean is_remote_node(node_t *node)
Definition: utils.c:2061
const char * pe_pref(GHashTable *options, const char *name)
Definition: common.c:182
void dump_node_capacity(int level, const char *comment, node_t *node)
Definition: utils.c:262
char * clone_name
Definition: status.h:241
action_t * find_first_action(GListPtr input, const char *uuid, const char *task, node_t *on_node)
Definition: utils.c:1165
xmlNode * params_restart
Definition: internal.h:259
xmlNode * op_entry
Definition: status.h:306
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
Definition: logging.h:196
resource_t * uber_parent(resource_t *rsc)
Definition: complex.c:780
int id
Definition: status.h:301
resource_t * remote_rsc
Definition: status.h:145
#define clear_bit(word, bit)
Definition: crm_internal.h:220
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:1284
#define RSC_START
Definition: crm.h:173
int get_target_rc(xmlNode *xml_op)
Definition: unpack.c:2904
GHashTable * tickets
Definition: status.h:97
enum rsc_role_e role
Definition: status.h:277
#define XML_OP_ATTR_ON_FAIL
Definition: msg_xml.h:220
GListPtr children
Definition: status.h:284
gboolean get_target_role(resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:1729
void print_resource(int log_level, const char *pre_text, resource_t *rsc, gboolean details)
Definition: utils.c:1070
GListPtr actions_before
Definition: status.h:347
#define crm_time_log_duration
Definition: iso8601.h:73
gboolean order_actions(action_t *lh_action, action_t *rh_action, enum pe_ordering order)
Definition: utils.c:1765
gboolean is_remote_node
Definition: status.h:262
#define XML_LRM_ATTR_OP_SECURE
Definition: msg_xml.h:273
GHashTable * extra
Definition: status.h:325
char * id
Definition: status.h:240
GHashTable * parameters
Definition: status.h:281
#define CRMD_ACTION_START
Definition: crm.h:150
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:2894
int get_failcount_all(node_t *node, resource_t *rsc, time_t *last_failure, pe_working_set_t *data_set)
Definition: utils.c:1696
gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data)
#define XML_TAG_ATTR_SETS
Definition: msg_xml.h:173
GHashTable * utilization
Definition: status.h:150
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:257
const char * role2text(enum rsc_role_e role)
Definition: common.c:338
void hash2field(gpointer key, gpointer value, gpointer user_data)
Definition: xml.c:5008
gboolean add_tag_ref(GHashTable *tags, const char *tag_name, const char *obj_ref)
Definition: utils.c:2198
#define CRMD_ACTION_STOP
Definition: crm.h:153
#define pe_rsc_starting
Definition: status.h:193
#define pe_warn(fmt...)
Definition: internal.h:27
struct node_shared_s * details
Definition: status.h:165
char * calculate_operation_digest(xmlNode *local_cib, const char *version)
Calculate and return digest of XML operation.
Definition: digest.c:175
#define CRMD_ACTION_DEMOTE
Definition: crm.h:158
#define set_bit(word, bit)
Definition: crm_internal.h:219
gboolean unclean
Definition: status.h:135
#define crm_debug(fmt, args...)
Definition: logging.h:253
Utility functions.
#define XML_ATTR_ID
Definition: msg_xml.h:100
GListPtr find_recurring_actions(GListPtr input, node_t *not_on_node)
Definition: utils.c:1107
char * digest_all_calc
Definition: internal.h:260
char * clone_strip(const char *last_rsc_id)
Definition: unpack.c:1500
crm_time_t * crm_time_calculate_duration(crm_time_t *dt, crm_time_t *value)
Definition: iso8601.c:1064
ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
Definition: utils.c:1846
char * score2char(int score)
Definition: utils.c:268
resource_object_functions_t * fns
Definition: status.h:249
char * task
Definition: status.h:308
#define sort_return(an_int, why)
Definition: utils.c:1318
void pe_free_action(action_t *action)
Definition: utils.c:1086
resource_t * container
Definition: status.h:290
GHashTable * allowed_nodes
Definition: status.h:275
unsigned long long crm_get_interval(const char *input)
Definition: utils.c:714
GHashTable * digest_cache
Definition: status.h:153
#define crm_trace(fmt, args...)
Definition: logging.h:254
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:129
enum rsc_digest_cmp_val rc
Definition: internal.h:256
void set_bit_recursive(resource_t *rsc, unsigned long long flag)
Definition: utils.c:2116
char * digest_secure_calc
Definition: internal.h:261
resource_t * rsc_contains_remote_node(pe_working_set_t *data_set, resource_t *rsc)
Definition: utils.c:2070
void dump_rsc_utilization(int level, const char *comment, resource_t *rsc, node_t *node)
Definition: utils.c:283
GHashTable * meta
Definition: status.h:324
gint sort_node_uname(gconstpointer a, gconstpointer b)
Definition: utils.c:165
GListPtr refs
Definition: status.h:361
const char * stonith_action
Definition: status.h:87
const char * crm_element_value_const(const xmlNode *data, const char *name)
Definition: xml.c:4025
int get_failcount_full(node_t *node, resource_t *rsc, time_t *last_failure, bool effective, xmlNode *xml_op, pe_working_set_t *data_set)
Definition: utils.c:1622
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:234
gboolean is_baremetal_remote_node(node_t *node)
Definition: utils.c:2043
void pe_fence_node(pe_working_set_t *data_set, node_t *node, const char *reason)
Definition: unpack.c:66
#define XML_TAG_META_SETS
Definition: msg_xml.h:174
GListPtr actions
Definition: status.h:107
Wrappers for and extensions to libxml2.
GHashTable * config_hash
Definition: status.h:96
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:2793
long long int crm_time_get_seconds_since_epoch(crm_time_t *dt)
Definition: iso8601.c:305
int crm_element_value_int(xmlNode *data, const char *name, int *dest)
Definition: xml.c:4006
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5839
unsigned long long flags
Definition: status.h:264
long long crm_int_helper(const char *text, char **end_text)
Definition: utils.c:588
char * crm_itoa(int an_int)
Definition: utils.c:432
gboolean crm_is_true(const char *s)
Definition: utils.c:674
#define crm_time_log(level, prefix, dt, flags)
Definition: iso8601.h:66
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
Definition: cib_utils.c:230
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:203
char * uuid
Definition: status.h:309
#define XML_LRM_ATTR_RESTART_DIGEST
Definition: msg_xml.h:274
void unpack_operation(action_t *action, xmlNode *xml_obj, resource_t *container, pe_working_set_t *data_set)
Definition: utils.c:656
#define crm_time_log_with_timezone
Definition: iso8601.h:72
enum rsc_role_e text2role(const char *role)
Definition: common.c:358
xmlNode * input
Definition: status.h:81
GListPtr fillers
Definition: status.h:291
void filter_action_parameters(xmlNode *param_set, const char *version)
Definition: utils.c:1048
int failure_timeout
Definition: status.h:258
xmlNode * params_all
Definition: internal.h:257
int remote_reconnect_interval
Definition: status.h:297
gboolean decode_transition_magic(const char *magic, char **uuid, int *transition_id, int *action_id, int *op_status, int *op_rc, int *target_rc)
Definition: utils.c:939
GListPtr find_actions(GListPtr input, const char *key, node_t *on_node)
Definition: utils.c:1195
#define XML_LRM_ATTR_TARGET_UUID
Definition: msg_xml.h:266
node_t * node
Definition: status.h:305
long long int crm_time_get_seconds(crm_time_t *dt)
Definition: iso8601.c:269
gboolean(* active)(resource_t *, gboolean)
Definition: complex.h:47
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Definition: xml.c:5024
action_t * action
Definition: status.h:412
GListPtr actions
Definition: status.h:269
void dump_node_scores_worker(int level, const char *file, const char *function, int line, resource_t *rsc, const char *comment, GHashTable *nodes)
Definition: utils.c:174
pe_ordering
Definition: status.h:371
void(* print)(resource_t *, const char *, long, void *)
Definition: complex.h:46
#define pe_rsc_unique
Definition: status.h:177
gint sort_rsc_index(gconstpointer a, gconstpointer b)
Definition: utils.c:305
GHashTable * meta
Definition: status.h:280
void trigger_unfencing(resource_t *rsc, node_t *node, const char *reason, action_t *dependency, pe_working_set_t *data_set)
Definition: utils.c:2163
const char * rsc_printable_id(resource_t *rsc)
Definition: utils.c:2015
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:414
#define pe_set_action_bit(action, bit)
Definition: internal.h:30
int char2score(const char *score)
Definition: utils.c:216
#define crm_err(fmt, args...)
Definition: logging.h:248
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:145
#define RSC_STATUS
Definition: crm.h:187
int crm_parse_int(const char *text, const char *default_text)
Definition: utils.c:634
#define RSC_PROMOTE
Definition: crm.h:179
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:98
GHashTable * attrs
Definition: status.h:147
#define pe_clear_action_bit(action, bit)
Definition: internal.h:31
op_digest_cache_t * rsc_action_digest_cmp(resource_t *rsc, xmlNode *xml_op, node_t *node, pe_working_set_t *data_set)
Definition: utils.c:1925
enum rsc_role_e next_role
Definition: status.h:278
gboolean online
Definition: status.h:131
void xml_remove_prop(xmlNode *obj, const char *name)
Definition: xml.c:4043
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition: xpath.c:64
gboolean shutdown
Definition: status.h:137
void print_str_str(gpointer key, gpointer value, gpointer user_data)
Definition: utils.c:1062
GListPtr actions_after
Definition: status.h:348
xmlNode * params_secure
Definition: internal.h:258
int merge_weights(int w1, int w2)
Definition: common.c:377
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:270
#define pe_rsc_managed
Definition: status.h:172
#define CRMD_ACTION_MIGRATE
Definition: crm.h:147
enum rsc_role_e fail_role
Definition: status.h:315
char * id
Definition: status.h:360
#define CRM_ASSERT(expr)
Definition: error.h:35
char data[0]
Definition: internal.h:58
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:83
int crm_time_compare(crm_time_t *dt, crm_time_t *rhs)
Definition: iso8601.c:1141
enum node_type type
Definition: status.h:148
node_t * allocated_to
Definition: status.h:272
rsc_role_e
Definition: common.h:81
char * generate_op_key(const char *rsc_id, const char *op_type, int interval)
Definition: utils.c:794
node_t * pe_find_node_id(GListPtr node_list, const char *id)
Definition: status.c:282
enum pe_action_flags flags
Definition: status.h:312
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:269
gboolean standby
Definition: status.h:355
Definition: status.h:359
#define XML_OP_ATTR_START_DELAY
Definition: msg_xml.h:221
#define pe_flag_have_quorum
Definition: status.h:57
int rsc_discover_mode
Definition: status.h:166
void unpack_instance_attributes(xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now)
Definition: rules.c:686
action_t * get_pseudo_op(const char *name, pe_working_set_t *data_set)
Definition: utils.c:1817
gboolean granted
Definition: status.h:353
Definition: status.h:161
action_t * pe_fence_op(node_t *node, const char *op, bool optional, pe_working_set_t *data_set)
Definition: utils.c:2129
resource_t * rsc
Definition: status.h:304
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:259
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:24
GHashTable * singletons
Definition: status.h:98
#define ID(x)
Definition: msg_xml.h:408
unsigned long long flags
Definition: status.h:90
#define pe_err(fmt...)
Definition: internal.h:26
xmlNode * ops_xml
Definition: status.h:244
resource_t * pe_find_resource(GListPtr rsc_list, const char *id_rh)
Definition: status.c:252
#define pe_rsc_needs_fencing
Definition: status.h:203
#define safe_str_eq(a, b)
Definition: util.h:74
char * id
Definition: status.h:352
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define crm_str_hash
Definition: crm.h:196
gint sort_rsc_priority(gconstpointer a, gconstpointer b)
Definition: utils.c:332
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:45
void print_node(const char *pre_text, node_t *node, gboolean details)
Definition: utils.c:1026
#define pe_flag_sanitized
Definition: status.h:78
#define pe_rsc_fence_device
Definition: status.h:178
GList * GListPtr
Definition: crm.h:190
#define CRMD_ACTION_CANCEL
Definition: crm.h:145
crm_time_t * now
Definition: status.h:82
#define XML_TAG_PARAMS
Definition: msg_xml.h:176
#define crm_info(fmt, args...)
Definition: logging.h:251
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: utils.c:1428
char * digest_restart_calc
Definition: internal.h:262
GListPtr node_list_dup(GListPtr list1, gboolean reset, gboolean filter)
Definition: utils.c:139
char * score2char_stack(int score, char *buf, size_t len)
Definition: utils.c:254
#define crm_time_log_date
Definition: iso8601.h:70
GHashTable * state
Definition: status.h:356
#define pe_flag_stonith_enabled
Definition: status.h:62
action_tasks
Definition: common.h:52
void clear_bit_recursive(resource_t *rsc, unsigned long long flag)
Definition: utils.c:2103
int priority
Definition: status.h:255
#define CRMD_ACTION_STATUS
Definition: crm.h:164
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:115