pacemaker  2.1.0-7c3f660
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-2021 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU 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
14 #include <pacemaker-internal.h>
15 
17 rsc2node_new(const char *id, pe_resource_t *rsc,
18  int node_weight, const char *discover_mode,
19  pe_node_t *foo_node, pe_working_set_t *data_set)
20 {
21  pe__location_t *new_con = NULL;
22 
23  if (rsc == NULL || id == NULL) {
24  pe_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc);
25  return NULL;
26 
27  } else if (foo_node == NULL) {
28  CRM_CHECK(node_weight == 0, return NULL);
29  }
30 
31  new_con = calloc(1, sizeof(pe__location_t));
32  if (new_con != NULL) {
33  new_con->id = strdup(id);
34  new_con->rsc_lh = rsc;
35  new_con->node_list_rh = NULL;
36  new_con->role_filter = RSC_ROLE_UNKNOWN;
37 
38 
39  if (pcmk__str_eq(discover_mode, "always", pcmk__str_null_matches | pcmk__str_casei)) {
41  } else if (pcmk__str_eq(discover_mode, "never", pcmk__str_casei)) {
43  } else if (pcmk__str_eq(discover_mode, "exclusive", pcmk__str_casei)) {
45  rsc->exclusive_discover = TRUE;
46  } else {
47  pe_err("Invalid %s value %s in location constraint", XML_LOCATION_ATTR_DISCOVERY, discover_mode);
48  }
49 
50  if (foo_node != NULL) {
51  pe_node_t *copy = pe__copy_node(foo_node);
52 
53  copy->weight = node_weight;
54  new_con->node_list_rh = g_list_prepend(NULL, copy);
55  }
56 
57  data_set->placement_constraints = g_list_prepend(data_set->placement_constraints, new_con);
58  rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con);
59  }
60 
61  return new_con;
62 }
63 
64 gboolean
66 {
67  if (node == NULL) {
68  return FALSE;
69  }
70 #if 0
71  if (node->weight < 0) {
72  return FALSE;
73  }
74 #endif
75 
76  if (node->details->online == FALSE
77  || node->details->shutdown || node->details->unclean
78  || node->details->standby || node->details->maintenance) {
79  crm_trace("%s: online=%d, unclean=%d, standby=%d, maintenance=%d",
80  node->details->uname, node->details->online,
81  node->details->unclean, node->details->standby, node->details->maintenance);
82  return FALSE;
83  }
84  return TRUE;
85 }
86 
95 GHashTable *
96 pcmk__copy_node_table(GHashTable *nodes)
97 {
98  GHashTable *new_table = NULL;
99  GHashTableIter iter;
100  pe_node_t *node = NULL;
101 
102  if (nodes == NULL) {
103  return NULL;
104  }
105  new_table = pcmk__strkey_table(NULL, free);
106  g_hash_table_iter_init(&iter, nodes);
107  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
108  pe_node_t *new_node = pe__copy_node(node);
109 
110  g_hash_table_insert(new_table, (gpointer) new_node->details->id,
111  new_node);
112  }
113  return new_table;
114 }
115 
125 GList *
126 pcmk__copy_node_list(const GList *list, bool reset)
127 {
128  GList *result = NULL;
129 
130  for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
131  pe_node_t *new_node = NULL;
132  pe_node_t *this_node = (pe_node_t *) gIter->data;
133 
134  new_node = pe__copy_node(this_node);
135  if (reset) {
136  new_node->weight = 0;
137  }
138  result = g_list_prepend(result, new_node);
139  }
140  return result;
141 }
142 
143 struct node_weight_s {
144  pe_node_t *active;
145  pe_working_set_t *data_set;
146 };
147 
148 /* return -1 if 'a' is more preferred
149  * return 1 if 'b' is more preferred
150  */
151 
152 static gint
153 sort_node_weight(gconstpointer a, gconstpointer b, gpointer data)
154 {
155  const pe_node_t *node1 = (const pe_node_t *)a;
156  const pe_node_t *node2 = (const pe_node_t *)b;
157  struct node_weight_s *nw = data;
158 
159  int node1_weight = 0;
160  int node2_weight = 0;
161 
162  int result = 0;
163 
164  if (a == NULL) {
165  return 1;
166  }
167  if (b == NULL) {
168  return -1;
169  }
170 
171  node1_weight = node1->weight;
172  node2_weight = node2->weight;
173 
174  if (can_run_resources(node1) == FALSE) {
175  node1_weight = -INFINITY;
176  }
177  if (can_run_resources(node2) == FALSE) {
178  node2_weight = -INFINITY;
179  }
180 
181  if (node1_weight > node2_weight) {
182  crm_trace("%s (%d) > %s (%d) : weight",
183  node1->details->uname, node1_weight, node2->details->uname, node2_weight);
184  return -1;
185  }
186 
187  if (node1_weight < node2_weight) {
188  crm_trace("%s (%d) < %s (%d) : weight",
189  node1->details->uname, node1_weight, node2->details->uname, node2_weight);
190  return 1;
191  }
192 
193  crm_trace("%s (%d) == %s (%d) : weight",
194  node1->details->uname, node1_weight, node2->details->uname, node2_weight);
195 
196  if (pcmk__str_eq(nw->data_set->placement_strategy, "minimal", pcmk__str_casei)) {
197  goto equal;
198  }
199 
200  if (pcmk__str_eq(nw->data_set->placement_strategy, "balanced", pcmk__str_casei)) {
201  result = compare_capacity(node1, node2);
202  if (result < 0) {
203  crm_trace("%s > %s : capacity (%d)",
204  node1->details->uname, node2->details->uname, result);
205  return -1;
206  } else if (result > 0) {
207  crm_trace("%s < %s : capacity (%d)",
208  node1->details->uname, node2->details->uname, result);
209  return 1;
210  }
211  }
212 
213  /* now try to balance resources across the cluster */
214  if (node1->details->num_resources < node2->details->num_resources) {
215  crm_trace("%s (%d) > %s (%d) : resources",
216  node1->details->uname, node1->details->num_resources,
217  node2->details->uname, node2->details->num_resources);
218  return -1;
219 
220  } else if (node1->details->num_resources > node2->details->num_resources) {
221  crm_trace("%s (%d) < %s (%d) : resources",
222  node1->details->uname, node1->details->num_resources,
223  node2->details->uname, node2->details->num_resources);
224  return 1;
225  }
226 
227  if (nw->active && nw->active->details == node1->details) {
228  crm_trace("%s (%d) > %s (%d) : active",
229  node1->details->uname, node1->details->num_resources,
230  node2->details->uname, node2->details->num_resources);
231  return -1;
232  } else if (nw->active && nw->active->details == node2->details) {
233  crm_trace("%s (%d) < %s (%d) : active",
234  node1->details->uname, node1->details->num_resources,
235  node2->details->uname, node2->details->num_resources);
236  return 1;
237  }
238  equal:
239  crm_trace("%s = %s", node1->details->uname, node2->details->uname);
240  return strcmp(node1->details->uname, node2->details->uname);
241 }
242 
243 GList *
244 sort_nodes_by_weight(GList *nodes, pe_node_t *active_node,
245  pe_working_set_t *data_set)
246 {
247  struct node_weight_s nw = { active_node, data_set };
248 
249  return g_list_sort_with_data(nodes, sort_node_weight, &nw);
250 }
251 
252 void
254 {
255  if (rsc->allocated_to) {
256  pe_node_t *old = rsc->allocated_to;
257 
258  crm_info("Deallocating %s from %s", rsc->id, old->details->uname);
260  rsc->allocated_to = NULL;
261 
262  old->details->allocated_rsc = g_list_remove(old->details->allocated_rsc, rsc);
263  old->details->num_resources--;
264  /* old->count--; */
266  free(old);
267  }
268 }
269 
270 gboolean
271 native_assign_node(pe_resource_t *rsc, pe_node_t *chosen, gboolean force)
272 {
273  pcmk__output_t *out = rsc->cluster->priv;
274 
275  CRM_ASSERT(rsc->variant == pe_native);
276 
277  if (force == FALSE && chosen != NULL) {
278  bool unset = FALSE;
279 
280  if(chosen->weight < 0) {
281  unset = TRUE;
282 
283  // Allow the graph to assume that the remote resource will come up
284  } else if (!can_run_resources(chosen) && !pe__is_guest_node(chosen)) {
285  unset = TRUE;
286  }
287 
288  if(unset) {
289  crm_debug("All nodes for resource %s are unavailable"
290  ", unclean or shutting down (%s: %d, %d)",
291  rsc->id, chosen->details->uname, can_run_resources(chosen), chosen->weight);
292  pe__set_next_role(rsc, RSC_ROLE_STOPPED, "node availability");
293  chosen = NULL;
294  }
295  }
296 
297  /* todo: update the old node for each resource to reflect its
298  * new resource count
299  */
300 
301  native_deallocate(rsc);
303 
304  if (chosen == NULL) {
305  GList *gIter = NULL;
306  char *rc_inactive = pcmk__itoa(PCMK_OCF_NOT_RUNNING);
307 
308  crm_debug("Could not allocate a node for %s", rsc->id);
309  pe__set_next_role(rsc, RSC_ROLE_STOPPED, "unable to allocate");
310 
311  for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
312  pe_action_t *op = (pe_action_t *) gIter->data;
313  const char *interval_ms_s = g_hash_table_lookup(op->meta, XML_LRM_ATTR_INTERVAL_MS);
314 
315  crm_debug("Processing %s", op->uuid);
316  if(pcmk__str_eq(RSC_STOP, op->task, pcmk__str_casei)) {
318  __func__, __LINE__);
319 
320  } else if(pcmk__str_eq(RSC_START, op->task, pcmk__str_casei)) {
322  __func__, __LINE__);
323  //pe__set_resource_flags(rsc, pe_rsc_block);
324 
325  } else if (interval_ms_s && !pcmk__str_eq(interval_ms_s, "0", pcmk__str_casei)) {
326  if(pcmk__str_eq(rc_inactive, g_hash_table_lookup(op->meta, XML_ATTR_TE_TARGET_RC), pcmk__str_casei)) {
327  /* This is a recurring monitor for the stopped state, leave it alone */
328 
329  } else {
330  /* Normal monitor operation, cancel it */
332  __func__, __LINE__);
333  }
334  }
335  }
336 
337  free(rc_inactive);
338  return FALSE;
339  }
340 
341  crm_debug("Assigning %s to %s", chosen->details->uname, rsc->id);
342  rsc->allocated_to = pe__copy_node(chosen);
343 
344  chosen->details->allocated_rsc = g_list_prepend(chosen->details->allocated_rsc, rsc);
345  chosen->details->num_resources++;
346  chosen->count++;
347  calculate_utilization(chosen->details->utilization, rsc->utilization, FALSE);
348 
350  out->message(out, "resource-util", rsc, chosen, __func__);
351  }
352 
353  return TRUE;
354 }
355 
356 void
357 log_action(unsigned int log_level, const char *pre_text, pe_action_t * action, gboolean details)
358 {
359  const char *node_uname = NULL;
360  const char *node_uuid = NULL;
361  const char *desc = NULL;
362 
363  if (action == NULL) {
364  crm_trace("%s%s: <NULL>", pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": ");
365  return;
366  }
367 
368  if (pcmk_is_set(action->flags, pe_action_pseudo)) {
369  node_uname = NULL;
370  node_uuid = NULL;
371 
372  } else if (action->node != NULL) {
373  node_uname = action->node->details->uname;
374  node_uuid = action->node->details->id;
375  } else {
376  node_uname = "<none>";
377  node_uuid = NULL;
378  }
379 
380  switch (text2task(action->task)) {
381  case stonith_node:
382  case shutdown_crm:
383  if (pcmk_is_set(action->flags, pe_action_pseudo)) {
384  desc = "Pseudo ";
385  } else if (pcmk_is_set(action->flags, pe_action_optional)) {
386  desc = "Optional ";
387  } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
388  desc = "!!Non-Startable!! ";
389  } else if (pcmk_is_set(action->flags, pe_action_processed)) {
390  desc = "";
391  } else {
392  desc = "(Provisional) ";
393  }
394  crm_trace("%s%s%sAction %d: %s%s%s%s%s%s",
395  ((pre_text == NULL)? "" : pre_text),
396  ((pre_text == NULL)? "" : ": "),
397  desc, action->id, action->uuid,
398  (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
399  (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
400  (node_uuid? ")" : ""));
401  break;
402  default:
403  if (pcmk_is_set(action->flags, pe_action_optional)) {
404  desc = "Optional ";
405  } else if (pcmk_is_set(action->flags, pe_action_pseudo)) {
406  desc = "Pseudo ";
407  } else if (!pcmk_is_set(action->flags, pe_action_runnable)) {
408  desc = "!!Non-Startable!! ";
409  } else if (pcmk_is_set(action->flags, pe_action_processed)) {
410  desc = "";
411  } else {
412  desc = "(Provisional) ";
413  }
414  crm_trace("%s%s%sAction %d: %s %s%s%s%s%s%s",
415  ((pre_text == NULL)? "" : pre_text),
416  ((pre_text == NULL)? "" : ": "),
417  desc, action->id, action->uuid,
418  (action->rsc? action->rsc->id : "<none>"),
419  (node_uname? "\ton " : ""), (node_uname? node_uname : ""),
420  (node_uuid? "\t\t(" : ""), (node_uuid? node_uuid : ""),
421  (node_uuid? ")" : ""));
422  break;
423  }
424 
425  if (details) {
426  GList *gIter = NULL;
427 
428  crm_trace("\t\t====== Preceding Actions");
429 
430  gIter = action->actions_before;
431  for (; gIter != NULL; gIter = gIter->next) {
432  pe_action_wrapper_t *other = (pe_action_wrapper_t *) gIter->data;
433 
434  log_action(log_level + 1, "\t\t", other->action, FALSE);
435  }
436 
437  crm_trace("\t\t====== Subsequent Actions");
438 
439  gIter = action->actions_after;
440  for (; gIter != NULL; gIter = gIter->next) {
441  pe_action_wrapper_t *other = (pe_action_wrapper_t *) gIter->data;
442 
443  log_action(log_level + 1, "\t\t", other->action, FALSE);
444  }
445 
446  crm_trace("\t\t====== End");
447 
448  } else {
449  crm_trace("\t\t(before=%d, after=%d)",
450  g_list_length(action->actions_before), g_list_length(action->actions_after));
451  }
452 }
453 
454 gboolean
455 can_run_any(GHashTable * nodes)
456 {
457  GHashTableIter iter;
458  pe_node_t *node = NULL;
459 
460  if (nodes == NULL) {
461  return FALSE;
462  }
463 
464  g_hash_table_iter_init(&iter, nodes);
465  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
466  if (can_run_resources(node) && node->weight >= 0) {
467  return TRUE;
468  }
469  }
470 
471  return FALSE;
472 }
473 
474 pe_action_t *
475 create_pseudo_resource_op(pe_resource_t * rsc, const char *task, bool optional, bool runnable, pe_working_set_t *data_set)
476 {
477  pe_action_t *action = custom_action(rsc, pcmk__op_key(rsc->id, task, 0),
478  task, NULL, optional, TRUE, data_set);
479  update_action_flags(action, pe_action_pseudo, __func__, __LINE__);
480  update_action_flags(action, pe_action_runnable, __func__, __LINE__);
481  if(runnable) {
482  update_action_flags(action, pe_action_runnable, __func__, __LINE__);
483  }
484  return action;
485 }
486 
499 pe_action_t *
500 pe_cancel_op(pe_resource_t *rsc, const char *task, guint interval_ms,
501  pe_node_t *node, pe_working_set_t *data_set)
502 {
503  pe_action_t *cancel_op;
504  char *interval_ms_s = crm_strdup_printf("%u", interval_ms);
505 
506  // @TODO dangerous if possible to schedule another action with this key
507  char *key = pcmk__op_key(rsc->id, task, interval_ms);
508 
509  cancel_op = custom_action(rsc, key, RSC_CANCEL, node, FALSE, TRUE,
510  data_set);
511 
512  free(cancel_op->task);
513  cancel_op->task = strdup(RSC_CANCEL);
514 
515  free(cancel_op->cancel_task);
516  cancel_op->cancel_task = strdup(task);
517 
518  add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, task);
519  add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL_MS, interval_ms_s);
520  free(interval_ms_s);
521 
522  return cancel_op;
523 }
524 
534 pe_action_t *
536 {
537  char *shutdown_id = crm_strdup_printf("%s-%s", CRM_OP_SHUTDOWN,
538  node->details->uname);
539 
540  pe_action_t *shutdown_op = custom_action(NULL, shutdown_id, CRM_OP_SHUTDOWN,
541  node, FALSE, TRUE, data_set);
542 
543  crm_notice("Scheduling shutdown of node %s", node->details->uname);
544  shutdown_constraints(node, shutdown_op, data_set);
546  return shutdown_op;
547 }
548 
549 static char *
550 generate_transition_magic(const char *transition_key, int op_status, int op_rc)
551 {
552  CRM_CHECK(transition_key != NULL, return NULL);
553  return crm_strdup_printf("%d:%d;%s", op_status, op_rc, transition_key);
554 }
555 
556 static void
557 append_digest(lrmd_event_data_t *op, xmlNode *update, const char *version,
558  const char *magic, int level)
559 {
560  /* this will enable us to later determine that the
561  * resource's parameters have changed and we should force
562  * a restart
563  */
564  char *digest = NULL;
565  xmlNode *args_xml = NULL;
566 
567  if (op->params == NULL) {
568  return;
569  }
570 
571  args_xml = create_xml_node(NULL, XML_TAG_PARAMS);
572  g_hash_table_foreach(op->params, hash2field, args_xml);
573  pcmk__filter_op_for_digest(args_xml);
574  digest = calculate_operation_digest(args_xml, version);
575 
576 #if 0
577  if (level < get_crm_log_level()
578  && op->interval_ms == 0 && pcmk__str_eq(op->op_type, CRMD_ACTION_START, pcmk__str_none)) {
579  char *digest_source = dump_xml_unformatted(args_xml);
580 
581  do_crm_log(level, "Calculated digest %s for %s (%s). Source: %s\n",
582  digest, ID(update), magic, digest_source);
583  free(digest_source);
584  }
585 #endif
586  crm_xml_add(update, XML_LRM_ATTR_OP_DIGEST, digest);
587 
588  free_xml(args_xml);
589  free(digest);
590 }
591 
592 #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
593 
608 xmlNode *
610  const char *caller_version, int target_rc,
611  const char *node, const char *origin, int level)
612 {
613  char *key = NULL;
614  char *magic = NULL;
615  char *op_id = NULL;
616  char *op_id_additional = NULL;
617  char *local_user_data = NULL;
618  const char *exit_reason = NULL;
619 
620  xmlNode *xml_op = NULL;
621  const char *task = NULL;
622 
623  CRM_CHECK(op != NULL, return NULL);
624  do_crm_log(level, "%s: Updating resource %s after %s op %s (interval=%u)",
625  origin, op->rsc_id, op->op_type, services_lrm_status_str(op->op_status),
626  op->interval_ms);
627 
628  crm_trace("DC version: %s", caller_version);
629 
630  task = op->op_type;
631 
632  /* Record a successful agent reload as a start, and a failed one as a
633  * monitor, to make life easier for the scheduler when determining the
634  * current state.
635  *
636  * @COMPAT We should check "reload" here only if the operation was for a
637  * pre-OCF-1.1 resource agent, but we don't know that here, and we should
638  * only ever get results for actions scheduled by us, so we can reasonably
639  * assume any "reload" is actually a pre-1.1 agent reload.
640  */
642  NULL)) {
643  if (op->op_status == PCMK_LRM_OP_DONE) {
644  task = CRMD_ACTION_START;
645  } else {
646  task = CRMD_ACTION_STATUS;
647  }
648  }
649 
650  key = pcmk__op_key(op->rsc_id, task, op->interval_ms);
651  if (pcmk__str_eq(task, CRMD_ACTION_NOTIFY, pcmk__str_none)) {
652  const char *n_type = crm_meta_value(op->params, "notify_type");
653  const char *n_task = crm_meta_value(op->params, "notify_operation");
654 
655  CRM_LOG_ASSERT(n_type != NULL);
656  CRM_LOG_ASSERT(n_task != NULL);
657  op_id = pcmk__notify_key(op->rsc_id, n_type, n_task);
658 
659  if (op->op_status != PCMK_LRM_OP_PENDING) {
660  /* Ignore notify errors.
661  *
662  * @TODO It might be better to keep the correct result here, and
663  * ignore it in process_graph_event().
664  */
666  op->rc = 0;
667  }
668 
669  } else if (did_rsc_op_fail(op, target_rc)) {
670  op_id = pcmk__op_key(op->rsc_id, "last_failure", 0);
671  if (op->interval_ms == 0) {
672  // Ensure 'last' gets updated, in case record-pending is true
673  op_id_additional = pcmk__op_key(op->rsc_id, "last", 0);
674  }
675  exit_reason = op->exit_reason;
676 
677  } else if (op->interval_ms > 0) {
678  op_id = strdup(key);
679 
680  } else {
681  op_id = pcmk__op_key(op->rsc_id, "last", 0);
682  }
683 
684  again:
685  xml_op = pcmk__xe_match(parent, XML_LRM_TAG_RSC_OP, XML_ATTR_ID, op_id);
686  if (xml_op == NULL) {
687  xml_op = create_xml_node(parent, XML_LRM_TAG_RSC_OP);
688  }
689 
690  if (op->user_data == NULL) {
691  crm_debug("Generating fake transition key for: " PCMK__OP_FMT
692  " %d from %s", op->rsc_id, op->op_type, op->interval_ms,
693  op->call_id, origin);
694  local_user_data = pcmk__transition_key(-1, op->call_id, target_rc,
695  FAKE_TE_ID);
696  op->user_data = local_user_data;
697  }
698 
699  if(magic == NULL) {
700  magic = generate_transition_magic(op->user_data, op->op_status, op->rc);
701  }
702 
703  crm_xml_add(xml_op, XML_ATTR_ID, op_id);
704  crm_xml_add(xml_op, XML_LRM_ATTR_TASK_KEY, key);
705  crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task);
706  crm_xml_add(xml_op, XML_ATTR_ORIGIN, origin);
707  crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, caller_version);
709  crm_xml_add(xml_op, XML_ATTR_TRANSITION_MAGIC, magic);
710  crm_xml_add(xml_op, XML_LRM_ATTR_EXIT_REASON, exit_reason == NULL ? "" : exit_reason);
711  crm_xml_add(xml_op, XML_LRM_ATTR_TARGET, node); /* For context during triage */
712 
714  crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op->rc);
717 
718  if (compare_version("2.1", caller_version) <= 0) {
719  if (op->t_run || op->t_rcchange || op->exec_time || op->queue_time) {
720  crm_trace("Timing data (" PCMK__OP_FMT
721  "): last=%u change=%u exec=%u queue=%u",
722  op->rsc_id, op->op_type, op->interval_ms,
723  op->t_run, op->t_rcchange, op->exec_time, op->queue_time);
724 
725  if ((op->interval_ms != 0) && (op->t_rcchange != 0)) {
726  // Recurring ops may have changed rc after initial run
728  (long long) op->t_rcchange);
729  } else {
731  (long long) op->t_run);
732  }
733 
736  }
737  }
738 
740  /*
741  * Record migrate_source and migrate_target always for migrate ops.
742  */
743  const char *name = XML_LRM_ATTR_MIGRATE_SOURCE;
744 
745  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
746 
748  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
749  }
750 
751  append_digest(op, xml_op, caller_version, magic, LOG_DEBUG);
752 
753  if (op_id_additional) {
754  free(op_id);
755  op_id = op_id_additional;
756  op_id_additional = NULL;
757  goto again;
758  }
759 
760  if (local_user_data) {
761  free(local_user_data);
762  op->user_data = NULL;
763  }
764  free(magic);
765  free(op_id);
766  free(key);
767  return xml_op;
768 }
769 
772 {
773  int rc = pcmk_rc_ok;
774  pcmk__output_t *out = NULL;
775  const char* argv[] = { "", NULL };
776  pcmk__supported_format_t formats[] = {
778  { NULL, NULL, NULL }
779  };
780 
781  pcmk__register_formats(NULL, formats);
782  rc = pcmk__output_new(&out, "log", NULL, (char**)argv);
783  if ((rc != pcmk_rc_ok) || (out == NULL)) {
784  crm_err("Can't log resource details due to internal error: %s\n",
785  pcmk_rc_str(rc));
786  return NULL;
787  }
788 
791  return out;
792 }
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 CRM_CHECK(expr, failure_action)
Definition: logging.h:218
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:317
enum rsc_role_e role_filter
Definition: internal.h:171
#define PCMK__SUPPORTED_FORMAT_LOG
#define RSC_STOP
Definition: crm.h:204
#define crm_notice(fmt, args...)
Definition: logging.h:352
#define CRMD_ACTION_MIGRATED
Definition: crm.h:174
char data[0]
Definition: cpg.c:55
#define INFINITY
Definition: crm.h:99
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:786
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:454
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:398
GList * sort_nodes_by_weight(GList *nodes, pe_node_t *active_node, pe_working_set_t *data_set)
int count
Definition: pe_types.h:243
unsigned int queue_time
Definition: lrmd.h:233
pe_resource_t * rsc
Definition: pe_types.h:409
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:432
gboolean exclusive_discover
Definition: pe_types.h:351
char * cancel_task
Definition: pe_types.h:415
#define CRMD_ACTION_NOTIFY
Definition: crm.h:187
pe_action_t * sched_shutdown_op(pe_node_t *node, pe_working_set_t *data_set)
gboolean native_assign_node(pe_resource_t *rsc, pe_node_t *chosen, gboolean force)
#define XML_LOCATION_ATTR_DISCOVERY
Definition: msg_xml.h:352
#define XML_RSC_OP_T_EXEC
Definition: msg_xml.h:319
const char * crm_meta_value(GHashTable *hash, const char *field)
Definition: utils.c:533
xmlNode * pcmk__xe_match(xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:496
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:324
pe_node_t * pe__copy_node(const pe_node_t *this_node)
Definition: utils.c:142
#define XML_LRM_ATTR_OP_DIGEST
Definition: msg_xml.h:310
int(* message)(pcmk__output_t *out, const char *message_id,...)
Resource agent executor.
unsigned int t_rcchange
Definition: lrmd.h:229
void pcmk__filter_op_for_digest(xmlNode *param_set)
Definition: operations.c:390
enum action_tasks text2task(const char *task)
Definition: common.c:354
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:202
pe_resource_t * rsc_lh
Definition: internal.h:170
enum ocf_exitcode rc
Definition: lrmd.h:221
#define RSC_START
Definition: crm.h:201
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:420
pe_node_t * allocated_to
Definition: pe_types.h:362
pe_action_t * action
Definition: pe_types.h:533
void pcmk__register_formats(GOptionGroup *group, pcmk__supported_format_t *table)
Definition: output.c:97
#define XML_RSC_OP_T_QUEUE
Definition: msg_xml.h:320
gboolean can_run_resources(const pe_node_t *node)
const char * action
Definition: pcmk_fence.c:30
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:47
unsigned int exec_time
Definition: lrmd.h:231
#define XML_ATTR_ORIGIN
Definition: msg_xml.h:124
void calculate_utilization(GHashTable *current_utilization, GHashTable *utilization, gboolean plus)
#define CRMD_ACTION_START
Definition: crm.h:176
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:298
#define pe_rsc_provisional
Definition: pe_types.h:258
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:297
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:241
char * calculate_operation_digest(xmlNode *local_cib, const char *version)
Calculate and return digest of XML operation.
Definition: digest.c:170
enum pe_discover_e discover_mode
Definition: internal.h:172
#define CRMD_ACTION_RELOAD_AGENT
Definition: crm.h:172
op_status
Definition: services.h:86
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:229
int rc
Definition: pcmk_fence.c:35
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:355
pcmk__output_t * pcmk__new_logger(void)
#define XML_ATTR_ID
Definition: msg_xml.h:129
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:140
bool pe__is_guest_node(const pe_node_t *node)
Definition: remote.c:33
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:413
GList * actions_after
Definition: pe_types.h:447
#define crm_trace(fmt, args...)
Definition: logging.h:356
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:159
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
GHashTable * meta
Definition: pe_types.h:423
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:114
struct pe_node_shared_s * details
Definition: pe_types.h:244
pe_node_t * node
Definition: pe_types.h:410
const char * uname
Definition: pe_types.h:209
void pcmk__register_lib_messages(pcmk__output_t *out)
Definition: pcmk_output.c:1496
#define XML_ATTR_TE_NOWAIT
Definition: msg_xml.h:401
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
GList * actions
Definition: pe_types.h:358
GHashTable * utilization
Definition: pe_types.h:374
#define XML_LRM_ATTR_MIGRATE_TARGET
Definition: msg_xml.h:323
gboolean standby
Definition: pe_types.h:214
#define XML_LRM_ATTR_EXIT_REASON
Definition: msg_xml.h:315
char * uuid
Definition: pe_types.h:414
void pe__register_messages(pcmk__output_t *out)
Definition: pe_output.c:2767
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:823
enum pe_obj_types variant
Definition: pe_types.h:329
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:953
gboolean can_run_any(GHashTable *nodes)
#define CRM_OP_SHUTDOWN
Definition: crm.h:144
const char * id
Definition: pe_types.h:208
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition: operations.c:45
const char * op_type
Definition: lrmd.h:205
#define CRMD_ACTION_RELOAD
Definition: crm.h:171
const char * crm_xml_add_ll(xmlNode *node, const char *name, long long value)
Create an XML attribute with specified name and long long int value.
Definition: nvpair.c:482
GHashTable * pcmk__copy_node_table(GHashTable *nodes)
unsigned int t_run
Definition: lrmd.h:227
#define XML_ATTR_TRANSITION_KEY
Definition: msg_xml.h:399
unsigned int get_crm_log_level(void)
Definition: logging.c:987
#define FAKE_TE_ID
void log_action(unsigned int log_level, const char *pre_text, pe_action_t *action, gboolean details)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:610
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:579
#define pe_flag_show_utilization
Definition: pe_types.h:134
gboolean did_rsc_op_fail(lrmd_event_data_t *event, int target_rc)
Definition: operations.c:437
#define crm_err(fmt, args...)
Definition: logging.h:350
#define CRM_ASSERT(expr)
Definition: results.h:42
void pe__set_next_role(pe_resource_t *rsc, enum rsc_role_e role, const char *why)
Definition: complex.c:1116
This structure contains everything that makes up a single output formatter.
int compare_version(const char *version1, const char *version2)
Definition: utils.c:232
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:295
char * dump_xml_unformatted(xmlNode *msg)
Definition: xml.c:2017
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:309
#define CRMD_ACTION_MIGRATE
Definition: crm.h:173
GList * rsc_location
Definition: pe_types.h:357
GHashTable * utilization
Definition: pe_types.h:235
gboolean shutdown
Definition: pe_types.h:219
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:53
#define crm_str(x)
Definition: logging.h:376
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:307
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:112
char * pcmk__transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition: operations.c:296
enum pe_action_flags flags
Definition: pe_types.h:418
gboolean maintenance
Definition: pe_types.h:222
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:308
GList * placement_constraints
Definition: pe_types.h:159
pe_working_set_t * cluster
Definition: pe_types.h:326
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition: output.c:31
void native_deallocate(pe_resource_t *rsc)
#define RSC_CANCEL
Definition: crm.h:196
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:299
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:265
int compare_capacity(const pe_node_t *node1, const pe_node_t *node2)
#define ID(x)
Definition: msg_xml.h:456
unsigned long long flags
Definition: pe_types.h:146
#define pe_err(fmt...)
Definition: internal.h:22
GList * allocated_rsc
Definition: pe_types.h:232
#define PCMK__OP_FMT
Definition: internal.h:168
char * name
Definition: pcmk_fence.c:31
#define XML_LRM_ATTR_MIGRATE_SOURCE
Definition: msg_xml.h:322
gboolean unclean
Definition: pe_types.h:217
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:209
#define crm_info(fmt, args...)
Definition: logging.h:353
uint32_t version
Definition: remote.c:147
gboolean online
Definition: pe_types.h:213
#define XML_ATTR_TE_TARGET_RC
Definition: msg_xml.h:402
GList * actions_before
Definition: pe_types.h:446
guint interval_ms
Definition: lrmd.h:214
char * id
Definition: pe_types.h:320
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, pe_node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Definition: utils.c:415
#define CRMD_ACTION_STATUS
Definition: crm.h:190