This source file includes following definitions.
- compare_attribute
- add_extra_info
- filter_attr_list
- get_operation_list
- add_dump_node
- append_dump_text
- 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
- role_desc
- 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
- status_node
- 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
- print_resource_header
- 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/common/xml_internal.h>
13 #include <crm/common/output.h>
14 #include <crm/cib/util.h>
15 #include <crm/msg_xml.h>
16 #include <crm/pengine/internal.h>
17
18
19 #define FILTER_STR { PCMK__FAIL_COUNT_PREFIX, PCMK__LAST_FAILURE_PREFIX, \
20 "shutdown", "terminate", "standby", "probe_complete", \
21 "#", NULL }
22
23 static int
24 compare_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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 static gboolean
48 add_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
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
94
95
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
107 static GList *
108 filter_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
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
125 static GList *
126 get_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,
134 XML_LRM_ATTR_INTERVAL_MS);
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
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
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
160 static void
161 add_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
167 static void
168 append_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
178 static char *
179 failed_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
187 pcmk__scan_min_int(crm_element_value(xml_op, XML_LRM_ATTR_RC), &rc, 0);
188 pcmk__scan_min_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS),
189 &status, 0);
190
191 if (crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE,
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);
198 time_s = crm_time_as_string(crm_when, crm_time_log_date | crm_time_log_timeofday | crm_time_log_with_timezone);
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),
204 crm_element_value(xml_op, XML_ATTR_UNAME),
205 services_ocf_exitcode_str(rc), rc,
206 crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
207 services_lrm_status_str(status),
208 exit_reason ? exit_reason : "none",
209 time_s,
210 crm_element_value(xml_op, XML_RSC_OP_T_QUEUE),
211 crm_element_value(xml_op, XML_RSC_OP_T_EXEC));
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),
219 crm_element_value(xml_op, XML_ATTR_UNAME),
220 services_ocf_exitcode_str(rc), rc,
221 crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
222 services_lrm_status_str(status),
223 exit_reason ? exit_reason : "none");
224 }
225 }
226
227 static const char *
228 get_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
235 static char *
236 last_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
252 static char *
253 op_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
274 if ((crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE, &epoch) == pcmk_ok)
275 && (epoch > 0)) {
276 char *time = pcmk__format_named_time(XML_RSC_OP_LAST_CHANGE, epoch);
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
327 static char *
328 resource_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'",
346 PCMK__LAST_FAILURE_PREFIX,
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
362 PCMK__OUTPUT_ARGS("cluster-summary", "pe_working_set_t *", "unsigned int", "unsigned int")
363 static int
364 cluster_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
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?
382 crm_element_value(dc_version, XML_NVPAIR_ATTR_VALUE)
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
414 PCMK__OUTPUT_LIST_FOOTER(out, rc);
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
423 PCMK__OUTPUT_ARGS("cluster-summary", "pe_working_set_t *", "unsigned int", "unsigned int")
424 static int
425 cluster_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
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?
443 crm_element_value(dc_version, XML_NVPAIR_ATTR_VALUE)
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
472
473
474
475 PCMK__OUTPUT_LIST_FOOTER(out, rc);
476
477 out->begin_list(out, NULL, NULL, "Config Options");
478 out->message(out, "cluster-options", data_set);
479 }
480
481 PCMK__OUTPUT_LIST_FOOTER(out, rc);
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
490 char *
491 pe__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
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 = "";
509 }
510 }
511
512
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
518 name_len = strlen(node->details->uname) + 1;
519 if (node_host) {
520 name_len += strlen(node_host) + 1;
521 }
522 if (node_id) {
523 name_len += strlen(node_id) + 3;
524 }
525
526
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
542 int
543 pe__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
573 static const char *
574 role_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
586 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "unsigned int")
587 static int
588 ban_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
606 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "unsigned int")
607 static int
608 ban_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
623 PCMK__OUTPUT_ARGS("ban", "pe_node_t *", "pe__location_t *", "unsigned int")
624 static int
625 ban_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
633 pcmk__output_create_xml_node(out, "ban",
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
640
641
642
643
644
645 "master_only", promoted_only,
646 NULL);
647
648 free(weight_s);
649 return pcmk_rc_ok;
650 }
651
652 PCMK__OUTPUT_ARGS("ban-list", "pe_working_set_t *", "const char *", "GList *",
653 "unsigned int", "gboolean")
654 static int
655 ban_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
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) &&
674 !pcmk__str_in_list(only_rsc, rsc_printable_id(uber_parent(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
688 PCMK__OUTPUT_LIST_FOOTER(out, rc);
689 return rc;
690 }
691
692 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
693 static int
694 cluster_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
754 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
755 static int
756 cluster_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
788 PCMK__OUTPUT_ARGS("cluster-counts", "unsigned int", "int", "int", "int")
789 static int
790 cluster_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
818 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
819 static int
820 cluster_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
852 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
853 static int
854 cluster_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
871 PCMK__OUTPUT_ARGS("cluster-dc", "pe_node_t *", "const char *", "const char *", "char *")
872 static int
873 cluster_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
896 PCMK__OUTPUT_ARGS("maint-mode", "unsigned long long int")
897 static int
898 cluster_maint_mode_text(pcmk__output_t *out, va_list args) {
899 unsigned long long flags = va_arg(args, unsigned long long);
900
901 if (pcmk_is_set(flags, pe_flag_maintenance_mode)) {
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;
905 } else if (pcmk_is_set(flags, pe_flag_stop_everything)) {
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
914 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
915 static int
916 cluster_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
943 case no_quorum_suicide:
944 out->list_item(out, NULL, "No quorum policy: Suicide");
945 break;
946 }
947
948 if (pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)) {
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
969 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
970 static int
971 cluster_options_log(pcmk__output_t *out, va_list args) {
972 pe_working_set_t *data_set = va_arg(args, pe_working_set_t *);
973
974 if (pcmk_is_set(data_set->flags, pe_flag_maintenance_mode)) {
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
983 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
984 static int
985 cluster_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
1020 PCMK__OUTPUT_ARGS("cluster-options", "pe_working_set_t *")
1021 static int
1022 cluster_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
1066 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1067 static int
1068 cluster_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
1079 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1080 static int
1081 cluster_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
1088 PCMK__OUTPUT_ARGS("cluster-stack", "const char *")
1089 static int
1090 cluster_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
1100 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1101 static int
1102 cluster_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
1124 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1125 static int
1126 cluster_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
1145 PCMK__OUTPUT_ARGS("cluster-times", "const char *", "const char *", "const char *", "const char *")
1146 static int
1147 cluster_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
1162 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
1163 static int
1164 failed_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
1174 PCMK__OUTPUT_ARGS("failed-action", "xmlNodePtr")
1175 static int
1176 failed_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
1189 pcmk__scan_min_int(crm_element_value(xml_op, XML_LRM_ATTR_RC), &rc, 0);
1190 pcmk__scan_min_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS),
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
1206 if ((crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE,
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);
1217 rc_change = crm_time_as_string(crm_when, crm_time_log_date | crm_time_log_timeofday | crm_time_log_with_timezone);
1218
1219 pcmk__xe_set_props(node, XML_RSC_OP_LAST_CHANGE, rc_change,
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
1235 PCMK__OUTPUT_ARGS("failed-action-list", "pe_working_set_t *", "GList *",
1236 "GList *", "gboolean")
1237 static int
1238 failed_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
1257 if (!pcmk__str_in_list(only_node, crm_element_value(xml_op, XML_ATTR_UNAME), pcmk__str_casei)) {
1258 continue;
1259 }
1260
1261 id = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
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
1277 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1278 return rc;
1279 }
1280
1281 static void
1282 status_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
1303 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1304 "GList *", "GList *")
1305 static int
1306 node_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
1334 pcmk__output_xml_pop_parent(out);
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
1354 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1355 pcmk__output_xml_pop_parent(out);
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
1375 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1376 "GList *", "GList *")
1377 static int
1378 node_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
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
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
1447 PCMK__OUTPUT_ARGS("node", "pe_node_t *", "unsigned int", "gboolean", "const char *",
1448 "GList *", "GList *")
1449 static int
1450 node_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 {
1507 pcmk__output_xml_create_parent(out, "node",
1508 "name", node->details->uname,
1509 NULL);
1510 }
1511
1512 return pcmk_rc_ok;
1513 }
1514
1515 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1516 static int
1517 node_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
1545 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1546 static int
1547 node_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
1581 PCMK__OUTPUT_ARGS("node-and-op", "pe_working_set_t *", "xmlNodePtr")
1582 static int
1583 node_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
1596 pcmk__scan_min_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS),
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
1616 if (crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE,
1617 &last_change) == pcmk_ok) {
1618 last_change_str = crm_strdup_printf(", %s=%s, exec=%sms",
1619 XML_RSC_OP_LAST_CHANGE,
1620 pcmk__trim(ctime(&last_change)),
1621 crm_element_value(xml_op, XML_RSC_OP_T_EXEC));
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),
1626 crm_element_value(xml_op, XML_ATTR_UNAME),
1627 crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
1628 crm_element_value(xml_op, XML_LRM_ATTR_RC),
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
1637 PCMK__OUTPUT_ARGS("node-and-op", "pe_working_set_t *", "xmlNodePtr")
1638 static int
1639 node_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
1650 pcmk__scan_min_int(crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS),
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,
1668 pcmk_is_set(pcmk_get_ra_caps(class), pcmk_ra_cap_provider) ? crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER) : "",
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
1677 if (crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE,
1678 &last_change) == pcmk_ok) {
1679 pcmk__xe_set_props(node, XML_RSC_OP_LAST_CHANGE,
1680 pcmk__trim(ctime(&last_change)),
1681 XML_RSC_OP_T_EXEC, crm_element_value(xml_op, XML_RSC_OP_T_EXEC),
1682 NULL);
1683 }
1684
1685 return pcmk_rc_ok;
1686 }
1687
1688 PCMK__OUTPUT_ARGS("node-attribute", "const char *", "const char *", "gboolean", "int")
1689 static int
1690 node_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
1710 PCMK__OUTPUT_ARGS("node-attribute-list", "pe_working_set_t *", "unsigned int",
1711 "gboolean", "GList *", "GList *")
1712 static int
1713 node_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
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
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
1772 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1773 return rc;
1774 }
1775
1776 PCMK__OUTPUT_ARGS("node-capacity", "pe_node_t *", "const char *")
1777 static int
1778 node_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
1793 PCMK__OUTPUT_ARGS("node-capacity", "pe_node_t *", "const char *")
1794 static int
1795 node_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
1809 PCMK__OUTPUT_ARGS("node-history-list", "pe_working_set_t *", "pe_node_t *", "xmlNodePtr",
1810 "GList *", "GList *", "unsigned int", "unsigned int")
1811 static int
1812 node_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
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
1835
1836
1837
1838
1839
1840
1841
1842 if (uber_parent(rsc)->variant == pe_group) {
1843 if (!pcmk__str_in_list(only_rsc, rsc_printable_id(rsc), pcmk__str_none) &&
1844 !pcmk__str_in_list(only_rsc, rsc_printable_id(uber_parent(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
1888 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1889 return rc;
1890 }
1891
1892 PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int")
1893 static int
1894 node_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
1914 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1915 return rc;
1916 }
1917
1918 PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int")
1919 static int
1920 node_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
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
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
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
2023 out->message(out, "node", node, show_opts, TRUE, node_mode, only_node, only_rsc);
2024 free(node_name);
2025 }
2026
2027
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
2049 PCMK__OUTPUT_LIST_FOOTER(out, rc);
2050 return rc;
2051 }
2052
2053 PCMK__OUTPUT_ARGS("node-list", "GList *", "GList *", "GList *", "unsigned int")
2054 static int
2055 node_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
2076 PCMK__OUTPUT_ARGS("node-summary", "pe_working_set_t *", "GList *", "GList *",
2077 "unsigned int", "unsigned int", "gboolean")
2078 static int
2079 node_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
2114 PCMK__OUTPUT_LIST_FOOTER(out, rc);
2115 return rc;
2116 }
2117
2118 PCMK__OUTPUT_ARGS("node-weight", "pe_resource_t *", "const char *", "const char *", "char *")
2119 static int
2120 node_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
2137 PCMK__OUTPUT_ARGS("node-weight", "pe_resource_t *", "const char *", "const char *", "char *")
2138 static int
2139 node_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
2159 PCMK__OUTPUT_ARGS("op-history", "xmlNodePtr", "const char *", "const char *", "int",
2160 "unsigned int")
2161 static int
2162 op_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
2178 PCMK__OUTPUT_ARGS("op-history", "xmlNodePtr", "const char *", "const char *", "int",
2179 "unsigned int")
2180 static int
2181 op_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
2207 if ((crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE,
2208 &epoch) == pcmk_ok) && (epoch > 0)) {
2209 crm_xml_add(node, XML_RSC_OP_LAST_CHANGE, pcmk__epoch2str(&epoch));
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);
2215 crm_xml_add(node, XML_RSC_OP_T_EXEC, s);
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);
2221 crm_xml_add(node, XML_RSC_OP_T_QUEUE, s);
2222 free(s);
2223 }
2224 }
2225
2226 return pcmk_rc_ok;
2227 }
2228
2229 PCMK__OUTPUT_ARGS("promotion-score", "pe_resource_t *", "pe_node_t *", "char *")
2230 static int
2231 promotion_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
2244 PCMK__OUTPUT_ARGS("promotion-score", "pe_resource_t *", "pe_node_t *", "char *")
2245 static int
2246 promotion_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
2264 PCMK__OUTPUT_ARGS("resource-config", "pe_resource_t *", "gboolean")
2265 static int
2266 resource_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
2285 PCMK__OUTPUT_ARGS("resource-history", "pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
2286 static int
2287 resource_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
2307 PCMK__OUTPUT_ARGS("resource-history", "pe_resource_t *", "const char *", "gboolean", "int", "time_t", "gboolean")
2308 static int
2309 resource_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
2334 crm_xml_add(node, PCMK__FAIL_COUNT_PREFIX, s);
2335 free(s);
2336 }
2337
2338 if (last_failure > 0) {
2339 crm_xml_add(node, PCMK__LAST_FAILURE_PREFIX, pcmk__epoch2str(&last_failure));
2340 }
2341 }
2342
2343 if (as_header == FALSE) {
2344 pcmk__output_xml_pop_parent(out);
2345 }
2346
2347 return pcmk_rc_ok;
2348 }
2349
2350 static void
2351 print_resource_header(pcmk__output_t *out, unsigned int show_opts)
2352 {
2353 if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
2354
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
2364 PCMK__OUTPUT_ARGS("resource-list", "pe_working_set_t *", "unsigned int",
2365 "gboolean", "GList *", "GList *", "gboolean")
2366 static int
2367 resource_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
2381
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
2389
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
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
2407 gboolean is_active = rsc->fns->active(rsc, TRUE);
2408 gboolean partially_active = rsc->fns->active(rsc, FALSE);
2409
2410
2411 if (pcmk_is_set(rsc->flags, pe_rsc_orphan) && !is_active) {
2412 continue;
2413
2414
2415 } else if (pcmk_is_set(show_opts, pcmk_show_rscs_by_node)) {
2416 if (is_active) {
2417 continue;
2418 }
2419
2420
2421 } else if (pcmk_is_set(show_opts, pcmk_show_brief) && (rsc->variant == pe_native)) {
2422 continue;
2423
2424
2425
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
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
2471 PCMK__OUTPUT_ARGS("resource-operation-list", "pe_working_set_t *", "pe_resource_t *",
2472 "pe_node_t *", "GList *", "unsigned int")
2473 static int
2474 resource_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
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,
2490 XML_LRM_ATTR_INTERVAL_MS);
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
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
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
2514 out->message(out, "op-history", xml_op, task, interval_ms_s,
2515 op_rc_i, show_opts);
2516 }
2517
2518
2519 g_list_free(op_list);
2520
2521 PCMK__OUTPUT_LIST_FOOTER(out, rc);
2522 return rc;
2523 }
2524
2525 PCMK__OUTPUT_ARGS("resource-util", "pe_resource_t *", "pe_node_t *", "const char *")
2526 static int
2527 resource_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
2543 PCMK__OUTPUT_ARGS("resource-util", "pe_resource_t *", "pe_node_t *", "const char *")
2544 static int
2545 resource_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
2561 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2562 static int
2563 ticket_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
2584 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2585 static int
2586 ticket_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
2607 PCMK__OUTPUT_ARGS("ticket", "pe_ticket_t *")
2608 static int
2609 ticket_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
2627 PCMK__OUTPUT_ARGS("ticket-list", "pe_working_set_t *", "gboolean")
2628 static int
2629 ticket_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
2643 out->begin_list(out, NULL, NULL, "Tickets");
2644
2645
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
2653 out->end_list(out);
2654 return pcmk_rc_ok;
2655 }
2656
2657 static 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
2731 void
2732 pe__register_messages(pcmk__output_t *out) {
2733 pcmk__register_messages(out, fmt_functions);
2734 }
2735
2736 void
2737 pe__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 }