diff options
Diffstat (limited to '')
-rw-r--r-- | lib/pengine/common.c | 339 |
1 files changed, 201 insertions, 138 deletions
diff --git a/lib/pengine/common.c b/lib/pengine/common.c index 6c69bfc..0fdd5a1 100644 --- a/lib/pengine/common.c +++ b/lib/pengine/common.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -15,6 +15,7 @@ #include <glib.h> +#include <crm/common/scheduler_internal.h> #include <crm/pengine/internal.h> gboolean was_processing_error = FALSE; @@ -104,7 +105,7 @@ static pcmk__cluster_option_t pe_opts[] = { }, { "stonith-action", NULL, "select", "reboot, off, poweroff", - "reboot", pcmk__is_fencing_action, + PCMK_ACTION_REBOOT, pcmk__is_fencing_action, N_("Action to send to fence device when a node needs to be fenced " "(\"poweroff\" is a deprecated alias for \"off\")"), NULL @@ -157,7 +158,17 @@ static pcmk__cluster_option_t pe_opts[] = { "twice, the maximum `pcmk_delay_base/max`. By default, priority " "fencing delay is disabled.") }, - + { + XML_CONFIG_ATTR_NODE_PENDING_TIMEOUT, NULL, "time", NULL, + "0", pcmk__valid_interval_spec, + N_("How long to wait for a node that has joined the cluster to join " + "the controller process group"), + N_("Fence nodes that do not join the controller process group within " + "this much time after joining the cluster, to allow the cluster " + "to continue managing resources. A value of 0 means never fence " + "pending nodes. Setting the value to 2h means fence nodes after " + "2 hours.") + }, { "cluster-delay", NULL, "time", NULL, "60s", pcmk__valid_interval_spec, @@ -311,34 +322,34 @@ fail2text(enum action_fail_response fail) const char *result = "<unknown>"; switch (fail) { - case action_fail_ignore: + case pcmk_on_fail_ignore: result = "ignore"; break; - case action_fail_demote: + case pcmk_on_fail_demote: result = "demote"; break; - case action_fail_block: + case pcmk_on_fail_block: result = "block"; break; - case action_fail_recover: + case pcmk_on_fail_restart: result = "recover"; break; - case action_fail_migrate: + case pcmk_on_fail_ban: result = "migrate"; break; - case action_fail_stop: + case pcmk_on_fail_stop: result = "stop"; break; - case action_fail_fence: + case pcmk_on_fail_fence_node: result = "fence"; break; - case action_fail_standby: + case pcmk_on_fail_standby_node: result = "standby"; break; - case action_fail_restart_container: + case pcmk_on_fail_restart_container: result = "restart-container"; break; - case action_fail_reset_remote: + case pcmk_on_fail_reset_remote: result = "reset-remote"; break; } @@ -348,49 +359,46 @@ fail2text(enum action_fail_response fail) enum action_tasks text2task(const char *task) { - if (pcmk__str_eq(task, CRMD_ACTION_STOP, pcmk__str_casei)) { - return stop_rsc; - } else if (pcmk__str_eq(task, CRMD_ACTION_STOPPED, pcmk__str_casei)) { - return stopped_rsc; - } else if (pcmk__str_eq(task, CRMD_ACTION_START, pcmk__str_casei)) { - return start_rsc; - } else if (pcmk__str_eq(task, CRMD_ACTION_STARTED, pcmk__str_casei)) { - return started_rsc; - } else if (pcmk__str_eq(task, CRM_OP_SHUTDOWN, pcmk__str_casei)) { - return shutdown_crm; - } else if (pcmk__str_eq(task, CRM_OP_FENCE, pcmk__str_casei)) { - return stonith_node; - } else if (pcmk__str_eq(task, CRMD_ACTION_STATUS, pcmk__str_casei)) { - return monitor_rsc; - } else if (pcmk__str_eq(task, CRMD_ACTION_NOTIFY, pcmk__str_casei)) { - return action_notify; - } else if (pcmk__str_eq(task, CRMD_ACTION_NOTIFIED, pcmk__str_casei)) { - return action_notified; - } else if (pcmk__str_eq(task, CRMD_ACTION_PROMOTE, pcmk__str_casei)) { - return action_promote; - } else if (pcmk__str_eq(task, CRMD_ACTION_DEMOTE, pcmk__str_casei)) { - return action_demote; - } else if (pcmk__str_eq(task, CRMD_ACTION_PROMOTED, pcmk__str_casei)) { - return action_promoted; - } else if (pcmk__str_eq(task, CRMD_ACTION_DEMOTED, pcmk__str_casei)) { - return action_demoted; - } -#if SUPPORT_TRACING - if (pcmk__str_eq(task, CRMD_ACTION_CANCEL, pcmk__str_casei)) { - return no_action; - } else if (pcmk__str_eq(task, CRMD_ACTION_DELETE, pcmk__str_casei)) { - return no_action; - } else if (pcmk__str_eq(task, CRMD_ACTION_STATUS, pcmk__str_casei)) { - return no_action; - } else if (pcmk__str_eq(task, CRMD_ACTION_MIGRATE, pcmk__str_casei)) { - return no_action; - } else if (pcmk__str_eq(task, CRMD_ACTION_MIGRATED, pcmk__str_casei)) { - return no_action; - } - crm_trace("Unsupported action: %s", task); -#endif + if (pcmk__str_eq(task, PCMK_ACTION_STOP, pcmk__str_casei)) { + return pcmk_action_stop; + + } else if (pcmk__str_eq(task, PCMK_ACTION_STOPPED, pcmk__str_casei)) { + return pcmk_action_stopped; + + } else if (pcmk__str_eq(task, PCMK_ACTION_START, pcmk__str_casei)) { + return pcmk_action_start; + + } else if (pcmk__str_eq(task, PCMK_ACTION_RUNNING, pcmk__str_casei)) { + return pcmk_action_started; + + } else if (pcmk__str_eq(task, PCMK_ACTION_DO_SHUTDOWN, pcmk__str_casei)) { + return pcmk_action_shutdown; - return no_action; + } else if (pcmk__str_eq(task, PCMK_ACTION_STONITH, pcmk__str_casei)) { + return pcmk_action_fence; + + } else if (pcmk__str_eq(task, PCMK_ACTION_MONITOR, pcmk__str_casei)) { + return pcmk_action_monitor; + + } else if (pcmk__str_eq(task, PCMK_ACTION_NOTIFY, pcmk__str_casei)) { + return pcmk_action_notify; + + } else if (pcmk__str_eq(task, PCMK_ACTION_NOTIFIED, pcmk__str_casei)) { + return pcmk_action_notified; + + } else if (pcmk__str_eq(task, PCMK_ACTION_PROMOTE, pcmk__str_casei)) { + return pcmk_action_promote; + + } else if (pcmk__str_eq(task, PCMK_ACTION_DEMOTE, pcmk__str_casei)) { + return pcmk_action_demote; + + } else if (pcmk__str_eq(task, PCMK_ACTION_PROMOTED, pcmk__str_casei)) { + return pcmk_action_promoted; + + } else if (pcmk__str_eq(task, PCMK_ACTION_DEMOTED, pcmk__str_casei)) { + return pcmk_action_demoted; + } + return pcmk_action_unspecified; } const char * @@ -399,47 +407,47 @@ task2text(enum action_tasks task) const char *result = "<unknown>"; switch (task) { - case no_action: + case pcmk_action_unspecified: result = "no_action"; break; - case stop_rsc: - result = CRMD_ACTION_STOP; + case pcmk_action_stop: + result = PCMK_ACTION_STOP; break; - case stopped_rsc: - result = CRMD_ACTION_STOPPED; + case pcmk_action_stopped: + result = PCMK_ACTION_STOPPED; break; - case start_rsc: - result = CRMD_ACTION_START; + case pcmk_action_start: + result = PCMK_ACTION_START; break; - case started_rsc: - result = CRMD_ACTION_STARTED; + case pcmk_action_started: + result = PCMK_ACTION_RUNNING; break; - case shutdown_crm: - result = CRM_OP_SHUTDOWN; + case pcmk_action_shutdown: + result = PCMK_ACTION_DO_SHUTDOWN; break; - case stonith_node: - result = CRM_OP_FENCE; + case pcmk_action_fence: + result = PCMK_ACTION_STONITH; break; - case monitor_rsc: - result = CRMD_ACTION_STATUS; + case pcmk_action_monitor: + result = PCMK_ACTION_MONITOR; break; - case action_notify: - result = CRMD_ACTION_NOTIFY; + case pcmk_action_notify: + result = PCMK_ACTION_NOTIFY; break; - case action_notified: - result = CRMD_ACTION_NOTIFIED; + case pcmk_action_notified: + result = PCMK_ACTION_NOTIFIED; break; - case action_promote: - result = CRMD_ACTION_PROMOTE; + case pcmk_action_promote: + result = PCMK_ACTION_PROMOTE; break; - case action_promoted: - result = CRMD_ACTION_PROMOTED; + case pcmk_action_promoted: + result = PCMK_ACTION_PROMOTED; break; - case action_demote: - result = CRMD_ACTION_DEMOTE; + case pcmk_action_demote: + result = PCMK_ACTION_DEMOTE; break; - case action_demoted: - result = CRMD_ACTION_DEMOTED; + case pcmk_action_demoted: + result = PCMK_ACTION_DEMOTED; break; } @@ -450,50 +458,50 @@ const char * role2text(enum rsc_role_e role) { switch (role) { - case RSC_ROLE_UNKNOWN: - return RSC_ROLE_UNKNOWN_S; - case RSC_ROLE_STOPPED: - return RSC_ROLE_STOPPED_S; - case RSC_ROLE_STARTED: - return RSC_ROLE_STARTED_S; - case RSC_ROLE_UNPROMOTED: + case pcmk_role_stopped: + return PCMK__ROLE_STOPPED; + + case pcmk_role_started: + return PCMK__ROLE_STARTED; + + case pcmk_role_unpromoted: #ifdef PCMK__COMPAT_2_0 - return RSC_ROLE_UNPROMOTED_LEGACY_S; + return PCMK__ROLE_UNPROMOTED_LEGACY; #else - return RSC_ROLE_UNPROMOTED_S; + return PCMK__ROLE_UNPROMOTED; #endif - case RSC_ROLE_PROMOTED: + + case pcmk_role_promoted: #ifdef PCMK__COMPAT_2_0 - return RSC_ROLE_PROMOTED_LEGACY_S; + return PCMK__ROLE_PROMOTED_LEGACY; #else - return RSC_ROLE_PROMOTED_S; + return PCMK__ROLE_PROMOTED; #endif + + default: // pcmk_role_unknown + return PCMK__ROLE_UNKNOWN; } - CRM_CHECK(role >= RSC_ROLE_UNKNOWN, return RSC_ROLE_UNKNOWN_S); - CRM_CHECK(role < RSC_ROLE_MAX, return RSC_ROLE_UNKNOWN_S); - // coverity[dead_error_line] - return RSC_ROLE_UNKNOWN_S; } enum rsc_role_e text2role(const char *role) { CRM_ASSERT(role != NULL); - if (pcmk__str_eq(role, RSC_ROLE_STOPPED_S, pcmk__str_casei)) { - return RSC_ROLE_STOPPED; - } else if (pcmk__str_eq(role, RSC_ROLE_STARTED_S, pcmk__str_casei)) { - return RSC_ROLE_STARTED; - } else if (pcmk__strcase_any_of(role, RSC_ROLE_UNPROMOTED_S, - RSC_ROLE_UNPROMOTED_LEGACY_S, NULL)) { - return RSC_ROLE_UNPROMOTED; - } else if (pcmk__strcase_any_of(role, RSC_ROLE_PROMOTED_S, - RSC_ROLE_PROMOTED_LEGACY_S, NULL)) { - return RSC_ROLE_PROMOTED; - } else if (pcmk__str_eq(role, RSC_ROLE_UNKNOWN_S, pcmk__str_casei)) { - return RSC_ROLE_UNKNOWN; + if (pcmk__str_eq(role, PCMK__ROLE_STOPPED, pcmk__str_casei)) { + return pcmk_role_stopped; + } else if (pcmk__str_eq(role, PCMK__ROLE_STARTED, pcmk__str_casei)) { + return pcmk_role_started; + } else if (pcmk__strcase_any_of(role, PCMK__ROLE_UNPROMOTED, + PCMK__ROLE_UNPROMOTED_LEGACY, NULL)) { + return pcmk_role_unpromoted; + } else if (pcmk__strcase_any_of(role, PCMK__ROLE_PROMOTED, + PCMK__ROLE_PROMOTED_LEGACY, NULL)) { + return pcmk_role_promoted; + } else if (pcmk__str_eq(role, PCMK__ROLE_UNKNOWN, pcmk__str_casei)) { + return pcmk_role_unknown; } crm_err("Unknown role: %s", role); - return RSC_ROLE_UNKNOWN; + return pcmk_role_unknown; } void @@ -514,48 +522,103 @@ add_hash_param(GHashTable * hash, const char *name, const char *value) } } +/*! + * \internal + * \brief Look up an attribute value on the appropriate node + * + * If \p node is a guest node and either the \c XML_RSC_ATTR_TARGET meta + * attribute is set to "host" for \p rsc or \p force_host is \c true, query the + * attribute on the node's host. Otherwise, query the attribute on \p node + * itself. + * + * \param[in] node Node to query attribute value on by default + * \param[in] name Name of attribute to query + * \param[in] rsc Resource on whose behalf we're querying + * \param[in] node_type Type of resource location lookup + * \param[in] force_host Force a lookup on the guest node's host, regardless of + * the \c XML_RSC_ATTR_TARGET value + * + * \return Value of the attribute on \p node or on the host of \p node + * + * \note If \p force_host is \c true, \p node \e must be a guest node. + */ const char * -pe_node_attribute_calculated(const pe_node_t *node, const char *name, - const pe_resource_t *rsc) +pe__node_attribute_calculated(const pcmk_node_t *node, const char *name, + const pcmk_resource_t *rsc, + enum pcmk__rsc_node node_type, + bool force_host) { - const char *source; - - if(node == NULL) { - return NULL; + // @TODO: Use pe__is_guest_node() after merging libpe_{rules,status} + bool is_guest = (node != NULL) + && (node->details->type == pcmk_node_variant_remote) + && (node->details->remote_rsc != NULL) + && (node->details->remote_rsc->container != NULL); + const char *source = NULL; + const char *node_type_s = NULL; + const char *reason = NULL; + + const pcmk_resource_t *container = NULL; + const pcmk_node_t *host = NULL; + + CRM_ASSERT((node != NULL) && (name != NULL) && (rsc != NULL) + && (!force_host || is_guest)); + + /* Ignore XML_RSC_ATTR_TARGET if node is not a guest node. This represents a + * user configuration error. + */ + source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET); + if (!force_host + && (!is_guest || !pcmk__str_eq(source, "host", pcmk__str_casei))) { - } else if(rsc == NULL) { return g_hash_table_lookup(node->details->attrs, name); } - source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET); - if(source == NULL || !pcmk__str_eq("host", source, pcmk__str_casei)) { - return g_hash_table_lookup(node->details->attrs, name); - } + container = node->details->remote_rsc->container; - /* Use attributes set for the containers location - * instead of for the container itself - * - * Useful when the container is using the host's local - * storage - */ + switch (node_type) { + case pcmk__rsc_node_assigned: + node_type_s = "assigned"; + host = container->allocated_to; + if (host == NULL) { + reason = "not assigned"; + } + break; - CRM_ASSERT(node->details->remote_rsc); - CRM_ASSERT(node->details->remote_rsc->container); + case pcmk__rsc_node_current: + node_type_s = "current"; - if(node->details->remote_rsc->container->running_on) { - pe_node_t *host = node->details->remote_rsc->container->running_on->data; - pe_rsc_trace(rsc, "%s: Looking for %s on the container host %s", - rsc->id, name, pe__node_name(host)); - return g_hash_table_lookup(host->details->attrs, name); + if (container->running_on != NULL) { + host = container->running_on->data; + } + if (host == NULL) { + reason = "inactive"; + } + break; + + default: + // Add support for other enum pcmk__rsc_node values if needed + CRM_ASSERT(false); + break; } - pe_rsc_trace(rsc, "%s: Not looking for %s on the container host: %s is inactive", - rsc->id, name, node->details->remote_rsc->container->id); + if (host != NULL) { + const char *value = g_hash_table_lookup(host->details->attrs, name); + + pe_rsc_trace(rsc, + "%s: Value lookup for %s on %s container host %s %s%s", + rsc->id, name, node_type_s, pe__node_name(host), + ((value != NULL)? "succeeded: " : "failed"), + pcmk__s(value, "")); + return value; + } + pe_rsc_trace(rsc, + "%s: Not looking for %s on %s container host: %s is %s", + rsc->id, name, node_type_s, container->id, reason); return NULL; } const char * -pe_node_attribute_raw(const pe_node_t *node, const char *name) +pe_node_attribute_raw(const pcmk_node_t *node, const char *name) { if(node == NULL) { return NULL; |