This source file includes following definitions.
- print_constraint
- cli_resource_print_cts_constraints
- cli_resource_print_cts
- cli_resource_print_operations
- cli_resource_print
- 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
- add_resource_name
- PCMK__OUTPUT_ARGS
- crm_resource_register_messages
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdint.h>
13
14 #include <crm_resource.h>
15 #include <crm/common/lists_internal.h>
16 #include <crm/common/output.h>
17 #include <crm/common/results.h>
18
19 #define cons_string(x) x?x:"NA"
20 static int
21 print_constraint(xmlNode *xml_obj, void *userdata)
22 {
23 pe_working_set_t *data_set = (pe_working_set_t *) userdata;
24 pcmk__output_t *out = data_set->priv;
25 xmlNode *lifetime = NULL;
26 const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
27
28 if (id == NULL) {
29 return pcmk_rc_ok;
30 }
31
32
33 lifetime = first_named_child(xml_obj, "lifetime");
34 if (pe_evaluate_rules(lifetime, NULL, data_set->now, NULL) == FALSE) {
35 return pcmk_rc_ok;
36 }
37
38 if (!pcmk__str_eq(XML_CONS_TAG_RSC_DEPEND, crm_element_name(xml_obj), pcmk__str_casei)) {
39 return pcmk_rc_ok;
40 }
41
42 out->info(out, "Constraint %s %s %s %s %s %s %s",
43 crm_element_name(xml_obj),
44 cons_string(crm_element_value(xml_obj, XML_ATTR_ID)),
45 cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE)),
46 cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET)),
47 cons_string(crm_element_value(xml_obj, XML_RULE_ATTR_SCORE)),
48 cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_ROLE)),
49 cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET_ROLE)));
50
51 return pcmk_rc_ok;
52 }
53
54 void
55 cli_resource_print_cts_constraints(pe_working_set_t * data_set)
56 {
57 pcmk__xe_foreach_child(pcmk_find_cib_element(data_set->input, XML_CIB_TAG_CONSTRAINTS),
58 NULL, print_constraint, data_set);
59 }
60
61 void
62 cli_resource_print_cts(pe_resource_t * rsc, pcmk__output_t *out)
63 {
64 const char *host = NULL;
65 bool needs_quorum = TRUE;
66 const char *rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE);
67 const char *rprov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
68 const char *rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
69 pe_node_t *node = pe__current_node(rsc);
70
71 if (pcmk__str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
72 needs_quorum = FALSE;
73 } else {
74
75 }
76
77 if (node != NULL) {
78 host = node->details->uname;
79 }
80
81 out->info(out, "Resource: %s %s %s %s %s %s %s %s %d %lld %#.16llx",
82 crm_element_name(rsc->xml), rsc->id,
83 rsc->clone_name ? rsc->clone_name : rsc->id, rsc->parent ? rsc->parent->id : "NA",
84 rprov ? rprov : "NA", rclass, rtype, host ? host : "NA", needs_quorum, rsc->flags,
85 rsc->flags);
86
87 g_list_foreach(rsc->children, (GFunc) cli_resource_print_cts, out);
88 }
89
90
91 int
92 cli_resource_print_operations(const char *rsc_id, const char *host_uname,
93 bool active, pe_working_set_t * data_set)
94 {
95 pcmk__output_t *out = data_set->priv;
96 int rc = pcmk_rc_no_output;
97 GList *ops = find_operations(rsc_id, host_uname, active, data_set);
98
99 if (!ops) {
100 return rc;
101 }
102
103 out->begin_list(out, NULL, NULL, "Resource Operations");
104 rc = pcmk_rc_ok;
105
106 for (GList *lpc = ops; lpc != NULL; lpc = lpc->next) {
107 xmlNode *xml_op = (xmlNode *) lpc->data;
108 out->message(out, "node-and-op", data_set, xml_op);
109 }
110
111 out->end_list(out);
112 return rc;
113 }
114
115
116 int
117 cli_resource_print(pe_resource_t *rsc, pe_working_set_t *data_set, bool expanded)
118 {
119 pcmk__output_t *out = data_set->priv;
120 uint32_t show_opts = pcmk_show_pending;
121 GList *all = NULL;
122
123 all = g_list_prepend(all, (gpointer) "*");
124
125 out->begin_list(out, NULL, NULL, "Resource Config");
126 out->message(out, crm_map_element_name(rsc->xml), show_opts, rsc, all, all);
127 out->message(out, "resource-config", rsc, !expanded);
128 out->end_list(out);
129
130 g_list_free(all);
131 return pcmk_rc_ok;
132 }
133
134 PCMK__OUTPUT_ARGS("attribute-list", "pe_resource_t *", "const char *", "const char *")
135 static int
136 attribute_list_default(pcmk__output_t *out, va_list args) {
137 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
138 const char *attr = va_arg(args, char *);
139 const char *value = va_arg(args, const char *);
140
141 if (value != NULL) {
142 out->begin_list(out, NULL, NULL, "Attributes");
143 out->list_item(out, attr, "%s", value);
144 out->end_list(out);
145 return pcmk_rc_ok;
146 } else {
147 out->err(out, "Attribute '%s' not found for '%s'", attr, rsc->id);
148 }
149 return pcmk_rc_ok;
150 }
151
152 PCMK__OUTPUT_ARGS("agent-status", "int", "const char *", "const char *", "const char *",
153 "const char *", "const char *", "crm_exit_t", "const char *")
154 static int
155 agent_status_default(pcmk__output_t *out, va_list args) {
156 int status = va_arg(args, int);
157 const char *action = va_arg(args, const char *);
158 const char *name = va_arg(args, const char *);
159 const char *class = va_arg(args, const char *);
160 const char *provider = va_arg(args, const char *);
161 const char *type = va_arg(args, const char *);
162 crm_exit_t rc = va_arg(args, crm_exit_t);
163 const char *exit_reason = va_arg(args, const char *);
164
165 if (status == PCMK_EXEC_DONE) {
166
167
168
169 out->info(out, "Operation %s%s%s (%s%s%s:%s) returned %d (%s%s%s)",
170 action,
171 ((name == NULL)? "" : " for "), ((name == NULL)? "" : name),
172 class,
173 ((provider == NULL)? "" : ":"),
174 ((provider == NULL)? "" : provider),
175 type, (int) rc, services_ocf_exitcode_str((int) rc),
176 ((exit_reason == NULL)? "" : ": "),
177 ((exit_reason == NULL)? "" : exit_reason));
178 } else {
179
180
181
182 out->err(out,
183 "Operation %s%s%s (%s%s%s:%s) could not be executed (%s%s%s)",
184 action,
185 ((name == NULL)? "" : " for "), ((name == NULL)? "" : name),
186 class,
187 ((provider == NULL)? "" : ":"),
188 ((provider == NULL)? "" : provider),
189 type, pcmk_exec_status_str(status),
190 ((exit_reason == NULL)? "" : ": "),
191 ((exit_reason == NULL)? "" : exit_reason));
192 }
193
194 return pcmk_rc_ok;
195 }
196
197 PCMK__OUTPUT_ARGS("agent-status", "int", "const char *", "const char *", "const char *",
198 "const char *", "const char *", "crm_exit_t", "const char *")
199 static int
200 agent_status_xml(pcmk__output_t *out, va_list args) {
201 int status = va_arg(args, int);
202 const char *action G_GNUC_UNUSED = va_arg(args, const char *);
203 const char *name G_GNUC_UNUSED = va_arg(args, const char *);
204 const char *class G_GNUC_UNUSED = va_arg(args, const char *);
205 const char *provider G_GNUC_UNUSED = va_arg(args, const char *);
206 const char *type G_GNUC_UNUSED = va_arg(args, const char *);
207 crm_exit_t rc = va_arg(args, crm_exit_t);
208 const char *exit_reason = va_arg(args, const char *);
209
210 char *exit_str = pcmk__itoa(rc);
211 char *status_str = pcmk__itoa(status);
212
213 pcmk__output_create_xml_node(out, "agent-status",
214 "code", exit_str,
215 "message", services_ocf_exitcode_str((int) rc),
216 "execution_code", status_str,
217 "execution_message", pcmk_exec_status_str(status),
218 "reason", exit_reason,
219 NULL);
220
221 free(exit_str);
222 free(status_str);
223
224 return pcmk_rc_ok;
225 }
226
227 PCMK__OUTPUT_ARGS("attribute-list", "pe_resource_t *", "const char *", "const char *")
228 static int
229 attribute_list_text(pcmk__output_t *out, va_list args) {
230 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
231 const char *attr = va_arg(args, char *);
232 const char *value = va_arg(args, const char *);
233
234 if (value != NULL) {
235 pcmk__formatted_printf(out, "%s\n", value);
236 return pcmk_rc_ok;
237 } else {
238 out->err(out, "Attribute '%s' not found for '%s'", attr, rsc->id);
239 }
240 return pcmk_rc_ok;
241 }
242 PCMK__OUTPUT_ARGS("override", "const char *", "const char *", "const char *")
243 static int
244 override_default(pcmk__output_t *out, va_list args) {
245 const char *rsc_name = va_arg(args, const char *);
246 const char *name = va_arg(args, const char *);
247 const char *value = va_arg(args, const char *);
248
249 if (rsc_name == NULL) {
250 out->list_item(out, NULL, "Overriding the cluster configuration with '%s' = '%s'",
251 name, value);
252 } else {
253 out->list_item(out, NULL, "Overriding the cluster configuration for '%s' with '%s' = '%s'",
254 rsc_name, name, value);
255 }
256
257 return pcmk_rc_ok;
258 }
259
260 PCMK__OUTPUT_ARGS("override", "const char *", "const char *", "const char *")
261 static int
262 override_xml(pcmk__output_t *out, va_list args) {
263 const char *rsc_name = va_arg(args, const char *);
264 const char *name = va_arg(args, const char *);
265 const char *value = va_arg(args, const char *);
266
267 xmlNodePtr node = pcmk__output_create_xml_node(out, "override",
268 "name", name,
269 "value", value,
270 NULL);
271
272 if (rsc_name != NULL) {
273 crm_xml_add(node, "rsc", rsc_name);
274 }
275
276 return pcmk_rc_ok;
277 }
278
279 PCMK__OUTPUT_ARGS("property-list", "pe_resource_t *", "const char *")
280 static int
281 property_list_default(pcmk__output_t *out, va_list args) {
282 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
283 const char *attr = va_arg(args, char *);
284
285 const char *value = crm_element_value(rsc->xml, attr);
286
287 if (value != NULL) {
288 out->begin_list(out, NULL, NULL, "Properties");
289 out->list_item(out, attr, "%s", value);
290 out->end_list(out);
291 }
292
293 return pcmk_rc_ok;
294 }
295
296 PCMK__OUTPUT_ARGS("property-list", "pe_resource_t *", "const char *")
297 static int
298 property_list_text(pcmk__output_t *out, va_list args) {
299 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
300 const char *attr = va_arg(args, const char *);
301
302 const char *value = crm_element_value(rsc->xml, attr);
303
304 if (value != NULL) {
305 pcmk__formatted_printf(out, "%s\n", value);
306 }
307
308 return pcmk_rc_ok;
309 }
310
311 PCMK__OUTPUT_ARGS("resource-agent-action", "int", "const char *", "const char *",
312 "const char *", "const char *", "const char *", "GHashTable *",
313 "crm_exit_t", "int", "const char *", "const char *", "const char *")
314 static int
315 resource_agent_action_default(pcmk__output_t *out, va_list args) {
316 int verbose = va_arg(args, int);
317
318 const char *class = va_arg(args, const char *);
319 const char *provider = va_arg(args, const char *);
320 const char *type = va_arg(args, const char *);
321 const char *rsc_name = va_arg(args, const char *);
322 const char *action = va_arg(args, const char *);
323 GHashTable *overrides = va_arg(args, GHashTable *);
324 crm_exit_t rc = va_arg(args, crm_exit_t);
325 int status = va_arg(args, int);
326 const char *exit_reason = va_arg(args, const char *);
327 const char *stdout_data = va_arg(args, const char *);
328 const char *stderr_data = va_arg(args, const char *);
329
330 if (overrides) {
331 GHashTableIter iter;
332 const char *name = NULL;
333 const char *value = NULL;
334
335 out->begin_list(out, NULL, NULL, "overrides");
336
337 g_hash_table_iter_init(&iter, overrides);
338 while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &value)) {
339 out->message(out, "override", rsc_name, name, value);
340 }
341
342 out->end_list(out);
343 }
344
345 out->message(out, "agent-status", status, action, rsc_name, class, provider,
346 type, rc, exit_reason);
347
348
349 if (verbose == 0 && pcmk__str_eq(action, "validate-all", pcmk__str_casei)) {
350 return pcmk_rc_ok;
351 }
352
353 if (stdout_data || stderr_data) {
354 xmlNodePtr doc = NULL;
355
356 if (stdout_data != NULL) {
357 doc = string2xml(stdout_data);
358 }
359 if (doc != NULL) {
360 out->output_xml(out, "command", stdout_data);
361 xmlFreeNode(doc);
362 } else {
363 out->subprocess_output(out, rc, stdout_data, stderr_data);
364 }
365 }
366
367 return pcmk_rc_ok;
368 }
369
370 PCMK__OUTPUT_ARGS("resource-agent-action", "int", "const char *", "const char *",
371 "const char *", "const char *", "const char *", "GHashTable *",
372 "crm_exit_t", "int", "const char *", "const char *", "const char *")
373 static int
374 resource_agent_action_xml(pcmk__output_t *out, va_list args) {
375 int verbose G_GNUC_UNUSED = va_arg(args, int);
376
377 const char *class = va_arg(args, const char *);
378 const char *provider = va_arg(args, const char *);
379 const char *type = va_arg(args, const char *);
380 const char *rsc_name = va_arg(args, const char *);
381 const char *action = va_arg(args, const char *);
382 GHashTable *overrides = va_arg(args, GHashTable *);
383 crm_exit_t rc = va_arg(args, crm_exit_t);
384 int status = va_arg(args, int);
385 const char *exit_reason = va_arg(args, const char *);
386 const char *stdout_data = va_arg(args, const char *);
387 const char *stderr_data = va_arg(args, const char *);
388
389 xmlNodePtr node = pcmk__output_xml_create_parent(out, "resource-agent-action",
390 "action", action,
391 "class", class,
392 "type", type,
393 NULL);
394
395 if (rsc_name) {
396 crm_xml_add(node, "rsc", rsc_name);
397 }
398
399 if (provider) {
400 crm_xml_add(node, "provider", provider);
401 }
402
403 if (overrides) {
404 GHashTableIter iter;
405 const char *name = NULL;
406 const char *value = NULL;
407
408 out->begin_list(out, NULL, NULL, "overrides");
409
410 g_hash_table_iter_init(&iter, overrides);
411 while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &value)) {
412 out->message(out, "override", rsc_name, name, value);
413 }
414
415 out->end_list(out);
416 }
417
418 out->message(out, "agent-status", status, action, rsc_name, class, provider,
419 type, rc, exit_reason);
420
421 if (stdout_data || stderr_data) {
422 xmlNodePtr doc = NULL;
423
424 if (stdout_data != NULL) {
425 doc = string2xml(stdout_data);
426 }
427 if (doc != NULL) {
428 out->output_xml(out, "command", stdout_data);
429 xmlFreeNode(doc);
430 } else {
431 out->subprocess_output(out, rc, stdout_data, stderr_data);
432 }
433 }
434
435 pcmk__output_xml_pop_parent(out);
436 return pcmk_rc_ok;
437 }
438
439 PCMK__OUTPUT_ARGS("resource-check-list", "resource_checks_t *")
440 static int
441 resource_check_list_default(pcmk__output_t *out, va_list args) {
442 resource_checks_t *checks = va_arg(args, resource_checks_t *);
443
444 const pe_resource_t *parent = pe__const_top_resource(checks->rsc, false);
445
446 if (checks->flags == 0) {
447 return pcmk_rc_no_output;
448 }
449
450 out->begin_list(out, NULL, NULL, "Resource Checks");
451
452 if (pcmk_is_set(checks->flags, rsc_remain_stopped)) {
453 out->list_item(out, "check", "Configuration specifies '%s' should remain stopped",
454 parent->id);
455 }
456
457 if (pcmk_is_set(checks->flags, rsc_unpromotable)) {
458 out->list_item(out, "check", "Configuration specifies '%s' should not be promoted",
459 parent->id);
460 }
461
462 if (pcmk_is_set(checks->flags, rsc_unmanaged)) {
463 out->list_item(out, "check", "Configuration prevents cluster from stopping or starting unmanaged '%s'",
464 parent->id);
465 }
466
467 if (pcmk_is_set(checks->flags, rsc_locked)) {
468 out->list_item(out, "check", "'%s' is locked to node %s due to shutdown",
469 parent->id, checks->lock_node);
470 }
471
472 if (pcmk_is_set(checks->flags, rsc_node_health)) {
473 out->list_item(out, "check",
474 "'%s' cannot run on unhealthy nodes due to "
475 PCMK__OPT_NODE_HEALTH_STRATEGY "='%s'",
476 parent->id,
477 pe_pref(checks->rsc->cluster->config_hash,
478 PCMK__OPT_NODE_HEALTH_STRATEGY));
479 }
480
481 out->end_list(out);
482 return pcmk_rc_ok;
483 }
484
485 PCMK__OUTPUT_ARGS("resource-check-list", "resource_checks_t *")
486 static int
487 resource_check_list_xml(pcmk__output_t *out, va_list args) {
488 resource_checks_t *checks = va_arg(args, resource_checks_t *);
489
490 const pe_resource_t *parent = pe__const_top_resource(checks->rsc, false);
491
492 xmlNodePtr node = pcmk__output_create_xml_node(out, "check",
493 "id", parent->id,
494 NULL);
495
496 if (pcmk_is_set(checks->flags, rsc_remain_stopped)) {
497 pcmk__xe_set_bool_attr(node, "remain_stopped", true);
498 }
499
500 if (pcmk_is_set(checks->flags, rsc_unpromotable)) {
501 pcmk__xe_set_bool_attr(node, "promotable", false);
502 }
503
504 if (pcmk_is_set(checks->flags, rsc_unmanaged)) {
505 pcmk__xe_set_bool_attr(node, "unmanaged", true);
506 }
507
508 if (pcmk_is_set(checks->flags, rsc_locked)) {
509 crm_xml_add(node, "locked-to", checks->lock_node);
510 }
511
512 if (pcmk_is_set(checks->flags, rsc_node_health)) {
513 pcmk__xe_set_bool_attr(node, "unhealthy", true);
514 }
515
516 return pcmk_rc_ok;
517 }
518
519 PCMK__OUTPUT_ARGS("resource-search-list", "GList *", "const char *")
520 static int
521 resource_search_list_default(pcmk__output_t *out, va_list args)
522 {
523 GList *nodes = va_arg(args, GList *);
524 const char *requested_name = va_arg(args, const char *);
525
526 bool printed = false;
527 int rc = pcmk_rc_no_output;
528
529 if (!out->is_quiet(out) && nodes == NULL) {
530 out->err(out, "resource %s is NOT running", requested_name);
531 return rc;
532 }
533
534 for (GList *lpc = nodes; lpc != NULL; lpc = lpc->next) {
535 node_info_t *ni = (node_info_t *) lpc->data;
536
537 if (!printed) {
538 out->begin_list(out, NULL, NULL, "Nodes");
539 printed = true;
540 rc = pcmk_rc_ok;
541 }
542
543 if (out->is_quiet(out)) {
544 out->list_item(out, "node", "%s", ni->node_name);
545 } else {
546 const char *role_text = "";
547
548 if (ni->promoted) {
549 #ifdef PCMK__COMPAT_2_0
550 role_text = " " RSC_ROLE_PROMOTED_LEGACY_S;
551 #else
552 role_text = " " RSC_ROLE_PROMOTED_S;
553 #endif
554 }
555 out->list_item(out, "node", "resource %s is running on: %s%s",
556 requested_name, ni->node_name, role_text);
557 }
558 }
559
560 if (printed) {
561 out->end_list(out);
562 }
563
564 return rc;
565 }
566
567 PCMK__OUTPUT_ARGS("resource-search-list", "GList *", "const char *")
568 static int
569 resource_search_list_xml(pcmk__output_t *out, va_list args)
570 {
571 GList *nodes = va_arg(args, GList *);
572 const char *requested_name = va_arg(args, const char *);
573
574 pcmk__output_xml_create_parent(out, "nodes",
575 "resource", requested_name,
576 NULL);
577
578 for (GList *lpc = nodes; lpc != NULL; lpc = lpc->next) {
579 node_info_t *ni = (node_info_t *) lpc->data;
580 xmlNodePtr sub_node = pcmk__output_create_xml_text_node(out, "node", ni->node_name);
581
582 if (ni->promoted) {
583 crm_xml_add(sub_node, "state", "promoted");
584 }
585 }
586
587 return pcmk_rc_ok;
588 }
589
590 PCMK__OUTPUT_ARGS("resource-reasons-list", "GList *", "pe_resource_t *",
591 "pe_node_t *")
592 static int
593 resource_reasons_list_default(pcmk__output_t *out, va_list args)
594 {
595 GList *resources = va_arg(args, GList *);
596 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
597 pe_node_t *node = va_arg(args, pe_node_t *);
598
599 const char *host_uname = (node == NULL)? NULL : node->details->uname;
600
601 out->begin_list(out, NULL, NULL, "Resource Reasons");
602
603 if ((rsc == NULL) && (host_uname == NULL)) {
604 GList *lpc = NULL;
605 GList *hosts = NULL;
606
607 for (lpc = resources; lpc != NULL; lpc = lpc->next) {
608 pe_resource_t *rsc = (pe_resource_t *) lpc->data;
609 rsc->fns->location(rsc, &hosts, TRUE);
610
611 if (hosts == NULL) {
612 out->list_item(out, "reason", "Resource %s is not running", rsc->id);
613 } else {
614 out->list_item(out, "reason", "Resource %s is running", rsc->id);
615 }
616
617 cli_resource_check(out, rsc, NULL);
618 g_list_free(hosts);
619 hosts = NULL;
620 }
621
622 } else if ((rsc != NULL) && (host_uname != NULL)) {
623 if (resource_is_running_on(rsc, host_uname)) {
624 out->list_item(out, "reason", "Resource %s is running on host %s",
625 rsc->id, host_uname);
626 } else {
627 out->list_item(out, "reason", "Resource %s is not running on host %s",
628 rsc->id, host_uname);
629 }
630
631 cli_resource_check(out, rsc, node);
632
633 } else if ((rsc == NULL) && (host_uname != NULL)) {
634 const char* host_uname = node->details->uname;
635 GList *allResources = node->details->allocated_rsc;
636 GList *activeResources = node->details->running_rsc;
637 GList *unactiveResources = pcmk__subtract_lists(allResources, activeResources, (GCompareFunc) strcmp);
638 GList *lpc = NULL;
639
640 for (lpc = activeResources; lpc != NULL; lpc = lpc->next) {
641 pe_resource_t *rsc = (pe_resource_t *) lpc->data;
642 out->list_item(out, "reason", "Resource %s is running on host %s",
643 rsc->id, host_uname);
644 cli_resource_check(out, rsc, node);
645 }
646
647 for(lpc = unactiveResources; lpc != NULL; lpc = lpc->next) {
648 pe_resource_t *rsc = (pe_resource_t *) lpc->data;
649 out->list_item(out, "reason", "Resource %s is assigned to host %s but not running",
650 rsc->id, host_uname);
651 cli_resource_check(out, rsc, node);
652 }
653
654 g_list_free(allResources);
655 g_list_free(activeResources);
656 g_list_free(unactiveResources);
657
658 } else if ((rsc != NULL) && (host_uname == NULL)) {
659 GList *hosts = NULL;
660
661 rsc->fns->location(rsc, &hosts, TRUE);
662 out->list_item(out, "reason", "Resource %s is %srunning",
663 rsc->id, (hosts? "" : "not "));
664 cli_resource_check(out, rsc, NULL);
665 g_list_free(hosts);
666 }
667
668 out->end_list(out);
669 return pcmk_rc_ok;
670 }
671
672 PCMK__OUTPUT_ARGS("resource-reasons-list", "GList *", "pe_resource_t *",
673 "pe_node_t *")
674 static int
675 resource_reasons_list_xml(pcmk__output_t *out, va_list args)
676 {
677 GList *resources = va_arg(args, GList *);
678 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
679 pe_node_t *node = va_arg(args, pe_node_t *);
680
681 const char *host_uname = (node == NULL)? NULL : node->details->uname;
682
683 xmlNodePtr xml_node = pcmk__output_xml_create_parent(out, "reason", NULL);
684
685 if ((rsc == NULL) && (host_uname == NULL)) {
686 GList *lpc = NULL;
687 GList *hosts = NULL;
688
689 pcmk__output_xml_create_parent(out, "resources", NULL);
690
691 for (lpc = resources; lpc != NULL; lpc = lpc->next) {
692 pe_resource_t *rsc = (pe_resource_t *) lpc->data;
693
694 rsc->fns->location(rsc, &hosts, TRUE);
695
696 pcmk__output_xml_create_parent(out, "resource",
697 "id", rsc->id,
698 "running", pcmk__btoa(hosts != NULL),
699 NULL);
700
701 cli_resource_check(out, rsc, NULL);
702 pcmk__output_xml_pop_parent(out);
703 g_list_free(hosts);
704 hosts = NULL;
705 }
706
707 pcmk__output_xml_pop_parent(out);
708
709 } else if ((rsc != NULL) && (host_uname != NULL)) {
710 if (resource_is_running_on(rsc, host_uname)) {
711 crm_xml_add(xml_node, "running_on", host_uname);
712 }
713
714 cli_resource_check(out, rsc, node);
715
716 } else if ((rsc == NULL) && (host_uname != NULL)) {
717 const char* host_uname = node->details->uname;
718 GList *allResources = node->details->allocated_rsc;
719 GList *activeResources = node->details->running_rsc;
720 GList *unactiveResources = pcmk__subtract_lists(allResources, activeResources, (GCompareFunc) strcmp);
721 GList *lpc = NULL;
722
723 pcmk__output_xml_create_parent(out, "resources", NULL);
724
725 for (lpc = activeResources; lpc != NULL; lpc = lpc->next) {
726 pe_resource_t *rsc = (pe_resource_t *) lpc->data;
727
728 pcmk__output_xml_create_parent(out, "resource",
729 "id", rsc->id,
730 "running", "true",
731 "host", host_uname,
732 NULL);
733
734 cli_resource_check(out, rsc, node);
735 pcmk__output_xml_pop_parent(out);
736 }
737
738 for(lpc = unactiveResources; lpc != NULL; lpc = lpc->next) {
739 pe_resource_t *rsc = (pe_resource_t *) lpc->data;
740
741 pcmk__output_xml_create_parent(out, "resource",
742 "id", rsc->id,
743 "running", "false",
744 "host", host_uname,
745 NULL);
746
747 cli_resource_check(out, rsc, node);
748 pcmk__output_xml_pop_parent(out);
749 }
750
751 pcmk__output_xml_pop_parent(out);
752 g_list_free(allResources);
753 g_list_free(activeResources);
754 g_list_free(unactiveResources);
755
756 } else if ((rsc != NULL) && (host_uname == NULL)) {
757 GList *hosts = NULL;
758
759 rsc->fns->location(rsc, &hosts, TRUE);
760 crm_xml_add(xml_node, "running", pcmk__btoa(hosts != NULL));
761 cli_resource_check(out, rsc, NULL);
762 g_list_free(hosts);
763 }
764
765 return pcmk_rc_ok;
766 }
767
768 static void
769 add_resource_name(pe_resource_t *rsc, pcmk__output_t *out) {
770 if (rsc->children == NULL) {
771 out->list_item(out, "resource", "%s", rsc->id);
772 } else {
773 g_list_foreach(rsc->children, (GFunc) add_resource_name, out);
774 }
775 }
776
777 PCMK__OUTPUT_ARGS("resource-names-list", "GList *")
778 static int
779 resource_names(pcmk__output_t *out, va_list args) {
780 GList *resources = va_arg(args, GList *);
781
782 if (resources == NULL) {
783 out->err(out, "NO resources configured\n");
784 return pcmk_rc_no_output;
785 }
786
787 out->begin_list(out, NULL, NULL, "Resource Names");
788 g_list_foreach(resources, (GFunc) add_resource_name, out);
789 out->end_list(out);
790 return pcmk_rc_ok;
791 }
792
793 static pcmk__message_entry_t fmt_functions[] = {
794 { "agent-status", "default", agent_status_default },
795 { "agent-status", "xml", agent_status_xml },
796 { "attribute-list", "default", attribute_list_default },
797 { "attribute-list", "text", attribute_list_text },
798 { "override", "default", override_default },
799 { "override", "xml", override_xml },
800 { "property-list", "default", property_list_default },
801 { "property-list", "text", property_list_text },
802 { "resource-agent-action", "default", resource_agent_action_default },
803 { "resource-agent-action", "xml", resource_agent_action_xml },
804 { "resource-check-list", "default", resource_check_list_default },
805 { "resource-check-list", "xml", resource_check_list_xml },
806 { "resource-search-list", "default", resource_search_list_default },
807 { "resource-search-list", "xml", resource_search_list_xml },
808 { "resource-reasons-list", "default", resource_reasons_list_default },
809 { "resource-reasons-list", "xml", resource_reasons_list_xml },
810 { "resource-names-list", "default", resource_names },
811
812 { NULL, NULL, NULL }
813 };
814
815 void
816 crm_resource_register_messages(pcmk__output_t *out) {
817 pcmk__register_messages(out, fmt_functions);
818 }