pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
native.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2024 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <stdint.h>
13 
14 #include <crm/common/output.h>
15 #include <crm/pengine/rules.h>
16 #include <crm/pengine/status.h>
17 #include <crm/pengine/complex.h>
18 #include <crm/pengine/internal.h>
19 #include <crm/common/xml.h>
20 #include <pe_status_private.h>
21 
26 static bool
27 is_multiply_active(const pcmk_resource_t *rsc)
28 {
29  unsigned int count = 0;
30 
31  if (pcmk__is_primitive(rsc)) {
32  pe__find_active_requires(rsc, &count);
33  }
34  return count > 1;
35 }
36 
37 static void
38 native_priority_to_node(pcmk_resource_t *rsc, pcmk_node_t *node,
39  gboolean failed)
40 {
41  int priority = 0;
42  const bool promoted = (rsc->priv->orig_role == pcmk_role_promoted);
43 
44  if ((rsc->priv->priority == 0) || failed) {
45  return;
46  }
47 
48  if (promoted) {
49  // Promoted instance takes base priority + 1
50  priority = rsc->priv->priority + 1;
51 
52  } else {
53  priority = rsc->priv->priority;
54  }
55 
56  node->priv->priority += priority;
57  pcmk__rsc_trace(rsc, "%s now has priority %d with %s'%s' (priority: %d%s)",
58  pcmk__node_name(node), node->priv->priority,
59  (promoted? "promoted " : ""),
60  rsc->id, rsc->priv->priority, (promoted? " + 1" : ""));
61 
62  /* Priority of a resource running on a guest node is added to the cluster
63  * node as well. */
64  if ((node->priv->remote != NULL)
65  && (node->priv->remote->priv->launcher != NULL)) {
66  const pcmk_resource_t *launcher = NULL;
67 
68  launcher = node->priv->remote->priv->launcher;
69  for (GList *gIter = launcher->priv->active_nodes;
70  gIter != NULL; gIter = gIter->next) {
71 
72  pcmk_node_t *a_node = gIter->data;
73 
74  a_node->priv->priority += priority;
75  pcmk__rsc_trace(rsc,
76  "%s now has priority %d with %s'%s' "
77  "(priority: %d%s) from guest node %s",
78  pcmk__node_name(a_node), a_node->priv->priority,
79  (promoted? "promoted " : ""), rsc->id,
80  rsc->priv->priority, (promoted? " + 1" : ""),
81  pcmk__node_name(node));
82  }
83  }
84 }
85 
86 void
88  pcmk_scheduler_t *scheduler, gboolean failed)
89 {
91 
92  CRM_CHECK(node != NULL, return);
93 
94  for (GList *gIter = rsc->priv->active_nodes;
95  gIter != NULL; gIter = gIter->next) {
96 
97  pcmk_node_t *a_node = (pcmk_node_t *) gIter->data;
98 
99  if (pcmk__same_node(a_node, node)) {
100  return;
101  }
102  }
103 
104  pcmk__rsc_trace(rsc, "Adding %s to %s %s", rsc->id, pcmk__node_name(node),
105  pcmk_is_set(rsc->flags, pcmk__rsc_managed)? "" : "(unmanaged)");
106 
107  rsc->priv->active_nodes = g_list_append(rsc->priv->active_nodes, node);
108  if (pcmk__is_primitive(rsc)) {
109  node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
110  native_priority_to_node(rsc, node, failed);
111  if (node->details->maintenance) {
114  }
115  }
116 
117  if (!pcmk_is_set(rsc->flags, pcmk__rsc_managed)) {
118  pcmk_resource_t *p = parent;
119 
120  pcmk__rsc_info(rsc, "resource %s isn't managed", rsc->id);
122  "not_managed_default", scheduler);
123 
124  while(p && node->details->online) {
125  /* add without the additional location constraint */
126  p->priv->active_nodes = g_list_append(p->priv->active_nodes, node);
127  p = p->priv->parent;
128  }
129  return;
130  }
131 
132  if (is_multiply_active(rsc)) {
133  switch (rsc->priv->multiply_active_policy) {
135  {
136  GHashTableIter gIter;
137  pcmk_node_t *local_node = NULL;
138 
139  /* make sure it doesn't come up again */
140  if (rsc->priv->allowed_nodes != NULL) {
141  g_hash_table_destroy(rsc->priv->allowed_nodes);
142  }
143  rsc->priv->allowed_nodes =
145  g_hash_table_iter_init(&gIter, rsc->priv->allowed_nodes);
146  while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
147  local_node->assign->score = -PCMK_SCORE_INFINITY;
148  }
149  }
150  break;
154 
155  /* If the resource belongs to a group or bundle configured with
156  * PCMK_META_MULTIPLE_ACTIVE=PCMK_VALUE_BLOCK, block the entire
157  * entity.
158  */
159  if ((pcmk__is_group(parent) || pcmk__is_bundle(parent))
160  && (parent->priv->multiply_active_policy
162 
163  for (GList *gIter = parent->priv->children;
164  gIter != NULL; gIter = gIter->next) {
165  pcmk_resource_t *child = gIter->data;
166 
169  }
170  }
171  break;
172 
173  // pcmk__multiply_active_restart, pcmk__multiply_active_unexpected
174  default:
175  /* The scheduler will do the right thing because the relevant
176  * variables and flags are set when unpacking the history.
177  */
178  break;
179  }
180  crm_debug("%s is active on multiple nodes including %s: %s",
181  rsc->id, pcmk__node_name(node),
183 
184  } else {
185  pcmk__rsc_trace(rsc, "Resource %s is active on %s",
186  rsc->id, pcmk__node_name(node));
187  }
188 
189  if (parent != NULL) {
190  native_add_running(parent, node, scheduler, FALSE);
191  }
192 }
193 
194 static void
195 recursive_clear_unique(pcmk_resource_t *rsc, gpointer user_data)
196 {
200  g_list_foreach(rsc->priv->children, (GFunc) recursive_clear_unique,
201  NULL);
202 }
203 
204 gboolean
206 {
208  const char *standard = crm_element_value(rsc->priv->xml, PCMK_XA_CLASS);
209  uint32_t ra_caps = pcmk_get_ra_caps(standard);
210 
211  pcmk__rsc_trace(rsc, "Processing resource %s...", rsc->id);
212 
213  // Only some agent standards support unique and promotable clones
214  if (!pcmk_is_set(ra_caps, pcmk_ra_cap_unique)
216  && pcmk__is_clone(parent)) {
217 
218  /* @COMPAT We should probably reject this situation as an error (as we
219  * do for promotable below) rather than warn and convert, but that would
220  * be a backward-incompatible change that we should probably do with a
221  * transform at a schema major version bump.
222  */
223  pe__force_anon(standard, parent, rsc->id, scheduler);
224 
225  /* Clear PCMK_META_GLOBALLY_UNIQUE on the parent and all its descendants
226  * unpacked so far (clearing the parent should make any future children
227  * unpacking correct). We have to clear this resource explicitly because
228  * it isn't hooked into the parent's children yet.
229  */
230  recursive_clear_unique(parent, NULL);
231  recursive_clear_unique(rsc, NULL);
232  }
233  if (!pcmk_is_set(ra_caps, pcmk_ra_cap_promotable)
235 
236  pcmk__config_err("Resource %s is of type %s and therefore "
237  "cannot be used as a promotable clone resource",
238  rsc->id, standard);
239  return FALSE;
240  }
241  return TRUE;
242 }
243 
244 static bool
245 rsc_is_on_node(pcmk_resource_t *rsc, const pcmk_node_t *node, int flags)
246 {
247  pcmk__rsc_trace(rsc, "Checking whether %s is on %s",
248  rsc->id, pcmk__node_name(node));
249 
251  && (rsc->priv->active_nodes != NULL)) {
252 
253  for (GList *iter = rsc->priv->active_nodes;
254  iter != NULL; iter = iter->next) {
255 
256  if (pcmk__same_node((pcmk_node_t *) iter->data, node)) {
257  return true;
258  }
259  }
260 
262  && (rsc->priv->assigned_node != NULL)
263  && pcmk__same_node(rsc->priv->assigned_node, node)) {
264  return true;
265  }
266  return false;
267 }
268 
270 native_find_rsc(pcmk_resource_t *rsc, const char *id,
271  const pcmk_node_t *on_node, int flags)
272 {
273  bool match = false;
274  pcmk_resource_t *result = NULL;
275 
276  CRM_CHECK(id && rsc && rsc->id, return NULL);
277 
279  const char *rid = pcmk__xe_id(rsc->priv->xml);
280 
281  if (!pcmk__is_clone(pe__const_top_resource(rsc, false))) {
282  match = false;
283 
284  } else if (!strcmp(id, rsc->id) || pcmk__str_eq(id, rid, pcmk__str_none)) {
285  match = true;
286  }
287 
288  } else if (!strcmp(id, rsc->id)) {
289  match = true;
290 
292  && pcmk__str_eq(rsc->priv->history_id, id, pcmk__str_none)) {
293  match = true;
294 
297  && !pcmk_is_set(rsc->flags, pcmk__rsc_unique))) {
298  match = pe_base_name_eq(rsc, id);
299  }
300 
301  if (match && on_node) {
302  if (!rsc_is_on_node(rsc, on_node, flags)) {
303  match = false;
304  }
305  }
306 
307  if (match) {
308  return rsc;
309  }
310 
311  for (GList *gIter = rsc->priv->children;
312  gIter != NULL; gIter = gIter->next) {
313 
314  pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
315 
316  result = rsc->priv->fns->find_rsc(child, id, on_node, flags);
317  if (result) {
318  return result;
319  }
320  }
321  return NULL;
322 }
323 
324 // create is ignored
325 char *
326 native_parameter(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create,
327  const char *name, pcmk_scheduler_t *scheduler)
328 {
329  const char *value = NULL;
330  GHashTable *params = NULL;
331 
332  CRM_CHECK(rsc != NULL, return NULL);
333  CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
334 
335  pcmk__rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
336  params = pe_rsc_params(rsc, node, scheduler);
337  value = g_hash_table_lookup(params, name);
338  if (value == NULL) {
339  /* try meta attributes instead */
340  value = g_hash_table_lookup(rsc->priv->meta, name);
341  }
342  return pcmk__str_copy(value);
343 }
344 
345 gboolean
346 native_active(pcmk_resource_t * rsc, gboolean all)
347 {
348  for (GList *gIter = rsc->priv->active_nodes;
349  gIter != NULL; gIter = gIter->next) {
350 
351  pcmk_node_t *a_node = (pcmk_node_t *) gIter->data;
352 
353  if (a_node->details->unclean) {
354  pcmk__rsc_trace(rsc, "Resource %s: %s is unclean",
355  rsc->id, pcmk__node_name(a_node));
356  return TRUE;
357  } else if (!a_node->details->online
358  && pcmk_is_set(rsc->flags, pcmk__rsc_managed)) {
359  pcmk__rsc_trace(rsc, "Resource %s: %s is offline",
360  rsc->id, pcmk__node_name(a_node));
361  } else {
362  pcmk__rsc_trace(rsc, "Resource %s active on %s",
363  rsc->id, pcmk__node_name(a_node));
364  return TRUE;
365  }
366  }
367  return FALSE;
368 }
369 
370 struct print_data_s {
371  long options;
372  void *print_data;
373 };
374 
375 static const char *
376 native_pending_state(const pcmk_resource_t *rsc)
377 {
378  const char *pending_state = NULL;
379 
380  if (pcmk__str_eq(rsc->priv->pending_action, PCMK_ACTION_START,
381  pcmk__str_none)) {
382  pending_state = "Starting";
383 
384  } else if (pcmk__str_eq(rsc->priv->pending_action, PCMK_ACTION_STOP,
385  pcmk__str_none)) {
386  pending_state = "Stopping";
387 
388  } else if (pcmk__str_eq(rsc->priv->pending_action, PCMK_ACTION_MIGRATE_TO,
389  pcmk__str_none)) {
390  pending_state = "Migrating";
391 
392  } else if (pcmk__str_eq(rsc->priv->pending_action,
394  /* Work might be done in here. */
395  pending_state = "Migrating";
396 
397  } else if (pcmk__str_eq(rsc->priv->pending_action, PCMK_ACTION_PROMOTE,
398  pcmk__str_none)) {
399  pending_state = "Promoting";
400 
401  } else if (pcmk__str_eq(rsc->priv->pending_action, PCMK_ACTION_DEMOTE,
402  pcmk__str_none)) {
403  pending_state = "Demoting";
404  }
405 
406  return pending_state;
407 }
408 
409 static const char *
410 native_pending_action(const pcmk_resource_t *rsc)
411 {
412  const char *pending_action = NULL;
413 
414  if (pcmk__str_eq(rsc->priv->pending_action, PCMK_ACTION_MONITOR,
415  pcmk__str_none)) {
416  pending_action = "Monitoring";
417 
418  /* Pending probes are not printed, even if pending
419  * operations are requested. If someone ever requests that
420  * behavior, uncomment this and the corresponding part of
421  * unpack.c:unpack_rsc_op().
422  */
423 #if 0
424  } else if (pcmk__str_eq(rsc->private->pending_action, "probe",
425  pcmk__str_none)) {
426  pending_action = "Checking";
427 #endif
428  }
429 
430  return pending_action;
431 }
432 
433 static enum rsc_role_e
434 native_displayable_role(const pcmk_resource_t *rsc)
435 {
436  enum rsc_role_e role = rsc->priv->orig_role;
437 
438  if ((role == pcmk_role_started)
439  && pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
441 
442  role = pcmk_role_unpromoted;
443  }
444  return role;
445 }
446 
447 static const char *
448 native_displayable_state(const pcmk_resource_t *rsc, bool print_pending)
449 {
450  const char *rsc_state = NULL;
451 
452  if (print_pending) {
453  rsc_state = native_pending_state(rsc);
454  }
455  if (rsc_state == NULL) {
456  rsc_state = pcmk_role_text(native_displayable_role(rsc));
457  }
458  return rsc_state;
459 }
460 
461 // Append a flag to resource description string's flags list
462 static bool
463 add_output_flag(GString *s, const char *flag_desc, bool have_flags)
464 {
465  g_string_append(s, (have_flags? ", " : " ("));
466  g_string_append(s, flag_desc);
467  return true;
468 }
469 
470 // Append a node name to resource description string's node list
471 static bool
472 add_output_node(GString *s, const char *node, bool have_nodes)
473 {
474  g_string_append(s, (have_nodes? " " : " [ "));
475  g_string_append(s, node);
476  return true;
477 }
478 
493 gchar *
495  const pcmk_node_t *node, uint32_t show_opts,
496  const char *target_role, bool show_nodes)
497 {
498  const char *class = crm_element_value(rsc->priv->xml, PCMK_XA_CLASS);
499  const char *provider = NULL;
500  const char *kind = crm_element_value(rsc->priv->xml, PCMK_XA_TYPE);
501  GString *outstr = NULL;
502  bool have_flags = false;
503 
504  if (!pcmk__is_primitive(rsc)) {
505  return NULL;
506  }
507 
508  CRM_CHECK(name != NULL, name = "unknown");
509  CRM_CHECK(kind != NULL, kind = "unknown");
510  CRM_CHECK(class != NULL, class = "unknown");
511 
513  provider = crm_element_value(rsc->priv->xml, PCMK_XA_PROVIDER);
514  }
515 
516  if ((node == NULL) && (rsc->priv->lock_node != NULL)) {
517  node = rsc->priv->lock_node;
518  }
519  if (pcmk_any_flags_set(show_opts, pcmk_show_rsc_only)
520  || pcmk__list_of_multiple(rsc->priv->active_nodes)) {
521  node = NULL;
522  }
523 
524  outstr = g_string_sized_new(128);
525 
526  // Resource name and agent
527  pcmk__g_strcat(outstr,
528  name, "\t(", class, ((provider == NULL)? "" : ":"),
529  pcmk__s(provider, ""), ":", kind, "):\t", NULL);
530 
531  // State on node
532  if (pcmk_is_set(rsc->flags, pcmk__rsc_removed)) {
533  g_string_append(outstr, " ORPHANED");
534  }
535  if (pcmk_is_set(rsc->flags, pcmk__rsc_failed)) {
536  enum rsc_role_e role = native_displayable_role(rsc);
537 
538  g_string_append(outstr, " FAILED");
539  if (role > pcmk_role_unpromoted) {
540  pcmk__add_word(&outstr, 0, pcmk_role_text(role));
541  }
542  } else {
543  bool show_pending = pcmk_is_set(show_opts, pcmk_show_pending);
544 
545  pcmk__add_word(&outstr, 0, native_displayable_state(rsc, show_pending));
546  }
547  if (node) {
548  pcmk__add_word(&outstr, 0, pcmk__node_name(node));
549  }
550 
551  // Failed probe operation
552  if (native_displayable_role(rsc) == pcmk_role_stopped) {
553  xmlNode *probe_op = pe__failed_probe_for_rsc(rsc,
554  node ? node->priv->name : NULL);
555  if (probe_op != NULL) {
556  int rc;
557 
559  &rc, 0);
560  pcmk__g_strcat(outstr, " (", crm_exit_str(rc), ") ", NULL);
561  }
562  }
563 
564  // Flags, as: (<flag> [...])
565  if (node && !(node->details->online) && node->details->unclean) {
566  have_flags = add_output_flag(outstr, "UNCLEAN", have_flags);
567  }
568  if ((node != NULL) && pcmk__same_node(node, rsc->priv->lock_node)) {
569  have_flags = add_output_flag(outstr, "LOCKED", have_flags);
570  }
571  if (pcmk_is_set(show_opts, pcmk_show_pending)) {
572  const char *pending_action = native_pending_action(rsc);
573 
574  if (pending_action != NULL) {
575  have_flags = add_output_flag(outstr, pending_action, have_flags);
576  }
577  }
578  if (target_role != NULL) {
579  switch (pcmk_parse_role(target_role)) {
580  case pcmk_role_unknown:
582  " %s for resource %s", target_role, rsc->id);
583  break;
584 
585  case pcmk_role_stopped:
586  have_flags = add_output_flag(outstr, "disabled", have_flags);
587  break;
588 
590  if (pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
592  have_flags = add_output_flag(outstr,
594  have_flags);
595  g_string_append(outstr, target_role);
596  }
597  break;
598 
599  default:
600  /* Only show target role if it limits our abilities (i.e. ignore
601  * Started, as it is the default anyways, and doesn't prevent
602  * the resource from becoming promoted).
603  */
604  break;
605  }
606  }
607 
608  // Blocked or maintenance implies unmanaged
609  if (pcmk_any_flags_set(rsc->flags,
611  if (pcmk_is_set(rsc->flags, pcmk__rsc_blocked)) {
612  have_flags = add_output_flag(outstr, "blocked", have_flags);
613 
614  } else if (pcmk_is_set(rsc->flags, pcmk__rsc_maintenance)) {
615  have_flags = add_output_flag(outstr, "maintenance", have_flags);
616  }
617  } else if (!pcmk_is_set(rsc->flags, pcmk__rsc_managed)) {
618  have_flags = add_output_flag(outstr, "unmanaged", have_flags);
619  }
620 
621  if (pcmk_is_set(rsc->flags, pcmk__rsc_ignore_failure)) {
622  have_flags = add_output_flag(outstr, "failure ignored", have_flags);
623  }
624 
625 
626  if (have_flags) {
627  g_string_append_c(outstr, ')');
628  }
629 
630  // User-supplied description
631  if (pcmk_any_flags_set(show_opts, pcmk_show_rsc_only|pcmk_show_description)
632  || pcmk__list_of_multiple(rsc->priv->active_nodes)) {
633  const char *desc = crm_element_value(rsc->priv->xml,
635 
636  if (desc) {
637  g_string_append(outstr, " (");
638  g_string_append(outstr, desc);
639  g_string_append(outstr, ")");
640 
641  }
642  }
643 
644  if (show_nodes && !pcmk_is_set(show_opts, pcmk_show_rsc_only)
645  && pcmk__list_of_multiple(rsc->priv->active_nodes)) {
646  bool have_nodes = false;
647 
648  for (GList *iter = rsc->priv->active_nodes;
649  iter != NULL; iter = iter->next) {
650 
651  pcmk_node_t *n = (pcmk_node_t *) iter->data;
652 
653  have_nodes = add_output_node(outstr, n->priv->name, have_nodes);
654  }
655  if (have_nodes) {
656  g_string_append(outstr, " ]");
657  }
658  }
659 
660  return g_string_free(outstr, FALSE);
661 }
662 
663 int
665  const char *name, const pcmk_node_t *node,
666  uint32_t show_opts)
667 {
668  const char *kind = crm_element_value(rsc->priv->xml, PCMK_XA_TYPE);
669  const char *target_role = NULL;
670  const char *cl = NULL;
671 
672  xmlNode *child = NULL;
673  gchar *content = NULL;
674 
675  pcmk__assert((kind != NULL) && pcmk__is_primitive(rsc));
676 
677  if (crm_is_true(g_hash_table_lookup(rsc->priv->meta,
679  && !pcmk_is_set(show_opts, pcmk_show_implicit_rscs)) {
680 
681  crm_trace("skipping print of internal resource %s", rsc->id);
682  return pcmk_rc_no_output;
683  }
684  target_role = g_hash_table_lookup(rsc->priv->meta,
686 
687  if (!pcmk_is_set(rsc->flags, pcmk__rsc_managed)) {
689 
690  } else if (pcmk_is_set(rsc->flags, pcmk__rsc_failed)) {
692 
693  } else if (pcmk__is_primitive(rsc)
694  && (rsc->priv->active_nodes == NULL)) {
696 
697  } else if (pcmk__list_of_multiple(rsc->priv->active_nodes)) {
699 
700  } else if (pcmk_is_set(rsc->flags, pcmk__rsc_ignore_failure)) {
702 
703  } else {
704  cl = PCMK__VALUE_RSC_OK;
705  }
706 
707  child = pcmk__output_create_html_node(out, "li", NULL, NULL, NULL);
708  child = pcmk__html_create(child, PCMK__XE_SPAN, NULL, cl);
709  content = pcmk__native_output_string(rsc, name, node, show_opts,
710  target_role, true);
711  pcmk__xe_set_content(child, "%s", content);
712  g_free(content);
713 
714  return pcmk_rc_ok;
715 }
716 
717 int
719  const char *name, const pcmk_node_t *node,
720  uint32_t show_opts)
721 {
722  const char *target_role = NULL;
723 
724  pcmk__assert(pcmk__is_primitive(rsc));
725 
726  if (crm_is_true(g_hash_table_lookup(rsc->priv->meta,
728  && !pcmk_is_set(show_opts, pcmk_show_implicit_rscs)) {
729 
730  crm_trace("skipping print of internal resource %s", rsc->id);
731  return pcmk_rc_no_output;
732  }
733  target_role = g_hash_table_lookup(rsc->priv->meta,
735 
736  {
737  gchar *s = pcmk__native_output_string(rsc, name, node, show_opts,
738  target_role, true);
739 
740  out->list_item(out, NULL, "%s", s);
741  g_free(s);
742  }
743 
744  return pcmk_rc_ok;
745 }
746 
747 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
748  "GList *")
749 int
750 pe__resource_xml(pcmk__output_t *out, va_list args)
751 {
752  uint32_t show_opts = va_arg(args, uint32_t);
753  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
754  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
755  GList *only_rsc = va_arg(args, GList *);
756 
757  int rc = pcmk_rc_no_output;
758  bool print_pending = pcmk_is_set(show_opts, pcmk_show_pending);
759  const char *class = crm_element_value(rsc->priv->xml, PCMK_XA_CLASS);
760  const char *prov = crm_element_value(rsc->priv->xml, PCMK_XA_PROVIDER);
761 
762  char ra_name[LINE_MAX];
763  const char *rsc_state = native_displayable_state(rsc, print_pending);
764  const char *target_role = NULL;
765  const char *active = pcmk__btoa(rsc->priv->fns->active(rsc, TRUE));
766  const char *orphaned = pcmk__flag_text(rsc->flags, pcmk__rsc_removed);
767  const char *blocked = pcmk__flag_text(rsc->flags, pcmk__rsc_blocked);
768  const char *maintenance = pcmk__flag_text(rsc->flags,
770  const char *managed = pcmk__flag_text(rsc->flags, pcmk__rsc_managed);
771  const char *failed = pcmk__flag_text(rsc->flags, pcmk__rsc_failed);
772  const char *ignored = pcmk__flag_text(rsc->flags, pcmk__rsc_ignore_failure);
773  char *nodes_running_on = NULL;
774  const char *pending = print_pending? native_pending_action(rsc) : NULL;
775  const char *locked_to = NULL;
776  const char *desc = pe__resource_description(rsc, show_opts);
777 
778  pcmk__assert(pcmk__is_primitive(rsc));
779 
780  if (rsc->priv->fns->is_filtered(rsc, only_rsc, TRUE)) {
781  return pcmk_rc_no_output;
782  }
783 
784  // Resource information
785  snprintf(ra_name, LINE_MAX, "%s%s%s:%s", class,
786  ((prov == NULL)? "" : ":"), ((prov == NULL)? "" : prov),
788 
789  target_role = g_hash_table_lookup(rsc->priv->meta,
791 
792  nodes_running_on = pcmk__itoa(g_list_length(rsc->priv->active_nodes));
793 
794  if (rsc->priv->lock_node != NULL) {
795  locked_to = rsc->priv->lock_node->priv->name;
796  }
797 
800  PCMK_XA_RESOURCE_AGENT, ra_name,
801  PCMK_XA_ROLE, rsc_state,
802  PCMK_XA_TARGET_ROLE, target_role,
803  PCMK_XA_ACTIVE, active,
804  PCMK_XA_ORPHANED, orphaned,
805  PCMK_XA_BLOCKED, blocked,
806  PCMK_XA_MAINTENANCE, maintenance,
807  PCMK_XA_MANAGED, managed,
808  PCMK_XA_FAILED, failed,
809  PCMK_XA_FAILURE_IGNORED, ignored,
810  PCMK_XA_NODES_RUNNING_ON, nodes_running_on,
811  PCMK_XA_PENDING, pending,
812  PCMK_XA_LOCKED_TO, locked_to,
813  PCMK_XA_DESCRIPTION, desc,
814  NULL);
815  free(nodes_running_on);
816 
817  pcmk__assert(rc == pcmk_rc_ok);
818 
819  for (GList *gIter = rsc->priv->active_nodes;
820  gIter != NULL; gIter = gIter->next) {
821 
822  pcmk_node_t *node = (pcmk_node_t *) gIter->data;
823  const char *cached = pcmk__btoa(node->details->online);
824 
825  rc = pe__name_and_nvpairs_xml(out, false, PCMK_XE_NODE,
826  PCMK_XA_NAME, node->priv->name,
827  PCMK_XA_ID, node->priv->id,
828  PCMK_XA_CACHED, cached,
829  NULL);
830  pcmk__assert(rc == pcmk_rc_ok);
831  }
832 
834  return rc;
835 }
836 
837 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
838  "GList *")
839 int
840 pe__resource_html(pcmk__output_t *out, va_list args)
841 {
842  uint32_t show_opts = va_arg(args, uint32_t);
843  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
844  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
845  GList *only_rsc = va_arg(args, GList *);
846 
847  const pcmk_node_t *node = pcmk__current_node(rsc);
848 
849  if (rsc->priv->fns->is_filtered(rsc, only_rsc, TRUE)) {
850  return pcmk_rc_no_output;
851  }
852 
853  pcmk__assert(pcmk__is_primitive(rsc));
854 
855  if (node == NULL) {
856  // This is set only if a non-probe action is pending on this node
857  node = rsc->priv->pending_node;
858  }
859  return pe__common_output_html(out, rsc, rsc_printable_id(rsc), node, show_opts);
860 }
861 
862 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
863  "GList *")
864 int
865 pe__resource_text(pcmk__output_t *out, va_list args)
866 {
867  uint32_t show_opts = va_arg(args, uint32_t);
868  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
869  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
870  GList *only_rsc = va_arg(args, GList *);
871 
872  const pcmk_node_t *node = pcmk__current_node(rsc);
873 
874  pcmk__assert(pcmk__is_primitive(rsc));
875 
876  if (rsc->priv->fns->is_filtered(rsc, only_rsc, TRUE)) {
877  return pcmk_rc_no_output;
878  }
879 
880  if (node == NULL) {
881  // This is set only if a non-probe action is pending on this node
882  node = rsc->priv->pending_node;
883  }
884  return pe__common_output_text(out, rsc, rsc_printable_id(rsc), node, show_opts);
885 }
886 
887 void
889 {
890  pcmk__rsc_trace(rsc, "Freeing resource action list (not the data)");
891  common_free(rsc);
892 }
893 
894 enum rsc_role_e
895 native_resource_state(const pcmk_resource_t * rsc, gboolean current)
896 {
897  enum rsc_role_e role = rsc->priv->next_role;
898 
899  if (current) {
900  role = rsc->priv->orig_role;
901  }
902  pcmk__rsc_trace(rsc, "%s state: %s", rsc->id, pcmk_role_text(role));
903  return role;
904 }
905 
917 pcmk_node_t *
918 native_location(const pcmk_resource_t *rsc, GList **list, uint32_t target)
919 {
920  pcmk_node_t *one = NULL;
921  GList *result = NULL;
922 
923  if (rsc->priv->children != NULL) {
924 
925  for (GList *gIter = rsc->priv->children;
926  gIter != NULL; gIter = gIter->next) {
927 
928  pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
929 
930  child->priv->fns->location(child, &result, target);
931  }
932 
933  } else {
935  result = g_list_copy(rsc->priv->active_nodes);
936  }
938  && (rsc->priv->pending_node != NULL)
939  && !pe_find_node_id(result, rsc->priv->pending_node->priv->id)) {
940  result = g_list_append(result, (gpointer) rsc->priv->pending_node);
941  }
943  && (rsc->priv->assigned_node != NULL)) {
944  result = g_list_append(result, rsc->priv->assigned_node);
945  }
946  }
947 
948  if (result && (result->next == NULL)) {
949  one = result->data;
950  }
951 
952  if (list) {
953  GList *gIter = result;
954 
955  for (; gIter != NULL; gIter = gIter->next) {
956  pcmk_node_t *node = (pcmk_node_t *) gIter->data;
957 
958  if ((*list == NULL)
959  || (pe_find_node_id(*list, node->priv->id) == NULL)) {
960  *list = g_list_append(*list, node);
961  }
962  }
963  }
964 
965  g_list_free(result);
966  return one;
967 }
968 
969 static void
970 get_rscs_brief(GList *rsc_list, GHashTable * rsc_table, GHashTable * active_table)
971 {
972  GList *gIter = rsc_list;
973 
974  for (; gIter != NULL; gIter = gIter->next) {
975  pcmk_resource_t *rsc = (pcmk_resource_t *) gIter->data;
976 
977  const char *class = crm_element_value(rsc->priv->xml, PCMK_XA_CLASS);
978  const char *kind = crm_element_value(rsc->priv->xml, PCMK_XA_TYPE);
979 
980  int offset = 0;
981  char buffer[LINE_MAX];
982 
983  int *rsc_counter = NULL;
984  int *active_counter = NULL;
985 
986  if (!pcmk__is_primitive(rsc)) {
987  continue;
988  }
989 
990  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
992  const char *prov = crm_element_value(rsc->priv->xml,
994 
995  if (prov != NULL) {
996  offset += snprintf(buffer + offset, LINE_MAX - offset,
997  ":%s", prov);
998  }
999  }
1000  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
1001  CRM_LOG_ASSERT(offset > 0);
1002 
1003  if (rsc_table) {
1004  rsc_counter = g_hash_table_lookup(rsc_table, buffer);
1005  if (rsc_counter == NULL) {
1006  rsc_counter = pcmk__assert_alloc(1, sizeof(int));
1007  *rsc_counter = 0;
1008  g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
1009  }
1010  (*rsc_counter)++;
1011  }
1012 
1013  if (active_table) {
1014  for (GList *gIter2 = rsc->priv->active_nodes;
1015  gIter2 != NULL; gIter2 = gIter2->next) {
1016 
1017  pcmk_node_t *node = (pcmk_node_t *) gIter2->data;
1018  GHashTable *node_table = NULL;
1019 
1020  if (node->details->unclean == FALSE && node->details->online == FALSE &&
1022  continue;
1023  }
1024 
1025  node_table = g_hash_table_lookup(active_table,
1026  node->priv->name);
1027  if (node_table == NULL) {
1028  node_table = pcmk__strkey_table(free, free);
1029  g_hash_table_insert(active_table,
1030  strdup(node->priv->name),
1031  node_table);
1032  }
1033 
1034  active_counter = g_hash_table_lookup(node_table, buffer);
1035  if (active_counter == NULL) {
1036  active_counter = pcmk__assert_alloc(1, sizeof(int));
1037  *active_counter = 0;
1038  g_hash_table_insert(node_table, strdup(buffer), active_counter);
1039  }
1040  (*active_counter)++;
1041  }
1042  }
1043  }
1044 }
1045 
1046 static void
1047 destroy_node_table(gpointer data)
1048 {
1049  GHashTable *node_table = data;
1050 
1051  if (node_table) {
1052  g_hash_table_destroy(node_table);
1053  }
1054 }
1055 
1056 int
1057 pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, uint32_t show_opts)
1058 {
1059  GHashTable *rsc_table = pcmk__strkey_table(free, free);
1060  GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1061  GList *sorted_rscs;
1062  int rc = pcmk_rc_no_output;
1063 
1064  get_rscs_brief(rsc_list, rsc_table, active_table);
1065 
1066  /* Make a list of the rsc_table keys so that it can be sorted. This is to make sure
1067  * output order stays consistent between systems.
1068  */
1069  sorted_rscs = g_hash_table_get_keys(rsc_table);
1070  sorted_rscs = g_list_sort(sorted_rscs, (GCompareFunc) strcmp);
1071 
1072  for (GList *gIter = sorted_rscs; gIter; gIter = gIter->next) {
1073  char *type = (char *) gIter->data;
1074  int *rsc_counter = g_hash_table_lookup(rsc_table, type);
1075 
1076  GList *sorted_nodes = NULL;
1077  int active_counter_all = 0;
1078 
1079  /* Also make a list of the active_table keys so it can be sorted. If there's
1080  * more than one instance of a type of resource running, we need the nodes to
1081  * be sorted to make sure output order stays consistent between systems.
1082  */
1083  sorted_nodes = g_hash_table_get_keys(active_table);
1084  sorted_nodes = g_list_sort(sorted_nodes, (GCompareFunc) pcmk__numeric_strcasecmp);
1085 
1086  for (GList *gIter2 = sorted_nodes; gIter2; gIter2 = gIter2->next) {
1087  char *node_name = (char *) gIter2->data;
1088  GHashTable *node_table = g_hash_table_lookup(active_table, node_name);
1089  int *active_counter = NULL;
1090 
1091  if (node_table == NULL) {
1092  continue;
1093  }
1094 
1095  active_counter = g_hash_table_lookup(node_table, type);
1096 
1097  if (active_counter == NULL || *active_counter == 0) {
1098  continue;
1099 
1100  } else {
1101  active_counter_all += *active_counter;
1102  }
1103 
1104  if (pcmk_is_set(show_opts, pcmk_show_rsc_only)) {
1105  node_name = NULL;
1106  }
1107 
1108  if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs)) {
1109  out->list_item(out, NULL, "%d/%d\t(%s):\tActive %s",
1110  *active_counter,
1111  rsc_counter ? *rsc_counter : 0, type,
1112  (*active_counter > 0) && node_name ? node_name : "");
1113  } else {
1114  out->list_item(out, NULL, "%d\t(%s):\tActive %s",
1115  *active_counter, type,
1116  (*active_counter > 0) && node_name ? node_name : "");
1117  }
1118 
1119  rc = pcmk_rc_ok;
1120  }
1121 
1122  if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs) && active_counter_all == 0) {
1123  out->list_item(out, NULL, "%d/%d\t(%s):\tActive",
1124  active_counter_all,
1125  rsc_counter ? *rsc_counter : 0, type);
1126  rc = pcmk_rc_ok;
1127  }
1128 
1129  if (sorted_nodes) {
1130  g_list_free(sorted_nodes);
1131  }
1132  }
1133 
1134  if (rsc_table) {
1135  g_hash_table_destroy(rsc_table);
1136  rsc_table = NULL;
1137  }
1138  if (active_table) {
1139  g_hash_table_destroy(active_table);
1140  active_table = NULL;
1141  }
1142  if (sorted_rscs) {
1143  g_list_free(sorted_rscs);
1144  }
1145 
1146  return rc;
1147 }
1148 
1149 gboolean
1150 pe__native_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc,
1151  gboolean check_parent)
1152 {
1154  pcmk__str_in_list(rsc->id, only_rsc, pcmk__str_star_matches)) {
1155  return FALSE;
1156  } else if (check_parent && (rsc->priv->parent != NULL)) {
1157  const pcmk_resource_t *up = pe__const_top_resource(rsc, true);
1158 
1159  return up->priv->fns->is_filtered(up, only_rsc, FALSE);
1160  }
1161 
1162  return TRUE;
1163 }
1164 
1173 unsigned int
1175 {
1176  pcmk__assert(pcmk__is_primitive(rsc));
1177  return 1U;
1178 }
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
Definition: complex.c:1043
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:213
#define PCMK__VALUE_RSC_OK
#define PCMK_XA_NAME
Definition: xml_names.h:330
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
Definition: roles.c:23
Also match anonymous clone instances by base name.
Definition: resources.h:37
char data[0]
Definition: cpg.c:58
#define PCMK_XA_MANAGED
Definition: xml_names.h:323
Control output from tools.
gboolean(* active)(pcmk_resource_t *rsc, gboolean all)
#define PCMK_VALUE_FALSE
Definition: options.h:153
#define PCMK__XA_RC_CODE
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:116
pcmk_node_t * pe__find_active_requires(const pcmk_resource_t *rsc, unsigned int *count)
Definition: complex.c:1217
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
Definition: complex.c:1017
pcmk_resource_t * parent
Stopped.
Definition: roles.h:36
const char * name
Definition: cib.c:26
enum pcmk_ipc_server type
Definition: cpg.c:51
#define PCMK_XA_NODES_RUNNING_ON
Definition: xml_names.h:340
xmlNode * pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name)
Definition: utils.c:882
#define pcmk__rsc_trace(rsc, fmt, args...)
gboolean(* is_filtered)(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
Match only clones and their instances, by either clone or instance ID.
Definition: resources.h:40
#define PCMK__VALUE_RSC_MULTIPLE
int pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, uint32_t show_opts)
Definition: native.c:1057
#define pcmk__rsc_info(rsc, fmt, args...)
void pe__force_anon(const char *standard, pcmk_resource_t *rsc, const char *rid, pcmk_scheduler_t *scheduler)
Definition: clone.c:205
#define pcmk__set_rsc_flags(resource, flags_to_set)
#define pcmk__insert_meta(obj, name, value)
#define pcmk__config_err(fmt...)
char * native_parameter(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create, const char *name, pcmk_scheduler_t *scheduler)
Definition: native.c:326
#define PCMK_ACTION_MONITOR
Definition: actions.h:51
const char * pe__resource_description(const pcmk_resource_t *rsc, uint32_t show_opts)
Definition: pe_output.c:22
#define PCMK_XA_FAILURE_IGNORED
Definition: xml_names.h:284
gboolean pe__native_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
Definition: native.c:1150
Do nothing to resource.
#define PCMK_ACTION_MIGRATE_TO
Definition: actions.h:50
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, uint32_t target)
#define PCMK_XA_PROVIDER
Definition: xml_names.h:364
Promoted.
Definition: roles.h:39
gboolean unclean
Definition: nodes.h:58
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:196
const char * rsc_printable_id(const pcmk_resource_t *rsc)
Definition: utils.c:563
const pcmk__rsc_methods_t * fns
xmlNodePtr pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: output_html.c:449
int pe__resource_text(pcmk__output_t *out, va_list args)
#define PCMK_XA_TYPE
Definition: xml_names.h:430
#define PCMK_XA_TARGET_ROLE
Definition: xml_names.h:422
int pe__common_output_html(pcmk__output_t *out, const pcmk_resource_t *rsc, const char *name, const pcmk_node_t *node, uint32_t show_opts)
Definition: native.c:664
#define PCMK__XE_SPAN
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
Definition: roles.c:51
#define PCMK_XA_FAILED
Definition: xml_names.h:283
#define PCMK__VALUE_RSC_FAILURE_IGNORED
Also match clone instance ID from resource history.
Definition: resources.h:34
pcmk__node_private_t * priv
Definition: nodes.h:85
#define PCMK_META_GLOBALLY_UNIQUE
Definition: options.h:89
#define PCMK_ACTION_DEMOTE
Definition: actions.h:40
void common_free(pcmk_resource_t *rsc)
Definition: complex.c:1060
const char * crm_exit_str(crm_exit_t exit_code)
Definition: results.c:748
int pe__common_output_text(pcmk__output_t *out, const pcmk_resource_t *rsc, const char *name, const pcmk_node_t *node, uint32_t show_opts)
Definition: native.c:718
#define crm_debug(fmt, args...)
Definition: logging.h:370
#define PCMK_XA_LOCKED_TO
Definition: xml_names.h:318
#define PCMK_XA_CACHED
Definition: xml_names.h:242
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name,...) G_GNUC_NULL_TERMINATED
Definition: pe_output.c:616
pcmk_node_t * pe_find_node_id(const GList *node_list, const char *id)
Find a node by ID in a list of nodes.
Definition: status.c:510
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
Definition: utils.c:365
void native_add_running(pcmk_resource_t *rsc, pcmk_node_t *node, pcmk_scheduler_t *scheduler, gboolean failed)
Definition: native.c:87
xmlNode * pcmk__html_create(xmlNode *parent, const char *name, const char *id, const char *class_name)
Definition: output_html.c:483
unsigned int pe__primitive_max_per_node(const pcmk_resource_t *rsc)
Definition: native.c:1174
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: xml_element.c:1168
#define PCMK_XA_DESCRIPTION
Definition: xml_names.h:261
#define crm_trace(fmt, args...)
Definition: logging.h:372
enum pcmk__multiply_active multiply_active_policy
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1297
gboolean maintenance
Definition: nodes.h:66
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:80
const char * pcmk__multiply_active_text(const pcmk_resource_t *rsc)
Get readable description of a multiply-active recovery type.
Definition: resources.c:54
#define PCMK_ACTION_START
Definition: actions.h:63
gboolean native_unpack(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler)
Definition: native.c:205
pcmk__resource_private_t * priv
Definition: resources.h:61
#define PCMK__VALUE_RSC_FAILED
#define PCMK_XA_ORPHANED
Definition: xml_names.h:353
Unpromoted.
Definition: roles.h:38
Wrappers for and extensions to libxml2.
rsc_role_e
Definition: roles.h:34
#define PCMK_META_TARGET_ROLE
Definition: options.h:113
Match clone instances (even unique) by base name as well as exact ID.
Definition: resources.h:46
pcmk_resource_t *(* find_rsc)(pcmk_resource_t *rsc, const char *search, const pcmk_node_t *node, int flags)
#define PCMK_ACTION_STOP
Definition: actions.h:66
void pcmk__xe_set_content(xmlNode *node, const char *format,...) G_GNUC_PRINTF(2
enum rsc_role_e native_resource_state(const pcmk_resource_t *rsc, gboolean current)
Definition: native.c:895
GHashTable * pe__node_list2table(const GList *list)
Definition: utils.c:119
#define PCMK_XA_RESOURCE_AGENT
Definition: xml_names.h:383
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
#define PCMK_XA_ID
Definition: xml_names.h:301
#define PCMK_XA_BLOCKED
Definition: xml_names.h:239
gboolean native_active(pcmk_resource_t *rsc, gboolean all)
Definition: native.c:346
#define PCMK_XA_ACTIVE
Definition: xml_names.h:230
const pcmk_node_t * pending_node
#define pcmk__str_copy(str)
const pcmk_node_t * lock_node
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:562
GList * running_rsc
Definition: nodes.h:70
#define PCMK_XA_MAINTENANCE
Definition: xml_names.h:321
int pe__resource_xml(pcmk__output_t *out, va_list args)
#define pcmk__assert(expr)
const char * target
Definition: pcmk_fence.c:31
#define PCMK_XA_CLASS
Definition: xml_names.h:246
#define PCMK_XE_NODE
Definition: xml_names.h:136
Cluster status and scheduling.
GList * nodes
Definition: scheduler.h:97
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:685
pcmk__action_result_t result
Definition: pcmk_fence.c:37
pcmk_scheduler_t * scheduler
gchar * pcmk__native_output_string(const pcmk_resource_t *rsc, const char *name, const pcmk_node_t *node, uint32_t show_opts, const char *target_role, bool show_nodes)
Definition: native.c:494
If matching by node, compare current node instead of assigned node.
Definition: resources.h:43
void(*) void(* list_item)(pcmk__output_t *out, const char *name, const char *format,...) G_GNUC_PRINTF(3
pcmk_resource_t * remote
pcmk_resource_t * launcher
#define PCMK_XA_PENDING
Definition: xml_names.h:356
#define PCMK_ACTION_MIGRATE_FROM
Definition: actions.h:49
Started.
Definition: roles.h:37
This structure contains everything that makes up a single output formatter.
#define PCMK_ACTION_PROMOTE
Definition: actions.h:57
int pe__resource_html(pcmk__output_t *out, va_list args)
gboolean crm_is_true(const char *s)
Definition: strings.c:490
Stop on all and leave stopped.
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition: strings.c:1079
#define PCMK__VALUE_RSC_MANAGED
unsigned long long flags
Definition: resources.h:69
#define PCMK__META_INTERNAL_RSC
gboolean online
Definition: nodes.h:50
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition: agents.c:27
Resource role is unknown.
Definition: roles.h:35
GHashTable * pe_rsc_params(pcmk_resource_t *rsc, const pcmk_node_t *node, pcmk_scheduler_t *scheduler)
Get a table of resource parameters.
Definition: complex.c:476
const char * parent
Definition: cib.c:27
struct pcmk__node_details * details
Definition: nodes.h:82
#define PCMK_XE_RESOURCE
Definition: xml_names.h:172
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:257
#define PCMK_XA_ROLE
Definition: xml_names.h:387
pcmk_node_t * native_location(const pcmk_resource_t *rsc, GList **list, uint32_t target)
Definition: native.c:918
pcmk_resource_t * native_find_rsc(pcmk_resource_t *rsc, const char *id, const pcmk_node_t *on_node, int flags)
Definition: native.c:270
uint64_t flags
Definition: remote.c:211
void native_free(pcmk_resource_t *rsc)
Definition: native.c:888
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:26
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
Definition: strings.c:982