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