diff --git a/include/crm/common/agents_internal.h b/include/crm/common/agents_internal.h new file mode 100644 index 0000000000..693bf87dd0 --- /dev/null +++ b/include/crm/common/agents_internal.h @@ -0,0 +1,23 @@ +/* + * Copyright 2025 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#ifndef PCMK__CRM_COMMON_AGENTS_INTERNAL__H +#define PCMK__CRM_COMMON_AGENTS_INTERNAL__H + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCMK__FENCING_STONITH_TIMEOUT "stonith-timeout" + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_AGENTS_INTERNAL__H diff --git a/include/crm_internal.h b/include/crm_internal.h index 337d309b99..0aec87fe4e 100644 --- a/include/crm_internal.h +++ b/include/crm_internal.h @@ -1,100 +1,101 @@ /* * Copyright 2006-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #ifndef PCMK__CRM_INTERNAL__H #define PCMK__CRM_INTERNAL__H #ifndef PCMK__CONFIG_H #define PCMK__CONFIG_H #include #endif #include /* Our minimum glib dependency is 2.42. Define that as both the minimum and * maximum glib APIs that are allowed (i.e. APIs that were already deprecated * in 2.42, and APIs introduced after 2.42, cannot be used by Pacemaker code). */ #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_42 #define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_42 #define G_LOG_DOMAIN "Pacemaker" #include #include #include /* Public API headers can guard including deprecated API headers with this * symbol, thus preventing internal code (which includes this header) from using * deprecated APIs, while still allowing external code to use them by default. */ #define PCMK_ALLOW_DEPRECATED 0 #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define N_(String) (String) #ifdef ENABLE_NLS #define _(String) gettext(String) #else #define _(String) (String) #endif /* * IPC service names that are only used internally */ #define PCMK__SERVER_BASED_RO "cib_ro" #define PCMK__SERVER_BASED_RW "cib_rw" #define PCMK__SERVER_BASED_SHM "cib_shm" /* * IPC commands that can be sent to Pacemaker daemons */ #define PCMK__ATTRD_CMD_PEER_REMOVE "peer-remove" #define PCMK__ATTRD_CMD_UPDATE "update" #define PCMK__ATTRD_CMD_UPDATE_BOTH "update-both" #define PCMK__ATTRD_CMD_UPDATE_DELAY "update-delay" #define PCMK__ATTRD_CMD_QUERY "query" #define PCMK__ATTRD_CMD_REFRESH "refresh" #define PCMK__ATTRD_CMD_SYNC_RESPONSE "sync-response" #define PCMK__ATTRD_CMD_CLEAR_FAILURE "clear-failure" #define PCMK__ATTRD_CMD_CONFIRM "confirm" #define PCMK__CONTROLD_CMD_NODES "list-nodes" #define ST__LEVEL_MIN 1 #define ST__LEVEL_MAX 9 #ifdef __cplusplus } #endif #endif // CRM_INTERNAL__H diff --git a/lib/common/agents.c b/lib/common/agents.c index e5caecd075..ffaa889ecc 100644 --- a/lib/common/agents.c +++ b/lib/common/agents.c @@ -1,209 +1,209 @@ /* * Copyright 2004-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include #include #include #include // g_str_has_prefix() #include #include /*! * \brief Get capabilities of a resource agent standard * * \param[in] standard Standard name * * \return Bitmask of enum pcmk_ra_caps values */ uint32_t pcmk_get_ra_caps(const char *standard) { /* @COMPAT This should probably be case-sensitive, but isn't, * for backward compatibility. */ if (standard == NULL) { return pcmk_ra_cap_none; } else if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_OCF)) { return pcmk_ra_cap_provider | pcmk_ra_cap_params | pcmk_ra_cap_unique | pcmk_ra_cap_promotable | pcmk_ra_cap_cli_exec; } else if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_STONITH)) { /* @COMPAT Stonith resources can't really be unique clones, but we've * allowed it in the past and have it in some scheduler regression tests * (which were likely never used as real configurations). * * @TODO Remove pcmk_ra_cap_unique at the next major schema version * bump, with a transform to remove PCMK_META_GLOBALLY_UNIQUE from the * config. */ return pcmk_ra_cap_params | pcmk_ra_cap_unique | pcmk_ra_cap_stdin | pcmk_ra_cap_fence_params; } else if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_LSB)) { return pcmk_ra_cap_status | pcmk_ra_cap_cli_exec; } else if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_SYSTEMD) || !strcasecmp(standard, PCMK_RESOURCE_CLASS_SERVICE)) { return pcmk_ra_cap_status; } return pcmk_ra_cap_none; } int pcmk__effective_rc(int rc) { int remapped_rc = rc; switch (rc) { case PCMK_OCF_DEGRADED: remapped_rc = PCMK_OCF_OK; break; case PCMK_OCF_DEGRADED_PROMOTED: remapped_rc = PCMK_OCF_RUNNING_PROMOTED; break; default: break; } return remapped_rc; } char * crm_generate_ra_key(const char *standard, const char *provider, const char *type) { bool std_empty = pcmk__str_empty(standard); bool prov_empty = pcmk__str_empty(provider); bool ty_empty = pcmk__str_empty(type); if (std_empty || ty_empty) { return NULL; } return crm_strdup_printf("%s%s%s:%s", standard, (prov_empty ? "" : ":"), (prov_empty ? "" : provider), type); } /*! * \brief Parse a "standard[:provider]:type" agent specification * * \param[in] spec Agent specification * \param[out] standard Newly allocated memory containing agent standard (or NULL) * \param[out] provider Newly allocated memory containing agent provider (or NULL) * \param[put] type Newly allocated memory containing agent type (or NULL) * * \return pcmk_ok if the string could be parsed, -EINVAL otherwise * * \note It is acceptable for the type to contain a ':' if the standard supports * that. For example, systemd supports the form "systemd:UNIT@A:B". * \note It is the caller's responsibility to free the returned values. */ int crm_parse_agent_spec(const char *spec, char **standard, char **provider, char **type) { char *colon; CRM_CHECK(spec && standard && provider && type, return -EINVAL); *standard = NULL; *provider = NULL; *type = NULL; colon = strchr(spec, ':'); if ((colon == NULL) || (colon == spec)) { return -EINVAL; } *standard = strndup(spec, colon - spec); spec = colon + 1; if (pcmk_is_set(pcmk_get_ra_caps(*standard), pcmk_ra_cap_provider)) { colon = strchr(spec, ':'); if ((colon == NULL) || (colon == spec)) { free(*standard); return -EINVAL; } *provider = strndup(spec, colon - spec); spec = colon + 1; } if (*spec == '\0') { free(*standard); free(*provider); return -EINVAL; } *type = strdup(spec); return pcmk_ok; } /*! * \brief Check whether a given stonith parameter is handled by Pacemaker * * Return true if a given string is the name of one of the special resource * instance attributes interpreted directly by Pacemaker for stonith-class * resources. * * \param[in] param Parameter name to check * * \return true if \p param is a special fencing parameter */ bool pcmk_stonith_param(const char *param) { if (param == NULL) { return false; } - /* @COMPAT Pacemaker does not handle PCMK_STONITH_STONITH_TIMEOUT specially + /* @COMPAT Pacemaker does not handle PCMK__FENCING_STONITH_TIMEOUT specially * as a resource parameter, so pcmk_stonith_param() should not return true * for it. It is unclear from the commit history why we returned true for it * in the first place. * * However, when the feature set is less than 3.16.0, * calculate_secure_digest() filters out these special fencing parameters * when calculating the digest. There's no good reason why a user should * have configured this as a fence resource parameter in the first place. * * But out of an abundance of caution, we should wait to drop - * PCMK_STONITH_STONITH_TIMEOUT from this function until we no longer + * PCMK__FENCING_STONITH_TIMEOUT from this function until we no longer * support rolling upgrades from below Pacemaker 2.1.5. */ if (pcmk__str_any_of(param, PCMK_FENCING_PROVIDES, - PCMK_STONITH_STONITH_TIMEOUT, NULL)) { + PCMK__FENCING_STONITH_TIMEOUT, NULL)) { return true; } if (!g_str_has_prefix(param, "pcmk_")) { // Short-circuit common case return false; } if (pcmk__str_any_of(param, PCMK_FENCING_ACTION_LIMIT, PCMK_FENCING_DELAY_BASE, PCMK_FENCING_DELAY_MAX, PCMK_FENCING_HOST_ARGUMENT, PCMK_FENCING_HOST_CHECK, PCMK_FENCING_HOST_LIST, PCMK_FENCING_HOST_MAP, NULL)) { return true; } param = strchr(param + 5, '_'); // Skip past "pcmk_ACTION" return pcmk__str_any_of(param, "_action", "_timeout", "_retries", NULL); } diff --git a/lib/common/tests/agents/pcmk_stonith_param_test.c b/lib/common/tests/agents/pcmk_stonith_param_test.c index 32858d5eb4..c9912b0b7f 100644 --- a/lib/common/tests/agents/pcmk_stonith_param_test.c +++ b/lib/common/tests/agents/pcmk_stonith_param_test.c @@ -1,50 +1,50 @@ /* * Copyright 2020-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU General Public License version 2 * or later (GPLv2+) WITHOUT ANY WARRANTY. */ #include #include #include static void is_stonith_param(void **state) { assert_false(pcmk_stonith_param(NULL)); assert_false(pcmk_stonith_param("")); assert_false(pcmk_stonith_param("unrecognized")); assert_false(pcmk_stonith_param("pcmk_unrecognized")); assert_false(pcmk_stonith_param("x" PCMK_FENCING_ACTION_LIMIT)); assert_false(pcmk_stonith_param(PCMK_FENCING_ACTION_LIMIT "x")); assert_true(pcmk_stonith_param(PCMK_FENCING_ACTION_LIMIT)); assert_true(pcmk_stonith_param(PCMK_FENCING_DELAY_BASE)); assert_true(pcmk_stonith_param(PCMK_FENCING_DELAY_MAX)); assert_true(pcmk_stonith_param(PCMK_FENCING_HOST_ARGUMENT)); assert_true(pcmk_stonith_param(PCMK_FENCING_HOST_CHECK)); assert_true(pcmk_stonith_param(PCMK_FENCING_HOST_LIST)); assert_true(pcmk_stonith_param(PCMK_FENCING_HOST_MAP)); assert_true(pcmk_stonith_param(PCMK_FENCING_PROVIDES)); - assert_true(pcmk_stonith_param(PCMK_STONITH_STONITH_TIMEOUT)); + assert_true(pcmk_stonith_param(PCMK__FENCING_STONITH_TIMEOUT)); } static void is_stonith_action_param(void **state) { /* Currently, the function accepts any string not containing underbars as * the action name, so we do not need to verify particular action names. */ assert_false(pcmk_stonith_param("pcmk_on_unrecognized")); assert_true(pcmk_stonith_param("pcmk_on_action")); assert_true(pcmk_stonith_param("pcmk_on_timeout")); assert_true(pcmk_stonith_param("pcmk_on_retries")); } PCMK__UNIT_TEST(NULL, NULL, cmocka_unit_test(is_stonith_param), cmocka_unit_test(is_stonith_action_param))