From 58cd86eb6dcfb8eca0cc31ac76744478e0951d9f Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mar 09 2021 06:18:48 +0000 Subject: Low: tools: handle required node names better in crm_resource Currently, --fail is the only option that requires a node name to be specified, but generalize the handling so future options can reuse it. This also makes the error handling closer to what's done for required resource names, both in error message and exit status. --- diff --git a/tools/crm_resource.c b/tools/crm_resource.c index 0f0c647..3bdb898 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -74,6 +74,7 @@ struct { gboolean require_crmd; // Whether command requires controller IPC gboolean require_dataset; // Whether command requires populated data set gboolean require_resource; // Whether command requires resource specified + gboolean require_node; // Whether command requires node specified int find_flags; // Flags to use when searching for resource // Command-line option values @@ -774,6 +775,7 @@ option_cb(const gchar *option_name, const gchar *optarg, gpointer data, gboolean fail_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) { options.require_crmd = TRUE; + options.require_node = TRUE; SET_COMMAND(cmd_fail); return TRUE; } @@ -1483,9 +1485,13 @@ main(int argc, char **argv) { xmlNode *cib_xml_copy = NULL; pe_resource_t *rsc = NULL; - + pe_node_t *node = NULL; int rc = pcmk_rc_ok; + /* + * Parse command line arguments + */ + pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY); GOptionContext *context = NULL; GOptionGroup *output_group = NULL; @@ -1502,6 +1508,10 @@ main(int argc, char **argv) goto done; } + /* + * Set verbosity + */ + for (int i = 0; i < args->verbosity; i++) { crm_bump_log_level(argc, argv); } @@ -1518,9 +1528,9 @@ main(int argc, char **argv) crm_log_args(argc, argv); - if (options.host_uname) { - crm_trace("Option host => %s", options.host_uname); - } + /* + * Validate option combinations + */ // If the user didn't explicitly specify a command, list resources if (options.rsc_cmd == cmd_none) { @@ -1634,30 +1644,42 @@ main(int argc, char **argv) * the values and set error if they don't make sense. */ validate_cmdline_config(); + if (error != NULL) { + exit_code = CRM_EX_USAGE; + goto done; + } + } else if (options.cmdline_params != NULL) { // @COMPAT @TODO error out here when we can break backward compatibility g_hash_table_destroy(options.cmdline_params); options.cmdline_params = NULL; } - if (error != NULL) { + if (options.require_resource && (options.rsc_id == NULL)) { + rc = ENXIO; + exit_code = CRM_EX_USAGE; + g_set_error(&error, PCMK__EXITC_ERROR, exit_code, + "Must supply a resource id with -r"); + goto done; + } + if (options.require_node && (options.host_uname == NULL)) { + rc = ENXIO; exit_code = CRM_EX_USAGE; + g_set_error(&error, PCMK__EXITC_ERROR, exit_code, + "Must supply a node name with -N"); goto done; } + /* + * Set up necessary connections + */ + if (options.force) { crm_debug("Forcing..."); cib__set_call_options(options.cib_options, crm_system_name, cib_quorum_override); } - if (options.require_resource && !options.rsc_id) { - rc = ENXIO; - g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE, - "Must supply a resource id with -r"); - goto done; - } - if (options.find_flags && options.rsc_id) { options.require_dataset = TRUE; } @@ -1700,6 +1722,11 @@ main(int argc, char **argv) } } + // If user supplied a node name, check whether it exists + if ((options.host_uname != NULL) && (data_set != NULL)) { + node = pe_find_node(data_set->nodes, options.host_uname); + } + // Establish a connection to the controller if needed if (options.require_crmd) { rc = pcmk_new_ipc_api(&controld_api, pcmk_ipc_controld); @@ -1718,6 +1745,10 @@ main(int argc, char **argv) } } + /* + * Handle requested command + */ + switch (options.rsc_cmd) { case cmd_list_resources: { GListPtr all = NULL; @@ -1844,18 +1875,11 @@ main(int argc, char **argv) break; case cmd_why: - { - pe_node_t *dest = NULL; - - if (options.host_uname) { - dest = pe_find_node(data_set->nodes, options.host_uname); - if (dest == NULL) { - rc = pcmk_rc_node_unknown; - goto done; - } - } - out->message(out, "resource-reasons-list", cib_conn, data_set->resources, rsc, dest); - rc = pcmk_rc_ok; + if ((options.host_uname != NULL) && (node == NULL)) { + rc = pcmk_rc_node_unknown; + } else { + rc = out->message(out, "resource-reasons-list", cib_conn, + data_set->resources, rsc, node); } break; @@ -1878,15 +1902,10 @@ main(int argc, char **argv) case cmd_ban: if (options.host_uname == NULL) { rc = ban_or_move(out, rsc, options.move_lifetime, &exit_code); + } else if (node == NULL) { + rc = pcmk_rc_node_unknown; } else { - pe_node_t *dest = pe_find_node(data_set->nodes, - options.host_uname); - - if (dest == NULL) { - rc = pcmk_rc_node_unknown; - goto done; - } - rc = cli_resource_ban(out, options.rsc_id, dest->details->uname, + rc = cli_resource_ban(out, options.rsc_id, node->details->uname, options.move_lifetime, NULL, cib_conn, options.cib_options, options.promoted_role_only); @@ -2002,6 +2021,10 @@ main(int argc, char **argv) break; } + /* + * Clean up and exit + */ + done: if (rc != pcmk_rc_ok) { if (rc == pcmk_rc_no_quorum) { diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c index 9ff9e96..3e69dc7 100644 --- a/tools/crm_resource_runtime.c +++ b/tools/crm_resource_runtime.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2020 the Pacemaker project contributors + * Copyright 2004-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -511,11 +511,7 @@ send_lrm_rsc_op(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, bool do_fail_ return EINVAL; } - if (host_uname == NULL) { - out->err(out, "Please specify a node name"); - return EINVAL; - - } else { + { pe_node_t *node = pe_find_node(data_set->nodes, host_uname); if (node == NULL) {