pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcmk_sched_utils.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 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 General Public License version 2
7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 #include <crm/msg_xml.h>
12 #include <crm/lrmd.h> // lrmd_event_data_t
13 #include <pacemaker-internal.h>
14 
16 rsc2node_new(const char *id, pe_resource_t *rsc,
17  int node_weight, const char *discover_mode,
18  pe_node_t *foo_node, pe_working_set_t *data_set)
19 {
20  pe__location_t *new_con = NULL;
21 
22  if (rsc == NULL || id == NULL) {
23  pe_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc);
24  return NULL;
25 
26  } else if (foo_node == NULL) {
27  CRM_CHECK(node_weight == 0, return NULL);
28  }
29 
30  new_con = calloc(1, sizeof(pe__location_t));
31  if (new_con != NULL) {
32  new_con->id = strdup(id);
33  new_con->rsc_lh = rsc;
34  new_con->node_list_rh = NULL;
35  new_con->role_filter = RSC_ROLE_UNKNOWN;
36 
37 
38  if (discover_mode == NULL || safe_str_eq(discover_mode, "always")) {
40  } else if (safe_str_eq(discover_mode, "never")) {
42  } else if (safe_str_eq(discover_mode, "exclusive")) {
44  rsc->exclusive_discover = TRUE;
45  } else {
46  pe_err("Invalid %s value %s in location constraint", XML_LOCATION_ATTR_DISCOVERY, discover_mode);
47  }
48 
49  if (foo_node != NULL) {
50  pe_node_t *copy = pe__copy_node(foo_node);
51 
52  copy->weight = node_weight;
53  new_con->node_list_rh = g_list_prepend(NULL, copy);
54  }
55 
56  data_set->placement_constraints = g_list_prepend(data_set->placement_constraints, new_con);
57  rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con);
58  }
59 
60  return new_con;
61 }
62 
63 gboolean
65 {
66  if (node == NULL) {
67  return FALSE;
68  }
69 #if 0
70  if (node->weight < 0) {
71  return FALSE;
72  }
73 #endif
74 
75  if (node->details->online == FALSE
76  || node->details->shutdown || node->details->unclean
77  || node->details->standby || node->details->maintenance) {
78  crm_trace("%s: online=%d, unclean=%d, standby=%d, maintenance=%d",
79  node->details->uname, node->details->online,
80  node->details->unclean, node->details->standby, node->details->maintenance);
81  return FALSE;
82  }
83  return TRUE;
84 }
85 
94 GHashTable *
95 pcmk__copy_node_table(GHashTable *nodes)
96 {
97  GHashTable *new_table = NULL;
98  GHashTableIter iter;
99  pe_node_t *node = NULL;
100 
101  if (nodes == NULL) {
102  return NULL;
103  }
104  new_table = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free);
105  g_hash_table_iter_init(&iter, nodes);
106  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
107  pe_node_t *new_node = pe__copy_node(node);
108 
109  g_hash_table_insert(new_table, (gpointer) new_node->details->id,
110  new_node);
111  }
112  return new_table;
113 }
114 
124 GList *
125 pcmk__copy_node_list(const GList *list, bool reset)
126 {
127  GList *result = NULL;
128 
129  for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
130  pe_node_t *new_node = NULL;
131  pe_node_t *this_node = (pe_node_t *) gIter->data;
132 
133  new_node = pe__copy_node(this_node);
134  if (reset) {
135  new_node->weight = 0;
136  }
137  result = g_list_prepend(result, new_node);
138  }
139  return result;
140 }
141 
142 struct node_weight_s {
143  pe_node_t *active;
144  pe_working_set_t *data_set;
145 };
146 
147 /* return -1 if 'a' is more preferred
148  * return 1 if 'b' is more preferred
149  */
150 
151 static gint
152 sort_node_weight(gconstpointer a, gconstpointer b, gpointer data)
153 {
154  const pe_node_t *node1 = (const pe_node_t *)a;
155  const pe_node_t *node2 = (const pe_node_t *)b;
156  struct node_weight_s *nw = data;
157 
158  int node1_weight = 0;
159  int node2_weight = 0;
160 
161  int result = 0;
162 
163  if (a == NULL) {
164  return 1;
165  }
166  if (b == NULL) {
167  return -1;
168  }
169 
170  node1_weight = node1->weight;
171  node2_weight = node2->weight;
172 
173  if (can_run_resources(node1) == FALSE) {
174  node1_weight = -INFINITY;
175  }
176  if (can_run_resources(node2) == FALSE) {
177  node2_weight = -INFINITY;
178  }
179 
180  if (node1_weight > node2_weight) {
181  crm_trace("%s (%d) > %s (%d) : weight",
182  node1->details->uname, node1_weight, node2->details->uname, node2_weight);
183  return -1;
184  }
185 
186  if (node1_weight < node2_weight) {
187  crm_trace("%s (%d) < %s (%d) : weight",
188  node1->details->uname, node1_weight, node2->details->uname, node2_weight);
189  return 1;
190  }
191 
192  crm_trace("%s (%d) == %s (%d) : weight",
193  node1->details->uname, node1_weight, node2->details->uname, node2_weight);
194 
195  if (safe_str_eq(nw->data_set->placement_strategy, "minimal")) {
196  goto equal;
197  }
198 
199  if (safe_str_eq(nw->data_set->placement_strategy, "balanced")) {
200  result = compare_capacity(node1, node2);
201  if (result < 0) {
202  crm_trace("%s > %s : capacity (%d)",
203  node1->details->uname, node2->details->uname, result);
204  return -1;
205  } else if (result > 0) {
206  crm_trace("%s < %s : capacity (%d)",
207  node1->details->uname, node2->details->uname, result);
208  return 1;
209  }
210  }
211 
212  /* now try to balance resources across the cluster */
213  if (node1->details->num_resources < node2->details->num_resources) {
214  crm_trace("%s (%d) > %s (%d) : resources",
215  node1->details->uname, node1->details->num_resources,
216  node2->details->uname, node2->details->num_resources);
217  return -1;
218 
219  } else if (node1->details->num_resources > node2->details->num_resources) {
220  crm_trace("%s (%d) < %s (%d) : resources",
221  node1->details->uname, node1->details->num_resources,
222  node2->details->uname, node2->details->num_resources);
223  return 1;
224  }
225 
226  if (nw->active && nw->active->details == node1->details) {
227  crm_trace("%s (%d) > %s (%d) : active",
228  node1->details->uname, node1->details->num_resources,
229  node2->details->uname, node2->details->num_resources);
230  return -1;
231  } else if (nw->active && nw->active->details == node2->details) {
232  crm_trace("%s (%d) < %s (%d) : active",
233  node1->details->uname, node1->details->num_resources,
234  node2->details->uname, node2->details->num_resources);
235  return 1;
236  }
237  equal:
238  crm_trace("%s = %s", node1->details->uname, node2->details->uname);
239  return strcmp(node1->details->uname, node2->details->uname);
240 }
241 
242 GList *
243 sort_nodes_by_weight(GList *nodes, pe_node_t *active_node,
244  pe_working_set_t *data_set)
245 {
246  struct node_weight_s nw = { active_node, data_set };
247 
248  return g_list_sort_with_data(nodes, sort_node_weight, &nw);
249 }
250 
251 void
253 {
254  if (rsc->allocated_to) {
255  pe_node_t *old = rsc->allocated_to;
256 
257  crm_info("Deallocating %s from %s", rsc->id, old->details->uname);
259  rsc->allocated_to = NULL;
260 
261  old->details->allocated_rsc = g_list_remove(old->details->allocated_rsc, rsc);
262  old->details->num_resources--;
263  /* old->count--; */
265  free(old);
266  }
267 }
268 
269 gboolean
270 native_assign_node(pe_resource_t * rsc, GListPtr nodes, pe_node_t * chosen, gboolean force)
271 {
272  CRM_ASSERT(rsc->variant == pe_native);
273 
274  if (force == FALSE && chosen != NULL) {
275  bool unset = FALSE;
276 
277  if(chosen->weight < 0) {
278  unset = TRUE;
279 
280  // Allow the graph to assume that the remote resource will come up
281  } else if (!can_run_resources(chosen) && !pe__is_guest_node(chosen)) {
282  unset = TRUE;
283  }
284 
285  if(unset) {
286  crm_debug("All nodes for resource %s are unavailable"
287  ", unclean or shutting down (%s: %d, %d)",
288  rsc->id, chosen->details->uname, can_run_resources(chosen), chosen->weight);
290  chosen = NULL;
291  }
292  }
293 
294  /* todo: update the old node for each resource to reflect its
295  * new resource count
296  */
297 
298  native_deallocate(rsc);
300 
301  if (chosen == NULL) {
302  GListPtr gIter = NULL;
303  char *rc_inactive = crm_itoa(PCMK_OCF_NOT_RUNNING);
304 
305  crm_debug("Could not allocate a node for %s", rsc->id);
307 
308  for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
309  pe_action_t *op = (pe_action_t *) gIter->data;
310  const char *interval_ms_s = g_hash_table_lookup(op->meta, XML_LRM_ATTR_INTERVAL_MS);
311 
312  crm_debug("Processing %s", op->uuid);
313  if(safe_str_eq(RSC_STOP, op->task)) {
314  update_action_flags(op, pe_action_optional | pe_action_clear, __FUNCTION__, __LINE__);
315 
316  } else if(safe_str_eq(RSC_START, op->task)) {
317  update_action_flags(op, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
318  /* set_bit(rsc->flags, pe_rsc_block); */
319 
320  } else if (interval_ms_s && safe_str_neq(interval_ms_s, "0")) {
321  if(safe_str_eq(rc_inactive, g_hash_table_lookup(op->meta, XML_ATTR_TE_TARGET_RC))) {
322  /* This is a recurring monitor for the stopped state, leave it alone */
323 
324  } else {
325  /* Normal monitor operation, cancel it */
326  update_action_flags(op, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
327  }
328  }
329  }
330 
331  free(rc_inactive);
332  return FALSE;
333  }
334 
335  crm_debug("Assigning %s to %s", chosen->details->uname, rsc->id);
336  rsc->allocated_to = pe__copy_node(chosen);
337 
338  chosen->details->allocated_rsc = g_list_prepend(chosen->details->allocated_rsc, rsc);
339  chosen->details->num_resources++;
340  chosen->count++;
341  calculate_utilization(chosen->details->utilization, rsc->utilization, FALSE);
343  __FUNCTION__, rsc, chosen);
344 
345  return TRUE;
346 }
347 
348 void
349 log_action(unsigned int log_level, const char *pre_text, pe_action_t * action, gboolean details)
350 {
351  const char *node_uname = NULL;
352  const char *node_uuid = NULL;
353 
354  if (action == NULL) {
355  crm_trace("%s%s: <NULL>", pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": ");
356  return;
357  }
358 
359  if (is_set(action->flags, pe_action_pseudo)) {
360  node_uname = NULL;
361  node_uuid = NULL;
362 
363  } else if (action->node != NULL) {
364  node_uname = action->node->details->uname;
365  node_uuid = action->node->details->id;
366  } else {
367  node_uname = "<none>";
368  node_uuid = NULL;
369  }
370 
371  switch (text2task(action->task)) {
372  case stonith_node:
373  case shutdown_crm:
374  crm_trace("%s%s%sAction %d: %s%s%s%s%s%s",
375  pre_text == NULL ? "" : pre_text,
376  pre_text == NULL ? "" : ": ",
377  is_set(action->flags,
378  pe_action_pseudo) ? "Pseudo " : is_set(action->flags,
380  "Optional " : is_set(action->flags,
381  pe_action_runnable) ? is_set(action->flags,
383  ? "" : "(Provisional) " : "!!Non-Startable!! ", action->id,
384  action->uuid, node_uname ? "\ton " : "",
385  node_uname ? node_uname : "", node_uuid ? "\t\t(" : "",
386  node_uuid ? node_uuid : "", node_uuid ? ")" : "");
387  break;
388  default:
389  crm_trace("%s%s%sAction %d: %s %s%s%s%s%s%s",
390  pre_text == NULL ? "" : pre_text,
391  pre_text == NULL ? "" : ": ",
392  is_set(action->flags,
393  pe_action_optional) ? "Optional " : is_set(action->flags,
395  ? "Pseudo " : is_set(action->flags,
396  pe_action_runnable) ? is_set(action->flags,
398  ? "" : "(Provisional) " : "!!Non-Startable!! ", action->id,
399  action->uuid, action->rsc ? action->rsc->id : "<none>",
400  node_uname ? "\ton " : "", node_uname ? node_uname : "",
401  node_uuid ? "\t\t(" : "", node_uuid ? node_uuid : "", node_uuid ? ")" : "");
402 
403  break;
404  }
405 
406  if (details) {
407  GListPtr gIter = NULL;
408 
409  crm_trace("\t\t====== Preceding Actions");
410 
411  gIter = action->actions_before;
412  for (; gIter != NULL; gIter = gIter->next) {
413  pe_action_wrapper_t *other = (pe_action_wrapper_t *) gIter->data;
414 
415  log_action(log_level + 1, "\t\t", other->action, FALSE);
416  }
417 
418  crm_trace("\t\t====== Subsequent Actions");
419 
420  gIter = action->actions_after;
421  for (; gIter != NULL; gIter = gIter->next) {
422  pe_action_wrapper_t *other = (pe_action_wrapper_t *) gIter->data;
423 
424  log_action(log_level + 1, "\t\t", other->action, FALSE);
425  }
426 
427  crm_trace("\t\t====== End");
428 
429  } else {
430  crm_trace("\t\t(before=%d, after=%d)",
431  g_list_length(action->actions_before), g_list_length(action->actions_after));
432  }
433 }
434 
435 gboolean
436 can_run_any(GHashTable * nodes)
437 {
438  GHashTableIter iter;
439  pe_node_t *node = NULL;
440 
441  if (nodes == NULL) {
442  return FALSE;
443  }
444 
445  g_hash_table_iter_init(&iter, nodes);
446  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
447  if (can_run_resources(node) && node->weight >= 0) {
448  return TRUE;
449  }
450  }
451 
452  return FALSE;
453 }
454 
455 pe_action_t *
456 create_pseudo_resource_op(pe_resource_t * rsc, const char *task, bool optional, bool runnable, pe_working_set_t *data_set)
457 {
458  pe_action_t *action = custom_action(rsc, pcmk__op_key(rsc->id, task, 0),
459  task, NULL, optional, TRUE, data_set);
460  update_action_flags(action, pe_action_pseudo, __FUNCTION__, __LINE__);
461  update_action_flags(action, pe_action_runnable, __FUNCTION__, __LINE__);
462  if(runnable) {
463  update_action_flags(action, pe_action_runnable, __FUNCTION__, __LINE__);
464  }
465  return action;
466 }
467 
480 pe_action_t *
481 pe_cancel_op(pe_resource_t *rsc, const char *task, guint interval_ms,
482  pe_node_t *node, pe_working_set_t *data_set)
483 {
484  pe_action_t *cancel_op;
485  char *interval_ms_s = crm_strdup_printf("%u", interval_ms);
486 
487  // @TODO dangerous if possible to schedule another action with this key
488  char *key = pcmk__op_key(rsc->id, task, interval_ms);
489 
490  cancel_op = custom_action(rsc, key, RSC_CANCEL, node, FALSE, TRUE,
491  data_set);
492 
493  free(cancel_op->task);
494  cancel_op->task = strdup(RSC_CANCEL);
495 
496  free(cancel_op->cancel_task);
497  cancel_op->cancel_task = strdup(task);
498 
499  add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, task);
500  add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL_MS, interval_ms_s);
501  free(interval_ms_s);
502 
503  return cancel_op;
504 }
505 
515 pe_action_t *
517 {
518  char *shutdown_id = crm_strdup_printf("%s-%s", CRM_OP_SHUTDOWN,
519  node->details->uname);
520 
521  pe_action_t *shutdown_op = custom_action(NULL, shutdown_id, CRM_OP_SHUTDOWN,
522  node, FALSE, TRUE, data_set);
523 
524  crm_notice("Scheduling shutdown of node %s", node->details->uname);
525  shutdown_constraints(node, shutdown_op, data_set);
527  return shutdown_op;
528 }
529 
530 static char *
531 generate_transition_magic(const char *transition_key, int op_status, int op_rc)
532 {
533  CRM_CHECK(transition_key != NULL, return NULL);
534  return crm_strdup_printf("%d:%d;%s", op_status, op_rc, transition_key);
535 }
536 
537 static void
538 append_digest(lrmd_event_data_t *op, xmlNode *update, const char *version,
539  const char *magic, int level)
540 {
541  /* this will enable us to later determine that the
542  * resource's parameters have changed and we should force
543  * a restart
544  */
545  char *digest = NULL;
546  xmlNode *args_xml = NULL;
547 
548  if (op->params == NULL) {
549  return;
550  }
551 
552  args_xml = create_xml_node(NULL, XML_TAG_PARAMS);
553  g_hash_table_foreach(op->params, hash2field, args_xml);
554  pcmk__filter_op_for_digest(args_xml);
555  digest = calculate_operation_digest(args_xml, version);
556 
557 #if 0
558  if (level < get_crm_log_level()
559  && op->interval_ms == 0 && crm_str_eq(op->op_type, CRMD_ACTION_START, TRUE)) {
560  char *digest_source = dump_xml_unformatted(args_xml);
561 
562  do_crm_log(level, "Calculated digest %s for %s (%s). Source: %s\n",
563  digest, ID(update), magic, digest_source);
564  free(digest_source);
565  }
566 #endif
567  crm_xml_add(update, XML_LRM_ATTR_OP_DIGEST, digest);
568 
569  free_xml(args_xml);
570  free(digest);
571 }
572 
573 #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
574 
589 xmlNode *
591  const char *caller_version, int target_rc,
592  const char *node, const char *origin, int level)
593 {
594  char *key = NULL;
595  char *magic = NULL;
596  char *op_id = NULL;
597  char *op_id_additional = NULL;
598  char *local_user_data = NULL;
599  const char *exit_reason = NULL;
600 
601  xmlNode *xml_op = NULL;
602  const char *task = NULL;
603 
604  CRM_CHECK(op != NULL, return NULL);
605  do_crm_log(level, "%s: Updating resource %s after %s op %s (interval=%u)",
606  origin, op->rsc_id, op->op_type, services_lrm_status_str(op->op_status),
607  op->interval_ms);
608 
609  crm_trace("DC version: %s", caller_version);
610 
611  task = op->op_type;
612 
613  /* Record a successful reload as a start, and a failed reload as a monitor,
614  * to make life easier for the scheduler when determining the current state.
615  */
616  if (crm_str_eq(task, "reload", TRUE)) {
617  if (op->op_status == PCMK_LRM_OP_DONE) {
618  task = CRMD_ACTION_START;
619  } else {
620  task = CRMD_ACTION_STATUS;
621  }
622  }
623 
624  key = pcmk__op_key(op->rsc_id, task, op->interval_ms);
625  if (crm_str_eq(task, CRMD_ACTION_NOTIFY, TRUE)) {
626  const char *n_type = crm_meta_value(op->params, "notify_type");
627  const char *n_task = crm_meta_value(op->params, "notify_operation");
628 
629  CRM_LOG_ASSERT(n_type != NULL);
630  CRM_LOG_ASSERT(n_task != NULL);
631  op_id = pcmk__notify_key(op->rsc_id, n_type, n_task);
632 
633  if (op->op_status != PCMK_LRM_OP_PENDING) {
634  /* Ignore notify errors.
635  *
636  * @TODO It might be better to keep the correct result here, and
637  * ignore it in process_graph_event().
638  */
640  op->rc = 0;
641  }
642 
643  } else if (did_rsc_op_fail(op, target_rc)) {
644  op_id = pcmk__op_key(op->rsc_id, "last_failure", 0);
645  if (op->interval_ms == 0) {
646  // Ensure 'last' gets updated, in case record-pending is true
647  op_id_additional = pcmk__op_key(op->rsc_id, "last", 0);
648  }
649  exit_reason = op->exit_reason;
650 
651  } else if (op->interval_ms > 0) {
652  op_id = strdup(key);
653 
654  } else {
655  op_id = pcmk__op_key(op->rsc_id, "last", 0);
656  }
657 
658  again:
659  xml_op = find_entity(parent, XML_LRM_TAG_RSC_OP, op_id);
660  if (xml_op == NULL) {
661  xml_op = create_xml_node(parent, XML_LRM_TAG_RSC_OP);
662  }
663 
664  if (op->user_data == NULL) {
665  crm_debug("Generating fake transition key for: " PCMK__OP_FMT
666  " %d from %s", op->rsc_id, op->op_type, op->interval_ms,
667  op->call_id, origin);
668  local_user_data = pcmk__transition_key(-1, op->call_id, target_rc,
669  FAKE_TE_ID);
670  op->user_data = local_user_data;
671  }
672 
673  if(magic == NULL) {
674  magic = generate_transition_magic(op->user_data, op->op_status, op->rc);
675  }
676 
677  crm_xml_add(xml_op, XML_ATTR_ID, op_id);
678  crm_xml_add(xml_op, XML_LRM_ATTR_TASK_KEY, key);
679  crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task);
680  crm_xml_add(xml_op, XML_ATTR_ORIGIN, origin);
681  crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, caller_version);
683  crm_xml_add(xml_op, XML_ATTR_TRANSITION_MAGIC, magic);
684  crm_xml_add(xml_op, XML_LRM_ATTR_EXIT_REASON, exit_reason == NULL ? "" : exit_reason);
685  crm_xml_add(xml_op, XML_LRM_ATTR_TARGET, node); /* For context during triage */
686 
688  crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op->rc);
691 
692  if (compare_version("2.1", caller_version) <= 0) {
693  if (op->t_run || op->t_rcchange || op->exec_time || op->queue_time) {
694  crm_trace("Timing data (" PCMK__OP_FMT
695  "): last=%u change=%u exec=%u queue=%u",
696  op->rsc_id, op->op_type, op->interval_ms,
697  op->t_run, op->t_rcchange, op->exec_time, op->queue_time);
698 
699  if (op->interval_ms == 0) {
701  (long long) op->t_run);
702 
703  // @COMPAT last-run is deprecated
705  (long long) op->t_run);
706 
707  } else if(op->t_rcchange) {
708  /* last-run is not accurate for recurring ops */
710  (long long) op->t_rcchange);
711 
712  } else {
713  /* ...but is better than nothing otherwise */
715  (long long) op->t_run);
716  }
717 
720  }
721  }
722 
723  if (crm_str_eq(op->op_type, CRMD_ACTION_MIGRATE, TRUE)
724  || crm_str_eq(op->op_type, CRMD_ACTION_MIGRATED, TRUE)) {
725  /*
726  * Record migrate_source and migrate_target always for migrate ops.
727  */
728  const char *name = XML_LRM_ATTR_MIGRATE_SOURCE;
729 
730  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
731 
733  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
734  }
735 
736  append_digest(op, xml_op, caller_version, magic, LOG_DEBUG);
737 
738  if (op_id_additional) {
739  free(op_id);
740  op_id = op_id_additional;
741  op_id_additional = NULL;
742  goto again;
743  }
744 
745  if (local_user_data) {
746  free(local_user_data);
747  op->user_data = NULL;
748  }
749  free(magic);
750  free(op_id);
751  free(key);
752  return xml_op;
753 }
GList * pcmk__copy_node_list(const GList *list, bool reset)
pe_action_t * pe_cancel_op(pe_resource_t *rsc, const char *name, guint interval_ms, pe_node_t *node, pe_working_set_t *data_set)
#define LOG_TRACE
Definition: logging.h:36
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:233
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:280
GListPtr allocated_rsc
Definition: pe_types.h:219
enum rsc_role_e role_filter
Definition: internal.h:57
#define RSC_STOP
Definition: crm.h:199
#define crm_notice(fmt, args...)
Definition: logging.h:365
#define CRMD_ACTION_MIGRATED
Definition: crm.h:169
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:263
#define INFINITY
Definition: crm.h:95
const char * user_data
Definition: lrmd.h:207
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:784
const char * rsc_id
Definition: lrmd.h:203
const char * crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
Create an XML attribute with specified name and unsigned value.
Definition: nvpair.c:446
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:360
GList * sort_nodes_by_weight(GList *nodes, pe_node_t *active_node, pe_working_set_t *data_set)
int count
Definition: pe_types.h:230
unsigned int queue_time
Definition: lrmd.h:233
pe_resource_t * rsc
Definition: pe_types.h:388
enum rsc_role_e next_role
Definition: pe_types.h:355
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:424
gboolean exclusive_discover
Definition: pe_types.h:336
char * cancel_task
Definition: pe_types.h:394
#define CRMD_ACTION_NOTIFY
Definition: crm.h:182
pe_action_t * sched_shutdown_op(pe_node_t *node, pe_working_set_t *data_set)
#define XML_LOCATION_ATTR_DISCOVERY
Definition: msg_xml.h:315
xmlNode * find_entity(xmlNode *parent, const char *node_name, const char *id)
Definition: xml.c:1829
#define XML_RSC_OP_T_EXEC
Definition: msg_xml.h:282
const char * crm_meta_value(GHashTable *hash, const char *field)
Definition: utils.c:476
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:316
pe_node_t * pe__copy_node(const pe_node_t *this_node)
Definition: utils.c:139
#define XML_LRM_ATTR_OP_DIGEST
Definition: msg_xml.h:273
Resource agent executor.
unsigned int t_rcchange
Definition: lrmd.h:229
void pcmk__filter_op_for_digest(xmlNode *param_set)
Definition: operations.c:272
enum action_tasks text2task(const char *task)
Definition: common.c:358
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:219
#define clear_bit(word, bit)
Definition: crm_internal.h:69
pe_resource_t * rsc_lh
Definition: internal.h:56
enum ocf_exitcode rc
Definition: lrmd.h:221
#define RSC_START
Definition: crm.h:196
pe_node_t * allocated_to
Definition: pe_types.h:347
pe_action_t * action
Definition: pe_types.h:507
#define XML_RSC_OP_T_QUEUE
Definition: msg_xml.h:283
gboolean can_run_resources(const pe_node_t *node)
GListPtr actions_before
Definition: pe_types.h:425
gboolean native_assign_node(pe_resource_t *rsc, GListPtr candidates, pe_node_t *chosen, gboolean force)
const char * action
Definition: pcmk_fence.c:29
unsigned int exec_time
Definition: lrmd.h:231
#define XML_ATTR_ORIGIN
Definition: msg_xml.h:91
void calculate_utilization(GHashTable *current_utilization, GHashTable *utilization, gboolean plus)
#define CRMD_ACTION_START
Definition: crm.h:171
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:261
GListPtr placement_constraints
Definition: pe_types.h:148
#define pe_rsc_provisional
Definition: pe_types.h:245
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:260
pe__location_t * rsc2node_new(const char *id, pe_resource_t *rsc, int weight, const char *discovery_mode, pe_node_t *node, pe_working_set_t *data_set)
void * params
Definition: lrmd.h:240
int weight
Definition: pe_types.h:228
char * calculate_operation_digest(xmlNode *local_cib, const char *version)
Calculate and return digest of XML operation.
Definition: digest.c:167
enum pe_discover_e discover_mode
Definition: internal.h:58
op_status
Definition: services.h:118
#define set_bit(word, bit)
Definition: crm_internal.h:68
const char * exit_reason
Definition: lrmd.h:248
char * pcmk__notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
Definition: operations.c:129
pe_action_t * create_pseudo_resource_op(pe_resource_t *rsc, const char *task, bool optional, bool runnable, pe_working_set_t *data_set)
#define crm_debug(fmt, args...)
Definition: logging.h:368
#define XML_ATTR_ID
Definition: msg_xml.h:96
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:107
xmlNode * pcmk__create_history_xml(xmlNode *parent, lrmd_event_data_t *event, const char *caller_version, int target_rc, const char *node, const char *origin, int level)
char * task
Definition: pe_types.h:392
#define crm_trace(fmt, args...)
Definition: logging.h:369
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:150
GHashTable * meta
Definition: pe_types.h:402
struct pe_node_shared_s * details
Definition: pe_types.h:231
pe_node_t * node
Definition: pe_types.h:389
unsigned long long flags
Definition: pe_types.h:332
const char * uname
Definition: pe_types.h:196
#define XML_ATTR_TE_NOWAIT
Definition: msg_xml.h:363
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1976
GHashTable * utilization
Definition: pe_types.h:359
#define XML_LRM_ATTR_MIGRATE_TARGET
Definition: msg_xml.h:286
gboolean standby
Definition: pe_types.h:201
#define XML_LRM_ATTR_EXIT_REASON
Definition: msg_xml.h:278
char * uuid
Definition: pe_types.h:393
gboolean update_action_flags(pe_action_t *action, enum pe_action_flags flags, const char *source, int line)
void free_xml(xmlNode *child)
Definition: xml.c:2136
enum pe_obj_types variant
Definition: pe_types.h:314
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:326
gboolean can_run_any(GHashTable *nodes)
GListPtr actions
Definition: pe_types.h:343
GListPtr rsc_location
Definition: pe_types.h:342
#define CRM_OP_SHUTDOWN
Definition: crm.h:140
const char * id
Definition: pe_types.h:195
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:40
const char * op_type
Definition: lrmd.h:205
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:474
GHashTable * pcmk__copy_node_table(GHashTable *nodes)
unsigned int t_run
Definition: lrmd.h:227
#define XML_ATTR_TRANSITION_KEY
Definition: msg_xml.h:361
unsigned int get_crm_log_level(void)
Definition: logging.c:922
#define FAKE_TE_ID
gboolean show_utilization
void log_action(unsigned int log_level, const char *pre_text, pe_action_t *action, gboolean details)
gboolean pe__is_guest_node(pe_node_t *node)
Definition: remote.c:47
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:573
gboolean did_rsc_op_fail(lrmd_event_data_t *event, int target_rc)
Definition: operations.c:340
#define CRM_ASSERT(expr)
Definition: results.h:42
int compare_version(const char *version1, const char *version2)
Definition: utils.c:227
void dump_rsc_utilization(int level, const char *comment, pe_resource_t *rsc, pe_node_t *node)
Definition: utils.c:412
GListPtr actions_after
Definition: pe_types.h:426
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:258
char * dump_xml_unformatted(xmlNode *msg)
Definition: xml.c:3321
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:272
#define CRMD_ACTION_MIGRATE
Definition: crm.h:168
#define crm_str_hash
Definition: util.h:66
GHashTable * utilization
Definition: pe_types.h:222
gboolean shutdown
Definition: pe_types.h:206
char data[0]
Definition: internal.h:90
#define crm_str(x)
Definition: logging.h:389
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:270
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:79
char * pcmk__transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition: operations.c:196
enum pe_action_flags flags
Definition: pe_types.h:397
gboolean maintenance
Definition: pe_types.h:209
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:271
void native_deallocate(pe_resource_t *rsc)
#define RSC_CANCEL
Definition: crm.h:191
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:262
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:228
#define XML_RSC_OP_LAST_RUN
Definition: msg_xml.h:281
int compare_capacity(const pe_node_t *node1, const pe_node_t *node2)
#define ID(x)
Definition: msg_xml.h:418
#define pe_err(fmt...)
Definition: internal.h:21
#define safe_str_eq(a, b)
Definition: util.h:65
#define PCMK__OP_FMT
Definition: internal.h:147
char * name
Definition: pcmk_fence.c:30
#define XML_LRM_ATTR_MIGRATE_SOURCE
Definition: msg_xml.h:285
gboolean unclean
Definition: pe_types.h:204
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define LOG_STDOUT
Definition: logging.h:41
GList * GListPtr
Definition: crm.h:214
gboolean shutdown_constraints(pe_node_t *node, pe_action_t *shutdown_op, pe_working_set_t *data_set)
#define XML_TAG_PARAMS
Definition: msg_xml.h:169
#define crm_info(fmt, args...)
Definition: logging.h:366
uint32_t version
Definition: remote.c:147
gboolean online
Definition: pe_types.h:200
#define XML_ATTR_TE_TARGET_RC
Definition: msg_xml.h:364
guint interval_ms
Definition: lrmd.h:214
char * id
Definition: pe_types.h:305
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:485
#define CRMD_ACTION_STATUS
Definition: crm.h:185