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