summaryrefslogtreecommitdiffstats
path: root/tools/crm_resource.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/crm_resource.c1101
1 files changed, 598 insertions, 503 deletions
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 7c4a0a1..c592e86 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2023 the Pacemaker project contributors
+ * Copyright 2004-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -18,6 +18,7 @@
#include <pacemaker-internal.h>
#include <sys/param.h>
+#include <stdint.h> // uint32_t
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
@@ -53,14 +54,15 @@ enum rsc_command {
cmd_list_all_ops,
cmd_list_alternatives,
cmd_list_instances,
+ cmd_list_options,
cmd_list_providers,
cmd_list_resources,
cmd_list_standards,
cmd_locate,
cmd_metadata,
cmd_move,
- cmd_query_raw_xml,
cmd_query_xml,
+ cmd_query_xml_raw,
cmd_refresh,
cmd_restart,
cmd_set_param,
@@ -72,18 +74,10 @@ enum rsc_command {
struct {
enum rsc_command rsc_cmd; // crm_resource command to perform
- // Infrastructure that given command needs to work
- gboolean require_cib; // Whether command requires CIB IPC
- int cib_options; // Options to use with CIB IPC calls
- gboolean require_crmd; // Whether command requires controller IPC
- gboolean require_scheduler; // Whether command requires scheduler data
- 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
gchar *rsc_id; // Value of --resource
gchar *rsc_type; // Value of --resource-type
+ gboolean all; // --all was given
gboolean force; // --force was given
gboolean clear_expired; // --expired was given
gboolean recursive; // --recursive was given
@@ -92,18 +86,19 @@ struct {
gchar *interval_spec; // Value of --interval
gchar *move_lifetime; // Value of --lifetime
gchar *operation; // Value of --operation
+ enum pcmk__opt_flags opt_list; // Parsed from --list-options
const char *attr_set_type; // Instance, meta, utilization, or element attribute
gchar *prop_id; // --nvpair (attribute XML ID)
char *prop_name; // Attribute name
gchar *prop_set; // --set-name (attribute block XML ID)
gchar *prop_value; // --parameter-value (attribute value)
- int timeout_ms; // Parsed from --timeout value
+ guint timeout_ms; // Parsed from --timeout value
char *agent_spec; // Standard and/or provider and/or agent
gchar *xml_file; // Value of (deprecated) --xml-file
int check_level; // Optional value of --validate or --force-check
// Resource configuration specified via command-line arguments
- gboolean cmdline_config; // Resource configuration was via arguments
+ bool cmdline_config; // Resource configuration was via arguments
char *v_agent; // Value of --agent
char *v_class; // Value of --class
char *v_provider; // Value of --provider
@@ -113,66 +108,17 @@ struct {
gchar **remainder; // Positional arguments as given
GHashTable *override_params; // Resource parameter values that override config
} options = {
- .attr_set_type = XML_TAG_ATTR_SETS,
+ .attr_set_type = PCMK_XE_INSTANCE_ATTRIBUTES,
.check_level = -1,
- .cib_options = cib_sync_call,
- .require_cib = TRUE,
- .require_scheduler = TRUE,
- .require_resource = TRUE,
+ .rsc_cmd = cmd_list_resources, // List all resources if no command given
};
-#if 0
-// @COMPAT @TODO enable this at next backward compatibility break
-#define SET_COMMAND(cmd) do { \
- if (options.rsc_cmd != cmd_none) { \
- g_set_error(error, PCMK__EXITC_ERROR, CRM_EX_USAGE, \
- "Only one command option may be specified"); \
- return FALSE; \
- } \
- options.rsc_cmd = (cmd); \
- } while (0)
-#else
-#define SET_COMMAND(cmd) do { \
- if (options.rsc_cmd != cmd_none) { \
- reset_options(); \
- } \
- options.rsc_cmd = (cmd); \
- } while (0)
-#endif
-
-gboolean agent_provider_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
gboolean attr_set_type_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean class_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean cleanup_refresh_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean delete_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean expired_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean list_agents_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error);
-gboolean list_providers_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error);
-gboolean list_standards_cb(const gchar *option_name, const gchar *optarg,
+gboolean cmdline_config_cb(const gchar *option_name, const gchar *optarg,
gpointer data, GError **error);
-gboolean list_alternatives_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error);
-gboolean metadata_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error);
gboolean option_cb(const gchar *option_name, const gchar *optarg,
gpointer data, GError **error);
-gboolean fail_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean flag_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean get_param_prop_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean list_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean set_delete_param_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean set_prop_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
gboolean timeout_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean validate_or_force_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error);
-gboolean restart_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error);
-gboolean digests_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error);
-gboolean wait_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
-gboolean why_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
static crm_exit_t exit_code = CRM_EX_OK;
static pcmk__output_t *out = NULL;
@@ -326,77 +272,266 @@ build_constraint_list(xmlNode *root)
xmlXPathObjectPtr xpathObj = NULL;
int ndx = 0;
- cib_constraints = pcmk_find_cib_element(root, XML_CIB_TAG_CONSTRAINTS);
- xpathObj = xpath_search(cib_constraints, "//" XML_CONS_TAG_RSC_LOCATION);
+ cib_constraints = pcmk_find_cib_element(root, PCMK_XE_CONSTRAINTS);
+ xpathObj = xpath_search(cib_constraints, "//" PCMK_XE_RSC_LOCATION);
for (ndx = 0; ndx < numXpathResults(xpathObj); ndx++) {
xmlNode *match = getXpathResult(xpathObj, ndx);
- retval = g_list_insert_sorted(retval, (gpointer) ID(match), compare_id);
+ retval = g_list_insert_sorted(retval, (gpointer) pcmk__xe_id(match),
+ compare_id);
}
freeXpathObject(xpathObj);
return retval;
}
+static gboolean
+validate_opt_list(const gchar *optarg)
+{
+ if (pcmk__str_eq(optarg, PCMK_VALUE_FENCING, pcmk__str_none)) {
+ options.opt_list = pcmk__opt_fencing;
+
+ } else if (pcmk__str_eq(optarg, PCMK__VALUE_PRIMITIVE, pcmk__str_none)) {
+ options.opt_list = pcmk__opt_primitive;
+
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*!
+ * \internal
+ * \brief Process options that set the command
+ *
+ * Nothing else should set \c options.rsc_cmd.
+ *
+ * \param[in] option_name Name of the option being parsed
+ * \param[in] optarg Value to be parsed
+ * \param[in] data Ignored
+ * \param[out] error Where to store recoverable error, if any
+ *
+ * \return \c TRUE if the option was successfully parsed, or \c FALSE if an
+ * error occurred, in which case \p *error is set
+ */
+static gboolean
+command_cb(const gchar *option_name, const gchar *optarg, gpointer data,
+ GError **error)
+{
+ // Sorted by enum rsc_command name
+ if (pcmk__str_any_of(option_name, "-B", "--ban", NULL)) {
+ options.rsc_cmd = cmd_ban;
+
+ } else if (pcmk__str_any_of(option_name, "-C", "--cleanup", NULL)) {
+ options.rsc_cmd = cmd_cleanup;
+
+ } else if (pcmk__str_any_of(option_name, "-U", "--clear", NULL)) {
+ options.rsc_cmd = cmd_clear;
+
+ } else if (pcmk__str_any_of(option_name, "-a", "--constraints", NULL)) {
+ options.rsc_cmd = cmd_colocations;
+
+ } else if (pcmk__str_any_of(option_name, "-A", "--stack", NULL)) {
+ options.rsc_cmd = cmd_colocations;
+ options.recursive = TRUE;
+
+ } else if (pcmk__str_any_of(option_name, "-c", "--list-cts", NULL)) {
+ options.rsc_cmd = cmd_cts;
+
+ } else if (pcmk__str_any_of(option_name, "-D", "--delete", NULL)) {
+ options.rsc_cmd = cmd_delete;
+
+ } else if (pcmk__str_any_of(option_name, "-d", "--delete-parameter",
+ NULL)) {
+ options.rsc_cmd = cmd_delete_param;
+ pcmk__str_update(&options.prop_name, optarg);
+
+ } else if (pcmk__str_eq(option_name, "--digests", pcmk__str_none)) {
+ options.rsc_cmd = cmd_digests;
+
+ if (options.override_params == NULL) {
+ options.override_params = pcmk__strkey_table(free, free);
+ }
+
+ } else if (pcmk__str_any_of(option_name,
+ "--force-demote", "--force-promote",
+ "--force-start", "--force-stop",
+ "--force-check", "--validate", NULL)) {
+ options.rsc_cmd = cmd_execute_agent;
+
+ g_free(options.operation);
+ options.operation = g_strdup(option_name + 2); // skip "--"
+
+ if (options.override_params == NULL) {
+ options.override_params = pcmk__strkey_table(free, free);
+ }
+
+ if (optarg != NULL) {
+ if (pcmk__scan_min_int(optarg, &options.check_level,
+ 0) != pcmk_rc_ok) {
+ g_set_error(error, G_OPTION_ERROR, CRM_EX_INVALID_PARAM,
+ _("Invalid check level setting: %s"), optarg);
+ return FALSE;
+ }
+ }
+
+ } else if (pcmk__str_any_of(option_name, "-F", "--fail", NULL)) {
+ options.rsc_cmd = cmd_fail;
+
+ } else if (pcmk__str_any_of(option_name, "-g", "--get-parameter", NULL)) {
+ options.rsc_cmd = cmd_get_param;
+ pcmk__str_update(&options.prop_name, optarg);
+
+ } else if (pcmk__str_any_of(option_name, "-G", "--get-property", NULL)) {
+ options.rsc_cmd = cmd_get_property;
+ pcmk__str_update(&options.prop_name, optarg);
+
+ } else if (pcmk__str_any_of(option_name, "-O", "--list-operations", NULL)) {
+ options.rsc_cmd = cmd_list_active_ops;
+
+ } else if (pcmk__str_eq(option_name, "--list-agents", pcmk__str_none)) {
+ options.rsc_cmd = cmd_list_agents;
+ pcmk__str_update(&options.agent_spec, optarg);
+
+ } else if (pcmk__str_any_of(option_name, "-o", "--list-all-operations",
+ NULL)) {
+ options.rsc_cmd = cmd_list_all_ops;
+
+ } else if (pcmk__str_eq(option_name, "--list-ocf-alternatives",
+ pcmk__str_none)) {
+ options.rsc_cmd = cmd_list_alternatives;
+ pcmk__str_update(&options.agent_spec, optarg);
+
+ } else if (pcmk__str_eq(option_name, "--list-options", pcmk__str_none)) {
+ options.rsc_cmd = cmd_list_options;
+ return validate_opt_list(optarg);
+
+ } else if (pcmk__str_any_of(option_name, "-l", "--list-raw", NULL)) {
+ options.rsc_cmd = cmd_list_instances;
+
+ } else if (pcmk__str_eq(option_name, "--list-ocf-providers",
+ pcmk__str_none)) {
+ options.rsc_cmd = cmd_list_providers;
+ pcmk__str_update(&options.agent_spec, optarg);
+
+ } else if (pcmk__str_any_of(option_name, "-L", "--list", NULL)) {
+ options.rsc_cmd = cmd_list_resources;
+
+ } else if (pcmk__str_eq(option_name, "--list-standards", pcmk__str_none)) {
+ options.rsc_cmd = cmd_list_standards;
+
+ } else if (pcmk__str_any_of(option_name, "-W", "--locate", NULL)) {
+ options.rsc_cmd = cmd_locate;
+
+ } else if (pcmk__str_eq(option_name, "--show-metadata", pcmk__str_none)) {
+ options.rsc_cmd = cmd_metadata;
+ pcmk__str_update(&options.agent_spec, optarg);
+
+ } else if (pcmk__str_any_of(option_name, "-M", "--move", NULL)) {
+ options.rsc_cmd = cmd_move;
+
+ } else if (pcmk__str_any_of(option_name, "-q", "--query-xml", NULL)) {
+ options.rsc_cmd = cmd_query_xml;
+
+ } else if (pcmk__str_any_of(option_name, "-w", "--query-xml-raw", NULL)) {
+ options.rsc_cmd = cmd_query_xml_raw;
+
+ } else if (pcmk__str_any_of(option_name, "-R", "--refresh", NULL)) {
+ options.rsc_cmd = cmd_refresh;
+
+ } else if (pcmk__str_eq(option_name, "--restart", pcmk__str_none)) {
+ options.rsc_cmd = cmd_restart;
+
+ } else if (pcmk__str_any_of(option_name, "-p", "--set-parameter", NULL)) {
+ options.rsc_cmd = cmd_set_param;
+ pcmk__str_update(&options.prop_name, optarg);
+
+ } else if (pcmk__str_any_of(option_name, "-S", "--set-property", NULL)) {
+ options.rsc_cmd = cmd_set_property;
+ pcmk__str_update(&options.prop_name, optarg);
+
+ } else if (pcmk__str_eq(option_name, "--wait", pcmk__str_none)) {
+ options.rsc_cmd = cmd_wait;
+
+ } else if (pcmk__str_any_of(option_name, "-Y", "--why", NULL)) {
+ options.rsc_cmd = cmd_why;
+ }
+
+ return TRUE;
+}
+
/* short option letters still available: eEJkKXyYZ */
static GOptionEntry query_entries[] = {
- { "list", 'L', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
+ { "list", 'L', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"List all cluster resources with status",
NULL },
- { "list-raw", 'l', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
+ { "list-raw", 'l', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"List IDs of all instantiated resources (individual members\n"
INDENT "rather than groups etc.)",
NULL },
- { "list-cts", 'c', G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
+ { "list-cts", 'c', G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK, command_cb,
NULL,
NULL },
- { "list-operations", 'O', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
+ { "list-operations", 'O', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ command_cb,
"List active resource operations, optionally filtered by\n"
INDENT "--resource and/or --node",
NULL },
- { "list-all-operations", 'o', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
+ { "list-all-operations", 'o', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ command_cb,
"List all resource operations, optionally filtered by\n"
INDENT "--resource and/or --node",
NULL },
+ { "list-options", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, command_cb,
+ "List all available options of the given type\n"
+ INDENT "Allowed values:\n"
+ INDENT PCMK__VALUE_PRIMITIVE "(primitive resource meta-attributes), "
+ INDENT PCMK_VALUE_FENCING " (parameters common to all fencing resources)",
+ "TYPE" },
{ "list-standards", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- list_standards_cb,
+ command_cb,
"List supported standards",
NULL },
{ "list-ocf-providers", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- list_providers_cb,
+ command_cb,
"List all available OCF providers",
NULL },
{ "list-agents", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
- list_agents_cb,
+ command_cb,
"List all agents available for the named standard and/or provider",
"STD:PROV" },
{ "list-ocf-alternatives", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
- list_alternatives_cb,
+ command_cb,
"List all available providers for the named OCF agent",
"AGENT" },
- { "show-metadata", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
- metadata_cb,
+ { "show-metadata", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, command_cb,
"Show the metadata for the named class:provider:agent",
"SPEC" },
- { "query-xml", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
+ { "query-xml", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"Show XML configuration of resource (after any template expansion)",
NULL },
- { "query-xml-raw", 'w', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
+ { "query-xml-raw", 'w', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ command_cb,
"Show XML configuration of resource (before any template expansion)",
NULL },
- { "get-parameter", 'g', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, get_param_prop_cb,
+ { "get-parameter", 'g', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
+ command_cb,
"Display named parameter for resource (use instance attribute\n"
INDENT "unless --element, --meta, or --utilization is specified)",
"PARAM" },
- { "get-property", 'G', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, get_param_prop_cb,
+ { "get-property", 'G', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK,
+ command_cb,
"Display named property of resource ('class', 'type', or 'provider') "
"(requires --resource)",
"PROPERTY" },
- { "locate", 'W', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
+ { "locate", 'W', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"Show node(s) currently running resource",
NULL },
- { "constraints", 'a', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
+ { "constraints", 'a', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ command_cb,
"Display the location and colocation constraints that apply to a\n"
INDENT "resource, and if --recursive is specified, to the resources\n"
INDENT "directly or indirectly involved in those colocations.\n"
@@ -404,10 +539,10 @@ static GOptionEntry query_entries[] = {
INDENT "bundle instance, constraints for the collective resource\n"
INDENT "will be shown unless --force is given.",
NULL },
- { "stack", 'A', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
+ { "stack", 'A', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"Equivalent to --constraints --recursive",
NULL },
- { "why", 'Y', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, why_cb,
+ { "why", 'Y', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"Show why resources are not running, optionally filtered by\n"
INDENT "--resource and/or --node",
NULL },
@@ -417,7 +552,7 @@ static GOptionEntry query_entries[] = {
static GOptionEntry command_entries[] = {
{ "validate", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- validate_or_force_cb,
+ command_cb,
"Validate resource configuration by calling agent's validate-all\n"
INDENT "action. The configuration may be specified either by giving an\n"
INDENT "existing resource name with -r, or by specifying --class,\n"
@@ -425,7 +560,7 @@ static GOptionEntry command_entries[] = {
INDENT "--option arguments. An optional LEVEL argument can be given\n"
INDENT "to control the level of checking performed.",
"LEVEL" },
- { "cleanup", 'C', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, cleanup_refresh_cb,
+ { "cleanup", 'C', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"If resource has any past failures, clear its history and fail\n"
INDENT "count. Optionally filtered by --resource, --node, --operation\n"
INDENT "and --interval (otherwise all). --operation and --interval\n"
@@ -435,23 +570,26 @@ static GOptionEntry command_entries[] = {
INDENT "resource, the clean-up applies to the whole collective resource\n"
INDENT "unless --force is given.",
NULL },
- { "refresh", 'R', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, cleanup_refresh_cb,
+ { "refresh", 'R', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"Delete resource's history (including failures) so its current state\n"
INDENT "is rechecked. Optionally filtered by --resource and --node\n"
INDENT "(otherwise all). If the named resource is part of a group, or one\n"
INDENT "numbered instance of a clone or bundled resource, the refresh\n"
INDENT "applies to the whole collective resource unless --force is given.",
NULL },
- { "set-parameter", 'p', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, set_delete_param_cb,
+ { "set-parameter", 'p', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
+ command_cb,
"Set named parameter for resource (requires -v). Use instance\n"
INDENT "attribute unless --element, --meta, or --utilization is "
"specified.",
"PARAM" },
- { "delete-parameter", 'd', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, set_delete_param_cb,
+ { "delete-parameter", 'd', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
+ command_cb,
"Delete named parameter for resource. Use instance attribute\n"
INDENT "unless --element, --meta or, --utilization is specified.",
"PARAM" },
- { "set-property", 'S', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, set_prop_cb,
+ { "set-property", 'S', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK,
+ command_cb,
"Set named property of resource ('class', 'type', or 'provider') "
"(requires -r, -t, -v)",
"PROPERTY" },
@@ -460,7 +598,7 @@ static GOptionEntry command_entries[] = {
};
static GOptionEntry location_entries[] = {
- { "move", 'M', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
+ { "move", 'M', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"Create a constraint to move resource. If --node is specified,\n"
INDENT "the constraint will be to move to that node, otherwise it\n"
INDENT "will be to ban the current node. Unless --force is specified\n"
@@ -471,7 +609,7 @@ static GOptionEntry location_entries[] = {
INDENT "resource from running on its previous location until the\n"
INDENT "implicit constraint expires or is removed with --clear.",
NULL },
- { "ban", 'B', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
+ { "ban", 'B', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"Create a constraint to keep resource off a node.\n"
INDENT "Optional: --node, --lifetime, --promoted.\n"
INDENT "NOTE: This will prevent the resource from running on the\n"
@@ -479,10 +617,10 @@ static GOptionEntry location_entries[] = {
INDENT "removed with --clear. If --node is not specified, it defaults\n"
INDENT "to the node currently running the resource for primitives\n"
INDENT "and groups, or the promoted instance of promotable clones with\n"
- INDENT "promoted-max=1 (all other situations result in an error as\n"
- INDENT "there is no sane default).",
+ INDENT PCMK_META_PROMOTED_MAX "=1 (all other situations result in an\n"
+ INDENT "error as there is no sane default).",
NULL },
- { "clear", 'U', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
+ { "clear", 'U', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"Remove all constraints created by the --ban and/or --move\n"
INDENT "commands. Requires: --resource. Optional: --node, --promoted,\n"
INDENT "--expired. If --node is not specified, all constraints created\n"
@@ -492,7 +630,8 @@ static GOptionEntry location_entries[] = {
INDENT "node. If --expired is specified, only those constraints whose\n"
INDENT "lifetimes have expired will be removed.",
NULL },
- { "expired", 'e', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, expired_cb,
+ { "expired", 'e', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE,
+ &options.clear_expired,
"Modifies the --clear argument to remove constraints with\n"
INDENT "expired lifetimes.",
NULL },
@@ -516,20 +655,20 @@ static GOptionEntry location_entries[] = {
};
static GOptionEntry advanced_entries[] = {
- { "delete", 'D', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, delete_cb,
+ { "delete", 'D', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"(Advanced) Delete a resource from the CIB. Required: -t",
NULL },
- { "fail", 'F', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, fail_cb,
+ { "fail", 'F', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"(Advanced) Tell the cluster this resource has failed",
NULL },
- { "restart", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, restart_cb,
+ { "restart", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"(Advanced) Tell the cluster to restart this resource and\n"
INDENT "anything that depends on it",
NULL },
- { "wait", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, wait_cb,
+ { "wait", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"(Advanced) Wait until the cluster settles into a stable state",
NULL },
- { "digests", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, digests_cb,
+ { "digests", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"(Advanced) Show parameter hashes that Pacemaker uses to detect\n"
INDENT "configuration changes (only accurate if there is resource\n"
INDENT "history on the specified node). Required: --resource, --node.\n"
@@ -538,32 +677,30 @@ static GOptionEntry advanced_entries[] = {
INDENT "changes).",
NULL },
{ "force-demote", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- validate_or_force_cb,
+ command_cb,
"(Advanced) Bypass the cluster and demote a resource on the local\n"
INDENT "node. Unless --force is specified, this will refuse to do so if\n"
INDENT "the cluster believes the resource is a clone instance already\n"
INDENT "running on the local node.",
NULL },
- { "force-stop", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- validate_or_force_cb,
+ { "force-stop", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"(Advanced) Bypass the cluster and stop a resource on the local node",
NULL },
- { "force-start", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- validate_or_force_cb,
+ { "force-start", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb,
"(Advanced) Bypass the cluster and start a resource on the local\n"
INDENT "node. Unless --force is specified, this will refuse to do so if\n"
INDENT "the cluster believes the resource is a clone instance already\n"
INDENT "running on the local node.",
NULL },
{ "force-promote", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- validate_or_force_cb,
+ command_cb,
"(Advanced) Bypass the cluster and promote a resource on the local\n"
INDENT "node. Unless --force is specified, this will refuse to do so if\n"
INDENT "the cluster believes the resource is a clone instance already\n"
INDENT "running on the local node.",
NULL },
{ "force-check", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- validate_or_force_cb,
+ command_cb,
"(Advanced) Bypass the cluster and check the state of a resource on\n"
INDENT "the local node. An optional LEVEL argument can be given\n"
INDENT "to control the level of checking performed.",
@@ -603,15 +740,16 @@ static GOptionEntry addl_entries[] = {
{ "interval", 'I', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.interval_spec,
"Interval of operation to clear (default 0) (with -C -r -n)",
"N" },
- { "class", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, class_cb,
+ { "class", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, cmdline_config_cb,
"The standard the resource agent conforms to (for example, ocf).\n"
INDENT "Use with --agent, --provider, --option, and --validate.",
"CLASS" },
- { "agent", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, agent_provider_cb,
+ { "agent", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, cmdline_config_cb,
"The agent to use (for example, IPaddr). Use with --class,\n"
INDENT "--provider, --option, and --validate.",
"AGENT" },
- { "provider", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, agent_provider_cb,
+ { "provider", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
+ cmdline_config_cb,
"The vendor that supplies the resource agent (for example,\n"
INDENT "heartbeat). Use with --class, --agent, --option, and --validate.",
"PROVIDER" },
@@ -630,6 +768,10 @@ static GOptionEntry addl_entries[] = {
"(Advanced) Abort if command does not finish in this time (with\n"
INDENT "--restart, --wait, --force-*)",
"N" },
+ { "all", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.all,
+ "List all options, including advanced and deprecated (with\n"
+ INDENT "--list-options)",
+ NULL },
{ "force", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.force,
"Force the action to be performed. See help for individual commands for\n"
INDENT "additional behavior.",
@@ -644,136 +786,33 @@ static GOptionEntry addl_entries[] = {
{ NULL }
};
-static void
-reset_options(void) {
- options.require_crmd = FALSE;
- options.require_node = FALSE;
-
- options.require_cib = TRUE;
- options.require_scheduler = TRUE;
- options.require_resource = TRUE;
-
- options.find_flags = 0;
-}
-
-gboolean
-agent_provider_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- options.cmdline_config = TRUE;
- options.require_resource = FALSE;
-
- if (pcmk__str_eq(option_name, "--provider", pcmk__str_casei)) {
- pcmk__str_update(&options.v_provider, optarg);
- } else {
- pcmk__str_update(&options.v_agent, optarg);
- }
-
- return TRUE;
-}
-
gboolean
attr_set_type_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
if (pcmk__str_any_of(option_name, "-m", "--meta", NULL)) {
- options.attr_set_type = XML_TAG_META_SETS;
+ options.attr_set_type = PCMK_XE_META_ATTRIBUTES;
} else if (pcmk__str_any_of(option_name, "-z", "--utilization", NULL)) {
- options.attr_set_type = XML_TAG_UTILIZATION;
- } else if (pcmk__str_eq(option_name, "--element", pcmk__str_casei)) {
+ options.attr_set_type = PCMK_XE_UTILIZATION;
+ } else if (pcmk__str_eq(option_name, "--element", pcmk__str_none)) {
options.attr_set_type = ATTR_SET_ELEMENT;
}
return TRUE;
}
gboolean
-class_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- pcmk__str_update(&options.v_class, optarg);
- options.cmdline_config = TRUE;
- options.require_resource = FALSE;
- return TRUE;
-}
-
-gboolean
-cleanup_refresh_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- if (pcmk__str_any_of(option_name, "-C", "--cleanup", NULL)) {
- SET_COMMAND(cmd_cleanup);
- } else {
- SET_COMMAND(cmd_refresh);
- }
-
- options.require_resource = FALSE;
- if (getenv("CIB_file") == NULL) {
- options.require_crmd = TRUE;
- }
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_anon_basename;
- return TRUE;
-}
-
-gboolean
-delete_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- SET_COMMAND(cmd_delete);
- options.require_scheduler = FALSE;
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_basename;
- return TRUE;
-}
-
-gboolean
-expired_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- options.clear_expired = TRUE;
- options.require_resource = FALSE;
- return TRUE;
-}
-
-static void
-get_agent_spec(const gchar *optarg)
-{
- options.require_cib = FALSE;
- options.require_scheduler = FALSE;
- options.require_resource = FALSE;
- pcmk__str_update(&options.agent_spec, optarg);
-}
-
-gboolean
-list_agents_cb(const gchar *option_name, const gchar *optarg, gpointer data,
- GError **error)
-{
- SET_COMMAND(cmd_list_agents);
- get_agent_spec(optarg);
- return TRUE;
-}
-
-gboolean
-list_providers_cb(const gchar *option_name, const gchar *optarg, gpointer data,
+cmdline_config_cb(const gchar *option_name, const gchar *optarg, gpointer data,
GError **error)
{
- SET_COMMAND(cmd_list_providers);
- get_agent_spec(optarg);
- return TRUE;
-}
+ options.cmdline_config = true;
-gboolean
-list_standards_cb(const gchar *option_name, const gchar *optarg, gpointer data,
- GError **error)
-{
- SET_COMMAND(cmd_list_standards);
- options.require_cib = FALSE;
- options.require_scheduler = FALSE;
- options.require_resource = FALSE;
- return TRUE;
-}
+ if (pcmk__str_eq(option_name, "--class", pcmk__str_none)) {
+ pcmk__str_update(&options.v_class, optarg);
-gboolean
-list_alternatives_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error)
-{
- SET_COMMAND(cmd_list_alternatives);
- get_agent_spec(optarg);
- return TRUE;
-}
+ } else if (pcmk__str_eq(option_name, "--provider", pcmk__str_none)) {
+ pcmk__str_update(&options.v_provider, optarg);
-gboolean
-metadata_cb(const gchar *option_name, const gchar *optarg, gpointer data,
- GError **error)
-{
- SET_COMMAND(cmd_metadata);
- get_agent_spec(optarg);
+ } else { // --agent
+ pcmk__str_update(&options.v_agent, optarg);
+ }
return TRUE;
}
@@ -795,173 +834,16 @@ 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) {
- SET_COMMAND(cmd_fail);
- options.require_crmd = TRUE;
- options.require_node = TRUE;
- return TRUE;
-}
-
-gboolean
-flag_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- if (pcmk__str_any_of(option_name, "-U", "--clear", NULL)) {
- SET_COMMAND(cmd_clear);
- options.find_flags = pcmk_rsc_match_history
- |pcmk_rsc_match_anon_basename;
- } else if (pcmk__str_any_of(option_name, "-B", "--ban", NULL)) {
- SET_COMMAND(cmd_ban);
- options.find_flags = pcmk_rsc_match_history
- |pcmk_rsc_match_anon_basename;
- } else if (pcmk__str_any_of(option_name, "-M", "--move", NULL)) {
- SET_COMMAND(cmd_move);
- options.find_flags = pcmk_rsc_match_history
- |pcmk_rsc_match_anon_basename;
- } else if (pcmk__str_any_of(option_name, "-q", "--query-xml", NULL)) {
- SET_COMMAND(cmd_query_xml);
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_basename;
- } else if (pcmk__str_any_of(option_name, "-w", "--query-xml-raw", NULL)) {
- SET_COMMAND(cmd_query_raw_xml);
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_basename;
- } else if (pcmk__str_any_of(option_name, "-W", "--locate", NULL)) {
- SET_COMMAND(cmd_locate);
- options.find_flags = pcmk_rsc_match_history
- |pcmk_rsc_match_anon_basename;
-
- } else if (pcmk__str_any_of(option_name, "-a", "--constraints", NULL)) {
- SET_COMMAND(cmd_colocations);
- options.find_flags = pcmk_rsc_match_history
- |pcmk_rsc_match_anon_basename;
-
- } else if (pcmk__str_any_of(option_name, "-A", "--stack", NULL)) {
- SET_COMMAND(cmd_colocations);
- options.find_flags = pcmk_rsc_match_history
- |pcmk_rsc_match_anon_basename;
- options.recursive = TRUE;
- }
-
- return TRUE;
-}
-
-gboolean
-get_param_prop_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- if (pcmk__str_any_of(option_name, "-g", "--get-parameter", NULL)) {
- SET_COMMAND(cmd_get_param);
- } else {
- SET_COMMAND(cmd_get_property);
- }
-
- pcmk__str_update(&options.prop_name, optarg);
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_basename;
- return TRUE;
-}
-
-gboolean
-list_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- if (pcmk__str_any_of(option_name, "-c", "--list-cts", NULL)) {
- SET_COMMAND(cmd_cts);
- } else if (pcmk__str_any_of(option_name, "-L", "--list", NULL)) {
- SET_COMMAND(cmd_list_resources);
- } else if (pcmk__str_any_of(option_name, "-l", "--list-raw", NULL)) {
- SET_COMMAND(cmd_list_instances);
- } else if (pcmk__str_any_of(option_name, "-O", "--list-operations", NULL)) {
- SET_COMMAND(cmd_list_active_ops);
- } else {
- SET_COMMAND(cmd_list_all_ops);
- }
-
- options.require_resource = FALSE;
- return TRUE;
-}
-
-gboolean
-set_delete_param_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- if (pcmk__str_any_of(option_name, "-p", "--set-parameter", NULL)) {
- SET_COMMAND(cmd_set_param);
- } else {
- SET_COMMAND(cmd_delete_param);
- }
-
- pcmk__str_update(&options.prop_name, optarg);
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_basename;
- return TRUE;
-}
-
-gboolean
-set_prop_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- SET_COMMAND(cmd_set_property);
- options.require_scheduler = FALSE;
- pcmk__str_update(&options.prop_name, optarg);
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_basename;
- return TRUE;
-}
-
-gboolean
timeout_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- options.timeout_ms = crm_get_msec(optarg);
- return TRUE;
-}
-
-gboolean
-validate_or_force_cb(const gchar *option_name, const gchar *optarg,
- gpointer data, GError **error)
-{
- SET_COMMAND(cmd_execute_agent);
- if (options.operation) {
- g_free(options.operation);
- }
- options.operation = g_strdup(option_name + 2); // skip "--"
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_anon_basename;
- if (options.override_params == NULL) {
- options.override_params = pcmk__strkey_table(free, free);
- }
-
- if (optarg != NULL) {
- if (pcmk__scan_min_int(optarg, &options.check_level, 0) != pcmk_rc_ok) {
- g_set_error(error, G_OPTION_ERROR, CRM_EX_INVALID_PARAM,
- _("Invalid check level setting: %s"), optarg);
- return FALSE;
- }
- }
-
- return TRUE;
-}
+ long long timeout_ms = crm_get_msec(optarg);
-gboolean
-restart_cb(const gchar *option_name, const gchar *optarg, gpointer data,
- GError **error)
-{
- SET_COMMAND(cmd_restart);
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_anon_basename;
- return TRUE;
-}
-
-gboolean
-digests_cb(const gchar *option_name, const gchar *optarg, gpointer data,
- GError **error)
-{
- SET_COMMAND(cmd_digests);
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_anon_basename;
- if (options.override_params == NULL) {
- options.override_params = pcmk__strkey_table(free, free);
+ if (timeout_ms < 0) {
+ // @COMPAT When we can break backward compatibilty, return FALSE
+ crm_warn("Ignoring invalid timeout '%s'", optarg);
+ options.timeout_ms = 0U;
+ } else {
+ options.timeout_ms = (guint) QB_MIN(timeout_ms, UINT_MAX);
}
- options.require_node = TRUE;
- options.require_scheduler = TRUE;
- return TRUE;
-}
-
-gboolean
-wait_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- SET_COMMAND(cmd_wait);
- options.require_resource = FALSE;
- options.require_scheduler = FALSE;
- return TRUE;
-}
-
-gboolean
-why_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
- SET_COMMAND(cmd_why);
- options.require_resource = FALSE;
- options.find_flags = pcmk_rsc_match_history|pcmk_rsc_match_anon_basename;
return TRUE;
}
@@ -979,8 +861,8 @@ ban_or_move(pcmk__output_t *out, pcmk_resource_t *rsc,
if (nactive == 1) {
rc = cli_resource_ban(out, options.rsc_id, current->details->uname, move_lifetime,
- cib_conn, options.cib_options, options.promoted_role_only,
- PCMK__ROLE_PROMOTED);
+ cib_conn, cib_sync_call,
+ options.promoted_role_only, PCMK_ROLE_PROMOTED);
} else if (pcmk_is_set(rsc->flags, pcmk_rsc_promotable)) {
int count = 0;
@@ -993,14 +875,15 @@ ban_or_move(pcmk__output_t *out, pcmk_resource_t *rsc,
if (child_role == pcmk_role_promoted) {
count++;
- current = pe__current_node(child);
+ current = pcmk__current_node(child);
}
}
if(count == 1 && current) {
rc = cli_resource_ban(out, options.rsc_id, current->details->uname, move_lifetime,
- cib_conn, options.cib_options, options.promoted_role_only,
- PCMK__ROLE_PROMOTED);
+ cib_conn, cib_sync_call,
+ options.promoted_role_only,
+ PCMK_ROLE_PROMOTED);
} else {
rc = EINVAL;
@@ -1066,12 +949,12 @@ clear_constraints(pcmk__output_t *out, xmlNodePtr *cib_xml_copy)
if (options.clear_expired) {
rc = cli_resource_clear_all_expired(scheduler->input, cib_conn,
- options.cib_options, options.rsc_id,
+ cib_sync_call, options.rsc_id,
options.host_uname,
options.promoted_role_only);
} else if (options.host_uname) {
- dest = pe_find_node(scheduler->nodes, options.host_uname);
+ dest = pcmk_find_node(scheduler, options.host_uname);
if (dest == NULL) {
rc = pcmk_rc_node_unknown;
if (!out->is_quiet(out)) {
@@ -1080,11 +963,11 @@ clear_constraints(pcmk__output_t *out, xmlNodePtr *cib_xml_copy)
return rc;
}
rc = cli_resource_clear(options.rsc_id, dest->details->uname, NULL,
- cib_conn, options.cib_options, TRUE, options.force);
+ cib_conn, cib_sync_call, true, options.force);
} else {
rc = cli_resource_clear(options.rsc_id, NULL, scheduler->nodes,
- cib_conn, options.cib_options, TRUE, options.force);
+ cib_conn, cib_sync_call, true, options.force);
}
if (!out->is_quiet(out)) {
@@ -1119,35 +1002,12 @@ clear_constraints(pcmk__output_t *out, xmlNodePtr *cib_xml_copy)
}
static int
-delete(void)
-{
- int rc = pcmk_rc_ok;
- xmlNode *msg_data = NULL;
-
- if (options.rsc_type == NULL) {
- rc = ENXIO;
- g_set_error(&error, PCMK__RC_ERROR, rc,
- _("You need to specify a resource type with -t"));
- return rc;
- }
-
- msg_data = create_xml_node(NULL, options.rsc_type);
- crm_xml_add(msg_data, XML_ATTR_ID, options.rsc_id);
-
- rc = cib_conn->cmds->remove(cib_conn, XML_CIB_TAG_RESOURCES, msg_data,
- options.cib_options);
- rc = pcmk_legacy2rc(rc);
- free_xml(msg_data);
- return rc;
-}
-
-static int
initialize_scheduler_data(xmlNodePtr *cib_xml_copy)
{
int rc = pcmk_rc_ok;
if (options.xml_file != NULL) {
- *cib_xml_copy = filename2xml(options.xml_file);
+ *cib_xml_copy = pcmk__xml_read(options.xml_file);
if (*cib_xml_copy == NULL) {
rc = pcmk_rc_cib_corrupt;
}
@@ -1161,7 +1021,7 @@ initialize_scheduler_data(xmlNodePtr *cib_xml_copy)
if (scheduler == NULL) {
rc = ENOMEM;
} else {
- pe__set_working_set_flags(scheduler,
+ pcmk__set_scheduler_flags(scheduler,
pcmk_sched_no_counts
|pcmk_sched_no_compat);
scheduler->priv = out;
@@ -1179,6 +1039,26 @@ initialize_scheduler_data(xmlNodePtr *cib_xml_copy)
return pcmk_rc_ok;
}
+static void
+list_options(void)
+{
+ switch (options.opt_list) {
+ case pcmk__opt_fencing:
+ exit_code = pcmk_rc2exitc(pcmk__list_fencing_params(out,
+ options.all));
+ break;
+ case pcmk__opt_primitive:
+ exit_code = pcmk_rc2exitc(pcmk__list_primitive_meta(out,
+ options.all));
+ break;
+ default:
+ exit_code = CRM_EX_SOFTWARE;
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
+ "BUG: Invalid option list type");
+ break;
+ }
+}
+
static int
refresh(pcmk__output_t *out)
{
@@ -1187,10 +1067,10 @@ refresh(pcmk__output_t *out)
int attr_options = pcmk__node_attr_none;
if (options.host_uname) {
- pcmk_node_t *node = pe_find_node(scheduler->nodes, options.host_uname);
+ pcmk_node_t *node = pcmk_find_node(scheduler, options.host_uname);
- if (pe__is_guest_or_remote_node(node)) {
- node = pe__current_node(node->details->remote_rsc);
+ if (pcmk__is_pacemaker_remote_node(node)) {
+ node = pcmk__current_node(node->details->remote_rsc);
if (node == NULL) {
rc = ENXIO;
g_set_error(&error, PCMK__RC_ERROR, rc,
@@ -1268,12 +1148,12 @@ set_property(void)
CRM_LOG_ASSERT(options.prop_name != NULL);
- msg_data = create_xml_node(NULL, options.rsc_type);
- crm_xml_add(msg_data, XML_ATTR_ID, options.rsc_id);
+ msg_data = pcmk__xe_create(NULL, options.rsc_type);
+ crm_xml_add(msg_data, PCMK_XA_ID, options.rsc_id);
crm_xml_add(msg_data, options.prop_name, options.prop_value);
- rc = cib_conn->cmds->modify(cib_conn, XML_CIB_TAG_RESOURCES, msg_data,
- options.cib_options);
+ rc = cib_conn->cmds->modify(cib_conn, PCMK_XE_RESOURCES, msg_data,
+ cib_sync_call);
rc = pcmk_legacy2rc(rc);
free_xml(msg_data);
@@ -1308,7 +1188,7 @@ show_metadata(pcmk__output_t *out, const char *agent_spec)
rc = pcmk_legacy2rc(rc);
if (metadata) {
- out->output_xml(out, "metadata", metadata);
+ out->output_xml(out, PCMK_XE_METADATA, metadata);
free(metadata);
} else {
/* We were given a validly formatted spec, but it doesn't necessarily
@@ -1366,16 +1246,209 @@ validate_cmdline_config(void)
options.v_agent ? options.v_agent : "");
}
- if (error != NULL) {
- return;
+ if ((error == NULL) && (options.cmdline_params == NULL)) {
+ options.cmdline_params = pcmk__strkey_table(free, free);
}
+}
- if (options.cmdline_params == NULL) {
- options.cmdline_params = pcmk__strkey_table(free, free);
+/*!
+ * \internal
+ * \brief Get the <tt>enum pe_find</tt> flags for a given command
+ *
+ * \return <tt>enum pe_find</tt> flag group appropriate for \c options.rsc_cmd.
+ */
+static uint32_t
+get_find_flags(void)
+{
+ switch (options.rsc_cmd) {
+ case cmd_ban:
+ case cmd_cleanup:
+ case cmd_clear:
+ case cmd_colocations:
+ case cmd_digests:
+ case cmd_execute_agent:
+ case cmd_locate:
+ case cmd_move:
+ case cmd_refresh:
+ case cmd_restart:
+ case cmd_why:
+ return pcmk_rsc_match_history|pcmk_rsc_match_anon_basename;
+
+ // @COMPAT See note in is_scheduler_required()
+ case cmd_delete:
+ case cmd_delete_param:
+ case cmd_get_param:
+ case cmd_get_property:
+ case cmd_query_xml_raw:
+ case cmd_query_xml:
+ case cmd_set_param:
+ case cmd_set_property:
+ return pcmk_rsc_match_history|pcmk_rsc_match_basename;
+
+ default:
+ return 0;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Check whether a node argument is required
+ *
+ * \return \c true if a \c --node argument is required, or \c false otherwise
+ */
+static bool
+is_node_required(void)
+{
+ switch (options.rsc_cmd) {
+ case cmd_digests:
+ case cmd_fail:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Check whether a resource argument is required
+ *
+ * \return \c true if a \c --resource argument is required, or \c false
+ * otherwise
+ */
+static bool
+is_resource_required(void)
+{
+ if (options.cmdline_config) {
+ return false;
+ }
+
+ switch (options.rsc_cmd) {
+ case cmd_clear:
+ return !options.clear_expired;
+
+ case cmd_cleanup:
+ case cmd_cts:
+ case cmd_list_active_ops:
+ case cmd_list_agents:
+ case cmd_list_all_ops:
+ case cmd_list_alternatives:
+ case cmd_list_instances:
+ case cmd_list_options:
+ case cmd_list_providers:
+ case cmd_list_resources:
+ case cmd_list_standards:
+ case cmd_metadata:
+ case cmd_refresh:
+ case cmd_wait:
+ case cmd_why:
+ return false;
+
+ default:
+ return true;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Check whether a CIB connection is required
+ *
+ * \return \c true if a CIB connection is required, or \c false otherwise
+ */
+static bool
+is_cib_required(void)
+{
+ if (options.cmdline_config) {
+ return false;
+ }
+
+ switch (options.rsc_cmd) {
+ case cmd_list_agents:
+ case cmd_list_alternatives:
+ case cmd_list_options:
+ case cmd_list_providers:
+ case cmd_list_standards:
+ case cmd_metadata:
+ return false;
+ default:
+ return true;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Check whether a controller IPC connection is required
+ *
+ * \return \c true if a controller connection is required, or \c false otherwise
+ */
+static bool
+is_controller_required(void)
+{
+ switch (options.rsc_cmd) {
+ case cmd_cleanup:
+ case cmd_refresh:
+ return getenv("CIB_file") == NULL;
+
+ case cmd_fail:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Check whether a scheduler IPC connection is required
+ *
+ * \return \c true if a scheduler connection is required, or \c false otherwise
+ */
+static bool
+is_scheduler_required(void)
+{
+ if (options.cmdline_config) {
+ return false;
+ }
+
+ /* @COMPAT cmd_delete does not actually need the scheduler and should not
+ * set find_flags. However, crm_resource --delete currently throws a
+ * "resource not found" error if the resource doesn't exist. This is
+ * incorrect behavior (deleting a nonexistent resource should be considered
+ * success); however, we shouldn't change it until 3.0.0.
+ */
+ switch (options.rsc_cmd) {
+ case cmd_list_agents:
+ case cmd_list_alternatives:
+ case cmd_list_options:
+ case cmd_list_providers:
+ case cmd_list_standards:
+ case cmd_metadata:
+ case cmd_wait:
+ return false;
+ default:
+ return true;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Check whether the chosen command accepts clone instances
+ *
+ * \return \c true if \p options.rsc_cmd accepts or ignores clone instances, or
+ * \c false otherwise
+ */
+static bool
+accept_clone_instance(void)
+{
+ // @COMPAT At 3.0.0, add cmd_delete; for now, don't throw error
+ switch (options.rsc_cmd) {
+ case cmd_ban:
+ case cmd_clear:
+ case cmd_move:
+ case cmd_restart:
+ return false;
+ default:
+ return true;
}
- options.require_resource = FALSE;
- options.require_scheduler = FALSE;
- options.require_cib = FALSE;
}
static GOptionContext *
@@ -1407,14 +1480,14 @@ build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
"location:\n\n"
"\t# crm_resource --resource myResource --clear\n\n"
"Stop 'myResource' (and anything that depends on it):\n\n"
- "\t# crm_resource --resource myResource --set-parameter target-role "
- "--meta --parameter-value Stopped\n\n"
+ "\t# crm_resource --resource myResource --set-parameter "
+ PCMK_META_TARGET_ROLE "--meta --parameter-value Stopped\n\n"
"Tell the cluster not to manage 'myResource' (the cluster will not "
"attempt to start or stop the\n"
"resource under any circumstances; useful when performing maintenance "
"tasks on a resource):\n\n"
- "\t# crm_resource --resource myResource --set-parameter is-managed "
- "--meta --parameter-value false\n\n"
+ "\t# crm_resource --resource myResource --set-parameter "
+ PCMK_META_IS_MANAGED "--meta --parameter-value false\n\n"
"Erase the operation history of 'myResource' on 'aNode' (the cluster "
"will 'forget' the existing\n"
"resource state, including any errors, and attempt to recover the"
@@ -1449,6 +1522,7 @@ main(int argc, char **argv)
xmlNode *cib_xml_copy = NULL;
pcmk_resource_t *rsc = NULL;
pcmk_node_t *node = NULL;
+ uint32_t find_flags = 0;
int rc = pcmk_rc_ok;
GOptionGroup *output_group = NULL;
@@ -1492,12 +1566,6 @@ main(int argc, char **argv)
* Validate option combinations
*/
- // If the user didn't explicitly specify a command, list resources
- if (options.rsc_cmd == cmd_none) {
- options.rsc_cmd = cmd_list_resources;
- options.require_resource = FALSE;
- }
-
// --expired without --clear/-U doesn't make sense
if (options.clear_expired && (options.rsc_cmd != cmd_clear)) {
exit_code = CRM_EX_USAGE;
@@ -1508,8 +1576,8 @@ main(int argc, char **argv)
if ((options.remainder != NULL) && (options.override_params != NULL)) {
// Commands that use positional arguments will create override_params
for (gchar **s = options.remainder; *s; s++) {
- char *name = calloc(1, strlen(*s));
- char *value = calloc(1, strlen(*s));
+ char *name = pcmk__assert_alloc(1, strlen(*s));
+ char *value = pcmk__assert_alloc(1, strlen(*s));
int rc = sscanf(*s, "%[^=]=%s", name, value);
if (rc == 2) {
@@ -1541,7 +1609,7 @@ main(int argc, char **argv)
/* Add 1 for the strv[0] string below, and add another 1 for the NULL
* at the end of the array so g_strjoinv knows when to stop.
*/
- strv = calloc(len+2, sizeof(char *));
+ strv = pcmk__assert_alloc(len+2, sizeof(char *));
strv[0] = strdup("non-option ARGV-elements:\n");
for (gchar **s = options.remainder; *s; s++) {
@@ -1566,28 +1634,30 @@ main(int argc, char **argv)
}
if (pcmk__str_eq(args->output_ty, "xml", pcmk__str_none)) {
- /* Kind of a hack to display XML lists using a real tag instead of <list>. This just
- * saves from having to write custom messages to build the lists around all these things
- */
switch (options.rsc_cmd) {
- case cmd_execute_agent:
- case cmd_list_resources:
- case cmd_query_xml:
- case cmd_query_raw_xml:
- case cmd_list_active_ops:
- case cmd_list_all_ops:
- case cmd_colocations:
- pcmk__force_args(context, &error, "%s --xml-simple-list --xml-substitute", g_get_prgname());
+ /* These are the only commands that have historically used the <list>
+ * elements in their XML schema. For all others, use the simple list
+ * argument.
+ */
+ case cmd_get_param:
+ case cmd_get_property:
+ case cmd_list_instances:
+ case cmd_list_standards:
+ pcmk__output_enable_list_element(out);
break;
default:
- pcmk__force_args(context, &error, "%s --xml-substitute", g_get_prgname());
break;
}
+
} else if (pcmk__str_eq(args->output_ty, "text", pcmk__str_null_matches)) {
- if ((options.rsc_cmd == cmd_colocations) ||
- options.rsc_cmd == cmd_list_resources) {
- pcmk__force_args(context, &error, "%s --text-fancy", g_get_prgname());
+ switch (options.rsc_cmd) {
+ case cmd_colocations:
+ case cmd_list_resources:
+ pcmk__output_text_set_fancy(out, true);
+ break;
+ default:
+ break;
}
}
@@ -1612,13 +1682,13 @@ main(int argc, char **argv)
options.cmdline_params = NULL;
}
- if (options.require_resource && (options.rsc_id == NULL)) {
+ if (is_resource_required() && (options.rsc_id == NULL)) {
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)) {
+ if (is_node_required() && (options.host_uname == NULL)) {
exit_code = CRM_EX_USAGE;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
_("Must supply a node name with -N"));
@@ -1629,12 +1699,8 @@ main(int argc, char **argv)
* Set up necessary connections
*/
- if (options.find_flags && options.rsc_id) {
- options.require_scheduler = TRUE;
- }
-
// Establish a connection to the CIB if needed
- if (options.require_cib) {
+ if (is_cib_required()) {
cib_conn = cib_new();
if ((cib_conn == NULL) || (cib_conn->cmds == NULL)) {
exit_code = CRM_EX_DISCONNECT;
@@ -1653,7 +1719,7 @@ main(int argc, char **argv)
}
// Populate scheduler data from XML file if specified or CIB query otherwise
- if (options.require_scheduler) {
+ if (is_scheduler_required()) {
rc = initialize_scheduler_data(&cib_xml_copy);
if (rc != pcmk_rc_ok) {
exit_code = pcmk_rc2exitc(rc);
@@ -1661,10 +1727,12 @@ main(int argc, char **argv)
}
}
+ find_flags = get_find_flags();
+
// If command requires that resource exist if specified, find it
- if (options.find_flags && options.rsc_id) {
+ if ((find_flags != 0) && (options.rsc_id != NULL)) {
rsc = pe_find_resource_with_flags(scheduler->resources, options.rsc_id,
- options.find_flags);
+ find_flags);
if (rsc == NULL) {
exit_code = CRM_EX_NOSUCH;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
@@ -1675,9 +1743,9 @@ main(int argc, char **argv)
/* The --ban, --clear, --move, and --restart commands do not work with
* instances of clone resourcs.
*/
- if (strchr(options.rsc_id, ':') != NULL && pe_rsc_is_clone(rsc->parent) &&
- (options.rsc_cmd == cmd_ban || options.rsc_cmd == cmd_clear ||
- options.rsc_cmd == cmd_move || options.rsc_cmd == cmd_restart)) {
+ if (pcmk__is_clone(rsc->parent) && (strchr(options.rsc_id, ':') != NULL)
+ && !accept_clone_instance()) {
+
exit_code = CRM_EX_INVALID_PARAM;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
_("Cannot operate on clone resource instance '%s'"), options.rsc_id);
@@ -1687,7 +1755,7 @@ main(int argc, char **argv)
// If user supplied a node name, check whether it exists
if ((options.host_uname != NULL) && (scheduler != NULL)) {
- node = pe_find_node(scheduler->nodes, options.host_uname);
+ node = pcmk_find_node(scheduler, options.host_uname);
if (node == NULL) {
exit_code = CRM_EX_NOSUCH;
@@ -1698,7 +1766,7 @@ main(int argc, char **argv)
}
// Establish a connection to the controller if needed
- if (options.require_crmd) {
+ if (is_controller_required()) {
rc = pcmk_new_ipc_api(&controld_api, pcmk_ipc_controld);
if (rc != pcmk_rc_ok) {
exit_code = pcmk_rc2exitc(rc);
@@ -1725,10 +1793,11 @@ main(int argc, char **argv)
switch (options.rsc_cmd) {
case cmd_list_resources: {
GList *all = NULL;
+ uint32_t show_opts = pcmk_show_inactive_rscs | pcmk_show_rsc_only | pcmk_show_pending;
+
all = g_list_prepend(all, (gpointer) "*");
rc = out->message(out, "resource-list", scheduler,
- pcmk_show_inactive_rscs | pcmk_show_rsc_only | pcmk_show_pending,
- true, all, all, false);
+ show_opts, true, all, all, false);
g_list_free(all);
if (rc == pcmk_rc_no_output) {
@@ -1746,6 +1815,10 @@ main(int argc, char **argv)
break;
+ case cmd_list_options:
+ list_options();
+ break;
+
case cmd_list_alternatives:
rc = pcmk__list_alternatives(out, options.agent_spec);
break;
@@ -1774,7 +1847,7 @@ main(int argc, char **argv)
*/
rc = cli_resource_restart(out, rsc, node, options.move_lifetime,
options.timeout_ms, cib_conn,
- options.cib_options, options.promoted_role_only,
+ cib_sync_call, options.promoted_role_only,
options.force);
break;
@@ -1798,7 +1871,7 @@ main(int argc, char **argv)
goto done;
case cmd_digests:
- node = pe_find_node(scheduler->nodes, options.host_uname);
+ node = pcmk_find_node(scheduler, options.host_uname);
if (node == NULL) {
rc = pcmk_rc_node_unknown;
} else {
@@ -1850,7 +1923,7 @@ main(int argc, char **argv)
rc = cli_resource_print(rsc, scheduler, true);
break;
- case cmd_query_raw_xml:
+ case cmd_query_xml_raw:
rc = cli_resource_print(rsc, scheduler, false);
break;
@@ -1873,7 +1946,7 @@ main(int argc, char **argv)
} else {
rc = cli_resource_move(rsc, options.rsc_id, options.host_uname,
options.move_lifetime, cib_conn,
- options.cib_options, scheduler,
+ cib_sync_call, scheduler,
options.promoted_role_only,
options.force);
}
@@ -1893,9 +1966,8 @@ main(int argc, char **argv)
} else {
rc = cli_resource_ban(out, options.rsc_id, node->details->uname,
options.move_lifetime, cib_conn,
- options.cib_options,
- options.promoted_role_only,
- PCMK__ROLE_PROMOTED);
+ cib_sync_call, options.promoted_role_only,
+ PCMK_ROLE_PROMOTED);
}
if (rc == EINVAL) {
@@ -1933,15 +2005,17 @@ main(int argc, char **argv)
crm_debug("Looking up %s in %s", options.prop_name, rsc->id);
- if (pcmk__str_eq(options.attr_set_type, XML_TAG_ATTR_SETS, pcmk__str_none)) {
+ if (pcmk__str_eq(options.attr_set_type, PCMK_XE_INSTANCE_ATTRIBUTES,
+ pcmk__str_none)) {
params = pe_rsc_params(rsc, current, scheduler);
free_params = false;
value = g_hash_table_lookup(params, options.prop_name);
- } else if (pcmk__str_eq(options.attr_set_type, XML_TAG_META_SETS, pcmk__str_none)) {
+ } else if (pcmk__str_eq(options.attr_set_type,
+ PCMK_XE_META_ATTRIBUTES, pcmk__str_none)) {
params = pcmk__strkey_table(free, free);
- get_meta_attributes(params, rsc, current, scheduler);
+ get_meta_attributes(params, rsc, NULL, scheduler);
value = g_hash_table_lookup(params, options.prop_name);
@@ -1951,9 +2025,14 @@ main(int argc, char **argv)
free_params = false;
} else {
+ pe_rule_eval_data_t rule_data = {
+ .now = scheduler->now,
+ };
+
params = pcmk__strkey_table(free, free);
- pe__unpack_dataset_nvpairs(rsc->xml, XML_TAG_UTILIZATION, NULL, params,
- NULL, FALSE, scheduler);
+ pe__unpack_dataset_nvpairs(rsc->xml, PCMK_XE_UTILIZATION,
+ &rule_data, params, NULL, FALSE,
+ scheduler);
value = g_hash_table_lookup(params, options.prop_name);
}
@@ -1982,7 +2061,6 @@ main(int argc, char **argv)
options.prop_name,
options.prop_value,
options.recursive, cib_conn,
- options.cib_options,
options.force);
break;
@@ -1993,8 +2071,7 @@ main(int argc, char **argv)
options.attr_set_type,
options.prop_id,
options.prop_name, cib_conn,
- options.cib_options,
- options.force);
+ cib_sync_call, options.force);
break;
case cmd_cleanup:
@@ -2019,7 +2096,25 @@ main(int argc, char **argv)
break;
case cmd_delete:
- rc = delete();
+ /* rsc_id was already checked for NULL much earlier when validating
+ * command line arguments.
+ */
+ if (options.rsc_type == NULL) {
+ // @COMPAT @TODO change this to exit_code = CRM_EX_USAGE
+ rc = ENXIO;
+ g_set_error(&error, PCMK__RC_ERROR, rc,
+ _("You need to specify a resource type with -t"));
+ } else {
+ rc = pcmk__resource_delete(cib_conn, cib_sync_call,
+ options.rsc_id, options.rsc_type);
+
+ if (rc != pcmk_rc_ok) {
+ g_set_error(&error, PCMK__RC_ERROR, rc,
+ _("Could not delete resource %s: %s"),
+ options.rsc_id, pcmk_rc_str(rc));
+ }
+ }
+
break;
default: