pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pe_output.c
Go to the documentation of this file.
1/*
2 * Copyright 2019-2021 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>
13#include <crm/common/output.h>
14#include <crm/cib/util.h>
15#include <crm/msg_xml.h>
17
18/* Never display node attributes whose name starts with one of these prefixes */
19#define FILTER_STR { PCMK__FAIL_COUNT_PREFIX, PCMK__LAST_FAILURE_PREFIX, \
20 "shutdown", "terminate", "standby", "probe_complete", \
21 "#", NULL }
22
23static int
24compare_attribute(gconstpointer a, gconstpointer b)
25{
26 int rc;
27
28 rc = strcmp((const char *)a, (const char *)b);
29
30 return rc;
31}
32
47static gboolean
48add_extra_info(pe_node_t *node, GList *rsc_list, pe_working_set_t *data_set,
49 const char *attrname, int *expected_score)
50{
51 GList *gIter = NULL;
52
53 for (gIter = rsc_list; gIter != NULL; gIter = gIter->next) {
54 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
55 const char *type = g_hash_table_lookup(rsc->meta, "type");
56 const char *name = NULL;
57 GHashTable *params = NULL;
58
59 if (rsc->children != NULL) {
60 if (add_extra_info(node, rsc->children, data_set, attrname,
61 expected_score)) {
62 return TRUE;
63 }
64 }
65
66 if (!pcmk__strcase_any_of(type, "ping", "pingd", NULL)) {
67 continue;
68 }
69
70 params = pe_rsc_params(rsc, node, data_set);
71 name = g_hash_table_lookup(params, "name");
72
73 if (name == NULL) {
74 name = "pingd";
75 }
76
77 /* To identify the resource with the attribute name. */
78 if (pcmk__str_eq(name, attrname, pcmk__str_casei)) {
79 int host_list_num = 0;
80 const char *hosts = g_hash_table_lookup(params, "host_list");
81 const char *multiplier = g_hash_table_lookup(params, "multiplier");
82 int multiplier_i;
83
84 if (hosts) {
85 char **host_list = g_strsplit(hosts, " ", 0);
86 host_list_num = g_strv_length(host_list);
87 g_strfreev(host_list);
88 }
89
90 if ((multiplier == NULL)
91 || (pcmk__scan_min_int(multiplier, &multiplier_i,
92 INT_MIN) != pcmk_rc_ok)) {
93 /* The ocf:pacemaker:ping resource agent defaults multiplier to
94 * 1. The agent currently does not handle invalid text, but it
95 * should, and this would be a reasonable choice ...
96 */
97 multiplier_i = 1;
98 }
99 *expected_score = host_list_num * multiplier_i;
100
101 return TRUE;
102 }
103 }
104 return FALSE;
105}
106
107static GList *
108filter_attr_list(GList *attr_list, char *name)
109{
110 int i;
111 const char *filt_str[] = FILTER_STR;
112
113 CRM_CHECK(name != NULL, return attr_list);
114
115 /* filtering automatic attributes */
116 for (i = 0; filt_str[i] != NULL; i++) {
117 if (g_str_has_prefix(name, filt_str[i])) {
118 return attr_list;
119 }
120 }
121
122 return g_list_insert_sorted(attr_list, name, compare_attribute);
123}
124
125static GList *
126get_operation_list(xmlNode *rsc_entry) {
127 GList *op_list = NULL;
128 xmlNode *rsc_op = NULL;
129
130 for (rsc_op = pcmk__xe_first_child(rsc_entry); rsc_op != NULL;
131 rsc_op = pcmk__xe_next(rsc_op)) {
132 const char *task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
133 const char *interval_ms_s = crm_element_value(rsc_op,
135 const char *op_rc = crm_element_value(rsc_op, XML_LRM_ATTR_RC);
136 int op_rc_i;
137
138 pcmk__scan_min_int(op_rc, &op_rc_i, 0);
139
140 /* Display 0-interval monitors as "probe" */
141 if (pcmk__str_eq(task, CRMD_ACTION_STATUS, pcmk__str_casei)
142 && pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches | pcmk__str_casei)) {
143 task = "probe";
144 }
145
146 /* Ignore notifies and some probes */
147 if (pcmk__str_eq(task, CRMD_ACTION_NOTIFY, pcmk__str_casei) || (pcmk__str_eq(task, "probe", pcmk__str_casei) && (op_rc_i == 7))) {
148 continue;
149 }
150
151 if (pcmk__str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, pcmk__str_none)) {
152 op_list = g_list_append(op_list, rsc_op);
153 }
154 }
155
156 op_list = g_list_sort(op_list, sort_op_by_callid);
157 return op_list;
158}
159
160static void
161add_dump_node(gpointer key, gpointer value, gpointer user_data)
162{
163 xmlNodePtr node = user_data;
164 pcmk_create_xml_text_node(node, (const char *) key, (const char *) value);
165}
166
167static void
168append_dump_text(gpointer key, gpointer value, gpointer user_data)
169{
170 char **dump_text = user_data;
171 char *new_text = crm_strdup_printf("%s %s=%s",
172 *dump_text, (char *)key, (char *)value);
173
174 free(*dump_text);
175 *dump_text = new_text;
176}
177
178static char *
179failed_action_string(xmlNodePtr xml_op) {
180 const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
181 int rc;
182 int status;
183 const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
184
185 time_t last_change = 0;
186
189 &status, 0);
190
192 &last_change) == pcmk_ok) {
193 crm_time_t *crm_when = crm_time_new(NULL);
194 char *time_s = NULL;
195 char *buf = NULL;
196
197 crm_time_set_timet(crm_when, &last_change);
199
200 buf = crm_strdup_printf("%s on %s '%s' (%d): call=%s, status='%s', "
201 "exitreason='%s', " XML_RSC_OP_LAST_CHANGE
202 "='%s', queued=%sms, exec=%sms",
203 op_key ? op_key : ID(xml_op),
205 services_ocf_exitcode_str(rc), rc,
207 services_lrm_status_str(status),
208 exit_reason ? exit_reason : "none",
209 time_s,
212
213 crm_time_free(crm_when);
214 free(time_s);
215 return buf;
216 } else {
217 return crm_strdup_printf("%s on %s '%s' (%d): call=%s, status=%s, exitreason='%s'",
218 op_key ? op_key : ID(xml_op),
220 services_ocf_exitcode_str(rc), rc,
222 services_lrm_status_str(status),
223 exit_reason ? exit_reason : "none");
224 }
225}
226
227static const char *
228get_cluster_stack(pe_working_set_t *data_set)
229{
230 xmlNode *stack = get_xpath_object("//nvpair[@name='cluster-infrastructure']",
231 data_set->input, LOG_DEBUG);
232 return stack? crm_element_value(stack, XML_NVPAIR_ATTR_VALUE) : "unknown";
233}
234
235static char *
236last_changed_string(const char *last_written, const char *user,
237 const char *client, const char *origin) {
238 if (last_written != NULL || user != NULL || client != NULL || origin != NULL) {
239 return crm_strdup_printf("%s%s%s%s%s%s%s",
240 last_written ? last_written : "",
241 user ? " by " : "",
242 user ? user : "",
243 client ? " via " : "",
244 client ? client : "",
245 origin ? " on " : "",
246 origin ? origin : "");
247 } else {
248 return strdup("");
249 }
250}
251
252static char *
253op_history_string(xmlNode *xml_op, const char *task, const char *interval_ms_s,
254 int rc, gboolean print_timing) {
255 const char *call = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
256 char *interval_str = NULL;
257 char *buf = NULL;
258
259 if (interval_ms_s && !pcmk__str_eq(interval_ms_s, "0", pcmk__str_casei)) {
260 char *pair = pcmk__format_nvpair("interval", interval_ms_s, "ms");
261 interval_str = crm_strdup_printf(" %s", pair);
262 free(pair);
263 }
264
265 if (print_timing) {
266 char *last_change_str = NULL;
267 char *exec_str = NULL;
268 char *queue_str = NULL;
269
270 const char *value = NULL;
271
272 time_t epoch = 0;
273
275 && (epoch > 0)) {
277
278 last_change_str = crm_strdup_printf(" %s", time);
279 free(time);
280 }
281
282 value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
283 if (value) {
284 char *pair = pcmk__format_nvpair(XML_RSC_OP_T_EXEC, value, "ms");
285 exec_str = crm_strdup_printf(" %s", pair);
286 free(pair);
287 }
288
289 value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
290 if (value) {
291 char *pair = pcmk__format_nvpair(XML_RSC_OP_T_QUEUE, value, "ms");
292 queue_str = crm_strdup_printf(" %s", pair);
293 free(pair);
294 }
295
296 buf = crm_strdup_printf("(%s) %s:%s%s%s%s rc=%d (%s)", call, task,
297 interval_str ? interval_str : "",
298 last_change_str ? last_change_str : "",
299 exec_str ? exec_str : "",
300 queue_str ? queue_str : "",
301 rc, services_ocf_exitcode_str(rc));
302
303 if (last_change_str) {
304 free(last_change_str);
305 }
306
307 if (exec_str) {
308 free(exec_str);
309 }
310
311 if (queue_str) {
312 free(queue_str);
313 }
314 } else {
315 buf = crm_strdup_printf("(%s) %s%s%s", call, task,
316 interval_str ? ":" : "",
317 interval_str ? interval_str : "");
318 }
319
320 if (interval_str) {
321 free(interval_str);
322 }
323
324 return buf;
325}
326
327static char *
328resource_history_string(pe_resource_t *rsc, const char *rsc_id, gboolean all,
329 int failcount, time_t last_failure) {
330 char *buf = NULL;
331
332 if (rsc == NULL) {
333 buf = crm_strdup_printf("%s: orphan", rsc_id);
334 } else if (all || failcount || last_failure > 0) {
335 char *failcount_s = NULL;
336 char *lastfail_s = NULL;
337
338 if (failcount > 0) {
339 failcount_s = crm_strdup_printf(" %s=%d", PCMK__FAIL_COUNT_PREFIX,
340 failcount);
341 } else {
342 failcount_s = strdup("");
343 }
344 if (last_failure > 0) {
345 lastfail_s = crm_strdup_printf(" %s='%s'",
347 pcmk__epoch2str(&last_failure));
348 }
349
350 buf = crm_strdup_printf("%s: migration-threshold=%d%s%s",
351 rsc_id, rsc->migration_threshold, failcount_s,
352 lastfail_s? lastfail_s : "");
353 free(failcount_s);
354 free(lastfail_s);
355 } else {
356 buf = crm_strdup_printf("%s:", rsc_id);
357 }
358
359 return buf;
360}
361
362PCMK__OUTPUT_ARGS("cluster-summary", "pe_working_set_t *", "unsigned int", "unsigned int")
363static int
364cluster_summary(pcmk__output_t *out, va_list args) {
365 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
366 unsigned int section_opts = va_arg(args, unsigned int);
367 unsigned int show_opts = va_arg(args, unsigned int);
368
369 int rc = pcmk_rc_no_output;
370 const char *stack_s = get_cluster_stack(data_set);
371
372 if (pcmk_is_set(section_opts, pcmk_section_stack)) {
373 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
374 out->message(out, "cluster-stack", stack_s);
375 }
376
377 /* Always print DC if none, even if not requested */
378 if (data_set->dc_node == NULL || pcmk_is_set(section_opts, pcmk_section_dc)) {
379 xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']",
380 data_set->input, LOG_DEBUG);
381 const char *dc_version_s = dc_version?
383 : NULL;
384 const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
385 char *dc_name = data_set->dc_node ? pe__node_display_name(data_set->dc_node, pcmk_is_set(show_opts, pcmk_show_node_id)) : NULL;
386
387 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
388 out->message(out, "cluster-dc", data_set->dc_node, quorum, dc_version_s, dc_name);
389 free(dc_name);
390 }
391
392 if (pcmk_is_set(section_opts, pcmk_section_times)) {
393 const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN);
394 const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER);
395 const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT);
396 const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG);
397
398 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
399 out->message(out, "cluster-times", last_written, user, client, origin);
400 }
401
402 if (pcmk_is_set(section_opts, pcmk_section_counts)) {
403 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
404 out->message(out, "cluster-counts", g_list_length(data_set->nodes),
405 data_set->ninstances, data_set->disabled_resources,
406 data_set->blocked_resources);
407 }
408
409 if (pcmk_is_set(section_opts, pcmk_section_options)) {
410 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
411 out->message(out, "cluster-options", data_set);
412 }
413
415
416 if (out->message(out, "maint-mode", data_set->flags) == pcmk_rc_ok) {
417 rc = pcmk_rc_ok;
418 }
419
420 return rc;
421}
422
423PCMK__OUTPUT_ARGS("cluster-summary", "pe_working_set_t *", "unsigned int", "unsigned int")
424static int
425cluster_summary_html(pcmk__output_t *out, va_list args) {
426 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
427 unsigned int section_opts = va_arg(args, unsigned int);
428 unsigned int show_opts = va_arg(args, unsigned int);
429
430 int rc = pcmk_rc_no_output;
431 const char *stack_s = get_cluster_stack(data_set);
432
433 if (pcmk_is_set(section_opts, pcmk_section_stack)) {
434 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
435 out->message(out, "cluster-stack", stack_s);
436 }
437
438 /* Always print DC if none, even if not requested */
439 if (data_set->dc_node == NULL || pcmk_is_set(section_opts, pcmk_section_dc)) {
440 xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']",
441 data_set->input, LOG_DEBUG);
442 const char *dc_version_s = dc_version?
444 : NULL;
445 const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
446 char *dc_name = data_set->dc_node ? pe__node_display_name(data_set->dc_node, pcmk_is_set(show_opts, pcmk_show_node_id)) : NULL;
447
448 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
449 out->message(out, "cluster-dc", data_set->dc_node, quorum, dc_version_s, dc_name);
450 free(dc_name);
451 }
452
453 if (pcmk_is_set(section_opts, pcmk_section_times)) {
454 const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN);
455 const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER);
456 const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT);
457 const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG);
458
459 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
460 out->message(out, "cluster-times", last_written, user, client, origin);
461 }
462
463 if (pcmk_is_set(section_opts, pcmk_section_counts)) {
464 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
465 out->message(out, "cluster-counts", g_list_length(data_set->nodes),
466 data_set->ninstances, data_set->disabled_resources,
467 data_set->blocked_resources);
468 }
469
470 if (pcmk_is_set(section_opts, pcmk_section_options)) {
471 /* Kind of a hack - close the list we may have opened earlier in this
472 * function so we can put all the options into their own list. We
473 * only want to do this on HTML output, though.
474 */
476
477 out->begin_list(out, NULL, NULL, "Config Options");
478 out->message(out, "cluster-options", data_set);
479 }
480
482
483 if (out->message(out, "maint-mode", data_set->flags) == pcmk_rc_ok) {
484 rc = pcmk_rc_ok;
485 }
486
487 return rc;
488}
489
490char *
491pe__node_display_name(pe_node_t *node, bool print_detail)
492{
493 char *node_name;
494 const char *node_host = NULL;
495 const char *node_id = NULL;
496 int name_len;
497
498 CRM_ASSERT((node != NULL) && (node->details != NULL) && (node->details->uname != NULL));
499
500 /* Host is displayed only if this is a guest node */
501 if (pe__is_guest_node(node)) {
502 pe_node_t *host_node = pe__current_node(node->details->remote_rsc);
503
504 if (host_node && host_node->details) {
505 node_host = host_node->details->uname;
506 }
507 if (node_host == NULL) {
508 node_host = ""; /* so we at least get "uname@" to indicate guest */
509 }
510 }
511
512 /* Node ID is displayed if different from uname and detail is requested */
513 if (print_detail && !pcmk__str_eq(node->details->uname, node->details->id, pcmk__str_casei)) {
514 node_id = node->details->id;
515 }
516
517 /* Determine name length */
518 name_len = strlen(node->details->uname) + 1;
519 if (node_host) {
520 name_len += strlen(node_host) + 1; /* "@node_host" */
521 }
522 if (node_id) {
523 name_len += strlen(node_id) + 3; /* + " (node_id)" */
524 }
525
526 /* Allocate and populate display name */
527 node_name = malloc(name_len);
528 CRM_ASSERT(node_name != NULL);
529 strcpy(node_name, node->details->uname);
530 if (node_host) {
531 strcat(node_name, "@");
532 strcat(node_name, node_host);
533 }
534 if (node_id) {
535 strcat(node_name, " (");
536 strcat(node_name, node_id);
537 strcat(node_name, ")");
538 }
539 return node_name;
540}
541
542int
543pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name
544 , size_t pairs_count, ...)
545{
546 xmlNodePtr xml_node = NULL;
547 va_list args;
548
549 CRM_ASSERT(tag_name != NULL);
550
551 xml_node = pcmk__output_xml_peek_parent(out);
552 CRM_ASSERT(xml_node != NULL);
553 xml_node = is_list
554 ? create_xml_node(xml_node, tag_name)
555 : xmlNewChild(xml_node, NULL, (pcmkXmlStr) tag_name, NULL);
556
557 va_start(args, pairs_count);
558 while(pairs_count--) {
559 const char *param_name = va_arg(args, const char *);
560 const char *param_value = va_arg(args, const char *);
561 if (param_name && param_value) {
562 crm_xml_add(xml_node, param_name, param_value);
563 }
564 };
565 va_end(args);
566
567 if (is_list) {
568 pcmk__output_xml_push_parent(out, xml_node);
569 }
570 return pcmk_rc_ok;
571}
572
573static const char *
574role_desc(enum rsc_role_e role)
575{
576 if (role == RSC_ROLE_PROMOTED) {
577#ifdef PCMK__COMPAT_2_0
578 return "as " RSC_ROLE_PROMOTED_LEGACY_S " ";
579#else
580 return "in " RSC_ROLE_PROMOTED_S " role ";
581#endif
582 }
583 return "";
584}
585
586PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "unsigned int")
587static int
588ban_html(pcmk__output_t *out, va_list args) {
589 pe_node_t *pe_node = va_arg(args, pe_node_t *);
590 pe__location_t *location = va_arg(args, pe__location_t *);
591 unsigned int show_opts = va_arg(args, unsigned int);
592
593 char *node_name = pe__node_display_name(pe_node,
594 pcmk_is_set(show_opts, pcmk_show_node_id));
595 char *buf = crm_strdup_printf("%s\tprevents %s from running %son %s",
596 location->id, location->rsc_lh->id,
597 role_desc(location->role_filter), node_name);
598
599 pcmk__output_create_html_node(out, "li", NULL, NULL, buf);
600
601 free(node_name);
602 free(buf);
603 return pcmk_rc_ok;
604}
605
606PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "unsigned int")
607static int
608ban_text(pcmk__output_t *out, va_list args) {
609 pe_node_t *pe_node = va_arg(args, pe_node_t *);
610 pe__location_t *location = va_arg(args, pe__location_t *);
611 unsigned int show_opts = va_arg(args, unsigned int);
612
613 char *node_name = pe__node_display_name(pe_node,
614 pcmk_is_set(show_opts, pcmk_show_node_id));
615 out->list_item(out, NULL, "%s\tprevents %s from running %son %s",
616 location->id, location->rsc_lh->id,
617 role_desc(location->role_filter), node_name);
618
619 free(node_name);
620 return pcmk_rc_ok;
621}
622
623PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "unsigned int")
624static int
625ban_xml(pcmk__output_t *out, va_list args) {
626 pe_node_t *pe_node = va_arg(args, pe_node_t *);
627 pe__location_t *location = va_arg(args, pe__location_t *);
628 unsigned int show_opts G_GNUC_UNUSED = va_arg(args, unsigned int);
629
630 const char *promoted_only = pcmk__btoa(location->role_filter == RSC_ROLE_PROMOTED);
631 char *weight_s = pcmk__itoa(pe_node->weight);
632
634 "id", location->id,
635 "resource", location->rsc_lh->id,
636 "node", pe_node->details->uname,
637 "weight", weight_s,
638 "promoted-only", promoted_only,
639 /* This is a deprecated alias for
640 * promoted_only. Removing it will break
641 * backward compatibility of the API schema,
642 * which will require an API schema major
643 * version bump.
644 */
645 "master_only", promoted_only,
646 NULL);
647
648 free(weight_s);
649 return pcmk_rc_ok;
650}
651
652PCMK__OUTPUT_ARGS("ban-list", "pe_working_set_t *", "const char *", "GList *",
653 "unsigned int", "gboolean")
654static int
655ban_list(pcmk__output_t *out, va_list args) {
656 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
657 const char *prefix = va_arg(args, const char *);
658 GList *only_rsc = va_arg(args, GList *);
659 unsigned int show_opts = va_arg(args, unsigned int);
660 gboolean print_spacer = va_arg(args, gboolean);
661
662 GList *gIter, *gIter2;
663 int rc = pcmk_rc_no_output;
664
665 /* Print each ban */
666 for (gIter = data_set->placement_constraints; gIter != NULL; gIter = gIter->next) {
667 pe__location_t *location = gIter->data;
668
669 if (prefix != NULL && !g_str_has_prefix(location->id, prefix)) {
670 continue;
671 }
672
673 if (!pcmk__str_in_list(only_rsc, rsc_printable_id(location->rsc_lh), pcmk__str_none) &&
675 continue;
676 }
677
678 for (gIter2 = location->node_list_rh; gIter2 != NULL; gIter2 = gIter2->next) {
679 pe_node_t *node = (pe_node_t *) gIter2->data;
680
681 if (node->weight < 0) {
682 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Negative Location Constraints");
683 out->message(out, "ban", node, location, show_opts);
684 }
685 }
686 }
687
689 return rc;
690}
691
692PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
693static int
694cluster_counts_html(pcmk__output_t *out, va_list args) {
695 unsigned int nnodes = va_arg(args, unsigned int);
696 int nresources = va_arg(args, int);
697 int ndisabled = va_arg(args, int);
698 int nblocked = va_arg(args, int);
699
700 xmlNodePtr nodes_node = pcmk__output_create_xml_node(out, "li", NULL);
701 xmlNodePtr resources_node = pcmk__output_create_xml_node(out, "li", NULL);
702
703 char *nnodes_str = crm_strdup_printf("%d node%s configured",
704 nnodes, pcmk__plural_s(nnodes));
705
706 pcmk_create_html_node(nodes_node, "span", NULL, NULL, nnodes_str);
707 free(nnodes_str);
708
709 if (ndisabled && nblocked) {
710 char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
711 nresources, pcmk__plural_s(nresources),
712 ndisabled);
713 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
714 free(s);
715
716 pcmk_create_html_node(resources_node, "span", NULL, "bold", "DISABLED");
717
718 s = crm_strdup_printf(", %d ", nblocked);
719 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
720 free(s);
721
722 pcmk_create_html_node(resources_node, "span", NULL, "bold", "BLOCKED");
723 pcmk_create_html_node(resources_node, "span", NULL, NULL,
724 " from further action due to failure)");
725 } else if (ndisabled && !nblocked) {
726 char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
727 nresources, pcmk__plural_s(nresources),
728 ndisabled);
729 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
730 free(s);
731
732 pcmk_create_html_node(resources_node, "span", NULL, "bold", "DISABLED");
733 pcmk_create_html_node(resources_node, "span", NULL, NULL, ")");
734 } else if (!ndisabled && nblocked) {
735 char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
736 nresources, pcmk__plural_s(nresources),
737 nblocked);
738 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
739 free(s);
740
741 pcmk_create_html_node(resources_node, "span", NULL, "bold", "BLOCKED");
742 pcmk_create_html_node(resources_node, "span", NULL, NULL,
743 " from further action due to failure)");
744 } else {
745 char *s = crm_strdup_printf("%d resource instance%s configured",
746 nresources, pcmk__plural_s(nresources));
747 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
748 free(s);
749 }
750
751 return pcmk_rc_ok;
752}
753
754PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
755static int
756cluster_counts_text(pcmk__output_t *out, va_list args) {
757 unsigned int nnodes = va_arg(args, unsigned int);
758 int nresources = va_arg(args, int);
759 int ndisabled = va_arg(args, int);
760 int nblocked = va_arg(args, int);
761
762 out->list_item(out, NULL, "%d node%s configured",
763 nnodes, pcmk__plural_s(nnodes));
764
765 if (ndisabled && nblocked) {
766 out->list_item(out, NULL, "%d resource instance%s configured "
767 "(%d DISABLED, %d BLOCKED from "
768 "further action due to failure)",
769 nresources, pcmk__plural_s(nresources), ndisabled,
770 nblocked);
771 } else if (ndisabled && !nblocked) {
772 out->list_item(out, NULL, "%d resource instance%s configured "
773 "(%d DISABLED)",
774 nresources, pcmk__plural_s(nresources), ndisabled);
775 } else if (!ndisabled && nblocked) {
776 out->list_item(out, NULL, "%d resource instance%s configured "
777 "(%d BLOCKED from further action "
778 "due to failure)",
779 nresources, pcmk__plural_s(nresources), nblocked);
780 } else {
781 out->list_item(out, NULL, "%d resource instance%s configured",
782 nresources, pcmk__plural_s(nresources));
783 }
784
785 return pcmk_rc_ok;
786}
787
788PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
789static int
790cluster_counts_xml(pcmk__output_t *out, va_list args) {
791 unsigned int nnodes = va_arg(args, unsigned int);
792 int nresources = va_arg(args, int);
793 int ndisabled = va_arg(args, int);
794 int nblocked = va_arg(args, int);
795
796 xmlNodePtr nodes_node = pcmk__output_create_xml_node(out, "nodes_configured", NULL);
797 xmlNodePtr resources_node = pcmk__output_create_xml_node(out, "resources_configured", NULL);
798
799 char *s = pcmk__itoa(nnodes);
800 crm_xml_add(nodes_node, "number", s);
801 free(s);
802
803 s = pcmk__itoa(nresources);
804 crm_xml_add(resources_node, "number", s);
805 free(s);
806
807 s = pcmk__itoa(ndisabled);
808 crm_xml_add(resources_node, "disabled", s);
809 free(s);
810
811 s = pcmk__itoa(nblocked);
812 crm_xml_add(resources_node, "blocked", s);
813 free(s);
814
815 return pcmk_rc_ok;
816}
817
818PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
819static int
820cluster_dc_html(pcmk__output_t *out, va_list args) {
821 pe_node_t *dc = va_arg(args, pe_node_t *);
822 const char *quorum = va_arg(args, const char *);
823 const char *dc_version_s = va_arg(args, const char *);
824 char *dc_name = va_arg(args, char *);
825
826 xmlNodePtr node = pcmk__output_create_xml_node(out, "li", NULL);
827
828 pcmk_create_html_node(node, "span", NULL, "bold", "Current DC: ");
829
830 if (dc) {
831 if (crm_is_true(quorum)) {
832 char *buf = crm_strdup_printf("%s (version %s) - partition with quorum",
833 dc_name, dc_version_s ? dc_version_s : "unknown");
834 pcmk_create_html_node(node, "span", NULL, NULL, buf);
835 free(buf);
836 } else {
837 char *buf = crm_strdup_printf("%s (version %s) - partition",
838 dc_name, dc_version_s ? dc_version_s : "unknown");
839 pcmk_create_html_node(node, "span", NULL, NULL, buf);
840 free(buf);
841
842 pcmk_create_html_node(node, "span", NULL, "warning", "WITHOUT");
843 pcmk_create_html_node(node, "span", NULL, NULL, "quorum");
844 }
845 } else {
846 pcmk_create_html_node(node ,"span", NULL, "warning", "NONE");
847 }
848
849 return pcmk_rc_ok;
850}
851
852PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
853static int
854cluster_dc_text(pcmk__output_t *out, va_list args) {
855 pe_node_t *dc = va_arg(args, pe_node_t *);
856 const char *quorum = va_arg(args, const char *);
857 const char *dc_version_s = va_arg(args, const char *);
858 char *dc_name = va_arg(args, char *);
859
860 if (dc) {
861 out->list_item(out, "Current DC", "%s (version %s) - partition %s quorum",
862 dc_name, dc_version_s ? dc_version_s : "unknown",
863 crm_is_true(quorum) ? "with" : "WITHOUT");
864 } else {
865 out->list_item(out, "Current DC", "NONE");
866 }
867
868 return pcmk_rc_ok;
869}
870
871PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
872static int
873cluster_dc_xml(pcmk__output_t *out, va_list args) {
874 pe_node_t *dc = va_arg(args, pe_node_t *);
875 const char *quorum = va_arg(args, const char *);
876 const char *dc_version_s = va_arg(args, const char *);
877 char *dc_name G_GNUC_UNUSED = va_arg(args, char *);
878
879 if (dc) {
880 pcmk__output_create_xml_node(out, "current_dc",
881 "present", "true",
882 "version", dc_version_s ? dc_version_s : "",
883 "name", dc->details->uname,
884 "id", dc->details->id,
885 "with_quorum", pcmk__btoa(crm_is_true(quorum)),
886 NULL);
887 } else {
888 pcmk__output_create_xml_node(out, "current_dc",
889 "present", "false",
890 NULL);
891 }
892
893 return pcmk_rc_ok;
894}
895
896PCMK__OUTPUT_ARGS("maint-mode", "unsigned long long int")
897static int
898cluster_maint_mode_text(pcmk__output_t *out, va_list args) {
899 unsigned long long flags = va_arg(args, unsigned long long);
900
902 pcmk__formatted_printf(out, "\n *** Resource management is DISABLED ***\n");
903 pcmk__formatted_printf(out, " The cluster will not attempt to start, stop or recover services\n");
904 return pcmk_rc_ok;
906 pcmk__formatted_printf(out, "\n *** Resource management is DISABLED ***\n");
907 pcmk__formatted_printf(out, " The cluster will keep all resources stopped\n");
908 return pcmk_rc_ok;
909 } else {
910 return pcmk_rc_no_output;
911 }
912}
913
914PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
915static int
916cluster_options_html(pcmk__output_t *out, va_list args) {
917 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
918
919 out->list_item(out, NULL, "STONITH of failed nodes %s",
920 pcmk_is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
921
922 out->list_item(out, NULL, "Cluster is %s",
923 pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
924
925 switch (data_set->no_quorum_policy) {
926 case no_quorum_freeze:
927 out->list_item(out, NULL, "No quorum policy: Freeze resources");
928 break;
929
930 case no_quorum_stop:
931 out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
932 break;
933
934 case no_quorum_demote:
935 out->list_item(out, NULL, "No quorum policy: Demote promotable "
936 "resources and stop all other resources");
937 break;
938
939 case no_quorum_ignore:
940 out->list_item(out, NULL, "No quorum policy: Ignore");
941 break;
942
944 out->list_item(out, NULL, "No quorum policy: Suicide");
945 break;
946 }
947
949 xmlNodePtr node = pcmk__output_create_xml_node(out, "li", NULL);
950
951 pcmk_create_html_node(node, "span", NULL, NULL, "Resource management: ");
952 pcmk_create_html_node(node, "span", NULL, "bold", "DISABLED");
953 pcmk_create_html_node(node, "span", NULL, NULL,
954 " (the cluster will not attempt to start, stop, or recover services)");
955 } else if (pcmk_is_set(data_set->flags, pe_flag_stop_everything)) {
956 xmlNodePtr node = pcmk__output_create_xml_node(out, "li", NULL);
957
958 pcmk_create_html_node(node, "span", NULL, NULL, "Resource management: ");
959 pcmk_create_html_node(node, "span", NULL, "bold", "STOPPED");
960 pcmk_create_html_node(node, "span", NULL, NULL,
961 " (the cluster will keep all resources stopped)");
962 } else {
963 out->list_item(out, NULL, "Resource management: enabled");
964 }
965
966 return pcmk_rc_ok;
967}
968
969PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
970static int
971cluster_options_log(pcmk__output_t *out, va_list args) {
972 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
973
975 return out->info(out, "Resource management is DISABLED. The cluster will not attempt to start, stop or recover services.");
976 } else if (pcmk_is_set(data_set->flags, pe_flag_stop_everything)) {
977 return out->info(out, "Resource management is DISABLED. The cluster has stopped all resources.");
978 } else {
979 return pcmk_rc_no_output;
980 }
981}
982
983PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
984static int
985cluster_options_text(pcmk__output_t *out, va_list args) {
986 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
987
988 out->list_item(out, NULL, "STONITH of failed nodes %s",
989 pcmk_is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
990
991 out->list_item(out, NULL, "Cluster is %s",
992 pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
993
994 switch (data_set->no_quorum_policy) {
995 case no_quorum_freeze:
996 out->list_item(out, NULL, "No quorum policy: Freeze resources");
997 break;
998
999 case no_quorum_stop:
1000 out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
1001 break;
1002
1003 case no_quorum_demote:
1004 out->list_item(out, NULL, "No quorum policy: Demote promotable "
1005 "resources and stop all other resources");
1006 break;
1007
1008 case no_quorum_ignore:
1009 out->list_item(out, NULL, "No quorum policy: Ignore");
1010 break;
1011
1012 case no_quorum_suicide:
1013 out->list_item(out, NULL, "No quorum policy: Suicide");
1014 break;
1015 }
1016
1017 return pcmk_rc_ok;
1018}
1019
1020PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
1021static int
1022cluster_options_xml(pcmk__output_t *out, va_list args) {
1023 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1024
1025 const char *no_quorum_policy = NULL;
1026 char *stonith_timeout_str = pcmk__itoa(data_set->stonith_timeout);
1027 char *priority_fencing_delay_str = pcmk__itoa(data_set->priority_fencing_delay * 1000);
1028
1029 switch (data_set->no_quorum_policy) {
1030 case no_quorum_freeze:
1031 no_quorum_policy = "freeze";
1032 break;
1033
1034 case no_quorum_stop:
1035 no_quorum_policy = "stop";
1036 break;
1037
1038 case no_quorum_demote:
1039 no_quorum_policy = "demote";
1040 break;
1041
1042 case no_quorum_ignore:
1043 no_quorum_policy = "ignore";
1044 break;
1045
1046 case no_quorum_suicide:
1047 no_quorum_policy = "suicide";
1048 break;
1049 }
1050
1051 pcmk__output_create_xml_node(out, "cluster_options",
1052 "stonith-enabled", pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)),
1053 "symmetric-cluster", pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster)),
1054 "no-quorum-policy", no_quorum_policy,
1055 "maintenance-mode", pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)),
1056 "stop-all-resources", pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_stop_everything)),
1057 "stonith-timeout-ms", stonith_timeout_str,
1058 "priority-fencing-delay-ms", priority_fencing_delay_str,
1059 NULL);
1060 free(stonith_timeout_str);
1061 free(priority_fencing_delay_str);
1062
1063 return pcmk_rc_ok;
1064}
1065
1066PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1067static int
1068cluster_stack_html(pcmk__output_t *out, va_list args) {
1069 const char *stack_s = va_arg(args, const char *);
1070
1071 xmlNodePtr node = pcmk__output_create_xml_node(out, "li", NULL);
1072
1073 pcmk_create_html_node(node, "span", NULL, "bold", "Stack: ");
1074 pcmk_create_html_node(node, "span", NULL, NULL, stack_s);
1075
1076 return pcmk_rc_ok;
1077}
1078
1079PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1080static int
1081cluster_stack_text(pcmk__output_t *out, va_list args) {
1082 const char *stack_s = va_arg(args, const char *);
1083
1084 out->list_item(out, "Stack", "%s", stack_s);
1085 return pcmk_rc_ok;
1086}
1087
1088PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1089static int
1090cluster_stack_xml(pcmk__output_t *out, va_list args) {
1091 const char *stack_s = va_arg(args, const char *);
1092
1093 pcmk__output_create_xml_node(out, "stack",
1094 "type", stack_s,
1095 NULL);
1096
1097 return pcmk_rc_ok;
1098}
1099
1100PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1101static int
1102cluster_times_html(pcmk__output_t *out, va_list args) {
1103 const char *last_written = va_arg(args, const char *);
1104 const char *user = va_arg(args, const char *);
1105 const char *client = va_arg(args, const char *);
1106 const char *origin = va_arg(args, const char *);
1107
1108 xmlNodePtr updated_node = pcmk__output_create_xml_node(out, "li", NULL);
1109 xmlNodePtr changed_node = pcmk__output_create_xml_node(out, "li", NULL);
1110
1111 char *buf = last_changed_string(last_written, user, client, origin);
1112
1113 pcmk_create_html_node(updated_node, "span", NULL, "bold", "Last updated: ");
1114 pcmk_create_html_node(updated_node, "span", NULL, NULL,
1115 pcmk__epoch2str(NULL));
1116
1117 pcmk_create_html_node(changed_node, "span", NULL, "bold", "Last change: ");
1118 pcmk_create_html_node(changed_node, "span", NULL, NULL, buf);
1119
1120 free(buf);
1121 return pcmk_rc_ok;
1122}
1123
1124PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1125static int
1126cluster_times_xml(pcmk__output_t *out, va_list args) {
1127 const char *last_written = va_arg(args, const char *);
1128 const char *user = va_arg(args, const char *);
1129 const char *client = va_arg(args, const char *);
1130 const char *origin = va_arg(args, const char *);
1131
1132 pcmk__output_create_xml_node(out, "last_update",
1133 "time", pcmk__epoch2str(NULL),
1134 NULL);
1135 pcmk__output_create_xml_node(out, "last_change",
1136 "time", last_written ? last_written : "",
1137 "user", user ? user : "",
1138 "client", client ? client : "",
1139 "origin", origin ? origin : "",
1140 NULL);
1141
1142 return pcmk_rc_ok;
1143}
1144
1145PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1146static int
1147cluster_times_text(pcmk__output_t *out, va_list args) {
1148 const char *last_written = va_arg(args, const char *);
1149 const char *user = va_arg(args, const char *);
1150 const char *client = va_arg(args, const char *);
1151 const char *origin = va_arg(args, const char *);
1152
1153 char *buf = last_changed_string(last_written, user, client, origin);
1154
1155 out->list_item(out, "Last updated", "%s", pcmk__epoch2str(NULL));
1156 out->list_item(out, "Last change", " %s", buf);
1157
1158 free(buf);
1159 return pcmk_rc_ok;
1160}
1161
1162PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
1163static int
1164failed_action_text(pcmk__output_t *out, va_list args) {
1165 xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
1166
1167 char *s = failed_action_string(xml_op);
1168
1169 out->list_item(out, NULL, "%s", s);
1170 free(s);
1171 return pcmk_rc_ok;
1172}
1173
1174PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
1175static int
1176failed_action_xml(pcmk__output_t *out, va_list args) {
1177 xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
1178
1179 const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
1180 int rc;
1181 int status;
1182 const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
1183
1184 time_t epoch = 0;
1185 char *rc_s = NULL;
1186 char *reason_s = crm_xml_escape(exit_reason ? exit_reason : "none");
1187 xmlNodePtr node = NULL;
1188
1191 &status, 0);
1192
1193 rc_s = pcmk__itoa(rc);
1194 node = pcmk__output_create_xml_node(out, "failure",
1195 (op_key == NULL)? "id" : "op_key",
1196 (op_key == NULL)? ID(xml_op) : op_key,
1197 "node", crm_element_value(xml_op, XML_ATTR_UNAME),
1198 "exitstatus", services_ocf_exitcode_str(rc),
1199 "exitreason", reason_s,
1200 "exitcode", rc_s,
1201 "call", crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
1202 "status", services_lrm_status_str(status),
1203 NULL);
1204 free(rc_s);
1205
1207 &epoch) == pcmk_ok) && (epoch > 0)) {
1208 guint interval_ms = 0;
1209 char *s = NULL;
1210 crm_time_t *crm_when = crm_time_new_undefined();
1211 char *rc_change = NULL;
1212
1213 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
1214 s = pcmk__itoa(interval_ms);
1215
1216 crm_time_set_timet(crm_when, &epoch);
1218
1220 "queued", crm_element_value(xml_op, XML_RSC_OP_T_QUEUE),
1221 "exec", crm_element_value(xml_op, XML_RSC_OP_T_EXEC),
1222 "interval", s,
1223 "task", crm_element_value(xml_op, XML_LRM_ATTR_TASK),
1224 NULL);
1225
1226 free(s);
1227 free(rc_change);
1228 crm_time_free(crm_when);
1229 }
1230
1231 free(reason_s);
1232 return pcmk_rc_ok;
1233}
1234
1235PCMK__OUTPUT_ARGS("failed-action-list", "pe_working_set_t *", "GList *",
1236 "GList *", "gboolean")
1237static int
1238failed_action_list(pcmk__output_t *out, va_list args) {
1239 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1240 GList *only_node = va_arg(args, GList *);
1241 GList *only_rsc = va_arg(args, GList *);
1242 gboolean print_spacer = va_arg(args, gboolean);
1243
1244 xmlNode *xml_op = NULL;
1245 int rc = pcmk_rc_no_output;
1246
1247 const char *id = NULL;
1248
1249 if (xmlChildElementCount(data_set->failed) == 0) {
1250 return rc;
1251 }
1252
1253 for (xml_op = pcmk__xml_first_child(data_set->failed); xml_op != NULL;
1254 xml_op = pcmk__xml_next(xml_op)) {
1255 char *rsc = NULL;
1256
1258 continue;
1259 }
1260
1262 if (parse_op_key(id ? id : ID(xml_op), &rsc, NULL, NULL) == FALSE) {
1263 continue;
1264 }
1265
1266 if (!pcmk__str_in_list(only_rsc, rsc, pcmk__str_none)) {
1267 free(rsc);
1268 continue;
1269 }
1270
1271 free(rsc);
1272
1273 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Failed Resource Actions");
1274 out->message(out, "failed-action", xml_op);
1275 }
1276
1278 return rc;
1279}
1280
1281static void
1282status_node(pe_node_t *node, xmlNodePtr parent)
1283{
1284 if (node->details->standby_onfail && node->details->online) {
1285 pcmk_create_html_node(parent, "span", NULL, "standby", " standby (on-fail)");
1286 } else if (node->details->standby && node->details->online) {
1287 char *s = crm_strdup_printf(" standby%s", node->details->running_rsc ? " (with active resources)" : "");
1288 pcmk_create_html_node(parent, "span", NULL, " standby", s);
1289 free(s);
1290 } else if (node->details->standby) {
1291 pcmk_create_html_node(parent, "span", NULL, "offline", " OFFLINE (standby)");
1292 } else if (node->details->maintenance && node->details->online) {
1293 pcmk_create_html_node(parent, "span", NULL, "maint", " maintenance");
1294 } else if (node->details->maintenance) {
1295 pcmk_create_html_node(parent, "span", NULL, "offline", " OFFLINE (maintenance)");
1296 } else if (node->details->online) {
1297 pcmk_create_html_node(parent, "span", NULL, "online", " online");
1298 } else {
1299 pcmk_create_html_node(parent, "span", NULL, "offline", " OFFLINE");
1300 }
1301}
1302
1303PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1304 "GList *", "GList *")
1305static int
1306node_html(pcmk__output_t *out, va_list args) {
1307 pe_node_t *node = va_arg(args, pe_node_t *);
1308 unsigned int show_opts = va_arg(args, unsigned int);
1309 gboolean full = va_arg(args, gboolean);
1310 const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1311 GList *only_node = va_arg(args, GList *);
1312 GList *only_rsc = va_arg(args, GList *);
1313
1314 char *node_name = pe__node_display_name(node, pcmk_is_set(show_opts, pcmk_show_node_id));
1315
1316 if (full) {
1317 xmlNodePtr item_node;
1318
1319 if (pcmk_all_flags_set(show_opts, pcmk_show_brief | pcmk_show_rscs_by_node)) {
1320 GList *rscs = pe__filter_rsc_list(node->details->running_rsc, only_rsc);
1321
1322 out->begin_list(out, NULL, NULL, "Node: %s", node_name);
1323 item_node = pcmk__output_xml_create_parent(out, "li", NULL);
1324 pcmk_create_html_node(item_node, "span", NULL, NULL, "Status:");
1325 status_node(node, item_node);
1326
1327 if (rscs != NULL) {
1328 unsigned int new_show_opts = (show_opts | pcmk_show_rsc_only) & ~pcmk_show_inactive_rscs;
1329 out->begin_list(out, NULL, NULL, "Resources");
1330 pe__rscs_brief_output(out, rscs, new_show_opts);
1331 out->end_list(out);
1332 }
1333
1335 out->end_list(out);
1336
1337 } else if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
1338 GList *lpc2 = NULL;
1339 int rc = pcmk_rc_no_output;
1340
1341 out->begin_list(out, NULL, NULL, "Node: %s", node_name);
1342 item_node = pcmk__output_xml_create_parent(out, "li", NULL);
1343 pcmk_create_html_node(item_node, "span", NULL, NULL, "Status:");
1344 status_node(node, item_node);
1345
1346 for (lpc2 = node->details->running_rsc; lpc2 != NULL; lpc2 = lpc2->next) {
1347 pe_resource_t *rsc = (pe_resource_t *) lpc2->data;
1348 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Resources");
1349
1350 out->message(out, crm_map_element_name(rsc->xml), show_opts | pcmk_show_rsc_only,
1351 rsc, only_node, only_rsc);
1352 }
1353
1356 out->end_list(out);
1357
1358 } else {
1359 char *buf = crm_strdup_printf("Node: %s", node_name);
1360
1361 item_node = pcmk__output_create_xml_node(out, "li", NULL);
1362 pcmk_create_html_node(item_node, "span", NULL, NULL, buf);
1363 status_node(node, item_node);
1364
1365 free(buf);
1366 }
1367 } else {
1368 out->begin_list(out, NULL, NULL, "Node: %s", node_name);
1369 }
1370
1371 free(node_name);
1372 return pcmk_rc_ok;
1373}
1374
1375PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1376 "GList *", "GList *")
1377static int
1378node_text(pcmk__output_t *out, va_list args) {
1379 pe_node_t *node = va_arg(args, pe_node_t *);
1380 unsigned int show_opts = va_arg(args, unsigned int);
1381 gboolean full = va_arg(args, gboolean);
1382 const char *node_mode = va_arg(args, const char *);
1383 GList *only_node = va_arg(args, GList *);
1384 GList *only_rsc = va_arg(args, GList *);
1385
1386 if (full) {
1387 char *node_name = pe__node_display_name(node, pcmk_is_set(show_opts, pcmk_show_node_id));
1388 char *buf = NULL;
1389
1390 /* Print the node name and status */
1391 if (pe__is_guest_node(node)) {
1392 buf = crm_strdup_printf("GuestNode %s: %s", node_name, node_mode);
1393 } else if (pe__is_remote_node(node)) {
1394 buf = crm_strdup_printf("RemoteNode %s: %s", node_name, node_mode);
1395 } else {
1396 buf = crm_strdup_printf("Node %s: %s", node_name, node_mode);
1397 }
1398
1399 /* If we're grouping by node, print its resources */
1400 if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
1401 if (pcmk_is_set(show_opts, pcmk_show_brief)) {
1402 GList *rscs = pe__filter_rsc_list(node->details->running_rsc, only_rsc);
1403
1404 if (rscs != NULL) {
1405 unsigned int new_show_opts = (show_opts | pcmk_show_rsc_only) & ~pcmk_show_inactive_rscs;
1406 out->begin_list(out, NULL, NULL, "%s", buf);
1407 out->begin_list(out, NULL, NULL, "Resources");
1408
1409 pe__rscs_brief_output(out, rscs, new_show_opts);
1410
1411 out->end_list(out);
1412 out->end_list(out);
1413
1414 g_list_free(rscs);
1415 }
1416
1417 } else {
1418 GList *gIter2 = NULL;
1419
1420 out->begin_list(out, NULL, NULL, "%s", buf);
1421 out->begin_list(out, NULL, NULL, "Resources");
1422
1423 for (gIter2 = node->details->running_rsc; gIter2 != NULL; gIter2 = gIter2->next) {
1424 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
1425 out->message(out, crm_map_element_name(rsc->xml), show_opts | pcmk_show_rsc_only,
1426 rsc, only_node, only_rsc);
1427 }
1428
1429 out->end_list(out);
1430 out->end_list(out);
1431 }
1432 } else {
1433 out->list_item(out, NULL, "%s", buf);
1434 }
1435
1436 free(buf);
1437 free(node_name);
1438 } else {
1439 char *node_name = pe__node_display_name(node, pcmk_is_set(show_opts, pcmk_show_node_id));
1440 out->begin_list(out, NULL, NULL, "Node: %s", node_name);
1441 free(node_name);
1442 }
1443
1444 return pcmk_rc_ok;
1445}
1446
1447PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1448 "GList *", "GList *")
1449static int
1450node_xml(pcmk__output_t *out, va_list args) {
1451 pe_node_t *node = va_arg(args, pe_node_t *);
1452 unsigned int show_opts G_GNUC_UNUSED = va_arg(args, unsigned int);
1453 gboolean full = va_arg(args, gboolean);
1454 const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1455 GList *only_node = va_arg(args, GList *);
1456 GList *only_rsc = va_arg(args, GList *);
1457
1458 if (full) {
1459 const char *node_type = "unknown";
1460 char *length_s = pcmk__itoa(g_list_length(node->details->running_rsc));
1461
1462 switch (node->details->type) {
1463 case node_member:
1464 node_type = "member";
1465 break;
1466 case node_remote:
1467 node_type = "remote";
1468 break;
1469 case node_ping:
1470 node_type = "ping";
1471 break;
1472 }
1473 pe__name_and_nvpairs_xml(out, true, "node", 13,
1474 "name", node->details->uname,
1475 "id", node->details->id,
1476 "online", pcmk__btoa(node->details->online),
1477 "standby", pcmk__btoa(node->details->standby),
1478 "standby_onfail", pcmk__btoa(node->details->standby_onfail),
1479 "maintenance", pcmk__btoa(node->details->maintenance),
1480 "pending", pcmk__btoa(node->details->pending),
1481 "unclean", pcmk__btoa(node->details->unclean),
1482 "shutdown", pcmk__btoa(node->details->shutdown),
1483 "expected_up", pcmk__btoa(node->details->expected_up),
1484 "is_dc", pcmk__btoa(node->details->is_dc),
1485 "resources_running", length_s,
1486 "type", node_type);
1487
1488 if (pe__is_guest_node(node)) {
1489 xmlNodePtr xml_node = pcmk__output_xml_peek_parent(out);
1490 crm_xml_add(xml_node, "id_as_resource", node->details->remote_rsc->container->id);
1491 }
1492
1493 if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
1494 GList *lpc = NULL;
1495
1496 for (lpc = node->details->running_rsc; lpc != NULL; lpc = lpc->next) {
1497 pe_resource_t *rsc = (pe_resource_t *) lpc->data;
1498 out->message(out, crm_map_element_name(rsc->xml), show_opts | pcmk_show_rsc_only,
1499 rsc, only_node, only_rsc);
1500 }
1501 }
1502
1503 free(length_s);
1504
1505 out->end_list(out);
1506 } else {
1508 "name", node->details->uname,
1509 NULL);
1510 }
1511
1512 return pcmk_rc_ok;
1513}
1514
1515PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1516static int
1517node_attribute_text(pcmk__output_t *out, va_list args) {
1518 const char *name = va_arg(args, const char *);
1519 const char *value = va_arg(args, const char *);
1520 gboolean add_extra = va_arg(args, gboolean);
1521 int expected_score = va_arg(args, int);
1522
1523 if (add_extra) {
1524 int v;
1525
1526 if (value == NULL) {
1527 v = 0;
1528 } else {
1529 pcmk__scan_min_int(value, &v, INT_MIN);
1530 }
1531 if (v <= 0) {
1532 out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is lost", name, value);
1533 } else if (v < expected_score) {
1534 out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is degraded (Expected=%d)", name, value, expected_score);
1535 } else {
1536 out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1537 }
1538 } else {
1539 out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1540 }
1541
1542 return pcmk_rc_ok;
1543}
1544
1545PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1546static int
1547node_attribute_html(pcmk__output_t *out, va_list args) {
1548 const char *name = va_arg(args, const char *);
1549 const char *value = va_arg(args, const char *);
1550 gboolean add_extra = va_arg(args, gboolean);
1551 int expected_score = va_arg(args, int);
1552
1553 if (add_extra) {
1554 int v;
1555 char *s = crm_strdup_printf("%s: %s", name, value);
1556 xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li", NULL);
1557
1558 if (value == NULL) {
1559 v = 0;
1560 } else {
1561 pcmk__scan_min_int(value, &v, INT_MIN);
1562 }
1563
1564 pcmk_create_html_node(item_node, "span", NULL, NULL, s);
1565 free(s);
1566
1567 if (v <= 0) {
1568 pcmk_create_html_node(item_node, "span", NULL, "bold", "(connectivity is lost)");
1569 } else if (v < expected_score) {
1570 char *buf = crm_strdup_printf("(connectivity is degraded -- expected %d", expected_score);
1571 pcmk_create_html_node(item_node, "span", NULL, "bold", buf);
1572 free(buf);
1573 }
1574 } else {
1575 out->list_item(out, NULL, "%s: %s", name, value);
1576 }
1577
1578 return pcmk_rc_ok;
1579}
1580
1581PCMK__OUTPUT_ARGS("node-and-op", "pe_working_set_t *", "xmlNodePtr")
1582static int
1583node_and_op(pcmk__output_t *out, va_list args) {
1584 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1585 xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
1586
1587 pe_resource_t *rsc = NULL;
1588 gchar *node_str = NULL;
1589 char *last_change_str = NULL;
1590
1591 const char *op_rsc = crm_element_value(xml_op, "resource");
1592 const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
1593 int status;
1594 time_t last_change = 0;
1595
1597 &status, 0);
1598
1599 rsc = pe_find_resource(data_set->resources, op_rsc);
1600
1601 if (rsc) {
1602 pe_node_t *node = pe__current_node(rsc);
1603 const char *target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
1604 unsigned int show_opts = pcmk_show_rsc_only | pcmk_show_pending;
1605
1606 if (node == NULL) {
1607 node = rsc->pending_node;
1608 }
1609
1610 node_str = pcmk__native_output_string(rsc, rsc_printable_id(rsc), node,
1611 show_opts, target_role, false);
1612 } else {
1613 node_str = crm_strdup_printf("Unknown resource %s", op_rsc);
1614 }
1615
1617 &last_change) == pcmk_ok) {
1618 last_change_str = crm_strdup_printf(", %s=%s, exec=%sms",
1620 pcmk__trim(ctime(&last_change)),
1622 }
1623
1624 out->list_item(out, NULL, "%s: %s (node=%s, call=%s, rc=%s%s): %s",
1625 node_str, op_key ? op_key : ID(xml_op),
1629 last_change_str ? last_change_str : "",
1630 services_lrm_status_str(status));
1631
1632 g_free(node_str);
1633 free(last_change_str);
1634 return pcmk_rc_ok;
1635}
1636
1637PCMK__OUTPUT_ARGS("node-and-op", "pe_working_set_t *", "xmlNodePtr")
1638static int
1639node_and_op_xml(pcmk__output_t *out, va_list args) {
1640 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1641 xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
1642
1643 pe_resource_t *rsc = NULL;
1644 const char *op_rsc = crm_element_value(xml_op, "resource");
1645 const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
1646 int status;
1647 time_t last_change = 0;
1648 xmlNode *node = NULL;
1649
1651 &status, 0);
1652 node = pcmk__output_create_xml_node(out, "operation",
1653 "op", op_key ? op_key : ID(xml_op),
1654 "node", crm_element_value(xml_op, XML_ATTR_UNAME),
1655 "call", crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
1656 "rc", crm_element_value(xml_op, XML_LRM_ATTR_RC),
1657 "status", services_lrm_status_str(status),
1658 NULL);
1659
1660 rsc = pe_find_resource(data_set->resources, op_rsc);
1661
1662 if (rsc) {
1663 const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1664 const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
1665 char *agent_tuple = NULL;
1666
1667 agent_tuple = crm_strdup_printf("%s:%s:%s", class,
1669 kind);
1670
1671 pcmk__xe_set_props(node, "rsc", rsc_printable_id(rsc),
1672 "agent", agent_tuple,
1673 NULL);
1674 free(agent_tuple);
1675 }
1676
1678 &last_change) == pcmk_ok) {
1680 pcmk__trim(ctime(&last_change)),
1682 NULL);
1683 }
1684
1685 return pcmk_rc_ok;
1686}
1687
1688PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1689static int
1690node_attribute_xml(pcmk__output_t *out, va_list args) {
1691 const char *name = va_arg(args, const char *);
1692 const char *value = va_arg(args, const char *);
1693 gboolean add_extra = va_arg(args, gboolean);
1694 int expected_score = va_arg(args, int);
1695
1696 xmlNodePtr node = pcmk__output_create_xml_node(out, "attribute",
1697 "name", name,
1698 "value", value,
1699 NULL);
1700
1701 if (add_extra) {
1702 char *buf = pcmk__itoa(expected_score);
1703 crm_xml_add(node, "expected", buf);
1704 free(buf);
1705 }
1706
1707 return pcmk_rc_ok;
1708}
1709
1710PCMK__OUTPUT_ARGS("node-attribute-list", "pe_working_set_t *", "unsigned int",
1711 "gboolean", "GList *", "GList *")
1712static int
1713node_attribute_list(pcmk__output_t *out, va_list args) {
1714 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1715 unsigned int show_opts = va_arg(args, unsigned int);
1716 gboolean print_spacer = va_arg(args, gboolean);
1717 GList *only_node = va_arg(args, GList *);
1718 GList *only_rsc = va_arg(args, GList *);
1719
1720 int rc = pcmk_rc_no_output;
1721
1722 /* Display each node's attributes */
1723 for (GList *gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1724 pe_node_t *node = gIter->data;
1725
1726 GList *attr_list = NULL;
1727 GHashTableIter iter;
1728 gpointer key;
1729
1730 if (!node || !node->details || !node->details->online) {
1731 continue;
1732 }
1733
1734 g_hash_table_iter_init(&iter, node->details->attrs);
1735 while (g_hash_table_iter_next (&iter, &key, NULL)) {
1736 attr_list = filter_attr_list(attr_list, key);
1737 }
1738
1739 if (attr_list == NULL) {
1740 continue;
1741 }
1742
1743 if (!pcmk__str_in_list(only_node, node->details->uname, pcmk__str_casei)) {
1744 g_list_free(attr_list);
1745 continue;
1746 }
1747
1748 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc, "Node Attributes");
1749
1750 out->message(out, "node", node, show_opts, FALSE, NULL, only_node, only_rsc);
1751
1752 for (GList *aIter = attr_list; aIter != NULL; aIter = aIter->next) {
1753 const char *name = aIter->data;
1754 const char *value = NULL;
1755 int expected_score = 0;
1756 gboolean add_extra = FALSE;
1757
1758 value = pe_node_attribute_raw(node, name);
1759
1760 add_extra = add_extra_info(node, node->details->running_rsc,
1761 data_set, name, &expected_score);
1762
1763 /* Print attribute name and value */
1764 out->message(out, "node-attribute", name, value, add_extra,
1765 expected_score);
1766 }
1767
1768 g_list_free(attr_list);
1769 out->end_list(out);
1770 }
1771
1773 return rc;
1774}
1775
1776PCMK__OUTPUT_ARGS("node-capacity", "pe_node_t *", "const char *")
1777static int
1778node_capacity(pcmk__output_t *out, va_list args)
1779{
1780 pe_node_t *node = va_arg(args, pe_node_t *);
1781 const char *comment = va_arg(args, const char *);
1782
1783 char *dump_text = crm_strdup_printf("%s: %s capacity:",
1784 comment, node->details->uname);
1785
1786 g_hash_table_foreach(node->details->utilization, append_dump_text, &dump_text);
1787 out->list_item(out, NULL, "%s", dump_text);
1788 free(dump_text);
1789
1790 return pcmk_rc_ok;
1791}
1792
1793PCMK__OUTPUT_ARGS("node-capacity", "pe_node_t *", "const char *")
1794static int
1795node_capacity_xml(pcmk__output_t *out, va_list args)
1796{
1797 pe_node_t *node = va_arg(args, pe_node_t *);
1798 const char *comment = va_arg(args, const char *);
1799
1800 xmlNodePtr xml_node = pcmk__output_create_xml_node(out, "capacity",
1801 "node", node->details->uname,
1802 "comment", comment,
1803 NULL);
1804 g_hash_table_foreach(node->details->utilization, add_dump_node, xml_node);
1805
1806 return pcmk_rc_ok;
1807}
1808
1809PCMK__OUTPUT_ARGS("node-history-list", "pe_working_set_t *", "pe_node_t *", "xmlNodePtr",
1810 "GList *", "GList *", "unsigned int", "unsigned int")
1811static int
1812node_history_list(pcmk__output_t *out, va_list args) {
1813 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1814 pe_node_t *node = va_arg(args, pe_node_t *);
1815 xmlNode *node_state = va_arg(args, xmlNode *);
1816 GList *only_node = va_arg(args, GList *);
1817 GList *only_rsc = va_arg(args, GList *);
1818 unsigned int section_opts = va_arg(args, unsigned int);
1819 unsigned int show_opts = va_arg(args, unsigned int);
1820
1821 xmlNode *lrm_rsc = NULL;
1822 xmlNode *rsc_entry = NULL;
1823 int rc = pcmk_rc_no_output;
1824
1825 lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
1826 lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE);
1827
1828 /* Print history of each of the node's resources */
1829 for (rsc_entry = first_named_child(lrm_rsc, XML_LRM_TAG_RESOURCE);
1830 rsc_entry != NULL; rsc_entry = crm_next_same_xml(rsc_entry)) {
1831 const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID);
1832 pe_resource_t *rsc = pe_find_resource(data_set->resources, rsc_id);
1833
1834 /* We can't use is_filtered here to filter group resources. For is_filtered,
1835 * we have to decide whether to check the parent or not. If we check the
1836 * parent, all elements of a group will always be printed because that's how
1837 * is_filtered works for groups. If we do not check the parent, sometimes
1838 * this will filter everything out.
1839 *
1840 * For other resource types, is_filtered is okay.
1841 */
1842 if (uber_parent(rsc)->variant == pe_group) {
1843 if (!pcmk__str_in_list(only_rsc, rsc_printable_id(rsc), pcmk__str_none) &&
1845 continue;
1846 }
1847 } else {
1848 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1849 continue;
1850 }
1851 }
1852
1853 if (!pcmk_is_set(section_opts, pcmk_section_operations)) {
1854 time_t last_failure = 0;
1855 int failcount = pe_get_failcount(node, rsc, &last_failure, pe_fc_default,
1856 NULL, data_set);
1857
1858 if (failcount <= 0) {
1859 continue;
1860 }
1861
1862 if (rc == pcmk_rc_no_output) {
1863 rc = pcmk_rc_ok;
1864 out->message(out, "node", node, show_opts, FALSE, NULL, only_node, only_rsc);
1865 }
1866
1867 out->message(out, "resource-history", rsc, rsc_id, FALSE,
1868 failcount, last_failure, FALSE);
1869 } else {
1870 GList *op_list = get_operation_list(rsc_entry);
1871 pe_resource_t *rsc = pe_find_resource(data_set->resources,
1872 crm_element_value(rsc_entry, XML_ATTR_ID));
1873
1874 if (op_list == NULL) {
1875 continue;
1876 }
1877
1878 if (rc == pcmk_rc_no_output) {
1879 rc = pcmk_rc_ok;
1880 out->message(out, "node", node, show_opts, FALSE, NULL, only_node, only_rsc);
1881 }
1882
1883 out->message(out, "resource-operation-list", data_set, rsc, node,
1884 op_list, show_opts);
1885 }
1886 }
1887
1889 return rc;
1890}
1891
1892PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int")
1893static int
1894node_list_html(pcmk__output_t *out, va_list args) {
1895 GList *nodes = va_arg(args, GList *);
1896 GList *only_node = va_arg(args, GList *);
1897 GList *only_rsc = va_arg(args, GList *);
1898 unsigned int show_opts = va_arg(args, unsigned int);
1899
1900 int rc = pcmk_rc_no_output;
1901
1902 for (GList *gIter = nodes; gIter != NULL; gIter = gIter->next) {
1903 pe_node_t *node = (pe_node_t *) gIter->data;
1904
1905 if (!pcmk__str_in_list(only_node, node->details->uname, pcmk__str_casei)) {
1906 continue;
1907 }
1908
1909 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Node List");
1910
1911 out->message(out, "node", node, show_opts, TRUE, NULL, only_node, only_rsc);
1912 }
1913
1915 return rc;
1916}
1917
1918PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int")
1919static int
1920node_list_text(pcmk__output_t *out, va_list args) {
1921 GList *nodes = va_arg(args, GList *);
1922 GList *only_node = va_arg(args, GList *);
1923 GList *only_rsc = va_arg(args, GList *);
1924 unsigned int show_opts = va_arg(args, unsigned int);
1925
1926 /* space-separated lists of node names */
1927 char *online_nodes = NULL;
1928 char *online_remote_nodes = NULL;
1929 char *online_guest_nodes = NULL;
1930 char *offline_nodes = NULL;
1931 char *offline_remote_nodes = NULL;
1932
1933 size_t online_nodes_len = 0;
1934 size_t online_remote_nodes_len = 0;
1935 size_t online_guest_nodes_len = 0;
1936 size_t offline_nodes_len = 0;
1937 size_t offline_remote_nodes_len = 0;
1938
1939 int rc = pcmk_rc_no_output;
1940
1941 for (GList *gIter = nodes; gIter != NULL; gIter = gIter->next) {
1942 pe_node_t *node = (pe_node_t *) gIter->data;
1943 const char *node_mode = NULL;
1944 char *node_name = pe__node_display_name(node, pcmk_is_set(show_opts, pcmk_show_node_id));
1945
1946 if (!pcmk__str_in_list(only_node, node->details->uname, pcmk__str_casei)) {
1947 free(node_name);
1948 continue;
1949 }
1950
1951 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Node List");
1952
1953 /* Get node mode */
1954 if (node->details->unclean) {
1955 if (node->details->online) {
1956 node_mode = "UNCLEAN (online)";
1957
1958 } else if (node->details->pending) {
1959 node_mode = "UNCLEAN (pending)";
1960
1961 } else {
1962 node_mode = "UNCLEAN (offline)";
1963 }
1964
1965 } else if (node->details->pending) {
1966 node_mode = "pending";
1967
1968 } else if (node->details->standby_onfail && node->details->online) {
1969 node_mode = "standby (on-fail)";
1970
1971 } else if (node->details->standby) {
1972 if (node->details->online) {
1973 if (node->details->running_rsc) {
1974 node_mode = "standby (with active resources)";
1975 } else {
1976 node_mode = "standby";
1977 }
1978 } else {
1979 node_mode = "OFFLINE (standby)";
1980 }
1981
1982 } else if (node->details->maintenance) {
1983 if (node->details->online) {
1984 node_mode = "maintenance";
1985 } else {
1986 node_mode = "OFFLINE (maintenance)";
1987 }
1988
1989 } else if (node->details->online) {
1990 node_mode = "online";
1991 if (!pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
1992 if (pe__is_guest_node(node)) {
1993 pcmk__add_word(&online_guest_nodes,
1994 &online_guest_nodes_len, node_name);
1995 } else if (pe__is_remote_node(node)) {
1996 pcmk__add_word(&online_remote_nodes,
1997 &online_remote_nodes_len, node_name);
1998 } else {
1999 pcmk__add_word(&online_nodes, &online_nodes_len, node_name);
2000 }
2001 free(node_name);
2002 continue;
2003 }
2004
2005 } else {
2006 node_mode = "OFFLINE";
2007 if (!pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
2008 if (pe__is_remote_node(node)) {
2009 pcmk__add_word(&offline_remote_nodes,
2010 &offline_remote_nodes_len, node_name);
2011 } else if (pe__is_guest_node(node)) {
2012 /* ignore offline guest nodes */
2013 } else {
2014 pcmk__add_word(&offline_nodes,
2015 &offline_nodes_len, node_name);
2016 }
2017 free(node_name);
2018 continue;
2019 }
2020 }
2021
2022 /* If we get here, node is in bad state, or we're grouping by node */
2023 out->message(out, "node", node, show_opts, TRUE, node_mode, only_node, only_rsc);
2024 free(node_name);
2025 }
2026
2027 /* If we're not grouping by node, summarize nodes by status */
2028 if (online_nodes) {
2029 out->list_item(out, "Online", "[ %s ]", online_nodes);
2030 free(online_nodes);
2031 }
2032 if (offline_nodes) {
2033 out->list_item(out, "OFFLINE", "[ %s ]", offline_nodes);
2034 free(offline_nodes);
2035 }
2036 if (online_remote_nodes) {
2037 out->list_item(out, "RemoteOnline", "[ %s ]", online_remote_nodes);
2038 free(online_remote_nodes);
2039 }
2040 if (offline_remote_nodes) {
2041 out->list_item(out, "RemoteOFFLINE", "[ %s ]", offline_remote_nodes);
2042 free(offline_remote_nodes);
2043 }
2044 if (online_guest_nodes) {
2045 out->list_item(out, "GuestOnline", "[ %s ]", online_guest_nodes);
2046 free(online_guest_nodes);
2047 }
2048
2050 return rc;
2051}
2052
2053PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int")
2054static int
2055node_list_xml(pcmk__output_t *out, va_list args) {
2056 GList *nodes = va_arg(args, GList *);
2057 GList *only_node = va_arg(args, GList *);
2058 GList *only_rsc = va_arg(args, GList *);
2059 unsigned int show_opts = va_arg(args, unsigned int);
2060
2061 out->begin_list(out, NULL, NULL, "nodes");
2062 for (GList *gIter = nodes; gIter != NULL; gIter = gIter->next) {
2063 pe_node_t *node = (pe_node_t *) gIter->data;
2064
2065 if (!pcmk__str_in_list(only_node, node->details->uname, pcmk__str_casei)) {
2066 continue;
2067 }
2068
2069 out->message(out, "node", node, show_opts, TRUE, NULL, only_node, only_rsc);
2070 }
2071 out->end_list(out);
2072
2073 return pcmk_rc_ok;
2074}
2075
2076PCMK__OUTPUT_ARGS("node-summary", "pe_working_set_t *", "GList *", "GList *",
2077 "unsigned int", "unsigned int", "gboolean")
2078static int
2079node_summary(pcmk__output_t *out, va_list args) {
2080 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
2081 GList *only_node = va_arg(args, GList *);
2082 GList *only_rsc = va_arg(args, GList *);
2083 unsigned int section_opts = va_arg(args, unsigned int);
2084 unsigned int show_opts = va_arg(args, unsigned int);
2085 gboolean print_spacer = va_arg(args, gboolean);
2086
2087 xmlNode *node_state = NULL;
2088 xmlNode *cib_status = get_object_root(XML_CIB_TAG_STATUS, data_set->input);
2089 int rc = pcmk_rc_no_output;
2090
2091 if (xmlChildElementCount(cib_status) == 0) {
2092 return rc;
2093 }
2094
2095 for (node_state = first_named_child(cib_status, XML_CIB_TAG_STATE);
2096 node_state != NULL; node_state = crm_next_same_xml(node_state)) {
2097 pe_node_t *node = pe_find_node_id(data_set->nodes, ID(node_state));
2098
2099 if (!node || !node->details || !node->details->online) {
2100 continue;
2101 }
2102
2103 if (!pcmk__str_in_list(only_node, node->details->uname, pcmk__str_casei)) {
2104 continue;
2105 }
2106
2107 PCMK__OUTPUT_LIST_HEADER(out, print_spacer, rc,
2108 pcmk_is_set(section_opts, pcmk_section_operations) ? "Operations" : "Migration Summary");
2109
2110 out->message(out, "node-history-list", data_set, node, node_state,
2111 only_node, only_rsc, section_opts, show_opts);
2112 }
2113
2115 return rc;
2116}
2117
2118PCMK__OUTPUT_ARGS("node-weight", "pe_resource_t *", "const char *", "const char *", "char *")
2119static int
2120node_weight(pcmk__output_t *out, va_list args)
2121{
2122 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2123 const char *prefix = va_arg(args, const char *);
2124 const char *uname = va_arg(args, const char *);
2125 char *score = va_arg(args, char *);
2126
2127 if (rsc) {
2128 out->list_item(out, NULL, "%s: %s allocation score on %s: %s",
2129 prefix, rsc->id, uname, score);
2130 } else {
2131 out->list_item(out, NULL, "%s: %s = %s", prefix, uname, score);
2132 }
2133
2134 return pcmk_rc_ok;
2135}
2136
2137PCMK__OUTPUT_ARGS("node-weight", "pe_resource_t *", "const char *", "const char *", "char *")
2138static int
2139node_weight_xml(pcmk__output_t *out, va_list args)
2140{
2141 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2142 const char *prefix = va_arg(args, const char *);
2143 const char *uname = va_arg(args, const char *);
2144 char *score = va_arg(args, char *);
2145
2146 xmlNodePtr node = pcmk__output_create_xml_node(out, "node_weight",
2147 "function", prefix,
2148 "node", uname,
2149 "score", score,
2150 NULL);
2151
2152 if (rsc) {
2153 crm_xml_add(node, "id", rsc->id);
2154 }
2155
2156 return pcmk_rc_ok;
2157}
2158
2159PCMK__OUTPUT_ARGS("op-history", "xmlNodePtr", "const char *", "const char *", "int",
2160 "unsigned int")
2161static int
2162op_history_text(pcmk__output_t *out, va_list args) {
2163 xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
2164 const char *task = va_arg(args, const char *);
2165 const char *interval_ms_s = va_arg(args, const char *);
2166 int rc = va_arg(args, int);
2167 unsigned int show_opts = va_arg(args, unsigned int);
2168
2169 char *buf = op_history_string(xml_op, task, interval_ms_s, rc,
2170 pcmk_is_set(show_opts, pcmk_show_timing));
2171
2172 out->list_item(out, NULL, "%s", buf);
2173
2174 free(buf);
2175 return pcmk_rc_ok;
2176}
2177
2178PCMK__OUTPUT_ARGS("op-history", "xmlNodePtr", "const char *", "const char *", "int",
2179 "unsigned int")
2180static int
2181op_history_xml(pcmk__output_t *out, va_list args) {
2182 xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
2183 const char *task = va_arg(args, const char *);
2184 const char *interval_ms_s = va_arg(args, const char *);
2185 int rc = va_arg(args, int);
2186 unsigned int show_opts = va_arg(args, unsigned int);
2187
2188 char *rc_s = pcmk__itoa(rc);
2189 xmlNodePtr node = pcmk__output_create_xml_node(out, "operation_history",
2190 "call", crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
2191 "task", task,
2192 "rc", rc_s,
2193 "rc_text", services_ocf_exitcode_str(rc),
2194 NULL);
2195 free(rc_s);
2196
2197 if (interval_ms_s && !pcmk__str_eq(interval_ms_s, "0", pcmk__str_casei)) {
2198 char *s = crm_strdup_printf("%sms", interval_ms_s);
2199 crm_xml_add(node, "interval", s);
2200 free(s);
2201 }
2202
2203 if (pcmk_is_set(show_opts, pcmk_show_timing)) {
2204 const char *value = NULL;
2205 time_t epoch = 0;
2206
2208 &epoch) == pcmk_ok) && (epoch > 0)) {
2210 }
2211
2212 value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
2213 if (value) {
2214 char *s = crm_strdup_printf("%sms", value);
2216 free(s);
2217 }
2218 value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
2219 if (value) {
2220 char *s = crm_strdup_printf("%sms", value);
2222 free(s);
2223 }
2224 }
2225
2226 return pcmk_rc_ok;
2227}
2228
2229PCMK__OUTPUT_ARGS("promotion-score", "pe_resource_t *", "pe_node_t *", "char *")
2230static int
2231promotion_score(pcmk__output_t *out, va_list args)
2232{
2233 pe_resource_t *child_rsc = va_arg(args, pe_resource_t *);
2234 pe_node_t *chosen = va_arg(args, pe_node_t *);
2235 char *score = va_arg(args, char *);
2236
2237 out->list_item(out, NULL, "%s promotion score on %s: %s",
2238 child_rsc->id,
2239 chosen? chosen->details->uname : "none",
2240 score);
2241 return pcmk_rc_ok;
2242}
2243
2244PCMK__OUTPUT_ARGS("promotion-score", "pe_resource_t *", "pe_node_t *", "char *")
2245static int
2246promotion_score_xml(pcmk__output_t *out, va_list args)
2247{
2248 pe_resource_t *child_rsc = va_arg(args, pe_resource_t *);
2249 pe_node_t *chosen = va_arg(args, pe_node_t *);
2250 char *score = va_arg(args, char *);
2251
2252 xmlNodePtr node = pcmk__output_create_xml_node(out, "promotion_score",
2253 "id", child_rsc->id,
2254 "score", score,
2255 NULL);
2256
2257 if (chosen) {
2258 crm_xml_add(node, "node", chosen->details->uname);
2259 }
2260
2261 return pcmk_rc_ok;
2262}
2263
2264PCMK__OUTPUT_ARGS("resource-config", "pe_resource_t *", "gboolean")
2265static int
2266resource_config(pcmk__output_t *out, va_list args) {
2267 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2268 gboolean raw = va_arg(args, gboolean);
2269
2270 char *rsc_xml = NULL;
2271
2272 if (raw) {
2273 rsc_xml = dump_xml_formatted(rsc->orig_xml ? rsc->orig_xml : rsc->xml);
2274 } else {
2275 rsc_xml = dump_xml_formatted(rsc->xml);
2276 }
2277
2278 pcmk__formatted_printf(out, "Resource XML:\n");
2279 out->output_xml(out, "xml", rsc_xml);
2280
2281 free(rsc_xml);
2282 return pcmk_rc_ok;
2283}
2284
2285PCMK__OUTPUT_ARGS("resource-history", "pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
2286static int
2287resource_history_text(pcmk__output_t *out, va_list args) {
2288 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2289 const char *rsc_id = va_arg(args, const char *);
2290 gboolean all = va_arg(args, gboolean);
2291 int failcount = va_arg(args, int);
2292 time_t last_failure = va_arg(args, int);
2293 gboolean as_header = va_arg(args, gboolean);
2294
2295 char *buf = resource_history_string(rsc, rsc_id, all, failcount, last_failure);
2296
2297 if (as_header) {
2298 out->begin_list(out, NULL, NULL, "%s", buf);
2299 } else {
2300 out->list_item(out, NULL, "%s", buf);
2301 }
2302
2303 free(buf);
2304 return pcmk_rc_ok;
2305}
2306
2307PCMK__OUTPUT_ARGS("resource-history", "pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
2308static int
2309resource_history_xml(pcmk__output_t *out, va_list args) {
2310 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2311 const char *rsc_id = va_arg(args, const char *);
2312 gboolean all = va_arg(args, gboolean);
2313 int failcount = va_arg(args, int);
2314 time_t last_failure = va_arg(args, int);
2315 gboolean as_header = va_arg(args, gboolean);
2316
2317 xmlNodePtr node = pcmk__output_xml_create_parent(out, "resource_history",
2318 "id", rsc_id,
2319 NULL);
2320
2321 if (rsc == NULL) {
2322 crm_xml_add(node, "orphan", "true");
2323 } else if (all || failcount || last_failure > 0) {
2324 char *migration_s = pcmk__itoa(rsc->migration_threshold);
2325
2326 pcmk__xe_set_props(node, "orphan", "false",
2327 "migration-threshold", migration_s,
2328 NULL);
2329 free(migration_s);
2330
2331 if (failcount > 0) {
2332 char *s = pcmk__itoa(failcount);
2333
2335 free(s);
2336 }
2337
2338 if (last_failure > 0) {
2340 }
2341 }
2342
2343 if (as_header == FALSE) {
2345 }
2346
2347 return pcmk_rc_ok;
2348}
2349
2350static void
2351print_resource_header(pcmk__output_t *out, unsigned int show_opts)
2352{
2353 if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
2354 /* Active resources have already been printed by node */
2355 out->begin_list(out, NULL, NULL, "Inactive Resources");
2356 } else if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs)) {
2357 out->begin_list(out, NULL, NULL, "Full List of Resources");
2358 } else {
2359 out->begin_list(out, NULL, NULL, "Active Resources");
2360 }
2361}
2362
2363
2364PCMK__OUTPUT_ARGS("resource-list", "pe_working_set_t *", "unsigned int",
2365 "gboolean", "GList *", "GList *", "gboolean")
2366static int
2367resource_list(pcmk__output_t *out, va_list args)
2368{
2369 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
2370 unsigned int show_opts = va_arg(args, unsigned int);
2371 gboolean print_summary = va_arg(args, gboolean);
2372 GList *only_node = va_arg(args, GList *);
2373 GList *only_rsc = va_arg(args, GList *);
2374 gboolean print_spacer = va_arg(args, gboolean);
2375
2376 GList *rsc_iter;
2377 int rc = pcmk_rc_no_output;
2378 bool printed_header = false;
2379
2380 /* If we already showed active resources by node, and
2381 * we're not showing inactive resources, we have nothing to do
2382 */
2383 if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node) &&
2384 !pcmk_is_set(show_opts, pcmk_show_inactive_rscs)) {
2385 return rc;
2386 }
2387
2388 /* If we haven't already printed resources grouped by node,
2389 * and brief output was requested, print resource summary */
2390 if (pcmk_is_set(show_opts, pcmk_show_brief) && !pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
2391 GList *rscs = pe__filter_rsc_list(data_set->resources, only_rsc);
2392
2393 PCMK__OUTPUT_SPACER_IF(out, print_spacer);
2394 print_resource_header(out, show_opts);
2395 printed_header = true;
2396
2397 rc = pe__rscs_brief_output(out, rscs, show_opts);
2398 g_list_free(rscs);
2399 }
2400
2401 /* For each resource, display it if appropriate */
2402 for (rsc_iter = data_set->resources; rsc_iter != NULL; rsc_iter = rsc_iter->next) {
2403 pe_resource_t *rsc = (pe_resource_t *) rsc_iter->data;
2404 int x;
2405
2406 /* Complex resources may have some sub-resources active and some inactive */
2407 gboolean is_active = rsc->fns->active(rsc, TRUE);
2408 gboolean partially_active = rsc->fns->active(rsc, FALSE);
2409
2410 /* Skip inactive orphans (deleted but still in CIB) */
2411 if (pcmk_is_set(rsc->flags, pe_rsc_orphan) && !is_active) {
2412 continue;
2413
2414 /* Skip active resources if we already displayed them by node */
2415 } else if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
2416 if (is_active) {
2417 continue;
2418 }
2419
2420 /* Skip primitives already counted in a brief summary */
2421 } else if (pcmk_is_set(show_opts, pcmk_show_brief) && (rsc->variant == pe_native)) {
2422 continue;
2423
2424 /* Skip resources that aren't at least partially active,
2425 * unless we're displaying inactive resources
2426 */
2427 } else if (!partially_active && !pcmk_is_set(show_opts, pcmk_show_inactive_rscs)) {
2428 continue;
2429
2430 } else if (partially_active && !pe__rsc_running_on_any(rsc, only_node)) {
2431 continue;
2432 }
2433
2434 if (!printed_header) {
2435 PCMK__OUTPUT_SPACER_IF(out, print_spacer);
2436 print_resource_header(out, show_opts);
2437 printed_header = true;
2438 }
2439
2440 /* Print this resource */
2441 x = out->message(out, crm_map_element_name(rsc->xml), show_opts, rsc,
2442 only_node, only_rsc);
2443 if (x == pcmk_rc_ok) {
2444 rc = pcmk_rc_ok;
2445 }
2446 }
2447
2448 if (print_summary && rc != pcmk_rc_ok) {
2449 if (!printed_header) {
2450 PCMK__OUTPUT_SPACER_IF(out, print_spacer);
2451 print_resource_header(out, show_opts);
2452 printed_header = true;
2453 }
2454
2455 if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
2456 out->list_item(out, NULL, "No inactive resources");
2457 } else if (pcmk_is_set(show_opts, pcmk_show_inactive_rscs)) {
2458 out->list_item(out, NULL, "No resources");
2459 } else {
2460 out->list_item(out, NULL, "No active resources");
2461 }
2462 }
2463
2464 if (printed_header) {
2465 out->end_list(out);
2466 }
2467
2468 return rc;
2469}
2470
2471PCMK__OUTPUT_ARGS("resource-operation-list", "pe_working_set_t *", "pe_resource_t *",
2472 "pe_node_t *", "GList *", "unsigned int")
2473static int
2474resource_operation_list(pcmk__output_t *out, va_list args)
2475{
2476 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
2477 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2478 pe_node_t *node = va_arg(args, pe_node_t *);
2479 GList *op_list = va_arg(args, GList *);
2480 unsigned int show_opts = va_arg(args, unsigned int);
2481
2482 GList *gIter = NULL;
2483 int rc = pcmk_rc_no_output;
2484
2485 /* Print each operation */
2486 for (gIter = op_list; gIter != NULL; gIter = gIter->next) {
2487 xmlNode *xml_op = (xmlNode *) gIter->data;
2488 const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
2489 const char *interval_ms_s = crm_element_value(xml_op,
2491 const char *op_rc = crm_element_value(xml_op, XML_LRM_ATTR_RC);
2492 int op_rc_i;
2493
2494 pcmk__scan_min_int(op_rc, &op_rc_i, 0);
2495
2496 /* Display 0-interval monitors as "probe" */
2497 if (pcmk__str_eq(task, CRMD_ACTION_STATUS, pcmk__str_casei)
2498 && pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches | pcmk__str_casei)) {
2499 task = "probe";
2500 }
2501
2502 /* If this is the first printed operation, print heading for resource */
2503 if (rc == pcmk_rc_no_output) {
2504 time_t last_failure = 0;
2505 int failcount = pe_get_failcount(node, rsc, &last_failure, pe_fc_default,
2506 NULL, data_set);
2507
2508 out->message(out, "resource-history", rsc, rsc_printable_id(rsc), TRUE,
2509 failcount, last_failure, TRUE);
2510 rc = pcmk_rc_ok;
2511 }
2512
2513 /* Print the operation */
2514 out->message(out, "op-history", xml_op, task, interval_ms_s,
2515 op_rc_i, show_opts);
2516 }
2517
2518 /* Free the list we created (no need to free the individual items) */
2519 g_list_free(op_list);
2520
2522 return rc;
2523}
2524
2525PCMK__OUTPUT_ARGS("resource-util", "pe_resource_t *", "pe_node_t *", "const char *")
2526static int
2527resource_util(pcmk__output_t *out, va_list args)
2528{
2529 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2530 pe_node_t *node = va_arg(args, pe_node_t *);
2531 const char *fn = va_arg(args, const char *);
2532
2533 char *dump_text = crm_strdup_printf("%s: %s utilization on %s:",
2534 fn, rsc->id, node->details->uname);
2535
2536 g_hash_table_foreach(rsc->utilization, append_dump_text, &dump_text);
2537 out->list_item(out, NULL, "%s", dump_text);
2538 free(dump_text);
2539
2540 return pcmk_rc_ok;
2541}
2542
2543PCMK__OUTPUT_ARGS("resource-util", "pe_resource_t *", "pe_node_t *", "const char *")
2544static int
2545resource_util_xml(pcmk__output_t *out, va_list args)
2546{
2547 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
2548 pe_node_t *node = va_arg(args, pe_node_t *);
2549 const char *fn = va_arg(args, const char *);
2550
2551 xmlNodePtr xml_node = pcmk__output_create_xml_node(out, "utilization",
2552 "resource", rsc->id,
2553 "node", node->details->uname,
2554 "function", fn,
2555 NULL);
2556 g_hash_table_foreach(rsc->utilization, add_dump_node, xml_node);
2557
2558 return pcmk_rc_ok;
2559}
2560
2561PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2562static int
2563ticket_html(pcmk__output_t *out, va_list args) {
2564 pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
2565
2566 if (ticket->last_granted > -1) {
2567 char *time = pcmk__format_named_time("last-granted",
2568 ticket->last_granted);
2569
2570 out->list_item(out, NULL, "%s:\t%s%s %s", ticket->id,
2571 ticket->granted ? "granted" : "revoked",
2572 ticket->standby ? " [standby]" : "",
2573 time);
2574 free(time);
2575 } else {
2576 out->list_item(out, NULL, "%s:\t%s%s", ticket->id,
2577 ticket->granted ? "granted" : "revoked",
2578 ticket->standby ? " [standby]" : "");
2579 }
2580
2581 return pcmk_rc_ok;
2582}
2583
2584PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2585static int
2586ticket_text(pcmk__output_t *out, va_list args) {
2587 pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
2588
2589 if (ticket->last_granted > -1) {
2590 char *time = pcmk__format_named_time("last-granted",
2591 ticket->last_granted);
2592
2593 out->list_item(out, ticket->id, "%s%s %s",
2594 ticket->granted ? "granted" : "revoked",
2595 ticket->standby ? " [standby]" : "",
2596 time);
2597 free(time);
2598 } else {
2599 out->list_item(out, ticket->id, "%s%s",
2600 ticket->granted ? "granted" : "revoked",
2601 ticket->standby ? " [standby]" : "");
2602 }
2603
2604 return pcmk_rc_ok;
2605}
2606
2607PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2608static int
2609ticket_xml(pcmk__output_t *out, va_list args) {
2610 pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
2611
2612 xmlNodePtr node = NULL;
2613
2614 node = pcmk__output_create_xml_node(out, "ticket",
2615 "id", ticket->id,
2616 "status", ticket->granted ? "granted" : "revoked",
2617 "standby", pcmk__btoa(ticket->standby),
2618 NULL);
2619
2620 if (ticket->last_granted > -1) {
2621 crm_xml_add(node, "last-granted", pcmk__epoch2str(&ticket->last_granted));
2622 }
2623
2624 return pcmk_rc_ok;
2625}
2626
2627PCMK__OUTPUT_ARGS("ticket-list", "pe_working_set_t *", "gboolean")
2628static int
2629ticket_list(pcmk__output_t *out, va_list args) {
2630 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
2631 gboolean print_spacer = va_arg(args, gboolean);
2632
2633 GHashTableIter iter;
2634 gpointer key, value;
2635
2636 if (g_hash_table_size(data_set->tickets) == 0) {
2637 return pcmk_rc_no_output;
2638 }
2639
2640 PCMK__OUTPUT_SPACER_IF(out, print_spacer);
2641
2642 /* Print section heading */
2643 out->begin_list(out, NULL, NULL, "Tickets");
2644
2645 /* Print each ticket */
2646 g_hash_table_iter_init(&iter, data_set->tickets);
2647 while (g_hash_table_iter_next(&iter, &key, &value)) {
2648 pe_ticket_t *ticket = (pe_ticket_t *) value;
2649 out->message(out, "ticket", ticket);
2650 }
2651
2652 /* Close section */
2653 out->end_list(out);
2654 return pcmk_rc_ok;
2655}
2656
2657static pcmk__message_entry_t fmt_functions[] = {
2658 { "ban", "default", ban_text },
2659 { "ban", "html", ban_html },
2660 { "ban", "xml", ban_xml },
2661 { "ban-list", "default", ban_list },
2662 { "bundle", "default", pe__bundle_text },
2663 { "bundle", "xml", pe__bundle_xml },
2664 { "bundle", "html", pe__bundle_html },
2665 { "clone", "default", pe__clone_default },
2666 { "clone", "xml", pe__clone_xml },
2667 { "cluster-counts", "default", cluster_counts_text },
2668 { "cluster-counts", "html", cluster_counts_html },
2669 { "cluster-counts", "xml", cluster_counts_xml },
2670 { "cluster-dc", "default", cluster_dc_text },
2671 { "cluster-dc", "html", cluster_dc_html },
2672 { "cluster-dc", "xml", cluster_dc_xml },
2673 { "cluster-options", "default", cluster_options_text },
2674 { "cluster-options", "html", cluster_options_html },
2675 { "cluster-options", "log", cluster_options_log },
2676 { "cluster-options", "xml", cluster_options_xml },
2677 { "cluster-summary", "default", cluster_summary },
2678 { "cluster-summary", "html", cluster_summary_html },
2679 { "cluster-stack", "default", cluster_stack_text },
2680 { "cluster-stack", "html", cluster_stack_html },
2681 { "cluster-stack", "xml", cluster_stack_xml },
2682 { "cluster-times", "default", cluster_times_text },
2683 { "cluster-times", "html", cluster_times_html },
2684 { "cluster-times", "xml", cluster_times_xml },
2685 { "failed-action", "default", failed_action_text },
2686 { "failed-action", "xml", failed_action_xml },
2687 { "failed-action-list", "default", failed_action_list },
2688 { "group", "default", pe__group_default},
2689 { "group", "xml", pe__group_xml },
2690 { "maint-mode", "text", cluster_maint_mode_text },
2691 { "node", "default", node_text },
2692 { "node", "html", node_html },
2693 { "node", "xml", node_xml },
2694 { "node-and-op", "default", node_and_op },
2695 { "node-and-op", "xml", node_and_op_xml },
2696 { "node-capacity", "default", node_capacity },
2697 { "node-capacity", "xml", node_capacity_xml },
2698 { "node-history-list", "default", node_history_list },
2699 { "node-list", "default", node_list_text },
2700 { "node-list", "html", node_list_html },
2701 { "node-list", "xml", node_list_xml },
2702 { "node-weight", "default", node_weight },
2703 { "node-weight", "xml", node_weight_xml },
2704 { "node-attribute", "default", node_attribute_text },
2705 { "node-attribute", "html", node_attribute_html },
2706 { "node-attribute", "xml", node_attribute_xml },
2707 { "node-attribute-list", "default", node_attribute_list },
2708 { "node-summary", "default", node_summary },
2709 { "op-history", "default", op_history_text },
2710 { "op-history", "xml", op_history_xml },
2711 { "primitive", "default", pe__resource_text },
2712 { "primitive", "xml", pe__resource_xml },
2713 { "primitive", "html", pe__resource_html },
2714 { "promotion-score", "default", promotion_score },
2715 { "promotion-score", "xml", promotion_score_xml },
2716 { "resource-config", "default", resource_config },
2717 { "resource-history", "default", resource_history_text },
2718 { "resource-history", "xml", resource_history_xml },
2719 { "resource-list", "default", resource_list },
2720 { "resource-operation-list", "default", resource_operation_list },
2721 { "resource-util", "default", resource_util },
2722 { "resource-util", "xml", resource_util_xml },
2723 { "ticket", "default", ticket_text },
2724 { "ticket", "html", ticket_html },
2725 { "ticket", "xml", ticket_xml },
2726 { "ticket-list", "default", ticket_list },
2727
2728 { NULL, NULL, NULL }
2729};
2730
2731void
2733 pcmk__register_messages(out, fmt_functions);
2734}
2735
2736void
2737pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
2738{
2739 if (node == NULL) {
2740 crm_trace("<NULL>");
2741 return;
2742 }
2743
2744 CRM_ASSERT(node->details);
2745 crm_trace("%sNode %s: (weight=%d, fixed=%s)",
2746 node->details->online ? "" : "Unavailable/Unclean ",
2747 node->details->uname, node->weight, node->fixed ? "True" : "False");
2748
2749 if (details) {
2750 char *pe_mutable = strdup("\t\t");
2751 GList *gIter = node->details->running_rsc;
2752 GList *all = NULL;
2753
2754 all = g_list_prepend(all, (gpointer) "*");
2755
2756 crm_trace("\t\t===Node Attributes");
2757 g_hash_table_foreach(node->details->attrs, print_str_str, pe_mutable);
2758 free(pe_mutable);
2759
2760 crm_trace("\t\t=== Resources");
2761
2762 for (; gIter != NULL; gIter = gIter->next) {
2763 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2764
2765 out->message(out, crm_map_element_name(rsc->xml),
2766 pe_print_pending, rsc, all, all);
2767 }
2768
2769 g_list_free(all);
2770 }
2771}
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition agents.c:31
@ pcmk_ra_cap_provider
Definition agents.h:47
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
Definition cib_utils.c:146
#define PCMK__LAST_FAILURE_PREFIX
Definition internal.h:319
#define PCMK__FAIL_COUNT_PREFIX
Definition internal.h:318
char * pcmk__format_nvpair(const char *name, const char *value, const char *units)
Definition nvpair.c:285
char * pcmk__format_named_time(const char *name, time_t epoch_time)
Definition nvpair.c:304
uint64_t flags
Definition remote.c:3
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition operations.c:185
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
gboolean crm_is_true(const char *s)
Definition strings.c:415
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:114
@ pe_print_pending
Definition common.h:132
#define RSC_ROLE_PROMOTED_LEGACY_S
Definition common.h:116
rsc_role_e
Possible roles that a resource can be in.
Definition common.h:92
@ RSC_ROLE_PROMOTED
Definition common.h:97
#define RSC_ROLE_PROMOTED_S
Definition common.h:114
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition complex.c:903
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 uname[MAX_NAME]
Definition cpg.c:5
uint32_t id
Definition cpg.c:0
#define CRMD_ACTION_NOTIFY
Definition crm.h:187
#define CRMD_ACTION_STATUS
Definition crm.h:190
#define crm_time_log_timeofday
Definition iso8601.h:67
char * crm_time_as_string(crm_time_t *dt, int flags)
Definition iso8601.c:497
void crm_time_free(crm_time_t *dt)
Definition iso8601.c:141
void crm_time_set_timet(crm_time_t *target, time_t *source)
Definition iso8601.c:1255
#define crm_time_log_with_timezone
Definition iso8601.h:68
#define crm_time_log_date
Definition iso8601.h:66
crm_time_t * crm_time_new(const char *string)
Definition iso8601.c:93
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition iso8601.c:117
struct crm_time_s crm_time_t
Definition iso8601.h:32
const char * pcmk__epoch2str(time_t *when)
Definition iso8601.c:1715
#define CRM_CHECK(expr, failure_action)
Definition logging.h:218
#define crm_trace(fmt, args...)
Definition logging.h:356
#define XML_LRM_TAG_RSC_OP
Definition msg_xml.h:265
#define ID(x)
Definition msg_xml.h:456
#define XML_ATTR_UNAME
Definition msg_xml.h:151
#define XML_RSC_ATTR_TARGET_ROLE
Definition msg_xml.h:233
#define XML_NVPAIR_ATTR_VALUE
Definition msg_xml.h:378
#define XML_LRM_TAG_RESOURCES
Definition msg_xml.h:263
#define XML_LRM_ATTR_TASK_KEY
Definition msg_xml.h:298
#define XML_CIB_TAG_STATE
Definition msg_xml.h:198
#define XML_LRM_ATTR_OPSTATUS
Definition msg_xml.h:307
#define XML_ATTR_ID
Definition msg_xml.h:129
#define XML_ATTR_HAVE_QUORUM
Definition msg_xml.h:118
#define XML_RSC_OP_T_EXEC
Definition msg_xml.h:319
#define XML_LRM_ATTR_EXIT_REASON
Definition msg_xml.h:315
#define XML_AGENT_ATTR_PROVIDER
Definition msg_xml.h:267
#define XML_AGENT_ATTR_CLASS
Definition msg_xml.h:266
#define XML_ATTR_UPDATE_CLIENT
Definition msg_xml.h:137
#define XML_LRM_ATTR_TASK
Definition msg_xml.h:297
#define XML_ATTR_TYPE
Definition msg_xml.h:132
#define XML_CIB_ATTR_WRITTEN
Definition msg_xml.h:126
#define XML_CIB_TAG_STATUS
Definition msg_xml.h:179
#define XML_RSC_OP_LAST_CHANGE
Definition msg_xml.h:317
#define XML_LRM_ATTR_CALLID
Definition msg_xml.h:309
#define XML_CIB_TAG_LRM
Definition msg_xml.h:262
#define XML_ATTR_UPDATE_ORIG
Definition msg_xml.h:136
#define XML_ATTR_UPDATE_USER
Definition msg_xml.h:138
#define XML_LRM_ATTR_RC
Definition msg_xml.h:308
#define XML_RSC_OP_T_QUEUE
Definition msg_xml.h:320
#define XML_LRM_ATTR_INTERVAL_MS
Definition msg_xml.h:295
#define XML_LRM_TAG_RESOURCE
Definition msg_xml.h:264
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:530
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition nvpair.c:623
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
Definition nvpair.c:651
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition nvpair.c:324
Control output from tools.
@ pcmk_show_rscs_by_node
Definition output.h:62
@ pcmk_show_timing
Definition output.h:60
@ pcmk_show_pending
Definition output.h:63
@ pcmk_show_brief
Definition output.h:56
@ pcmk_show_rsc_only
Definition output.h:64
@ pcmk_show_inactive_rscs
Definition output.h:61
@ pcmk_show_node_id
Definition output.h:58
@ pcmk_section_times
Definition output.h:29
@ pcmk_section_operations
Definition output.h:36
@ pcmk_section_options
Definition output.h:31
@ pcmk_section_stack
Definition output.h:27
@ pcmk_section_counts
Definition output.h:30
@ pcmk_section_dc
Definition output.h:28
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition output_xml.c:511
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition output.c:145
xmlNodePtr pcmk__output_xml_create_parent(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition output_xml.c:432
xmlNodePtr pcmk__output_xml_peek_parent(pcmk__output_t *out)
Definition output_xml.c:527
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
xmlNodePtr pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id, const char *class_name, const char *text)
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond)
xmlNodePtr pcmk__output_create_xml_node(pcmk__output_t *out, const char *name,...) G_GNUC_NULL_TERMINATED
Definition output_xml.c:465
void pcmk__output_xml_push_parent(pcmk__output_t *out, xmlNodePtr node)
Definition output_xml.c:495
void void void pcmk__formatted_printf(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define PCMK__OUTPUT_ARGS(ARGS...)
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
char * name
Definition pcmk_fence.c:31
int rc
Definition pcmk_fence.c:35
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:543
char * pe__node_display_name(pe_node_t *node, bool print_detail)
Definition pe_output.c:491
#define FILTER_STR
Definition pe_output.c:19
void pe__register_messages(pcmk__output_t *out)
Definition pe_output.c:2732
void pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
Definition pe_output.c:2737
@ no_quorum_suicide
Definition pe_types.h:66
@ no_quorum_demote
Definition pe_types.h:67
@ no_quorum_freeze
Definition pe_types.h:63
@ no_quorum_ignore
Definition pe_types.h:65
@ no_quorum_stop
Definition pe_types.h:64
#define pe_flag_maintenance_mode
Definition pe_types.h:96
#define pe_flag_symmetric_cluster
Definition pe_types.h:95
#define pe_rsc_orphan
Definition pe_types.h:248
#define pe_flag_stop_everything
Definition pe_types.h:105
node_type
Definition pe_types.h:70
@ node_ping
Definition pe_types.h:71
@ node_remote
Definition pe_types.h:73
@ node_member
Definition pe_types.h:72
@ pe_group
Definition pe_types.h:38
@ pe_native
Definition pe_types.h:37
#define pe_flag_stonith_enabled
Definition pe_types.h:98
int pe__clone_xml(pcmk__output_t *out, va_list args)
Definition clone.c:644
bool pe__rsc_running_on_any(pe_resource_t *rsc, GList *node_list)
Definition utils.c:2399
gchar * pcmk__native_output_string(pe_resource_t *rsc, const char *name, pe_node_t *node, unsigned long show_opts, const char *target_role, bool show_nodes)
Definition native.c:545
const char * pe_node_attribute_raw(pe_node_t *node, const char *name)
Definition common.c:635
int pe__bundle_xml(pcmk__output_t *out, va_list args)
Definition bundle.c:1475
int pe__group_xml(pcmk__output_t *out, va_list args)
Definition group.c:259
int pe__bundle_html(pcmk__output_t *out, va_list args)
Definition bundle.c:1599
int pe_get_failcount(pe_node_t *node, pe_resource_t *rsc, time_t *last_failure, uint32_t flags, xmlNode *xml_op, pe_working_set_t *data_set)
Definition failcounts.c:251
int pe__clone_default(pcmk__output_t *out, va_list args)
Definition clone.c:706
GList * pe__filter_rsc_list(GList *rscs, GList *filter)
Definition utils.c:2418
int pe__bundle_text(pcmk__output_t *out, va_list args)
Definition bundle.c:1727
void print_str_str(gpointer key, gpointer value, gpointer user_data)
Definition utils.c:1336
gint sort_op_by_callid(gconstpointer a, gconstpointer b)
Definition utils.c:1638
int pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, unsigned int options)
Definition native.c:1263
@ pe_fc_default
Definition internal.h:299
int pe__resource_xml(pcmk__output_t *out, va_list args)
Definition native.c:901
int pe__group_default(pcmk__output_t *out, va_list args)
Definition group.c:309
int pe__resource_text(pcmk__output_t *out, va_list args)
Definition native.c:999
int pe__resource_html(pcmk__output_t *out, va_list args)
Definition native.c:975
bool pe__is_guest_node(const pe_node_t *node)
Definition remote.c:33
bool pe__is_remote_node(const pe_node_t *node)
Definition remote.c:25
#define CRM_ASSERT(expr)
Definition results.h:42
@ pcmk_rc_no_output
Definition results.h:112
@ pcmk_rc_ok
Definition results.h:142
#define pcmk_ok
Definition results.h:67
pe_node_t * pe_find_node_id(GList *node_list, const char *id)
Definition status.c:418
const char * rsc_printable_id(pe_resource_t *rsc)
Definition utils.c:1917
pe_resource_t * pe_find_resource(GList *rsc_list, const char *id_rh)
Definition status.c:382
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition strings.c:127
#define pcmk__plural_s(i)
char * pcmk__trim(char *str)
Definition strings.c:455
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:955
@ pcmk__str_none
@ pcmk__str_null_matches
@ pcmk__str_casei
gboolean pcmk__str_in_list(GList *lst, const gchar *s, uint32_t flags)
Definition strings.c:895
This structure contains everything that makes up a single output formatter.
int(* message)(pcmk__output_t *out, const char *message_id,...)
void(* begin_list)(pcmk__output_t *out, const char *singular_noun, const char *plural_noun, const char *format,...) G_GNUC_PRINTF(4
pe_resource_t * rsc_lh
Definition internal.h:170
enum rsc_role_e role_filter
Definition internal.h:171
int weight
Definition pe_types.h:241
gboolean fixed
Definition pe_types.h:242
struct pe_node_shared_s * details
Definition pe_types.h:244
GHashTable * attrs
Definition pe_types.h:234
gboolean shutdown
Definition pe_types.h:219
gboolean expected_up
Definition pe_types.h:220
const char * id
Definition pe_types.h:208
gboolean online
Definition pe_types.h:213
gboolean standby_onfail
Definition pe_types.h:215
const char * uname
Definition pe_types.h:209
gboolean standby
Definition pe_types.h:214
GHashTable * utilization
Definition pe_types.h:235
pe_resource_t * remote_rsc
Definition pe_types.h:230
gboolean is_dc
Definition pe_types.h:221
gboolean unclean
Definition pe_types.h:217
gboolean maintenance
Definition pe_types.h:222
enum node_type type
Definition pe_types.h:210
gboolean pending
Definition pe_types.h:216
GList * running_rsc
Definition pe_types.h:231
enum pe_obj_types variant
Definition pe_types.h:331
GHashTable * meta
Definition pe_types.h:374
int migration_threshold
Definition pe_types.h:345
pe_resource_t * container
Definition pe_types.h:381
xmlNode * xml
Definition pe_types.h:324
GHashTable * utilization
Definition pe_types.h:376
pe_node_t * pending_node
Definition pe_types.h:384
unsigned long long flags
Definition pe_types.h:349
xmlNode * orig_xml
Definition pe_types.h:325
resource_object_functions_t * fns
Definition pe_types.h:333
char * id
Definition pe_types.h:458
gboolean granted
Definition pe_types.h:459
time_t last_granted
Definition pe_types.h:460
xmlNode * input
Definition pe_types.h:137
GList * resources
Definition pe_types.h:158
pe_node_t * dc_node
Definition pe_types.h:142
xmlNode * failed
Definition pe_types.h:165
unsigned long long flags
Definition pe_types.h:146
enum pe_quorum_policy no_quorum_policy
Definition pe_types.h:149
GHashTable * tickets
Definition pe_types.h:152
GList * placement_constraints
Definition pe_types.h:159
int priority_fencing_delay
Definition pe_types.h:190
gboolean(* is_filtered)(pe_resource_t *, GList *, gboolean)
Definition pe_types.h:57
gboolean(* active)(pe_resource_t *, gboolean)
Definition pe_types.h:52
char * dump_xml_formatted(xmlNode *msg)
Definition xml.c:2006
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition xml.c:446
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition xml.c:2790
xmlNode * pcmk_create_xml_text_node(xmlNode *parent, const char *name, const char *content)
Definition xml.c:721
const xmlChar * pcmkXmlStr
Definition xml.h:51
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition xpath.c:214
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition xml.c:2816
char * crm_xml_escape(const char *text)
Definition xml.c:1335
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
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition xml.c:696
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
Definition xml.c:2972