pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
native.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2023 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/msg_xml.h>
20 #include <pe_status_private.h>
21 
22 #ifdef PCMK__COMPAT_2_0
23 #define PROVIDER_SEP "::"
24 #else
25 #define PROVIDER_SEP ":"
26 #endif
27 
32 static bool
33 is_multiply_active(const pcmk_resource_t *rsc)
34 {
35  unsigned int count = 0;
36 
37  if (rsc->variant == pcmk_rsc_variant_primitive) {
38  pe__find_active_requires(rsc, &count);
39  }
40  return count > 1;
41 }
42 
43 static void
44 native_priority_to_node(pcmk_resource_t *rsc, pcmk_node_t *node,
45  gboolean failed)
46 {
47  int priority = 0;
48 
49  if ((rsc->priority == 0) || (failed == TRUE)) {
50  return;
51  }
52 
53  if (rsc->role == pcmk_role_promoted) {
54  // Promoted instance takes base priority + 1
55  priority = rsc->priority + 1;
56 
57  } else {
58  priority = rsc->priority;
59  }
60 
61  node->details->priority += priority;
62  pe_rsc_trace(rsc, "%s now has priority %d with %s'%s' (priority: %d%s)",
63  pe__node_name(node), node->details->priority,
64  (rsc->role == pcmk_role_promoted)? "promoted " : "",
65  rsc->id, rsc->priority,
66  (rsc->role == pcmk_role_promoted)? " + 1" : "");
67 
68  /* Priority of a resource running on a guest node is added to the cluster
69  * node as well. */
70  if (node->details->remote_rsc
71  && node->details->remote_rsc->container) {
72  GList *gIter = node->details->remote_rsc->container->running_on;
73 
74  for (; gIter != NULL; gIter = gIter->next) {
75  pcmk_node_t *a_node = gIter->data;
76 
77  a_node->details->priority += priority;
78  pe_rsc_trace(rsc, "%s now has priority %d with %s'%s' (priority: %d%s) "
79  "from guest node %s",
80  pe__node_name(a_node), a_node->details->priority,
81  (rsc->role == pcmk_role_promoted)? "promoted " : "",
82  rsc->id, rsc->priority,
83  (rsc->role == pcmk_role_promoted)? " + 1" : "",
84  pe__node_name(node));
85  }
86  }
87 }
88 
89 void
91  pcmk_scheduler_t *scheduler, gboolean failed)
92 {
93  GList *gIter = rsc->running_on;
94 
95  CRM_CHECK(node != NULL, return);
96  for (; gIter != NULL; gIter = gIter->next) {
97  pcmk_node_t *a_node = (pcmk_node_t *) gIter->data;
98 
99  CRM_CHECK(a_node != NULL, return);
100  if (pcmk__str_eq(a_node->details->id, node->details->id, pcmk__str_casei)) {
101  return;
102  }
103  }
104 
105  pe_rsc_trace(rsc, "Adding %s to %s %s", rsc->id, pe__node_name(node),
106  pcmk_is_set(rsc->flags, pcmk_rsc_managed)? "" : "(unmanaged)");
107 
108  rsc->running_on = g_list_append(rsc->running_on, node);
109  if (rsc->variant == pcmk_rsc_variant_primitive) {
110  node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
111 
112  native_priority_to_node(rsc, node, failed);
113  }
114 
115  if ((rsc->variant == pcmk_rsc_variant_primitive)
116  && node->details->maintenance) {
119  }
120 
121  if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
122  pcmk_resource_t *p = rsc->parent;
123 
124  pe_rsc_info(rsc, "resource %s isn't managed", rsc->id);
125  resource_location(rsc, node, INFINITY, "not_managed_default",
126  scheduler);
127 
128  while(p && node->details->online) {
129  /* add without the additional location constraint */
130  p->running_on = g_list_append(p->running_on, node);
131  p = p->parent;
132  }
133  return;
134  }
135 
136  if (is_multiply_active(rsc)) {
137  switch (rsc->recovery_type) {
139  {
140  GHashTableIter gIter;
141  pcmk_node_t *local_node = NULL;
142 
143  /* make sure it doesn't come up again */
144  if (rsc->allowed_nodes != NULL) {
145  g_hash_table_destroy(rsc->allowed_nodes);
146  }
148  g_hash_table_iter_init(&gIter, rsc->allowed_nodes);
149  while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
150  local_node->weight = -INFINITY;
151  }
152  }
153  break;
157 
158  /* If the resource belongs to a group or bundle configured with
159  * multiple-active=block, block the entire entity.
160  */
161  if (rsc->parent
162  && ((rsc->parent->variant == pcmk_rsc_variant_group)
163  || (rsc->parent->variant == pcmk_rsc_variant_bundle))
165  GList *gIter = rsc->parent->children;
166 
167  for (; gIter != NULL; gIter = gIter->next) {
168  pcmk_resource_t *child = gIter->data;
169 
172  }
173  }
174  break;
175 
176  // pcmk_multiply_active_restart, pcmk_multiply_active_unexpected
177  default:
178  /* The scheduler will do the right thing because the relevant
179  * variables and flags are set when unpacking the history.
180  */
181  break;
182  }
183  crm_debug("%s is active on multiple nodes including %s: %s",
184  rsc->id, pe__node_name(node),
185  recovery2text(rsc->recovery_type));
186 
187  } else {
188  pe_rsc_trace(rsc, "Resource %s is active on %s",
189  rsc->id, pe__node_name(node));
190  }
191 
192  if (rsc->parent != NULL) {
193  native_add_running(rsc->parent, node, scheduler, FALSE);
194  }
195 }
196 
197 static void
198 recursive_clear_unique(pcmk_resource_t *rsc, gpointer user_data)
199 {
202  g_list_foreach(rsc->children, (GFunc) recursive_clear_unique, NULL);
203 }
204 
205 gboolean
207 {
209  const char *standard = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
210  uint32_t ra_caps = pcmk_get_ra_caps(standard);
211 
212  pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
213 
214  // Only some agent standards support unique and promotable clones
215  if (!pcmk_is_set(ra_caps, pcmk_ra_cap_unique)
217  && pe_rsc_is_clone(parent)) {
218 
219  /* @COMPAT We should probably reject this situation as an error (as we
220  * do for promotable below) rather than warn and convert, but that would
221  * be a backward-incompatible change that we should probably do with a
222  * transform at a schema major version bump.
223  */
224  pe__force_anon(standard, parent, rsc->id, scheduler);
225 
226  /* Clear globally-unique on the parent and all its descendants unpacked
227  * so far (clearing the parent should make any future children unpacking
228  * correct). We have to clear this resource explicitly because it isn't
229  * hooked into the parent's children yet.
230  */
231  recursive_clear_unique(parent, NULL);
232  recursive_clear_unique(rsc, NULL);
233  }
234  if (!pcmk_is_set(ra_caps, pcmk_ra_cap_promotable)
235  && pcmk_is_set(parent->flags, pcmk_rsc_promotable)) {
236 
237  pe_err("Resource %s is of type %s and therefore "
238  "cannot be used as a promotable clone resource",
239  rsc->id, standard);
240  return FALSE;
241  }
242  return TRUE;
243 }
244 
245 static bool
246 rsc_is_on_node(pcmk_resource_t *rsc, const pcmk_node_t *node, int flags)
247 {
248  pe_rsc_trace(rsc, "Checking whether %s is on %s",
249  rsc->id, pe__node_name(node));
250 
252  && (rsc->running_on != NULL)) {
253 
254  for (GList *iter = rsc->running_on; iter; iter = iter->next) {
255  pcmk_node_t *loc = (pcmk_node_t *) iter->data;
256 
257  if (loc->details == node->details) {
258  return true;
259  }
260  }
261 
262  } else if (pcmk_is_set(flags, pe_find_inactive) // @COMPAT deprecated
263  && (rsc->running_on == NULL)) {
264  return true;
265 
267  && (rsc->allocated_to != NULL)
268  && (rsc->allocated_to->details == node->details)) {
269  return true;
270  }
271  return false;
272 }
273 
275 native_find_rsc(pcmk_resource_t *rsc, const char *id,
276  const pcmk_node_t *on_node, int flags)
277 {
278  bool match = false;
279  pcmk_resource_t *result = NULL;
280 
281  CRM_CHECK(id && rsc && rsc->id, return NULL);
282 
284  const char *rid = ID(rsc->xml);
285 
286  if (!pe_rsc_is_clone(pe__const_top_resource(rsc, false))) {
287  match = false;
288 
289  } else if (!strcmp(id, rsc->id) || pcmk__str_eq(id, rid, pcmk__str_none)) {
290  match = true;
291  }
292 
293  } else if (!strcmp(id, rsc->id)) {
294  match = true;
295 
297  && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
298  match = true;
299 
302  && !pcmk_is_set(rsc->flags, pcmk_rsc_unique))) {
303  match = pe_base_name_eq(rsc, id);
304  }
305 
306  if (match && on_node) {
307  if (!rsc_is_on_node(rsc, on_node, flags)) {
308  match = false;
309  }
310  }
311 
312  if (match) {
313  return rsc;
314  }
315 
316  for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
317  pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
318 
319  result = rsc->fns->find_rsc(child, id, on_node, flags);
320  if (result) {
321  return result;
322  }
323  }
324  return NULL;
325 }
326 
327 // create is ignored
328 char *
329 native_parameter(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create,
330  const char *name, pcmk_scheduler_t *scheduler)
331 {
332  char *value_copy = NULL;
333  const char *value = NULL;
334  GHashTable *params = NULL;
335 
336  CRM_CHECK(rsc != NULL, return NULL);
337  CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
338 
339  pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
340  params = pe_rsc_params(rsc, node, scheduler);
341  value = g_hash_table_lookup(params, name);
342  if (value == NULL) {
343  /* try meta attributes instead */
344  value = g_hash_table_lookup(rsc->meta, name);
345  }
346  pcmk__str_update(&value_copy, value);
347  return value_copy;
348 }
349 
350 gboolean
351 native_active(pcmk_resource_t * rsc, gboolean all)
352 {
353  for (GList *gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
354  pcmk_node_t *a_node = (pcmk_node_t *) gIter->data;
355 
356  if (a_node->details->unclean) {
357  pe_rsc_trace(rsc, "Resource %s: %s is unclean",
358  rsc->id, pe__node_name(a_node));
359  return TRUE;
360  } else if (!a_node->details->online
361  && pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
362  pe_rsc_trace(rsc, "Resource %s: %s is offline",
363  rsc->id, pe__node_name(a_node));
364  } else {
365  pe_rsc_trace(rsc, "Resource %s active on %s",
366  rsc->id, pe__node_name(a_node));
367  return TRUE;
368  }
369  }
370  return FALSE;
371 }
372 
373 struct print_data_s {
374  long options;
375  void *print_data;
376 };
377 
378 static const char *
379 native_pending_state(const pcmk_resource_t *rsc)
380 {
381  const char *pending_state = NULL;
382 
383  if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_START, pcmk__str_casei)) {
384  pending_state = "Starting";
385 
386  } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_STOP,
387  pcmk__str_casei)) {
388  pending_state = "Stopping";
389 
390  } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_MIGRATE_TO,
391  pcmk__str_casei)) {
392  pending_state = "Migrating";
393 
394  } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_MIGRATE_FROM,
395  pcmk__str_casei)) {
396  /* Work might be done in here. */
397  pending_state = "Migrating";
398 
399  } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_PROMOTE,
400  pcmk__str_casei)) {
401  pending_state = "Promoting";
402 
403  } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_DEMOTE,
404  pcmk__str_casei)) {
405  pending_state = "Demoting";
406  }
407 
408  return pending_state;
409 }
410 
411 static const char *
412 native_pending_task(const pcmk_resource_t *rsc)
413 {
414  const char *pending_task = NULL;
415 
416  if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_MONITOR, pcmk__str_casei)) {
417  pending_task = "Monitoring";
418 
419  /* Pending probes are not printed, even if pending
420  * operations are requested. If someone ever requests that
421  * behavior, uncomment this and the corresponding part of
422  * unpack.c:unpack_rsc_op().
423  */
424  /*
425  } else if (pcmk__str_eq(rsc->pending_task, "probe", pcmk__str_casei)) {
426  pending_task = "Checking";
427  */
428  }
429 
430  return pending_task;
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->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 = role2text(native_displayable_role(rsc));
457  }
458  return rsc_state;
459 }
460 
465 static void
466 native_print_xml(pcmk_resource_t *rsc, const char *pre_text, long options,
467  void *print_data)
468 {
469  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
470  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
471  const char *rsc_state = native_displayable_state(rsc, pcmk_is_set(options, pe_print_pending));
472  const char *target_role = NULL;
473 
474  /* resource information. */
475  status_print("%s<resource ", pre_text);
476  status_print(XML_ATTR_ID "=\"%s\" ", rsc_printable_id(rsc));
477  status_print("resource_agent=\"%s%s%s:%s\" ", class,
478  ((prov == NULL)? "" : PROVIDER_SEP),
479  ((prov == NULL)? "" : prov),
481 
482  status_print("role=\"%s\" ", rsc_state);
483  if (rsc->meta) {
484  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
485  }
486  if (target_role) {
487  status_print("target_role=\"%s\" ", target_role);
488  }
489  status_print("active=\"%s\" ", pcmk__btoa(rsc->fns->active(rsc, TRUE)));
490  status_print("orphaned=\"%s\" ", pe__rsc_bool_str(rsc, pcmk_rsc_removed));
491  status_print("blocked=\"%s\" ",
492  pe__rsc_bool_str(rsc, pcmk_rsc_blocked));
493  status_print("managed=\"%s\" ",
494  pe__rsc_bool_str(rsc, pcmk_rsc_managed));
495  status_print("failed=\"%s\" ", pe__rsc_bool_str(rsc, pcmk_rsc_failed));
496  status_print("failure_ignored=\"%s\" ",
497  pe__rsc_bool_str(rsc, pcmk_rsc_ignore_failure));
498  status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
499 
500  if (options & pe_print_pending) {
501  const char *pending_task = native_pending_task(rsc);
502 
503  if (pending_task) {
504  status_print("pending=\"%s\" ", pending_task);
505  }
506  }
507 
508  /* print out the nodes this resource is running on */
509  if (options & pe_print_rsconly) {
510  status_print("/>\n");
511  /* do nothing */
512  } else if (rsc->running_on != NULL) {
513  GList *gIter = rsc->running_on;
514 
515  status_print(">\n");
516  for (; gIter != NULL; gIter = gIter->next) {
517  pcmk_node_t *node = (pcmk_node_t *) gIter->data;
518 
519  status_print("%s <node name=\"%s\" " XML_ATTR_ID "=\"%s\" "
520  "cached=\"%s\"/>\n",
521  pre_text, pcmk__s(node->details->uname, ""),
522  node->details->id, pcmk__btoa(!node->details->online));
523  }
524  status_print("%s</resource>\n", pre_text);
525  } else {
526  status_print("/>\n");
527  }
528 }
529 
530 // Append a flag to resource description string's flags list
531 static bool
532 add_output_flag(GString *s, const char *flag_desc, bool have_flags)
533 {
534  g_string_append(s, (have_flags? ", " : " ("));
535  g_string_append(s, flag_desc);
536  return true;
537 }
538 
539 // Append a node name to resource description string's node list
540 static bool
541 add_output_node(GString *s, const char *node, bool have_nodes)
542 {
543  g_string_append(s, (have_nodes? " " : " [ "));
544  g_string_append(s, node);
545  return true;
546 }
547 
562 gchar *
564  const pcmk_node_t *node, uint32_t show_opts,
565  const char *target_role, bool show_nodes)
566 {
567  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
568  const char *provider = NULL;
569  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
570  GString *outstr = NULL;
571  bool have_flags = false;
572 
573  if (rsc->variant != pcmk_rsc_variant_primitive) {
574  return NULL;
575  }
576 
577  CRM_CHECK(name != NULL, name = "unknown");
578  CRM_CHECK(kind != NULL, kind = "unknown");
579  CRM_CHECK(class != NULL, class = "unknown");
580 
582  provider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
583  }
584 
585  if ((node == NULL) && (rsc->lock_node != NULL)) {
586  node = rsc->lock_node;
587  }
588  if (pcmk_any_flags_set(show_opts, pcmk_show_rsc_only)
589  || pcmk__list_of_multiple(rsc->running_on)) {
590  node = NULL;
591  }
592 
593  outstr = g_string_sized_new(128);
594 
595  // Resource name and agent
596  pcmk__g_strcat(outstr,
597  name, "\t(", class, ((provider == NULL)? "" : PROVIDER_SEP),
598  pcmk__s(provider, ""), ":", kind, "):\t", NULL);
599 
600  // State on node
601  if (pcmk_is_set(rsc->flags, pcmk_rsc_removed)) {
602  g_string_append(outstr, " ORPHANED");
603  }
604  if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
605  enum rsc_role_e role = native_displayable_role(rsc);
606 
607  g_string_append(outstr, " FAILED");
608  if (role > pcmk_role_unpromoted) {
609  pcmk__add_word(&outstr, 0, role2text(role));
610  }
611  } else {
612  bool show_pending = pcmk_is_set(show_opts, pcmk_show_pending);
613 
614  pcmk__add_word(&outstr, 0, native_displayable_state(rsc, show_pending));
615  }
616  if (node) {
617  pcmk__add_word(&outstr, 0, pe__node_name(node));
618  }
619 
620  // Failed probe operation
621  if (native_displayable_role(rsc) == pcmk_role_stopped) {
622  xmlNode *probe_op = pe__failed_probe_for_rsc(rsc, node ? node->details->uname : NULL);
623  if (probe_op != NULL) {
624  int rc;
625 
627  pcmk__g_strcat(outstr, " (", services_ocf_exitcode_str(rc), ") ",
628  NULL);
629  }
630  }
631 
632  // Flags, as: (<flag> [...])
633  if (node && !(node->details->online) && node->details->unclean) {
634  have_flags = add_output_flag(outstr, "UNCLEAN", have_flags);
635  }
636  if (node && (node == rsc->lock_node)) {
637  have_flags = add_output_flag(outstr, "LOCKED", have_flags);
638  }
639  if (pcmk_is_set(show_opts, pcmk_show_pending)) {
640  const char *pending_task = native_pending_task(rsc);
641 
642  if (pending_task) {
643  have_flags = add_output_flag(outstr, pending_task, have_flags);
644  }
645  }
646  if (target_role) {
647  enum rsc_role_e target_role_e = text2role(target_role);
648 
649  /* Only show target role if it limits our abilities (i.e. ignore
650  * Started, as it is the default anyways, and doesn't prevent the
651  * resource from becoming promoted).
652  */
653  if (target_role_e == pcmk_role_stopped) {
654  have_flags = add_output_flag(outstr, "disabled", have_flags);
655 
656  } else if (pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
658  && (target_role_e == pcmk_role_unpromoted)) {
659  have_flags = add_output_flag(outstr, "target-role:", have_flags);
660  g_string_append(outstr, target_role);
661  }
662  }
663 
664  // Blocked or maintenance implies unmanaged
665  if (pcmk_any_flags_set(rsc->flags,
667  if (pcmk_is_set(rsc->flags, pcmk_rsc_blocked)) {
668  have_flags = add_output_flag(outstr, "blocked", have_flags);
669 
670  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_maintenance)) {
671  have_flags = add_output_flag(outstr, "maintenance", have_flags);
672  }
673  } else if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
674  have_flags = add_output_flag(outstr, "unmanaged", have_flags);
675  }
676 
677  if (pcmk_is_set(rsc->flags, pcmk_rsc_ignore_failure)) {
678  have_flags = add_output_flag(outstr, "failure ignored", have_flags);
679  }
680 
681 
682  if (have_flags) {
683  g_string_append_c(outstr, ')');
684  }
685 
686  // User-supplied description
687  if (pcmk_any_flags_set(show_opts, pcmk_show_rsc_only|pcmk_show_description)
688  || pcmk__list_of_multiple(rsc->running_on)) {
689  const char *desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
690 
691  if (desc) {
692  g_string_append(outstr, " (");
693  g_string_append(outstr, desc);
694  g_string_append(outstr, ")");
695 
696  }
697  }
698 
699  if (show_nodes && !pcmk_is_set(show_opts, pcmk_show_rsc_only)
700  && pcmk__list_of_multiple(rsc->running_on)) {
701  bool have_nodes = false;
702 
703  for (GList *iter = rsc->running_on; iter != NULL; iter = iter->next) {
704  pcmk_node_t *n = (pcmk_node_t *) iter->data;
705 
706  have_nodes = add_output_node(outstr, n->details->uname, have_nodes);
707  }
708  if (have_nodes) {
709  g_string_append(outstr, " ]");
710  }
711  }
712 
713  return g_string_free(outstr, FALSE);
714 }
715 
716 int
718  const char *name, const pcmk_node_t *node,
719  uint32_t show_opts)
720 {
721  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
722  const char *target_role = NULL;
723 
724  xmlNodePtr list_node = NULL;
725  const char *cl = NULL;
726 
728  CRM_ASSERT(kind != NULL);
729 
730  if (rsc->meta) {
731  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
732 
733  if (crm_is_true(is_internal)
734  && !pcmk_is_set(show_opts, pcmk_show_implicit_rscs)) {
735 
736  crm_trace("skipping print of internal resource %s", rsc->id);
737  return pcmk_rc_no_output;
738  }
739  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
740  }
741 
742  if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
743  cl = "rsc-managed";
744 
745  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
746  cl = "rsc-failed";
747 
748  } else if ((rsc->variant == pcmk_rsc_variant_primitive)
749  && (rsc->running_on == NULL)) {
750  cl = "rsc-failed";
751 
752  } else if (pcmk__list_of_multiple(rsc->running_on)) {
753  cl = "rsc-multiple";
754 
755  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_ignore_failure)) {
756  cl = "rsc-failure-ignored";
757 
758  } else {
759  cl = "rsc-ok";
760  }
761 
762  {
763  gchar *s = pcmk__native_output_string(rsc, name, node, show_opts,
764  target_role, true);
765 
766  list_node = pcmk__output_create_html_node(out, "li", NULL, NULL, NULL);
767  pcmk_create_html_node(list_node, "span", NULL, cl, s);
768  g_free(s);
769  }
770 
771  return pcmk_rc_ok;
772 }
773 
774 int
776  const char *name, const pcmk_node_t *node,
777  uint32_t show_opts)
778 {
779  const char *target_role = NULL;
780 
782 
783  if (rsc->meta) {
784  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
785 
786  if (crm_is_true(is_internal)
787  && !pcmk_is_set(show_opts, pcmk_show_implicit_rscs)) {
788 
789  crm_trace("skipping print of internal resource %s", rsc->id);
790  return pcmk_rc_no_output;
791  }
792  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
793  }
794 
795  {
796  gchar *s = pcmk__native_output_string(rsc, name, node, show_opts,
797  target_role, true);
798 
799  out->list_item(out, NULL, "%s", s);
800  g_free(s);
801  }
802 
803  return pcmk_rc_ok;
804 }
805 
810 void
811 common_print(pcmk_resource_t *rsc, const char *pre_text, const char *name,
812  const pcmk_node_t *node, long options, void *print_data)
813 {
814  const char *target_role = NULL;
815 
817 
818  if (rsc->meta) {
819  const char *is_internal = g_hash_table_lookup(rsc->meta,
821 
822  if (crm_is_true(is_internal)
823  && !pcmk_is_set(options, pe_print_implicit)) {
824 
825  crm_trace("skipping print of internal resource %s", rsc->id);
826  return;
827  }
828  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
829  }
830 
831  if (options & pe_print_xml) {
832  native_print_xml(rsc, pre_text, options, print_data);
833  return;
834  }
835 
836  if ((pre_text == NULL) && (options & pe_print_printf)) {
837  pre_text = " ";
838  }
839 
840  if (options & pe_print_html) {
841  if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
842  status_print("<font color=\"yellow\">");
843 
844  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
845  status_print("<font color=\"red\">");
846 
847  } else if (rsc->running_on == NULL) {
848  status_print("<font color=\"red\">");
849 
850  } else if (pcmk__list_of_multiple(rsc->running_on)) {
851  status_print("<font color=\"orange\">");
852 
853  } else if (pcmk_is_set(rsc->flags, pcmk_rsc_ignore_failure)) {
854  status_print("<font color=\"yellow\">");
855 
856  } else {
857  status_print("<font color=\"green\">");
858  }
859  }
860 
861  {
862  gchar *resource_s = pcmk__native_output_string(rsc, name, node, options,
863  target_role, false);
864  status_print("%s%s", (pre_text? pre_text : ""), resource_s);
865  g_free(resource_s);
866  }
867 
868  if (pcmk_is_set(options, pe_print_html)) {
869  status_print(" </font> ");
870  }
871 
872  if (!pcmk_is_set(options, pe_print_rsconly)
873  && pcmk__list_of_multiple(rsc->running_on)) {
874 
875  GList *gIter = rsc->running_on;
876  int counter = 0;
877 
878  if (options & pe_print_html) {
879  status_print("<ul>\n");
880  } else if ((options & pe_print_printf)
881  || (options & pe_print_ncurses)) {
882  status_print("[");
883  }
884 
885  for (; gIter != NULL; gIter = gIter->next) {
886  pcmk_node_t *n = (pcmk_node_t *) gIter->data;
887 
888  counter++;
889 
890  if (options & pe_print_html) {
891  status_print("<li>\n%s", pe__node_name(n));
892 
893  } else if ((options & pe_print_printf)
894  || (options & pe_print_ncurses)) {
895  status_print(" %s", pe__node_name(n));
896 
897  } else if ((options & pe_print_log)) {
898  status_print("\t%d : %s", counter, pe__node_name(n));
899 
900  } else {
901  status_print("%s", pe__node_name(n));
902  }
903  if (options & pe_print_html) {
904  status_print("</li>\n");
905 
906  }
907  }
908 
909  if (options & pe_print_html) {
910  status_print("</ul>\n");
911  } else if ((options & pe_print_printf)
912  || (options & pe_print_ncurses)) {
913  status_print(" ]");
914  }
915  }
916 
917  if (options & pe_print_html) {
918  status_print("<br/>\n");
919  } else if (options & pe_print_suppres_nl) {
920  /* nothing */
921  } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
922  status_print("\n");
923  }
924 }
925 
930 void
931 native_print(pcmk_resource_t *rsc, const char *pre_text, long options,
932  void *print_data)
933 {
934  const pcmk_node_t *node = NULL;
935 
937  if (options & pe_print_xml) {
938  native_print_xml(rsc, pre_text, options, print_data);
939  return;
940  }
941 
942  node = pe__current_node(rsc);
943 
944  if (node == NULL) {
945  // This is set only if a non-probe action is pending on this node
946  node = rsc->pending_node;
947  }
948 
949  common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
950 }
951 
952 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
953  "GList *")
954 int
955 pe__resource_xml(pcmk__output_t *out, va_list args)
956 {
957  uint32_t show_opts = va_arg(args, uint32_t);
958  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
959  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
960  GList *only_rsc = va_arg(args, GList *);
961 
962  bool print_pending = pcmk_is_set(show_opts, pcmk_show_pending);
963  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
964  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
965  const char *rsc_state = native_displayable_state(rsc, print_pending);
966 
967  const char *desc = NULL;
968  char ra_name[LINE_MAX];
969  char *nodes_running_on = NULL;
970  const char *lock_node_name = NULL;
971  int rc = pcmk_rc_no_output;
972  const char *target_role = NULL;
973 
974  desc = pe__resource_description(rsc, show_opts);
975 
976  if (rsc->meta != NULL) {
977  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
978  }
979 
980  CRM_ASSERT(rsc->variant == pcmk_rsc_variant_primitive);
981 
982  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
983  return pcmk_rc_no_output;
984  }
985 
986  /* resource information. */
987  snprintf(ra_name, LINE_MAX, "%s%s%s:%s", class,
988  ((prov == NULL)? "" : PROVIDER_SEP), ((prov == NULL)? "" : prov),
989  crm_element_value(rsc->xml, XML_ATTR_TYPE));
990 
991  nodes_running_on = pcmk__itoa(g_list_length(rsc->running_on));
992 
993  if (rsc->lock_node != NULL) {
994  lock_node_name = rsc->lock_node->details->uname;
995  }
996 
997  rc = pe__name_and_nvpairs_xml(out, true, "resource", 15,
998  "id", rsc_printable_id(rsc),
999  "resource_agent", ra_name,
1000  "role", rsc_state,
1001  "target_role", target_role,
1002  "active", pcmk__btoa(rsc->fns->active(rsc, TRUE)),
1003  "orphaned", pe__rsc_bool_str(rsc, pcmk_rsc_removed),
1004  "blocked", pe__rsc_bool_str(rsc, pcmk_rsc_blocked),
1005  "maintenance", pe__rsc_bool_str(rsc, pcmk_rsc_maintenance),
1006  "managed", pe__rsc_bool_str(rsc, pcmk_rsc_managed),
1007  "failed", pe__rsc_bool_str(rsc, pcmk_rsc_failed),
1008  "failure_ignored", pe__rsc_bool_str(rsc, pcmk_rsc_ignore_failure),
1009  "nodes_running_on", nodes_running_on,
1010  "pending", (print_pending? native_pending_task(rsc) : NULL),
1011  "locked_to", lock_node_name,
1012  "description", desc);
1013  free(nodes_running_on);
1014 
1015  CRM_ASSERT(rc == pcmk_rc_ok);
1016 
1017  if (rsc->running_on != NULL) {
1018  GList *gIter = rsc->running_on;
1019 
1020  for (; gIter != NULL; gIter = gIter->next) {
1021  pcmk_node_t *node = (pcmk_node_t *) gIter->data;
1022 
1023  rc = pe__name_and_nvpairs_xml(out, false, "node", 3,
1024  "name", node->details->uname,
1025  "id", node->details->id,
1026  "cached", pcmk__btoa(node->details->online));
1027  CRM_ASSERT(rc == pcmk_rc_ok);
1028  }
1029  }
1030 
1032  return rc;
1033 }
1034 
1035 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
1036  "GList *")
1037 int
1038 pe__resource_html(pcmk__output_t *out, va_list args)
1039 {
1040  uint32_t show_opts = va_arg(args, uint32_t);
1041  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
1042  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
1043  GList *only_rsc = va_arg(args, GList *);
1044 
1045  const pcmk_node_t *node = pe__current_node(rsc);
1046 
1047  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1048  return pcmk_rc_no_output;
1049  }
1050 
1052 
1053  if (node == NULL) {
1054  // This is set only if a non-probe action is pending on this node
1055  node = rsc->pending_node;
1056  }
1057  return pe__common_output_html(out, rsc, rsc_printable_id(rsc), node, show_opts);
1058 }
1059 
1060 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
1061  "GList *")
1062 int
1063 pe__resource_text(pcmk__output_t *out, va_list args)
1064 {
1065  uint32_t show_opts = va_arg(args, uint32_t);
1066  pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
1067  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
1068  GList *only_rsc = va_arg(args, GList *);
1069 
1070  const pcmk_node_t *node = pe__current_node(rsc);
1071 
1073 
1074  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1075  return pcmk_rc_no_output;
1076  }
1077 
1078  if (node == NULL) {
1079  // This is set only if a non-probe action is pending on this node
1080  node = rsc->pending_node;
1081  }
1082  return pe__common_output_text(out, rsc, rsc_printable_id(rsc), node, show_opts);
1083 }
1084 
1085 void
1087 {
1088  pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
1089  common_free(rsc);
1090 }
1091 
1092 enum rsc_role_e
1093 native_resource_state(const pcmk_resource_t * rsc, gboolean current)
1094 {
1095  enum rsc_role_e role = rsc->next_role;
1096 
1097  if (current) {
1098  role = rsc->role;
1099  }
1100  pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
1101  return role;
1102 }
1103 
1115 pcmk_node_t *
1116 native_location(const pcmk_resource_t *rsc, GList **list, int current)
1117 {
1118  // @COMPAT: Accept a pcmk__rsc_node argument instead of int current
1119  pcmk_node_t *one = NULL;
1120  GList *result = NULL;
1121 
1122  if (rsc->children) {
1123  GList *gIter = rsc->children;
1124 
1125  for (; gIter != NULL; gIter = gIter->next) {
1126  pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
1127 
1128  child->fns->location(child, &result, current);
1129  }
1130 
1131  } else if (current) {
1132 
1133  if (rsc->running_on) {
1134  result = g_list_copy(rsc->running_on);
1135  }
1136  if ((current == 2) && rsc->pending_node
1137  && !pe_find_node_id(result, rsc->pending_node->details->id)) {
1138  result = g_list_append(result, rsc->pending_node);
1139  }
1140 
1141  } else if (current == FALSE && rsc->allocated_to) {
1142  result = g_list_append(NULL, rsc->allocated_to);
1143  }
1144 
1145  if (result && (result->next == NULL)) {
1146  one = result->data;
1147  }
1148 
1149  if (list) {
1150  GList *gIter = result;
1151 
1152  for (; gIter != NULL; gIter = gIter->next) {
1153  pcmk_node_t *node = (pcmk_node_t *) gIter->data;
1154 
1155  if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
1156  *list = g_list_append(*list, node);
1157  }
1158  }
1159  }
1160 
1161  g_list_free(result);
1162  return one;
1163 }
1164 
1165 static void
1166 get_rscs_brief(GList *rsc_list, GHashTable * rsc_table, GHashTable * active_table)
1167 {
1168  GList *gIter = rsc_list;
1169 
1170  for (; gIter != NULL; gIter = gIter->next) {
1171  pcmk_resource_t *rsc = (pcmk_resource_t *) gIter->data;
1172 
1173  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1174  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
1175 
1176  int offset = 0;
1177  char buffer[LINE_MAX];
1178 
1179  int *rsc_counter = NULL;
1180  int *active_counter = NULL;
1181 
1182  if (rsc->variant != pcmk_rsc_variant_primitive) {
1183  continue;
1184  }
1185 
1186  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
1188  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
1189 
1190  if (prov != NULL) {
1191  offset += snprintf(buffer + offset, LINE_MAX - offset,
1192  PROVIDER_SEP "%s", prov);
1193  }
1194  }
1195  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
1196  CRM_LOG_ASSERT(offset > 0);
1197 
1198  if (rsc_table) {
1199  rsc_counter = g_hash_table_lookup(rsc_table, buffer);
1200  if (rsc_counter == NULL) {
1201  rsc_counter = calloc(1, sizeof(int));
1202  *rsc_counter = 0;
1203  g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
1204  }
1205  (*rsc_counter)++;
1206  }
1207 
1208  if (active_table) {
1209  GList *gIter2 = rsc->running_on;
1210 
1211  for (; gIter2 != NULL; gIter2 = gIter2->next) {
1212  pcmk_node_t *node = (pcmk_node_t *) gIter2->data;
1213  GHashTable *node_table = NULL;
1214 
1215  if (node->details->unclean == FALSE && node->details->online == FALSE &&
1217  continue;
1218  }
1219 
1220  node_table = g_hash_table_lookup(active_table, node->details->uname);
1221  if (node_table == NULL) {
1222  node_table = pcmk__strkey_table(free, free);
1223  g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
1224  }
1225 
1226  active_counter = g_hash_table_lookup(node_table, buffer);
1227  if (active_counter == NULL) {
1228  active_counter = calloc(1, sizeof(int));
1229  *active_counter = 0;
1230  g_hash_table_insert(node_table, strdup(buffer), active_counter);
1231  }
1232  (*active_counter)++;
1233  }
1234  }
1235  }
1236 }
1237 
1238 static void
1239 destroy_node_table(gpointer data)
1240 {
1241  GHashTable *node_table = data;
1242 
1243  if (node_table) {
1244  g_hash_table_destroy(node_table);
1245  }
1246 }
1247 
1252 void
1253 print_rscs_brief(GList *rsc_list, const char *pre_text, long options,
1254  void *print_data, gboolean print_all)
1255 {
1256  GHashTable *rsc_table = pcmk__strkey_table(free, free);
1257  GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1258  GHashTableIter hash_iter;
1259  char *type = NULL;
1260  int *rsc_counter = NULL;
1261 
1262  get_rscs_brief(rsc_list, rsc_table, active_table);
1263 
1264  g_hash_table_iter_init(&hash_iter, rsc_table);
1265  while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
1266  GHashTableIter hash_iter2;
1267  char *node_name = NULL;
1268  GHashTable *node_table = NULL;
1269  int active_counter_all = 0;
1270 
1271  g_hash_table_iter_init(&hash_iter2, active_table);
1272  while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
1273  int *active_counter = g_hash_table_lookup(node_table, type);
1274 
1275  if (active_counter == NULL || *active_counter == 0) {
1276  continue;
1277 
1278  } else {
1279  active_counter_all += *active_counter;
1280  }
1281 
1282  if (options & pe_print_rsconly) {
1283  node_name = NULL;
1284  }
1285 
1286  if (options & pe_print_html) {
1287  status_print("<li>\n");
1288  }
1289 
1290  if (print_all) {
1291  status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1292  active_counter ? *active_counter : 0,
1293  rsc_counter ? *rsc_counter : 0, type,
1294  active_counter && (*active_counter > 0) && node_name ? node_name : "");
1295  } else {
1296  status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1297  active_counter ? *active_counter : 0, type,
1298  active_counter && (*active_counter > 0) && node_name ? node_name : "");
1299  }
1300 
1301  if (options & pe_print_html) {
1302  status_print("</li>\n");
1303  }
1304  }
1305 
1306  if (print_all && active_counter_all == 0) {
1307  if (options & pe_print_html) {
1308  status_print("<li>\n");
1309  }
1310 
1311  status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
1312  active_counter_all,
1313  rsc_counter ? *rsc_counter : 0, type);
1314 
1315  if (options & pe_print_html) {
1316  status_print("</li>\n");
1317  }
1318  }
1319  }
1320 
1321  if (rsc_table) {
1322  g_hash_table_destroy(rsc_table);
1323  rsc_table = NULL;
1324  }
1325  if (active_table) {
1326  g_hash_table_destroy(active_table);
1327  active_table = NULL;
1328  }
1329 }
1330 
1331 int
1332 pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, uint32_t show_opts)
1333 {
1334  GHashTable *rsc_table = pcmk__strkey_table(free, free);
1335  GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1336  GList *sorted_rscs;
1337  int rc = pcmk_rc_no_output;
1338 
1339  get_rscs_brief(rsc_list, rsc_table, active_table);
1340 
1341  /* Make a list of the rsc_table keys so that it can be sorted. This is to make sure
1342  * output order stays consistent between systems.
1343  */
1344  sorted_rscs = g_hash_table_get_keys(rsc_table);
1345  sorted_rscs = g_list_sort(sorted_rscs, (GCompareFunc) strcmp);
1346 
1347  for (GList *gIter = sorted_rscs; gIter; gIter = gIter->next) {
1348  char *type = (char *) gIter->data;
1349  int *rsc_counter = g_hash_table_lookup(rsc_table, type);
1350 
1351  GList *sorted_nodes = NULL;
1352  int active_counter_all = 0;
1353 
1354  /* Also make a list of the active_table keys so it can be sorted. If there's
1355  * more than one instance of a type of resource running, we need the nodes to
1356  * be sorted to make sure output order stays consistent between systems.
1357  */
1358  sorted_nodes = g_hash_table_get_keys(active_table);
1359  sorted_nodes = g_list_sort(sorted_nodes, (GCompareFunc) pcmk__numeric_strcasecmp);
1360 
1361  for (GList *gIter2 = sorted_nodes; gIter2; gIter2 = gIter2->next) {
1362  char *node_name = (char *) gIter2->data;
1363  GHashTable *node_table = g_hash_table_lookup(active_table, node_name);
1364  int *active_counter = NULL;
1365 
1366  if (node_table == NULL) {
1367  continue;
1368  }
1369 
1370  active_counter = g_hash_table_lookup(node_table, type);
1371 
1372  if (active_counter == NULL || *active_counter == 0) {
1373  continue;
1374 
1375  } else {
1376  active_counter_all += *active_counter;
1377  }
1378 
1379  if (pcmk_is_set(show_opts, pcmk_show_rsc_only)) {
1380  node_name = NULL;
1381  }
1382 
1383  if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs)) {
1384  out->list_item(out, NULL, "%d/%d\t(%s):\tActive %s",
1385  *active_counter,
1386  rsc_counter ? *rsc_counter : 0, type,
1387  (*active_counter > 0) && node_name ? node_name : "");
1388  } else {
1389  out->list_item(out, NULL, "%d\t(%s):\tActive %s",
1390  *active_counter, type,
1391  (*active_counter > 0) && node_name ? node_name : "");
1392  }
1393 
1394  rc = pcmk_rc_ok;
1395  }
1396 
1397  if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs) && active_counter_all == 0) {
1398  out->list_item(out, NULL, "%d/%d\t(%s):\tActive",
1399  active_counter_all,
1400  rsc_counter ? *rsc_counter : 0, type);
1401  rc = pcmk_rc_ok;
1402  }
1403 
1404  if (sorted_nodes) {
1405  g_list_free(sorted_nodes);
1406  }
1407  }
1408 
1409  if (rsc_table) {
1410  g_hash_table_destroy(rsc_table);
1411  rsc_table = NULL;
1412  }
1413  if (active_table) {
1414  g_hash_table_destroy(active_table);
1415  active_table = NULL;
1416  }
1417  if (sorted_rscs) {
1418  g_list_free(sorted_rscs);
1419  }
1420 
1421  return rc;
1422 }
1423 
1424 gboolean
1425 pe__native_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc,
1426  gboolean check_parent)
1427 {
1429  pcmk__str_in_list(rsc->id, only_rsc, pcmk__str_star_matches)) {
1430  return FALSE;
1431  } else if (check_parent && rsc->parent) {
1432  const pcmk_resource_t *up = pe__const_top_resource(rsc, true);
1433 
1434  return up->fns->is_filtered(up, only_rsc, FALSE);
1435  }
1436 
1437  return TRUE;
1438 }
1439 
1448 unsigned int
1450 {
1451  CRM_ASSERT((rsc != NULL) && (rsc->variant == pcmk_rsc_variant_primitive));
1452  return 1U;
1453 }
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
Definition: complex.c:962
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:238
void native_print(pcmk_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:931
Also match anonymous clone instances by base name.
Definition: resources.h:202
char data[0]
Definition: cpg.c:55
#define INFINITY
Definition: crm.h:98
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, int current)
List nodes where a resource (or any of its children) is.
Definition: resources.h:339
Control output from tools.
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:127
pcmk_node_t * pe__find_active_requires(const pcmk_resource_t *rsc, unsigned int *count)
Definition: complex.c:1139
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
Definition: complex.c:936
Stopped.
Definition: roles.h:29
const char * name
Definition: cib.c:26
#define XML_ATTR_TYPE
Definition: msg_xml.h:160
enum rsc_role_e role
Resource&#39;s current role.
Definition: resources.h:468
xmlNode * pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name)
Definition: utils.c:869
GList * children
Resource&#39;s child resources, if any.
Definition: resources.h:475
Match only clones and their instances, by either clone or instance ID.
Definition: resources.h:205
#define XML_BOOLEAN_FALSE
Definition: msg_xml.h:168
#define PROVIDER_SEP
Definition: native.c:25
int pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, uint32_t show_opts)
Definition: native.c:1332
void pe__force_anon(const char *standard, pcmk_resource_t *rsc, const char *rid, pcmk_scheduler_t *scheduler)
Definition: clone.c:210
xmlNode * xml
Resource configuration (possibly expanded from template)
Definition: resources.h:404
enum rsc_role_e next_role
Resource&#39;s scheduled next role.
Definition: resources.h:469
xmlNode * pcmk_create_html_node(xmlNode *parent, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: xml.c:684
char * native_parameter(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create, const char *name, pcmk_scheduler_t *scheduler)
Definition: native.c:329
Do nothing to resource.
Definition: resources.h:79
#define PCMK_ACTION_MONITOR
Definition: actions.h:59
const char * pe__resource_description(const pcmk_resource_t *rsc, uint32_t show_opts)
Definition: pe_output.c:22
GHashTable * meta
Resource&#39;s meta-attributes.
Definition: resources.h:471
Whether resource, its node, or entire cluster is in maintenance mode.
Definition: resources.h:181
gboolean pe__native_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
Definition: native.c:1425
#define PCMK_ACTION_MIGRATE_TO
Definition: actions.h:58
Promoted.
Definition: roles.h:32
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:222
Group resource.
Definition: resources.h:35
enum crm_ais_msg_types type
Definition: cpg.c:48
const char * rsc_printable_id(const pcmk_resource_t *rsc)
Definition: utils.c:546
#define resource_s
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:434
pcmk_resource_t * container
Resource containing this one, if any.
Definition: resources.h:480
int pe__resource_text(pcmk__output_t *out, va_list args)
Implementation of pcmk_scheduler_t.
Definition: scheduler.h:172
char * pending_task
Pending action in history, if any.
Definition: resources.h:428
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:717
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:64
GList * nodes
Nodes in cluster.
Definition: scheduler.h:195
void print_rscs_brief(GList *rsc_list, const char *pre_text, long options, void *print_data, gboolean print_all)
Definition: native.c:1253
Also match clone instance ID from resource history.
Definition: resources.h:199
pcmk_resource_t *(* find_rsc)(pcmk_resource_t *rsc, const char *search, const pcmk_node_t *node, int flags)
Search for a resource ID in a resource and its children.
Definition: resources.h:287
const char * role2text(enum rsc_role_e role)
Definition: common.c:458
Stop on all and leave stopped.
Definition: resources.h:78
#define PCMK_ACTION_DEMOTE
Definition: actions.h:49
pcmk_resource_t * parent
Resource&#39;s parent resource, if any.
Definition: resources.h:413
void common_free(pcmk_resource_t *rsc)
Definition: complex.c:980
Bundle resource.
Definition: resources.h:37
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:775
Implementation of pcmk_resource_t.
Definition: resources.h:399
#define crm_debug(fmt, args...)
Definition: logging.h:386
Primitive resource.
Definition: resources.h:34
#define XML_ATTR_ID
Definition: msg_xml.h:156
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:447
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:448
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
Definition: utils.c:360
void native_add_running(pcmk_resource_t *rsc, pcmk_node_t *node, pcmk_scheduler_t *scheduler, gboolean failed)
Definition: native.c:90
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name, size_t pairs_count,...)
Definition: pe_output.c:597
int priority
Configured priority.
Definition: resources.h:422
unsigned int pe__primitive_max_per_node(const pcmk_resource_t *rsc)
Definition: native.c:1449
Whether resource is considered failed.
Definition: resources.h:151
#define crm_trace(fmt, args...)
Definition: logging.h:387
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1217
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:99
struct pe_node_shared_s * details
Basic node information.
Definition: nodes.h:134
enum rsc_recovery_type recovery_type
How to recover if failed.
Definition: resources.h:419
#define PCMK_ACTION_START
Definition: actions.h:71
gboolean native_unpack(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler)
Definition: native.c:206
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:281
unsigned long long flags
Group of enum pcmk_rsc_flags.
Definition: resources.h:429
const char * uname
Node name in cluster.
Definition: nodes.h:68
Unpromoted.
Definition: roles.h:31
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
rsc_role_e
Definition: roles.h:27
char * clone_name
Resource instance ID in history.
Definition: resources.h:401
Match clone instances (even unique) by base name as well as exact ID.
Definition: resources.h:214
#define XML_ATTR_DESC
Definition: msg_xml.h:155
#define PCMK_ACTION_STOP
Definition: actions.h:74
enum rsc_role_e native_resource_state(const pcmk_resource_t *rsc, gboolean current)
Definition: native.c:1093
GHashTable * pe__node_list2table(const GList *list)
Definition: utils.c:116
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:249
PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *", "GList *")
Definition: native.c:952
gboolean native_active(pcmk_resource_t *rsc, gboolean all)
Definition: native.c:351
Whether resource is blocked from further action.
Definition: resources.h:109
Implementation of pcmk_node_t.
Definition: nodes.h:130
enum rsc_role_e text2role(const char *role)
Definition: common.c:487
enum pe_obj_types variant
Resource variant.
Definition: resources.h:414
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:522
const char * id
Node ID at the cluster layer.
Definition: nodes.h:67
int pe__resource_xml(pcmk__output_t *out, va_list args)
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:250
GList * running_rsc
List of resources active on node.
Definition: nodes.h:113
Whether resource has an ignorable failure.
Definition: resources.h:175
gboolean(* active)(pcmk_resource_t *rsc, gboolean all)
Check whether a resource is active.
Definition: resources.h:317
Cluster status and scheduling.
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:608
pcmk__action_result_t result
Definition: pcmk_fence.c:35
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:508
pcmk_rsc_methods_t * fns
Resource object methods.
Definition: resources.h:416
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:563
#define CRM_ASSERT(expr)
Definition: results.h:42
If matching by node, compare current node instead of assigned node.
Definition: resources.h:208
void(*) void(* list_item)(pcmk__output_t *out, const char *name, const char *format,...) G_GNUC_PRINTF(3
#define status_print(fmt, args...)
#define PCMK_ACTION_MIGRATE_FROM
Definition: actions.h:57
Started.
Definition: roles.h:30
This structure contains everything that makes up a single output formatter.
pcmk_node_t * allocated_to
Node resource is assigned to.
Definition: resources.h:451
#define XML_RSC_ATTR_INTERNAL_RSC
Definition: msg_xml.h:256
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:70
#define PCMK_ACTION_PROMOTE
Definition: actions.h:65
int pe__resource_html(pcmk__output_t *out, va_list args)
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition: strings.c:1023
gboolean(* is_filtered)(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
Check whether a given resource is in a list of resources.
Definition: resources.h:369
GList * running_on
Nodes where resource may be active.
Definition: resources.h:460
gboolean maintenance
Whether in maintenance mode.
Definition: nodes.h:81
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:317
pcmk_node_t * native_location(const pcmk_resource_t *rsc, GList **list, int current)
Definition: native.c:1116
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition: agents.c:31
pcmk_node_t * pending_node
Node on which pending_task is happening.
Definition: resources.h:484
gboolean crm_is_true(const char *s)
Definition: strings.c:416
Whether resource can be promoted and demoted.
Definition: resources.h:124
void common_print(pcmk_resource_t *rsc, const char *pre_text, const char *name, const pcmk_node_t *node, long options, void *print_data)
Definition: native.c:811
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:37
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:446
#define ID(x)
Definition: msg_xml.h:474
#define pe_err(fmt...)
Definition: internal.h:39
const char * parent
Definition: cib.c:27
Whether resource is managed.
Definition: resources.h:106
gboolean unclean
Whether node requires fencing.
Definition: nodes.h:76
Whether resource has been removed from the configuration.
Definition: resources.h:103
pcmk_resource_t * native_find_rsc(pcmk_resource_t *rsc, const char *id, const pcmk_node_t *on_node, int flags)
Definition: native.c:275
gboolean online
Whether online.
Definition: nodes.h:72
uint64_t flags
Definition: remote.c:215
Whether resource is not an anonymous clone instance.
Definition: resources.h:118
void native_free(pcmk_resource_t *rsc)
Definition: native.c:1086
pcmk_resource_t * remote_rsc
Remote connection resource for node, if it is a Pacemaker Remote node.
Definition: nodes.h:111
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:35
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:280
char * id
Resource ID in configuration.
Definition: resources.h:400
GHashTable * allowed_nodes
Nodes where resource may run (key is node ID, not name)
Definition: resources.h:466
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
Definition: strings.c:888