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