This source file includes following definitions.
- failed_action_string
- get_cluster_stack
- last_changed_string
- op_history_string
- resource_history_string
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- pe__node_display_name
- pe__name_and_nvpairs_xml
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- PCMK__OUTPUT_ARGS
- pe__register_messages
- pe__output_node
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/common/iso8601_internal.h>
12 #include <crm/msg_xml.h>
13 #include <crm/pengine/internal.h>
14
15 static char *
16 failed_action_string(xmlNodePtr xml_op) {
17 const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
18 int rc = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_RC), "0");
19 int status = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS), "0");
20 const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
21
22 time_t last_change = 0;
23
24 if (crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE,
25 &last_change) == pcmk_ok) {
26 crm_time_t *crm_when = crm_time_new(NULL);
27 char *time_s = NULL;
28 char *buf = NULL;
29
30 crm_time_set_timet(crm_when, &last_change);
31 time_s = crm_time_as_string(crm_when, crm_time_log_date | crm_time_log_timeofday | crm_time_log_with_timezone);
32
33 buf = crm_strdup_printf("%s on %s '%s' (%d): call=%s, status='%s', "
34 "exitreason='%s', " XML_RSC_OP_LAST_CHANGE
35 "='%s', queued=%sms, exec=%sms",
36 op_key ? op_key : ID(xml_op),
37 crm_element_value(xml_op, XML_ATTR_UNAME),
38 services_ocf_exitcode_str(rc), rc,
39 crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
40 services_lrm_status_str(status),
41 exit_reason ? exit_reason : "none",
42 time_s,
43 crm_element_value(xml_op, XML_RSC_OP_T_QUEUE),
44 crm_element_value(xml_op, XML_RSC_OP_T_EXEC));
45
46 crm_time_free(crm_when);
47 free(time_s);
48 return buf;
49 } else {
50 return crm_strdup_printf("%s on %s '%s' (%d): call=%s, status=%s, exitreason='%s'",
51 op_key ? op_key : ID(xml_op),
52 crm_element_value(xml_op, XML_ATTR_UNAME),
53 services_ocf_exitcode_str(rc), rc,
54 crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
55 services_lrm_status_str(status),
56 exit_reason ? exit_reason : "none");
57 }
58 }
59
60 static const char *
61 get_cluster_stack(pe_working_set_t *data_set)
62 {
63 xmlNode *stack = get_xpath_object("//nvpair[@name='cluster-infrastructure']",
64 data_set->input, LOG_DEBUG);
65 return stack? crm_element_value(stack, XML_NVPAIR_ATTR_VALUE) : "unknown";
66 }
67
68 static char *
69 last_changed_string(const char *last_written, const char *user,
70 const char *client, const char *origin) {
71 if (last_written != NULL || user != NULL || client != NULL || origin != NULL) {
72 return crm_strdup_printf("%s%s%s%s%s%s%s",
73 last_written ? last_written : "",
74 user ? " by " : "",
75 user ? user : "",
76 client ? " via " : "",
77 client ? client : "",
78 origin ? " on " : "",
79 origin ? origin : "");
80 } else {
81 return strdup("");
82 }
83 }
84
85 static char *
86 op_history_string(xmlNode *xml_op, const char *task, const char *interval_ms_s,
87 int rc, gboolean print_timing) {
88 const char *call = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
89 char *interval_str = NULL;
90 char *buf = NULL;
91
92 if (interval_ms_s && !pcmk__str_eq(interval_ms_s, "0", pcmk__str_casei)) {
93 char *pair = pcmk_format_nvpair("interval", interval_ms_s, "ms");
94 interval_str = crm_strdup_printf(" %s", pair);
95 free(pair);
96 }
97
98 if (print_timing) {
99 char *last_change_str = NULL;
100 char *last_run_str = NULL;
101 char *exec_str = NULL;
102 char *queue_str = NULL;
103
104 const char *value = NULL;
105
106 time_t epoch = 0;
107
108 if ((crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE, &epoch) == pcmk_ok)
109 && (epoch > 0)) {
110 char *time = pcmk_format_named_time(XML_RSC_OP_LAST_CHANGE, epoch);
111 last_change_str = crm_strdup_printf(" %s", time);
112 free(time);
113 }
114
115 if ((crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_RUN, &epoch) == pcmk_ok)
116 && (epoch > 0)) {
117 char *time = pcmk_format_named_time(XML_RSC_OP_LAST_RUN, epoch);
118 last_run_str = crm_strdup_printf(" %s", time);
119 free(time);
120 }
121
122 value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
123 if (value) {
124 char *pair = pcmk_format_nvpair(XML_RSC_OP_T_EXEC, value, "ms");
125 exec_str = crm_strdup_printf(" %s", pair);
126 free(pair);
127 }
128
129 value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
130 if (value) {
131 char *pair = pcmk_format_nvpair(XML_RSC_OP_T_QUEUE, value, "ms");
132 queue_str = crm_strdup_printf(" %s", pair);
133 free(pair);
134 }
135
136 buf = crm_strdup_printf("(%s) %s:%s%s%s%s%s rc=%d (%s)", call, task,
137 interval_str ? interval_str : "",
138 last_change_str ? last_change_str : "",
139 last_run_str ? last_run_str : "",
140 exec_str ? exec_str : "",
141 queue_str ? queue_str : "",
142 rc, services_ocf_exitcode_str(rc));
143
144 if (last_change_str) {
145 free(last_change_str);
146 }
147
148 if (last_run_str) {
149 free(last_run_str);
150 }
151
152 if (exec_str) {
153 free(exec_str);
154 }
155
156 if (queue_str) {
157 free(queue_str);
158 }
159 } else {
160 buf = crm_strdup_printf("(%s) %s%s%s", call, task,
161 interval_str ? ":" : "",
162 interval_str ? interval_str : "");
163 }
164
165 if (interval_str) {
166 free(interval_str);
167 }
168
169 return buf;
170 }
171
172 static char *
173 resource_history_string(pe_resource_t *rsc, const char *rsc_id, gboolean all,
174 int failcount, time_t last_failure) {
175 char *buf = NULL;
176
177 if (rsc == NULL) {
178 buf = crm_strdup_printf("%s: orphan", rsc_id);
179 } else if (all || failcount || last_failure > 0) {
180 char *failcount_s = NULL;
181 char *lastfail_s = NULL;
182
183 if (failcount > 0) {
184 failcount_s = crm_strdup_printf(" %s=%d", PCMK__FAIL_COUNT_PREFIX,
185 failcount);
186 } else {
187 failcount_s = strdup("");
188 }
189 if (last_failure > 0) {
190 lastfail_s = crm_strdup_printf(" %s='%s'",
191 PCMK__LAST_FAILURE_PREFIX,
192 pcmk__epoch2str(&last_failure));
193 }
194
195 buf = crm_strdup_printf("%s: migration-threshold=%d%s%s",
196 rsc_id, rsc->migration_threshold, failcount_s,
197 lastfail_s? lastfail_s : "");
198 free(failcount_s);
199 free(lastfail_s);
200 } else {
201 buf = crm_strdup_printf("%s:", rsc_id);
202 }
203
204 return buf;
205 }
206
207 PCMK__OUTPUT_ARGS("cluster-summary", "pe_working_set_t *", "gboolean", "gboolean", "gboolean",
208 "gboolean", "gboolean", "gboolean")
209 int
210 pe__cluster_summary(pcmk__output_t *out, va_list args) {
211 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
212 gboolean print_clone_detail = va_arg(args, gboolean);
213 gboolean show_stack = va_arg(args, gboolean);
214 gboolean show_dc = va_arg(args, gboolean);
215 gboolean show_times = va_arg(args, gboolean);
216 gboolean show_counts = va_arg(args, gboolean);
217 gboolean show_options = va_arg(args, gboolean);
218 int rc = pcmk_rc_no_output;
219
220 const char *stack_s = get_cluster_stack(data_set);
221
222 if (show_stack) {
223 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
224 out->message(out, "cluster-stack", stack_s);
225 }
226
227
228 if (data_set->dc_node == NULL || show_dc) {
229 xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']",
230 data_set->input, LOG_DEBUG);
231 const char *dc_version_s = dc_version?
232 crm_element_value(dc_version, XML_NVPAIR_ATTR_VALUE)
233 : NULL;
234 const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
235 char *dc_name = data_set->dc_node ? pe__node_display_name(data_set->dc_node, print_clone_detail) : NULL;
236
237 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
238 out->message(out, "cluster-dc", data_set->dc_node, quorum, dc_version_s, dc_name);
239 free(dc_name);
240 }
241
242 if (show_times) {
243 const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN);
244 const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER);
245 const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT);
246 const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG);
247
248 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
249 out->message(out, "cluster-times", last_written, user, client, origin);
250 }
251
252 if (show_counts) {
253 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
254 out->message(out, "cluster-counts", g_list_length(data_set->nodes),
255 data_set->ninstances, data_set->disabled_resources,
256 data_set->blocked_resources);
257 }
258
259 if (show_options) {
260 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
261 out->message(out, "cluster-options", data_set);
262 }
263
264 PCMK__OUTPUT_LIST_FOOTER(out, rc);
265
266 if (out->message(out, "maint-mode", data_set->flags) == pcmk_rc_ok) {
267 rc = pcmk_rc_ok;
268 }
269
270 return rc;
271 }
272
273 PCMK__OUTPUT_ARGS("cluster-summary", "pe_working_set_t *", "gboolean", "gboolean", "gboolean",
274 "gboolean", "gboolean", "gboolean")
275 int
276 pe__cluster_summary_html(pcmk__output_t *out, va_list args) {
277 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
278 gboolean print_clone_detail = va_arg(args, gboolean);
279 gboolean show_stack = va_arg(args, gboolean);
280 gboolean show_dc = va_arg(args, gboolean);
281 gboolean show_times = va_arg(args, gboolean);
282 gboolean show_counts = va_arg(args, gboolean);
283 gboolean show_options = va_arg(args, gboolean);
284 int rc = pcmk_rc_no_output;
285
286 const char *stack_s = get_cluster_stack(data_set);
287
288 if (show_stack) {
289 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
290 out->message(out, "cluster-stack", stack_s);
291 }
292
293
294 if (data_set->dc_node == NULL || show_dc) {
295 xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']",
296 data_set->input, LOG_DEBUG);
297 const char *dc_version_s = dc_version?
298 crm_element_value(dc_version, XML_NVPAIR_ATTR_VALUE)
299 : NULL;
300 const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
301 char *dc_name = data_set->dc_node ? pe__node_display_name(data_set->dc_node, print_clone_detail) : NULL;
302
303 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
304 out->message(out, "cluster-dc", data_set->dc_node, quorum, dc_version_s, dc_name);
305 free(dc_name);
306 }
307
308 if (show_times) {
309 const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN);
310 const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER);
311 const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT);
312 const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG);
313
314 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
315 out->message(out, "cluster-times", last_written, user, client, origin);
316 }
317
318 if (show_counts) {
319 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Cluster Summary");
320 out->message(out, "cluster-counts", g_list_length(data_set->nodes),
321 data_set->ninstances, data_set->disabled_resources,
322 data_set->blocked_resources);
323 }
324
325 if (show_options) {
326
327
328
329
330 PCMK__OUTPUT_LIST_FOOTER(out, rc);
331
332 out->begin_list(out, NULL, NULL, "Config Options");
333 out->message(out, "cluster-options", data_set);
334 }
335
336 PCMK__OUTPUT_LIST_FOOTER(out, rc);
337
338 if (out->message(out, "maint-mode", data_set->flags) == pcmk_rc_ok) {
339 rc = pcmk_rc_ok;
340 }
341
342 return rc;
343 }
344
345 char *
346 pe__node_display_name(pe_node_t *node, bool print_detail)
347 {
348 char *node_name;
349 const char *node_host = NULL;
350 const char *node_id = NULL;
351 int name_len;
352
353 CRM_ASSERT((node != NULL) && (node->details != NULL) && (node->details->uname != NULL));
354
355
356 if (pe__is_guest_node(node)) {
357 pe_node_t *host_node = pe__current_node(node->details->remote_rsc);
358
359 if (host_node && host_node->details) {
360 node_host = host_node->details->uname;
361 }
362 if (node_host == NULL) {
363 node_host = "";
364 }
365 }
366
367
368 if (print_detail && !pcmk__str_eq(node->details->uname, node->details->id, pcmk__str_casei)) {
369 node_id = node->details->id;
370 }
371
372
373 name_len = strlen(node->details->uname) + 1;
374 if (node_host) {
375 name_len += strlen(node_host) + 1;
376 }
377 if (node_id) {
378 name_len += strlen(node_id) + 3;
379 }
380
381
382 node_name = malloc(name_len);
383 CRM_ASSERT(node_name != NULL);
384 strcpy(node_name, node->details->uname);
385 if (node_host) {
386 strcat(node_name, "@");
387 strcat(node_name, node_host);
388 }
389 if (node_id) {
390 strcat(node_name, " (");
391 strcat(node_name, node_id);
392 strcat(node_name, ")");
393 }
394 return node_name;
395 }
396
397 int
398 pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name
399 , size_t pairs_count, ...)
400 {
401 xmlNodePtr xml_node = NULL;
402 va_list args;
403
404 CRM_ASSERT(tag_name != NULL);
405
406 xml_node = pcmk__output_xml_peek_parent(out);
407 CRM_ASSERT(xml_node != NULL);
408 xml_node = is_list
409 ? create_xml_node(xml_node, tag_name)
410 : xmlNewChild(xml_node, NULL, (pcmkXmlStr) tag_name, NULL);
411
412 va_start(args, pairs_count);
413 while(pairs_count--) {
414 const char *param_name = va_arg(args, const char *);
415 const char *param_value = va_arg(args, const char *);
416 if (param_name && param_value) {
417 xmlSetProp(xml_node, (pcmkXmlStr)param_name, (pcmkXmlStr)param_value);
418 }
419 };
420 va_end(args);
421
422 if (is_list) {
423 pcmk__output_xml_push_parent(out, xml_node);
424 }
425 return pcmk_rc_ok;
426 }
427
428 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "gboolean")
429 int
430 pe__ban_html(pcmk__output_t *out, va_list args) {
431 pe_node_t *pe_node = va_arg(args, pe_node_t *);
432 pe__location_t *location = va_arg(args, pe__location_t *);
433 gboolean print_clone_detail = va_arg(args, gboolean);
434
435 char *node_name = pe__node_display_name(pe_node, print_clone_detail);
436 char *buf = crm_strdup_printf("%s\tprevents %s from running %son %s",
437 location->id, location->rsc_lh->id,
438 location->role_filter == RSC_ROLE_MASTER ? "as Master " : "",
439 node_name);
440
441 pcmk__output_create_html_node(out, "li", NULL, NULL, buf);
442
443 free(node_name);
444 free(buf);
445 return pcmk_rc_ok;
446 }
447
448 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "gboolean")
449 int
450 pe__ban_text(pcmk__output_t *out, va_list args) {
451 pe_node_t *pe_node = va_arg(args, pe_node_t *);
452 pe__location_t *location = va_arg(args, pe__location_t *);
453 gboolean print_clone_detail = va_arg(args, gboolean);
454
455 char *node_name = pe__node_display_name(pe_node, print_clone_detail);
456 out->list_item(out, NULL, "%s\tprevents %s from running %son %s",
457 location->id, location->rsc_lh->id,
458 location->role_filter == RSC_ROLE_MASTER ? "as Master " : "",
459 node_name);
460
461 free(node_name);
462 return pcmk_rc_ok;
463 }
464
465 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "gboolean")
466 int
467 pe__ban_xml(pcmk__output_t *out, va_list args) {
468 xmlNodePtr node = pcmk__output_create_xml_node(out, "ban");
469 pe_node_t *pe_node = va_arg(args, pe_node_t *);
470 pe__location_t *location = va_arg(args, pe__location_t *);
471 gboolean print_clone_detail G_GNUC_UNUSED = va_arg(args, gboolean);
472
473 char *weight_s = crm_itoa(pe_node->weight);
474
475 xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) location->id);
476 xmlSetProp(node, (pcmkXmlStr) "resource", (pcmkXmlStr) location->rsc_lh->id);
477 xmlSetProp(node, (pcmkXmlStr) "node", (pcmkXmlStr) pe_node->details->uname);
478 xmlSetProp(node, (pcmkXmlStr) "weight", (pcmkXmlStr) weight_s);
479 xmlSetProp(node, (pcmkXmlStr) "master_only",
480 (pcmkXmlStr) pcmk__btoa(location->role_filter == RSC_ROLE_MASTER));
481
482 free(weight_s);
483 return pcmk_rc_ok;
484 }
485
486 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
487 int
488 pe__cluster_counts_html(pcmk__output_t *out, va_list args) {
489 xmlNodePtr nodes_node = pcmk__output_create_xml_node(out, "li");
490 xmlNodePtr resources_node = pcmk__output_create_xml_node(out, "li");
491
492 unsigned int nnodes = va_arg(args, unsigned int);
493 int nresources = va_arg(args, int);
494 int ndisabled = va_arg(args, int);
495 int nblocked = va_arg(args, int);
496
497 char *nnodes_str = crm_strdup_printf("%d node%s configured",
498 nnodes, pcmk__plural_s(nnodes));
499
500 pcmk_create_html_node(nodes_node, "span", NULL, NULL, nnodes_str);
501 free(nnodes_str);
502
503 if (ndisabled && nblocked) {
504 char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
505 nresources, pcmk__plural_s(nresources),
506 ndisabled);
507 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
508 free(s);
509
510 pcmk_create_html_node(resources_node, "span", NULL, "bold", "DISABLED");
511
512 s = crm_strdup_printf(", %d ", nblocked);
513 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
514 free(s);
515
516 pcmk_create_html_node(resources_node, "span", NULL, "bold", "BLOCKED");
517 pcmk_create_html_node(resources_node, "span", NULL, NULL,
518 " from further action due to failure)");
519 } else if (ndisabled && !nblocked) {
520 char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
521 nresources, pcmk__plural_s(nresources),
522 ndisabled);
523 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
524 free(s);
525
526 pcmk_create_html_node(resources_node, "span", NULL, "bold", "DISABLED");
527 pcmk_create_html_node(resources_node, "span", NULL, NULL, ")");
528 } else if (!ndisabled && nblocked) {
529 char *s = crm_strdup_printf("%d resource instance%s configured (%d ",
530 nresources, pcmk__plural_s(nresources),
531 nblocked);
532 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
533 free(s);
534
535 pcmk_create_html_node(resources_node, "span", NULL, "bold", "BLOCKED");
536 pcmk_create_html_node(resources_node, "span", NULL, NULL,
537 " from further action due to failure)");
538 } else {
539 char *s = crm_strdup_printf("%d resource instance%s configured",
540 nresources, pcmk__plural_s(nresources));
541 pcmk_create_html_node(resources_node, "span", NULL, NULL, s);
542 free(s);
543 }
544
545 return pcmk_rc_ok;
546 }
547
548 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
549 int
550 pe__cluster_counts_text(pcmk__output_t *out, va_list args) {
551 unsigned int nnodes = va_arg(args, unsigned int);
552 int nresources = va_arg(args, int);
553 int ndisabled = va_arg(args, int);
554 int nblocked = va_arg(args, int);
555
556 out->list_item(out, NULL, "%d node%s configured",
557 nnodes, pcmk__plural_s(nnodes));
558
559 if (ndisabled && nblocked) {
560 out->list_item(out, NULL, "%d resource instance%s configured "
561 "(%d DISABLED, %d BLOCKED from "
562 "further action due to failure)",
563 nresources, pcmk__plural_s(nresources), ndisabled,
564 nblocked);
565 } else if (ndisabled && !nblocked) {
566 out->list_item(out, NULL, "%d resource instance%s configured "
567 "(%d DISABLED)",
568 nresources, pcmk__plural_s(nresources), ndisabled);
569 } else if (!ndisabled && nblocked) {
570 out->list_item(out, NULL, "%d resource instance%s configured "
571 "(%d BLOCKED from further action "
572 "due to failure)",
573 nresources, pcmk__plural_s(nresources), nblocked);
574 } else {
575 out->list_item(out, NULL, "%d resource instance%s configured",
576 nresources, pcmk__plural_s(nresources));
577 }
578
579 return pcmk_rc_ok;
580 }
581
582 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
583 int
584 pe__cluster_counts_xml(pcmk__output_t *out, va_list args) {
585 xmlNodePtr nodes_node = pcmk__output_create_xml_node(out, "nodes_configured");
586 xmlNodePtr resources_node = pcmk__output_create_xml_node(out, "resources_configured");
587
588 unsigned int nnodes = va_arg(args, unsigned int);
589 int nresources = va_arg(args, int);
590 int ndisabled = va_arg(args, int);
591 int nblocked = va_arg(args, int);
592
593 char *s = crm_itoa(nnodes);
594 xmlSetProp(nodes_node, (pcmkXmlStr) "number", (pcmkXmlStr) s);
595 free(s);
596
597 s = crm_itoa(nresources);
598 xmlSetProp(resources_node, (pcmkXmlStr) "number", (pcmkXmlStr) s);
599 free(s);
600
601 s = crm_itoa(ndisabled);
602 xmlSetProp(resources_node, (pcmkXmlStr) "disabled", (pcmkXmlStr) s);
603 free(s);
604
605 s = crm_itoa(nblocked);
606 xmlSetProp(resources_node, (pcmkXmlStr) "blocked", (pcmkXmlStr) s);
607 free(s);
608
609 return pcmk_rc_ok;
610 }
611
612 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
613 int
614 pe__cluster_dc_html(pcmk__output_t *out, va_list args) {
615 xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
616
617 pe_node_t *dc = va_arg(args, pe_node_t *);
618 const char *quorum = va_arg(args, const char *);
619 const char *dc_version_s = va_arg(args, const char *);
620 char *dc_name = va_arg(args, char *);
621
622 pcmk_create_html_node(node, "span", NULL, "bold", "Current DC: ");
623
624 if (dc) {
625 if (crm_is_true(quorum)) {
626 char *buf = crm_strdup_printf("%s (version %s) - partition with quorum",
627 dc_name, dc_version_s ? dc_version_s : "unknown");
628 pcmk_create_html_node(node, "span", NULL, NULL, buf);
629 free(buf);
630 } else {
631 char *buf = crm_strdup_printf("%s (version %s) - partition",
632 dc_name, dc_version_s ? dc_version_s : "unknown");
633 pcmk_create_html_node(node, "span", NULL, NULL, buf);
634 free(buf);
635
636 pcmk_create_html_node(node, "span", NULL, "warning", "WITHOUT");
637 pcmk_create_html_node(node, "span", NULL, NULL, "quorum");
638 }
639 } else {
640 pcmk_create_html_node(node ,"span", NULL, "warning", "NONE");
641 }
642
643 return pcmk_rc_ok;
644 }
645
646 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
647 int
648 pe__cluster_dc_text(pcmk__output_t *out, va_list args) {
649 pe_node_t *dc = va_arg(args, pe_node_t *);
650 const char *quorum = va_arg(args, const char *);
651 const char *dc_version_s = va_arg(args, const char *);
652 char *dc_name = va_arg(args, char *);
653
654 if (dc) {
655 out->list_item(out, "Current DC", "%s (version %s) - partition %s quorum",
656 dc_name, dc_version_s ? dc_version_s : "unknown",
657 crm_is_true(quorum) ? "with" : "WITHOUT");
658 } else {
659 out->list_item(out, "Current DC", "NONE");
660 }
661
662 return pcmk_rc_ok;
663 }
664
665 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
666 int
667 pe__cluster_dc_xml(pcmk__output_t *out, va_list args) {
668 xmlNodePtr node = pcmk__output_create_xml_node(out, "current_dc");
669
670 pe_node_t *dc = va_arg(args, pe_node_t *);
671 const char *quorum = va_arg(args, const char *);
672 const char *dc_version_s = va_arg(args, const char *);
673 char *dc_name G_GNUC_UNUSED = va_arg(args, char *);
674
675 if (dc) {
676 xmlSetProp(node, (pcmkXmlStr) "present", (pcmkXmlStr) "true");
677 xmlSetProp(node, (pcmkXmlStr) "version", (pcmkXmlStr) (dc_version_s ? dc_version_s : ""));
678 xmlSetProp(node, (pcmkXmlStr) "name", (pcmkXmlStr) dc->details->uname);
679 xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) dc->details->id);
680 xmlSetProp(node, (pcmkXmlStr) "with_quorum",
681 (pcmkXmlStr) pcmk__btoa(crm_is_true(quorum)));
682 } else {
683 xmlSetProp(node, (pcmkXmlStr) "present", (pcmkXmlStr) "false");
684 }
685
686 return pcmk_rc_ok;
687 }
688
689 PCMK__OUTPUT_ARGS("maint-mode", "unsigned long long")
690 int
691 pe__cluster_maint_mode_text(pcmk__output_t *out, va_list args) {
692 unsigned long long flags = va_arg(args, unsigned long long);
693
694 if (pcmk_is_set(flags, pe_flag_maintenance_mode)) {
695 fprintf(out->dest, "\n *** Resource management is DISABLED ***");
696 fprintf(out->dest, "\n The cluster will not attempt to start, stop or recover services");
697 fprintf(out->dest, "\n");
698 return pcmk_rc_ok;
699 } else if (pcmk_is_set(flags, pe_flag_stop_everything)) {
700 fprintf(out->dest, "\n *** Resource management is DISABLED ***");
701 fprintf(out->dest, "\n The cluster will keep all resources stopped");
702 fprintf(out->dest, "\n");
703 return pcmk_rc_ok;
704 } else {
705 return pcmk_rc_no_output;
706 }
707 }
708
709 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
710 int
711 pe__cluster_options_html(pcmk__output_t *out, va_list args) {
712 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
713
714 out->list_item(out, NULL, "STONITH of failed nodes %s",
715 pcmk_is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
716
717 out->list_item(out, NULL, "Cluster is %s",
718 pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
719
720 switch (data_set->no_quorum_policy) {
721 case no_quorum_freeze:
722 out->list_item(out, NULL, "No quorum policy: Freeze resources");
723 break;
724
725 case no_quorum_stop:
726 out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
727 break;
728
729 case no_quorum_demote:
730 out->list_item(out, NULL, "No quorum policy: Demote promotable "
731 "resources and stop all other resources");
732 break;
733
734 case no_quorum_ignore:
735 out->list_item(out, NULL, "No quorum policy: Ignore");
736 break;
737
738 case no_quorum_suicide:
739 out->list_item(out, NULL, "No quorum policy: Suicide");
740 break;
741 }
742
743 if (pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)) {
744 xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
745
746 pcmk_create_html_node(node, "span", NULL, NULL, "Resource management: ");
747 pcmk_create_html_node(node, "span", NULL, "bold", "DISABLED");
748 pcmk_create_html_node(node, "span", NULL, NULL,
749 " (the cluster will not attempt to start, stop, or recover services)");
750 } else if (pcmk_is_set(data_set->flags, pe_flag_stop_everything)) {
751 xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
752
753 pcmk_create_html_node(node, "span", NULL, NULL, "Resource management: ");
754 pcmk_create_html_node(node, "span", NULL, "bold", "STOPPED");
755 pcmk_create_html_node(node, "span", NULL, NULL,
756 " (the cluster will keep all resources stopped)");
757 } else {
758 out->list_item(out, NULL, "Resource management: enabled");
759 }
760
761 return pcmk_rc_ok;
762 }
763
764 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
765 int
766 pe__cluster_options_log(pcmk__output_t *out, va_list args) {
767 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
768
769 if (pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)) {
770 out->info(out, "Resource management is DISABLED. The cluster will not attempt to start, stop or recover services.");
771 return pcmk_rc_ok;
772 } else if (pcmk_is_set(data_set->flags, pe_flag_stop_everything)) {
773 out->info(out, "Resource management is DISABLED. The cluster has stopped all resources.");
774 return pcmk_rc_ok;
775 } else {
776 return pcmk_rc_no_output;
777 }
778 }
779
780 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
781 int
782 pe__cluster_options_text(pcmk__output_t *out, va_list args) {
783 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
784
785 out->list_item(out, NULL, "STONITH of failed nodes %s",
786 pcmk_is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled");
787
788 out->list_item(out, NULL, "Cluster is %s",
789 pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster) ? "symmetric" : "asymmetric");
790
791 switch (data_set->no_quorum_policy) {
792 case no_quorum_freeze:
793 out->list_item(out, NULL, "No quorum policy: Freeze resources");
794 break;
795
796 case no_quorum_stop:
797 out->list_item(out, NULL, "No quorum policy: Stop ALL resources");
798 break;
799
800 case no_quorum_demote:
801 out->list_item(out, NULL, "No quorum policy: Demote promotable "
802 "resources and stop all other resources");
803 break;
804
805 case no_quorum_ignore:
806 out->list_item(out, NULL, "No quorum policy: Ignore");
807 break;
808
809 case no_quorum_suicide:
810 out->list_item(out, NULL, "No quorum policy: Suicide");
811 break;
812 }
813
814 return pcmk_rc_ok;
815 }
816
817 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
818 int
819 pe__cluster_options_xml(pcmk__output_t *out, va_list args) {
820 xmlNodePtr node = pcmk__output_create_xml_node(out, "cluster_options");
821 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
822
823 xmlSetProp(node, (pcmkXmlStr) "stonith-enabled",
824 (pcmkXmlStr) pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)));
825 xmlSetProp(node, (pcmkXmlStr) "symmetric-cluster",
826 (pcmkXmlStr) pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster)));
827
828 switch (data_set->no_quorum_policy) {
829 case no_quorum_freeze:
830 xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "freeze");
831 break;
832
833 case no_quorum_stop:
834 xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "stop");
835 break;
836
837 case no_quorum_demote:
838 xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "demote");
839 break;
840
841 case no_quorum_ignore:
842 xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "ignore");
843 break;
844
845 case no_quorum_suicide:
846 xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "suicide");
847 break;
848 }
849
850 xmlSetProp(node, (pcmkXmlStr) "maintenance-mode",
851 (pcmkXmlStr) pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)));
852 xmlSetProp(node, (pcmkXmlStr) "stop-all-resources",
853 (pcmkXmlStr) pcmk__btoa(pcmk_is_set(data_set->flags, pe_flag_stop_everything)));
854
855 return pcmk_rc_ok;
856 }
857
858 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
859 int
860 pe__cluster_stack_html(pcmk__output_t *out, va_list args) {
861 xmlNodePtr node = pcmk__output_create_xml_node(out, "li");
862 const char *stack_s = va_arg(args, const char *);
863
864 pcmk_create_html_node(node, "span", NULL, "bold", "Stack: ");
865 pcmk_create_html_node(node, "span", NULL, NULL, stack_s);
866
867 return pcmk_rc_ok;
868 }
869
870 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
871 int
872 pe__cluster_stack_text(pcmk__output_t *out, va_list args) {
873 const char *stack_s = va_arg(args, const char *);
874 out->list_item(out, "Stack", "%s", stack_s);
875 return pcmk_rc_ok;
876 }
877
878 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
879 int
880 pe__cluster_stack_xml(pcmk__output_t *out, va_list args) {
881 xmlNodePtr node = pcmk__output_create_xml_node(out, "stack");
882 const char *stack_s = va_arg(args, const char *);
883
884 xmlSetProp(node, (pcmkXmlStr) "type", (pcmkXmlStr) stack_s);
885
886 return pcmk_rc_ok;
887 }
888
889 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
890 int
891 pe__cluster_times_html(pcmk__output_t *out, va_list args) {
892 xmlNodePtr updated_node = pcmk__output_create_xml_node(out, "li");
893 xmlNodePtr changed_node = pcmk__output_create_xml_node(out, "li");
894
895 const char *last_written = va_arg(args, const char *);
896 const char *user = va_arg(args, const char *);
897 const char *client = va_arg(args, const char *);
898 const char *origin = va_arg(args, const char *);
899
900 char *buf = last_changed_string(last_written, user, client, origin);
901
902 pcmk_create_html_node(updated_node, "span", NULL, "bold", "Last updated: ");
903 pcmk_create_html_node(updated_node, "span", NULL, NULL,
904 pcmk__epoch2str(NULL));
905
906 pcmk_create_html_node(changed_node, "span", NULL, "bold", "Last change: ");
907 pcmk_create_html_node(changed_node, "span", NULL, NULL, buf);
908
909 free(buf);
910 return pcmk_rc_ok;
911 }
912
913 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
914 int
915 pe__cluster_times_xml(pcmk__output_t *out, va_list args) {
916 xmlNodePtr updated_node = pcmk__output_create_xml_node(out, "last_update");
917 xmlNodePtr changed_node = pcmk__output_create_xml_node(out, "last_change");
918
919 const char *last_written = va_arg(args, const char *);
920 const char *user = va_arg(args, const char *);
921 const char *client = va_arg(args, const char *);
922 const char *origin = va_arg(args, const char *);
923
924 xmlSetProp(updated_node, (pcmkXmlStr) "time",
925 (pcmkXmlStr) pcmk__epoch2str(NULL));
926 xmlSetProp(changed_node, (pcmkXmlStr) "time", (pcmkXmlStr) (last_written ? last_written : ""));
927 xmlSetProp(changed_node, (pcmkXmlStr) "user", (pcmkXmlStr) (user ? user : ""));
928 xmlSetProp(changed_node, (pcmkXmlStr) "client", (pcmkXmlStr) (client ? client : ""));
929 xmlSetProp(changed_node, (pcmkXmlStr) "origin", (pcmkXmlStr) (origin ? origin : ""));
930
931 return pcmk_rc_ok;
932 }
933
934 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
935 int
936 pe__cluster_times_text(pcmk__output_t *out, va_list args) {
937 const char *last_written = va_arg(args, const char *);
938 const char *user = va_arg(args, const char *);
939 const char *client = va_arg(args, const char *);
940 const char *origin = va_arg(args, const char *);
941
942 char *buf = last_changed_string(last_written, user, client, origin);
943
944 out->list_item(out, "Last updated", "%s", pcmk__epoch2str(NULL));
945 out->list_item(out, "Last change", " %s", buf);
946
947 free(buf);
948 return pcmk_rc_ok;
949 }
950
951 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
952 int
953 pe__failed_action_text(pcmk__output_t *out, va_list args) {
954 xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
955 char *s = failed_action_string(xml_op);
956
957 out->list_item(out, NULL, "%s", s);
958 free(s);
959 return pcmk_rc_ok;
960 }
961
962 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
963 int
964 pe__failed_action_xml(pcmk__output_t *out, va_list args) {
965 xmlNodePtr xml_op = va_arg(args, xmlNodePtr);
966
967 const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
968 const char *last = crm_element_value(xml_op, XML_RSC_OP_LAST_CHANGE);
969 int rc = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_RC), "0");
970 int status = crm_parse_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS), "0");
971 const char *exit_reason = crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON);
972
973 char *rc_s = crm_itoa(rc);
974 char *reason_s = crm_xml_escape(exit_reason ? exit_reason : "none");
975 xmlNodePtr node = pcmk__output_create_xml_node(out, "failure");
976
977 xmlSetProp(node, (pcmkXmlStr) (op_key ? "op_key" : "id"),
978 (pcmkXmlStr) (op_key ? op_key : "id"));
979 xmlSetProp(node, (pcmkXmlStr) "node",
980 (pcmkXmlStr) crm_element_value(xml_op, XML_ATTR_UNAME));
981 xmlSetProp(node, (pcmkXmlStr) "exitstatus",
982 (pcmkXmlStr) services_ocf_exitcode_str(rc));
983 xmlSetProp(node, (pcmkXmlStr) "exitreason", (pcmkXmlStr) reason_s);
984 xmlSetProp(node, (pcmkXmlStr) "exitcode", (pcmkXmlStr) rc_s);
985 xmlSetProp(node, (pcmkXmlStr) "call",
986 (pcmkXmlStr) crm_element_value(xml_op, XML_LRM_ATTR_CALLID));
987 xmlSetProp(node, (pcmkXmlStr) "status",
988 (pcmkXmlStr) services_lrm_status_str(status));
989
990 if (last) {
991 guint interval_ms = 0;
992 char *s = NULL;
993 time_t when = crm_parse_int(last, "0");
994 crm_time_t *crm_when = crm_time_new(NULL);
995 char *rc_change = NULL;
996
997 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
998 s = crm_itoa(interval_ms);
999
1000 crm_time_set_timet(crm_when, &when);
1001 rc_change = crm_time_as_string(crm_when, crm_time_log_date | crm_time_log_timeofday | crm_time_log_with_timezone);
1002
1003 xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_CHANGE, (pcmkXmlStr) rc_change);
1004 xmlSetProp(node, (pcmkXmlStr) "queued",
1005 (pcmkXmlStr) crm_element_value(xml_op, XML_RSC_OP_T_QUEUE));
1006 xmlSetProp(node, (pcmkXmlStr) "exec",
1007 (pcmkXmlStr) crm_element_value(xml_op, XML_RSC_OP_T_EXEC));
1008 xmlSetProp(node, (pcmkXmlStr) "interval", (pcmkXmlStr) s);
1009 xmlSetProp(node, (pcmkXmlStr) "task",
1010 (pcmkXmlStr) crm_element_value(xml_op, XML_LRM_ATTR_TASK));
1011
1012 free(s);
1013 free(rc_change);
1014 crm_time_free(crm_when);
1015 }
1016
1017 free(reason_s);
1018 free(rc_s);
1019 return pcmk_rc_ok;
1020 }
1021
1022 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1023 "gboolean", "gboolean", "gboolean", "GListPtr", "GListPtr")
1024 int
1025 pe__node_html(pcmk__output_t *out, va_list args) {
1026 pe_node_t *node = va_arg(args, pe_node_t *);
1027 unsigned int print_opts = va_arg(args, unsigned int);
1028 gboolean full = va_arg(args, gboolean);
1029 const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1030 gboolean print_clone_detail = va_arg(args, gboolean);
1031 gboolean print_brief = va_arg(args, gboolean);
1032 gboolean group_by_node = va_arg(args, gboolean);
1033 GListPtr only_node = va_arg(args, GListPtr);
1034 GListPtr only_rsc = va_arg(args, GListPtr);
1035
1036 char *node_name = pe__node_display_name(node, print_clone_detail);
1037 char *buf = crm_strdup_printf("Node: %s", node_name);
1038
1039 if (full) {
1040 xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li");
1041
1042 pcmk_create_html_node(item_node, "span", NULL, NULL, buf);
1043
1044 if (node->details->standby_onfail && node->details->online) {
1045 pcmk_create_html_node(item_node, "span", NULL, "standby", " standby (on-fail)");
1046 } else if (node->details->standby && node->details->online) {
1047 char *s = crm_strdup_printf(" standby%s", node->details->running_rsc ? " (with active resources)" : "");
1048 pcmk_create_html_node(item_node, "span", NULL, " standby", s);
1049 free(s);
1050 } else if (node->details->standby) {
1051 pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE (standby)");
1052 } else if (node->details->maintenance && node->details->online) {
1053 pcmk_create_html_node(item_node, "span", NULL, "maint", " maintenance");
1054 } else if (node->details->maintenance) {
1055 pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE (maintenance)");
1056 } else if (node->details->online) {
1057 pcmk_create_html_node(item_node, "span", NULL, "online", " online");
1058 } else {
1059 pcmk_create_html_node(item_node, "span", NULL, "offline", " OFFLINE");
1060 }
1061 if (print_brief && group_by_node) {
1062 GListPtr rscs = pe__filter_rsc_list(node->details->running_rsc, only_rsc);
1063
1064 if (rscs != NULL) {
1065 out->begin_list(out, NULL, NULL, NULL);
1066 pe__rscs_brief_output(out, rscs, print_opts | pe_print_rsconly, FALSE);
1067 out->end_list(out);
1068 }
1069
1070 } else if (group_by_node) {
1071 GListPtr lpc2 = NULL;
1072
1073 out->begin_list(out, NULL, NULL, NULL);
1074 for (lpc2 = node->details->running_rsc; lpc2 != NULL; lpc2 = lpc2->next) {
1075 pe_resource_t *rsc = (pe_resource_t *) lpc2->data;
1076 out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly,
1077 rsc, only_node, only_rsc);
1078 }
1079 out->end_list(out);
1080 }
1081 } else {
1082 out->begin_list(out, NULL, NULL, "%s", buf);
1083 }
1084
1085 free(buf);
1086 free(node_name);
1087 return pcmk_rc_ok;
1088 }
1089
1090 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1091 "gboolean", "gboolean", "gboolean", "GListPtr", "GListPtr")
1092 int
1093 pe__node_text(pcmk__output_t *out, va_list args) {
1094 pe_node_t *node = va_arg(args, pe_node_t *);
1095 unsigned int print_opts = va_arg(args, unsigned int);
1096 gboolean full = va_arg(args, gboolean);
1097 const char *node_mode = va_arg(args, const char *);
1098 gboolean print_clone_detail = va_arg(args, gboolean);
1099 gboolean print_brief = va_arg(args, gboolean);
1100 gboolean group_by_node = va_arg(args, gboolean);
1101 GListPtr only_node = va_arg(args, GListPtr);
1102 GListPtr only_rsc = va_arg(args, GListPtr);
1103
1104 if (full) {
1105 char *node_name = pe__node_display_name(node, print_clone_detail);
1106 char *buf = NULL;
1107
1108
1109 if (pe__is_guest_node(node)) {
1110 buf = crm_strdup_printf("GuestNode %s: %s", node_name, node_mode);
1111 } else if (pe__is_remote_node(node)) {
1112 buf = crm_strdup_printf("RemoteNode %s: %s", node_name, node_mode);
1113 } else {
1114 buf = crm_strdup_printf("Node %s: %s", node_name, node_mode);
1115 }
1116
1117
1118 if (group_by_node) {
1119 if (print_brief) {
1120 GListPtr rscs = pe__filter_rsc_list(node->details->running_rsc, only_rsc);
1121
1122 if (rscs != NULL) {
1123 out->begin_list(out, NULL, NULL, "%s", buf);
1124 out->begin_list(out, NULL, NULL, "Resources");
1125
1126 pe__rscs_brief_output(out, rscs, print_opts | pe_print_rsconly, FALSE);
1127
1128 out->end_list(out);
1129 out->end_list(out);
1130 }
1131
1132 } else {
1133 GListPtr gIter2 = NULL;
1134
1135 out->begin_list(out, NULL, NULL, "%s", buf);
1136 out->begin_list(out, NULL, NULL, "Resources");
1137
1138 for (gIter2 = node->details->running_rsc; gIter2 != NULL; gIter2 = gIter2->next) {
1139 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
1140 out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly,
1141 rsc, only_node, only_rsc);
1142 }
1143
1144 out->end_list(out);
1145 out->end_list(out);
1146 }
1147 } else {
1148 out->list_item(out, NULL, "%s", buf);
1149 }
1150
1151 free(buf);
1152 free(node_name);
1153 } else {
1154 out->begin_list(out, NULL, NULL, "Node: %s", pe__node_display_name(node, print_clone_detail));
1155 }
1156
1157 return pcmk_rc_ok;
1158 }
1159
1160 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1161 "gboolean", "gboolean", "gboolean", "GListPtr", "GListPtr")
1162 int
1163 pe__node_xml(pcmk__output_t *out, va_list args) {
1164 pe_node_t *node = va_arg(args, pe_node_t *);
1165 unsigned int print_opts = va_arg(args, unsigned int);
1166 gboolean full = va_arg(args, gboolean);
1167 const char *node_mode G_GNUC_UNUSED = va_arg(args, const char *);
1168 gboolean print_clone_detail G_GNUC_UNUSED = va_arg(args, gboolean);
1169 gboolean print_brief G_GNUC_UNUSED = va_arg(args, gboolean);
1170 gboolean group_by_node = va_arg(args, gboolean);
1171 GListPtr only_node = va_arg(args, GListPtr);
1172 GListPtr only_rsc = va_arg(args, GListPtr);
1173
1174 if (full) {
1175 const char *node_type = "unknown";
1176 char *length_s = crm_itoa(g_list_length(node->details->running_rsc));
1177
1178 switch (node->details->type) {
1179 case node_member:
1180 node_type = "member";
1181 break;
1182 case node_remote:
1183 node_type = "remote";
1184 break;
1185 case node_ping:
1186 node_type = "ping";
1187 break;
1188 }
1189 pe__name_and_nvpairs_xml(out, true, "node", 13,
1190 "name", node->details->uname,
1191 "id", node->details->id,
1192 "online", pcmk__btoa(node->details->online),
1193 "standby", pcmk__btoa(node->details->standby),
1194 "standby_onfail", pcmk__btoa(node->details->standby_onfail),
1195 "maintenance", pcmk__btoa(node->details->maintenance),
1196 "pending", pcmk__btoa(node->details->pending),
1197 "unclean", pcmk__btoa(node->details->unclean),
1198 "shutdown", pcmk__btoa(node->details->shutdown),
1199 "expected_up", pcmk__btoa(node->details->expected_up),
1200 "is_dc", pcmk__btoa(node->details->is_dc),
1201 "resources_running", length_s,
1202 "type", node_type);
1203
1204 if (pe__is_guest_node(node)) {
1205 xmlNodePtr xml_node = pcmk__output_xml_peek_parent(out);
1206 xmlSetProp(xml_node, (pcmkXmlStr) "id_as_resource",
1207 (pcmkXmlStr) node->details->remote_rsc->container->id);
1208 }
1209
1210 if (group_by_node) {
1211 GListPtr lpc = NULL;
1212
1213 for (lpc = node->details->running_rsc; lpc != NULL; lpc = lpc->next) {
1214 pe_resource_t *rsc = (pe_resource_t *) lpc->data;
1215 out->message(out, crm_map_element_name(rsc->xml), print_opts | pe_print_rsconly,
1216 rsc, only_node, only_rsc);
1217 }
1218 }
1219
1220 free(length_s);
1221
1222 out->end_list(out);
1223 } else {
1224 xmlNodePtr parent = pcmk__output_xml_create_parent(out, "node");
1225 xmlSetProp(parent, (pcmkXmlStr) "name", (pcmkXmlStr) node->details->uname);
1226 }
1227
1228 return pcmk_rc_ok;
1229 }
1230
1231 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1232 int
1233 pe__node_attribute_text(pcmk__output_t *out, va_list args) {
1234 const char *name = va_arg(args, const char *);
1235 const char *value = va_arg(args, const char *);
1236 gboolean add_extra = va_arg(args, gboolean);
1237 int expected_score = va_arg(args, int);
1238
1239
1240 if (add_extra) {
1241 int v = crm_parse_int(value, "0");
1242
1243 if (v <= 0) {
1244 out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is lost", name, value);
1245 } else if (v < expected_score) {
1246 out->list_item(out, NULL, "%-32s\t: %-10s\t: Connectivity is degraded (Expected=%d)", name, value, expected_score);
1247 } else {
1248 out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1249 }
1250 } else {
1251 out->list_item(out, NULL, "%-32s\t: %-10s", name, value);
1252 }
1253
1254 return pcmk_rc_ok;
1255 }
1256
1257 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1258 int
1259 pe__node_attribute_html(pcmk__output_t *out, va_list args) {
1260 const char *name = va_arg(args, const char *);
1261 const char *value = va_arg(args, const char *);
1262 gboolean add_extra = va_arg(args, gboolean);
1263 int expected_score = va_arg(args, int);
1264
1265 if (add_extra) {
1266 int v = crm_parse_int(value, "0");
1267 char *s = crm_strdup_printf("%s: %s", name, value);
1268 xmlNodePtr item_node = pcmk__output_create_xml_node(out, "li");
1269
1270 pcmk_create_html_node(item_node, "span", NULL, NULL, s);
1271 free(s);
1272
1273 if (v <= 0) {
1274 pcmk_create_html_node(item_node, "span", NULL, "bold", "(connectivity is lost)");
1275 } else if (v < expected_score) {
1276 char *buf = crm_strdup_printf("(connectivity is degraded -- expected %d", expected_score);
1277 pcmk_create_html_node(item_node, "span", NULL, "bold", buf);
1278 free(buf);
1279 }
1280 } else {
1281 out->list_item(out, NULL, "%s: %s", name, value);
1282 }
1283
1284 return pcmk_rc_ok;
1285 }
1286
1287 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1288 int
1289 pe__node_attribute_xml(pcmk__output_t *out, va_list args) {
1290 const char *name = va_arg(args, const char *);
1291 const char *value = va_arg(args, const char *);
1292 gboolean add_extra = va_arg(args, gboolean);
1293 int expected_score = va_arg(args, int);
1294
1295 xmlNodePtr node = pcmk__output_create_xml_node(out, "attribute");
1296 xmlSetProp(node, (pcmkXmlStr) "name", (pcmkXmlStr) name);
1297 xmlSetProp(node, (pcmkXmlStr) "value", (pcmkXmlStr) value);
1298
1299 if (add_extra) {
1300 char *buf = crm_itoa(expected_score);
1301 xmlSetProp(node, (pcmkXmlStr) "expected", (pcmkXmlStr) buf);
1302 free(buf);
1303 }
1304
1305 return pcmk_rc_ok;
1306 }
1307
1308 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1309 int
1310 pe__node_list_html(pcmk__output_t *out, va_list args) {
1311 GListPtr nodes = va_arg(args, GListPtr);
1312 GListPtr only_node = va_arg(args, GListPtr);
1313 GListPtr only_rsc = va_arg(args, GListPtr);
1314 unsigned int print_opts = va_arg(args, unsigned int);
1315 gboolean print_clone_detail = va_arg(args, gboolean);
1316 gboolean print_brief = va_arg(args, gboolean);
1317 gboolean group_by_node = va_arg(args, gboolean);
1318
1319 int rc = pcmk_rc_no_output;
1320
1321 for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1322 pe_node_t *node = (pe_node_t *) gIter->data;
1323
1324 if (!pcmk__str_in_list(only_node, node->details->uname)) {
1325 continue;
1326 }
1327
1328 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Node List");
1329
1330 out->message(out, "node", node, print_opts, TRUE, NULL, print_clone_detail,
1331 print_brief, group_by_node, only_node, only_rsc);
1332 }
1333
1334 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1335 return rc;
1336 }
1337
1338 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1339 int
1340 pe__node_list_text(pcmk__output_t *out, va_list args) {
1341 GListPtr nodes = va_arg(args, GListPtr);
1342 GListPtr only_node = va_arg(args, GListPtr);
1343 GListPtr only_rsc = va_arg(args, GListPtr);
1344 unsigned int print_opts = va_arg(args, unsigned int);
1345 gboolean print_clone_detail = va_arg(args, gboolean);
1346 gboolean print_brief = va_arg(args, gboolean);
1347 gboolean group_by_node = va_arg(args, gboolean);
1348
1349
1350 char *online_nodes = NULL;
1351 char *online_remote_nodes = NULL;
1352 char *online_guest_nodes = NULL;
1353 char *offline_nodes = NULL;
1354 char *offline_remote_nodes = NULL;
1355
1356 size_t online_nodes_len = 0;
1357 size_t online_remote_nodes_len = 0;
1358 size_t online_guest_nodes_len = 0;
1359 size_t offline_nodes_len = 0;
1360 size_t offline_remote_nodes_len = 0;
1361
1362 int rc = pcmk_rc_no_output;
1363
1364 for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1365 pe_node_t *node = (pe_node_t *) gIter->data;
1366 const char *node_mode = NULL;
1367 char *node_name = pe__node_display_name(node, print_clone_detail);
1368
1369 if (!pcmk__str_in_list(only_node, node->details->uname)) {
1370 free(node_name);
1371 continue;
1372 }
1373
1374 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Node List");
1375
1376
1377 if (node->details->unclean) {
1378 if (node->details->online) {
1379 node_mode = "UNCLEAN (online)";
1380
1381 } else if (node->details->pending) {
1382 node_mode = "UNCLEAN (pending)";
1383
1384 } else {
1385 node_mode = "UNCLEAN (offline)";
1386 }
1387
1388 } else if (node->details->pending) {
1389 node_mode = "pending";
1390
1391 } else if (node->details->standby_onfail && node->details->online) {
1392 node_mode = "standby (on-fail)";
1393
1394 } else if (node->details->standby) {
1395 if (node->details->online) {
1396 if (node->details->running_rsc) {
1397 node_mode = "standby (with active resources)";
1398 } else {
1399 node_mode = "standby";
1400 }
1401 } else {
1402 node_mode = "OFFLINE (standby)";
1403 }
1404
1405 } else if (node->details->maintenance) {
1406 if (node->details->online) {
1407 node_mode = "maintenance";
1408 } else {
1409 node_mode = "OFFLINE (maintenance)";
1410 }
1411
1412 } else if (node->details->online) {
1413 node_mode = "online";
1414 if (group_by_node == FALSE) {
1415 if (pe__is_guest_node(node)) {
1416 pcmk__add_word(&online_guest_nodes,
1417 &online_guest_nodes_len, node_name);
1418 } else if (pe__is_remote_node(node)) {
1419 pcmk__add_word(&online_remote_nodes,
1420 &online_remote_nodes_len, node_name);
1421 } else {
1422 pcmk__add_word(&online_nodes, &online_nodes_len, node_name);
1423 }
1424 free(node_name);
1425 continue;
1426 }
1427
1428 } else {
1429 node_mode = "OFFLINE";
1430 if (group_by_node == FALSE) {
1431 if (pe__is_remote_node(node)) {
1432 pcmk__add_word(&offline_remote_nodes,
1433 &offline_remote_nodes_len, node_name);
1434 } else if (pe__is_guest_node(node)) {
1435
1436 } else {
1437 pcmk__add_word(&offline_nodes,
1438 &offline_nodes_len, node_name);
1439 }
1440 free(node_name);
1441 continue;
1442 }
1443 }
1444
1445
1446 out->message(out, "node", node, print_opts, TRUE, node_mode, print_clone_detail,
1447 print_brief, group_by_node, only_node, only_rsc);
1448 free(node_name);
1449 }
1450
1451
1452 if (online_nodes) {
1453 out->list_item(out, "Online", "[ %s ]", online_nodes);
1454 free(online_nodes);
1455 }
1456 if (offline_nodes) {
1457 out->list_item(out, "OFFLINE", "[ %s ]", offline_nodes);
1458 free(offline_nodes);
1459 }
1460 if (online_remote_nodes) {
1461 out->list_item(out, "RemoteOnline", "[ %s ]", online_remote_nodes);
1462 free(online_remote_nodes);
1463 }
1464 if (offline_remote_nodes) {
1465 out->list_item(out, "RemoteOFFLINE", "[ %s ]", offline_remote_nodes);
1466 free(offline_remote_nodes);
1467 }
1468 if (online_guest_nodes) {
1469 out->list_item(out, "GuestOnline", "[ %s ]", online_guest_nodes);
1470 free(online_guest_nodes);
1471 }
1472
1473 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1474 return rc;
1475 }
1476
1477 PCMK__OUTPUT_ARGS("node-list", "GListPtr", "GListPtr", "GListPtr", "unsigned int", "gboolean", "gboolean", "gboolean")
1478 int
1479 pe__node_list_xml(pcmk__output_t *out, va_list args) {
1480 GListPtr nodes = va_arg(args, GListPtr);
1481 GListPtr only_node = va_arg(args, GListPtr);
1482 GListPtr only_rsc = va_arg(args, GListPtr);
1483 unsigned int print_opts = va_arg(args, unsigned int);
1484 gboolean print_clone_detail = va_arg(args, gboolean);
1485 gboolean print_brief = va_arg(args, gboolean);
1486 gboolean group_by_node = va_arg(args, gboolean);
1487
1488 out->begin_list(out, NULL, NULL, "nodes");
1489 for (GListPtr gIter = nodes; gIter != NULL; gIter = gIter->next) {
1490 pe_node_t *node = (pe_node_t *) gIter->data;
1491
1492 if (!pcmk__str_in_list(only_node, node->details->uname)) {
1493 continue;
1494 }
1495
1496 out->message(out, "node", node, print_opts, TRUE, NULL, print_clone_detail,
1497 print_brief, group_by_node, only_node, only_rsc);
1498 }
1499 out->end_list(out);
1500
1501 return pcmk_rc_ok;
1502 }
1503
1504 PCMK__OUTPUT_ARGS("op-history", "struct xmlNode *", "const char *", "const char *", "int", "gboolean")
1505 int
1506 pe__op_history_text(pcmk__output_t *out, va_list args) {
1507 xmlNode *xml_op = va_arg(args, xmlNode *);
1508 const char *task = va_arg(args, const char *);
1509 const char *interval_ms_s = va_arg(args, const char *);
1510 int rc = va_arg(args, int);
1511 gboolean print_timing = va_arg(args, gboolean);
1512
1513 char *buf = op_history_string(xml_op, task, interval_ms_s, rc, print_timing);
1514
1515 out->list_item(out, NULL, "%s", buf);
1516
1517 free(buf);
1518 return pcmk_rc_ok;
1519 }
1520
1521 PCMK__OUTPUT_ARGS("op-history", "struct xmlNode *", "const char *", "const char *", "int", "gboolean")
1522 int
1523 pe__op_history_xml(pcmk__output_t *out, va_list args) {
1524 xmlNode *xml_op = va_arg(args, xmlNode *);
1525 const char *task = va_arg(args, const char *);
1526 const char *interval_ms_s = va_arg(args, const char *);
1527 int rc = va_arg(args, int);
1528 gboolean print_timing = va_arg(args, gboolean);
1529
1530 char *rc_s = NULL;
1531
1532 xmlNodePtr node = pcmk__output_create_xml_node(out, "operation_history");
1533
1534 xmlSetProp(node, (pcmkXmlStr) "call",
1535 (pcmkXmlStr) crm_element_value(xml_op, XML_LRM_ATTR_CALLID));
1536 xmlSetProp(node, (pcmkXmlStr) "task", (pcmkXmlStr) task);
1537
1538 if (interval_ms_s && !pcmk__str_eq(interval_ms_s, "0", pcmk__str_casei)) {
1539 char *s = crm_strdup_printf("%sms", interval_ms_s);
1540 xmlSetProp(node, (pcmkXmlStr) "interval", (pcmkXmlStr) s);
1541 free(s);
1542 }
1543
1544 if (print_timing) {
1545 const char *value = NULL;
1546
1547 value = crm_element_value(xml_op, XML_RSC_OP_LAST_CHANGE);
1548 if (value) {
1549 time_t int_value = (time_t) crm_parse_int(value, NULL);
1550 if (int_value > 0) {
1551 xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_CHANGE,
1552 (pcmkXmlStr) pcmk__epoch2str(&int_value));
1553 }
1554 }
1555
1556 value = crm_element_value(xml_op, XML_RSC_OP_LAST_RUN);
1557 if (value) {
1558 time_t int_value = (time_t) crm_parse_int(value, NULL);
1559 if (int_value > 0) {
1560 xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_LAST_RUN,
1561 (pcmkXmlStr) pcmk__epoch2str(&int_value));
1562 }
1563 }
1564
1565 value = crm_element_value(xml_op, XML_RSC_OP_T_EXEC);
1566 if (value) {
1567 char *s = crm_strdup_printf("%sms", value);
1568 xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_T_EXEC, (pcmkXmlStr) s);
1569 free(s);
1570 }
1571 value = crm_element_value(xml_op, XML_RSC_OP_T_QUEUE);
1572 if (value) {
1573 char *s = crm_strdup_printf("%sms", value);
1574 xmlSetProp(node, (pcmkXmlStr) XML_RSC_OP_T_QUEUE, (pcmkXmlStr) s);
1575 free(s);
1576 }
1577 }
1578
1579 rc_s = crm_itoa(rc);
1580 xmlSetProp(node, (pcmkXmlStr) "rc", (pcmkXmlStr) rc_s);
1581 xmlSetProp(node, (pcmkXmlStr) "rc_text", (pcmkXmlStr) services_ocf_exitcode_str(rc));
1582 free(rc_s);
1583 return pcmk_rc_ok;
1584 }
1585
1586 PCMK__OUTPUT_ARGS("resource-history", "pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
1587 int
1588 pe__resource_history_text(pcmk__output_t *out, va_list args) {
1589 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1590 const char *rsc_id = va_arg(args, const char *);
1591 gboolean all = va_arg(args, gboolean);
1592 int failcount = va_arg(args, int);
1593 time_t last_failure = va_arg(args, int);
1594 gboolean as_header = va_arg(args, gboolean);
1595
1596 char *buf = resource_history_string(rsc, rsc_id, all, failcount, last_failure);
1597
1598 if (as_header) {
1599 out->begin_list(out, NULL, NULL, "%s", buf);
1600 } else {
1601 out->list_item(out, NULL, "%s", buf);
1602 }
1603
1604 free(buf);
1605 return pcmk_rc_ok;
1606 }
1607
1608 PCMK__OUTPUT_ARGS("resource-history", "pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
1609 int
1610 pe__resource_history_xml(pcmk__output_t *out, va_list args) {
1611 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1612 const char *rsc_id = va_arg(args, const char *);
1613 gboolean all = va_arg(args, gboolean);
1614 int failcount = va_arg(args, int);
1615 time_t last_failure = va_arg(args, int);
1616 gboolean as_header = va_arg(args, gboolean);
1617
1618 xmlNodePtr node = pcmk__output_xml_create_parent(out, "resource_history");
1619 xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) rsc_id);
1620
1621 if (rsc == NULL) {
1622 xmlSetProp(node, (pcmkXmlStr) "orphan", (pcmkXmlStr) "true");
1623 } else if (all || failcount || last_failure > 0) {
1624 char *migration_s = crm_itoa(rsc->migration_threshold);
1625
1626 xmlSetProp(node, (pcmkXmlStr) "orphan", (pcmkXmlStr) "false");
1627 xmlSetProp(node, (pcmkXmlStr) "migration-threshold",
1628 (pcmkXmlStr) migration_s);
1629 free(migration_s);
1630
1631 if (failcount > 0) {
1632 char *s = crm_itoa(failcount);
1633
1634 xmlSetProp(node, (pcmkXmlStr) PCMK__FAIL_COUNT_PREFIX,
1635 (pcmkXmlStr) s);
1636 free(s);
1637 }
1638
1639 if (last_failure > 0) {
1640 xmlSetProp(node, (pcmkXmlStr) PCMK__LAST_FAILURE_PREFIX,
1641 (pcmkXmlStr) pcmk__epoch2str(&last_failure));
1642 }
1643 }
1644
1645 if (as_header == FALSE) {
1646 pcmk__output_xml_pop_parent(out);
1647 }
1648
1649 return pcmk_rc_ok;
1650 }
1651
1652 PCMK__OUTPUT_ARGS("resource-list", "pe_working_set_t *", "unsigned int", "gboolean",
1653 "gboolean", "gboolean", "gboolean", "GListPtr", "GListPtr", "gboolean")
1654 int
1655 pe__resource_list(pcmk__output_t *out, va_list args)
1656 {
1657 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
1658 unsigned int print_opts = va_arg(args, unsigned int);
1659 gboolean group_by_node = va_arg(args, gboolean);
1660 gboolean inactive_resources = va_arg(args, gboolean);
1661 gboolean brief_output = va_arg(args, gboolean);
1662 gboolean print_summary = va_arg(args, gboolean);
1663 GListPtr only_node = va_arg(args, GListPtr);
1664 GListPtr only_rsc = va_arg(args, GListPtr);
1665 gboolean print_spacer = va_arg(args, gboolean);
1666
1667 GListPtr rsc_iter;
1668 int rc = pcmk_rc_no_output;
1669
1670
1671
1672
1673 if (group_by_node && !inactive_resources) {
1674 return rc;
1675 }
1676
1677 PCMK__OUTPUT_SPACER_IF(out, print_spacer);
1678
1679 if (group_by_node) {
1680
1681 out->begin_list(out, NULL, NULL, "Inactive Resources");
1682 } else if (inactive_resources) {
1683 out->begin_list(out, NULL, NULL, "Full List of Resources");
1684 } else {
1685 out->begin_list(out, NULL, NULL, "Active Resources");
1686 }
1687
1688
1689
1690 if (brief_output && !group_by_node) {
1691 GListPtr rscs = pe__filter_rsc_list(data_set->resources, only_rsc);
1692
1693 pe__rscs_brief_output(out, rscs, print_opts, inactive_resources);
1694 g_list_free(rscs);
1695 }
1696
1697
1698 for (rsc_iter = data_set->resources; rsc_iter != NULL; rsc_iter = rsc_iter->next) {
1699 pe_resource_t *rsc = (pe_resource_t *) rsc_iter->data;
1700 int x;
1701
1702
1703 gboolean is_active = rsc->fns->active(rsc, TRUE);
1704 gboolean partially_active = rsc->fns->active(rsc, FALSE);
1705
1706
1707 if (pcmk_is_set(rsc->flags, pe_rsc_orphan) && !is_active) {
1708 continue;
1709
1710
1711 } else if (group_by_node) {
1712 if (is_active) {
1713 continue;
1714 }
1715
1716
1717 } else if (brief_output && (rsc->variant == pe_native)) {
1718 continue;
1719
1720
1721
1722
1723 } else if (!partially_active && !inactive_resources) {
1724 continue;
1725
1726 } else if (partially_active && !pe__rsc_running_on_any_node_in_list(rsc, only_node)) {
1727 continue;
1728 }
1729
1730
1731 x = out->message(out, crm_map_element_name(rsc->xml), print_opts, rsc,
1732 only_node, only_rsc);
1733 if (x == pcmk_rc_ok) {
1734 rc = pcmk_rc_ok;
1735 }
1736 }
1737
1738 if (print_summary && rc != pcmk_rc_ok) {
1739 if (group_by_node) {
1740 out->list_item(out, NULL, "No inactive resources");
1741 } else if (inactive_resources) {
1742 out->list_item(out, NULL, "No resources");
1743 } else {
1744 out->list_item(out, NULL, "No active resources");
1745 }
1746 }
1747
1748 out->end_list(out);
1749 return rc;
1750 }
1751
1752 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
1753 int
1754 pe__ticket_html(pcmk__output_t *out, va_list args) {
1755 pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1756
1757 if (ticket->last_granted > -1) {
1758 char *time = pcmk_format_named_time("last-granted", ticket->last_granted);
1759 out->list_item(out, NULL, "%s:\t%s%s %s", ticket->id,
1760 ticket->granted ? "granted" : "revoked",
1761 ticket->standby ? " [standby]" : "",
1762 time);
1763 free(time);
1764 } else {
1765 out->list_item(out, NULL, "%s:\t%s%s", ticket->id,
1766 ticket->granted ? "granted" : "revoked",
1767 ticket->standby ? " [standby]" : "");
1768 }
1769
1770 return pcmk_rc_ok;
1771 }
1772
1773 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
1774 int
1775 pe__ticket_text(pcmk__output_t *out, va_list args) {
1776 pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1777
1778 if (ticket->last_granted > -1) {
1779 char *time = pcmk_format_named_time("last-granted", ticket->last_granted);
1780 out->list_item(out, ticket->id, "\t%s%s %s",
1781 ticket->granted ? "granted" : "revoked",
1782 ticket->standby ? " [standby]" : "",
1783 time);
1784 free(time);
1785 } else {
1786 out->list_item(out, ticket->id, "\t%s%s",
1787 ticket->granted ? "granted" : "revoked",
1788 ticket->standby ? " [standby]" : "");
1789 }
1790
1791 return pcmk_rc_ok;
1792 }
1793
1794 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
1795 int
1796 pe__ticket_xml(pcmk__output_t *out, va_list args) {
1797 xmlNodePtr node = NULL;
1798
1799 pe_ticket_t *ticket = va_arg(args, pe_ticket_t *);
1800
1801 node = pcmk__output_create_xml_node(out, "ticket");
1802 xmlSetProp(node, (pcmkXmlStr) "id", (pcmkXmlStr) ticket->id);
1803 xmlSetProp(node, (pcmkXmlStr) "status", (pcmkXmlStr) (ticket->granted ? "granted" : "revoked"));
1804 xmlSetProp(node, (pcmkXmlStr) "standby",
1805 (pcmkXmlStr) pcmk__btoa(ticket->standby));
1806
1807 if (ticket->last_granted > -1) {
1808 xmlSetProp(node, (pcmkXmlStr) "last-granted",
1809 (pcmkXmlStr) pcmk__epoch2str(&ticket->last_granted));
1810 }
1811
1812 return pcmk_rc_ok;
1813 }
1814
1815 static pcmk__message_entry_t fmt_functions[] = {
1816 { "ban", "html", pe__ban_html },
1817 { "ban", "log", pe__ban_text },
1818 { "ban", "text", pe__ban_text },
1819 { "ban", "xml", pe__ban_xml },
1820 { "bundle", "xml", pe__bundle_xml },
1821 { "bundle", "html", pe__bundle_html },
1822 { "bundle", "text", pe__bundle_text },
1823 { "bundle", "log", pe__bundle_text },
1824 { "clone", "xml", pe__clone_xml },
1825 { "clone", "html", pe__clone_html },
1826 { "clone", "text", pe__clone_text },
1827 { "clone", "log", pe__clone_text },
1828 { "cluster-counts", "html", pe__cluster_counts_html },
1829 { "cluster-counts", "log", pe__cluster_counts_text },
1830 { "cluster-counts", "text", pe__cluster_counts_text },
1831 { "cluster-counts", "xml", pe__cluster_counts_xml },
1832 { "cluster-dc", "html", pe__cluster_dc_html },
1833 { "cluster-dc", "log", pe__cluster_dc_text },
1834 { "cluster-dc", "text", pe__cluster_dc_text },
1835 { "cluster-dc", "xml", pe__cluster_dc_xml },
1836 { "cluster-options", "html", pe__cluster_options_html },
1837 { "cluster-options", "log", pe__cluster_options_log },
1838 { "cluster-options", "text", pe__cluster_options_text },
1839 { "cluster-options", "xml", pe__cluster_options_xml },
1840 { "cluster-summary", "default", pe__cluster_summary },
1841 { "cluster-summary", "html", pe__cluster_summary_html },
1842 { "cluster-stack", "html", pe__cluster_stack_html },
1843 { "cluster-stack", "log", pe__cluster_stack_text },
1844 { "cluster-stack", "text", pe__cluster_stack_text },
1845 { "cluster-stack", "xml", pe__cluster_stack_xml },
1846 { "cluster-times", "html", pe__cluster_times_html },
1847 { "cluster-times", "log", pe__cluster_times_text },
1848 { "cluster-times", "text", pe__cluster_times_text },
1849 { "cluster-times", "xml", pe__cluster_times_xml },
1850 { "failed-action", "html", pe__failed_action_text },
1851 { "failed-action", "log", pe__failed_action_text },
1852 { "failed-action", "text", pe__failed_action_text },
1853 { "failed-action", "xml", pe__failed_action_xml },
1854 { "group", "xml", pe__group_xml },
1855 { "group", "html", pe__group_html },
1856 { "group", "text", pe__group_text },
1857 { "group", "log", pe__group_text },
1858 { "maint-mode", "text", pe__cluster_maint_mode_text },
1859 { "node", "html", pe__node_html },
1860 { "node", "log", pe__node_text },
1861 { "node", "text", pe__node_text },
1862 { "node", "xml", pe__node_xml },
1863 { "node-list", "html", pe__node_list_html },
1864 { "node-list", "log", pe__node_list_text },
1865 { "node-list", "text", pe__node_list_text },
1866 { "node-list", "xml", pe__node_list_xml },
1867 { "node-attribute", "html", pe__node_attribute_html },
1868 { "node-attribute", "log", pe__node_attribute_text },
1869 { "node-attribute", "text", pe__node_attribute_text },
1870 { "node-attribute", "xml", pe__node_attribute_xml },
1871 { "op-history", "html", pe__op_history_text },
1872 { "op-history", "log", pe__op_history_text },
1873 { "op-history", "text", pe__op_history_text },
1874 { "op-history", "xml", pe__op_history_xml },
1875 { "primitive", "xml", pe__resource_xml },
1876 { "primitive", "html", pe__resource_html },
1877 { "primitive", "text", pe__resource_text },
1878 { "primitive", "log", pe__resource_text },
1879 { "resource-history", "default", pe__resource_history_text },
1880 { "resource-history", "xml", pe__resource_history_xml },
1881 { "resource-list", "default", pe__resource_list },
1882 { "ticket", "html", pe__ticket_html },
1883 { "ticket", "log", pe__ticket_text },
1884 { "ticket", "text", pe__ticket_text },
1885 { "ticket", "xml", pe__ticket_xml },
1886
1887 { NULL, NULL, NULL }
1888 };
1889
1890 void
1891 pe__register_messages(pcmk__output_t *out) {
1892 pcmk__register_messages(out, fmt_functions);
1893 }
1894
1895 void
1896 pe__output_node(pe_node_t *node, gboolean details, pcmk__output_t *out)
1897 {
1898 if (node == NULL) {
1899 crm_trace("<NULL>");
1900 return;
1901 }
1902
1903 CRM_ASSERT(node->details);
1904 crm_trace("%sNode %s: (weight=%d, fixed=%s)",
1905 node->details->online ? "" : "Unavailable/Unclean ",
1906 node->details->uname, node->weight, node->fixed ? "True" : "False");
1907
1908 if (details) {
1909 char *pe_mutable = strdup("\t\t");
1910 GListPtr gIter = node->details->running_rsc;
1911 GListPtr all = NULL;
1912
1913 all = g_list_prepend(all, strdup("*"));
1914
1915 crm_trace("\t\t===Node Attributes");
1916 g_hash_table_foreach(node->details->attrs, print_str_str, pe_mutable);
1917 free(pe_mutable);
1918
1919 crm_trace("\t\t=== Resources");
1920
1921 for (; gIter != NULL; gIter = gIter->next) {
1922 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1923
1924 out->message(out, crm_map_element_name(rsc->xml),
1925 pe_print_pending, rsc, all, all);
1926 }
1927
1928 g_list_free_full(all, free);
1929 }
1930 }