root/tools/crm_resource_print.c

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

DEFINITIONS

This source file includes following definitions.
  1. cli_resource_print_cts_constraints
  2. cli_resource_print_cts
  3. cli_resource_print_operations
  4. cli_resource_print
  5. PCMK__OUTPUT_ARGS
  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. add_resource_name
  22. PCMK__OUTPUT_ARGS
  23. crm_resource_register_messages

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

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