From 6d455d7da4e758d6ad8b9385a880c25e63f3ba37 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Jan 22 2021 12:12:34 +0000 Subject: Feature: tools: Use formatted output for resource searching. This reorganizes the cli_resource_search and do_find_resource functions into more logical functions. cli_resource_search now just puts together a list of resources and returns it. This list should not be freed because it reuses existing lists. Then, there is a formatted output message to do the actual printing. --- diff --git a/tools/crm_resource.c b/tools/crm_resource.c index 3df9419..9acb955 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -1844,10 +1844,11 @@ main(int argc, char **argv) data_set); break; - case cmd_locate: - cli_resource_search(out, rsc, options.rsc_id, data_set); - rc = pcmk_rc_ok; + case cmd_locate: { + GListPtr resources = cli_resource_search(out, rsc, options.rsc_id, data_set); + rc = out->message(out, "resource-search", resources, rsc, options.rsc_id); break; + } case cmd_query_xml: rc = cli_resource_print(out, rsc, data_set, TRUE); diff --git a/tools/crm_resource.h b/tools/crm_resource.h index 377f7aa..6de2457 100644 --- a/tools/crm_resource.h +++ b/tools/crm_resource.h @@ -69,8 +69,8 @@ int cli_resource_check(pcmk__output_t *out, cib_t * cib, pe_resource_t *rsc); int cli_resource_fail(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, const char *host_uname, const char *rsc_id, pe_working_set_t *data_set); -int cli_resource_search(pcmk__output_t *out, pe_resource_t *rsc, - const char *requested_name, pe_working_set_t *data_set); +GListPtr cli_resource_search(pcmk__output_t *out, pe_resource_t *rsc, + const char *requested_name, pe_working_set_t *data_set); int cli_resource_delete(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, const char *host_uname, pe_resource_t *rsc, const char *operation, const char *interval_spec, diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c index d2a2cc8..5ff3e9b 100644 --- a/tools/crm_resource_print.c +++ b/tools/crm_resource_print.c @@ -361,6 +361,76 @@ resource_check_xml(pcmk__output_t *out, va_list args) { return rc; } +PCMK__OUTPUT_ARGS("resource-search", "GListPtr", "pe_resource_t *", "gchar *") +static int +resource_search_default(pcmk__output_t *out, va_list args) +{ + GListPtr nodes = va_arg(args, GListPtr); + pe_resource_t *rsc = va_arg(args, pe_resource_t *); + gchar *requested_name = va_arg(args, gchar *); + + bool printed = false; + int rc = pcmk_rc_no_output; + + if (!out->is_quiet(out) && nodes == NULL) { + out->err(out, "resource %s is NOT running", requested_name); + return rc; + } + + for (GListPtr lpc = nodes; lpc != NULL; lpc = lpc->next) { + pe_node_t *node = (pe_node_t *) lpc->data; + + if (!printed) { + out->begin_list(out, NULL, NULL, "Nodes"); + printed = true; + rc = pcmk_rc_ok; + } + + if (out->is_quiet(out)) { + out->list_item(out, "node", "%s", node->details->uname); + } else { + const char *state = ""; + + if (!pe_rsc_is_clone(rsc) && rsc->fns->state(rsc, TRUE) == RSC_ROLE_MASTER) { + state = " Master"; + } + out->list_item(out, "node", "resource %s is running on: %s%s", + requested_name, node->details->uname, state); + } + } + + if (printed) { + out->end_list(out); + } + + return rc; +} + + +PCMK__OUTPUT_ARGS("resource-search", "GListPtr", "pe_resource_t *", "gchar *") +static int +resource_search_xml(pcmk__output_t *out, va_list args) +{ + GListPtr nodes = va_arg(args, GListPtr); + pe_resource_t *rsc = va_arg(args, pe_resource_t *); + gchar *requested_name = va_arg(args, gchar *); + + xmlNode *xml_node = pcmk__output_xml_create_parent(out, "nodes"); + + xmlSetProp(xml_node, (pcmkXmlStr) "resource", (pcmkXmlStr) requested_name); + + for (GListPtr lpc = nodes; lpc != NULL; lpc = lpc->next) { + pe_node_t *node = (pe_node_t *) lpc->data; + xmlNode *sub_node = pcmk__output_create_xml_text_node(out, "node", node->details->uname); + + if (!pe_rsc_is_clone(rsc) && rsc->fns->state(rsc, TRUE) == RSC_ROLE_MASTER) { + xmlSetProp(sub_node, (pcmkXmlStr) "state", (pcmkXmlStr) "promoted"); + } + } + + return pcmk_rc_ok; +} + PCMK__OUTPUT_ARGS("resource-why", "cib_t *", "GListPtr", "pe_resource_t *", "pe_node_t *") static int @@ -583,6 +653,8 @@ static pcmk__message_entry_t fmt_functions[] = { { "property", "text", property_text }, { "resource-check", "default", resource_check_default }, { "resource-check", "xml", resource_check_xml }, + { "resource-search", "default", resource_search_default }, + { "resource-search", "xml", resource_search_xml }, { "resource-why", "default", resource_why_default }, { "resource-why", "xml", resource_why_xml }, { "resource-names-list", "default", resource_names }, diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c index 4f8287b..bbd8bc1 100644 --- a/tools/crm_resource_runtime.c +++ b/tools/crm_resource_runtime.c @@ -12,37 +12,6 @@ #include #include -static int -do_find_resource(pcmk__output_t *out, const char *rsc, pe_resource_t * the_rsc, - pe_working_set_t * data_set) -{ - int found = 0; - GListPtr lpc = NULL; - - for (lpc = the_rsc->running_on; lpc != NULL; lpc = lpc->next) { - pe_node_t *node = (pe_node_t *) lpc->data; - - if (out->is_quiet(out)) { - out->info(out, "%s", node->details->uname); - } else { - const char *state = ""; - - if (!pe_rsc_is_clone(the_rsc) && the_rsc->fns->state(the_rsc, TRUE) == RSC_ROLE_MASTER) { - state = "Master"; - } - out->info(out, "resource %s is running on: %s %s", rsc, node->details->uname, state); - } - - found++; - } - - if (!out->is_quiet(out) && found == 0) { - out->err(out, "resource %s is NOT running", rsc); - } - - return found; -} - resource_checks_t * cli_check_resource(pe_resource_t *rsc, char *role_s, char *managed) { @@ -72,16 +41,19 @@ cli_check_resource(pe_resource_t *rsc, char *role_s, char *managed) return rc; } -int +GListPtr cli_resource_search(pcmk__output_t *out, pe_resource_t *rsc, const char *requested_name, pe_working_set_t *data_set) { - int found = 0; + GListPtr found = NULL; pe_resource_t *parent = uber_parent(rsc); if (pe_rsc_is_clone(rsc)) { for (GListPtr iter = rsc->children; iter != NULL; iter = iter->next) { - found += do_find_resource(out, requested_name, iter->data, data_set); + GListPtr extra = ((pe_resource_t *) iter->data)->running_on; + if (extra != NULL) { + found = g_list_concat(found, extra); + } } /* The anonymous clone children's common ID is supplied */ @@ -92,11 +64,14 @@ cli_resource_search(pcmk__output_t *out, pe_resource_t *rsc, const char *request && !pcmk__str_eq(requested_name, rsc->id, pcmk__str_casei)) { for (GListPtr iter = parent->children; iter; iter = iter->next) { - found += do_find_resource(out, requested_name, iter->data, data_set); + GListPtr extra = ((pe_resource_t *) iter->data)->running_on; + if (extra != NULL) { + found = g_list_concat(found, extra); + } } - } else { - found += do_find_resource(out, requested_name, rsc, data_set); + } else if (rsc->running_on != NULL) { + found = g_list_concat(found, rsc->running_on); } return found; @@ -1828,8 +1803,8 @@ cli_resource_execute(pcmk__output_t *out, pe_resource_t *rsc, action = rsc_action+6; if(pe_rsc_is_clone(rsc)) { - int rc = cli_resource_search(out, rsc, requested_name, data_set); - if(rc > 0 && force == FALSE) { + GListPtr rscs = cli_resource_search(out, rsc, requested_name, data_set); + if(rscs != NULL && force == FALSE) { out->err(out, "It is not safe to %s %s here: the cluster claims it is already active", action, rsc->id); out->err(out, "Try setting target-role=Stopped first or specifying "