pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
native.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2023 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <stdint.h>
13 
14 #include <crm/common/output.h>
15 #include <crm/pengine/rules.h>
16 #include <crm/pengine/status.h>
17 #include <crm/pengine/complex.h>
18 #include <crm/pengine/internal.h>
19 #include <crm/msg_xml.h>
20 #include <pe_status_private.h>
21 
22 #ifdef PCMK__COMPAT_2_0
23 #define PROVIDER_SEP "::"
24 #else
25 #define PROVIDER_SEP ":"
26 #endif
27 
32 static bool
33 is_multiply_active(const 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) {
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  }
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_block:
153 
154  /* If the resource belongs to a group or bundle configured with
155  * multiple-active=block, block the entire entity.
156  */
157  if (rsc->parent
158  && (rsc->parent->variant == pe_group || rsc->parent->variant == pe_container)
159  && rsc->parent->recovery_type == recovery_block) {
160  GList *gIter = rsc->parent->children;
161 
162  for (; gIter != NULL; gIter = gIter->next) {
163  pe_resource_t *child = (pe_resource_t *) gIter->data;
164 
167  }
168  }
169  break;
170  default: // recovery_stop_start, recovery_stop_unexpected
171  /* The scheduler will do the right thing because the relevant
172  * variables and flags are set when unpacking the history.
173  */
174  break;
175  }
176  crm_debug("%s is active on multiple nodes including %s: %s",
177  rsc->id, pe__node_name(node),
178  recovery2text(rsc->recovery_type));
179 
180  } else {
181  pe_rsc_trace(rsc, "Resource %s is active on %s",
182  rsc->id, pe__node_name(node));
183  }
184 
185  if (rsc->parent != NULL) {
186  native_add_running(rsc->parent, node, data_set, FALSE);
187  }
188 }
189 
190 static void
191 recursive_clear_unique(pe_resource_t *rsc, gpointer user_data)
192 {
195  g_list_foreach(rsc->children, (GFunc) recursive_clear_unique, NULL);
196 }
197 
198 gboolean
200 {
202  const char *standard = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
203  uint32_t ra_caps = pcmk_get_ra_caps(standard);
204 
205  pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
206 
207  // 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 descendants 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, pe__node_name(node));
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(pe__const_top_resource(rsc, false))) {
277  match = false;
278 
279  } else if (!strcmp(id, rsc->id) || pcmk__str_eq(id, rid, pcmk__str_none)) {
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  if (!rsc_is_on_node(rsc, on_node, flags)) {
298  match = false;
299  }
300  }
301 
302  if (match) {
303  return rsc;
304  }
305 
306  for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
307  pe_resource_t *child = (pe_resource_t *) gIter->data;
308 
309  result = rsc->fns->find_rsc(child, id, on_node, flags);
310  if (result) {
311  return result;
312  }
313  }
314  return NULL;
315 }
316 
317 // create is ignored
318 char *
319 native_parameter(pe_resource_t * rsc, pe_node_t * node, gboolean create, const char *name,
321 {
322  char *value_copy = NULL;
323  const char *value = NULL;
324  GHashTable *params = NULL;
325 
326  CRM_CHECK(rsc != NULL, return NULL);
327  CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
328 
329  pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
330  params = pe_rsc_params(rsc, node, data_set);
331  value = g_hash_table_lookup(params, name);
332  if (value == NULL) {
333  /* try meta attributes instead */
334  value = g_hash_table_lookup(rsc->meta, name);
335  }
336  pcmk__str_update(&value_copy, value);
337  return value_copy;
338 }
339 
340 gboolean
341 native_active(pe_resource_t * rsc, gboolean all)
342 {
343  for (GList *gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
344  pe_node_t *a_node = (pe_node_t *) gIter->data;
345 
346  if (a_node->details->unclean) {
347  pe_rsc_trace(rsc, "Resource %s: %s is unclean",
348  rsc->id, pe__node_name(a_node));
349  return TRUE;
350  } else if (a_node->details->online == FALSE && pcmk_is_set(rsc->flags, pe_rsc_managed)) {
351  pe_rsc_trace(rsc, "Resource %s: %s is offline",
352  rsc->id, pe__node_name(a_node));
353  } else {
354  pe_rsc_trace(rsc, "Resource %s active on %s",
355  rsc->id, pe__node_name(a_node));
356  return TRUE;
357  }
358  }
359  return FALSE;
360 }
361 
362 struct print_data_s {
363  long options;
364  void *print_data;
365 };
366 
367 static const char *
368 native_pending_state(const pe_resource_t *rsc)
369 {
370  const char *pending_state = NULL;
371 
372  if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_START, pcmk__str_casei)) {
373  pending_state = "Starting";
374 
375  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_STOP, pcmk__str_casei)) {
376  pending_state = "Stopping";
377 
378  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_MIGRATE, pcmk__str_casei)) {
379  pending_state = "Migrating";
380 
381  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_MIGRATED, pcmk__str_casei)) {
382  /* Work might be done in here. */
383  pending_state = "Migrating";
384 
385  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_PROMOTE, pcmk__str_casei)) {
386  pending_state = "Promoting";
387 
388  } else if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_DEMOTE, pcmk__str_casei)) {
389  pending_state = "Demoting";
390  }
391 
392  return pending_state;
393 }
394 
395 static const char *
396 native_pending_task(const pe_resource_t *rsc)
397 {
398  const char *pending_task = NULL;
399 
400  if (pcmk__str_eq(rsc->pending_task, CRMD_ACTION_STATUS, pcmk__str_casei)) {
401  pending_task = "Monitoring";
402 
403  /* Pending probes are not printed, even if pending
404  * operations are requested. If someone ever requests that
405  * behavior, uncomment this and the corresponding part of
406  * unpack.c:unpack_rsc_op().
407  */
408  /*
409  } else if (pcmk__str_eq(rsc->pending_task, "probe", pcmk__str_casei)) {
410  pending_task = "Checking";
411  */
412  }
413 
414  return pending_task;
415 }
416 
417 static enum rsc_role_e
418 native_displayable_role(const pe_resource_t *rsc)
419 {
420  enum rsc_role_e role = rsc->role;
421 
422  if ((role == RSC_ROLE_STARTED)
423  && pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
425 
426  role = RSC_ROLE_UNPROMOTED;
427  }
428  return role;
429 }
430 
431 static const char *
432 native_displayable_state(const pe_resource_t *rsc, bool print_pending)
433 {
434  const char *rsc_state = NULL;
435 
436  if (print_pending) {
437  rsc_state = native_pending_state(rsc);
438  }
439  if (rsc_state == NULL) {
440  rsc_state = role2text(native_displayable_role(rsc));
441  }
442  return rsc_state;
443 }
444 
449 static void
450 native_print_xml(pe_resource_t *rsc, const char *pre_text, long options,
451  void *print_data)
452 {
453  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
454  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
455  const char *rsc_state = native_displayable_state(rsc, pcmk_is_set(options, pe_print_pending));
456  const char *target_role = NULL;
457 
458  /* resource information. */
459  status_print("%s<resource ", pre_text);
460  status_print(XML_ATTR_ID "=\"%s\" ", rsc_printable_id(rsc));
461  status_print("resource_agent=\"%s%s%s:%s\" ", class,
462  ((prov == NULL)? "" : PROVIDER_SEP),
463  ((prov == NULL)? "" : prov),
465 
466  status_print("role=\"%s\" ", rsc_state);
467  if (rsc->meta) {
468  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
469  }
470  if (target_role) {
471  status_print("target_role=\"%s\" ", target_role);
472  }
473  status_print("active=\"%s\" ", pcmk__btoa(rsc->fns->active(rsc, TRUE)));
474  status_print("orphaned=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_orphan));
475  status_print("blocked=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_block));
476  status_print("managed=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_managed));
477  status_print("failed=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_failed));
478  status_print("failure_ignored=\"%s\" ",
479  pe__rsc_bool_str(rsc, pe_rsc_failure_ignored));
480  status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
481 
482  if (options & pe_print_pending) {
483  const char *pending_task = native_pending_task(rsc);
484 
485  if (pending_task) {
486  status_print("pending=\"%s\" ", pending_task);
487  }
488  }
489 
490  /* print out the nodes this resource is running on */
491  if (options & pe_print_rsconly) {
492  status_print("/>\n");
493  /* do nothing */
494  } else if (rsc->running_on != NULL) {
495  GList *gIter = rsc->running_on;
496 
497  status_print(">\n");
498  for (; gIter != NULL; gIter = gIter->next) {
499  pe_node_t *node = (pe_node_t *) gIter->data;
500 
501  status_print("%s <node name=\"%s\" " XML_ATTR_ID "=\"%s\" "
502  "cached=\"%s\"/>\n",
503  pre_text, pcmk__s(node->details->uname, ""),
504  node->details->id, pcmk__btoa(!node->details->online));
505  }
506  status_print("%s</resource>\n", pre_text);
507  } else {
508  status_print("/>\n");
509  }
510 }
511 
512 // Append a flag to resource description string's flags list
513 static bool
514 add_output_flag(GString *s, const char *flag_desc, bool have_flags)
515 {
516  g_string_append(s, (have_flags? ", " : " ("));
517  g_string_append(s, flag_desc);
518  return true;
519 }
520 
521 // Append a node name to resource description string's node list
522 static bool
523 add_output_node(GString *s, const char *node, bool have_nodes)
524 {
525  g_string_append(s, (have_nodes? " " : " [ "));
526  g_string_append(s, node);
527  return true;
528 }
529 
544 gchar *
546  const pe_node_t *node, uint32_t show_opts,
547  const char *target_role, bool show_nodes)
548 {
549  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
550  const char *provider = NULL;
551  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
552  GString *outstr = NULL;
553  bool have_flags = false;
554 
555  if (rsc->variant != pe_native) {
556  return NULL;
557  }
558 
559  CRM_CHECK(name != NULL, name = "unknown");
560  CRM_CHECK(kind != NULL, kind = "unknown");
561  CRM_CHECK(class != NULL, class = "unknown");
562 
564  provider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
565  }
566 
567  if ((node == NULL) && (rsc->lock_node != NULL)) {
568  node = rsc->lock_node;
569  }
570  if (pcmk_any_flags_set(show_opts, pcmk_show_rsc_only)
571  || pcmk__list_of_multiple(rsc->running_on)) {
572  node = NULL;
573  }
574 
575  outstr = g_string_sized_new(128);
576 
577  // Resource name and agent
578  pcmk__g_strcat(outstr,
579  name, "\t(", class, ((provider == NULL)? "" : PROVIDER_SEP),
580  pcmk__s(provider, ""), ":", kind, "):\t", NULL);
581 
582  // State on node
583  if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
584  g_string_append(outstr, " ORPHANED");
585  }
586  if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
587  enum rsc_role_e role = native_displayable_role(rsc);
588 
589  g_string_append(outstr, " FAILED");
590  if (role > RSC_ROLE_UNPROMOTED) {
591  pcmk__add_word(&outstr, 0, role2text(role));
592  }
593  } else {
594  bool show_pending = pcmk_is_set(show_opts, pcmk_show_pending);
595 
596  pcmk__add_word(&outstr, 0, native_displayable_state(rsc, show_pending));
597  }
598  if (node) {
599  pcmk__add_word(&outstr, 0, pe__node_name(node));
600  }
601 
602  // Failed probe operation
603  if (native_displayable_role(rsc) == RSC_ROLE_STOPPED) {
604  xmlNode *probe_op = pe__failed_probe_for_rsc(rsc, node ? node->details->uname : NULL);
605  if (probe_op != NULL) {
606  int rc;
607 
609  pcmk__g_strcat(outstr, " (", services_ocf_exitcode_str(rc), ") ",
610  NULL);
611  }
612  }
613 
614  // Flags, as: (<flag> [...])
615  if (node && !(node->details->online) && node->details->unclean) {
616  have_flags = add_output_flag(outstr, "UNCLEAN", have_flags);
617  }
618  if (node && (node == rsc->lock_node)) {
619  have_flags = add_output_flag(outstr, "LOCKED", have_flags);
620  }
621  if (pcmk_is_set(show_opts, pcmk_show_pending)) {
622  const char *pending_task = native_pending_task(rsc);
623 
624  if (pending_task) {
625  have_flags = add_output_flag(outstr, pending_task, have_flags);
626  }
627  }
628  if (target_role) {
629  enum rsc_role_e target_role_e = text2role(target_role);
630 
631  /* Only show target role if it limits our abilities (i.e. ignore
632  * Started, as it is the default anyways, and doesn't prevent the
633  * resource from becoming promoted).
634  */
635  if (target_role_e == RSC_ROLE_STOPPED) {
636  have_flags = add_output_flag(outstr, "disabled", have_flags);
637 
638  } else if (pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
640  && target_role_e == RSC_ROLE_UNPROMOTED) {
641  have_flags = add_output_flag(outstr, "target-role:", have_flags);
642  g_string_append(outstr, target_role);
643  }
644  }
645 
646  // Blocked or maintenance implies unmanaged
647  if (pcmk_any_flags_set(rsc->flags, pe_rsc_block|pe_rsc_maintenance)) {
648  if (pcmk_is_set(rsc->flags, pe_rsc_block)) {
649  have_flags = add_output_flag(outstr, "blocked", have_flags);
650 
651  } else if (pcmk_is_set(rsc->flags, pe_rsc_maintenance)) {
652  have_flags = add_output_flag(outstr, "maintenance", have_flags);
653  }
654  } else if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
655  have_flags = add_output_flag(outstr, "unmanaged", have_flags);
656  }
657 
658  if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
659  have_flags = add_output_flag(outstr, "failure ignored", have_flags);
660  }
661 
662 
663  if (have_flags) {
664  g_string_append_c(outstr, ')');
665  }
666 
667  // User-supplied description
668  if (pcmk_any_flags_set(show_opts, pcmk_show_rsc_only|pcmk_show_description)
669  || pcmk__list_of_multiple(rsc->running_on)) {
670  const char *desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
671 
672  if (desc) {
673  g_string_append(outstr, " (");
674  g_string_append(outstr, desc);
675  g_string_append(outstr, ")");
676 
677  }
678  }
679 
680  if (show_nodes && !pcmk_is_set(show_opts, pcmk_show_rsc_only)
681  && pcmk__list_of_multiple(rsc->running_on)) {
682  bool have_nodes = false;
683 
684  for (GList *iter = rsc->running_on; iter != NULL; iter = iter->next) {
685  pe_node_t *n = (pe_node_t *) iter->data;
686 
687  have_nodes = add_output_node(outstr, n->details->uname, have_nodes);
688  }
689  if (have_nodes) {
690  g_string_append(outstr, " ]");
691  }
692  }
693 
694  return g_string_free(outstr, FALSE);
695 }
696 
697 int
699  const char *name, const pe_node_t *node,
700  uint32_t show_opts)
701 {
702  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
703  const char *target_role = NULL;
704 
705  xmlNodePtr list_node = NULL;
706  const char *cl = NULL;
707 
708  CRM_ASSERT(rsc->variant == pe_native);
709  CRM_ASSERT(kind != NULL);
710 
711  if (rsc->meta) {
712  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
713 
714  if (crm_is_true(is_internal)
715  && !pcmk_is_set(show_opts, pcmk_show_implicit_rscs)) {
716 
717  crm_trace("skipping print of internal resource %s", rsc->id);
718  return pcmk_rc_no_output;
719  }
720  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
721  }
722 
723  if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
724  cl = "rsc-managed";
725 
726  } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
727  cl = "rsc-failed";
728 
729  } else if (rsc->variant == pe_native && (rsc->running_on == NULL)) {
730  cl = "rsc-failed";
731 
732  } else if (pcmk__list_of_multiple(rsc->running_on)) {
733  cl = "rsc-multiple";
734 
735  } else if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
736  cl = "rsc-failure-ignored";
737 
738  } else {
739  cl = "rsc-ok";
740  }
741 
742  {
743  gchar *s = pcmk__native_output_string(rsc, name, node, show_opts,
744  target_role, true);
745 
746  list_node = pcmk__output_create_html_node(out, "li", NULL, NULL, NULL);
747  pcmk_create_html_node(list_node, "span", NULL, cl, s);
748  g_free(s);
749  }
750 
751  return pcmk_rc_ok;
752 }
753 
754 int
756  const char *name, const pe_node_t *node,
757  uint32_t show_opts)
758 {
759  const char *target_role = NULL;
760 
761  CRM_ASSERT(rsc->variant == pe_native);
762 
763  if (rsc->meta) {
764  const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
765 
766  if (crm_is_true(is_internal)
767  && !pcmk_is_set(show_opts, pcmk_show_implicit_rscs)) {
768 
769  crm_trace("skipping print of internal resource %s", rsc->id);
770  return pcmk_rc_no_output;
771  }
772  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
773  }
774 
775  {
776  gchar *s = pcmk__native_output_string(rsc, name, node, show_opts,
777  target_role, true);
778 
779  out->list_item(out, NULL, "%s", s);
780  g_free(s);
781  }
782 
783  return pcmk_rc_ok;
784 }
785 
790 void
791 common_print(pe_resource_t *rsc, const char *pre_text, const char *name,
792  const pe_node_t *node, long options, void *print_data)
793 {
794  const char *target_role = NULL;
795 
796  CRM_ASSERT(rsc->variant == pe_native);
797 
798  if (rsc->meta) {
799  const char *is_internal = g_hash_table_lookup(rsc->meta,
801 
802  if (crm_is_true(is_internal)
803  && !pcmk_is_set(options, pe_print_implicit)) {
804 
805  crm_trace("skipping print of internal resource %s", rsc->id);
806  return;
807  }
808  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
809  }
810 
811  if (options & pe_print_xml) {
812  native_print_xml(rsc, pre_text, options, print_data);
813  return;
814  }
815 
816  if ((pre_text == NULL) && (options & pe_print_printf)) {
817  pre_text = " ";
818  }
819 
820  if (options & pe_print_html) {
821  if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
822  status_print("<font color=\"yellow\">");
823 
824  } else if (pcmk_is_set(rsc->flags, pe_rsc_failed)) {
825  status_print("<font color=\"red\">");
826 
827  } else if (rsc->running_on == NULL) {
828  status_print("<font color=\"red\">");
829 
830  } else if (pcmk__list_of_multiple(rsc->running_on)) {
831  status_print("<font color=\"orange\">");
832 
833  } else if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
834  status_print("<font color=\"yellow\">");
835 
836  } else {
837  status_print("<font color=\"green\">");
838  }
839  }
840 
841  {
842  gchar *resource_s = pcmk__native_output_string(rsc, name, node, options,
843  target_role, false);
844  status_print("%s%s", (pre_text? pre_text : ""), resource_s);
845  g_free(resource_s);
846  }
847 
848  if (pcmk_is_set(options, pe_print_html)) {
849  status_print(" </font> ");
850  }
851 
852  if (!pcmk_is_set(options, pe_print_rsconly)
853  && pcmk__list_of_multiple(rsc->running_on)) {
854 
855  GList *gIter = rsc->running_on;
856  int counter = 0;
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  for (; gIter != NULL; gIter = gIter->next) {
866  pe_node_t *n = (pe_node_t *) gIter->data;
867 
868  counter++;
869 
870  if (options & pe_print_html) {
871  status_print("<li>\n%s", pe__node_name(n));
872 
873  } else if ((options & pe_print_printf)
874  || (options & pe_print_ncurses)) {
875  status_print(" %s", pe__node_name(n));
876 
877  } else if ((options & pe_print_log)) {
878  status_print("\t%d : %s", counter, pe__node_name(n));
879 
880  } else {
881  status_print("%s", pe__node_name(n));
882  }
883  if (options & pe_print_html) {
884  status_print("</li>\n");
885 
886  }
887  }
888 
889  if (options & pe_print_html) {
890  status_print("</ul>\n");
891  } else if ((options & pe_print_printf)
892  || (options & pe_print_ncurses)) {
893  status_print(" ]");
894  }
895  }
896 
897  if (options & pe_print_html) {
898  status_print("<br/>\n");
899  } else if (options & pe_print_suppres_nl) {
900  /* nothing */
901  } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
902  status_print("\n");
903  }
904 }
905 
910 void
911 native_print(pe_resource_t *rsc, const char *pre_text, long options,
912  void *print_data)
913 {
914  const pe_node_t *node = NULL;
915 
916  CRM_ASSERT(rsc->variant == pe_native);
917  if (options & pe_print_xml) {
918  native_print_xml(rsc, pre_text, options, print_data);
919  return;
920  }
921 
922  node = pe__current_node(rsc);
923 
924  if (node == NULL) {
925  // This is set only if a non-probe action is pending on this node
926  node = rsc->pending_node;
927  }
928 
929  common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
930 }
931 
932 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pe_resource_t *", "GList *", "GList *")
933 int
934 pe__resource_xml(pcmk__output_t *out, va_list args)
935 {
936  uint32_t show_opts = va_arg(args, uint32_t);
937  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
938  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
939  GList *only_rsc = va_arg(args, GList *);
940 
941  bool print_pending = pcmk_is_set(show_opts, pcmk_show_pending);
942  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
943  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
944  const char *rsc_state = native_displayable_state(rsc, print_pending);
945 
946  const char *desc = NULL;
947  char ra_name[LINE_MAX];
948  char *nodes_running_on = NULL;
949  const char *lock_node_name = NULL;
950  int rc = pcmk_rc_no_output;
951  const char *target_role = NULL;
952 
953  desc = pe__resource_description(rsc, show_opts);
954 
955  if (rsc->meta != NULL) {
956  target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
957  }
958 
959  CRM_ASSERT(rsc->variant == pe_native);
960 
961  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
962  return pcmk_rc_no_output;
963  }
964 
965  /* resource information. */
966  snprintf(ra_name, LINE_MAX, "%s%s%s:%s", class,
967  ((prov == NULL)? "" : PROVIDER_SEP), ((prov == NULL)? "" : prov),
968  crm_element_value(rsc->xml, XML_ATTR_TYPE));
969 
970  nodes_running_on = pcmk__itoa(g_list_length(rsc->running_on));
971 
972  if (rsc->lock_node != NULL) {
973  lock_node_name = rsc->lock_node->details->uname;
974  }
975 
976  rc = pe__name_and_nvpairs_xml(out, true, "resource", 15,
977  "id", rsc_printable_id(rsc),
978  "resource_agent", ra_name,
979  "role", rsc_state,
980  "target_role", target_role,
981  "active", pcmk__btoa(rsc->fns->active(rsc, TRUE)),
982  "orphaned", pe__rsc_bool_str(rsc, pe_rsc_orphan),
983  "blocked", pe__rsc_bool_str(rsc, pe_rsc_block),
984  "maintenance", pe__rsc_bool_str(rsc, pe_rsc_maintenance),
985  "managed", pe__rsc_bool_str(rsc, pe_rsc_managed),
986  "failed", pe__rsc_bool_str(rsc, pe_rsc_failed),
987  "failure_ignored", pe__rsc_bool_str(rsc, pe_rsc_failure_ignored),
988  "nodes_running_on", nodes_running_on,
989  "pending", (print_pending? native_pending_task(rsc) : NULL),
990  "locked_to", lock_node_name,
991  "description", desc);
992  free(nodes_running_on);
993 
994  CRM_ASSERT(rc == pcmk_rc_ok);
995 
996  if (rsc->running_on != NULL) {
997  GList *gIter = rsc->running_on;
998 
999  for (; gIter != NULL; gIter = gIter->next) {
1000  pe_node_t *node = (pe_node_t *) gIter->data;
1001 
1002  rc = pe__name_and_nvpairs_xml(out, false, "node", 3,
1003  "name", node->details->uname,
1004  "id", node->details->id,
1005  "cached", pcmk__btoa(node->details->online));
1006  CRM_ASSERT(rc == pcmk_rc_ok);
1007  }
1008  }
1009 
1011  return rc;
1012 }
1013 
1014 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pe_resource_t *", "GList *", "GList *")
1015 int
1017 {
1018  uint32_t show_opts = va_arg(args, uint32_t);
1019  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1020  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
1021  GList *only_rsc = va_arg(args, GList *);
1022 
1023  const pe_node_t *node = pe__current_node(rsc);
1024 
1025  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1026  return pcmk_rc_no_output;
1027  }
1028 
1029  CRM_ASSERT(rsc->variant == pe_native);
1030 
1031  if (node == NULL) {
1032  // This is set only if a non-probe action is pending on this node
1033  node = rsc->pending_node;
1034  }
1035  return pe__common_output_html(out, rsc, rsc_printable_id(rsc), node, show_opts);
1036 }
1037 
1038 PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pe_resource_t *", "GList *", "GList *")
1039 int
1041 {
1042  uint32_t show_opts = va_arg(args, uint32_t);
1043  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1044  GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
1045  GList *only_rsc = va_arg(args, GList *);
1046 
1047  const pe_node_t *node = pe__current_node(rsc);
1048 
1049  CRM_ASSERT(rsc->variant == pe_native);
1050 
1051  if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1052  return pcmk_rc_no_output;
1053  }
1054 
1055  if (node == NULL) {
1056  // This is set only if a non-probe action is pending on this node
1057  node = rsc->pending_node;
1058  }
1059  return pe__common_output_text(out, rsc, rsc_printable_id(rsc), node, show_opts);
1060 }
1061 
1062 void
1064 {
1065  pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
1066  common_free(rsc);
1067 }
1068 
1069 enum rsc_role_e
1070 native_resource_state(const pe_resource_t * rsc, gboolean current)
1071 {
1072  enum rsc_role_e role = rsc->next_role;
1073 
1074  if (current) {
1075  role = rsc->role;
1076  }
1077  pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
1078  return role;
1079 }
1080 
1092 pe_node_t *
1093 native_location(const pe_resource_t *rsc, GList **list, int current)
1094 {
1095  pe_node_t *one = NULL;
1096  GList *result = NULL;
1097 
1098  if (rsc->children) {
1099  GList *gIter = rsc->children;
1100 
1101  for (; gIter != NULL; gIter = gIter->next) {
1102  pe_resource_t *child = (pe_resource_t *) gIter->data;
1103 
1104  child->fns->location(child, &result, current);
1105  }
1106 
1107  } else if (current) {
1108 
1109  if (rsc->running_on) {
1110  result = g_list_copy(rsc->running_on);
1111  }
1112  if ((current == 2) && rsc->pending_node
1113  && !pe_find_node_id(result, rsc->pending_node->details->id)) {
1114  result = g_list_append(result, rsc->pending_node);
1115  }
1116 
1117  } else if (current == FALSE && rsc->allocated_to) {
1118  result = g_list_append(NULL, rsc->allocated_to);
1119  }
1120 
1121  if (result && (result->next == NULL)) {
1122  one = result->data;
1123  }
1124 
1125  if (list) {
1126  GList *gIter = result;
1127 
1128  for (; gIter != NULL; gIter = gIter->next) {
1129  pe_node_t *node = (pe_node_t *) gIter->data;
1130 
1131  if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
1132  *list = g_list_append(*list, node);
1133  }
1134  }
1135  }
1136 
1137  g_list_free(result);
1138  return one;
1139 }
1140 
1141 static void
1142 get_rscs_brief(GList *rsc_list, GHashTable * rsc_table, GHashTable * active_table)
1143 {
1144  GList *gIter = rsc_list;
1145 
1146  for (; gIter != NULL; gIter = gIter->next) {
1147  pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1148 
1149  const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1150  const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
1151 
1152  int offset = 0;
1153  char buffer[LINE_MAX];
1154 
1155  int *rsc_counter = NULL;
1156  int *active_counter = NULL;
1157 
1158  if (rsc->variant != pe_native) {
1159  continue;
1160  }
1161 
1162  offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
1164  const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
1165 
1166  if (prov != NULL) {
1167  offset += snprintf(buffer + offset, LINE_MAX - offset,
1168  PROVIDER_SEP "%s", prov);
1169  }
1170  }
1171  offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
1172  CRM_LOG_ASSERT(offset > 0);
1173 
1174  if (rsc_table) {
1175  rsc_counter = g_hash_table_lookup(rsc_table, buffer);
1176  if (rsc_counter == NULL) {
1177  rsc_counter = calloc(1, sizeof(int));
1178  *rsc_counter = 0;
1179  g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
1180  }
1181  (*rsc_counter)++;
1182  }
1183 
1184  if (active_table) {
1185  GList *gIter2 = rsc->running_on;
1186 
1187  for (; gIter2 != NULL; gIter2 = gIter2->next) {
1188  pe_node_t *node = (pe_node_t *) gIter2->data;
1189  GHashTable *node_table = NULL;
1190 
1191  if (node->details->unclean == FALSE && node->details->online == FALSE &&
1192  pcmk_is_set(rsc->flags, pe_rsc_managed)) {
1193  continue;
1194  }
1195 
1196  node_table = g_hash_table_lookup(active_table, node->details->uname);
1197  if (node_table == NULL) {
1198  node_table = pcmk__strkey_table(free, free);
1199  g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
1200  }
1201 
1202  active_counter = g_hash_table_lookup(node_table, buffer);
1203  if (active_counter == NULL) {
1204  active_counter = calloc(1, sizeof(int));
1205  *active_counter = 0;
1206  g_hash_table_insert(node_table, strdup(buffer), active_counter);
1207  }
1208  (*active_counter)++;
1209  }
1210  }
1211  }
1212 }
1213 
1214 static void
1215 destroy_node_table(gpointer data)
1216 {
1217  GHashTable *node_table = data;
1218 
1219  if (node_table) {
1220  g_hash_table_destroy(node_table);
1221  }
1222 }
1223 
1228 void
1229 print_rscs_brief(GList *rsc_list, const char *pre_text, long options,
1230  void *print_data, gboolean print_all)
1231 {
1232  GHashTable *rsc_table = pcmk__strkey_table(free, free);
1233  GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1234  GHashTableIter hash_iter;
1235  char *type = NULL;
1236  int *rsc_counter = NULL;
1237 
1238  get_rscs_brief(rsc_list, rsc_table, active_table);
1239 
1240  g_hash_table_iter_init(&hash_iter, rsc_table);
1241  while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
1242  GHashTableIter hash_iter2;
1243  char *node_name = NULL;
1244  GHashTable *node_table = NULL;
1245  int active_counter_all = 0;
1246 
1247  g_hash_table_iter_init(&hash_iter2, active_table);
1248  while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
1249  int *active_counter = g_hash_table_lookup(node_table, type);
1250 
1251  if (active_counter == NULL || *active_counter == 0) {
1252  continue;
1253 
1254  } else {
1255  active_counter_all += *active_counter;
1256  }
1257 
1258  if (options & pe_print_rsconly) {
1259  node_name = NULL;
1260  }
1261 
1262  if (options & pe_print_html) {
1263  status_print("<li>\n");
1264  }
1265 
1266  if (print_all) {
1267  status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1268  active_counter ? *active_counter : 0,
1269  rsc_counter ? *rsc_counter : 0, type,
1270  active_counter && (*active_counter > 0) && node_name ? node_name : "");
1271  } else {
1272  status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1273  active_counter ? *active_counter : 0, type,
1274  active_counter && (*active_counter > 0) && node_name ? node_name : "");
1275  }
1276 
1277  if (options & pe_print_html) {
1278  status_print("</li>\n");
1279  }
1280  }
1281 
1282  if (print_all && active_counter_all == 0) {
1283  if (options & pe_print_html) {
1284  status_print("<li>\n");
1285  }
1286 
1287  status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
1288  active_counter_all,
1289  rsc_counter ? *rsc_counter : 0, type);
1290 
1291  if (options & pe_print_html) {
1292  status_print("</li>\n");
1293  }
1294  }
1295  }
1296 
1297  if (rsc_table) {
1298  g_hash_table_destroy(rsc_table);
1299  rsc_table = NULL;
1300  }
1301  if (active_table) {
1302  g_hash_table_destroy(active_table);
1303  active_table = NULL;
1304  }
1305 }
1306 
1307 int
1308 pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, uint32_t show_opts)
1309 {
1310  GHashTable *rsc_table = pcmk__strkey_table(free, free);
1311  GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1312  GList *sorted_rscs;
1313  int rc = pcmk_rc_no_output;
1314 
1315  get_rscs_brief(rsc_list, rsc_table, active_table);
1316 
1317  /* Make a list of the rsc_table keys so that it can be sorted. This is to make sure
1318  * output order stays consistent between systems.
1319  */
1320  sorted_rscs = g_hash_table_get_keys(rsc_table);
1321  sorted_rscs = g_list_sort(sorted_rscs, (GCompareFunc) strcmp);
1322 
1323  for (GList *gIter = sorted_rscs; gIter; gIter = gIter->next) {
1324  char *type = (char *) gIter->data;
1325  int *rsc_counter = g_hash_table_lookup(rsc_table, type);
1326 
1327  GList *sorted_nodes = NULL;
1328  int active_counter_all = 0;
1329 
1330  /* Also make a list of the active_table keys so it can be sorted. If there's
1331  * more than one instance of a type of resource running, we need the nodes to
1332  * be sorted to make sure output order stays consistent between systems.
1333  */
1334  sorted_nodes = g_hash_table_get_keys(active_table);
1335  sorted_nodes = g_list_sort(sorted_nodes, (GCompareFunc) pcmk__numeric_strcasecmp);
1336 
1337  for (GList *gIter2 = sorted_nodes; gIter2; gIter2 = gIter2->next) {
1338  char *node_name = (char *) gIter2->data;
1339  GHashTable *node_table = g_hash_table_lookup(active_table, node_name);
1340  int *active_counter = NULL;
1341 
1342  if (node_table == NULL) {
1343  continue;
1344  }
1345 
1346  active_counter = g_hash_table_lookup(node_table, type);
1347 
1348  if (active_counter == NULL || *active_counter == 0) {
1349  continue;
1350 
1351  } else {
1352  active_counter_all += *active_counter;
1353  }
1354 
1355  if (pcmk_is_set(show_opts, pcmk_show_rsc_only)) {
1356  node_name = NULL;
1357  }
1358 
1359  if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs)) {
1360  out->list_item(out, NULL, "%d/%d\t(%s):\tActive %s",
1361  *active_counter,
1362  rsc_counter ? *rsc_counter : 0, type,
1363  (*active_counter > 0) && node_name ? node_name : "");
1364  } else {
1365  out->list_item(out, NULL, "%d\t(%s):\tActive %s",
1366  *active_counter, type,
1367  (*active_counter > 0) && node_name ? node_name : "");
1368  }
1369 
1370  rc = pcmk_rc_ok;
1371  }
1372 
1373  if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs) && active_counter_all == 0) {
1374  out->list_item(out, NULL, "%d/%d\t(%s):\tActive",
1375  active_counter_all,
1376  rsc_counter ? *rsc_counter : 0, type);
1377  rc = pcmk_rc_ok;
1378  }
1379 
1380  if (sorted_nodes) {
1381  g_list_free(sorted_nodes);
1382  }
1383  }
1384 
1385  if (rsc_table) {
1386  g_hash_table_destroy(rsc_table);
1387  rsc_table = NULL;
1388  }
1389  if (active_table) {
1390  g_hash_table_destroy(active_table);
1391  active_table = NULL;
1392  }
1393  if (sorted_rscs) {
1394  g_list_free(sorted_rscs);
1395  }
1396 
1397  return rc;
1398 }
1399 
1400 gboolean
1401 pe__native_is_filtered(const pe_resource_t *rsc, GList *only_rsc,
1402  gboolean check_parent)
1403 {
1405  pcmk__str_in_list(rsc->id, only_rsc, pcmk__str_star_matches)) {
1406  return FALSE;
1407  } else if (check_parent && rsc->parent) {
1408  const pe_resource_t *up = pe__const_top_resource(rsc, true);
1409 
1410  return up->fns->is_filtered(up, only_rsc, FALSE);
1411  }
1412 
1413  return TRUE;
1414 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:235
#define CRMD_ACTION_MIGRATED
Definition: crm.h:172
gboolean native_active(pe_resource_t *rsc, gboolean all)
Definition: native.c:341
char data[0]
Definition: cpg.c:55
#define INFINITY
Definition: crm.h:99
Control output from tools.
gchar * pcmk__native_output_string(const pe_resource_t *rsc, const char *name, const pe_node_t *node, uint32_t show_opts, const char *target_role, bool show_nodes)
Definition: native.c:545
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:127
pe_resource_t * container
Definition: pe_types.h:412
const char * name
Definition: cib.c:24
#define XML_ATTR_TYPE
Definition: msg_xml.h:151
enum rsc_role_e role
Definition: pe_types.h:402
GList * children
Definition: pe_types.h:409
#define XML_BOOLEAN_FALSE
Definition: msg_xml.h:160
#define PROVIDER_SEP
Definition: native.c:25
gboolean native_unpack(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: native.c:199
int pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, uint32_t show_opts)
Definition: native.c:1308
enum rsc_role_e native_resource_state(const pe_resource_t *rsc, gboolean current)
Definition: native.c:1070
xmlNode * xml
Definition: pe_types.h:349
enum rsc_role_e next_role
Definition: pe_types.h:403
xmlNode * pcmk_create_html_node(xmlNode *parent, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: xml.c:714
pe_resource_t * remote_rsc
Definition: pe_types.h:253
void pe__force_anon(const char *standard, pe_resource_t *rsc, const char *rid, pe_working_set_t *data_set)
Definition: clone.c:209
GHashTable * meta
Definition: pe_types.h:405
match resource not running anywhere
Definition: pe_types.h:105
#define pe_rsc_unique
Definition: pe_types.h:278
resource_object_functions_t * fns
Definition: pe_types.h:358
#define CRMD_ACTION_PROMOTE
Definition: crm.h:180
const pe_resource_t * pe__const_top_resource(const pe_resource_t *rsc, bool include_bundle)
Definition: complex.c:947
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:219
int pe__resource_xml(pcmk__output_t *out, va_list args)
Definition: native.c:934
enum crm_ais_msg_types type
Definition: cpg.c:48
int pe__resource_text(pcmk__output_t *out, va_list args)
Definition: native.c:1040
void resource_location(pe_resource_t *rsc, const pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:398
#define resource_s
pe_node_t * allocated_to
Definition: pe_types.h:395
xmlNodePtr pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id, const char *class_name, const char *text)
Definition: output_html.c:434
const char * pe__resource_description(const pe_resource_t *rsc, uint32_t show_opts)
Definition: pe_output.c:19
char * pending_task
Definition: pe_types.h:371
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:77
GList * nodes
Definition: pe_types.h:180
void print_rscs_brief(GList *rsc_list, const char *pre_text, long options, void *print_data, gboolean print_all)
Definition: native.c:1229
#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:319
const char * role2text(enum rsc_role_e role)
Definition: common.c:450
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:292
#define crm_debug(fmt, args...)
Definition: logging.h:382
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:922
#define XML_ATTR_ID
Definition: msg_xml.h:147
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:496
#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:568
match only clone instances
Definition: pe_types.h:103
#define crm_trace(fmt, args...)
Definition: logging.h:383
void native_print(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: native.c:911
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1217
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
void native_free(pe_resource_t *rsc)
Definition: native.c:1063
struct pe_node_shared_s * details
Definition: pe_types.h:268
enum rsc_recovery_type recovery_type
Definition: pe_types.h:361
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:283
void common_free(pe_resource_t *rsc)
Definition: complex.c:964
unsigned long long flags
Definition: pe_types.h:373
const char * uname
Definition: pe_types.h:232
#define pe_rsc_promotable
Definition: pe_types.h:280
pe_working_set_t * data_set
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
char * clone_name
Definition: pe_types.h:348
#define XML_ATTR_DESC
Definition: msg_xml.h:146
GHashTable * pe__node_list2table(const GList *list)
Definition: utils.c:156
pe_node_t * native_location(const pe_resource_t *rsc, GList **list, int current)
Definition: native.c:1093
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:249
match base name of any clone instance
Definition: pe_types.h:106
enum rsc_role_e text2role(const char *role)
Definition: common.c:479
enum pe_obj_types variant
Definition: pe_types.h:356
gboolean(* is_filtered)(const pe_resource_t *, GList *, gboolean)
Definition: pe_types.h:58
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:518
void common_print(pe_resource_t *rsc, const char *pre_text, const char *name, const pe_node_t *node, long options, void *print_data)
Definition: native.c:791
const char * id
Definition: pe_types.h:231
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:250
GList * running_rsc
Definition: pe_types.h:254
match resource ID or LRM history ID
Definition: pe_types.h:101
gboolean pe__native_is_filtered(const pe_resource_t *rsc, GList *only_rsc, gboolean check_parent)
Definition: native.c:1401
pe_node_t * pe_find_node_id(const GList *node_list, const char *id)
Find a node by ID in a list of nodes.
Definition: status.c:448
const char * rsc_printable_id(const pe_resource_t *rsc)
Definition: utils.c:583
Cluster status and scheduling.
int pe__common_output_html(pcmk__output_t *out, const pe_resource_t *rsc, const char *name, const pe_node_t *node, uint32_t show_opts)
Definition: native.c:698
pe_node_t * pending_node
Definition: pe_types.h:416
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
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:500
#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
int pe__common_output_text(pcmk__output_t *out, const pe_resource_t *rsc, const char *name, const pe_node_t *node, uint32_t show_opts)
Definition: native.c:755
#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:436
#define CRMD_ACTION_MIGRATE
Definition: crm.h:171
#define XML_RSC_ATTR_INTERNAL_RSC
Definition: msg_xml.h:258
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:83
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition: strings.c:1023
rsc_role_e
Possible roles that a resource can be in.
Definition: common.h:92
GList * running_on
Definition: pe_types.h:398
#define pe_rsc_block
Definition: pe_types.h:274
gboolean maintenance
Definition: pe_types.h:245
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:326
#define pe_rsc_maintenance
Definition: pe_types.h:308
#define pe_rsc_failure_ignored
Definition: pe_types.h:306
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
Ignored.
Definition: common.h:127
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:50
int pe__resource_html(pcmk__output_t *out, va_list args)
Definition: native.c:1016
pe_node_t * pe__find_active_requires(const pe_resource_t *rsc, unsigned int *count)
Definition: complex.c:1121
#define ID(x)
Definition: msg_xml.h:480
#define pe_err(fmt...)
Definition: internal.h:52
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:240
#define pe_rsc_managed
Definition: pe_types.h:273
#define pe_rsc_orphan
Definition: pe_types.h:272
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:236
uint64_t flags
Definition: remote.c:215
match resource active on specified node
Definition: pe_types.h:104
pe_resource_t * parent
Definition: pe_types.h:354
xmlNode * pe__failed_probe_for_rsc(const pe_resource_t *rsc, const char *name)
Definition: utils.c:896
gboolean(* active)(pe_resource_t *, gboolean)
Definition: pe_types.h:53
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:48
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:282
char * id
Definition: pe_types.h:347
GHashTable * allowed_nodes
Definition: pe_types.h:400
match base name of anonymous clone instances
Definition: pe_types.h:102
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
Definition: strings.c:888
#define CRMD_ACTION_STATUS
Definition: crm.h:188