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