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