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