pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
native.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2024 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>
19#include <crm/common/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
32static bool
33is_multiply_active(const pcmk_resource_t *rsc)
34{
35 unsigned int count = 0;
36
37 if (pcmk__is_primitive(rsc)) {
38 pe__find_active_requires(rsc, &count);
39 }
40 return count > 1;
41}
42
43static void
44native_priority_to_node(pcmk_resource_t *rsc, pcmk_node_t *node,
45 gboolean failed)
46{
47 int priority = 0;
48
49 if ((rsc->priority == 0) || (failed == TRUE)) {
50 return;
51 }
52
53 if (rsc->role == pcmk_role_promoted) {
54 // Promoted instance takes base priority + 1
55 priority = rsc->priority + 1;
56
57 } else {
58 priority = rsc->priority;
59 }
60
61 node->details->priority += priority;
62 pcmk__rsc_trace(rsc, "%s now has priority %d with %s'%s' (priority: %d%s)",
63 pcmk__node_name(node), node->details->priority,
64 (rsc->role == pcmk_role_promoted)? "promoted " : "",
65 rsc->id, rsc->priority,
66 (rsc->role == pcmk_role_promoted)? " + 1" : "");
67
68 /* Priority of a resource running on a guest node is added to the cluster
69 * node as well. */
70 if (node->details->remote_rsc
71 && node->details->remote_rsc->container) {
72 GList *gIter = node->details->remote_rsc->container->running_on;
73
74 for (; gIter != NULL; gIter = gIter->next) {
75 pcmk_node_t *a_node = gIter->data;
76
77 a_node->details->priority += priority;
79 "%s now has priority %d with %s'%s' "
80 "(priority: %d%s) from guest node %s",
81 pcmk__node_name(a_node), a_node->details->priority,
82 (rsc->role == pcmk_role_promoted)? "promoted " : "",
83 rsc->id, rsc->priority,
84 (rsc->role == pcmk_role_promoted)? " + 1" : "",
85 pcmk__node_name(node));
86 }
87 }
88}
89
90void
92 pcmk_scheduler_t *scheduler, gboolean failed)
93{
94 GList *gIter = rsc->running_on;
95
96 CRM_CHECK(node != NULL, return);
97 for (; gIter != NULL; gIter = gIter->next) {
98 pcmk_node_t *a_node = (pcmk_node_t *) gIter->data;
99
100 CRM_CHECK(a_node != NULL, return);
101 if (pcmk__str_eq(a_node->details->id, node->details->id, pcmk__str_casei)) {
102 return;
103 }
104 }
105
106 pcmk__rsc_trace(rsc, "Adding %s to %s %s", rsc->id, pcmk__node_name(node),
107 pcmk_is_set(rsc->flags, pcmk_rsc_managed)? "" : "(unmanaged)");
108
109 rsc->running_on = g_list_append(rsc->running_on, node);
110 if (pcmk__is_primitive(rsc)) {
111 node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
112 native_priority_to_node(rsc, node, failed);
113 if (node->details->maintenance) {
116 }
117 }
118
119 if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
120 pcmk_resource_t *p = rsc->parent;
121
122 pcmk__rsc_info(rsc, "resource %s isn't managed", rsc->id);
124 "not_managed_default", scheduler);
125
126 while(p && node->details->online) {
127 /* add without the additional location constraint */
128 p->running_on = g_list_append(p->running_on, node);
129 p = p->parent;
130 }
131 return;
132 }
133
134 if (is_multiply_active(rsc)) {
135 switch (rsc->recovery_type) {
137 {
138 GHashTableIter gIter;
139 pcmk_node_t *local_node = NULL;
140
141 /* make sure it doesn't come up again */
142 if (rsc->allowed_nodes != NULL) {
143 g_hash_table_destroy(rsc->allowed_nodes);
144 }
146 g_hash_table_iter_init(&gIter, rsc->allowed_nodes);
147 while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
148 local_node->weight = -PCMK_SCORE_INFINITY;
149 }
150 }
151 break;
155
156 /* If the resource belongs to a group or bundle configured with
157 * PCMK_META_MULTIPLE_ACTIVE=PCMK_VALUE_BLOCK, block the entire
158 * entity.
159 */
160 if ((pcmk__is_group(rsc->parent)
161 || pcmk__is_bundle(rsc->parent))
163 GList *gIter = rsc->parent->children;
164
165 for (; gIter != NULL; gIter = gIter->next) {
166 pcmk_resource_t *child = gIter->data;
167
170 }
171 }
172 break;
173
174 // pcmk_multiply_active_restart, pcmk_multiply_active_unexpected
175 default:
176 /* The scheduler will do the right thing because the relevant
177 * variables and flags are set when unpacking the history.
178 */
179 break;
180 }
181 crm_debug("%s is active on multiple nodes including %s: %s",
182 rsc->id, pcmk__node_name(node),
184
185 } else {
186 pcmk__rsc_trace(rsc, "Resource %s is active on %s",
187 rsc->id, pcmk__node_name(node));
188 }
189
190 if (rsc->parent != NULL) {
191 native_add_running(rsc->parent, node, scheduler, FALSE);
192 }
193}
194
195static void
196recursive_clear_unique(pcmk_resource_t *rsc, gpointer user_data)
197{
200 g_list_foreach(rsc->children, (GFunc) recursive_clear_unique, NULL);
201}
202
203gboolean
205{
207 const char *standard = crm_element_value(rsc->xml, PCMK_XA_CLASS);
208 uint32_t ra_caps = pcmk_get_ra_caps(standard);
209
210 pcmk__rsc_trace(rsc, "Processing resource %s...", rsc->id);
211
212 // Only some agent standards support unique and promotable clones
213 if (!pcmk_is_set(ra_caps, pcmk_ra_cap_unique)
215 && pcmk__is_clone(parent)) {
216
217 /* @COMPAT We should probably reject this situation as an error (as we
218 * do for promotable below) rather than warn and convert, but that would
219 * be a backward-incompatible change that we should probably do with a
220 * transform at a schema major version bump.
221 */
222 pe__force_anon(standard, parent, rsc->id, scheduler);
223
224 /* Clear PCMK_META_GLOBALLY_UNIQUE on the parent and all its descendants
225 * unpacked so far (clearing the parent should make any future children
226 * unpacking correct). We have to clear this resource explicitly because
227 * it isn't hooked into the parent's children yet.
228 */
229 recursive_clear_unique(parent, NULL);
230 recursive_clear_unique(rsc, NULL);
231 }
234
235 pcmk__config_err("Resource %s is of type %s and therefore "
236 "cannot be used as a promotable clone resource",
237 rsc->id, standard);
238 return FALSE;
239 }
240 return TRUE;
241}
242
243static bool
244rsc_is_on_node(pcmk_resource_t *rsc, const pcmk_node_t *node, int flags)
245{
246 pcmk__rsc_trace(rsc, "Checking whether %s is on %s",
247 rsc->id, pcmk__node_name(node));
248
250 && (rsc->running_on != NULL)) {
251
252 for (GList *iter = rsc->running_on; iter; iter = iter->next) {
253 if (pcmk__same_node((pcmk_node_t *) iter->data, node)) {
254 return true;
255 }
256 }
257
258 } else if (pcmk_is_set(flags, pe_find_inactive) // @COMPAT deprecated
259 && (rsc->running_on == NULL)) {
260 return true;
261
263 && (rsc->allocated_to != NULL)
264 && pcmk__same_node(rsc->allocated_to, node)) {
265 return true;
266 }
267 return false;
268}
269
271native_find_rsc(pcmk_resource_t *rsc, const char *id,
272 const pcmk_node_t *on_node, int flags)
273{
274 bool match = false;
275 pcmk_resource_t *result = NULL;
276
277 CRM_CHECK(id && rsc && rsc->id, return NULL);
278
280 const char *rid = pcmk__xe_id(rsc->xml);
281
282 if (!pcmk__is_clone(pe__const_top_resource(rsc, false))) {
283 match = false;
284
285 } else if (!strcmp(id, rsc->id) || pcmk__str_eq(id, rid, pcmk__str_none)) {
286 match = true;
287 }
288
289 } else if (!strcmp(id, rsc->id)) {
290 match = true;
291
293 && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
294 match = true;
295
298 && !pcmk_is_set(rsc->flags, pcmk_rsc_unique))) {
299 match = pe_base_name_eq(rsc, id);
300 }
301
302 if (match && on_node) {
303 if (!rsc_is_on_node(rsc, on_node, flags)) {
304 match = false;
305 }
306 }
307
308 if (match) {
309 return rsc;
310 }
311
312 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
313 pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
314
315 result = rsc->fns->find_rsc(child, id, on_node, flags);
316 if (result) {
317 return result;
318 }
319 }
320 return NULL;
321}
322
323// create is ignored
324char *
325native_parameter(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create,
326 const char *name, pcmk_scheduler_t *scheduler)
327{
328 const char *value = NULL;
329 GHashTable *params = NULL;
330
331 CRM_CHECK(rsc != NULL, return NULL);
332 CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
333
334 pcmk__rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
335 params = pe_rsc_params(rsc, node, scheduler);
336 value = g_hash_table_lookup(params, name);
337 if (value == NULL) {
338 /* try meta attributes instead */
339 value = g_hash_table_lookup(rsc->meta, name);
340 }
341 return pcmk__str_copy(value);
342}
343
344gboolean
345native_active(pcmk_resource_t * rsc, gboolean all)
346{
347 for (GList *gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
348 pcmk_node_t *a_node = (pcmk_node_t *) gIter->data;
349
350 if (a_node->details->unclean) {
351 pcmk__rsc_trace(rsc, "Resource %s: %s is unclean",
352 rsc->id, pcmk__node_name(a_node));
353 return TRUE;
354 } else if (!a_node->details->online
356 pcmk__rsc_trace(rsc, "Resource %s: %s is offline",
357 rsc->id, pcmk__node_name(a_node));
358 } else {
359 pcmk__rsc_trace(rsc, "Resource %s active on %s",
360 rsc->id, pcmk__node_name(a_node));
361 return TRUE;
362 }
363 }
364 return FALSE;
365}
366
367struct print_data_s {
368 long options;
369 void *print_data;
370};
371
372static const char *
373native_pending_state(const pcmk_resource_t *rsc)
374{
375 const char *pending_state = NULL;
376
377 if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_START, pcmk__str_casei)) {
378 pending_state = "Starting";
379
380 } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_STOP,
382 pending_state = "Stopping";
383
384 } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_MIGRATE_TO,
386 pending_state = "Migrating";
387
388 } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_MIGRATE_FROM,
390 /* Work might be done in here. */
391 pending_state = "Migrating";
392
393 } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_PROMOTE,
395 pending_state = "Promoting";
396
397 } else if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_DEMOTE,
399 pending_state = "Demoting";
400 }
401
402 return pending_state;
403}
404
405static const char *
406native_pending_task(const pcmk_resource_t *rsc)
407{
408 const char *pending_task = NULL;
409
410 if (pcmk__str_eq(rsc->pending_task, PCMK_ACTION_MONITOR, pcmk__str_casei)) {
411 pending_task = "Monitoring";
412
413 /* Pending probes are not printed, even if pending
414 * operations are requested. If someone ever requests that
415 * behavior, uncomment this and the corresponding part of
416 * unpack.c:unpack_rsc_op().
417 */
418 /*
419 } else if (pcmk__str_eq(rsc->pending_task, "probe", pcmk__str_casei)) {
420 pending_task = "Checking";
421 */
422 }
423
424 return pending_task;
425}
426
427static enum rsc_role_e
428native_displayable_role(const pcmk_resource_t *rsc)
429{
430 enum rsc_role_e role = rsc->role;
431
432 if ((role == pcmk_role_started)
435
437 }
438 return role;
439}
440
441static const char *
442native_displayable_state(const pcmk_resource_t *rsc, bool print_pending)
443{
444 const char *rsc_state = NULL;
445
446 if (print_pending) {
447 rsc_state = native_pending_state(rsc);
448 }
449 if (rsc_state == NULL) {
450 rsc_state = pcmk_role_text(native_displayable_role(rsc));
451 }
452 return rsc_state;
453}
454
459static void
460native_print_xml(pcmk_resource_t *rsc, const char *pre_text, long options,
461 void *print_data)
462{
463 const char *class = crm_element_value(rsc->xml, PCMK_XA_CLASS);
464 const char *prov = crm_element_value(rsc->xml, PCMK_XA_PROVIDER);
465 const char *rsc_state = native_displayable_state(rsc, pcmk_is_set(options, pe_print_pending));
466 const char *target_role = NULL;
467
468 /* resource information. */
469 status_print("%s<resource ", pre_text);
470 status_print(PCMK_XA_ID "=\"%s\" ", rsc_printable_id(rsc));
471 status_print("resource_agent=\"%s%s%s:%s\" ", class,
472 ((prov == NULL)? "" : PROVIDER_SEP),
473 ((prov == NULL)? "" : prov),
475
476 status_print("role=\"%s\" ", rsc_state);
477 if (rsc->meta) {
478 target_role = g_hash_table_lookup(rsc->meta, PCMK_META_TARGET_ROLE);
479 }
480 if (target_role) {
481 status_print("target_role=\"%s\" ", target_role);
482 }
483 status_print("active=\"%s\" ", pcmk__btoa(rsc->fns->active(rsc, TRUE)));
484 status_print("orphaned=\"%s\" ",
485 pcmk__flag_text(rsc->flags, pcmk_rsc_removed));
486 status_print("blocked=\"%s\" ",
487 pcmk__flag_text(rsc->flags, pcmk_rsc_blocked));
488 status_print("managed=\"%s\" ",
489 pcmk__flag_text(rsc->flags, pcmk_rsc_managed));
490 status_print("failed=\"%s\" ",
491 pcmk__flag_text(rsc->flags, pcmk_rsc_failed));
492 status_print("failure_ignored=\"%s\" ",
493 pcmk__flag_text(rsc->flags, pcmk_rsc_ignore_failure));
494 status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
495
496 if (options & pe_print_pending) {
497 const char *pending_task = native_pending_task(rsc);
498
499 if (pending_task) {
500 status_print("pending=\"%s\" ", pending_task);
501 }
502 }
503
504 /* print out the nodes this resource is running on */
505 if (options & pe_print_rsconly) {
506 status_print("/>\n");
507 /* do nothing */
508 } else if (rsc->running_on != NULL) {
509 GList *gIter = rsc->running_on;
510
511 status_print(">\n");
512 for (; gIter != NULL; gIter = gIter->next) {
513 pcmk_node_t *node = (pcmk_node_t *) gIter->data;
514
515 status_print("%s <node " PCMK_XA_NAME "=\"%s\" "
516 PCMK_XA_ID "=\"%s\" cached=\"%s\"/>\n",
517 pre_text, pcmk__s(node->details->uname, ""),
518 node->details->id, pcmk__btoa(!node->details->online));
519 }
520 status_print("%s</resource>\n", pre_text);
521 } else {
522 status_print("/>\n");
523 }
524}
525
526// Append a flag to resource description string's flags list
527static bool
528add_output_flag(GString *s, const char *flag_desc, bool have_flags)
529{
530 g_string_append(s, (have_flags? ", " : " ("));
531 g_string_append(s, flag_desc);
532 return true;
533}
534
535// Append a node name to resource description string's node list
536static bool
537add_output_node(GString *s, const char *node, bool have_nodes)
538{
539 g_string_append(s, (have_nodes? " " : " [ "));
540 g_string_append(s, node);
541 return true;
542}
543
558gchar *
560 const pcmk_node_t *node, uint32_t show_opts,
561 const char *target_role, bool show_nodes)
562{
563 const char *class = crm_element_value(rsc->xml, PCMK_XA_CLASS);
564 const char *provider = NULL;
565 const char *kind = crm_element_value(rsc->xml, PCMK_XA_TYPE);
566 GString *outstr = NULL;
567 bool have_flags = false;
568
569 if (!pcmk__is_primitive(rsc)) {
570 return NULL;
571 }
572
573 CRM_CHECK(name != NULL, name = "unknown");
574 CRM_CHECK(kind != NULL, kind = "unknown");
575 CRM_CHECK(class != NULL, class = "unknown");
576
578 provider = crm_element_value(rsc->xml, PCMK_XA_PROVIDER);
579 }
580
581 if ((node == NULL) && (rsc->lock_node != NULL)) {
582 node = rsc->lock_node;
583 }
584 if (pcmk_any_flags_set(show_opts, pcmk_show_rsc_only)
585 || pcmk__list_of_multiple(rsc->running_on)) {
586 node = NULL;
587 }
588
589 outstr = g_string_sized_new(128);
590
591 // Resource name and agent
592 pcmk__g_strcat(outstr,
593 name, "\t(", class, ((provider == NULL)? "" : PROVIDER_SEP),
594 pcmk__s(provider, ""), ":", kind, "):\t", NULL);
595
596 // State on node
598 g_string_append(outstr, " ORPHANED");
599 }
600 if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
601 enum rsc_role_e role = native_displayable_role(rsc);
602
603 g_string_append(outstr, " FAILED");
604 if (role > pcmk_role_unpromoted) {
605 pcmk__add_word(&outstr, 0, pcmk_role_text(role));
606 }
607 } else {
608 bool show_pending = pcmk_is_set(show_opts, pcmk_show_pending);
609
610 pcmk__add_word(&outstr, 0, native_displayable_state(rsc, show_pending));
611 }
612 if (node) {
613 pcmk__add_word(&outstr, 0, pcmk__node_name(node));
614 }
615
616 // Failed probe operation
617 if (native_displayable_role(rsc) == pcmk_role_stopped) {
618 xmlNode *probe_op = pe__failed_probe_for_rsc(rsc, node ? node->details->uname : NULL);
619 if (probe_op != NULL) {
620 int rc;
621
623 &rc, 0);
624 pcmk__g_strcat(outstr, " (", services_ocf_exitcode_str(rc), ") ",
625 NULL);
626 }
627 }
628
629 // Flags, as: (<flag> [...])
630 if (node && !(node->details->online) && node->details->unclean) {
631 have_flags = add_output_flag(outstr, "UNCLEAN", have_flags);
632 }
633 if (node && (node == rsc->lock_node)) {
634 have_flags = add_output_flag(outstr, "LOCKED", have_flags);
635 }
636 if (pcmk_is_set(show_opts, pcmk_show_pending)) {
637 const char *pending_task = native_pending_task(rsc);
638
639 if (pending_task) {
640 have_flags = add_output_flag(outstr, pending_task, have_flags);
641 }
642 }
643 if (target_role != NULL) {
644 switch (pcmk_parse_role(target_role)) {
647 " %s for resource %s", target_role, rsc->id);
648 break;
649
651 have_flags = add_output_flag(outstr, "disabled", have_flags);
652 break;
653
657 have_flags = add_output_flag(outstr,
659 have_flags);
660 g_string_append(outstr, target_role);
661 }
662 break;
663
664 default:
665 /* Only show target role if it limits our abilities (i.e. ignore
666 * Started, as it is the default anyways, and doesn't prevent
667 * the resource from becoming promoted).
668 */
669 break;
670 }
671 }
672
673 // Blocked or maintenance implies unmanaged
674 if (pcmk_any_flags_set(rsc->flags,
677 have_flags = add_output_flag(outstr, "blocked", have_flags);
678
679 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_maintenance)) {
680 have_flags = add_output_flag(outstr, "maintenance", have_flags);
681 }
682 } else if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
683 have_flags = add_output_flag(outstr, "unmanaged", have_flags);
684 }
685
687 have_flags = add_output_flag(outstr, "failure ignored", have_flags);
688 }
689
690
691 if (have_flags) {
692 g_string_append_c(outstr, ')');
693 }
694
695 // User-supplied description
696 if (pcmk_any_flags_set(show_opts, pcmk_show_rsc_only|pcmk_show_description)
697 || pcmk__list_of_multiple(rsc->running_on)) {
698 const char *desc = crm_element_value(rsc->xml, PCMK_XA_DESCRIPTION);
699
700 if (desc) {
701 g_string_append(outstr, " (");
702 g_string_append(outstr, desc);
703 g_string_append(outstr, ")");
704
705 }
706 }
707
708 if (show_nodes && !pcmk_is_set(show_opts, pcmk_show_rsc_only)
709 && pcmk__list_of_multiple(rsc->running_on)) {
710 bool have_nodes = false;
711
712 for (GList *iter = rsc->running_on; iter != NULL; iter = iter->next) {
713 pcmk_node_t *n = (pcmk_node_t *) iter->data;
714
715 have_nodes = add_output_node(outstr, n->details->uname, have_nodes);
716 }
717 if (have_nodes) {
718 g_string_append(outstr, " ]");
719 }
720 }
721
722 return g_string_free(outstr, FALSE);
723}
724
725int
727 const char *name, const pcmk_node_t *node,
728 uint32_t show_opts)
729{
730 const char *kind = crm_element_value(rsc->xml, PCMK_XA_TYPE);
731 const char *target_role = NULL;
732 const char *cl = NULL;
733
734 xmlNode *child = NULL;
735 gchar *content = NULL;
736
737 CRM_ASSERT((kind != NULL) && pcmk__is_primitive(rsc));
738
739 if (rsc->meta) {
740 const char *is_internal = g_hash_table_lookup(rsc->meta,
742
743 if (crm_is_true(is_internal)
744 && !pcmk_is_set(show_opts, pcmk_show_implicit_rscs)) {
745
746 crm_trace("skipping print of internal resource %s", rsc->id);
747 return pcmk_rc_no_output;
748 }
749 target_role = g_hash_table_lookup(rsc->meta, PCMK_META_TARGET_ROLE);
750 }
751
752 if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
754
755 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
757
758 } else if (pcmk__is_primitive(rsc) && (rsc->running_on == NULL)) {
760
761 } else if (pcmk__list_of_multiple(rsc->running_on)) {
763
764 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_ignore_failure)) {
766
767 } else {
769 }
770
771 child = pcmk__output_create_html_node(out, "li", NULL, NULL, NULL);
772 child = pcmk__html_create(child, PCMK__XE_SPAN, NULL, cl);
773 content = pcmk__native_output_string(rsc, name, node, show_opts,
774 target_role, true);
775 pcmk__xe_set_content(child, "%s", content);
776 g_free(content);
777
778 return pcmk_rc_ok;
779}
780
781int
783 const char *name, const pcmk_node_t *node,
784 uint32_t show_opts)
785{
786 const char *target_role = NULL;
787
788 CRM_ASSERT(pcmk__is_primitive(rsc));
789
790 if (rsc->meta) {
791 const char *is_internal = g_hash_table_lookup(rsc->meta,
793
794 if (crm_is_true(is_internal)
795 && !pcmk_is_set(show_opts, pcmk_show_implicit_rscs)) {
796
797 crm_trace("skipping print of internal resource %s", rsc->id);
798 return pcmk_rc_no_output;
799 }
800 target_role = g_hash_table_lookup(rsc->meta, PCMK_META_TARGET_ROLE);
801 }
802
803 {
804 gchar *s = pcmk__native_output_string(rsc, name, node, show_opts,
805 target_role, true);
806
807 out->list_item(out, NULL, "%s", s);
808 g_free(s);
809 }
810
811 return pcmk_rc_ok;
812}
813
818void
819common_print(pcmk_resource_t *rsc, const char *pre_text, const char *name,
820 const pcmk_node_t *node, long options, void *print_data)
821{
822 const char *target_role = NULL;
823
824 CRM_ASSERT(pcmk__is_primitive(rsc));
825
826 if (rsc->meta) {
827 const char *is_internal = g_hash_table_lookup(rsc->meta,
829
830 if (crm_is_true(is_internal)
831 && !pcmk_is_set(options, pe_print_implicit)) {
832
833 crm_trace("skipping print of internal resource %s", rsc->id);
834 return;
835 }
836 target_role = g_hash_table_lookup(rsc->meta, PCMK_META_TARGET_ROLE);
837 }
838
839 if (options & pe_print_xml) {
840 native_print_xml(rsc, pre_text, options, print_data);
841 return;
842 }
843
844 if ((pre_text == NULL) && (options & pe_print_printf)) {
845 pre_text = " ";
846 }
847
848 if (options & pe_print_html) {
849 if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
850 status_print("<font color=\"yellow\">");
851
852 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_failed)) {
853 status_print("<font color=\"red\">");
854
855 } else if (rsc->running_on == NULL) {
856 status_print("<font color=\"red\">");
857
858 } else if (pcmk__list_of_multiple(rsc->running_on)) {
859 status_print("<font color=\"orange\">");
860
861 } else if (pcmk_is_set(rsc->flags, pcmk_rsc_ignore_failure)) {
862 status_print("<font color=\"yellow\">");
863
864 } else {
865 status_print("<font color=\"green\">");
866 }
867 }
868
869 {
870 gchar *resource_s = pcmk__native_output_string(rsc, name, node, options,
871 target_role, false);
872 status_print("%s%s", (pre_text? pre_text : ""), resource_s);
873 g_free(resource_s);
874 }
875
876 if (pcmk_is_set(options, pe_print_html)) {
877 status_print(" </font> ");
878 }
879
880 if (!pcmk_is_set(options, pe_print_rsconly)
881 && pcmk__list_of_multiple(rsc->running_on)) {
882
883 GList *gIter = rsc->running_on;
884 int counter = 0;
885
886 if (options & pe_print_html) {
887 status_print("<ul>\n");
888 } else if ((options & pe_print_printf)
889 || (options & pe_print_ncurses)) {
890 status_print("[");
891 }
892
893 for (; gIter != NULL; gIter = gIter->next) {
894 pcmk_node_t *n = (pcmk_node_t *) gIter->data;
895
896 counter++;
897
898 if (options & pe_print_html) {
899 status_print("<li>\n%s", pcmk__node_name(n));
900
901 } else if ((options & pe_print_printf)
902 || (options & pe_print_ncurses)) {
903 status_print(" %s", pcmk__node_name(n));
904
905 } else if ((options & pe_print_log)) {
906 status_print("\t%d : %s", counter, pcmk__node_name(n));
907
908 } else {
909 status_print("%s", pcmk__node_name(n));
910 }
911 if (options & pe_print_html) {
912 status_print("</li>\n");
913
914 }
915 }
916
917 if (options & pe_print_html) {
918 status_print("</ul>\n");
919 } else if ((options & pe_print_printf)
920 || (options & pe_print_ncurses)) {
921 status_print(" ]");
922 }
923 }
924
925 if (options & pe_print_html) {
926 status_print("<br/>\n");
927 } else if (options & pe_print_suppres_nl) {
928 /* nothing */
929 } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
930 status_print("\n");
931 }
932}
933
938void
939native_print(pcmk_resource_t *rsc, const char *pre_text, long options,
940 void *print_data)
941{
942 const pcmk_node_t *node = NULL;
943
944 CRM_ASSERT(pcmk__is_primitive(rsc));
945
946 if (options & pe_print_xml) {
947 native_print_xml(rsc, pre_text, options, print_data);
948 return;
949 }
950
951 node = pcmk__current_node(rsc);
952
953 if (node == NULL) {
954 // This is set only if a non-probe action is pending on this node
955 node = rsc->pending_node;
956 }
957
958 common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
959}
960
961PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
962 "GList *")
963int
964pe__resource_xml(pcmk__output_t *out, va_list args)
965{
966 uint32_t show_opts = va_arg(args, uint32_t);
967 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
968 GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
969 GList *only_rsc = va_arg(args, GList *);
970
971 int rc = pcmk_rc_no_output;
972 bool print_pending = pcmk_is_set(show_opts, pcmk_show_pending);
973 const char *class = crm_element_value(rsc->xml, PCMK_XA_CLASS);
974 const char *prov = crm_element_value(rsc->xml, PCMK_XA_PROVIDER);
975
976 char ra_name[LINE_MAX];
977 const char *rsc_state = native_displayable_state(rsc, print_pending);
978 const char *target_role = NULL;
979 const char *active = pcmk__btoa(rsc->fns->active(rsc, TRUE));
980 const char *orphaned = pcmk__flag_text(rsc->flags, pcmk_rsc_removed);
981 const char *blocked = pcmk__flag_text(rsc->flags, pcmk_rsc_blocked);
982 const char *maintenance = pcmk__flag_text(rsc->flags, pcmk_rsc_maintenance);
983 const char *managed = pcmk__flag_text(rsc->flags, pcmk_rsc_managed);
984 const char *failed = pcmk__flag_text(rsc->flags, pcmk_rsc_failed);
985 const char *ignored = pcmk__flag_text(rsc->flags, pcmk_rsc_ignore_failure);
986 char *nodes_running_on = NULL;
987 const char *pending = print_pending? native_pending_task(rsc) : NULL;
988 const char *locked_to = NULL;
989 const char *desc = pe__resource_description(rsc, show_opts);
990
991 CRM_ASSERT(pcmk__is_primitive(rsc));
992
993 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
994 return pcmk_rc_no_output;
995 }
996
997 // Resource information
998 snprintf(ra_name, LINE_MAX, "%s%s%s:%s", class,
999 ((prov == NULL)? "" : PROVIDER_SEP), ((prov == NULL)? "" : prov),
1001
1002 if (rsc->meta != NULL) {
1003 target_role = g_hash_table_lookup(rsc->meta, PCMK_META_TARGET_ROLE);
1004 }
1005
1006 nodes_running_on = pcmk__itoa(g_list_length(rsc->running_on));
1007
1008 if (rsc->lock_node != NULL) {
1009 locked_to = rsc->lock_node->details->uname;
1010 }
1011
1014 PCMK_XA_RESOURCE_AGENT, ra_name,
1015 PCMK_XA_ROLE, rsc_state,
1016 PCMK_XA_TARGET_ROLE, target_role,
1017 PCMK_XA_ACTIVE, active,
1018 PCMK_XA_ORPHANED, orphaned,
1019 PCMK_XA_BLOCKED, blocked,
1020 PCMK_XA_MAINTENANCE, maintenance,
1021 PCMK_XA_MANAGED, managed,
1022 PCMK_XA_FAILED, failed,
1023 PCMK_XA_FAILURE_IGNORED, ignored,
1024 PCMK_XA_NODES_RUNNING_ON, nodes_running_on,
1025 PCMK_XA_PENDING, pending,
1026 PCMK_XA_LOCKED_TO, locked_to,
1027 PCMK_XA_DESCRIPTION, desc,
1028 NULL);
1029 free(nodes_running_on);
1030
1031 CRM_ASSERT(rc == pcmk_rc_ok);
1032
1033 if (rsc->running_on != NULL) {
1034 GList *gIter = rsc->running_on;
1035
1036 for (; gIter != NULL; gIter = gIter->next) {
1037 pcmk_node_t *node = (pcmk_node_t *) gIter->data;
1038 const char *cached = pcmk__btoa(node->details->online);
1039
1040 rc = pe__name_and_nvpairs_xml(out, false, PCMK_XE_NODE,
1041 PCMK_XA_NAME, node->details->uname,
1042 PCMK_XA_ID, node->details->id,
1043 PCMK_XA_CACHED, cached,
1044 NULL);
1045 CRM_ASSERT(rc == pcmk_rc_ok);
1046 }
1047 }
1048
1050 return rc;
1051}
1052
1053PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
1054 "GList *")
1055int
1056pe__resource_html(pcmk__output_t *out, va_list args)
1057{
1058 uint32_t show_opts = va_arg(args, uint32_t);
1059 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
1060 GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
1061 GList *only_rsc = va_arg(args, GList *);
1062
1063 const pcmk_node_t *node = pcmk__current_node(rsc);
1064
1065 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1066 return pcmk_rc_no_output;
1067 }
1068
1069 CRM_ASSERT(pcmk__is_primitive(rsc));
1070
1071 if (node == NULL) {
1072 // This is set only if a non-probe action is pending on this node
1073 node = rsc->pending_node;
1074 }
1075 return pe__common_output_html(out, rsc, rsc_printable_id(rsc), node, show_opts);
1076}
1077
1078PCMK__OUTPUT_ARGS("primitive", "uint32_t", "pcmk_resource_t *", "GList *",
1079 "GList *")
1080int
1081pe__resource_text(pcmk__output_t *out, va_list args)
1082{
1083 uint32_t show_opts = va_arg(args, uint32_t);
1084 pcmk_resource_t *rsc = va_arg(args, pcmk_resource_t *);
1085 GList *only_node G_GNUC_UNUSED = va_arg(args, GList *);
1086 GList *only_rsc = va_arg(args, GList *);
1087
1088 const pcmk_node_t *node = pcmk__current_node(rsc);
1089
1090 CRM_ASSERT(pcmk__is_primitive(rsc));
1091
1092 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1093 return pcmk_rc_no_output;
1094 }
1095
1096 if (node == NULL) {
1097 // This is set only if a non-probe action is pending on this node
1098 node = rsc->pending_node;
1099 }
1100 return pe__common_output_text(out, rsc, rsc_printable_id(rsc), node, show_opts);
1101}
1102
1103void
1105{
1106 pcmk__rsc_trace(rsc, "Freeing resource action list (not the data)");
1107 common_free(rsc);
1108}
1109
1110enum rsc_role_e
1111native_resource_state(const pcmk_resource_t * rsc, gboolean current)
1112{
1113 enum rsc_role_e role = rsc->next_role;
1114
1115 if (current) {
1116 role = rsc->role;
1117 }
1118 pcmk__rsc_trace(rsc, "%s state: %s", rsc->id, pcmk_role_text(role));
1119 return role;
1120}
1121
1134native_location(const pcmk_resource_t *rsc, GList **list, int current)
1135{
1136 // @COMPAT: Accept a pcmk__rsc_node argument instead of int current
1137 pcmk_node_t *one = NULL;
1138 GList *result = NULL;
1139
1140 if (rsc->children) {
1141 GList *gIter = rsc->children;
1142
1143 for (; gIter != NULL; gIter = gIter->next) {
1144 pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
1145
1146 child->fns->location(child, &result, current);
1147 }
1148
1149 } else if (current) {
1150
1151 if (rsc->running_on) {
1152 result = g_list_copy(rsc->running_on);
1153 }
1154 if ((current == 2) && rsc->pending_node
1156 result = g_list_append(result, rsc->pending_node);
1157 }
1158
1159 } else if (current == FALSE && rsc->allocated_to) {
1160 result = g_list_append(NULL, rsc->allocated_to);
1161 }
1162
1163 if (result && (result->next == NULL)) {
1164 one = result->data;
1165 }
1166
1167 if (list) {
1168 GList *gIter = result;
1169
1170 for (; gIter != NULL; gIter = gIter->next) {
1171 pcmk_node_t *node = (pcmk_node_t *) gIter->data;
1172
1173 if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
1174 *list = g_list_append(*list, node);
1175 }
1176 }
1177 }
1178
1179 g_list_free(result);
1180 return one;
1181}
1182
1183static void
1184get_rscs_brief(GList *rsc_list, GHashTable * rsc_table, GHashTable * active_table)
1185{
1186 GList *gIter = rsc_list;
1187
1188 for (; gIter != NULL; gIter = gIter->next) {
1189 pcmk_resource_t *rsc = (pcmk_resource_t *) gIter->data;
1190
1191 const char *class = crm_element_value(rsc->xml, PCMK_XA_CLASS);
1192 const char *kind = crm_element_value(rsc->xml, PCMK_XA_TYPE);
1193
1194 int offset = 0;
1195 char buffer[LINE_MAX];
1196
1197 int *rsc_counter = NULL;
1198 int *active_counter = NULL;
1199
1200 if (!pcmk__is_primitive(rsc)) {
1201 continue;
1202 }
1203
1204 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
1206 const char *prov = crm_element_value(rsc->xml, PCMK_XA_PROVIDER);
1207
1208 if (prov != NULL) {
1209 offset += snprintf(buffer + offset, LINE_MAX - offset,
1210 PROVIDER_SEP "%s", prov);
1211 }
1212 }
1213 offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
1214 CRM_LOG_ASSERT(offset > 0);
1215
1216 if (rsc_table) {
1217 rsc_counter = g_hash_table_lookup(rsc_table, buffer);
1218 if (rsc_counter == NULL) {
1219 rsc_counter = pcmk__assert_alloc(1, sizeof(int));
1220 *rsc_counter = 0;
1221 g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
1222 }
1223 (*rsc_counter)++;
1224 }
1225
1226 if (active_table) {
1227 GList *gIter2 = rsc->running_on;
1228
1229 for (; gIter2 != NULL; gIter2 = gIter2->next) {
1230 pcmk_node_t *node = (pcmk_node_t *) gIter2->data;
1231 GHashTable *node_table = NULL;
1232
1233 if (node->details->unclean == FALSE && node->details->online == FALSE &&
1235 continue;
1236 }
1237
1238 node_table = g_hash_table_lookup(active_table, node->details->uname);
1239 if (node_table == NULL) {
1240 node_table = pcmk__strkey_table(free, free);
1241 g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
1242 }
1243
1244 active_counter = g_hash_table_lookup(node_table, buffer);
1245 if (active_counter == NULL) {
1246 active_counter = pcmk__assert_alloc(1, sizeof(int));
1247 *active_counter = 0;
1248 g_hash_table_insert(node_table, strdup(buffer), active_counter);
1249 }
1250 (*active_counter)++;
1251 }
1252 }
1253 }
1254}
1255
1256static void
1257destroy_node_table(gpointer data)
1258{
1259 GHashTable *node_table = data;
1260
1261 if (node_table) {
1262 g_hash_table_destroy(node_table);
1263 }
1264}
1265
1270void
1271print_rscs_brief(GList *rsc_list, const char *pre_text, long options,
1272 void *print_data, gboolean print_all)
1273{
1274 GHashTable *rsc_table = pcmk__strkey_table(free, free);
1275 GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1276 GHashTableIter hash_iter;
1277 char *type = NULL;
1278 int *rsc_counter = NULL;
1279
1280 get_rscs_brief(rsc_list, rsc_table, active_table);
1281
1282 g_hash_table_iter_init(&hash_iter, rsc_table);
1283 while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
1284 GHashTableIter hash_iter2;
1285 char *node_name = NULL;
1286 GHashTable *node_table = NULL;
1287 int active_counter_all = 0;
1288
1289 g_hash_table_iter_init(&hash_iter2, active_table);
1290 while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
1291 int *active_counter = g_hash_table_lookup(node_table, type);
1292
1293 if (active_counter == NULL || *active_counter == 0) {
1294 continue;
1295
1296 } else {
1297 active_counter_all += *active_counter;
1298 }
1299
1300 if (options & pe_print_rsconly) {
1301 node_name = NULL;
1302 }
1303
1304 if (options & pe_print_html) {
1305 status_print("<li>\n");
1306 }
1307
1308 if (print_all) {
1309 status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1310 active_counter ? *active_counter : 0,
1311 rsc_counter ? *rsc_counter : 0, type,
1312 active_counter && (*active_counter > 0) && node_name ? node_name : "");
1313 } else {
1314 status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
1315 active_counter ? *active_counter : 0, type,
1316 active_counter && (*active_counter > 0) && node_name ? node_name : "");
1317 }
1318
1319 if (options & pe_print_html) {
1320 status_print("</li>\n");
1321 }
1322 }
1323
1324 if (print_all && active_counter_all == 0) {
1325 if (options & pe_print_html) {
1326 status_print("<li>\n");
1327 }
1328
1329 status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
1330 active_counter_all,
1331 rsc_counter ? *rsc_counter : 0, type);
1332
1333 if (options & pe_print_html) {
1334 status_print("</li>\n");
1335 }
1336 }
1337 }
1338
1339 if (rsc_table) {
1340 g_hash_table_destroy(rsc_table);
1341 rsc_table = NULL;
1342 }
1343 if (active_table) {
1344 g_hash_table_destroy(active_table);
1345 active_table = NULL;
1346 }
1347}
1348
1349int
1350pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, uint32_t show_opts)
1351{
1352 GHashTable *rsc_table = pcmk__strkey_table(free, free);
1353 GHashTable *active_table = pcmk__strkey_table(free, destroy_node_table);
1354 GList *sorted_rscs;
1355 int rc = pcmk_rc_no_output;
1356
1357 get_rscs_brief(rsc_list, rsc_table, active_table);
1358
1359 /* Make a list of the rsc_table keys so that it can be sorted. This is to make sure
1360 * output order stays consistent between systems.
1361 */
1362 sorted_rscs = g_hash_table_get_keys(rsc_table);
1363 sorted_rscs = g_list_sort(sorted_rscs, (GCompareFunc) strcmp);
1364
1365 for (GList *gIter = sorted_rscs; gIter; gIter = gIter->next) {
1366 char *type = (char *) gIter->data;
1367 int *rsc_counter = g_hash_table_lookup(rsc_table, type);
1368
1369 GList *sorted_nodes = NULL;
1370 int active_counter_all = 0;
1371
1372 /* Also make a list of the active_table keys so it can be sorted. If there's
1373 * more than one instance of a type of resource running, we need the nodes to
1374 * be sorted to make sure output order stays consistent between systems.
1375 */
1376 sorted_nodes = g_hash_table_get_keys(active_table);
1377 sorted_nodes = g_list_sort(sorted_nodes, (GCompareFunc) pcmk__numeric_strcasecmp);
1378
1379 for (GList *gIter2 = sorted_nodes; gIter2; gIter2 = gIter2->next) {
1380 char *node_name = (char *) gIter2->data;
1381 GHashTable *node_table = g_hash_table_lookup(active_table, node_name);
1382 int *active_counter = NULL;
1383
1384 if (node_table == NULL) {
1385 continue;
1386 }
1387
1388 active_counter = g_hash_table_lookup(node_table, type);
1389
1390 if (active_counter == NULL || *active_counter == 0) {
1391 continue;
1392
1393 } else {
1394 active_counter_all += *active_counter;
1395 }
1396
1397 if (pcmk_is_set(show_opts, pcmk_show_rsc_only)) {
1398 node_name = NULL;
1399 }
1400
1401 if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs)) {
1402 out->list_item(out, NULL, "%d/%d\t(%s):\tActive %s",
1403 *active_counter,
1404 rsc_counter ? *rsc_counter : 0, type,
1405 (*active_counter > 0) && node_name ? node_name : "");
1406 } else {
1407 out->list_item(out, NULL, "%d\t(%s):\tActive %s",
1408 *active_counter, type,
1409 (*active_counter > 0) && node_name ? node_name : "");
1410 }
1411
1412 rc = pcmk_rc_ok;
1413 }
1414
1415 if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs) && active_counter_all == 0) {
1416 out->list_item(out, NULL, "%d/%d\t(%s):\tActive",
1417 active_counter_all,
1418 rsc_counter ? *rsc_counter : 0, type);
1419 rc = pcmk_rc_ok;
1420 }
1421
1422 if (sorted_nodes) {
1423 g_list_free(sorted_nodes);
1424 }
1425 }
1426
1427 if (rsc_table) {
1428 g_hash_table_destroy(rsc_table);
1429 rsc_table = NULL;
1430 }
1431 if (active_table) {
1432 g_hash_table_destroy(active_table);
1433 active_table = NULL;
1434 }
1435 if (sorted_rscs) {
1436 g_list_free(sorted_rscs);
1437 }
1438
1439 return rc;
1440}
1441
1442gboolean
1443pe__native_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc,
1444 gboolean check_parent)
1445{
1447 pcmk__str_in_list(rsc->id, only_rsc, pcmk__str_star_matches)) {
1448 return FALSE;
1449 } else if (check_parent && rsc->parent) {
1450 const pcmk_resource_t *up = pe__const_top_resource(rsc, true);
1451
1452 return up->fns->is_filtered(up, only_rsc, FALSE);
1453 }
1454
1455 return TRUE;
1456}
1457
1466unsigned int
1468{
1469 CRM_ASSERT(pcmk__is_primitive(rsc));
1470 return 1U;
1471}
#define PCMK_ACTION_STOP
Definition actions.h:75
#define PCMK_ACTION_PROMOTE
Definition actions.h:66
#define PCMK_ACTION_START
Definition actions.h:72
#define PCMK_ACTION_MIGRATE_FROM
Definition actions.h:58
#define PCMK_ACTION_MIGRATE_TO
Definition actions.h:59
#define PCMK_ACTION_MONITOR
Definition actions.h:60
#define PCMK_ACTION_DEMOTE
Definition actions.h:49
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition agents.c:31
@ pcmk_ra_cap_unique
Definition agents.h:62
@ pcmk_ra_cap_promotable
Definition agents.h:63
@ pcmk_ra_cap_provider
Definition agents.h:59
const char * parent
Definition cib.c:27
const char * name
Definition cib.c:26
void pe__force_anon(const char *standard, pcmk_resource_t *rsc, const char *rid, pcmk_scheduler_t *scheduler)
Definition clone.c:212
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:297
uint64_t flags
Definition remote.c:3
gboolean crm_is_true(const char *s)
Definition strings.c:488
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:98
#define resource_s
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
Definition complex.c:1007
GHashTable * pe_rsc_params(pcmk_resource_t *rsc, const pcmk_node_t *node, pcmk_scheduler_t *scheduler)
Get a table of resource parameters.
Definition complex.c:484
enum crm_ais_msg_types type
Definition cpg.c:3
char data[0]
Definition cpg.c:10
uint32_t id
Definition cpg.c:0
#define CRM_LOG_ASSERT(expr)
Definition logging.h:228
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
#define crm_debug(fmt, args...)
Definition logging.h:400
#define crm_trace(fmt, args...)
Definition logging.h:402
#define pcmk__config_err(fmt...)
gboolean native_active(pcmk_resource_t *rsc, gboolean all)
Definition native.c:345
int pe__common_output_html(pcmk__output_t *out, const pcmk_resource_t *rsc, const char *name, const pcmk_node_t *node, uint32_t show_opts)
Definition native.c:726
int pe__common_output_text(pcmk__output_t *out, const pcmk_resource_t *rsc, const char *name, const pcmk_node_t *node, uint32_t show_opts)
Definition native.c:782
int pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, uint32_t show_opts)
Definition native.c:1350
enum rsc_role_e native_resource_state(const pcmk_resource_t *rsc, gboolean current)
Definition native.c:1111
void native_free(pcmk_resource_t *rsc)
Definition native.c:1104
void common_print(pcmk_resource_t *rsc, const char *pre_text, const char *name, const pcmk_node_t *node, long options, void *print_data)
Definition native.c:819
#define PROVIDER_SEP
Definition native.c:25
gboolean pe__native_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
Definition native.c:1443
char * native_parameter(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create, const char *name, pcmk_scheduler_t *scheduler)
Definition native.c:325
gboolean native_unpack(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler)
Definition native.c:204
void print_rscs_brief(GList *rsc_list, const char *pre_text, long options, void *print_data, gboolean print_all)
Definition native.c:1271
pcmk_node_t * native_location(const pcmk_resource_t *rsc, GList **list, int current)
Definition native.c:1134
unsigned int pe__primitive_max_per_node(const pcmk_resource_t *rsc)
Definition native.c:1467
gchar * pcmk__native_output_string(const pcmk_resource_t *rsc, const char *name, const pcmk_node_t *node, uint32_t show_opts, const char *target_role, bool show_nodes)
Definition native.c:559
void native_add_running(pcmk_resource_t *rsc, pcmk_node_t *node, pcmk_scheduler_t *scheduler, gboolean failed)
Definition native.c:91
void native_print(pcmk_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition native.c:939
pcmk_resource_t * native_find_rsc(pcmk_resource_t *rsc, const char *id, const pcmk_node_t *on_node, int flags)
Definition native.c:271
pcmk_scheduler_t * scheduler
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:446
#define pcmk__insert_meta(obj, name, value)
#define PCMK_META_TARGET_ROLE
Definition options.h:113
#define PCMK_META_GLOBALLY_UNIQUE
Definition options.h:89
#define PCMK_VALUE_FALSE
Definition options.h:152
#define PCMK__VALUE_RSC_OK
#define PCMK__VALUE_RSC_FAILURE_IGNORED
#define PCMK__META_INTERNAL_RSC
#define PCMK__VALUE_RSC_FAILED
#define PCMK__VALUE_RSC_MULTIPLE
#define PCMK__VALUE_RSC_MANAGED
Control output from tools.
@ pcmk_show_implicit_rscs
Definition output.h:61
@ pcmk_show_pending
Definition output.h:65
@ pcmk_show_rsc_only
Definition output.h:66
@ pcmk_show_inactive_rscs
Definition output.h:63
@ pcmk_show_description
Definition output.h:69
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition output_xml.c:564
xmlNodePtr pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id, const char *class_name, const char *text)
#define PCMK__OUTPUT_ARGS(ARGS...)
xmlNode * pcmk__html_create(xmlNode *parent, const char *name, const char *id, const char *class)
pcmk__action_result_t result
Definition pcmk_fence.c:35
#define status_print(fmt, args...)
GHashTable * pe__node_list2table(const GList *list)
Definition utils.c:115
const char * pe__resource_description(const pcmk_resource_t *rsc, uint32_t show_opts)
Definition pe_output.c:22
pcmk_node_t * pe__find_active_requires(const pcmk_resource_t *rsc, unsigned int *count)
Definition complex.c:1208
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
Definition complex.c:1032
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name,...) G_GNUC_NULL_TERMINATED
Definition pe_output.c:610
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
Definition utils.c:359
xmlNode * pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name)
Definition utils.c:883
void common_free(pcmk_resource_t *rsc)
Definition complex.c:1049
int pe__resource_xml(pcmk__output_t *out, va_list args)
int pe__resource_text(pcmk__output_t *out, va_list args)
int pe__resource_html(pcmk__output_t *out, va_list args)
@ pe_print_ncurses
Definition resources.h:230
@ pe_print_printf
Definition resources.h:231
@ pe_print_rsconly
Definition resources.h:235
@ pe_print_implicit
Definition resources.h:243
@ pe_print_log
Definition resources.h:228
@ pe_print_xml
Definition resources.h:238
@ pe_print_pending
Definition resources.h:240
@ pe_print_suppres_nl
Definition resources.h:237
@ pe_print_html
Definition resources.h:229
@ pcmk_multiply_active_block
Definition resources.h:68
@ pcmk_multiply_active_stop
Definition resources.h:67
@ pcmk_rsc_match_anon_basename
Also match anonymous clone instances by base name.
Definition resources.h:188
@ pe_find_inactive
Definition resources.h:197
@ pcmk_rsc_match_clone_only
Match only clones and their instances, by either clone or instance ID.
Definition resources.h:191
@ pcmk_rsc_match_basename
Match clone instances (even unique) by base name as well as exact ID.
Definition resources.h:200
@ pcmk_rsc_match_history
Also match clone instance ID from resource history.
Definition resources.h:185
@ pcmk_rsc_match_current_node
If matching by node, compare current node instead of assigned node.
Definition resources.h:194
@ pcmk_rsc_promotable
Definition resources.h:106
@ pcmk_rsc_unique
Definition resources.h:100
@ pcmk_rsc_maintenance
Definition resources.h:166
@ pcmk_rsc_removed
Definition resources.h:85
@ pcmk_rsc_blocked
Definition resources.h:91
@ pcmk_rsc_managed
Definition resources.h:88
@ pcmk_rsc_ignore_failure
Definition resources.h:160
@ pcmk_rsc_failed
Definition resources.h:133
const char * pcmk__multiply_active_text(enum rsc_recovery_type recovery)
Get readable description of a multiply-active recovery type.
Definition resources.c:54
#define CRM_ASSERT(expr)
Definition results.h:42
@ pcmk_rc_no_output
Definition results.h:131
@ pcmk_rc_ok
Definition results.h:162
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
Definition roles.c:23
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
Definition roles.c:59
rsc_role_e
Definition roles.h:34
@ pcmk_role_started
Started.
Definition roles.h:37
@ pcmk_role_unknown
Resource role is unknown.
Definition roles.h:35
@ pcmk_role_unpromoted
Unpromoted.
Definition roles.h:38
@ pcmk_role_promoted
Promoted.
Definition roles.h:39
@ pcmk_role_stopped
Stopped.
Definition roles.h:36
#define pcmk__set_rsc_flags(resource, flags_to_set)
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
#define pcmk__rsc_info(rsc, fmt, args...)
#define pcmk__rsc_trace(rsc, fmt, args...)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition scores.h:24
Cluster status and scheduling.
pcmk_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:487
const char * rsc_printable_id(const pcmk_resource_t *rsc)
Definition utils.c:553
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition strings.c:1078
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition strings.c:127
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
Definition strings.c:981
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:683
@ pcmk__str_none
@ pcmk__str_star_matches
@ pcmk__str_casei
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition strings.c:1296
#define pcmk__str_copy(str)
This structure contains everything that makes up a single output formatter.
void(*) void(* list_item)(pcmk__output_t *out, const char *name, const char *format,...) G_GNUC_PRINTF(3
int weight
Definition nodes.h:162
struct pe_node_shared_s * details
Definition nodes.h:167
const char * id
Definition nodes.h:72
gboolean online
Definition nodes.h:80
const char * uname
Definition nodes.h:73
gboolean unclean
Definition nodes.h:91
pcmk_resource_t * remote_rsc
Definition nodes.h:135
gboolean maintenance
Definition nodes.h:104
GList * running_rsc
Definition nodes.h:139
GList * running_on
Definition resources.h:456
GHashTable * meta
Definition resources.h:467
GList * children
Definition resources.h:471
pcmk_resource_t * container
Definition resources.h:476
pcmk_rsc_methods_t * fns
Definition resources.h:412
char * clone_name
Definition resources.h:397
pcmk_node_t * allocated_to
Definition resources.h:447
xmlNode * xml
Definition resources.h:400
GHashTable * allowed_nodes
Definition resources.h:462
pcmk_node_t * lock_node
Definition resources.h:481
unsigned long long flags
Definition resources.h:428
pcmk_node_t * pending_node
Definition resources.h:480
char * pending_task
Definition resources.h:424
enum rsc_recovery_type recovery_type
Definition resources.h:415
enum rsc_role_e next_role
Definition resources.h:465
enum rsc_role_e role
Definition resources.h:464
pcmk_resource_t * parent
Definition resources.h:409
pcmk_resource_t *(* find_rsc)(pcmk_resource_t *rsc, const char *search, const pcmk_node_t *node, int flags)
Definition resources.h:276
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, int current)
Definition resources.h:328
gboolean(* is_filtered)(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
Definition resources.h:358
gboolean(* active)(pcmk_resource_t *rsc, gboolean all)
Definition resources.h:306
Wrappers for and extensions to libxml2.
void pcmk__xe_set_content(xmlNode *node, const char *format,...) G_GNUC_PRINTF(2
#define PCMK_XA_DESCRIPTION
Definition xml_names.h:256
#define PCMK_XA_CLASS
Definition xml_names.h:241
#define PCMK_XE_NODE
Definition xml_names.h:133
#define PCMK_XA_RESOURCE_AGENT
Definition xml_names.h:378
#define PCMK_XA_ORPHANED
Definition xml_names.h:348
#define PCMK_XA_LOCKED_TO
Definition xml_names.h:313
#define PCMK_XA_FAILED
Definition xml_names.h:278
#define PCMK_XA_ID
Definition xml_names.h:296
#define PCMK_XA_ROLE
Definition xml_names.h:382
#define PCMK_XA_PROVIDER
Definition xml_names.h:359
#define PCMK_XA_FAILURE_IGNORED
Definition xml_names.h:279
#define PCMK_XA_TARGET_ROLE
Definition xml_names.h:417
#define PCMK_XA_MAINTENANCE
Definition xml_names.h:316
#define PCMK_XA_ACTIVE
Definition xml_names.h:225
#define PCMK_XA_PENDING
Definition xml_names.h:351
#define PCMK_XA_TYPE
Definition xml_names.h:425
#define PCMK_XA_BLOCKED
Definition xml_names.h:234
#define PCMK_XA_NODES_RUNNING_ON
Definition xml_names.h:335
#define PCMK_XA_NAME
Definition xml_names.h:325
#define PCMK_XE_RESOURCE
Definition xml_names.h:168
#define PCMK_XA_CACHED
Definition xml_names.h:237
#define PCMK_XA_MANAGED
Definition xml_names.h:318
#define PCMK__XE_SPAN
#define PCMK__XA_RC_CODE