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