root/tools/crm_resource_print.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. print_constraint
  2. cli_resource_print_cts_constraints
  3. cli_resource_print_cts
  4. cli_resource_print_operations
  5. cli_resource_print
  6. PCMK__OUTPUT_ARGS
  7. PCMK__OUTPUT_ARGS
  8. PCMK__OUTPUT_ARGS
  9. PCMK__OUTPUT_ARGS
  10. PCMK__OUTPUT_ARGS
  11. PCMK__OUTPUT_ARGS
  12. PCMK__OUTPUT_ARGS
  13. PCMK__OUTPUT_ARGS
  14. PCMK__OUTPUT_ARGS
  15. PCMK__OUTPUT_ARGS
  16. PCMK__OUTPUT_ARGS
  17. PCMK__OUTPUT_ARGS
  18. PCMK__OUTPUT_ARGS
  19. PCMK__OUTPUT_ARGS
  20. PCMK__OUTPUT_ARGS
  21. PCMK__OUTPUT_ARGS
  22. add_resource_name
  23. PCMK__OUTPUT_ARGS
  24. crm_resource_register_messages

   1 /*
   2  * Copyright 2004-2023 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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     // @COMPAT lifetime is deprecated
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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         // @TODO check requires in resource meta-data and rsc_defaults
  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 // \return Standard Pacemaker return code
  91 int
  92 cli_resource_print_operations(const char *rsc_id, const char *host_uname,
     /* [previous][next][first][last][top][bottom][index][help] */
  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 // \return Standard Pacemaker return code
 116 int
 117 cli_resource_print(pe_resource_t *rsc, pe_working_set_t *data_set, bool expanded)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* Operation <action> [for <resource>] (<class>[:<provider>]:<agent>)
 167          * returned <exit-code> (<exit-description>[: <exit-reason>])
 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         /* Operation <action> [for <resource>] (<class>[:<provider>]:<agent>)
 180          * could not be executed (<execution-status>[: <exit-reason>])
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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     /* hide output for validate-all if not in verbose */
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *",
     /* [previous][next][first][last][top][bottom][index][help] */
 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) {
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *")
     /* [previous][next][first][last][top][bottom][index][help] */
 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) {
     /* [previous][next][first][last][top][bottom][index][help] */
 817     pcmk__register_messages(out, fmt_functions);
 818 }

/* [previous][next][first][last][top][bottom][index][help] */