From b921325616dbee33c3b0f8a2184e496f68c79dce Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Tue, 8 Apr 2025 02:31:37 -0700 Subject: [PATCH 01/75] Refactor: executor: Few best practices for execute_stonith_action() Signed-off-by: Reid Wahl --- daemons/execd/execd_commands.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c index e961d3d661a..0a187a4687a 100644 --- a/daemons/execd/execd_commands.c +++ b/daemons/execd/execd_commands.c @@ -1283,9 +1283,11 @@ execd_stonith_monitor(stonith_t *stonith_api, lrmd_rsc_t *rsc, lrmd_cmd_t *cmd) static void execute_stonith_action(lrmd_rsc_t *rsc, lrmd_cmd_t *cmd) { - int rc = 0; - bool do_monitor = FALSE; + int rc = pcmk_ok; + const char *rc_s = NULL; + bool do_monitor = false; + // Don't free; belongs to pacemaker-execd.c stonith_t *stonith_api = get_stonith_connection(); if (pcmk__str_eq(cmd->action, PCMK_ACTION_MONITOR, pcmk__str_casei) @@ -1295,17 +1297,19 @@ execute_stonith_action(lrmd_rsc_t *rsc, lrmd_cmd_t *cmd) rsc->fence_probe_result.execution_status, rsc->fence_probe_result.exit_reason); return; + } - } else if (stonith_api == NULL) { + if (stonith_api == NULL) { stonith_action_complete(cmd, PCMK_OCF_UNKNOWN_ERROR, PCMK_EXEC_NOT_CONNECTED, "No connection to fencer"); return; + } - } else if (pcmk__str_eq(cmd->action, PCMK_ACTION_START, pcmk__str_casei)) { + if (pcmk__str_eq(cmd->action, PCMK_ACTION_START, pcmk__str_casei)) { rc = execd_stonith_start(stonith_api, rsc, cmd); if (rc == pcmk_ok) { - do_monitor = TRUE; + do_monitor = true; } } else if (pcmk__str_eq(cmd->action, PCMK_ACTION_STOP, pcmk__str_casei)) { @@ -1313,7 +1317,7 @@ execute_stonith_action(lrmd_rsc_t *rsc, lrmd_cmd_t *cmd) } else if (pcmk__str_eq(cmd->action, PCMK_ACTION_MONITOR, pcmk__str_casei)) { - do_monitor = TRUE; + do_monitor = true; } else { stonith_action_complete(cmd, PCMK_OCF_UNIMPLEMENT_FEATURE, @@ -1325,15 +1329,17 @@ execute_stonith_action(lrmd_rsc_t *rsc, lrmd_cmd_t *cmd) if (do_monitor) { rc = execd_stonith_monitor(stonith_api, rsc, cmd); if (rc == pcmk_ok) { - // Don't clean up yet, we will find out result of the monitor later + // Don't clean up yet. We will get the result of the monitor later. return; } } + if (rc != -pcmk_err_generic) { + rc_s = pcmk_strerror(rc); + } stonith_action_complete(cmd, - ((rc == pcmk_ok)? CRM_EX_OK : CRM_EX_ERROR), - stonith__legacy2status(rc), - ((rc == -pcmk_err_generic)? NULL : pcmk_strerror(rc))); + ((rc == pcmk_rc_ok)? CRM_EX_OK : CRM_EX_ERROR), + stonith__legacy2status(rc), rc_s); } static void From f6750398c16190f5cbb6b6e5ea79e9b3b3d92a77 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Tue, 8 Apr 2025 22:51:25 -0700 Subject: [PATCH 02/75] Refactor: libstonithd: Replace stonith__device_parameter_flags() ...with stonith__param_is_supported(). The parameter flags are the only stonith device flags used outside of the fencer. This will allow us to move the flag enum into the fencer. Two lines in the fencer become longer than 80 characters because the flag names are so long, but this is temporary. Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 26 ++++++++++++--- include/crm/fencing/internal.h | 4 +-- lib/fencing/st_client.c | 56 +++++++++++++------------------- lib/fencing/st_rhcs.c | 15 ++++----- 4 files changed, 52 insertions(+), 49 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index b31c52bf947..7290b9df770 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -500,8 +500,17 @@ get_agent_metadata_cb(gpointer data) { case pcmk_rc_ok: if (device->agent_metadata) { read_action_metadata(device); - stonith__device_parameter_flags(&(device->flags), device->id, - device->agent_metadata); + + if (stonith__param_is_supported(device->agent_metadata, + "plug")) { + stonith__set_device_flags(device->flags, device->id, + st_device_supports_parameter_plug); + } + if (stonith__param_is_supported(device->agent_metadata, + "port")) { + stonith__set_device_flags(device->flags, device->id, + st_device_supports_parameter_port); + } } return G_SOURCE_REMOVE; @@ -1075,8 +1084,17 @@ build_device_from_xml(const xmlNode *dev) case pcmk_rc_ok: if (device->agent_metadata) { read_action_metadata(device); - stonith__device_parameter_flags(&(device->flags), device->id, - device->agent_metadata); + + if (stonith__param_is_supported(device->agent_metadata, + "plug")) { + stonith__set_device_flags(device->flags, device->id, + st_device_supports_parameter_plug); + } + if (stonith__param_is_supported(device->agent_metadata, + "port")) { + stonith__set_device_flags(device->flags, device->id, + st_device_supports_parameter_port); + } } break; diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 46159936457..1cf1937fef1 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -100,9 +100,7 @@ const char *stonith__later_succeeded(const stonith_history_t *event, const stonith_history_t *top_history); stonith_history_t *stonith__sort_history(stonith_history_t *history); -void stonith__device_parameter_flags(uint32_t *device_flags, - const char *device_name, - xmlNode *metadata); +bool stonith__param_is_supported(xmlNode *metadata, const char *name); /* Only 1-9 is allowed for fencing topology levels, * however, 0 is used to unregister all levels in diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 52d348d27d2..50c2b1ddb96 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -2429,46 +2429,34 @@ stonith__event_state_neq(stonith_history_t *history, void *user_data) return history->state != GPOINTER_TO_INT(user_data); } -void -stonith__device_parameter_flags(uint32_t *device_flags, const char *device_name, - xmlNode *metadata) +/*! + * \internal + * \brief Check whether a given parameter exists in a fence agent's metadata + * + * \param[in] metadata Agent metadata + * \param[in] name Parameter name + * + * \retval \c true If \p name exists as a parameter in \p metadata + * \retval \c false Otherwise + */ +bool +stonith__param_is_supported(xmlNode *metadata, const char *name) { + char *xpath_s = NULL; xmlXPathObject *xpath = NULL; - int max = 0; - int lpc = 0; - - CRM_CHECK((device_flags != NULL) && (metadata != NULL), return); - - xpath = pcmk__xpath_search(metadata->doc, "//" PCMK_XE_PARAMETER); - max = pcmk__xpath_num_results(xpath); + bool supported = false; - if (max == 0) { - xmlXPathFreeObject(xpath); - return; - } - - for (lpc = 0; lpc < max; lpc++) { - const char *parameter = NULL; - xmlNode *match = pcmk__xpath_result(xpath, lpc); - - CRM_LOG_ASSERT(match != NULL); - if (match == NULL) { - continue; - } + CRM_CHECK(metadata != NULL, return false); - parameter = crm_element_value(match, PCMK_XA_NAME); - - if (pcmk__str_eq(parameter, "plug", pcmk__str_casei)) { - stonith__set_device_flags(*device_flags, device_name, - st_device_supports_parameter_plug); - - } else if (pcmk__str_eq(parameter, "port", pcmk__str_casei)) { - stonith__set_device_flags(*device_flags, device_name, - st_device_supports_parameter_port); - } - } + xpath_s = crm_strdup_printf("//" PCMK_XE_PARAMETER + "[@" PCMK_XA_NAME "='%s']", + name); + xpath = pcmk__xpath_search(metadata->doc, xpath_s); + supported = (pcmk__xpath_num_results(xpath) > 0); + free(xpath_s); xmlXPathFreeObject(xpath); + return supported; } /*! diff --git a/lib/fencing/st_rhcs.c b/lib/fencing/st_rhcs.c index d091ea1153a..64cc3cd1772 100644 --- a/lib/fencing/st_rhcs.c +++ b/lib/fencing/st_rhcs.c @@ -282,16 +282,15 @@ stonith__rhcs_validate(stonith_t *st, int call_options, const char *target, rc = stonith__rhcs_get_metadata(agent, remaining_timeout, &metadata); if (rc == pcmk_ok) { - uint32_t device_flags = 0; - - stonith__device_parameter_flags(&device_flags, agent, metadata); - if (pcmk_is_set(device_flags, st_device_supports_parameter_port)) { - host_arg = "port"; - - } else if (pcmk_is_set(device_flags, - st_device_supports_parameter_plug)) { + if (stonith__param_is_supported(metadata, "plug")) { host_arg = "plug"; + } else if (stonith__param_is_supported(metadata, "port")) { + host_arg = "port"; } + + crm_trace("Using '%s' as default " PCMK_STONITH_HOST_ARGUMENT + " for %s", + pcmk__s(host_arg, PCMK_VALUE_NONE), agent); } pcmk__xml_free(metadata); From 3a3e1581822e23961beee38b11ed104030e7001e Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 02:18:22 -0700 Subject: [PATCH 03/75] Refactor: libstonithd: Rename host_arg to default_host_arg... ...in stonith__action_create(). make_args() uses an explicit PCMK_STONITH_HOST_ARGUMENT if configured. Signed-off-by: Reid Wahl --- lib/fencing/st_actions.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/fencing/st_actions.c b/lib/fencing/st_actions.c index 5da7acf026d..ad7a17ea26d 100644 --- a/lib/fencing/st_actions.c +++ b/lib/fencing/st_actions.c @@ -110,18 +110,19 @@ append_config_arg(gpointer key, gpointer value, gpointer user_data) * \internal * \brief Create a table of arguments for a fencing action * - * \param[in] agent Fencing agent name - * \param[in] action Name of fencing action - * \param[in] target Name of target node for fencing action - * \param[in] device_args Fence device parameters - * \param[in] port_map Target node-to-port mapping for fence device - * \param[in] host_arg Argument name for passing target + * \param[in] agent Fencing agent name + * \param[in] action Name of fencing action + * \param[in] target Name of target node for fencing action + * \param[in] device_args Fence device parameters + * \param[in] port_map Target node-to-port mapping for fence device + * \param[in] default_host_arg Default agent parameter for passing target * * \return Newly created hash table of arguments for fencing action */ static GHashTable * make_args(const char *agent, const char *action, const char *target, - GHashTable *device_args, GHashTable *port_map, const char *host_arg) + GHashTable *device_args, GHashTable *port_map, + const char *default_host_arg) { GHashTable *arg_list = NULL; const char *value = NULL; @@ -161,7 +162,7 @@ make_args(const char *agent, const char *action, const char *target, param = g_hash_table_lookup(device_args, PCMK_STONITH_HOST_ARGUMENT); if (param == NULL) { // Use caller's default (likely from agent metadata) - param = host_arg; + param = default_host_arg; } if ((param != NULL) && !pcmk__str_eq(agent, "fence_legacy", pcmk__str_none) @@ -238,13 +239,13 @@ stonith__action_result(stonith_action_t *action) * \internal * \brief Create a new fencing action to be executed * - * \param[in] agent Fence agent to use - * \param[in] action_name Fencing action to be executed - * \param[in] target Name of target of fencing action (if known) - * \param[in] timeout_sec Timeout to be used when executing action - * \param[in] device_args Parameters to pass to fence agent - * \param[in] port_map Mapping of target names to device ports - * \param[in] host_arg Agent parameter used to pass target name + * \param[in] agent Fence agent to use + * \param[in] action_name Fencing action to be executed + * \param[in] target Name of target of fencing action (if known) + * \param[in] timeout_sec Timeout to be used when executing action + * \param[in] device_args Parameters to pass to fence agent + * \param[in] port_map Mapping of target names to device ports + * \param[in] default_host_arg Default agent parameter for passing target * * \return Newly created fencing action (asserts on error, never NULL) */ @@ -252,12 +253,12 @@ stonith_action_t * stonith__action_create(const char *agent, const char *action_name, const char *target, int timeout_sec, GHashTable *device_args, GHashTable *port_map, - const char *host_arg) + const char *default_host_arg) { stonith_action_t *action = pcmk__assert_alloc(1, sizeof(stonith_action_t)); action->args = make_args(agent, action_name, target, device_args, port_map, - host_arg); + default_host_arg); crm_debug("Preparing '%s' action targeting %s using agent %s", action_name, pcmk__s(target, "no node"), agent); action->agent = strdup(agent); From 1ade26e842e4d8b2672528dc6646656c9b34cef7 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 02:33:17 -0700 Subject: [PATCH 04/75] Refactor: libstonithd: New stonith__default_host_arg() To reduce duplication Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 36 ++++--------------------- daemons/fenced/pacemaker-fenced.h | 1 + include/crm/fencing/internal.h | 2 +- lib/fencing/st_client.c | 45 ++++++++++++++++++++++--------- lib/fencing/st_rhcs.c | 7 +---- 5 files changed, 40 insertions(+), 51 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 7290b9df770..80aa8b44437 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -500,17 +500,8 @@ get_agent_metadata_cb(gpointer data) { case pcmk_rc_ok: if (device->agent_metadata) { read_action_metadata(device); - - if (stonith__param_is_supported(device->agent_metadata, - "plug")) { - stonith__set_device_flags(device->flags, device->id, - st_device_supports_parameter_plug); - } - if (stonith__param_is_supported(device->agent_metadata, - "port")) { - stonith__set_device_flags(device->flags, device->id, - st_device_supports_parameter_port); - } + device->default_host_arg = + stonith__default_host_arg(device->agent_metadata); } return G_SOURCE_REMOVE; @@ -551,7 +542,6 @@ stonith_device_execute(fenced_device_t *device) { int exec_rc = 0; const char *action_str = NULL; - const char *host_arg = NULL; async_command_t *cmd = NULL; stonith_action_t *action = NULL; int active_cmds = 0; @@ -640,16 +630,9 @@ stonith_device_execute(fenced_device_t *device) action_str = PCMK_ACTION_OFF; } - if (pcmk_is_set(device->flags, st_device_supports_parameter_port)) { - host_arg = "port"; - - } else if (pcmk_is_set(device->flags, st_device_supports_parameter_plug)) { - host_arg = "plug"; - } - action = stonith__action_create(device->agent, action_str, cmd->target, cmd->timeout, device->params, - device->aliases, host_arg); + device->aliases, device->default_host_arg); /* for async exec, exec_rc is negative for early error exit otherwise handling of success/errors is done via callbacks */ @@ -1084,17 +1067,8 @@ build_device_from_xml(const xmlNode *dev) case pcmk_rc_ok: if (device->agent_metadata) { read_action_metadata(device); - - if (stonith__param_is_supported(device->agent_metadata, - "plug")) { - stonith__set_device_flags(device->flags, device->id, - st_device_supports_parameter_plug); - } - if (stonith__param_is_supported(device->agent_metadata, - "port")) { - stonith__set_device_flags(device->flags, device->id, - st_device_supports_parameter_port); - } + device->default_host_arg = + stonith__default_host_arg(device->agent_metadata); } break; diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index c1590438cc1..cc5fdc99d02 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -47,6 +47,7 @@ typedef struct { mainloop_timer_t *timer; crm_trigger_t *work; xmlNode *agent_metadata; + const char *default_host_arg; /*! A verified device is one that has contacted the * agent successfully to perform a monitor operation */ diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 1cf1937fef1..f816e06821c 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -100,7 +100,7 @@ const char *stonith__later_succeeded(const stonith_history_t *event, const stonith_history_t *top_history); stonith_history_t *stonith__sort_history(stonith_history_t *history); -bool stonith__param_is_supported(xmlNode *metadata, const char *name); +const char *stonith__default_host_arg(xmlNode *metadata); /* Only 1-9 is allowed for fencing topology levels, * however, 0 is used to unregister all levels in diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 50c2b1ddb96..0451a966223 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -2439,26 +2439,45 @@ stonith__event_state_neq(stonith_history_t *history, void *user_data) * \retval \c true If \p name exists as a parameter in \p metadata * \retval \c false Otherwise */ -bool -stonith__param_is_supported(xmlNode *metadata, const char *name) +static bool +param_is_supported(xmlNode *metadata, const char *name) { - char *xpath_s = NULL; - xmlXPathObject *xpath = NULL; - bool supported = false; - - CRM_CHECK(metadata != NULL, return false); - - xpath_s = crm_strdup_printf("//" PCMK_XE_PARAMETER - "[@" PCMK_XA_NAME "='%s']", - name); - xpath = pcmk__xpath_search(metadata->doc, xpath_s); - supported = (pcmk__xpath_num_results(xpath) > 0); + char *xpath_s = crm_strdup_printf("//" PCMK_XE_PARAMETER + "[@" PCMK_XA_NAME "='%s']", + name); + xmlXPathObject *xpath = pcmk__xpath_search(metadata->doc, xpath_s); + bool supported = (pcmk__xpath_num_results(xpath) > 0); free(xpath_s); xmlXPathFreeObject(xpath); return supported; } +/*! + * \internal + * \brief Get the default host argument based on a device's agent metadata + * + * If an agent supports the "plug" parameter, default to that. Otherwise default + * to the "port" parameter if supported. Otherwise return \c NULL. + * + * \param[in] metadata Agent metadata + * + * \return Parameter name for default host argument + */ +const char * +stonith__default_host_arg(xmlNode *metadata) +{ + CRM_CHECK(metadata != NULL, return NULL); + + if (param_is_supported(metadata, "plug")) { + return "plug"; + } + if (param_is_supported(metadata, "port")) { + return "port"; + } + return NULL; +} + /*! * \internal * \brief Retrieve fence agent meta-data asynchronously diff --git a/lib/fencing/st_rhcs.c b/lib/fencing/st_rhcs.c index 64cc3cd1772..d2c5176c0de 100644 --- a/lib/fencing/st_rhcs.c +++ b/lib/fencing/st_rhcs.c @@ -282,12 +282,7 @@ stonith__rhcs_validate(stonith_t *st, int call_options, const char *target, rc = stonith__rhcs_get_metadata(agent, remaining_timeout, &metadata); if (rc == pcmk_ok) { - if (stonith__param_is_supported(metadata, "plug")) { - host_arg = "plug"; - } else if (stonith__param_is_supported(metadata, "port")) { - host_arg = "port"; - } - + host_arg = stonith__default_host_arg(metadata); crm_trace("Using '%s' as default " PCMK_STONITH_HOST_ARGUMENT " for %s", pcmk__s(host_arg, PCMK_VALUE_NONE), agent); From c5040ddc674af50f90993a37666db67808182532 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 02:35:12 -0700 Subject: [PATCH 05/75] Refactor: libstonithd: Drop st_device_supports_parameter_{plug,port} No longer used Signed-off-by: Reid Wahl --- include/crm/fencing/internal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index f816e06821c..f8a5853e388 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -26,8 +26,6 @@ enum st_device_flags { st_device_supports_list = (1 << 0), st_device_supports_status = (1 << 1), st_device_supports_reboot = (1 << 2), - st_device_supports_parameter_plug = (1 << 3), - st_device_supports_parameter_port = (1 << 4), st_device_supports_on = (1 << 5), }; From 3ce5d325cc3657a587ff8571e5083a9ee6beb834 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 16:27:56 -0700 Subject: [PATCH 06/75] Refactor: fencer: st_device_supports_none -> fenced_df_none Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 4 ++-- daemons/fenced/fenced_remote.c | 22 ++++++++++++++++------ daemons/fenced/pacemaker-fenced.h | 15 ++++++++++++--- include/crm/fencing/internal.h | 1 - 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 80aa8b44437..8cedaaa6316 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1981,7 +1981,7 @@ search_devices_record_result(struct device_search_s *search, const char *device, { search->replies_received++; if (can_fence && device) { - if (search->support_action_only != st_device_supports_none) { + if (search->support_action_only != fenced_df_none) { fenced_device_t *dev = g_hash_table_lookup(device_table, device); if (dev && !pcmk_is_set(dev->flags, search->support_action_only)) { return; @@ -3216,7 +3216,7 @@ handle_query_request(pcmk__request_t *request) get_capable_devices(target, action, timeout, pcmk_is_set(query->call_options, st_opt_allow_self_fencing), - query, stonith_query_capable_device_cb, st_device_supports_none); + query, stonith_query_capable_device_cb, fenced_df_none); return NULL; } diff --git a/daemons/fenced/fenced_remote.c b/daemons/fenced/fenced_remote.c index 42760b8d27d..744c1d231ab 100644 --- a/daemons/fenced/fenced_remote.c +++ b/daemons/fenced/fenced_remote.c @@ -139,7 +139,9 @@ count_peer_device(gpointer key, gpointer value, gpointer user_data) if (!props->executed[data->op->phase] && (!data->verified_only || props->verified) - && ((data->support_action_only == st_device_supports_none) || pcmk_is_set(props->device_support_flags, data->support_action_only))) { + && ((data->support_action_only == fenced_df_none) + || pcmk_is_set(props->device_support_flags, + data->support_action_only))) { ++(data->count); } } @@ -187,11 +189,17 @@ find_peer_device(const remote_fencing_op_t *op, const peer_device_info_t *peer, { device_properties_t *props = g_hash_table_lookup(peer->devices, device); - if (props && support_action_only != st_device_supports_none && !pcmk_is_set(props->device_support_flags, support_action_only)) { + if (props == NULL) { return NULL; } - return (props && !props->executed[op->phase] - && !props->disallowed[op->phase])? props : NULL; + if ((support_action_only != fenced_df_none) + && !pcmk_is_set(props->device_support_flags, support_action_only)) { + return NULL; + } + if (props->executed[op->phase] || props->disallowed[op->phase]) { + return NULL; + } + return props; } /*! @@ -217,7 +225,8 @@ grab_peer_device(const remote_fencing_op_t *op, peer_device_info_t *peer, } crm_trace("Removing %s from %s (%d remaining)", - device, peer->host, count_peer_devices(op, peer, FALSE, st_device_supports_none)); + device, peer->host, + count_peer_devices(op, peer, FALSE, fenced_df_none)); props->executed[op->phase] = TRUE; return TRUE; } @@ -2143,7 +2152,8 @@ all_topology_devices_found(const remote_fencing_op_t *op) if (skip_target && pcmk__str_eq(peer->host, op->target, pcmk__str_casei)) { continue; } - match = find_peer_device(op, peer, device->data, st_device_supports_none); + match = find_peer_device(op, peer, device->data, + fenced_df_none); } if (!match) { return FALSE; diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index cc5fdc99d02..0f0bf112c64 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -26,6 +26,15 @@ */ gboolean stonith_check_fence_tolerance(int tolerance, const char *target, const char *action); +/*! + * \internal + * \brief Flags for \c fenced_device_t configuration, state, and support + */ +enum fenced_device_flags { + //! This flag has no effect + fenced_df_none = UINT32_C(0), +}; + typedef struct { char *id; char *agent; @@ -39,7 +48,7 @@ typedef struct { /* whether the cluster should automatically unfence nodes with the device */ gboolean automatic_unfencing; - uint32_t flags; // Group of enum st_device_flags + uint32_t flags; // Group of enum fenced_device_flags and enum st_device_flags GHashTable *params; GHashTable *aliases; @@ -315,7 +324,7 @@ fenced_set_protocol_error(pcmk__action_result_t *result) * \param[in] action Action to check * * \return st_device_supports_on if \p action is "on", otherwise - * st_device_supports_none + * \c fenced_df_none */ static inline uint32_t fenced_support_flag(const char *action) @@ -323,7 +332,7 @@ fenced_support_flag(const char *action) if (pcmk__str_eq(action, PCMK_ACTION_ON, pcmk__str_none)) { return st_device_supports_on; } - return st_device_supports_none; + return fenced_df_none; } extern GHashTable *topology; diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index f8a5853e388..328b10f21ea 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -22,7 +22,6 @@ extern "C" { #endif enum st_device_flags { - st_device_supports_none = (0 << 0), st_device_supports_list = (1 << 0), st_device_supports_status = (1 << 1), st_device_supports_reboot = (1 << 2), From fd651618442b44f7d10f3b0b313f542f7d331172 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 16:33:09 -0700 Subject: [PATCH 07/75] Refactor: fencer: st_device_supports_list -> fenced_df_supports_list Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 4 ++-- daemons/fenced/pacemaker-fenced.h | 3 +++ include/crm/fencing/internal.h | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 8cedaaa6316..be646d2ab84 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -974,7 +974,7 @@ read_action_metadata(fenced_device_t *device) if (pcmk__str_eq(action, PCMK_ACTION_LIST, pcmk__str_none)) { stonith__set_device_flags(device->flags, device->id, - st_device_supports_list); + fenced_df_supports_list); } else if (pcmk__str_eq(action, PCMK_ACTION_STATUS, pcmk__str_none)) { stonith__set_device_flags(device->flags, device->id, st_device_supports_status); @@ -1019,7 +1019,7 @@ target_list_type(fenced_device_t *dev) check_type = PCMK_VALUE_STATIC_LIST; } else if (g_hash_table_lookup(dev->params, PCMK_STONITH_HOST_MAP)) { check_type = PCMK_VALUE_STATIC_LIST; - } else if (pcmk_is_set(dev->flags, st_device_supports_list)) { + } else if (pcmk_is_set(dev->flags, fenced_df_supports_list)) { check_type = PCMK_VALUE_DYNAMIC_LIST; } else if (pcmk_is_set(dev->flags, st_device_supports_status)) { check_type = PCMK_VALUE_STATUS; diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 0f0bf112c64..6c0ef818a5e 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -33,6 +33,9 @@ gboolean stonith_check_fence_tolerance(int tolerance, const char *target, const enum fenced_device_flags { //! This flag has no effect fenced_df_none = UINT32_C(0), + + //! Device supports list action + fenced_df_supports_list = (UINT32_C(1) << 0), }; typedef struct { diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 328b10f21ea..f61d7a2afea 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -22,7 +22,6 @@ extern "C" { #endif enum st_device_flags { - st_device_supports_list = (1 << 0), st_device_supports_status = (1 << 1), st_device_supports_reboot = (1 << 2), st_device_supports_on = (1 << 5), From 56b3515d4c20947ffedb390b5a560c33ff7f7f79 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 16:36:50 -0700 Subject: [PATCH 08/75] Refactor: fencer: st_device_supports_on -> fenced_df_supports_on Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 6 +++--- daemons/fenced/fenced_remote.c | 5 +++-- daemons/fenced/pacemaker-fenced.h | 7 +++++-- include/crm/fencing/internal.h | 1 - 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index be646d2ab84..e9eebbcfbf7 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -337,7 +337,7 @@ fenced_device_supports_on(const char *device_id) fenced_device_t *device = g_hash_table_lookup(device_table, device_id); if (device != NULL) { - return pcmk_is_set(device->flags, st_device_supports_on); + return pcmk_is_set(device->flags, fenced_df_supports_on); } } return false; @@ -993,7 +993,7 @@ read_action_metadata(fenced_device_t *device) device->automatic_unfencing = TRUE; } stonith__set_device_flags(device->flags, device->id, - st_device_supports_on); + fenced_df_supports_on); } if ((action != NULL) @@ -2125,7 +2125,7 @@ can_fence_host_with_device(fenced_device_t *dev, * or the local node is not allowed to perform it */ if (pcmk__str_eq(action, PCMK_ACTION_ON, pcmk__str_none) - && !pcmk_is_set(dev->flags, st_device_supports_on)) { + && !pcmk_is_set(dev->flags, fenced_df_supports_on)) { check_type = "Agent does not support 'on'"; goto search_report_results; diff --git a/daemons/fenced/fenced_remote.c b/daemons/fenced/fenced_remote.c index 744c1d231ab..b21163f0b0f 100644 --- a/daemons/fenced/fenced_remote.c +++ b/daemons/fenced/fenced_remote.c @@ -1686,7 +1686,8 @@ get_op_total_timeout(const remote_fencing_op_t *op, for (iter2 = op->query_results; iter2 != NULL; iter = iter2->next) { peer_device_info_t *peer = iter2->data; - if (find_peer_device(op, peer, iter->data, st_device_supports_on)) { + if (find_peer_device(op, peer, iter->data, + fenced_df_supports_on)) { total_timeout += get_device_timeout(op, peer, iter->data, true); break; @@ -2259,7 +2260,7 @@ add_device_properties(const xmlNode *xml, remote_fencing_op_t *op, // Nodes <2.1.5 won't set this, so assume unfencing in that case rc = pcmk__xe_get_flags(xml, PCMK__XA_ST_DEVICE_SUPPORT_FLAGS, &(props->device_support_flags), - st_device_supports_on); + fenced_df_supports_on); if (rc != pcmk_rc_ok) { crm_warn("Couldn't determine device support for %s " "(assuming unfencing): %s", device, pcmk_rc_str(rc)); diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 6c0ef818a5e..1341338d927 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -36,6 +36,9 @@ enum fenced_device_flags { //! Device supports list action fenced_df_supports_list = (UINT32_C(1) << 0), + + //! Device supports on action + fenced_df_supports_on = (UINT32_C(1) << 1), }; typedef struct { @@ -326,14 +329,14 @@ fenced_set_protocol_error(pcmk__action_result_t *result) * * \param[in] action Action to check * - * \return st_device_supports_on if \p action is "on", otherwise + * \return \c fenced_df_supports_on if \p action is "on", otherwise * \c fenced_df_none */ static inline uint32_t fenced_support_flag(const char *action) { if (pcmk__str_eq(action, PCMK_ACTION_ON, pcmk__str_none)) { - return st_device_supports_on; + return fenced_df_supports_on; } return fenced_df_none; } diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index f61d7a2afea..325a7c1b59f 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -24,7 +24,6 @@ extern "C" { enum st_device_flags { st_device_supports_status = (1 << 1), st_device_supports_reboot = (1 << 2), - st_device_supports_on = (1 << 5), }; #define stonith__set_device_flags(device_flags, device_id, flags_to_set) do { \ From c94adc828ebf0be57a3d27581db1cd102465bab5 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 16:38:28 -0700 Subject: [PATCH 09/75] Refactor: fencer: st_device_supports_reboot -> fenced_df_supports_reboot Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 8 ++++---- daemons/fenced/pacemaker-fenced.h | 3 +++ include/crm/fencing/internal.h | 1 - 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index e9eebbcfbf7..b803269dfe9 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -265,7 +265,7 @@ get_action_timeout(const fenced_device_t *device, const char *action, * we will remap to "off", so check timeout for "off" instead */ if (pcmk__str_eq(action, PCMK_ACTION_REBOOT, pcmk__str_none) - && !pcmk_is_set(device->flags, st_device_supports_reboot)) { + && !pcmk_is_set(device->flags, fenced_df_supports_reboot)) { crm_trace("%s doesn't support reboot, using timeout for off instead", device->id); action = PCMK_ACTION_OFF; @@ -621,7 +621,7 @@ stonith_device_execute(fenced_device_t *device) action_str = cmd->action; if (pcmk__str_eq(cmd->action, PCMK_ACTION_REBOOT, pcmk__str_none) - && !pcmk_is_set(device->flags, st_device_supports_reboot)) { + && !pcmk_is_set(device->flags, fenced_df_supports_reboot)) { crm_notice("Remapping 'reboot' action%s%s using %s to 'off' " "because agent '%s' does not support reboot", @@ -980,7 +980,7 @@ read_action_metadata(fenced_device_t *device) st_device_supports_status); } else if (pcmk__str_eq(action, PCMK_ACTION_REBOOT, pcmk__str_none)) { stonith__set_device_flags(device->flags, device->id, - st_device_supports_reboot); + fenced_df_supports_reboot); } else if (pcmk__str_eq(action, PCMK_ACTION_ON, pcmk__str_none)) { /* PCMK_XA_AUTOMATIC means the cluster will unfence a node when it * joins. @@ -2444,7 +2444,7 @@ stonith_query_capable_device_cb(GList * devices, void *user_data) /* If the originating fencer wants to reboot the node, and we have a * capable device that doesn't support "reboot", remap to "off" instead. */ - if (!pcmk_is_set(device->flags, st_device_supports_reboot) + if (!pcmk_is_set(device->flags, fenced_df_supports_reboot) && pcmk__str_eq(query->action, PCMK_ACTION_REBOOT, pcmk__str_none)) { crm_trace("%s doesn't support reboot, using values for off instead", diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 1341338d927..c573b26bdcb 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -39,6 +39,9 @@ enum fenced_device_flags { //! Device supports on action fenced_df_supports_on = (UINT32_C(1) << 1), + + //! Device supports reboot action + fenced_df_supports_reboot = (UINT32_C(1) << 2), }; typedef struct { diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 325a7c1b59f..caeb405669b 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -23,7 +23,6 @@ extern "C" { enum st_device_flags { st_device_supports_status = (1 << 1), - st_device_supports_reboot = (1 << 2), }; #define stonith__set_device_flags(device_flags, device_id, flags_to_set) do { \ From 04814dcfbb8cee446e91446e7bc65070b331c15a Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 16:34:20 -0700 Subject: [PATCH 10/75] Refactor: fencer: st_device_supports_status -> fenced_df_supports_status Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 4 ++-- daemons/fenced/pacemaker-fenced.h | 5 ++++- include/crm/fencing/internal.h | 4 ---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index b803269dfe9..1dd9665c8b6 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -977,7 +977,7 @@ read_action_metadata(fenced_device_t *device) fenced_df_supports_list); } else if (pcmk__str_eq(action, PCMK_ACTION_STATUS, pcmk__str_none)) { stonith__set_device_flags(device->flags, device->id, - st_device_supports_status); + fenced_df_supports_status); } else if (pcmk__str_eq(action, PCMK_ACTION_REBOOT, pcmk__str_none)) { stonith__set_device_flags(device->flags, device->id, fenced_df_supports_reboot); @@ -1021,7 +1021,7 @@ target_list_type(fenced_device_t *dev) check_type = PCMK_VALUE_STATIC_LIST; } else if (pcmk_is_set(dev->flags, fenced_df_supports_list)) { check_type = PCMK_VALUE_DYNAMIC_LIST; - } else if (pcmk_is_set(dev->flags, st_device_supports_status)) { + } else if (pcmk_is_set(dev->flags, fenced_df_supports_status)) { check_type = PCMK_VALUE_STATUS; } else { check_type = PCMK_VALUE_NONE; diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index c573b26bdcb..a291d576ee7 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -42,6 +42,9 @@ enum fenced_device_flags { //! Device supports reboot action fenced_df_supports_reboot = (UINT32_C(1) << 2), + + //! Device supports status action + fenced_df_supports_status = (UINT32_C(1) << 3), }; typedef struct { @@ -57,7 +60,7 @@ typedef struct { /* whether the cluster should automatically unfence nodes with the device */ gboolean automatic_unfencing; - uint32_t flags; // Group of enum fenced_device_flags and enum st_device_flags + uint32_t flags; // Group of enum fenced_device_flags GHashTable *params; GHashTable *aliases; diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index caeb405669b..f2c3a539ceb 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -21,10 +21,6 @@ extern "C" { #endif -enum st_device_flags { - st_device_supports_status = (1 << 1), -}; - #define stonith__set_device_flags(device_flags, device_id, flags_to_set) do { \ device_flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ "Fence device", device_id, \ From a10cf9d2f73ba5a6aeae3e88fc6a4a5383f2e651 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 17:38:39 -0700 Subject: [PATCH 11/75] Refactor: fencer: stonith__set_device_flags -> fenced_device_set_flags Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 15 +++++++-------- daemons/fenced/pacemaker-fenced.h | 15 +++++++++++++++ include/crm/fencing/internal.h | 7 ------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 1dd9665c8b6..069c68aedc9 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -973,14 +973,14 @@ read_action_metadata(fenced_device_t *device) action = crm_element_value(match, PCMK_XA_NAME); if (pcmk__str_eq(action, PCMK_ACTION_LIST, pcmk__str_none)) { - stonith__set_device_flags(device->flags, device->id, - fenced_df_supports_list); + fenced_device_set_flags(device, fenced_df_supports_list); + } else if (pcmk__str_eq(action, PCMK_ACTION_STATUS, pcmk__str_none)) { - stonith__set_device_flags(device->flags, device->id, - fenced_df_supports_status); + fenced_device_set_flags(device, fenced_df_supports_status); + } else if (pcmk__str_eq(action, PCMK_ACTION_REBOOT, pcmk__str_none)) { - stonith__set_device_flags(device->flags, device->id, - fenced_df_supports_reboot); + fenced_device_set_flags(device, fenced_df_supports_reboot); + } else if (pcmk__str_eq(action, PCMK_ACTION_ON, pcmk__str_none)) { /* PCMK_XA_AUTOMATIC means the cluster will unfence a node when it * joins. @@ -992,8 +992,7 @@ read_action_metadata(fenced_device_t *device) || pcmk__xe_attr_is_true(match, PCMK__XA_REQUIRED)) { device->automatic_unfencing = TRUE; } - stonith__set_device_flags(device->flags, device->id, - fenced_df_supports_on); + fenced_device_set_flags(device, fenced_df_supports_on); } if ((action != NULL) diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index a291d576ee7..73314a60006 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -47,6 +47,21 @@ enum fenced_device_flags { fenced_df_supports_status = (UINT32_C(1) << 3), }; +/*! + * \internal + * \brief Set flags for a fencing device + * + * \param[in,out] device Device whose flags to set (\c fenced_device_t) + * \param[in] set_flags Group of enum fenced_device_flags to set + */ +#define fenced_device_set_flags(device, set_flags) do { \ + pcmk__assert((device) != NULL); \ + (device)->flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ + "Fence device", (device)->id, \ + (device)->flags, set_flags, \ + #set_flags); \ + } while (0) + typedef struct { char *id; char *agent; diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index f2c3a539ceb..0e2b311ff2a 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -21,13 +21,6 @@ extern "C" { #endif -#define stonith__set_device_flags(device_flags, device_id, flags_to_set) do { \ - device_flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ - "Fence device", device_id, \ - (device_flags), (flags_to_set), \ - #flags_to_set); \ - } while (0) - #define stonith__set_call_options(st_call_opts, call_for, flags_to_set) do { \ st_call_opts = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ "Fencer call", (call_for), \ From 857249ebbb24014b4e5b67e16196cd738dbeaf3d Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 18:03:54 -0700 Subject: [PATCH 12/75] Refactor: fencer: New fenced_df_auto_unfence flag To replace fenced_device_t:automatic_unfencing Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 8 +++++--- daemons/fenced/pacemaker-fenced.h | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 069c68aedc9..d9abd930dce 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -164,7 +164,8 @@ fenced_foreach_device_remove(GHRFunc fn) static gboolean is_action_required(const char *action, const fenced_device_t *device) { - return (device != NULL) && device->automatic_unfencing + return (device != NULL) + && pcmk_is_set(device->flags, fenced_df_auto_unfence) && pcmk__str_eq(action, PCMK_ACTION_ON, pcmk__str_none); } @@ -990,7 +991,8 @@ read_action_metadata(fenced_device_t *device) */ if (pcmk__xe_attr_is_true(match, PCMK_XA_AUTOMATIC) || pcmk__xe_attr_is_true(match, PCMK__XA_REQUIRED)) { - device->automatic_unfencing = TRUE; + + fenced_device_set_flags(device, fenced_df_auto_unfence); } fenced_device_set_flags(device, fenced_df_supports_on); } @@ -1087,7 +1089,7 @@ build_device_from_xml(const xmlNode *dev) value = crm_element_value(dev, PCMK__XA_RSC_PROVIDES); if (pcmk__str_eq(value, PCMK_VALUE_UNFENCING, pcmk__str_casei)) { - device->automatic_unfencing = TRUE; + fenced_device_set_flags(device, fenced_df_auto_unfence); } if (is_action_required(PCMK_ACTION_ON, device)) { diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 73314a60006..8d5d213eeca 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -45,6 +45,9 @@ enum fenced_device_flags { //! Device supports status action fenced_df_supports_status = (UINT32_C(1) << 3), + + //! Device is automatically used to unfence newly joined nodes + fenced_df_auto_unfence = (UINT32_C(1) << 4), }; /*! @@ -72,9 +75,6 @@ typedef struct { GList *targets; time_t targets_age; - /* whether the cluster should automatically unfence nodes with the device */ - gboolean automatic_unfencing; - uint32_t flags; // Group of enum fenced_device_flags GHashTable *params; From e6fd6656c56a1421a96947294546cf13f76eb166 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 18:11:56 -0700 Subject: [PATCH 13/75] Refactor: fencer: New fenced_df_verified flag To replace fenced_device_t:verified Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 10 ++++++---- daemons/fenced/pacemaker-fenced.h | 24 ++++++++++++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index d9abd930dce..ab359d9cfc5 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1457,7 +1457,7 @@ stonith_device_remove(const char *id, bool from_cib) if (from_cib) { device->cib_registered = FALSE; } else { - device->verified = FALSE; + fenced_device_clear_flags(device, fenced_df_verified); device->api_registered = FALSE; } @@ -2438,7 +2438,8 @@ stonith_query_capable_device_cb(GList * devices, void *user_data) crm_xml_add(dev, PCMK_XA_AGENT, device->agent); // Has had successful monitor, list, or status on this node - crm_xml_add_int(dev, PCMK__XA_ST_MONITOR_VERIFIED, device->verified); + crm_xml_add_int(dev, PCMK__XA_ST_MONITOR_VERIFIED, + pcmk_is_set(device->flags, fenced_df_verified)); crm_xml_add_int(dev, PCMK__XA_ST_DEVICE_SUPPORT_FLAGS, device->flags); @@ -2767,12 +2768,13 @@ st_child_done(int pid, const pcmk__action_result_t *result, void *user_data) /* The device is ready to do something else now */ if (device) { - if (!device->verified && pcmk__result_ok(result) + if (!pcmk_is_set(device->flags, fenced_df_verified) + && pcmk__result_ok(result) && pcmk__strcase_any_of(cmd->action, PCMK_ACTION_LIST, PCMK_ACTION_MONITOR, PCMK_ACTION_STATUS, NULL)) { - device->verified = TRUE; + fenced_device_set_flags(device, fenced_df_verified); } mainloop_set_trigger(device->work); diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 8d5d213eeca..0dc9d0a77b0 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -48,6 +48,9 @@ enum fenced_device_flags { //! Device is automatically used to unfence newly joined nodes fenced_df_auto_unfence = (UINT32_C(1) << 4), + + //! Device has run a successful list, status, or monitor action on this node + fenced_df_verified = (UINT32_C(1) << 5), }; /*! @@ -65,6 +68,23 @@ enum fenced_device_flags { #set_flags); \ } while (0) +/*! + * \internal + * \brief Clear flags for a fencing device + * + * \param[in,out] device Device whose flags to clear (\c fenced_device_t) + * \param[in] clear_flags Group of enum fenced_device_flags to + * clear + */ +#define fenced_device_clear_flags(device, clear_flags) do { \ + pcmk__assert((device) != NULL); \ + (device)->flags = pcmk__clear_flags_as(__func__, __LINE__, \ + LOG_TRACE, "Fence device", \ + (device)->id, \ + (device)->flags, \ + clear_flags, #clear_flags); \ + } while (0) + typedef struct { char *id; char *agent; @@ -85,10 +105,6 @@ typedef struct { xmlNode *agent_metadata; const char *default_host_arg; - /*! A verified device is one that has contacted the - * agent successfully to perform a monitor operation */ - gboolean verified; - gboolean cib_registered; gboolean api_registered; gboolean dirty; From 466984b390e1d5b33a5803c22924b6501b907f80 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 18:17:11 -0700 Subject: [PATCH 14/75] Refactor: fencer: New fenced_df_api_registered flag To replace fenced_device_t:api_registered Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 17 ++++++++++------- daemons/fenced/pacemaker-fenced.h | 4 +++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index ab359d9cfc5..92a3f865786 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1407,7 +1407,8 @@ fenced_device_register(const xmlNode *dev, bool from_cib) guint ndevices = 0; fenced_device_t *old = g_hash_table_lookup(device_table, device->id); - if (from_cib && (old != NULL) && old->api_registered) { + if (from_cib && (old != NULL) + && pcmk_is_set(old->flags, fenced_df_api_registered)) { /* If the CIB is writing over an entry that is shared with a stonith * client, copy any pending ops that currently exist on the old * entry to the new one. Otherwise the pending ops will be reported @@ -1415,7 +1416,7 @@ fenced_device_register(const xmlNode *dev, bool from_cib) */ crm_info("Overwriting existing entry for %s from CIB", device->id); device->pending_ops = old->pending_ops; - device->api_registered = TRUE; + fenced_device_set_flags(device, fenced_df_api_registered); old->pending_ops = NULL; if (device->pending_ops != NULL) { mainloop_set_trigger(device->work); @@ -1431,7 +1432,7 @@ fenced_device_register(const xmlNode *dev, bool from_cib) if (from_cib) { device->cib_registered = TRUE; } else { - device->api_registered = TRUE; + fenced_device_set_flags(device, fenced_df_api_registered); } done: @@ -1457,11 +1458,13 @@ stonith_device_remove(const char *id, bool from_cib) if (from_cib) { device->cib_registered = FALSE; } else { - fenced_device_clear_flags(device, fenced_df_verified); - device->api_registered = FALSE; + fenced_device_clear_flags(device, + fenced_df_api_registered|fenced_df_verified); } - if (!device->cib_registered && !device->api_registered) { + if (!device->cib_registered + && !pcmk_is_set(device->flags, fenced_df_api_registered)) { + g_hash_table_remove(device_table, id); ndevices = g_hash_table_size(device_table); crm_info("Removed '%s' from device list (%u active device%s)", @@ -1956,7 +1959,7 @@ execute_agent_action(xmlNode *msg, pcmk__action_result_t *result) "'%s' not found", id); return; - } else if (!device->api_registered + } else if (!pcmk_is_set(device->flags, fenced_df_api_registered) && (strcmp(action, PCMK_ACTION_MONITOR) == 0)) { // Monitors may run only on "started" (API-registered) devices crm_info("Ignoring API '%s' action request because device %s not active", diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 0dc9d0a77b0..3128fa6d585 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -51,6 +51,9 @@ enum fenced_device_flags { //! Device has run a successful list, status, or monitor action on this node fenced_df_verified = (UINT32_C(1) << 5), + + //! Device has been registered via the stonith API + fenced_df_api_registered = (UINT32_C(1) << 6), }; /*! @@ -106,7 +109,6 @@ typedef struct { const char *default_host_arg; gboolean cib_registered; - gboolean api_registered; gboolean dirty; } fenced_device_t; From 350ead2b637257a76516360ef73abf30917a5cb2 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 21:03:49 -0700 Subject: [PATCH 15/75] Refactor: fencer: New fenced_df_cib_registered flag To replace stonith_device_t:cib_registered Signed-off-by: Reid Wahl --- daemons/fenced/fenced_cib.c | 5 +++-- daemons/fenced/fenced_commands.c | 15 +++++++++------ daemons/fenced/pacemaker-fenced.h | 4 +++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/daemons/fenced/fenced_cib.c b/daemons/fenced/fenced_cib.c index 90c225569eb..a8ae11cd112 100644 --- a/daemons/fenced/fenced_cib.c +++ b/daemons/fenced/fenced_cib.c @@ -196,7 +196,8 @@ update_stonith_watchdog_timeout_ms(xmlNode *cib) /*! * \internal - * \brief Mark a fence device dirty if its \c cib_registered flag is \c TRUE + * \brief Mark a fence device dirty if its \c fenced_df_cib_registered flag is + * set * * \param[in] key Ignored * \param[in,out] value Fence device (fenced_device_t *) @@ -209,7 +210,7 @@ mark_dirty_if_cib_registered(gpointer key, gpointer value, gpointer user_data) { fenced_device_t *device = value; - if (device->cib_registered) { + if (pcmk_is_set(device->flags, fenced_df_cib_registered)) { device->dirty = TRUE; } } diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 92a3f865786..4d38cf85396 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1430,7 +1430,7 @@ fenced_device_register(const xmlNode *dev, bool from_cib) } if (from_cib) { - device->cib_registered = TRUE; + fenced_device_set_flags(device, fenced_df_cib_registered); } else { fenced_device_set_flags(device, fenced_df_api_registered); } @@ -1456,25 +1456,28 @@ stonith_device_remove(const char *id, bool from_cib) } if (from_cib) { - device->cib_registered = FALSE; + fenced_device_clear_flags(device, fenced_df_cib_registered); } else { fenced_device_clear_flags(device, fenced_df_api_registered|fenced_df_verified); } - if (!device->cib_registered - && !pcmk_is_set(device->flags, fenced_df_api_registered)) { - + if (!pcmk_any_flags_set(device->flags, + fenced_df_api_registered + |fenced_df_cib_registered)) { g_hash_table_remove(device_table, id); ndevices = g_hash_table_size(device_table); crm_info("Removed '%s' from device list (%u active device%s)", id, ndevices, pcmk__plural_s(ndevices)); } else { // Exactly one is true at this point + const bool cib_registered = pcmk_is_set(device->flags, + fenced_df_cib_registered); + crm_trace("Not removing '%s' from device list (%u active) because " "still registered via %s", id, g_hash_table_size(device_table), - (device->cib_registered? "CIB" : "API")); + (cib_registered? "CIB" : "API")); } } diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 3128fa6d585..db55e24e5e6 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -54,6 +54,9 @@ enum fenced_device_flags { //! Device has been registered via the stonith API fenced_df_api_registered = (UINT32_C(1) << 6), + + //! Device has been registered via the fencer's CIB diff callback + fenced_df_cib_registered = (UINT32_C(1) << 7), }; /*! @@ -108,7 +111,6 @@ typedef struct { xmlNode *agent_metadata; const char *default_host_arg; - gboolean cib_registered; gboolean dirty; } fenced_device_t; From 092cdb8cc69bda6891486838e524abc8011f6dfd Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 21:07:10 -0700 Subject: [PATCH 16/75] Refactor: fencer: New fenced_df_dirty flag Signed-off-by: Reid Wahl --- daemons/fenced/fenced_cib.c | 4 ++-- daemons/fenced/fenced_commands.c | 2 +- daemons/fenced/pacemaker-fenced.h | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/daemons/fenced/fenced_cib.c b/daemons/fenced/fenced_cib.c index a8ae11cd112..a53dca26324 100644 --- a/daemons/fenced/fenced_cib.c +++ b/daemons/fenced/fenced_cib.c @@ -211,7 +211,7 @@ mark_dirty_if_cib_registered(gpointer key, gpointer value, gpointer user_data) fenced_device_t *device = value; if (pcmk_is_set(device->flags, fenced_df_cib_registered)) { - device->dirty = TRUE; + fenced_device_set_flags(device, fenced_df_dirty); } } @@ -233,7 +233,7 @@ device_is_dirty(gpointer key, gpointer value, gpointer user_data) { fenced_device_t *device = value; - return device->dirty; + return pcmk_is_set(device->flags, fenced_df_dirty); } /*! diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 4d38cf85396..c8b8e470464 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1401,7 +1401,7 @@ fenced_device_register(const xmlNode *dev, bool from_cib) device->id, ndevices, pcmk__plural_s(ndevices)); free_device(device); device = dup; - device->dirty = FALSE; + fenced_device_clear_flags(device, fenced_df_dirty); } else { guint ndevices = 0; diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index db55e24e5e6..66d82ea1eed 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -57,6 +57,9 @@ enum fenced_device_flags { //! Device has been registered via the fencer's CIB diff callback fenced_df_cib_registered = (UINT32_C(1) << 7), + + //! Device has not yet been re-registered after a CIB change + fenced_df_dirty = (UINT32_C(1) << 8), }; /*! @@ -110,8 +113,6 @@ typedef struct { crm_trigger_t *work; xmlNode *agent_metadata; const char *default_host_arg; - - gboolean dirty; } fenced_device_t; /* These values are used to index certain arrays by "phase". Usually an From 351f6cbc99af753c5e8d2e752ee15c27ac7b4cc4 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 22:24:19 -0700 Subject: [PATCH 17/75] Refactor: fencer: st_client_flags -> fenced_notify_flags Signed-off-by: Reid Wahl --- daemons/fenced/pacemaker-fenced.h | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 66d82ea1eed..c7895404478 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -94,6 +94,19 @@ enum fenced_device_flags { clear_flags, #clear_flags); \ } while (0) +/*! + * \internal + * \brief Flags for fencer client notification types + */ +enum fenced_notify_flags { + st_callback_unknown = UINT32_C(0), + st_callback_notify_fence = (UINT32_C(1) << 0), + st_callback_device_add = (UINT32_C(1) << 2), + st_callback_device_del = (UINT32_C(1) << 4), + st_callback_notify_history = (UINT32_C(1) << 5), + st_callback_notify_history_synced = (UINT32_C(1) << 6), +}; + typedef struct { char *id; char *agent; @@ -225,16 +238,6 @@ typedef struct remote_fencing_op_s { void fenced_broadcast_op_result(const remote_fencing_op_t *op, bool op_merged); -// Fencer-specific client flags -enum st_client_flags { - st_callback_unknown = UINT64_C(0), - st_callback_notify_fence = (UINT64_C(1) << 0), - st_callback_device_add = (UINT64_C(1) << 2), - st_callback_device_del = (UINT64_C(1) << 4), - st_callback_notify_history = (UINT64_C(1) << 5), - st_callback_notify_history_synced = (UINT64_C(1) << 6) -}; - // How the user specified the target of a topology level enum fenced_target_by { fenced_target_by_unknown = -1, // Invalid or not yet parsed From b0d757563536e5ff846f8b64cf13e919f03f827e Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 22:27:44 -0700 Subject: [PATCH 18/75] Refactor: fencer: st_callback_unknown -> fenced_nf_none Signed-off-by: Reid Wahl --- daemons/fenced/pacemaker-fenced.c | 2 +- daemons/fenced/pacemaker-fenced.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index cb862b22845..6b2188f6da1 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -273,7 +273,7 @@ get_stonith_flag(const char *name) return st_callback_notify_history_synced; } - return st_callback_unknown; + return fenced_nf_none; } static void diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index c7895404478..fb26099201a 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -99,7 +99,9 @@ enum fenced_device_flags { * \brief Flags for fencer client notification types */ enum fenced_notify_flags { - st_callback_unknown = UINT32_C(0), + //! This flag has no effect + fenced_nf_none = UINT32_C(0), + st_callback_notify_fence = (UINT32_C(1) << 0), st_callback_device_add = (UINT32_C(1) << 2), st_callback_device_del = (UINT32_C(1) << 4), From 1787302d838c8ca93de22f6cf3b5295305789d7b Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 22:33:28 -0700 Subject: [PATCH 19/75] Refactor: fencer: st_callback_notify_fence -> fenced_nf_fence_result Signed-off-by: Reid Wahl --- daemons/fenced/pacemaker-fenced.c | 2 +- daemons/fenced/pacemaker-fenced.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index 6b2188f6da1..674705cebbc 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -256,7 +256,7 @@ uint64_t get_stonith_flag(const char *name) { if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_FENCE, pcmk__str_none)) { - return st_callback_notify_fence; + return fenced_nf_fence_result; } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_ADD, pcmk__str_casei)) { return st_callback_device_add; diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index fb26099201a..e37134c012e 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -102,7 +102,9 @@ enum fenced_notify_flags { //! This flag has no effect fenced_nf_none = UINT32_C(0), - st_callback_notify_fence = (UINT32_C(1) << 0), + //! Notify about fencing operation results + fenced_nf_fence_result = (UINT32_C(1) << 0), + st_callback_device_add = (UINT32_C(1) << 2), st_callback_device_del = (UINT32_C(1) << 4), st_callback_notify_history = (UINT32_C(1) << 5), From f27812b4e5e43ddc81a5c0c0d102c0b41b10e129 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 22:46:31 -0700 Subject: [PATCH 20/75] Refactor: fencer: st_callback_device_add -> fenced_nf_device_registered Signed-off-by: Reid Wahl --- daemons/fenced/pacemaker-fenced.c | 2 +- daemons/fenced/pacemaker-fenced.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index 674705cebbc..f5a729741f6 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -259,7 +259,7 @@ get_stonith_flag(const char *name) return fenced_nf_fence_result; } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_ADD, pcmk__str_casei)) { - return st_callback_device_add; + return fenced_nf_device_registered; } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_DEL, pcmk__str_casei)) { return st_callback_device_del; diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index e37134c012e..13e4a43d642 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -105,7 +105,10 @@ enum fenced_notify_flags { //! Notify about fencing operation results fenced_nf_fence_result = (UINT32_C(1) << 0), - st_callback_device_add = (UINT32_C(1) << 2), + // @TODO Consider notifying about device registrations via the CIB + //! Notify about fencing device registrations via the fencer API + fenced_nf_device_registered = (UINT32_C(1) << 1), + st_callback_device_del = (UINT32_C(1) << 4), st_callback_notify_history = (UINT32_C(1) << 5), st_callback_notify_history_synced = (UINT32_C(1) << 6), From 7e31fe78bc48a9bc486b04708bbeb49c49d04f15 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 22:49:11 -0700 Subject: [PATCH 21/75] Refactor: fencer: st_callback_device_del -> fenced_nf_device_removed Signed-off-by: Reid Wahl --- daemons/fenced/pacemaker-fenced.c | 2 +- daemons/fenced/pacemaker-fenced.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index f5a729741f6..9c6fcf4c76e 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -262,7 +262,7 @@ get_stonith_flag(const char *name) return fenced_nf_device_registered; } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_DEL, pcmk__str_casei)) { - return st_callback_device_del; + return fenced_nf_device_removed; } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY, pcmk__str_none)) { diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 13e4a43d642..80d16d1cff1 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -109,7 +109,10 @@ enum fenced_notify_flags { //! Notify about fencing device registrations via the fencer API fenced_nf_device_registered = (UINT32_C(1) << 1), - st_callback_device_del = (UINT32_C(1) << 4), + // @TODO Consider notifying about device removals via the CIB + //! Notify about fencing device removals via the fencer API + fenced_nf_device_removed = (UINT32_C(1) << 2), + st_callback_notify_history = (UINT32_C(1) << 5), st_callback_notify_history_synced = (UINT32_C(1) << 6), }; From a71c98d86b3572d6903dc5f99f8d226a1b21332d Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 23:28:47 -0700 Subject: [PATCH 22/75] Refactor: fencer: New fenced_nf_history_changed flag To replace st_callback_notify_history Signed-off-by: Reid Wahl --- daemons/fenced/pacemaker-fenced.c | 2 +- daemons/fenced/pacemaker-fenced.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index 9c6fcf4c76e..1c2e10b2a59 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -266,7 +266,7 @@ get_stonith_flag(const char *name) } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY, pcmk__str_none)) { - return st_callback_notify_history; + return fenced_nf_history_changed; } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY_SYNCED, pcmk__str_none)) { diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 80d16d1cff1..6682a16bbfb 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -113,7 +113,9 @@ enum fenced_notify_flags { //! Notify about fencing device removals via the fencer API fenced_nf_device_removed = (UINT32_C(1) << 2), - st_callback_notify_history = (UINT32_C(1) << 5), + //! Notify about changes to fencing history + fenced_nf_history_changed = (UINT32_C(1) << 3), + st_callback_notify_history_synced = (UINT32_C(1) << 6), }; From b88c65dc9c2f3a45eab8de7e068fe97953ae9f8a Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 23:32:12 -0700 Subject: [PATCH 23/75] Refactor: fencer: New fenced_nf_history_synced flag To replace st_callback_notify_history_synced Signed-off-by: Reid Wahl --- daemons/fenced/pacemaker-fenced.c | 3 +-- daemons/fenced/pacemaker-fenced.h | 8 +++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index 1c2e10b2a59..b72204870bd 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -270,8 +270,7 @@ get_stonith_flag(const char *name) } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY_SYNCED, pcmk__str_none)) { - return st_callback_notify_history_synced; - + return fenced_nf_history_synced; } return fenced_nf_none; } diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 6682a16bbfb..8f48ae4329f 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -116,7 +116,13 @@ enum fenced_notify_flags { //! Notify about changes to fencing history fenced_nf_history_changed = (UINT32_C(1) << 3), - st_callback_notify_history_synced = (UINT32_C(1) << 6), + /* @FIXME A comment in stonith_fence_history() says its check is not + * conclusive: it may send a "history synced" notification when the history + * has not been synced. Hence "might have been synced" below. Try to find a + * better test. + */ + //! Notify when the fencing history might have been synced + fenced_nf_history_synced = (UINT32_C(1) << 4), }; typedef struct { From fda36c937b83506fb6060c2c52c6fbcb612f3e48 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 9 Apr 2025 23:47:10 -0700 Subject: [PATCH 24/75] Refactor: fencer: Best practices in get_stonith_flag() * Add Doxygen. * Return an enum value rather than a uint64_t value. * Rename to fenced_parse_notify_flag() in accordance with our current convention for flag parsing functions. * Rename "name" argument to "type". * Replace "else if" with "if" where possible. * Match case-sensitively. STONITH_OP_DEVICE_ADD and STONITH_OP_DEVICE_DEL may be coming from an arbitrary request. However, if the user is making the request via the stonith API functions (as any sane user should be), then the case will always match exactly. Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 5 +++-- daemons/fenced/pacemaker-fenced.c | 35 ++++++++++++++++++------------- daemons/fenced/pacemaker-fenced.h | 4 ++-- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index c8b8e470464..2eecfc8f151 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -3240,7 +3240,8 @@ handle_notify_request(pcmk__request_t *request) if (flag_name != NULL) { crm_debug("Enabling %s callbacks for client %s", flag_name, pcmk__request_origin(request)); - pcmk__set_client_flags(request->ipc_client, get_stonith_flag(flag_name)); + pcmk__set_client_flags(request->ipc_client, + fenced_parse_notify_flag(flag_name)); } flag_name = crm_element_value(request->xml, PCMK__XA_ST_NOTIFY_DEACTIVATE); @@ -3248,7 +3249,7 @@ handle_notify_request(pcmk__request_t *request) crm_debug("Disabling %s callbacks for client %s", flag_name, pcmk__request_origin(request)); pcmk__clear_client_flags(request->ipc_client, - get_stonith_flag(flag_name)); + fenced_parse_notify_flag(flag_name)); } pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index b72204870bd..7bcfa894f44 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -252,24 +252,31 @@ do_local_reply(const xmlNode *notify_src, pcmk__client_t *client, } } -uint64_t -get_stonith_flag(const char *name) +/*! + * \internal + * \brief Parse a fencer client notification type string to a flag + * + * \param[in] type Notification type string + * + * \return Flag corresponding to \p type, or \c fenced_nf_none if none exists + */ +enum fenced_notify_flags +fenced_parse_notify_flag(const char *type) { - if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_FENCE, pcmk__str_none)) { + if (pcmk__str_eq(type, PCMK__VALUE_ST_NOTIFY_FENCE, pcmk__str_none)) { return fenced_nf_fence_result; - - } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_ADD, pcmk__str_casei)) { + } + if (pcmk__str_eq(type, STONITH_OP_DEVICE_ADD, pcmk__str_none)) { return fenced_nf_device_registered; - - } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_DEL, pcmk__str_casei)) { + } + if (pcmk__str_eq(type, STONITH_OP_DEVICE_DEL, pcmk__str_none)) { return fenced_nf_device_removed; - - } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY, - pcmk__str_none)) { + } + if (pcmk__str_eq(type, PCMK__VALUE_ST_NOTIFY_HISTORY, pcmk__str_none)) { return fenced_nf_history_changed; - - } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY_SYNCED, - pcmk__str_none)) { + } + if (pcmk__str_eq(type, PCMK__VALUE_ST_NOTIFY_HISTORY_SYNCED, + pcmk__str_none)) { return fenced_nf_history_synced; } return fenced_nf_none; @@ -294,7 +301,7 @@ stonith_notify_client(gpointer key, gpointer value, gpointer user_data) return; } - if (pcmk_is_set(client->flags, get_stonith_flag(type))) { + if (pcmk_is_set(client->flags, fenced_parse_notify_flag(type))) { int rc = pcmk__ipc_send_xml(client, 0, update_msg, crm_ipc_server_event); diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 8f48ae4329f..f70628a6431 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -125,6 +125,8 @@ enum fenced_notify_flags { fenced_nf_history_synced = (UINT32_C(1) << 4), }; +enum fenced_notify_flags fenced_parse_notify_flag(const char *type); + typedef struct { char *id; char *agent; @@ -307,8 +309,6 @@ void init_stonith_remote_op_hash_table(GHashTable **table); void free_metadata_cache(void); void fenced_unregister_handlers(void); -uint64_t get_stonith_flag(const char *name); - void stonith_command(pcmk__client_t *client, uint32_t id, uint32_t flags, xmlNode *op_request, const char *remote_peer); From fc181200800791e5b31f446a6f83dd63fe746adb Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 10 Apr 2025 00:23:21 -0700 Subject: [PATCH 25/75] Refactor: fencer: Drop notifications for topology level add/remove These were never hooked up. No internal client tries to register for these notifications. If an external client tried (via stonith_api_operations_t:register_notification), it would be a no-op. fenced_parse_notify_flag() (previously get_stonith_flag()) returns the 0 flag for these notification type strings. So the "client gets notified for this type of event" bit could never get set. We could fix it, since some amount of work was done to set this up. However, if nothing internal needs it, I figure we might as well drop it. Signed-off-by: Reid Wahl --- daemons/fenced/fenced_cib.c | 10 ++------ daemons/fenced/fenced_commands.c | 39 +++++++++---------------------- daemons/fenced/pacemaker-fenced.c | 5 ++-- daemons/fenced/pacemaker-fenced.h | 6 ++--- 4 files changed, 17 insertions(+), 43 deletions(-) diff --git a/daemons/fenced/fenced_cib.c b/daemons/fenced/fenced_cib.c index a53dca26324..3cc669b3131 100644 --- a/daemons/fenced/fenced_cib.c +++ b/daemons/fenced/fenced_cib.c @@ -70,21 +70,17 @@ node_has_attr(const char *node, const char *name, const char *value) static void add_topology_level(xmlNode *match) { - char *desc = NULL; pcmk__action_result_t result = PCMK__UNKNOWN_RESULT; CRM_CHECK(match != NULL, return); - fenced_register_level(match, &desc, &result); - fenced_send_config_notification(STONITH_OP_LEVEL_ADD, &result, desc); + fenced_register_level(match, &result); pcmk__reset_result(&result); - free(desc); } static void topology_remove_helper(const char *node, int level) { - char *desc = NULL; pcmk__action_result_t result = PCMK__UNKNOWN_RESULT; xmlNode *data = pcmk__xe_create(NULL, PCMK_XE_FENCING_LEVEL); @@ -92,11 +88,9 @@ topology_remove_helper(const char *node, int level) crm_xml_add_int(data, PCMK_XA_INDEX, level); crm_xml_add(data, PCMK_XA_TARGET, node); - fenced_unregister_level(data, &desc, &result); - fenced_send_config_notification(STONITH_OP_LEVEL_DEL, &result, desc); + fenced_unregister_level(data, &result); pcmk__reset_result(&result); pcmk__xml_free(data); - free(desc); } static void diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 2eecfc8f151..8d9c4c5f28b 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1622,14 +1622,13 @@ parse_device_list(const char *devices) * \param[out] mode If not NULL, where to store level kind * \param[out] target If not NULL, where to store representation of target * \param[out] id If not NULL, where to store level number - * \param[out] desc If not NULL, where to store log-friendly level description * * \return Topology level XML from within \p xml, or NULL if not found - * \note The caller is responsible for freeing \p *target and \p *desc if set. + * \note The caller is responsible for freeing \p *target if set. */ static xmlNode * unpack_level_request(xmlNode *xml, enum fenced_target_by *mode, char **target, - int *id, char **desc) + int *id) { enum fenced_target_by local_mode = fenced_target_by_unknown; char *local_target = NULL; @@ -1644,17 +1643,10 @@ unpack_level_request(xmlNode *xml, enum fenced_target_by *mode, char **target, LOG_WARNING); } - if (xml == NULL) { - if (desc != NULL) { - *desc = crm_strdup_printf("missing"); - } - } else { + if (xml != NULL) { local_mode = unpack_level_kind(xml); local_target = stonith_level_key(xml, local_mode); crm_element_value_int(xml, PCMK_XA_INDEX, &local_id); - if (desc != NULL) { - *desc = crm_strdup_printf("%s[%d]", local_target, local_id); - } } if (mode != NULL) { @@ -1683,11 +1675,10 @@ unpack_level_request(xmlNode *xml, enum fenced_target_by *mode, char **target, * the entry's device list for the specified level. * * \param[in] msg XML request for STONITH level registration - * \param[out] desc If not NULL, set to string representation "TARGET[LEVEL]" * \param[out] result Where to set result of registration */ void -fenced_register_level(xmlNode *msg, char **desc, pcmk__action_result_t *result) +fenced_register_level(xmlNode *msg, pcmk__action_result_t *result) { int id = 0; xmlNode *level; @@ -1700,7 +1691,7 @@ fenced_register_level(xmlNode *msg, char **desc, pcmk__action_result_t *result) CRM_CHECK((msg != NULL) && (result != NULL), return); - level = unpack_level_request(msg, &mode, &target, &id, desc); + level = unpack_level_request(msg, &mode, &target, &id); if (level == NULL) { fenced_set_protocol_error(result); return; @@ -1795,12 +1786,10 @@ fenced_register_level(xmlNode *msg, char **desc, pcmk__action_result_t *result) * global topology table. * * \param[in] msg XML request for STONITH level registration - * \param[out] desc If not NULL, set to string representation "TARGET[LEVEL]" * \param[out] result Where to set result of unregistration */ void -fenced_unregister_level(xmlNode *msg, char **desc, - pcmk__action_result_t *result) +fenced_unregister_level(xmlNode *msg, pcmk__action_result_t *result) { int id = -1; stonith_topology_t *tp; @@ -1809,7 +1798,7 @@ fenced_unregister_level(xmlNode *msg, char **desc, CRM_CHECK(result != NULL, return); - level = unpack_level_request(msg, NULL, &target, &id, desc); + level = unpack_level_request(msg, NULL, &target, &id); if (level == NULL) { fenced_set_protocol_error(result); return; @@ -3454,19 +3443,16 @@ handle_device_delete_request(pcmk__request_t *request) static xmlNode * handle_level_add_request(pcmk__request_t *request) { - char *desc = NULL; const char *op = crm_element_value(request->xml, PCMK__XA_ST_OP); if (is_privileged(request->ipc_client, op)) { - fenced_register_level(request->xml, &desc, &request->result); + fenced_register_level(request->xml, &request->result); } else { - unpack_level_request(request->xml, NULL, NULL, NULL, &desc); + unpack_level_request(request->xml, NULL, NULL, NULL); pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, PCMK_EXEC_INVALID, "Unprivileged users must add level via CIB"); } - fenced_send_config_notification(op, &request->result, desc); - free(desc); return fenced_construct_reply(request->xml, NULL, &request->result); } @@ -3474,19 +3460,16 @@ handle_level_add_request(pcmk__request_t *request) static xmlNode * handle_level_delete_request(pcmk__request_t *request) { - char *desc = NULL; const char *op = crm_element_value(request->xml, PCMK__XA_ST_OP); if (is_privileged(request->ipc_client, op)) { - fenced_unregister_level(request->xml, &desc, &request->result); + fenced_unregister_level(request->xml, &request->result); } else { - unpack_level_request(request->xml, NULL, NULL, NULL, &desc); + unpack_level_request(request->xml, NULL, NULL, NULL); pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, PCMK_EXEC_INVALID, "Unprivileged users must delete level via CIB"); } - fenced_send_config_notification(op, &request->result, desc); - free(desc); return fenced_construct_reply(request->xml, NULL, &request->result); } diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index 7bcfa894f44..e1b6e1f6cd8 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -383,9 +383,8 @@ fenced_send_notification(const char *type, const pcmk__action_result_t *result, * \internal * \brief Send notifications for a configuration change to subscribed clients * - * \param[in] op Notification type (\c STONITH_OP_DEVICE_ADD, - * \c STONITH_OP_DEVICE_DEL, \c STONITH_OP_LEVEL_ADD, or - * \c STONITH_OP_LEVEL_DEL) + * \param[in] op Notification type (\c STONITH_OP_DEVICE_ADD or + * \c STONITH_OP_DEVICE_DEL) * \param[in] result Operation result * \param[in] desc Description of what changed (either device ID or string * representation of level diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index f70628a6431..566086f8472 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -317,10 +317,8 @@ int fenced_device_register(const xmlNode *dev, bool from_cib); void stonith_device_remove(const char *id, bool from_cib); char *stonith_level_key(const xmlNode *msg, enum fenced_target_by); -void fenced_register_level(xmlNode *msg, char **desc, - pcmk__action_result_t *result); -void fenced_unregister_level(xmlNode *msg, char **desc, - pcmk__action_result_t *result); +void fenced_register_level(xmlNode *msg, pcmk__action_result_t *result); +void fenced_unregister_level(xmlNode *msg, pcmk__action_result_t *result); stonith_topology_t *find_topology_for_host(const char *host); From b423b60c10a36f289979b3de886b9c6db3f891fd Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 10 Apr 2025 00:36:31 -0700 Subject: [PATCH 26/75] Refactor: fencer: Drop redundant topology add/remove helpers The logic is now simple enough not to merit separate functions. All we have to do is allow fenced_register_level() and fenced_unregister_level() to accept a NULL result argument. pcmk__set_result() and related functions accept a NULL argument. Signed-off-by: Reid Wahl --- daemons/fenced/fenced_cib.c | 43 ++++++++++---------------------- daemons/fenced/fenced_commands.c | 8 +++--- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/daemons/fenced/fenced_cib.c b/daemons/fenced/fenced_cib.c index 3cc669b3131..e76b25aeef8 100644 --- a/daemons/fenced/fenced_cib.c +++ b/daemons/fenced/fenced_cib.c @@ -67,44 +67,27 @@ node_has_attr(const char *node, const char *name, const char *value) return (match != NULL); } -static void -add_topology_level(xmlNode *match) -{ - pcmk__action_result_t result = PCMK__UNKNOWN_RESULT; - - CRM_CHECK(match != NULL, return); - - fenced_register_level(match, &result); - pcmk__reset_result(&result); -} - -static void -topology_remove_helper(const char *node, int level) -{ - pcmk__action_result_t result = PCMK__UNKNOWN_RESULT; - xmlNode *data = pcmk__xe_create(NULL, PCMK_XE_FENCING_LEVEL); - - crm_xml_add(data, PCMK__XA_ST_ORIGIN, __func__); - crm_xml_add_int(data, PCMK_XA_INDEX, level); - crm_xml_add(data, PCMK_XA_TARGET, node); - - fenced_unregister_level(data, &result); - pcmk__reset_result(&result); - pcmk__xml_free(data); -} - static void remove_topology_level(xmlNode *match) { int index = 0; char *key = NULL; + xmlNode *data = NULL; CRM_CHECK(match != NULL, return); key = stonith_level_key(match, fenced_target_by_unknown); crm_element_value_int(match, PCMK_XA_INDEX, &index); - topology_remove_helper(key, index); + + data = pcmk__xe_create(NULL, PCMK_XE_FENCING_LEVEL); + crm_xml_add(data, PCMK__XA_ST_ORIGIN, __func__); + crm_xml_add(data, PCMK_XA_TARGET, key); + crm_xml_add_int(data, PCMK_XA_INDEX, index); + + fenced_unregister_level(data, NULL); + free(key); + pcmk__xml_free(data); } static void @@ -119,7 +102,7 @@ register_fencing_topology(xmlXPathObjectPtr xpathObj) continue; } remove_topology_level(match); - add_topology_level(match); + fenced_register_level(match, NULL); } } @@ -446,7 +429,7 @@ update_fencing_topology(const char *event, xmlNode *msg) } if (strcmp(op, PCMK_VALUE_CREATE) == 0) { - add_topology_level(change->children); + fenced_register_level(change->children, NULL); } else if (strcmp(op, PCMK_VALUE_MODIFY) == 0) { xmlNode *match = pcmk__xe_first_child(change, @@ -455,7 +438,7 @@ update_fencing_topology(const char *event, xmlNode *msg) if (match != NULL) { remove_topology_level(match->children); - add_topology_level(match->children); + fenced_register_level(match->children, NULL); } } continue; diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 8d9c4c5f28b..5a332e0b36a 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1675,7 +1675,7 @@ unpack_level_request(xmlNode *xml, enum fenced_target_by *mode, char **target, * the entry's device list for the specified level. * * \param[in] msg XML request for STONITH level registration - * \param[out] result Where to set result of registration + * \param[out] result Where to set result of registration (can be \c NULL) */ void fenced_register_level(xmlNode *msg, pcmk__action_result_t *result) @@ -1689,7 +1689,7 @@ fenced_register_level(xmlNode *msg, pcmk__action_result_t *result) stonith_key_value_t *dIter = NULL; stonith_key_value_t *devices = NULL; - CRM_CHECK((msg != NULL) && (result != NULL), return); + CRM_CHECK(msg != NULL, return); level = unpack_level_request(msg, &mode, &target, &id); if (level == NULL) { @@ -1786,7 +1786,7 @@ fenced_register_level(xmlNode *msg, pcmk__action_result_t *result) * global topology table. * * \param[in] msg XML request for STONITH level registration - * \param[out] result Where to set result of unregistration + * \param[out] result Where to set result of unregistration (can be \c NULL) */ void fenced_unregister_level(xmlNode *msg, pcmk__action_result_t *result) @@ -1796,8 +1796,6 @@ fenced_unregister_level(xmlNode *msg, pcmk__action_result_t *result) char *target; xmlNode *level = NULL; - CRM_CHECK(result != NULL, return); - level = unpack_level_request(msg, NULL, &target, &id); if (level == NULL) { fenced_set_protocol_error(result); From f2f7a359855d674d89a95284fd841b34ff8337f0 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 10 Apr 2025 00:41:03 -0700 Subject: [PATCH 27/75] Refactor: fencer: Move fenced_set_protocol_error() out of header And rename accordingly Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 29 +++++++++++++++++++++-------- daemons/fenced/pacemaker-fenced.h | 7 ------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 5a332e0b36a..5f23b7b751f 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -117,6 +117,19 @@ typedef struct { static xmlNode *construct_async_reply(const async_command_t *cmd, const pcmk__action_result_t *result); +/*! + * \internal + * \brief Set a bad fencer API request error in a result object + * + * \param[out] result Result to set + */ +static inline void +set_bad_request_result(pcmk__action_result_t *result) +{ + pcmk__set_result(result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID, + "Fencer API request missing required information (bug?)"); +} + /*! * \internal * \brief Check whether the fencer's device table contains a watchdog device @@ -1693,7 +1706,7 @@ fenced_register_level(xmlNode *msg, pcmk__action_result_t *result) level = unpack_level_request(msg, &mode, &target, &id); if (level == NULL) { - fenced_set_protocol_error(result); + set_bad_request_result(result); return; } @@ -1798,7 +1811,7 @@ fenced_unregister_level(xmlNode *msg, pcmk__action_result_t *result) level = unpack_level_request(msg, NULL, &target, &id); if (level == NULL) { - fenced_set_protocol_error(result); + set_bad_request_result(result); return; } @@ -1916,7 +1929,7 @@ execute_agent_action(xmlNode *msg, pcmk__action_result_t *result) crm_info("Malformed API action request: device %s, action %s", (id? id : "not specified"), (action? action : "not specified")); - fenced_set_protocol_error(result); + set_bad_request_result(result); return; } @@ -1962,7 +1975,7 @@ execute_agent_action(xmlNode *msg, pcmk__action_result_t *result) cmd = create_async_command(msg); if (cmd == NULL) { crm_log_xml_warn(msg, "invalid"); - fenced_set_protocol_error(result); + set_bad_request_result(result); return; } @@ -2857,7 +2870,7 @@ fence_locally(xmlNode *msg, pcmk__action_result_t *result) cmd = create_async_command(msg); if (cmd == NULL) { crm_log_xml_warn(msg, "invalid"); - fenced_set_protocol_error(result); + set_bad_request_result(result); return; } @@ -3262,7 +3275,7 @@ handle_relay_request(pcmk__request_t *request) crm_element_value(dev, PCMK__XA_ST_TARGET)); if (initiate_remote_stonith_op(NULL, request->xml, FALSE) == NULL) { - fenced_set_protocol_error(&request->result); + set_bad_request_result(&request->result); return fenced_construct_reply(request->xml, NULL, &request->result); } @@ -3289,7 +3302,7 @@ handle_fence_request(pcmk__request_t *request) NULL); break; default: - fenced_set_protocol_error(&request->result); + set_bad_request_result(&request->result); break; } @@ -3356,7 +3369,7 @@ handle_fence_request(pcmk__request_t *request) } else if (initiate_remote_stonith_op(request->ipc_client, request->xml, FALSE) == NULL) { - fenced_set_protocol_error(&request->result); + set_bad_request_result(&request->result); } else { pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_PENDING, diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 566086f8472..23a9b032359 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -377,13 +377,6 @@ const char *fenced_get_local_node(void); void fenced_scheduler_cleanup(void); void fenced_scheduler_run(xmlNode *cib); -static inline void -fenced_set_protocol_error(pcmk__action_result_t *result) -{ - pcmk__set_result(result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID, - "Fencer API request missing required information (bug?)"); -} - /*! * \internal * \brief Get the device flag to use with a given action when searching devices From af96b65e29426abee7b8b2d4fa699a0cd8173b27 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 10 Apr 2025 22:39:52 -0700 Subject: [PATCH 28/75] API: libstonithd: Deprecate stonith_t and struct stonith_s There are no known external callers. Any externally relevant functionality should either already exist in libpacemaker or be added there. The libstonithd fencing API should be for internal use by other low-level libraries. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 3ae63885730..965fce613eb 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2024 the Pacemaker project contributors + * Copyright 2004-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -139,6 +139,7 @@ typedef struct stonith_history_s { char *exit_reason; } stonith_history_t; +// @TODO Keep this typedef but rename it and make it internal typedef struct stonith_s stonith_t; typedef struct stonith_event_s { @@ -566,6 +567,11 @@ typedef struct stonith_api_operations_s } stonith_api_operations_t; +// @TODO Keep this object but make it internal +/*! + * \brief Fencer API connection object + * \deprecated Use appropriate functions in libpacemaker instead + */ struct stonith_s { enum stonith_state state; int call_id; From 453a39bb08130bddda6976d64917189b5c0d91f6 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 10 Apr 2025 22:45:09 -0700 Subject: [PATCH 29/75] API: libstonithd: Deprecate enum stonith_state There are no known external users. Any externally relevant functionality should either already exist in libpacemaker or be added there. The libstonithd fencing API should be for internal use by other low-level libraries. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 965fce613eb..59bb10e20c1 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -32,7 +32,11 @@ extern "C" { # include // uint32_t # include // time_t -/* *INDENT-OFF* */ +// @TODO Keep this definition but make it internal +/*! + * \brief Fencer API connection state + * \deprecated Do not use + */ enum stonith_state { stonith_connected_command, stonith_connected_query, @@ -578,7 +582,6 @@ struct stonith_s { void *st_private; stonith_api_operations_t *cmds; }; -/* *INDENT-ON* */ /* Core functions */ stonith_t *stonith_api_new(void); From 8d2cf7156683ac39eed0b0d4c7b271b89e532222 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 10 Apr 2025 22:42:34 -0700 Subject: [PATCH 30/75] API: libstonithd: Deprecate stonith_api_operations_t ...and struct stonith_api_operations_s, and all of its members. There are no known external users. Any externally relevant functionality should either already exist in libpacemaker or be added there. The libstonithd fencing API should be for internal use by other low-level libraries. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 59bb10e20c1..7c1ec906988 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -173,12 +173,17 @@ typedef struct stonith_callback_data_s { void *opaque; } stonith_callback_data_t; -typedef struct stonith_api_operations_s -{ +// @TODO Keep this object but make it internal +/*! + * \brief Fencer API operations + * \deprecated Use appropriate functions in libpacemaker instead + */ +typedef struct stonith_api_operations_s { /*! * \brief Destroy a fencer connection * * \param[in,out] st Fencer connection to destroy + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*free) (stonith_t *st); @@ -191,6 +196,7 @@ typedef struct stonith_api_operations_s * store IPC file descriptor here * * \return Legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*connect) (stonith_t *st, const char *name, int *stonith_fd); @@ -200,6 +206,7 @@ typedef struct stonith_api_operations_s * \param[in,out] st Fencer connection to disconnect * * \return Legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*disconnect)(stonith_t *st); @@ -212,6 +219,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*remove_device)(stonith_t *st, int options, const char *name); @@ -230,6 +238,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*register_device)(stonith_t *st, int options, const char *id, const char *namespace_s, const char *agent, @@ -245,6 +254,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*remove_level)(stonith_t *st, int options, const char *node, int level); @@ -260,6 +270,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*register_level)(stonith_t *st, int options, const char *node, int level, const stonith_key_value_t *device_list); @@ -280,6 +291,7 @@ typedef struct stonith_api_operations_s * * \return Legacy Pacemaker return code * \note The caller is responsible for freeing *output using free(). + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*metadata)(stonith_t *stonith, int call_options, const char *agent, const char *namespace_s, char **output, int timeout_sec); @@ -301,6 +313,7 @@ typedef struct stonith_api_operations_s * \return Number of items in list on success, or negative errno otherwise * \note The caller is responsible for freeing the returned list with * stonith_key_value_freeall(). + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*list_agents)(stonith_t *stonith, int call_options, const char *namespace_s, stonith_key_value_t **devices, @@ -317,6 +330,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*list)(stonith_t *stonith, int call_options, const char *id, char **list_info, int timeout); @@ -331,6 +345,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*monitor)(stonith_t *stonith, int call_options, const char *id, int timeout); @@ -346,6 +361,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*status)(stonith_t *stonith, int call_options, const char *id, const char *port, int timeout); @@ -363,6 +379,7 @@ typedef struct stonith_api_operations_s * will be returned. * * \return Number of items in list on success, or negative errno otherwise + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*query)(stonith_t *stonith, int call_options, const char *target, stonith_key_value_t **devices, int timeout); @@ -381,6 +398,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*fence)(stonith_t *stonith, int call_options, const char *node, const char *action, int timeout, int tolerance); @@ -394,6 +412,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*confirm)(stonith_t *stonith, int call_options, const char *target); @@ -407,6 +426,7 @@ typedef struct stonith_api_operations_s * \param[in] timeout Error if unable to complete within this * * \return Legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*history)(stonith_t *stonith, int call_options, const char *node, stonith_history_t **history, int timeout); @@ -419,6 +439,7 @@ typedef struct stonith_api_operations_s * \param[in] callback Callback to register * * \return Legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*register_notification)(stonith_t *stonith, const char *event, void (*callback)(stonith_t *st, @@ -431,6 +452,7 @@ typedef struct stonith_api_operations_s * \param[in] event Event to unregister callbacks for (NULL for all) * * \return Legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*remove_notification)(stonith_t *stonith, const char *event); @@ -450,6 +472,7 @@ typedef struct stonith_api_operations_s * * \return \c TRUE on success, \c FALSE if call_id indicates error, * or -EINVAL if \p stonith is not valid + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*register_callback)(stonith_t *stonith, int call_id, int timeout, int options, void *user_data, @@ -466,6 +489,7 @@ typedef struct stonith_api_operations_s * \param[in] all_callbacks If true, unregister all callbacks * * \return pcmk_ok + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*remove_callback)(stonith_t *stonith, int call_id, bool all_callbacks); @@ -489,6 +513,7 @@ typedef struct stonith_api_operations_s * on success, otherwise a negative legacy Pacemaker return code * \note The caller should set only one of \p node, \p pattern, or \p attr * and \p value. + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*remove_level_full)(stonith_t *st, int options, const char *node, const char *pattern, @@ -516,6 +541,7 @@ typedef struct stonith_api_operations_s * on success, otherwise a negative legacy Pacemaker return code * * \note The caller should set only one of node, pattern or attr/value. + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*register_level_full)(stonith_t *st, int options, const char *node, const char *pattern, @@ -541,6 +567,7 @@ typedef struct stonith_api_operations_s * \return pcmk_ok if validation succeeds, -errno otherwise * \note If pcmk_ok is returned, the caller is responsible for freeing * the output (if requested) with free(). + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*validate)(stonith_t *st, int call_options, const char *rsc_id, const char *namespace_s, const char *agent, @@ -564,6 +591,7 @@ typedef struct stonith_api_operations_s * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*fence_with_delay)(stonith_t *stonith, int call_options, const char *node, const char *action, int timeout, From dd6519b52ef57bfe6be7f3261796a84df287932a Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 00:17:29 -0700 Subject: [PATCH 31/75] Refactor: libstonithd: New stonith__api_new() To replace stonith_api_new() Signed-off-by: Reid Wahl --- daemons/controld/controld_fencing.c | 2 +- daemons/execd/pacemaker-execd.c | 5 +++-- daemons/fenced/cts-fence-helper.c | 4 ++-- daemons/fenced/fenced_commands.c | 2 +- include/crm/fencing/internal.h | 2 ++ lib/fencing/st_client.c | 25 ++++++++++++++++++------- lib/lrmd/lrmd_client.c | 4 ++-- lib/pacemaker/pcmk_setup.c | 4 ++-- lib/pacemaker/pcmk_status.c | 2 +- tools/crm_mon.c | 4 ++-- tools/stonith_admin.c | 2 +- 11 files changed, 35 insertions(+), 21 deletions(-) diff --git a/daemons/controld/controld_fencing.c b/daemons/controld/controld_fencing.c index 4304ae799eb..a5a10359e00 100644 --- a/daemons/controld/controld_fencing.c +++ b/daemons/controld/controld_fencing.c @@ -661,7 +661,7 @@ controld_timer_fencer_connect(gpointer user_data) int rc = pcmk_ok; if (stonith_api == NULL) { - stonith_api = stonith_api_new(); + stonith_api = stonith__api_new(); if (stonith_api == NULL) { crm_err("Could not connect to fencer: API memory allocation failed"); return G_SOURCE_REMOVE; diff --git a/daemons/execd/pacemaker-execd.c b/daemons/execd/pacemaker-execd.c index c32f6b26aa2..67f0b7d6e36 100644 --- a/daemons/execd/pacemaker-execd.c +++ b/daemons/execd/pacemaker-execd.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the Pacemaker project contributors + * Copyright 2012-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -22,6 +22,7 @@ #include #include #include +#include // stonith__api_new() #include #include "pacemaker-execd.h" @@ -74,7 +75,7 @@ get_stonith_connection(void) if (stonith_api == NULL) { int rc = pcmk_ok; - stonith_api = stonith_api_new(); + stonith_api = stonith__api_new(); if (stonith_api == NULL) { crm_err("Could not connect to fencer: API memory allocation failed"); return NULL; diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c index 1424a316230..6d6c73a0580 100644 --- a/daemons/fenced/cts-fence-helper.c +++ b/daemons/fenced/cts-fence-helper.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2024 the Pacemaker project contributors + * Copyright 2009-2025 the Pacemaker project contributors * * This source code is licensed under the GNU General Public License version 2 * or later (GPLv2+) WITHOUT ANY WARRANTY. @@ -661,7 +661,7 @@ main(int argc, char **argv) crm_bump_log_level(argc, argv); } - st = stonith_api_new(); + st = stonith__api_new(); if (st == NULL) { exit_code = CRM_EX_DISCONNECT; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 5f23b7b751f..c4032584a6e 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -935,7 +935,7 @@ get_agent_metadata(const char *agent, xmlNode ** metadata) init_metadata_cache(); buffer = g_hash_table_lookup(metadata_cache, agent); if (buffer == NULL) { - stonith_t *st = stonith_api_new(); + stonith_t *st = stonith__api_new(); int rc; if (st == NULL) { diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 0e2b311ff2a..cbbddca12a6 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -21,6 +21,8 @@ extern "C" { #endif +stonith_t *stonith__api_new(void); + #define stonith__set_call_options(st_call_opts, call_for, flags_to_set) do { \ st_call_opts = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ "Fencer call", (call_for), \ diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 0451a966223..b9d522b7514 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -174,7 +174,7 @@ gboolean stonith__watchdog_fencing_enabled_for_node_api(stonith_t *st, const char *node) { gboolean rv = FALSE; - stonith_t *stonith_api = st?st:stonith_api_new(); + stonith_t *stonith_api = (st != NULL)? st : stonith__api_new(); char *list = NULL; if(stonith_api) { @@ -1858,8 +1858,15 @@ stonith_api_validate(stonith_t *st, int call_options, const char *rsc_id, return rc; } +/*! + * \internal + * \brief Create a new fencer API connection object + * + * \return Newly allocated fencer API connection object, or \c NULL on + * allocation failure + */ stonith_t * -stonith_api_new(void) +stonith__api_new(void) { stonith_t *new_stonith = NULL; stonith_private_t *private = NULL; @@ -1891,7 +1898,6 @@ stonith_api_new(void) return NULL; } -/* *INDENT-OFF* */ new_stonith->cmds->free = stonith_api_free; new_stonith->cmds->connect = stonith_api_signon; new_stonith->cmds->disconnect = stonith_api_signoff; @@ -1922,11 +1928,16 @@ stonith_api_new(void) new_stonith->cmds->register_notification = stonith_api_add_notification; new_stonith->cmds->validate = stonith_api_validate; -/* *INDENT-ON* */ return new_stonith; } +stonith_t * +stonith_api_new(void) +{ + return stonith__api_new(); +} + /*! * \brief Make a blocking connection attempt to the fencer * @@ -2005,7 +2016,7 @@ int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off) { int rc = pcmk_ok; - stonith_t *st = stonith_api_new(); + stonith_t *st = stonith__api_new(); const char *action = off? PCMK_ACTION_OFF : PCMK_ACTION_REBOOT; api_log_open(); @@ -2048,7 +2059,7 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) { int rc = pcmk_ok; time_t when = 0; - stonith_t *st = stonith_api_new(); + stonith_t *st = stonith__api_new(); stonith_history_t *history = NULL, *hp = NULL; if (st == NULL) { @@ -2119,7 +2130,7 @@ stonith_agent_exists(const char *agent, int timeout) return rc; } - st = stonith_api_new(); + st = stonith__api_new(); if (st == NULL) { crm_err("Could not list fence agents: API memory allocation failed"); return FALSE; diff --git a/lib/lrmd/lrmd_client.c b/lib/lrmd/lrmd_client.c index 23879814f5c..d8f259d4db9 100644 --- a/lib/lrmd/lrmd_client.c +++ b/lib/lrmd/lrmd_client.c @@ -2060,7 +2060,7 @@ static int stonith_get_metadata(const char *provider, const char *type, char **output) { int rc = pcmk_ok; - stonith_t *stonith_api = stonith_api_new(); + stonith_t *stonith_api = stonith__api_new(); if (stonith_api == NULL) { crm_err("Could not get fence agent meta-data: API memory allocation failed"); @@ -2220,7 +2220,7 @@ static int list_stonith_agents(lrmd_list_t ** resources) { int rc = 0; - stonith_t *stonith_api = stonith_api_new(); + stonith_t *stonith_api = stonith__api_new(); stonith_key_value_t *stonith_resources = NULL; stonith_key_value_t *dIter = NULL; diff --git a/lib/pacemaker/pcmk_setup.c b/lib/pacemaker/pcmk_setup.c index 42dd3f7b0ce..9267593d3f6 100644 --- a/lib/pacemaker/pcmk_setup.c +++ b/lib/pacemaker/pcmk_setup.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 the Pacemaker project contributors + * Copyright 2024-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -103,7 +103,7 @@ pcmk__setup_output_fencing(pcmk__output_t **out, stonith_t **st, xmlNode **xml) return rc; } - *st = stonith_api_new(); + *st = stonith__api_new(); if (*st == NULL) { return ENOMEM; } diff --git a/lib/pacemaker/pcmk_status.c b/lib/pacemaker/pcmk_status.c index 6fc1af7a112..4ec8e749ecf 100644 --- a/lib/pacemaker/pcmk_status.c +++ b/lib/pacemaker/pcmk_status.c @@ -24,7 +24,7 @@ static stonith_t * fencing_connect(void) { - stonith_t *st = stonith_api_new(); + stonith_t *st = stonith__api_new(); int rc = pcmk_rc_ok; if (st == NULL) { diff --git a/tools/crm_mon.c b/tools/crm_mon.c index c0ad6c47b91..c4f828edf61 100644 --- a/tools/crm_mon.c +++ b/tools/crm_mon.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2024 the Pacemaker project contributors + * Copyright 2004-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -856,7 +856,7 @@ setup_fencer_connection(void) int rc = pcmk_ok; if (options.fence_connect && st == NULL) { - st = stonith_api_new(); + st = stonith__api_new(); } if (!options.fence_connect || st == NULL || st->state != stonith_disconnected) { diff --git a/tools/stonith_admin.c b/tools/stonith_admin.c index b52e7deeb9e..08b7932f362 100644 --- a/tools/stonith_admin.c +++ b/tools/stonith_admin.c @@ -556,7 +556,7 @@ main(int argc, char **argv) out->quiet = args->quiet; - st = stonith_api_new(); + st = stonith__api_new(); if (st == NULL) { rc = -ENOMEM; } else if (!no_connect) { From d97746f0890519bbb6334c2c4135caea41da3c38 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 14:00:34 -0700 Subject: [PATCH 32/75] Doc: libstonithd: Update dlm warning to reflect that it's fixed upstream Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 7c1ec906988..2995a8a1027 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -20,10 +20,14 @@ extern "C" { * \ingroup fencing */ -/* IMPORTANT: DLM source code includes this file directly, without having access - * to other Pacemaker headers on its include path, so this file should *not* - * include any other Pacemaker headers. (DLM might be updated to avoid the - * issue, but we should still follow this guideline for a long time after.) +/* IMPORTANT: dlm source code includes this file directly. Until dlm v4.2.0 + * (commit 5afd9fdc), dlm did not have access to other Pacemaker headers on its + * include path. This file should *not* include any other Pacemaker headers + * until we decide that we no longer need to support dlm versions older than + * v4.2.0. + * + * @COMPAT Remove this restriction and take any opportunities to simplify code + * when possible. */ # include From 9cfbb35558ed116fbd4dc809705f954e56ae5c0a Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 00:07:58 -0700 Subject: [PATCH 33/75] API: libstonithd: Deprecate stonith_api_new() See commit 41839177, upon which this is based. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 13 ++++++++++++- lib/fencing/st_client.c | 22 ++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 2995a8a1027..9abcdcf3350 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -616,7 +616,6 @@ struct stonith_s { }; /* Core functions */ -stonith_t *stonith_api_new(void); void stonith_api_delete(stonith_t * st); void stonith_dump_pending_callbacks(stonith_t * st); @@ -749,6 +748,18 @@ bool stonith_agent_exists(const char *agent, int timeout); */ const char *stonith_action_str(const char *action); +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + +/* Normally we'd put this section in a separate file (crm/fencing/compat.h), but + * we can't do that for the reason noted at the top of this file. That does mean + * we have to duplicate these declarations where they're implemented. + */ + +//! \deprecated Use appropriate functions in libpacemaker +stonith_t *stonith_api_new(void); + +#endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + #ifdef __cplusplus } #endif diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index b9d522b7514..f9a66ed93d1 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1932,12 +1932,6 @@ stonith__api_new(void) return new_stonith; } -stonith_t * -stonith_api_new(void) -{ - return stonith__api_new(); -} - /*! * \brief Make a blocking connection attempt to the fencer * @@ -2749,3 +2743,19 @@ stonith__event_description(const stonith_event_t *event) ((reason == NULL)? "" : ")"), pcmk__s(event->id, "(none)")); } + +// Deprecated functions kept only for backward API compatibility +// LCOV_EXCL_START + +// See comments in stonith-ng.h for why we re-declare before defining + +stonith_t *stonith_api_new(void); + +stonith_t * +stonith_api_new(void) +{ + return stonith__api_new(); +} + +// LCOV_EXCL_STOP +// End deprecated API From cd9aef4e234559f959ccbf33dc3724b75a0213a2 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 00:47:25 -0700 Subject: [PATCH 34/75] Refactor: libstonithd: New stonith__api_free() To replace stonith_api_delete() Signed-off-by: Reid Wahl --- daemons/execd/pacemaker-execd.c | 6 +++--- daemons/fenced/cts-fence-helper.c | 8 ++++---- daemons/fenced/fenced_commands.c | 2 +- include/crm/fencing/internal.h | 1 + lib/fencing/st_client.c | 32 +++++++++++++++++++++---------- lib/pacemaker/pcmk_fence.c | 20 +++++++++---------- lib/pacemaker/pcmk_setup.c | 2 +- lib/pacemaker/pcmk_status.c | 4 ++-- tools/crm_mon.c | 6 +++--- tools/stonith_admin.c | 2 +- 10 files changed, 48 insertions(+), 35 deletions(-) diff --git a/daemons/execd/pacemaker-execd.c b/daemons/execd/pacemaker-execd.c index 67f0b7d6e36..ee87d1bb7e3 100644 --- a/daemons/execd/pacemaker-execd.c +++ b/daemons/execd/pacemaker-execd.c @@ -68,7 +68,7 @@ stonith_t * get_stonith_connection(void) { if (stonith_api && stonith_api->state == stonith_disconnected) { - stonith_api_delete(stonith_api); + stonith__api_free(stonith_api); stonith_api = NULL; } @@ -84,7 +84,7 @@ get_stonith_connection(void) if (rc != pcmk_ok) { crm_err("Could not connect to fencer in 10 attempts: %s " QB_XS " rc=%d", pcmk_strerror(rc), rc); - stonith_api_delete(stonith_api); + stonith__api_free(stonith_api); stonith_api = NULL; } else { stonith_api_operations_t *cmds = stonith_api->cmds; @@ -284,7 +284,7 @@ exit_executor(void) crm_info("Terminating with %d client%s", nclients, pcmk__plural_s(nclients)); - stonith_api_delete(stonith_api); + stonith__api_free(stonith_api); if (ipcs) { mainloop_del_ipc_server(ipcs); } diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c index 6d6c73a0580..33f9ce57f26 100644 --- a/daemons/fenced/cts-fence-helper.c +++ b/daemons/fenced/cts-fence-helper.c @@ -160,7 +160,7 @@ passive_test(void) rc = st->cmds->connect(st, crm_system_name, &pollfd.fd); if (rc != pcmk_ok) { - stonith_api_delete(st); + stonith__api_free(st); crm_exit(CRM_EX_DISCONNECT); } st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_DISCONNECT, @@ -323,7 +323,7 @@ sanity_tests(void) rc = st->cmds->connect(st, crm_system_name, &pollfd.fd); if (rc != pcmk_ok) { - stonith_api_delete(st); + stonith__api_free(st); crm_exit(CRM_EX_DISCONNECT); } st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_DISCONNECT, @@ -351,7 +351,7 @@ standard_dev_test(void) rc = st->cmds->connect(st, crm_system_name, &pollfd.fd); if (rc != pcmk_ok) { - stonith_api_delete(st); + stonith__api_free(st); crm_exit(CRM_EX_DISCONNECT); } @@ -606,7 +606,7 @@ test_shutdown(int nsig) crm_info("Disconnect: %d", rc); crm_debug("Destroy"); - stonith_api_delete(st); + stonith__api_free(st); } if (rc) { diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index c4032584a6e..bc24f794cde 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -945,7 +945,7 @@ get_agent_metadata(const char *agent, xmlNode ** metadata) } rc = st->cmds->metadata(st, st_opt_sync_call, agent, NULL, &buffer, 10); - stonith_api_delete(st); + stonith__api_free(st); if (rc || !buffer) { crm_err("Could not retrieve metadata for fencing agent %s", agent); return EAGAIN; diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index cbbddca12a6..b29e5328ced 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -22,6 +22,7 @@ extern "C" { #endif stonith_t *stonith__api_new(void); +void stonith__api_free(stonith_t *stonith_api); #define stonith__set_call_options(st_call_opts, call_for, flags_to_set) do { \ st_call_opts = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index f9a66ed93d1..e0e68f56005 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -219,7 +219,7 @@ stonith__watchdog_fencing_enabled_for_node_api(stonith_t *st, const char *node) } if (!st) { - stonith_api_delete(stonith_api); + stonith__api_free(stonith_api); } } else { crm_err("Stonith-API for watchdog-fencing-query couldn't be created."); @@ -1692,7 +1692,7 @@ stonith_dispatch(stonith_t * st) } static int -stonith_api_free(stonith_t * stonith) +free_stonith_api(stonith_t *stonith) { int rc = pcmk_ok; @@ -1728,10 +1728,7 @@ stonith_api_free(stonith_t * stonith) void stonith_api_delete(stonith_t * stonith) { - crm_trace("Destroying %p", stonith); - if(stonith) { - stonith->cmds->free(stonith); - } + stonith__api_free(stonith); } static gboolean @@ -1898,7 +1895,7 @@ stonith__api_new(void) return NULL; } - new_stonith->cmds->free = stonith_api_free; + new_stonith->cmds->free = free_stonith_api; new_stonith->cmds->connect = stonith_api_signon; new_stonith->cmds->disconnect = stonith_api_signoff; @@ -1932,6 +1929,21 @@ stonith__api_new(void) return new_stonith; } +/*! + * \internal + * \brief Free a fencer API connection object + * + * \param[in,out] stonith_api Fencer API connection object + */ +void +stonith__api_free(stonith_t *stonith_api) +{ + crm_trace("Destroying %p", stonith_api); + if (stonith_api != NULL) { + stonith_api->cmds->free(stonith_api); + } +} + /*! * \brief Make a blocking connection attempt to the fencer * @@ -2044,7 +2056,7 @@ stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off) } } - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -2104,7 +2116,7 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) } } - stonith_api_delete(st); + stonith__api_free(st); if(when) { api_log(LOG_INFO, "Node %u/%s last kicked at: %ld", nodeid, uname, (long int)when); @@ -2139,7 +2151,7 @@ stonith_agent_exists(const char *agent, int timeout) } stonith_key_value_freeall(devices, 1, 1); - stonith_api_delete(st); + stonith__api_free(st); return rc; } diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c index 04e9ee8ad2f..16cf66ec19c 100644 --- a/lib/pacemaker/pcmk_fence.c +++ b/lib/pacemaker/pcmk_fence.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2024 the Pacemaker project contributors + * Copyright 2009-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -246,7 +246,7 @@ pcmk_request_fencing(xmlNodePtr *xml, const char *target, const char *action, pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -346,7 +346,7 @@ pcmk_fence_history(xmlNodePtr *xml, const char *target, unsigned int timeout, pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -390,7 +390,7 @@ pcmk_fence_installed(xmlNodePtr *xml, unsigned int timeout) pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -472,7 +472,7 @@ pcmk_fence_list_targets(xmlNodePtr *xml, const char *device_id, unsigned int tim pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -509,7 +509,7 @@ pcmk_fence_metadata(xmlNodePtr *xml, const char *agent, unsigned int timeout) pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -557,7 +557,7 @@ pcmk_fence_registered(xmlNodePtr *xml, const char *target, unsigned int timeout) pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -585,7 +585,7 @@ pcmk_fence_register_level(xmlNodePtr *xml, const char *target, int fence_level, pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -611,7 +611,7 @@ pcmk_fence_unregister_level(xmlNodePtr *xml, const char *target, int fence_level pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } @@ -646,7 +646,7 @@ pcmk_fence_validate(xmlNodePtr *xml, const char *agent, const char *id, pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); return rc; } diff --git a/lib/pacemaker/pcmk_setup.c b/lib/pacemaker/pcmk_setup.c index 9267593d3f6..80a78c5fb66 100644 --- a/lib/pacemaker/pcmk_setup.c +++ b/lib/pacemaker/pcmk_setup.c @@ -111,7 +111,7 @@ pcmk__setup_output_fencing(pcmk__output_t **out, stonith_t **st, xmlNode **xml) rc = (*st)->cmds->connect(*st, crm_system_name, NULL); if (rc < 0) { rc = pcmk_legacy2rc(rc); - stonith_api_delete(*st); + stonith__api_free(*st); return rc; } diff --git a/lib/pacemaker/pcmk_status.c b/lib/pacemaker/pcmk_status.c index 4ec8e749ecf..bf76f102625 100644 --- a/lib/pacemaker/pcmk_status.c +++ b/lib/pacemaker/pcmk_status.c @@ -35,7 +35,7 @@ fencing_connect(void) if (rc == pcmk_rc_ok) { return st; } else { - stonith_api_delete(st); + stonith__api_free(st); return NULL; } } @@ -276,7 +276,7 @@ pcmk__status(pcmk__output_t *out, cib_t *cib, done: pcmk_free_scheduler(scheduler); - stonith_api_delete(stonith); + stonith__api_free(stonith); pcmk__xml_free(current_cib); return pcmk_rc_ok; } diff --git a/tools/crm_mon.c b/tools/crm_mon.c index c4f828edf61..ba3cc415de7 100644 --- a/tools/crm_mon.c +++ b/tools/crm_mon.c @@ -880,7 +880,7 @@ setup_fencer_connection(void) mon_st_callback_display); } } else { - stonith_api_delete(st); + stonith__api_free(st); st = NULL; } @@ -931,7 +931,7 @@ setup_cib_connection(void) out->err(out, "Cannot monitor CIB changes; exiting"); cib__clean_up_connection(&cib); - stonith_api_delete(st); + stonith__api_free(st); st = NULL; } } @@ -2120,7 +2120,7 @@ clean_up(crm_exit_t exit_code) } cib__clean_up_connection(&cib); - stonith_api_delete(st); + stonith__api_free(st); free(options.neg_location_prefix); free(options.only_node); free(options.only_rsc); diff --git a/tools/stonith_admin.c b/tools/stonith_admin.c index 08b7932f362..5d7547aba16 100644 --- a/tools/stonith_admin.c +++ b/tools/stonith_admin.c @@ -719,7 +719,7 @@ main(int argc, char **argv) if (st != NULL) { st->cmds->disconnect(st); - stonith_api_delete(st); + stonith__api_free(st); } return exit_code; From 00bd09492a1c8ff502c0929858da82071fcb0a85 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 00:51:07 -0700 Subject: [PATCH 35/75] API: libstonithd: Deprecate stonith_api_delete() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 5 +++-- lib/fencing/st_client.c | 14 ++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 9abcdcf3350..8b41630285a 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -616,8 +616,6 @@ struct stonith_s { }; /* Core functions */ -void stonith_api_delete(stonith_t * st); - void stonith_dump_pending_callbacks(stonith_t * st); bool stonith_dispatch(stonith_t * st); @@ -758,6 +756,9 @@ const char *stonith_action_str(const char *action); //! \deprecated Use appropriate functions in libpacemaker stonith_t *stonith_api_new(void); +//! \deprecated Use appropriate functions in libpacemaker +void stonith_api_delete(stonith_t *stonith); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index e0e68f56005..36e90c80b8e 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1725,12 +1725,6 @@ free_stonith_api(stonith_t *stonith) return rc; } -void -stonith_api_delete(stonith_t * stonith) -{ - stonith__api_free(stonith); -} - static gboolean is_stonith_param(gpointer key, gpointer value, gpointer user_data) { @@ -2769,5 +2763,13 @@ stonith_api_new(void) return stonith__api_new(); } +void stonith_api_delete(stonith_t *stonith); + +void +stonith_api_delete(stonith_t *stonith) +{ + stonith__api_free(stonith); +} + // LCOV_EXCL_STOP // End deprecated API From c42507163992d425fe60f8544c3a9dba6637f4a9 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 00:59:28 -0700 Subject: [PATCH 36/75] API: libstonithd: Deprecate stonith_dump_pending_callbacks() No internal callers and no known external callers Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 5 +++-- lib/fencing/st_client.c | 43 +++++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 8b41630285a..1be44a1f6f8 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -616,8 +616,6 @@ struct stonith_s { }; /* Core functions */ -void stonith_dump_pending_callbacks(stonith_t * st); - bool stonith_dispatch(stonith_t * st); stonith_key_value_t *stonith_key_value_add(stonith_key_value_t * kvp, const char *key, @@ -759,6 +757,9 @@ stonith_t *stonith_api_new(void); //! \deprecated Use appropriate functions in libpacemaker void stonith_api_delete(stonith_t *stonith); +//! \deprecated Do not use +void stonith_dump_pending_callbacks(stonith_t *stonith); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 36e90c80b8e..5a4162ef74f 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1359,26 +1359,6 @@ stonith_api_add_callback(stonith_t * stonith, int call_id, int timeout, int opti return TRUE; } -static void -stonith_dump_pending_op(gpointer key, gpointer value, gpointer user_data) -{ - int call = GPOINTER_TO_INT(key); - stonith_callback_client_t *blob = value; - - crm_debug("Call %d (%s): pending", call, pcmk__s(blob->id, "no ID")); -} - -void -stonith_dump_pending_callbacks(stonith_t * stonith) -{ - stonith_private_t *private = stonith->st_private; - - if (private->stonith_op_callback_table == NULL) { - return; - } - return g_hash_table_foreach(private->stonith_op_callback_table, stonith_dump_pending_op, NULL); -} - /*! * \internal * \brief Get the data section of a fencer notification @@ -2771,5 +2751,28 @@ stonith_api_delete(stonith_t *stonith) stonith__api_free(stonith); } +static void +stonith_dump_pending_op(gpointer key, gpointer value, gpointer user_data) +{ + int call = GPOINTER_TO_INT(key); + stonith_callback_client_t *blob = value; + + crm_debug("Call %d (%s): pending", call, pcmk__s(blob->id, "no ID")); +} + +void stonith_dump_pending_callbacks(stonith_t *stonith); + +void +stonith_dump_pending_callbacks(stonith_t *stonith) +{ + stonith_private_t *private = stonith->st_private; + + if (private->stonith_op_callback_table == NULL) { + return; + } + return g_hash_table_foreach(private->stonith_op_callback_table, + stonith_dump_pending_op, NULL); +} + // LCOV_EXCL_STOP // End deprecated API From 066df90789a0fe01731a3eb6e2b2749d0007b352 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 01:58:55 -0700 Subject: [PATCH 37/75] Test: fencer: Drop passive mode from cts-fence-helper Nothing uses it, and I'm not sure if anything has ever used it since it was added by 4cf76806. Signed-off-by: Reid Wahl --- daemons/fenced/cts-fence-helper.c | 32 ------------------------------- 1 file changed, 32 deletions(-) diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c index 33f9ce57f26..b5a5b304463 100644 --- a/daemons/fenced/cts-fence-helper.c +++ b/daemons/fenced/cts-fence-helper.c @@ -44,7 +44,6 @@ typedef void (*mainloop_test_iteration_cb) (int check_event); enum test_modes { test_standard = 0, // test using a specific developer environment - test_passive, // watch notifications only test_api_sanity, // sanity-test stonith client API using fence_dummy test_api_mainloop, // sanity-test mainloop code with async responses }; @@ -61,8 +60,6 @@ mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **e options.mode = test_api_mainloop; } else if (pcmk__str_any_of(option_name, "--api_test", "-t", NULL)) { options.mode = test_api_sanity; - } else if (pcmk__str_any_of(option_name, "--passive", "-p", NULL)) { - options.mode = test_passive; } return TRUE; @@ -77,10 +74,6 @@ static GOptionEntry entries[] = { NULL, NULL, }, - { "passive", 'p', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, mode_cb, - NULL, NULL, - }, - { NULL } }; @@ -153,28 +146,6 @@ st_global_callback(stonith_t * stonith, stonith_callback_data_t * data) pcmk__s(stonith__exit_reason(data), "unspecified reason")); } -static void -passive_test(void) -{ - int rc = 0; - - rc = st->cmds->connect(st, crm_system_name, &pollfd.fd); - if (rc != pcmk_ok) { - stonith__api_free(st); - crm_exit(CRM_EX_DISCONNECT); - } - st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_DISCONNECT, - st_callback); - st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_FENCE, - st_callback); - st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback); - st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback); - st->cmds->register_callback(st, 0, 120, st_opt_timeout_updates, NULL, "st_global_callback", - st_global_callback); - - dispatch_helper(600 * 1000); -} - #define single_test(cmd, str, num_notifications, expected_rc) \ { \ int rc = 0; \ @@ -673,9 +644,6 @@ main(int argc, char **argv) case test_standard: standard_dev_test(); break; - case test_passive: - passive_test(); - break; case test_api_sanity: sanity_tests(); break; From b2b2458bdf5a244967fdbf51c2abf1d232999a40 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 02:12:34 -0700 Subject: [PATCH 38/75] Refactor: libstonithd: New stonith__api_dispatch() To replace stonith_dispatch() Signed-off-by: Reid Wahl --- daemons/fenced/cts-fence-helper.c | 2 +- include/crm/fencing/internal.h | 1 + lib/fencing/st_client.c | 35 +++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c index b5a5b304463..e080700d826 100644 --- a/daemons/fenced/cts-fence-helper.c +++ b/daemons/fenced/cts-fence-helper.c @@ -110,7 +110,7 @@ dispatch_helper(int timeout) while (true) { rc = poll(&pollfd, 1, timeout); /* wait 10 minutes, -1 forever */ if (rc > 0) { - if (!stonith_dispatch(st)) { + if (stonith__api_dispatch(st) != pcmk_rc_ok) { break; } } else { diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index b29e5328ced..18ac7afa920 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -23,6 +23,7 @@ extern "C" { stonith_t *stonith__api_new(void); void stonith__api_free(stonith_t *stonith_api); +int stonith__api_dispatch(stonith_t *stonith_api); #define stonith__set_call_options(st_call_opts, call_for, flags_to_set) do { \ st_call_opts = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 5a4162ef74f..4384e2adad2 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -85,7 +85,6 @@ struct timer_rec_s { typedef int (*stonith_op_t) (const char *, int, const char *, xmlNode *, xmlNode *, xmlNode *, xmlNode **, xmlNode **); -bool stonith_dispatch(stonith_t * st); xmlNode *stonith_create_op(int call_id, const char *token, const char *op, xmlNode * data, int call_options); static int stonith_send_command(stonith_t *stonith, const char *op, @@ -1644,31 +1643,45 @@ stonith_send_command(stonith_t * stonith, const char *op, xmlNode * data, xmlNod return rc; } -/* Not used with mainloop */ -bool -stonith_dispatch(stonith_t * st) +/*! + * \internal + * \brief Process IPC messages for a fencer API connection + * + * This is used for testing purposes in scenarios that don't use a mainloop to + * dispatch messages automatically. + * + * \param[in,out] stonith_api Fencer API connetion object + * + * \return Standard Pacemaker return code + */ +int +stonith__api_dispatch(stonith_t *stonith_api) { - gboolean stay_connected = TRUE; stonith_private_t *private = NULL; - pcmk__assert(st != NULL); - private = st->st_private; + pcmk__assert(stonith_api != NULL); + private = stonith_api->st_private; while (crm_ipc_ready(private->ipc)) { - if (crm_ipc_read(private->ipc) > 0) { const char *msg = crm_ipc_buffer(private->ipc); - stonith_dispatch_internal(msg, strlen(msg), st); + stonith_dispatch_internal(msg, strlen(msg), stonith_api); } if (!crm_ipc_connected(private->ipc)) { crm_err("Connection closed"); - stay_connected = FALSE; + return ENOTCONN; } } - return stay_connected; + return pcmk_rc_ok; +} + +bool +stonith_dispatch(stonith_t *stonith_api) +{ + return (stonith__api_dispatch(stonith_api) == pcmk_rc_ok); } static int From 94af2dea9bd0393afc4207bfb59f5baecbe3c5be Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 02:15:02 -0700 Subject: [PATCH 39/75] API: libstonithd: Deprecate stonith_dispatch() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 5 +++-- lib/fencing/st_client.c | 14 ++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 1be44a1f6f8..de62109423a 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -616,8 +616,6 @@ struct stonith_s { }; /* Core functions */ -bool stonith_dispatch(stonith_t * st); - stonith_key_value_t *stonith_key_value_add(stonith_key_value_t * kvp, const char *key, const char *value); void stonith_key_value_freeall(stonith_key_value_t * kvp, int keys, int values); @@ -760,6 +758,9 @@ void stonith_api_delete(stonith_t *stonith); //! \deprecated Do not use void stonith_dump_pending_callbacks(stonith_t *stonith); +//! \deprecated Do not use +bool stonith_dispatch(stonith_t *stonith_api); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 4384e2adad2..28ac70ba9ba 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1678,12 +1678,6 @@ stonith__api_dispatch(stonith_t *stonith_api) return pcmk_rc_ok; } -bool -stonith_dispatch(stonith_t *stonith_api) -{ - return (stonith__api_dispatch(stonith_api) == pcmk_rc_ok); -} - static int free_stonith_api(stonith_t *stonith) { @@ -2787,5 +2781,13 @@ stonith_dump_pending_callbacks(stonith_t *stonith) stonith_dump_pending_op, NULL); } +bool stonith_dispatch(stonith_t *stonith_api); + +bool +stonith_dispatch(stonith_t *stonith_api) +{ + return (stonith__api_dispatch(stonith_api) == pcmk_rc_ok); +} + // LCOV_EXCL_STOP // End deprecated API From c6d050bc0dff2f334b95d13b3a13cd5c82c18b80 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 17:49:04 -0700 Subject: [PATCH 40/75] Refactor: libstonithd: Drop parse_device_list() Use g_strsplit() instead Signed-off-by: Reid Wahl --- daemons/fenced/fenced_commands.c | 48 +++++++++----------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index bc24f794cde..f70f2c56e73 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1600,33 +1600,6 @@ unpack_level_kind(const xmlNode *level) return fenced_target_by_unknown; } -static stonith_key_value_t * -parse_device_list(const char *devices) -{ - int lpc = 0; - int max = 0; - int last = 0; - stonith_key_value_t *output = NULL; - - if (devices == NULL) { - return output; - } - - max = strlen(devices); - for (lpc = 0; lpc <= max; lpc++) { - if (devices[lpc] == ',' || devices[lpc] == 0) { - char *line = strndup(devices + last, lpc - last); - - output = stonith_key_value_add(output, NULL, line); - free(line); - - last = lpc + 1; - } - } - - return output; -} - /*! * \internal * \brief Unpack essential information from topology request XML @@ -1699,8 +1672,7 @@ fenced_register_level(xmlNode *msg, pcmk__action_result_t *result) char *target; stonith_topology_t *tp; - stonith_key_value_t *dIter = NULL; - stonith_key_value_t *devices = NULL; + const char *value = NULL; CRM_CHECK(msg != NULL, return); @@ -1771,14 +1743,20 @@ fenced_register_level(xmlNode *msg, pcmk__action_result_t *result) tp->target, id); } - devices = parse_device_list(crm_element_value(level, PCMK_XA_DEVICES)); - for (dIter = devices; dIter; dIter = dIter->next) { - const char *device = dIter->value; + value = crm_element_value(level, PCMK_XA_DEVICES); + if (value != NULL) { + /* Empty string and whitespace are not possible with schema validation + * enabled. Don't bother handling them specially here. + */ + gchar **devices = g_strsplit(value, ",", 0); - crm_trace("Adding device '%s' for %s[%d]", device, tp->target, id); - tp->levels[id] = g_list_append(tp->levels[id], pcmk__str_copy(device)); + for (char **dev = devices; (dev != NULL) && (*dev != NULL); dev++) { + crm_trace("Adding device '%s' for %s[%d]", *dev, tp->target, id); + tp->levels[id] = g_list_append(tp->levels[id], + pcmk__str_copy(*dev)); + } + g_strfreev(devices); } - stonith_key_value_freeall(devices, 1, 1); { int nlevels = count_active_levels(tp); From fa93bc9967534dcf4b16d0bf8e1bd2fe88ad6b2b Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 18:35:18 -0700 Subject: [PATCH 41/75] Refactor: libstonithd: New stonith__key_value_add() To replace stonith_key_value_add() Signed-off-by: Reid Wahl --- daemons/execd/execd_commands.c | 2 +- daemons/fenced/cts-fence-helper.c | 53 ++++++++++++++++--------------- daemons/fenced/fenced_scheduler.c | 2 +- include/crm/fencing/internal.h | 3 ++ lib/fencing/st_client.c | 51 ++++++++++++++++++++--------- lib/fencing/st_lha.c | 4 +-- lib/fencing/st_rhcs.c | 2 +- lib/pacemaker/pcmk_fence.c | 2 +- tools/stonith_admin.c | 2 +- 9 files changed, 73 insertions(+), 48 deletions(-) diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c index 0a187a4687a..047af3cc5ac 100644 --- a/daemons/execd/execd_commands.c +++ b/daemons/execd/execd_commands.c @@ -1212,7 +1212,7 @@ execd_stonith_start(stonith_t *stonith_api, const lrmd_rsc_t *rsc, g_hash_table_iter_init(&iter, cmd->params); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { - device_params = stonith_key_value_add(device_params, key, value); + device_params = stonith__key_value_add(device_params, key, value); } } diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c index e080700d826..d05eb09e731 100644 --- a/daemons/fenced/cts-fence-helper.c +++ b/daemons/fenced/cts-fence-helper.c @@ -176,9 +176,9 @@ run_fence_failure_test(void) { stonith_key_value_t *params = NULL; - params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP, - "false_1_node1=1,2 false_1_node2=3,4"); - params = stonith_key_value_add(params, "mode", "fail"); + params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, + "false_1_node1=1,2 false_1_node2=3,4"); + params = stonith__key_value_add(params, "mode", "fail"); single_test(st-> cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_dummy", params), @@ -203,18 +203,18 @@ run_fence_failure_rollover_test(void) { stonith_key_value_t *params = NULL; - params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP, - "false_1_node1=1,2 false_1_node2=3,4"); - params = stonith_key_value_add(params, "mode", "fail"); + params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, + "false_1_node1=1,2 false_1_node2=3,4"); + params = stonith__key_value_add(params, "mode", "fail"); single_test(st-> cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_dummy", params), "Register device1 for rollover test", 1, 0); stonith_key_value_freeall(params, 1, 1); params = NULL; - params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP, - "false_1_node1=1,2 false_1_node2=3,4"); - params = stonith_key_value_add(params, "mode", "pass"); + params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, + "false_1_node1=1,2 false_1_node2=3,4"); + params = stonith__key_value_add(params, "mode", "pass"); single_test(st-> cmds->register_device(st, st_opts, "test-id2", "stonith-ng", "fence_dummy", params), @@ -243,10 +243,11 @@ run_standard_test(void) { stonith_key_value_t *params = NULL; - params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP, - "false_1_node1=1,2 false_1_node2=3,4"); - params = stonith_key_value_add(params, "mode", "pass"); - params = stonith_key_value_add(params, "mock_dynamic_hosts", "false_1_node1 false_1_node2"); + params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, + "false_1_node1=1,2 false_1_node2=3,4"); + params = stonith__key_value_add(params, "mode", "pass"); + params = stonith__key_value_add(params, "mock_dynamic_hosts", + "false_1_node1 false_1_node2"); single_test(st-> cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_dummy", params), @@ -326,8 +327,8 @@ standard_dev_test(void) crm_exit(CRM_EX_DISCONNECT); } - params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP, - "some-host=pcmk-7 true_1_node1=3,4"); + params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, + "some-host=pcmk-7 true_1_node1=3,4"); rc = st->cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_xvm", params); crm_debug("Register: %d", rc); @@ -499,26 +500,26 @@ test_register_async_devices(int check_event) char buf[16] = { 0, }; stonith_key_value_t *params = NULL; - params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP, - "false_1_node1=1,2"); - params = stonith_key_value_add(params, "mode", "fail"); + params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, + "false_1_node1=1,2"); + params = stonith__key_value_add(params, "mode", "fail"); st->cmds->register_device(st, st_opts, "false_1", "stonith-ng", "fence_dummy", params); stonith_key_value_freeall(params, 1, 1); params = NULL; - params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP, - "true_1_node1=1,2"); - params = stonith_key_value_add(params, "mode", "pass"); + params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, + "true_1_node1=1,2"); + params = stonith__key_value_add(params, "mode", "pass"); st->cmds->register_device(st, st_opts, "true_1", "stonith-ng", "fence_dummy", params); stonith_key_value_freeall(params, 1, 1); params = NULL; - params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP, - "custom_timeout_node1=1,2"); - params = stonith_key_value_add(params, "mode", "fail"); - params = stonith_key_value_add(params, "delay", "1000"); + params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, + "custom_timeout_node1=1,2"); + params = stonith__key_value_add(params, "mode", "fail"); + params = stonith__key_value_add(params, "delay", "1000"); snprintf(buf, sizeof(buf) - 1, "%d", MAINLOOP_DEFAULT_TIMEOUT + CUSTOM_TIMEOUT_ADDITION); - params = stonith_key_value_add(params, "pcmk_off_timeout", buf); + params = stonith__key_value_add(params, "pcmk_off_timeout", buf); st->cmds->register_device(st, st_opts, "false_custom_timeout", "stonith-ng", "fence_dummy", params); stonith_key_value_freeall(params, 1, 1); diff --git a/daemons/fenced/fenced_scheduler.c b/daemons/fenced/fenced_scheduler.c index a67fef5c3ab..14e3c7e2b02 100644 --- a/daemons/fenced/fenced_scheduler.c +++ b/daemons/fenced/fenced_scheduler.c @@ -220,7 +220,7 @@ register_if_fencing_device(gpointer data, gpointer user_data) if ((name == NULL) || (value == NULL)) { continue; } - params = stonith_key_value_add(params, name, value); + params = stonith__key_value_add(params, name, value); } xml = create_device_registration_xml(rsc_id, st_namespace_any, agent, diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 18ac7afa920..14d1a6d66b5 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -25,6 +25,9 @@ stonith_t *stonith__api_new(void); void stonith__api_free(stonith_t *stonith_api); int stonith__api_dispatch(stonith_t *stonith_api); +stonith_key_value_t *stonith__key_value_add(stonith_key_value_t *head, + const char *key, const char *value); + #define stonith__set_call_options(st_call_opts, call_for, flags_to_set) do { \ st_call_opts = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ "Fencer call", (call_for), \ diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 28ac70ba9ba..6b6fb7d8127 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -572,13 +572,12 @@ stonith_api_query(stonith_t * stonith, int call_options, const char *target, CRM_LOG_ASSERT(match != NULL); if(match != NULL) { + const char *match_id = crm_element_value(match, PCMK_XA_ID); xmlChar *match_path = xmlGetNodePath(match); crm_info("//*[@" PCMK_XA_AGENT "][%d] = %s", lpc, match_path); free(match_path); - *devices = stonith_key_value_add(*devices, NULL, - crm_element_value(match, - PCMK_XA_ID)); + *devices = stonith__key_value_add(*devices, NULL, match_id); } } @@ -1955,29 +1954,51 @@ stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts) return rc; } +/*! + * \internal + * \brief Append a newly allocated STONITH key-value pair to a list + * + * \param[in,out] head Head of key-value pair list (\c NULL for new list) + * \param[in] key Key to add + * \param[in] value Value to add + * + * \return Head of appended-to list (equal to \p head if \p head is not \c NULL) + * \note The caller is responsible for freeing the return value using + * \c stonith_key_value_freeall(). + */ stonith_key_value_t * -stonith_key_value_add(stonith_key_value_t * head, const char *key, const char *value) +stonith__key_value_add(stonith_key_value_t *head, const char *key, + const char *value) { - stonith_key_value_t *p, *end; + /* @COMPAT Replace this function with pcmk_prepend_nvpair(), and reverse the + * list when finished adding to it; or with a hash table where order does + * not matter + */ + stonith_key_value_t *pair = pcmk__assert_alloc(1, + sizeof(stonith_key_value_t)); - p = pcmk__assert_alloc(1, sizeof(stonith_key_value_t)); - p->key = pcmk__str_copy(key); - p->value = pcmk__str_copy(value); + pair->key = pcmk__str_copy(key); + pair->value = pcmk__str_copy(value); - end = head; - while (end && end->next) { - end = end->next; - } + if (head != NULL) { + stonith_key_value_t *end = head; + + for (; end->next != NULL; end = end->next); + end->next = pair; - if (end) { - end->next = p; } else { - head = p; + head = pair; } return head; } +stonith_key_value_t * +stonith_key_value_add(stonith_key_value_t * head, const char *key, const char *value) +{ + return stonith__key_value_add(head, key, value); +} + void stonith_key_value_freeall(stonith_key_value_t * head, int keys, int values) { diff --git a/lib/fencing/st_lha.c b/lib/fencing/st_lha.c index 7c42c69270a..90bc88015c0 100644 --- a/lib/fencing/st_lha.c +++ b/lib/fencing/st_lha.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2024 the Pacemaker project contributors + * Copyright 2004-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -142,7 +142,7 @@ stonith__list_lha_agents(stonith_key_value_t **devices) for (entry = type_list; entry != NULL && *entry; ++entry) { crm_trace("Added: %s", *entry); - *devices = stonith_key_value_add(*devices, NULL, *entry); + *devices = stonith__key_value_add(*devices, NULL, *entry); count++; } if (type_list && type_free_fn) { diff --git a/lib/fencing/st_rhcs.c b/lib/fencing/st_rhcs.c index d2c5176c0de..04b1c79ab15 100644 --- a/lib/fencing/st_rhcs.c +++ b/lib/fencing/st_rhcs.c @@ -81,7 +81,7 @@ stonith__list_rhcs_agents(stonith_key_value_t **devices) } for (int i = 0; i < file_num; i++) { - *devices = stonith_key_value_add(*devices, NULL, namelist[i]->d_name); + *devices = stonith__key_value_add(*devices, NULL, namelist[i]->d_name); free(namelist[i]); } free(namelist); diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c index 16cf66ec19c..5bc2ce6ec6f 100644 --- a/lib/pacemaker/pcmk_fence.c +++ b/lib/pacemaker/pcmk_fence.c @@ -68,7 +68,7 @@ handle_level(stonith_t *st, const char *target, int fence_level, GList *devices, stonith_key_value_t *kvs = NULL; for (GList *iter = devices; iter != NULL; iter = iter->next) { - kvs = stonith_key_value_add(kvs, NULL, iter->data); + kvs = stonith__key_value_add(kvs, NULL, iter->data); } rc = st->cmds->register_level_full(st, st_opts, node, pattern, name, diff --git a/tools/stonith_admin.c b/tools/stonith_admin.c index 5d7547aba16..fa50d108cb1 100644 --- a/tools/stonith_admin.c +++ b/tools/stonith_admin.c @@ -610,7 +610,7 @@ main(int argc, char **argv) if (options.params != NULL) { g_hash_table_iter_init(&iter, options.params); while (g_hash_table_iter_next(&iter, &key, &val)) { - params = stonith_key_value_add(params, key, val); + params = stonith__key_value_add(params, key, val); } } rc = st->cmds->register_device(st, st_opts, device, NULL, options.agent, From d85dd083b052411b91f10412b69b6f6e41bea5c6 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 18:50:07 -0700 Subject: [PATCH 42/75] API: libstonithd: Deprecate stonith_key_value_add() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 6 ++++-- lib/fencing/st_client.c | 16 ++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index de62109423a..6f0e8d87776 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -616,8 +616,6 @@ struct stonith_s { }; /* Core functions */ -stonith_key_value_t *stonith_key_value_add(stonith_key_value_t * kvp, const char *key, - const char *value); void stonith_key_value_freeall(stonith_key_value_t * kvp, int keys, int values); void stonith_history_free(stonith_history_t *history); @@ -761,6 +759,10 @@ void stonith_dump_pending_callbacks(stonith_t *stonith); //! \deprecated Do not use bool stonith_dispatch(stonith_t *stonith_api); +//! \deprecated Do not use +stonith_key_value_t *stonith_key_value_add(stonith_key_value_t *kvp, + const char *key, const char *value); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 6b6fb7d8127..9bf5c3d8a67 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1993,12 +1993,6 @@ stonith__key_value_add(stonith_key_value_t *head, const char *key, return head; } -stonith_key_value_t * -stonith_key_value_add(stonith_key_value_t * head, const char *key, const char *value) -{ - return stonith__key_value_add(head, key, value); -} - void stonith_key_value_freeall(stonith_key_value_t * head, int keys, int values) { @@ -2810,5 +2804,15 @@ stonith_dispatch(stonith_t *stonith_api) return (stonith__api_dispatch(stonith_api) == pcmk_rc_ok); } +stonith_key_value_t *stonith_key_value_add(stonith_key_value_t *head, + const char *key, const char *value); + +stonith_key_value_t * +stonith_key_value_add(stonith_key_value_t *head, const char *key, + const char *value) +{ + return stonith__key_value_add(head, key, value); +} + // LCOV_EXCL_STOP // End deprecated API From 15be84bd4d4557bb0984c9e4af323b89f0fe111c Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 19:07:16 -0700 Subject: [PATCH 43/75] Refactor: libstonithd: New stonith__key_value_freeall() To replace stonith_key_value_freeall() Signed-off-by: Reid Wahl --- daemons/execd/execd_commands.c | 2 +- daemons/fenced/cts-fence-helper.c | 18 +++++++++--------- daemons/fenced/fenced_scheduler.c | 2 +- include/crm/fencing/internal.h | 2 ++ include/crm/stonith-ng.h | 2 +- lib/fencing/st_client.c | 30 +++++++++++++++++++++++------- lib/lrmd/lrmd_client.c | 2 +- lib/pacemaker/pcmk_fence.c | 6 +++--- tools/stonith_admin.c | 2 +- 9 files changed, 42 insertions(+), 24 deletions(-) diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c index 047af3cc5ac..a59dee23560 100644 --- a/daemons/execd/execd_commands.c +++ b/daemons/execd/execd_commands.c @@ -1226,7 +1226,7 @@ execd_stonith_start(stonith_t *stonith_api, const lrmd_rsc_t *rsc, cmd->rsc_id, rsc->provider, rsc->type, device_params); - stonith_key_value_freeall(device_params, 1, 1); + stonith__key_value_freeall(device_params, true, true); return rc; } diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c index d05eb09e731..5d69f1444bc 100644 --- a/daemons/fenced/cts-fence-helper.c +++ b/daemons/fenced/cts-fence-helper.c @@ -195,7 +195,7 @@ run_fence_failure_test(void) single_test(st->cmds->remove_device(st, st_opts, "test-id1"), "Remove device1 for failure test", 1, 0); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); } static void @@ -210,7 +210,7 @@ run_fence_failure_rollover_test(void) single_test(st-> cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_dummy", params), "Register device1 for rollover test", 1, 0); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); params = NULL; params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, "false_1_node1=1,2 false_1_node2=3,4"); @@ -235,7 +235,7 @@ run_fence_failure_rollover_test(void) single_test(st->cmds->remove_device(st, st_opts, "test-id2"), "Remove device2 for rollover tests", 1, 0); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); } static void @@ -252,7 +252,7 @@ run_standard_test(void) single_test(st-> cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_dummy", params), "Register", 1, 0); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); params = NULL; single_test(st->cmds->list(st, st_opts, "test-id", NULL, 1), @@ -285,7 +285,7 @@ run_standard_test(void) single_test(st->cmds->remove_device(st, st_opts, "test-id"), "Remove test-id", 1, 0); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); } static void @@ -375,7 +375,7 @@ standard_dev_test(void) rc = st->cmds->remove_device(st, st_opts, "test-id"); crm_debug("Remove test-id: %d", rc); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); } static void @@ -504,14 +504,14 @@ test_register_async_devices(int check_event) "false_1_node1=1,2"); params = stonith__key_value_add(params, "mode", "fail"); st->cmds->register_device(st, st_opts, "false_1", "stonith-ng", "fence_dummy", params); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); params = NULL; params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, "true_1_node1=1,2"); params = stonith__key_value_add(params, "mode", "pass"); st->cmds->register_device(st, st_opts, "true_1", "stonith-ng", "fence_dummy", params); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); params = NULL; params = stonith__key_value_add(params, PCMK_STONITH_HOST_MAP, @@ -522,7 +522,7 @@ test_register_async_devices(int check_event) params = stonith__key_value_add(params, "pcmk_off_timeout", buf); st->cmds->register_device(st, st_opts, "false_custom_timeout", "stonith-ng", "fence_dummy", params); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); mainloop_test_done(__func__, true); } diff --git a/daemons/fenced/fenced_scheduler.c b/daemons/fenced/fenced_scheduler.c index 14e3c7e2b02..00a1952c177 100644 --- a/daemons/fenced/fenced_scheduler.c +++ b/daemons/fenced/fenced_scheduler.c @@ -225,7 +225,7 @@ register_if_fencing_device(gpointer data, gpointer user_data) xml = create_device_registration_xml(rsc_id, st_namespace_any, agent, params, rsc_provides); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); pcmk__assert(fenced_device_register(xml, true) == pcmk_rc_ok); pcmk__xml_free(xml); } diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 14d1a6d66b5..b4048e64d09 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -27,6 +27,8 @@ int stonith__api_dispatch(stonith_t *stonith_api); stonith_key_value_t *stonith__key_value_add(stonith_key_value_t *head, const char *key, const char *value); +void stonith__key_value_freeall(stonith_key_value_t *head, bool keys, + bool values); #define stonith__set_call_options(st_call_opts, call_for, flags_to_set) do { \ st_call_opts = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 6f0e8d87776..83ca9eb826c 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -316,7 +316,7 @@ typedef struct stonith_api_operations_s { * * \return Number of items in list on success, or negative errno otherwise * \note The caller is responsible for freeing the returned list with - * stonith_key_value_freeall(). + * \c stonith__key_value_freeall(). * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*list_agents)(stonith_t *stonith, int call_options, diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 9bf5c3d8a67..1df406243b8 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1964,7 +1964,7 @@ stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts) * * \return Head of appended-to list (equal to \p head if \p head is not \c NULL) * \note The caller is responsible for freeing the return value using - * \c stonith_key_value_freeall(). + * \c stonith__key_value_freeall(). */ stonith_key_value_t * stonith__key_value_add(stonith_key_value_t *head, const char *key, @@ -1993,13 +1993,23 @@ stonith__key_value_add(stonith_key_value_t *head, const char *key, return head; } +/*! + * \internal + * \brief Free all items in a \c stonith_key_value_t list + * + * This means freeing the list itself with all of its nodes. Keys and values may + * be freed depending on arguments. + * + * \param[in,out] head Head of list + * \param[in] keys If \c true, free all keys + * \param[in] values If \c true, free all values + */ void -stonith_key_value_freeall(stonith_key_value_t * head, int keys, int values) +stonith__key_value_freeall(stonith_key_value_t *head, bool keys, bool values) { - stonith_key_value_t *p; + while (head != NULL) { + stonith_key_value_t *next = head->next; - while (head) { - p = head->next; if (keys) { free(head->key); } @@ -2007,10 +2017,16 @@ stonith_key_value_freeall(stonith_key_value_t * head, int keys, int values) free(head->value); } free(head); - head = p; + head = next; } } +void +stonith_key_value_freeall(stonith_key_value_t * head, int keys, int values) +{ + stonith__key_value_freeall(head, (keys != 0), (values != 0)); +} + #define api_log_open() openlog("stonith-api", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON) #define api_log(level, fmt, args...) syslog(level, "%s: "fmt, __func__, args) @@ -2146,7 +2162,7 @@ stonith_agent_exists(const char *agent, int timeout) } } - stonith_key_value_freeall(devices, 1, 1); + stonith__key_value_freeall(devices, true, true); stonith__api_free(st); return rc; } diff --git a/lib/lrmd/lrmd_client.c b/lib/lrmd/lrmd_client.c index d8f259d4db9..b0d81bab00c 100644 --- a/lib/lrmd/lrmd_client.c +++ b/lib/lrmd/lrmd_client.c @@ -2239,7 +2239,7 @@ list_stonith_agents(lrmd_list_t ** resources) } } - stonith_key_value_freeall(stonith_resources, 1, 0); + stonith__key_value_freeall(stonith_resources, true, false); return rc; } diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c index 5bc2ce6ec6f..fc389c2e570 100644 --- a/lib/pacemaker/pcmk_fence.c +++ b/lib/pacemaker/pcmk_fence.c @@ -73,7 +73,7 @@ handle_level(stonith_t *st, const char *target, int fence_level, GList *devices, rc = st->cmds->register_level_full(st, st_opts, node, pattern, name, value, fence_level, kvs); - stonith_key_value_freeall(kvs, 0, 1); + stonith__key_value_freeall(kvs, false, true); } else { rc = st->cmds->remove_level_full(st, st_opts, node, pattern, name, value, fence_level); @@ -370,7 +370,7 @@ pcmk__fence_installed(pcmk__output_t *out, stonith_t *st, unsigned int timeout) } out->end_list(out); - stonith_key_value_freeall(devices, 1, 1); + stonith__key_value_freeall(devices, true, true); return pcmk_rc_ok; } @@ -533,7 +533,7 @@ pcmk__fence_registered(pcmk__output_t *out, stonith_t *st, const char *target, } out->end_list(out); - stonith_key_value_freeall(devices, 1, 1); + stonith__key_value_freeall(devices, true, true); /* Return pcmk_rc_ok here, not the number of results. Callers probably * don't care. diff --git a/tools/stonith_admin.c b/tools/stonith_admin.c index fa50d108cb1..bbbd7af0015 100644 --- a/tools/stonith_admin.c +++ b/tools/stonith_admin.c @@ -615,7 +615,7 @@ main(int argc, char **argv) } rc = st->cmds->register_device(st, st_opts, device, NULL, options.agent, params); - stonith_key_value_freeall(params, 1, 1); + stonith__key_value_freeall(params, true, true); rc = pcmk_legacy2rc(rc); if (rc != pcmk_rc_ok) { From 2538786a412782981302863c45c9b9e2f24e36b9 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 19:08:27 -0700 Subject: [PATCH 44/75] API: libstonithd: Deprecate stonith_key_value_freeall() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 5 +++-- lib/fencing/st_client.c | 14 ++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 83ca9eb826c..af7f0a583fb 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -616,8 +616,6 @@ struct stonith_s { }; /* Core functions */ -void stonith_key_value_freeall(stonith_key_value_t * kvp, int keys, int values); - void stonith_history_free(stonith_history_t *history); // Convenience functions @@ -763,6 +761,9 @@ bool stonith_dispatch(stonith_t *stonith_api); stonith_key_value_t *stonith_key_value_add(stonith_key_value_t *kvp, const char *key, const char *value); +//! \deprecated Do not use +void stonith_key_value_freeall(stonith_key_value_t *head, int keys, int values); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 1df406243b8..ec04fc270b8 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -2021,12 +2021,6 @@ stonith__key_value_freeall(stonith_key_value_t *head, bool keys, bool values) } } -void -stonith_key_value_freeall(stonith_key_value_t * head, int keys, int values) -{ - stonith__key_value_freeall(head, (keys != 0), (values != 0)); -} - #define api_log_open() openlog("stonith-api", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON) #define api_log(level, fmt, args...) syslog(level, "%s: "fmt, __func__, args) @@ -2830,5 +2824,13 @@ stonith_key_value_add(stonith_key_value_t *head, const char *key, return stonith__key_value_add(head, key, value); } +void stonith_key_value_freeall(stonith_key_value_t *head, int keys, int values); + +void +stonith_key_value_freeall(stonith_key_value_t *head, int keys, int values) +{ + stonith__key_value_freeall(head, (keys != 0), (values != 0)); +} + // LCOV_EXCL_STOP // End deprecated API From c4545a39a94158415b013050f56833db3e112717 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 19:17:27 -0700 Subject: [PATCH 45/75] Refactor: libstonithd: New stonith__history_free() To replace stonith_history_free() Signed-off-by: Reid Wahl --- daemons/controld/controld_fencing.c | 2 +- include/crm/fencing/internal.h | 1 + lib/fencing/st_client.c | 40 +++++++++++++++++++++-------- lib/pacemaker/pcmk_fence.c | 6 ++--- lib/pacemaker/pcmk_status.c | 2 +- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/daemons/controld/controld_fencing.c b/daemons/controld/controld_fencing.c index a5a10359e00..97adf0551cb 100644 --- a/daemons/controld/controld_fencing.c +++ b/daemons/controld/controld_fencing.c @@ -766,7 +766,7 @@ do_stonith_history_sync(gpointer user_data) stonith_api->cmds->history(stonith_api, st_opt_sync_call | st_opt_broadcast, NULL, &history, 5); - stonith_history_free(history); + stonith__history_free(history); return TRUE; } else { crm_info("Skip triggering stonith history-sync as stonith is disconnected"); diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index b4048e64d09..49ed9175316 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -88,6 +88,7 @@ void stonith__register_messages(pcmk__output_t *out); GList *stonith__parse_targets(const char *hosts); +void stonith__history_free(stonith_history_t *head); const char *stonith__later_succeeded(const stonith_history_t *event, const stonith_history_t *top_history); stonith_history_t *stonith__sort_history(stonith_history_t *history); diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index ec04fc270b8..b33563a2791 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -760,20 +760,38 @@ stonith_api_history(stonith_t * stonith, int call_options, const char *node, return rc; } -void stonith_history_free(stonith_history_t *history) +/*! + * \internal + * \brief Free a list of fencing history objects and all members of each object + * + * \param[in,out] head Head of fencing history object list + */ +void +stonith__history_free(stonith_history_t *head) { - stonith_history_t *hp, *hp_old; - - for (hp = history; hp; hp_old = hp, hp = hp->next, free(hp_old)) { - free(hp->target); - free(hp->action); - free(hp->origin); - free(hp->delegate); - free(hp->client); - free(hp->exit_reason); + /* @COMPAT Drop "next" member of stonith_history_t, use a GList or GSList, + * and use the appropriate free function (while ensuring the members get + * freed) + */ + while (head != NULL) { + stonith_history_t *next = head->next; + + free(head->target); + free(head->action); + free(head->origin); + free(head->delegate); + free(head->client); + free(head->exit_reason); + free(head); + head = next; } } +void stonith_history_free(stonith_history_t *history) +{ + stonith__history_free(history); +} + static gint stonithlib_GCompareFunc(gconstpointer a, gconstpointer b) { @@ -2113,7 +2131,7 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) } } - stonith_history_free(history); + stonith__history_free(history); if(rc == pcmk_ok) { api_log(LOG_INFO, "Found %d entries for %u/%s: %d in progress, %d completed", entries, nodeid, uname, progress, completed); diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c index fc389c2e570..ba701c13e1e 100644 --- a/lib/pacemaker/pcmk_fence.c +++ b/lib/pacemaker/pcmk_fence.c @@ -110,7 +110,7 @@ reduce_fence_history(stonith_history_t *history) || pcmk__str_eq(hp->delegate, np->delegate, pcmk__str_casei))) { /* purge older hp */ - stonith_history_free(hp); + stonith__history_free(hp); break; } } @@ -287,7 +287,7 @@ pcmk__fence_history(pcmk__output_t *out, stonith_t *st, const char *target, if (cleanup) { // Cleanup doesn't return a history list - stonith_history_free(history); + stonith__history_free(history); return pcmk_legacy2rc(rc); } @@ -322,7 +322,7 @@ pcmk__fence_history(pcmk__output_t *out, stonith_t *st, const char *target, out->end_list(out); - stonith_history_free(history); + stonith__history_free(history); return pcmk_legacy2rc(rc); } diff --git a/lib/pacemaker/pcmk_status.c b/lib/pacemaker/pcmk_status.c index bf76f102625..c0052e558a4 100644 --- a/lib/pacemaker/pcmk_status.c +++ b/lib/pacemaker/pcmk_status.c @@ -129,7 +129,7 @@ pcmk__output_cluster_status(pcmk_scheduler_t *scheduler, stonith_t *stonith, g_list_free_full(unames, free); g_list_free_full(resources, free); - stonith_history_free(stonith_history); + stonith__history_free(stonith_history); stonith_history = NULL; return rc; } From d2e80ec8737f6afcd1bbca3be7e4d894f15c1abf Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 19:18:25 -0700 Subject: [PATCH 46/75] API: libstonithd: Deprecate stonith_history_free() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 6 +++--- lib/fencing/st_client.c | 13 ++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index af7f0a583fb..d48a2935f01 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -615,9 +615,6 @@ struct stonith_s { stonith_api_operations_t *cmds; }; -/* Core functions */ -void stonith_history_free(stonith_history_t *history); - // Convenience functions int stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts); @@ -764,6 +761,9 @@ stonith_key_value_t *stonith_key_value_add(stonith_key_value_t *kvp, //! \deprecated Do not use void stonith_key_value_freeall(stonith_key_value_t *head, int keys, int values); +//! \deprecated Do not use +void stonith_history_free(stonith_history_t *head); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index b33563a2791..0b762a9d422 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -787,11 +787,6 @@ stonith__history_free(stonith_history_t *head) } } -void stonith_history_free(stonith_history_t *history) -{ - stonith__history_free(history); -} - static gint stonithlib_GCompareFunc(gconstpointer a, gconstpointer b) { @@ -2850,5 +2845,13 @@ stonith_key_value_freeall(stonith_key_value_t *head, int keys, int values) stonith__key_value_freeall(head, (keys != 0), (values != 0)); } +void stonith_history_free(stonith_history_t *head); + +void +stonith_history_free(stonith_history_t *head) +{ + stonith__history_free(head); +} + // LCOV_EXCL_STOP // End deprecated API From e6893dbe5d89f68db94c04fbe719afe8a783dc7e Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 20:42:38 -0700 Subject: [PATCH 47/75] Refactor: libstonithd: New stonith__api_connect_retry() To replace stonith_api_connect_retry() Signed-off-by: Reid Wahl --- daemons/controld/controld_fencing.c | 6 ++--- daemons/execd/pacemaker-execd.c | 6 ++--- daemons/fenced/cts-fence-helper.c | 4 +-- include/crm/fencing/internal.h | 3 +++ lib/fencing/st_client.c | 39 ++++++++++++++++++----------- lib/pacemaker/pcmk_fence.c | 6 ++--- 6 files changed, 39 insertions(+), 25 deletions(-) diff --git a/daemons/controld/controld_fencing.c b/daemons/controld/controld_fencing.c index 97adf0551cb..51367ca1a70 100644 --- a/daemons/controld/controld_fencing.c +++ b/daemons/controld/controld_fencing.c @@ -675,10 +675,10 @@ controld_timer_fencer_connect(gpointer user_data) if (user_data == NULL) { // Blocking (retry failures now until successful) - rc = stonith_api_connect_retry(stonith_api, crm_system_name, 30); - if (rc != pcmk_ok) { + rc = stonith__api_connect_retry(stonith_api, crm_system_name, 30); + if (rc != pcmk_rc_ok) { crm_err("Could not connect to fencer in 30 attempts: %s " - QB_XS " rc=%d", pcmk_strerror(rc), rc); + QB_XS " rc=%d", pcmk_rc_str(rc), rc); } } else { // Non-blocking (retry failures later in main loop) diff --git a/daemons/execd/pacemaker-execd.c b/daemons/execd/pacemaker-execd.c index ee87d1bb7e3..68daf77bf39 100644 --- a/daemons/execd/pacemaker-execd.c +++ b/daemons/execd/pacemaker-execd.c @@ -80,10 +80,10 @@ get_stonith_connection(void) crm_err("Could not connect to fencer: API memory allocation failed"); return NULL; } - rc = stonith_api_connect_retry(stonith_api, crm_system_name, 10); - if (rc != pcmk_ok) { + rc = stonith__api_connect_retry(stonith_api, crm_system_name, 10); + if (rc != pcmk_rc_ok) { crm_err("Could not connect to fencer in 10 attempts: %s " - QB_XS " rc=%d", pcmk_strerror(rc), rc); + QB_XS " rc=%d", pcmk_rc_str(rc), rc); stonith__api_free(stonith_api); stonith_api = NULL; } else { diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c index 5d69f1444bc..cc83fd32a31 100644 --- a/daemons/fenced/cts-fence-helper.c +++ b/daemons/fenced/cts-fence-helper.c @@ -530,9 +530,9 @@ test_register_async_devices(int check_event) static void try_mainloop_connect(int check_event) { - int rc = stonith_api_connect_retry(st, crm_system_name, 10); + int rc = stonith__api_connect_retry(st, crm_system_name, 10); - if (rc == pcmk_ok) { + if (rc == pcmk_rc_ok) { mainloop_test_done(__func__, true); return; } diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 49ed9175316..0dca71c7ec7 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -25,6 +25,9 @@ stonith_t *stonith__api_new(void); void stonith__api_free(stonith_t *stonith_api); int stonith__api_dispatch(stonith_t *stonith_api); +int stonith__api_connect_retry(stonith_t *stonith, const char *name, + int max_attempts); + stonith_key_value_t *stonith__key_value_add(stonith_key_value_t *head, const char *key, const char *value); void stonith__key_value_freeall(stonith_key_value_t *head, bool keys, diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 0b762a9d422..b3a4b6bcbf3 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1938,35 +1938,46 @@ stonith__api_free(stonith_t *stonith_api) } /*! - * \brief Make a blocking connection attempt to the fencer + * \internal + * \brief Connect to the fencer, retrying on failure * - * \param[in,out] st Fencer API object + * \param[in,out] stonith Fencer API connection object * \param[in] name Client name to use with fencer - * \param[in] max_attempts Return error if this many attempts fail + * \param[in] max_attempts Maximum number of attempts * - * \return pcmk_ok on success, result of last attempt otherwise + * \return \c pcmk_rc_ok on success, or result of last attempt otherwise */ int -stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts) +stonith__api_connect_retry(stonith_t *stonith_api, const char *name, + int max_attempts) { - int rc = -EINVAL; // if max_attempts is not positive + int rc = EINVAL; // if max_attempts is not positive for (int attempt = 1; attempt <= max_attempts; attempt++) { - rc = st->cmds->connect(st, name, NULL); - if (rc == pcmk_ok) { - return pcmk_ok; - } else if (attempt < max_attempts) { - crm_notice("Fencer connection attempt %d of %d failed (retrying in 2s): %s " - QB_XS " rc=%d", - attempt, max_attempts, pcmk_strerror(rc), rc); + rc = stonith_api->cmds->connect(stonith_api, name, NULL); + rc = pcmk_legacy2rc(rc); + + if (rc == pcmk_rc_ok) { + return rc; + } + if (attempt < max_attempts) { + crm_notice("Fencer connection attempt %d of %d failed " + "(retrying in 2s): %s " QB_XS " rc=%d", + attempt, max_attempts, pcmk_rc_str(rc), rc); sleep(2); } } crm_notice("Could not connect to fencer: %s " QB_XS " rc=%d", - pcmk_strerror(rc), rc); + pcmk_rc_str(rc), rc); return rc; } +int +stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts) +{ + return pcmk_rc2legacy(stonith__api_connect_retry(st, name, max_attempts)); +} + /*! * \internal * \brief Append a newly allocated STONITH key-value pair to a list diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c index ba701c13e1e..50df9fb13cc 100644 --- a/lib/pacemaker/pcmk_fence.c +++ b/lib/pacemaker/pcmk_fence.c @@ -154,13 +154,13 @@ async_fence_helper(gpointer user_data) { stonith_t *st = async_fence_data.st; int call_id = 0; - int rc = stonith_api_connect_retry(st, async_fence_data.name, 10); + int rc = stonith__api_connect_retry(st, async_fence_data.name, 10); int timeout = 0; - if (rc != pcmk_ok) { + if (rc != pcmk_rc_ok) { g_main_loop_quit(mainloop); pcmk__set_result(&async_fence_data.result, CRM_EX_ERROR, - PCMK_EXEC_NOT_CONNECTED, pcmk_strerror(rc)); + PCMK_EXEC_NOT_CONNECTED, pcmk_rc_str(rc)); return TRUE; } From 92a79497ae81670622bfe66b8f05cead5774f42e Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 20:45:55 -0700 Subject: [PATCH 48/75] API: libstonithd: Deprecate stonith_api_connect_retry() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 6 ++++-- lib/fencing/st_client.c | 15 +++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index d48a2935f01..2ac26110e70 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -616,8 +616,6 @@ struct stonith_s { }; // Convenience functions -int stonith_api_connect_retry(stonith_t *st, const char *name, - int max_attempts); const char *stonith_op_state_str(enum op_state state); /* Basic helpers that allows nodes to be fenced and the history to be @@ -764,6 +762,10 @@ void stonith_key_value_freeall(stonith_key_value_t *head, int keys, int values); //! \deprecated Do not use void stonith_history_free(stonith_history_t *head); +//! \deprecated Do not use +int stonith_api_connect_retry(stonith_t *st, const char *name, + int max_attempts); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index b3a4b6bcbf3..66894b6f693 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1972,12 +1972,6 @@ stonith__api_connect_retry(stonith_t *stonith_api, const char *name, return rc; } -int -stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts) -{ - return pcmk_rc2legacy(stonith__api_connect_retry(st, name, max_attempts)); -} - /*! * \internal * \brief Append a newly allocated STONITH key-value pair to a list @@ -2864,5 +2858,14 @@ stonith_history_free(stonith_history_t *head) stonith__history_free(head); } +int stonith_api_connect_retry(stonith_t *st, const char *name, + int max_attempts); + +int +stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts) +{ + return pcmk_rc2legacy(stonith__api_connect_retry(st, name, max_attempts)); +} + // LCOV_EXCL_STOP // End deprecated API From a9f1749726a644573aecb324b4f1210909b95ffc Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 20:55:42 -0700 Subject: [PATCH 49/75] Refactor: libstonithd: New stonith__op_state_text() To replace stonith_op_state_str() Signed-off-by: Reid Wahl --- daemons/fenced/fenced_history.c | 8 ++++---- daemons/fenced/fenced_remote.c | 18 +++++++++--------- include/crm/fencing/internal.h | 2 ++ lib/fencing/st_client.c | 32 +++++++++++++++++++++++--------- lib/fencing/st_output.c | 2 +- 5 files changed, 39 insertions(+), 23 deletions(-) diff --git a/daemons/fenced/fenced_history.c b/daemons/fenced/fenced_history.c index 9807a7f38cd..412fbd3e8d1 100644 --- a/daemons/fenced/fenced_history.c +++ b/daemons/fenced/fenced_history.c @@ -344,8 +344,8 @@ stonith_local_history_diff_and_merge(GHashTable *remote_history, crm_debug("Updating outdated pending operation %.8s " "(state=%s) according to the one (state=%s) from " "remote peer history", - op->id, stonith_op_state_str(op->state), - stonith_op_state_str(remote_op->state)); + op->id, stonith__op_state_text(op->state), + stonith__op_state_text(remote_op->state)); g_hash_table_steal(remote_history, op->id); op->id = remote_op->id; @@ -361,8 +361,8 @@ stonith_local_history_diff_and_merge(GHashTable *remote_history, crm_debug("Broadcasting operation %.8s (state=%s) to " "update the outdated pending one " "(state=%s) in remote peer history", - op->id, stonith_op_state_str(op->state), - stonith_op_state_str(remote_op->state)); + op->id, stonith__op_state_text(op->state), + stonith__op_state_text(remote_op->state)); g_hash_table_remove(remote_history, op->id); diff --git a/daemons/fenced/fenced_remote.c b/daemons/fenced/fenced_remote.c index b21163f0b0f..870c1dc75c1 100644 --- a/daemons/fenced/fenced_remote.c +++ b/daemons/fenced/fenced_remote.c @@ -514,7 +514,7 @@ finalize_op_duplicates(remote_fencing_op_t *op, xmlNode *data) crm_err("Skipping duplicate notification for %s@%s " QB_XS " state=%s id=%.8s", other->client_name, other->originator, - stonith_op_state_str(other->state), other->id); + stonith__op_state_text(other->state), other->id); } } } @@ -773,11 +773,11 @@ remote_op_query_timeout(gpointer data) } else if (op->query_results) { // Query succeeded, so attempt the actual fencing crm_debug("Query %.8s targeting %s complete (state=%s)", - op->id, op->target, stonith_op_state_str(op->state)); + op->id, op->target, stonith__op_state_text(op->state)); request_peer_fencing(op, NULL); } else { crm_debug("Query %.8s targeting %s timed out (state=%s)", - op->id, op->target, stonith_op_state_str(op->state)); + op->id, op->target, stonith__op_state_text(op->state)); finalize_timed_out_op(op, "No capable peers replied to device query " "within timeout"); } @@ -1348,7 +1348,7 @@ initiate_remote_stonith_op(const pcmk__client_t *client, xmlNode *request, crm_notice("Requesting peer fencing (%s) targeting %s " QB_XS " id=%.8s state=%s base_timeout=%ds", op->action, op->target, op->id, - stonith_op_state_str(op->state), op->base_timeout); + stonith__op_state_text(op->state), op->base_timeout); } query = stonith_create_op(op->client_callid, op->id, STONITH_OP_QUERY, @@ -1878,7 +1878,7 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) crm_trace("Action %.8s targeting %s for %s is %s", op->id, op->target, op->client_name, - stonith_op_state_str(op->state)); + stonith__op_state_text(op->state)); if ((op->phase == st_phase_on) && (op->devices != NULL)) { /* We are in the "on" phase of a remapped topology reboot. If this @@ -2038,7 +2038,7 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) /* We've exhausted all available peers */ crm_info("No remaining peers capable of fencing (%s) %s for client %s " QB_XS " state=%s", op->action, op->target, op->client_name, - stonith_op_state_str(op->state)); + stonith__op_state_text(op->state)); CRM_CHECK(op->state < st_done, return); finalize_timed_out_op(op, "All nodes failed, or are unable, to " "fence target"); @@ -2063,7 +2063,7 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) crm_info("No peers (out of %d) have devices capable of fencing " "(%s) %s for client %s " QB_XS " state=%s", op->replies, op->action, op->target, op->client_name, - stonith_op_state_str(op->state)); + stonith__op_state_text(op->state)); pcmk__reset_result(&op->result); pcmk__set_result(&op->result, CRM_EX_ERROR, @@ -2084,7 +2084,7 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) crm_info("No peers (out of %d) are capable of fencing (%s) %s " "for client %s " QB_XS " state=%s", op->replies, op->action, op->target, op->client_name, - stonith_op_state_str(op->state)); + stonith__op_state_text(op->state)); } op->state = st_failed; @@ -2434,7 +2434,7 @@ process_remote_stonith_query(xmlNode *msg) crm_info("Discarding query result from %s (%d device%s): " "Operation is %s", peer->host, peer->ndevices, pcmk__plural_s(peer->ndevices), - stonith_op_state_str(op->state)); + stonith__op_state_text(op->state)); } return pcmk_ok; diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 0dca71c7ec7..2811dbcb307 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -147,6 +147,8 @@ gchar *stonith__history_description(const stonith_history_t *event, const char *later_succeeded, uint32_t show_opts); +const char *stonith__op_state_text(enum op_state state); + /*! * \internal * \brief Is a fencing operation in pending state? diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 66894b6f693..b3447bde6a5 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -2419,23 +2419,37 @@ stonith__sort_history(stonith_history_t *history) } /*! - * \brief Return string equivalent of an operation state value + * \internal + * \brief Return string equivalent of a fencing operation state value * * \param[in] state Fencing operation state value * - * \return Human-friendly string equivalent of state + * \return Human-friendly string equivalent of \p state */ const char * -stonith_op_state_str(enum op_state state) +stonith__op_state_text(enum op_state state) { + // @COMPAT Move this to the fencer after dropping stonith_op_state_str() switch (state) { - case st_query: return "querying"; - case st_exec: return "executing"; - case st_done: return "completed"; - case st_duplicate: return "duplicate"; - case st_failed: return "failed"; + case st_query: + return "querying"; + case st_exec: + return "executing"; + case st_done: + return "completed"; + case st_duplicate: + return "duplicate"; + case st_failed: + return "failed"; + default: + return "unknown"; } - return "unknown"; +} + +const char * +stonith_op_state_str(enum op_state state) +{ + return stonith__op_state_text(state); } stonith_history_t * diff --git a/lib/fencing/st_output.c b/lib/fencing/st_output.c index 786f9d5a2dd..f23f59cca7a 100644 --- a/lib/fencing/st_output.c +++ b/lib/fencing/st_output.c @@ -55,7 +55,7 @@ timespec_string(time_t sec, long nsec, bool show_usec) { * \param[in] history Fence history entry to describe * * \return One-word description of history entry state - * \note This is similar to stonith_op_state_str() except user-oriented (i.e. + * \note This is similar to stonith__op_state_text() except user-oriented (i.e., * for cluster status) instead of developer-oriented (for debug logs). */ static const char * From 3a5e87d01f26ea036359fc94029d5712e3184340 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 20:57:34 -0700 Subject: [PATCH 50/75] API: libstonithd: Deprecate stonith_op_state_str() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 6 +++--- lib/fencing/st_client.c | 14 ++++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 2ac26110e70..57da338f668 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -615,9 +615,6 @@ struct stonith_s { stonith_api_operations_t *cmds; }; -// Convenience functions -const char *stonith_op_state_str(enum op_state state); - /* Basic helpers that allows nodes to be fenced and the history to be * queried without mainloop or the caller understanding the full API * @@ -766,6 +763,9 @@ void stonith_history_free(stonith_history_t *head); int stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts); +//! \deprecated Do not use +const char *stonith_op_state_str(enum op_state state); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index b3447bde6a5..19d93954843 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -2446,12 +2446,6 @@ stonith__op_state_text(enum op_state state) } } -const char * -stonith_op_state_str(enum op_state state) -{ - return stonith__op_state_text(state); -} - stonith_history_t * stonith__first_matching_event(stonith_history_t *history, bool (*matching_fn)(stonith_history_t *, void *), @@ -2881,5 +2875,13 @@ stonith_api_connect_retry(stonith_t *st, const char *name, int max_attempts) return pcmk_rc2legacy(stonith__api_connect_retry(st, name, max_attempts)); } +const char *stonith_op_state_str(enum op_state state); + +const char * +stonith_op_state_str(enum op_state state) +{ + return stonith__op_state_text(state); +} + // LCOV_EXCL_STOP // End deprecated API From 8d2f6d791d8d8809558af23e288ded28843bb51f Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 21:15:29 -0700 Subject: [PATCH 51/75] Refactor: libstonithd: New stonith__agent_exists() To replace stonith_agent_exists() Signed-off-by: Reid Wahl --- include/crm/fencing/internal.h | 4 +++ lib/fencing/st_client.c | 50 +++++++++++++++++++++++----------- tools/crm_resource.c | 3 +- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 2811dbcb307..7ebdd66b2c9 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -10,6 +10,8 @@ #ifndef PCMK__CRM_FENCING_INTERNAL__H #define PCMK__CRM_FENCING_INTERNAL__H +#include // bool + #include #include #include @@ -28,6 +30,8 @@ int stonith__api_dispatch(stonith_t *stonith_api); int stonith__api_connect_retry(stonith_t *stonith, const char *name, int max_attempts); +bool stonith__agent_exists(const char *name); + stonith_key_value_t *stonith__key_value_add(stonith_key_value_t *head, const char *key, const char *value); void stonith__key_value_freeall(stonith_key_value_t *head, bool keys, diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 19d93954843..1af68845c96 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -2148,37 +2148,55 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) return when; } +/*! + * \internal + * \brief Check whether a fence agent with a given name exists + * + * \param[in] name Agent name + * + * \retval \c true If a fence agent named \p name exists + * \retval \c false Otherwise + */ bool -stonith_agent_exists(const char *agent, int timeout) +stonith__agent_exists(const char *name) { - stonith_t *st = NULL; - stonith_key_value_t *devices = NULL; - stonith_key_value_t *dIter = NULL; - bool rc = FALSE; + stonith_t *stonith_api = NULL; + stonith_key_value_t *agents = NULL; + bool rc = false; - if (agent == NULL) { - return rc; + if (name == NULL) { + return false; } - st = stonith__api_new(); - if (st == NULL) { + stonith_api = stonith__api_new(); + if (stonith_api == NULL) { crm_err("Could not list fence agents: API memory allocation failed"); - return FALSE; + return false; } - st->cmds->list_agents(st, st_opt_sync_call, NULL, &devices, timeout == 0 ? 120 : timeout); - for (dIter = devices; dIter != NULL; dIter = dIter->next) { - if (pcmk__str_eq(dIter->value, agent, pcmk__str_none)) { - rc = TRUE; + // The list_agents method ignores its timeout argument + stonith_api->cmds->list_agents(stonith_api, st_opt_sync_call, NULL, &agents, + 0); + + for (const stonith_key_value_t *iter = agents; iter != NULL; + iter = iter->next) { + if (pcmk__str_eq(iter->value, name, pcmk__str_none)) { + rc = true; break; } } - stonith__key_value_freeall(devices, true, true); - stonith__api_free(st); + stonith__key_value_freeall(agents, true, true); + stonith__api_free(stonith_api); return rc; } +bool +stonith_agent_exists(const char *agent, int timeout) +{ + return stonith__agent_exists(agent); +} + const char * stonith_action_str(const char *action) { diff --git a/tools/crm_resource.c b/tools/crm_resource.c index e4ee98c3978..162ae406427 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -15,6 +15,7 @@ #include #include #include +#include // stonith__agent_exists() #include #include @@ -1161,7 +1162,7 @@ validate_cmdline_config(void) // Check whether agent exists if (pcmk__str_eq(options.class, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_none)) { - if (!stonith_agent_exists(options.agent, 0)) { + if (!stonith__agent_exists(options.agent)) { g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE, _("%s is not a known stonith agent"), options.agent); return; From 6a6c04321312c339ffe1c57ada3c71f990ede41f Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 21:18:03 -0700 Subject: [PATCH 52/75] API: libstonithd: Deprecate stonith_agent_exists() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 14 +++----------- lib/fencing/st_client.c | 14 ++++++++------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 57da338f668..6ba052e5f46 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -712,17 +712,6 @@ stonith_api_time_helper(uint32_t nodeid, bool in_progress) return (*st_time_fn) (nodeid, NULL, in_progress); } -/** - * Does the given agent describe a stonith resource that can exist? - * - * \param[in] agent What is the name of the agent? - * \param[in] timeout Timeout to use when querying. If 0 is given, - * use a default of 120. - * - * \return A boolean - */ -bool stonith_agent_exists(const char *agent, int timeout); - /*! * \brief Turn fence action into a more readable string * @@ -766,6 +755,9 @@ int stonith_api_connect_retry(stonith_t *st, const char *name, //! \deprecated Do not use const char *stonith_op_state_str(enum op_state state); +//! \deprecated Do not use +bool stonith_agent_exists(const char *agent, int timeout); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 1af68845c96..969ede7c873 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -2191,12 +2191,6 @@ stonith__agent_exists(const char *name) return rc; } -bool -stonith_agent_exists(const char *agent, int timeout) -{ - return stonith__agent_exists(agent); -} - const char * stonith_action_str(const char *action) { @@ -2901,5 +2895,13 @@ stonith_op_state_str(enum op_state state) return stonith__op_state_text(state); } +bool stonith_agent_exists(const char *agent, int timeout); + +bool +stonith_agent_exists(const char *agent, int timeout) +{ + return stonith__agent_exists(agent); +} + // LCOV_EXCL_STOP // End deprecated API From 148751f9e4fa88d91753172ba0d8b42c7550ee7d Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 22:48:54 -0700 Subject: [PATCH 53/75] Refactor: libstonithd: New history_action_text() To replace stonith_action_str() Signed-off-by: Reid Wahl --- lib/fencing/st_output.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/fencing/st_output.c b/lib/fencing/st_output.c index f23f59cca7a..3ce9d013146 100644 --- a/lib/fencing/st_output.c +++ b/lib/fencing/st_output.c @@ -48,6 +48,26 @@ timespec_string(time_t sec, long nsec, bool show_usec) { |(show_usec? crm_time_usecs : 0)); } +/*! + * \internal + * \brief Return a readable string equivalent of a fencing history item's action + * + * \param[in] history Fencing history entry + * + * \return Readable string equivalent of action belonging to \p history + */ +static const char * +history_action_text(const stonith_history_t *history) +{ + if (pcmk__str_eq(history->action, PCMK_ACTION_ON, pcmk__str_none)) { + return "unfencing"; + } + if (pcmk__str_eq(history->action, PCMK_ACTION_OFF, pcmk__str_none)) { + return "turning off"; + } + return pcmk__s(history->action, "fencing"); +} + /*! * \internal * \brief Return a status-friendly description of fence history entry state @@ -98,8 +118,7 @@ stonith__history_description(const stonith_history_t *history, history->completed_nsec, true); } - pcmk__g_strcat(str, - stonith_action_str(history->action), " of ", history->target, + pcmk__g_strcat(str, history_action_text(history), " of ", history->target, NULL); if (!pcmk_is_set(show_opts, pcmk_show_failed_detail)) { From 41268387914d3cce2b8b28da5fa66c0a27b5b372 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 22:49:49 -0700 Subject: [PATCH 54/75] API: libstonithd: Deprecate stonith_action_str() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 10 +++------- lib/fencing/st_client.c | 30 ++++++++++++++++-------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 6ba052e5f46..951472d3c7f 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -712,13 +712,6 @@ stonith_api_time_helper(uint32_t nodeid, bool in_progress) return (*st_time_fn) (nodeid, NULL, in_progress); } -/*! - * \brief Turn fence action into a more readable string - * - * \param[in] action Fence action - */ -const char *stonith_action_str(const char *action); - #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) /* Normally we'd put this section in a separate file (crm/fencing/compat.h), but @@ -758,6 +751,9 @@ const char *stonith_op_state_str(enum op_state state); //! \deprecated Do not use bool stonith_agent_exists(const char *agent, int timeout); +//! \deprecated Do not use +const char *stonith_action_str(const char *action); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 969ede7c873..37655062b32 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -2191,20 +2191,6 @@ stonith__agent_exists(const char *name) return rc; } -const char * -stonith_action_str(const char *action) -{ - if (action == NULL) { - return "fencing"; - } else if (strcmp(action, PCMK_ACTION_ON) == 0) { - return "unfencing"; - } else if (strcmp(action, PCMK_ACTION_OFF) == 0) { - return "turning off"; - } else { - return action; - } -} - /*! * \internal * \brief Parse a target name from one line of a target list string @@ -2903,5 +2889,21 @@ stonith_agent_exists(const char *agent, int timeout) return stonith__agent_exists(agent); } +const char *stonith_action_str(const char *action); + +const char * +stonith_action_str(const char *action) +{ + if (action == NULL) { + return "fencing"; + } else if (strcmp(action, PCMK_ACTION_ON) == 0) { + return "unfencing"; + } else if (strcmp(action, PCMK_ACTION_OFF) == 0) { + return "turning off"; + } else { + return action; + } +} + // LCOV_EXCL_STOP // End deprecated API From 1d0cfbb8cf2fdc9c0476e8a5ba00ebfbfc0a20fb Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 22:53:32 -0700 Subject: [PATCH 55/75] Doc: libstonithd: Document what dlm uses Similar to the many "sbd ... uses this" comments, to ensure that we don't delete anything that dlm depends on. Eventually dlm might use libpacemaker functions or something more sane. However, we'll have to keep these helpers public for a while to support old dlm versions. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 951472d3c7f..21f0fe90e68 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -620,7 +620,7 @@ struct stonith_s { * * At least one of nodeid and uname are required * - * NOTE: DLM uses both of these + * NOTE: dlm (as of at least 4.3.0) uses these (via the helper functions below) */ int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off); time_t stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress); @@ -667,9 +667,11 @@ time_t stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress); #define STONITH_LIBRARY "libstonithd.so.56" +// NOTE: dlm (as of at least 4.3.0) uses these (via the helper functions below) typedef int (*st_api_kick_fn) (int nodeid, const char *uname, int timeout, bool off); typedef time_t (*st_api_time_fn) (int nodeid, const char *uname, bool in_progress); +// NOTE: dlm (as of at least 4.3.0) uses this static inline int stonith_api_kick_helper(uint32_t nodeid, int timeout, bool off) { @@ -693,6 +695,7 @@ stonith_api_kick_helper(uint32_t nodeid, int timeout, bool off) return (*st_kick_fn) (nodeid, NULL, timeout, off); } +// NOTE: dlm (as of at least 4.3.0) uses this static inline time_t stonith_api_time_helper(uint32_t nodeid, bool in_progress) { From e8b2dd70436c4cccddfe8688fb0222efc40efc5c Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 23:08:54 -0700 Subject: [PATCH 56/75] Doc: libstonithd: Flag stonith API methods for later removal These can't go away as long as stonith_api_operations_t is public, but perhaps they can eventually. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 21f0fe90e68..139e173f0a9 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -258,6 +258,7 @@ typedef struct stonith_api_operations_s { * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \note Not used internally * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*remove_level)(stonith_t *st, int options, const char *node, @@ -274,6 +275,7 @@ typedef struct stonith_api_operations_s { * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \note Used only by cts-fence-helper.c internally * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*register_level)(stonith_t *st, int options, const char *node, @@ -365,6 +367,7 @@ typedef struct stonith_api_operations_s { * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \note Used only by cts-fence-helper.c internally * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*status)(stonith_t *stonith, int call_options, const char *id, @@ -402,6 +405,9 @@ typedef struct stonith_api_operations_s { * * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous) * on success, otherwise a negative legacy Pacemaker return code + * \note Used only by cts-fence-helper.c and \c stonith_api_kick() + * internally. The latter might go away eventually if dlm starts using + * \c pcmk_request_fencing(). * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*fence)(stonith_t *stonith, int call_options, const char *node, @@ -493,6 +499,7 @@ typedef struct stonith_api_operations_s { * \param[in] all_callbacks If true, unregister all callbacks * * \return pcmk_ok + * \note Not used internally (but perhaps it should be) * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*remove_callback)(stonith_t *stonith, int call_id, bool all_callbacks); @@ -571,6 +578,7 @@ typedef struct stonith_api_operations_s { * \return pcmk_ok if validation succeeds, -errno otherwise * \note If pcmk_ok is returned, the caller is responsible for freeing * the output (if requested) with free(). + * \note Not used internally * \deprecated \c stonith_api_operations_t is deprecated for external use */ int (*validate)(stonith_t *st, int call_options, const char *rsc_id, From d2cff5d358e5c0b0a475c910c9e22e9c0139c3a5 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 23:16:23 -0700 Subject: [PATCH 57/75] Refactor: libstonithd: New parse_namespace() To replace stonith_text2namespace() Signed-off-by: Reid Wahl --- lib/fencing/st_client.c | 45 ++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 37655062b32..d62d538094a 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -95,32 +95,50 @@ static void stonith_connection_destroy(gpointer user_data); static void stonith_send_notification(gpointer data, gpointer user_data); static int stonith_api_del_notification(stonith_t *stonith, const char *event); + /*! - * \brief Get agent namespace by name + * \internal + * \brief Parse fence agent namespace from a string * * \param[in] namespace_s Name of namespace as string * - * \return Namespace as enum value + * \return enum value parsed from \p namespace_s */ -enum stonith_namespace -stonith_text2namespace(const char *namespace_s) +static enum stonith_namespace +parse_namespace(const char *namespace_s) { if (pcmk__str_eq(namespace_s, "any", pcmk__str_null_matches)) { return st_namespace_any; - - } else if (!strcmp(namespace_s, "redhat") - || !strcmp(namespace_s, "stonith-ng")) { + } + /* @TODO Is "redhat" still necessary except for stonith_text2namespace() + * backward compatibility? + */ + if (pcmk__str_any_of(namespace_s, "redhat", "stonith-ng", NULL)) { return st_namespace_rhcs; - - } else if (!strcmp(namespace_s, "internal")) { + } + if (pcmk__str_eq(namespace_s, "internal", pcmk__str_none)) { return st_namespace_internal; - - } else if (!strcmp(namespace_s, "heartbeat")) { + } + if (pcmk__str_eq(namespace_s, "heartbeat", pcmk__str_none)) { return st_namespace_lha; } return st_namespace_invalid; } + +/*! + * \brief Get agent namespace by name + * + * \param[in] namespace_s Name of namespace as string + * + * \return Namespace as enum value + */ +enum stonith_namespace +stonith_text2namespace(const char *namespace_s) +{ + return parse_namespace(namespace_s); +} + /*! * \brief Get agent namespace name * @@ -336,8 +354,7 @@ stonith_api_register_device(stonith_t *st, int call_options, int rc = 0; xmlNode *data = NULL; - data = create_device_registration_xml(id, - stonith_text2namespace(namespace_s), + data = create_device_registration_xml(id, parse_namespace(namespace_s), agent, params, NULL); rc = stonith_send_command(st, STONITH_OP_DEVICE_ADD, data, NULL, call_options, 0); @@ -483,7 +500,7 @@ stonith_api_device_list(stonith_t *stonith, int call_options, int timeout) { int count = 0; - enum stonith_namespace ns = stonith_text2namespace(namespace_s); + enum stonith_namespace ns = parse_namespace(namespace_s); if (devices == NULL) { crm_err("Parameter error: stonith_api_device_list"); From 3fc5519a314106a24c3de5c46291f3b0a7042a81 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 23:17:31 -0700 Subject: [PATCH 58/75] API: libstonithd: Deprecate stonith_text2namespace() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 4 +++- lib/fencing/st_client.c | 22 ++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 139e173f0a9..2177be4d7e1 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -123,7 +123,6 @@ enum stonith_namespace { st_namespace_lha, // Linux-HA compatible }; -enum stonith_namespace stonith_text2namespace(const char *namespace_s); const char *stonith_namespace2text(enum stonith_namespace st_namespace); enum stonith_namespace stonith_get_namespace(const char *agent, const char *namespace_s); @@ -765,6 +764,9 @@ bool stonith_agent_exists(const char *agent, int timeout); //! \deprecated Do not use const char *stonith_action_str(const char *action); +//! \deprecated Do not use +enum stonith_namespace stonith_text2namespace(const char *namespace_s); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index d62d538094a..1d09232a272 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -125,20 +125,6 @@ parse_namespace(const char *namespace_s) return st_namespace_invalid; } - -/*! - * \brief Get agent namespace by name - * - * \param[in] namespace_s Name of namespace as string - * - * \return Namespace as enum value - */ -enum stonith_namespace -stonith_text2namespace(const char *namespace_s) -{ - return parse_namespace(namespace_s); -} - /*! * \brief Get agent namespace name * @@ -2922,5 +2908,13 @@ stonith_action_str(const char *action) } } +enum stonith_namespace stonith_text2namespace(const char *namespace_s); + +enum stonith_namespace +stonith_text2namespace(const char *namespace_s) +{ + return parse_namespace(namespace_s); +} + // LCOV_EXCL_STOP // End deprecated API From f165ae5de877e66f3d9bd7cc7486eaa6873bd311 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 23:22:19 -0700 Subject: [PATCH 59/75] Refactor: libstonithd: New namespace_text() To replace stonith_namespace2text() Signed-off-by: Reid Wahl --- lib/fencing/st_client.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 1d09232a272..3cd5a1e24b8 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -125,6 +125,31 @@ parse_namespace(const char *namespace_s) return st_namespace_invalid; } +/*! + * \internal + * \brief Get name of a fence agent namespace as a string + * + * \param[in] st_namespace Namespace as enum value + * + * \return Name of \p st_namespace as a string + */ +static const char * +namespace_text(enum stonith_namespace st_namespace) +{ + switch (st_namespace) { + case st_namespace_any: + return "any"; + case st_namespace_rhcs: + return "stonith-ng"; + case st_namespace_internal: + return "internal"; + case st_namespace_lha: + return "heartbeat"; + default: + return "unsupported"; + } +} + /*! * \brief Get agent namespace name * @@ -135,14 +160,7 @@ parse_namespace(const char *namespace_s) const char * stonith_namespace2text(enum stonith_namespace st_namespace) { - switch (st_namespace) { - case st_namespace_any: return "any"; - case st_namespace_rhcs: return "stonith-ng"; - case st_namespace_internal: return "internal"; - case st_namespace_lha: return "heartbeat"; - default: break; - } - return "unsupported"; + return namespace_text(st_namespace); } /*! @@ -317,8 +335,7 @@ create_device_registration_xml(const char *id, enum stonith_namespace standard, crm_xml_add(data, PCMK__XA_ST_ORIGIN, __func__); crm_xml_add(data, PCMK_XA_AGENT, agent); if ((standard != st_namespace_any) && (standard != st_namespace_invalid)) { - crm_xml_add(data, PCMK__XA_NAMESPACE, - stonith_namespace2text(standard)); + crm_xml_add(data, PCMK__XA_NAMESPACE, namespace_text(standard)); } if (rsc_provides) { crm_xml_add(data, PCMK__XA_RSC_PROVIDES, rsc_provides); @@ -524,8 +541,7 @@ stonith_api_device_metadata(stonith_t *stonith, int call_options, timeout_sec = PCMK_DEFAULT_ACTION_TIMEOUT_MS; } - crm_trace("Looking up metadata for %s agent %s", - stonith_namespace2text(ns), agent); + crm_trace("Looking up metadata for %s agent %s", namespace_text(ns), agent); switch (ns) { case st_namespace_rhcs: From 8b74e29063f83617141ea373571c88d91d772624 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 11 Apr 2025 23:23:13 -0700 Subject: [PATCH 60/75] API: libstonithd: Deprecate stonith_namespace2text() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 4 +++- lib/fencing/st_client.c | 21 ++++++++------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 2177be4d7e1..941bd7878cf 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -123,7 +123,6 @@ enum stonith_namespace { st_namespace_lha, // Linux-HA compatible }; -const char *stonith_namespace2text(enum stonith_namespace st_namespace); enum stonith_namespace stonith_get_namespace(const char *agent, const char *namespace_s); @@ -767,6 +766,9 @@ const char *stonith_action_str(const char *action); //! \deprecated Do not use enum stonith_namespace stonith_text2namespace(const char *namespace_s); +//! \deprecated Do not use +const char *stonith_namespace2text(enum stonith_namespace st_namespace); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 3cd5a1e24b8..ba36ca42a9d 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -150,19 +150,6 @@ namespace_text(enum stonith_namespace st_namespace) } } -/*! - * \brief Get agent namespace name - * - * \param[in] namespace Namespace as enum value - * - * \return Namespace name as string - */ -const char * -stonith_namespace2text(enum stonith_namespace st_namespace) -{ - return namespace_text(st_namespace); -} - /*! * \brief Determine namespace of a fence agent * @@ -2932,5 +2919,13 @@ stonith_text2namespace(const char *namespace_s) return parse_namespace(namespace_s); } +const char *stonith_namespace2text(enum stonith_namespace st_namespace); + +const char * +stonith_namespace2text(enum stonith_namespace st_namespace) +{ + return namespace_text(st_namespace); +} + // LCOV_EXCL_STOP // End deprecated API From 398eba620ed29d3f9c3d82554123339fefb43972 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 00:01:43 -0700 Subject: [PATCH 61/75] API: libstonithd: Ignore namespace_s in stonith API validate method It was already ignored (by stonith_get_namespace()) unless set to "internal". No external caller should be passing "internal" as the namespace_s argument of the stonith_api_operations_t:validate() method. Signed-off-by: Reid Wahl --- include/crm/fencing/internal.h | 6 ++---- include/crm/stonith-ng.h | 5 +---- lib/fencing/st_client.c | 11 +++++------ lib/pacemaker/pcmk_fence.c | 2 +- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h index 7ebdd66b2c9..f81044ddfa7 100644 --- a/include/crm/fencing/internal.h +++ b/include/crm/fencing/internal.h @@ -177,7 +177,6 @@ gboolean stonith__watchdog_fencing_enabled_for_node_api(stonith_t *st, const cha * \param[in,out] st Fencer connection to use * \param[in] call_options Group of enum stonith_call_options * \param[in] rsc_id Resource to validate - * \param[in] namespace_s Type of fence agent to search for * \param[in] agent Fence agent to validate * \param[in,out] params Fence device configuration parameters * \param[in] timeout_sec How long to wait for operation to complete @@ -187,9 +186,8 @@ gboolean stonith__watchdog_fencing_enabled_for_node_api(stonith_t *st, const cha * \return Standard Pacemaker return code */ int stonith__validate(stonith_t *st, int call_options, const char *rsc_id, - const char *namespace_s, const char *agent, - GHashTable *params, int timeout_sec, char **output, - char **error_output); + const char *agent, GHashTable *params, int timeout_sec, + char **output, char **error_output); #ifdef __cplusplus } diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 941bd7878cf..153f4b6015a 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -563,10 +563,7 @@ typedef struct stonith_api_operations_s { * \param[in,out] st Fencer connection to use * \param[in] call_options Group of enum stonith_call_options * \param[in] rsc_id ID used to replace CIB secrets in \p params - * \param[in] namespace_s Type of fence agent to validate ("redhat" - * or "stonith-ng" for RHCS-style, "internal" - * for Pacemaker-internal devices, "heartbeat" - * for LHA-style, or "any" or NULL for any) + * \param[in] namespace_s Ignored * \param[in] agent Fence agent to validate * \param[in] params Configuration parameters to pass to agent * \param[in] timeout Fail if no response within this many seconds diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index ba36ca42a9d..34ec0dee0ce 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -1738,9 +1738,8 @@ is_stonith_param(gpointer key, gpointer value, gpointer user_data) int stonith__validate(stonith_t *st, int call_options, const char *rsc_id, - const char *namespace_s, const char *agent, - GHashTable *params, int timeout_sec, char **output, - char **error_output) + const char *agent, GHashTable *params, int timeout_sec, + char **output, char **error_output) { int rc = pcmk_rc_ok; @@ -1778,7 +1777,7 @@ stonith__validate(stonith_t *st, int call_options, const char *rsc_id, timeout_sec = PCMK_DEFAULT_ACTION_TIMEOUT_MS; } - switch (stonith_get_namespace(agent, namespace_s)) { + switch (stonith_get_namespace(agent, NULL)) { case st_namespace_rhcs: rc = stonith__rhcs_validate(st, call_options, target, agent, params, host_arg, timeout_sec, @@ -1847,8 +1846,8 @@ stonith_api_validate(stonith_t *st, int call_options, const char *rsc_id, } } - rc = stonith__validate(st, call_options, rsc_id, namespace_s, agent, - params_table, timeout_sec, output, error_output); + rc = stonith__validate(st, call_options, rsc_id, agent, params_table, + timeout_sec, output, error_output); g_hash_table_destroy(params_table); return rc; diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c index 50df9fb13cc..f8ed1569798 100644 --- a/lib/pacemaker/pcmk_fence.c +++ b/lib/pacemaker/pcmk_fence.c @@ -623,7 +623,7 @@ pcmk__fence_validate(pcmk__output_t *out, stonith_t *st, const char *agent, char *error_output = NULL; int rc; - rc = stonith__validate(st, st_opt_sync_call, id, NULL, agent, params, + rc = stonith__validate(st, st_opt_sync_call, id, agent, params, pcmk__timeout_ms2s(timeout), &output, &error_output); out->message(out, "validate", agent, id, output, error_output, rc); return pcmk_legacy2rc(rc); From eb6ff9a8907767a575edf77262935b4f148ae0b6 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 00:09:44 -0700 Subject: [PATCH 62/75] API: liblrmd: Ignore provider for stonith-class resource metadata calls Provider is supported and allowed by the schema only for OCF-class resources. It was already being ignored for stonith-class resources unless provider was set to "internal", in which case behavior was undefined. Signed-off-by: Reid Wahl --- lib/lrmd/lrmd_client.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/lrmd/lrmd_client.c b/lib/lrmd/lrmd_client.c index b0d81bab00c..6a37ab5bf41 100644 --- a/lib/lrmd/lrmd_client.c +++ b/lib/lrmd/lrmd_client.c @@ -2057,7 +2057,7 @@ lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg) } static int -stonith_get_metadata(const char *provider, const char *type, char **output) +stonith_get_metadata(const char *type, char **output) { int rc = pcmk_ok; stonith_t *stonith_api = stonith__api_new(); @@ -2067,8 +2067,8 @@ stonith_get_metadata(const char *provider, const char *type, char **output) return -ENOMEM; } - rc = stonith_api->cmds->metadata(stonith_api, st_opt_sync_call, type, - provider, output, 0); + rc = stonith_api->cmds->metadata(stonith_api, st_opt_sync_call, type, NULL, + output, 0); if ((rc == pcmk_ok) && (*output == NULL)) { rc = -EIO; } @@ -2101,7 +2101,9 @@ lrmd_api_get_metadata_params(lrmd_t *lrmd, const char *standard, if (pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) { lrmd_key_value_freeall(params); - return stonith_get_metadata(provider, type, output); + + // stonith-class resources don't support a provider + return stonith_get_metadata(type, output); } params_table = pcmk__strkey_table(free, free); From f21d247aa9efb02e982b0f175e923842080ffd65 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 00:24:49 -0700 Subject: [PATCH 63/75] API: libstonithd: Ignore namespace_s in stonith API metadata method It was already ignored (by stonith_get_namespace()) unless set to "internal". No external caller should be passing "internal" as the namespace_s argument of the stonith_api_operations_t:validate() method. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 5 +---- lib/fencing/st_client.c | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 153f4b6015a..59f10f9eb85 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -286,10 +286,7 @@ typedef struct stonith_api_operations_s { * \param[in] call_options Group of enum stonith_call_options * (currently ignored) * \param[in] agent Fence agent to query - * \param[in] namespace_s Type of fence agent to search for ("redhat" - * or "stonith-ng" for RHCS-style, "internal" - * for Pacemaker-internal devices, "heartbeat" - * for LHA-style, or "any" or NULL for any) + * \param[in] namespace_s Ignored * \param[out] output Where to store metadata * \param[in] timeout_sec Error if not complete within this time * diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 34ec0dee0ce..277faf6ec94 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -522,7 +522,7 @@ stonith_api_device_metadata(stonith_t *stonith, int call_options, * the cluster is not running, which is important for higher-level tools. */ - enum stonith_namespace ns = stonith_get_namespace(agent, namespace_s); + enum stonith_namespace ns = stonith_get_namespace(agent, NULL); if (timeout_sec <= 0) { timeout_sec = PCMK_DEFAULT_ACTION_TIMEOUT_MS; From 7d5667a31a06d66da1dd3e3d0dbf0014710dc82f Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 00:34:22 -0700 Subject: [PATCH 64/75] Refactor: libstonithd: New get_namespace_from_agent() To replace stonith_get_namespace() Signed-off-by: Reid Wahl --- lib/fencing/st_client.c | 47 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 277faf6ec94..213638ff0fb 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -151,20 +151,20 @@ namespace_text(enum stonith_namespace st_namespace) } /*! - * \brief Determine namespace of a fence agent + * \internal + * \brief Determine fence agent namespace from agent name * - * \param[in] agent Fence agent type - * \param[in] namespace_s Name of agent namespace as string, if known + * This involves external checks (for example, checking the existence of a file + * or calling an external library function). * - * \return Namespace of specified agent, as enum value + * \param[in] agent Fence agent name + * + * \return Namespace to which \p agent belongs, or \c st_namespace_invalid if + * not found */ -enum stonith_namespace -stonith_get_namespace(const char *agent, const char *namespace_s) +static enum stonith_namespace +get_namespace_from_agent(const char *agent) { - if (pcmk__str_eq(namespace_s, "internal", pcmk__str_none)) { - return st_namespace_internal; - } - if (stonith__agent_is_rhcs(agent)) { return st_namespace_rhcs; } @@ -173,11 +173,28 @@ stonith_get_namespace(const char *agent, const char *namespace_s) if (stonith__agent_is_lha(agent)) { return st_namespace_lha; } -#endif +#endif // HAVE_STONITH_STONITH_H return st_namespace_invalid; } +/*! + * \brief Determine namespace of a fence agent + * + * \param[in] agent Fence agent type + * \param[in] namespace_s Name of agent namespace as string, if known + * + * \return Namespace of specified agent, as enum value + */ +enum stonith_namespace +stonith_get_namespace(const char *agent, const char *namespace_s) +{ + if (pcmk__str_eq(namespace_s, "internal", pcmk__str_none)) { + return st_namespace_internal; + } + return get_namespace_from_agent(agent); +} + gboolean stonith__watchdog_fencing_enabled_for_node_api(stonith_t *st, const char *node) { @@ -310,7 +327,7 @@ create_device_registration_xml(const char *id, enum stonith_namespace standard, #if HAVE_STONITH_STONITH_H if (standard == st_namespace_any) { - standard = stonith_get_namespace(agent, NULL); + standard = get_namespace_from_agent(agent); } if (standard == st_namespace_lha) { hash2field((gpointer) "plugin", (gpointer) agent, args); @@ -522,7 +539,7 @@ stonith_api_device_metadata(stonith_t *stonith, int call_options, * the cluster is not running, which is important for higher-level tools. */ - enum stonith_namespace ns = stonith_get_namespace(agent, NULL); + enum stonith_namespace ns = get_namespace_from_agent(agent); if (timeout_sec <= 0) { timeout_sec = PCMK_DEFAULT_ACTION_TIMEOUT_MS; @@ -1777,7 +1794,7 @@ stonith__validate(stonith_t *st, int call_options, const char *rsc_id, timeout_sec = PCMK_DEFAULT_ACTION_TIMEOUT_MS; } - switch (stonith_get_namespace(agent, NULL)) { + switch (get_namespace_from_agent(agent)) { case st_namespace_rhcs: rc = stonith__rhcs_validate(st, call_options, target, agent, params, host_arg, timeout_sec, @@ -2556,7 +2573,7 @@ stonith__metadata_async(const char *agent, int timeout_sec, void *user_data), void *user_data) { - switch (stonith_get_namespace(agent, NULL)) { + switch (get_namespace_from_agent(agent)) { case st_namespace_rhcs: { stonith_action_t *action = NULL; From ed3017ad13727aa7dcd6c67af020a28c9e4225ed Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 00:45:20 -0700 Subject: [PATCH 65/75] API: libstonithd: Deprecate stonith_get_namespace() Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 7 ++++--- lib/fencing/st_client.c | 29 ++++++++++++----------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 59f10f9eb85..19051352125 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -123,9 +123,6 @@ enum stonith_namespace { st_namespace_lha, // Linux-HA compatible }; -enum stonith_namespace stonith_get_namespace(const char *agent, - const char *namespace_s); - typedef struct stonith_key_value_s { char *key; char *value; @@ -763,6 +760,10 @@ enum stonith_namespace stonith_text2namespace(const char *namespace_s); //! \deprecated Do not use const char *stonith_namespace2text(enum stonith_namespace st_namespace); +//! \deprecated Do not use +enum stonith_namespace stonith_get_namespace(const char *agent, + const char *namespace_s); + #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #ifdef __cplusplus diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 213638ff0fb..8122af17d91 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -178,23 +178,6 @@ get_namespace_from_agent(const char *agent) return st_namespace_invalid; } -/*! - * \brief Determine namespace of a fence agent - * - * \param[in] agent Fence agent type - * \param[in] namespace_s Name of agent namespace as string, if known - * - * \return Namespace of specified agent, as enum value - */ -enum stonith_namespace -stonith_get_namespace(const char *agent, const char *namespace_s) -{ - if (pcmk__str_eq(namespace_s, "internal", pcmk__str_none)) { - return st_namespace_internal; - } - return get_namespace_from_agent(agent); -} - gboolean stonith__watchdog_fencing_enabled_for_node_api(stonith_t *st, const char *node) { @@ -2943,5 +2926,17 @@ stonith_namespace2text(enum stonith_namespace st_namespace) return namespace_text(st_namespace); } +enum stonith_namespace stonith_get_namespace(const char *agent, + const char *namespace_s); + +enum stonith_namespace +stonith_get_namespace(const char *agent, const char *namespace_s) +{ + if (pcmk__str_eq(namespace_s, "internal", pcmk__str_none)) { + return st_namespace_internal; + } + return get_namespace_from_agent(agent); +} + // LCOV_EXCL_STOP // End deprecated API From 08bb4d8b091b9fb918858e3696cc1dfbcea11596 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 00:56:09 -0700 Subject: [PATCH 66/75] API: libstonithd: Deprecate enum stonith_call_options and its values These were used externally only with stonith_api_operations_t methods, which are already deprecated. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 46 +++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 19051352125..04ca539ec4a 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -47,56 +47,72 @@ enum stonith_state { stonith_disconnected, }; -//! Flags that can be set in call options for API requests +// @TODO Keep this definition but make it internal +/*! + * \brief Flags that can be set in call options for API requests + * + * \deprecated Do not use + */ enum stonith_call_options { - //! No options + // No options + //! \deprecated Do not use st_opt_none = 0, #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) - //! \deprecated Unused + //! \deprecated Do not use st_opt_verbose = (1 << 0), #endif - //! The fencing target is allowed to execute the request + // The fencing target is allowed to execute the request + //! \deprecated Do not use st_opt_allow_self_fencing = (1 << 1), #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) - //! \deprecated Use st_opt_allow_self_fencing instead + //! \deprecated Do not use st_opt_allow_suicide = st_opt_allow_self_fencing, #endif // Used internally to indicate that request is manual fence confirmation - //! \internal Do not use + // \internal Do not use + //! \deprecated Do not use st_opt_manual_ack = (1 << 3), - //! Do not return any reply from server + // Do not return any reply from server + //! \deprecated Do not use st_opt_discard_reply = (1 << 4), // Used internally to indicate that request requires a fencing topology - //! \internal Do not use + // \internal Do not use + //! \deprecated Do not use st_opt_topology = (1 << 6), #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) - //! \deprecated Unused + //! \deprecated Do not use st_opt_scope_local = (1 << 8), #endif - //! Interpret target as node cluster layer ID instead of name + // Interpret target as node cluster layer ID instead of name + //! \deprecated Do not use st_opt_cs_nodeid = (1 << 9), - //! Wait for request to be completed before returning + // Wait for request to be completed before returning + //! \deprecated Do not use st_opt_sync_call = (1 << 12), - //! Request that server send an update with optimal callback timeout + // Request that server send an update with optimal callback timeout + //! \deprecated Do not use st_opt_timeout_updates = (1 << 13), - //! Invoke callback only if request succeeded + // Invoke callback only if request succeeded + //! \deprecated Do not use st_opt_report_only_success = (1 << 14), - //! For a fence history request, request that the history be cleared + // For a fence history request, request that the history be cleared + //! \deprecated Do not use st_opt_cleanup = (1 << 19), - //! For a fence history request, broadcast the request to all nodes + // For a fence history request, broadcast the request to all nodes + //! \deprecated Do not use st_opt_broadcast = (1 << 20), }; From d9fe1abf044af165fda9362bcd81ed69f1bb68d2 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 00:59:41 -0700 Subject: [PATCH 67/75] API: libstonithd: Deprecate enum op_state and its values Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 04ca539ec4a..10e244363eb 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -116,14 +116,18 @@ enum stonith_call_options { st_opt_broadcast = (1 << 20), }; -/*! Order matters here, do not change values */ -enum op_state -{ - st_query, - st_exec, - st_done, - st_duplicate, - st_failed, +// Order matters here, do not change values +// @TODO Keep this definition but make it internal +/*! + * \brief Fencing operation states + * \deprecated Do not use + */ +enum op_state { + st_query, //! \deprecated Do not use + st_exec, //! \deprecated Do not use + st_done, //! \deprecated Do not use + st_duplicate, //! \deprecated Do not use + st_failed, //! \deprecated Do not use }; // Supported fence agent interface standards From 1b77eb90bb50eec512d873443d0e0433a5fe6a92 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 01:03:50 -0700 Subject: [PATCH 68/75] API: libstonithd: Deprecate enum stonith_namespace and its values Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index 10e244363eb..be4ec0deb53 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -130,17 +130,26 @@ enum op_state { st_failed, //! \deprecated Do not use }; -// Supported fence agent interface standards +// @TODO Keep this definition but make it internal +/*! + * \brief Supported fence agent interface standards + * \deprecated Do not use + */ enum stonith_namespace { - st_namespace_invalid, - st_namespace_any, - st_namespace_internal, // Implemented internally by Pacemaker + st_namespace_invalid, //! \deprecated Do not use + st_namespace_any, //! \deprecated Do not use + + // Implemented internally by Pacemaker + st_namespace_internal, //! \deprecated Do not use /* Neither of these projects are active any longer, but the fence agent * interfaces they created are still in use and supported by Pacemaker. */ - st_namespace_rhcs, // Red Hat Cluster Suite compatible - st_namespace_lha, // Linux-HA compatible + // Red Hat Cluster Suite compatible + st_namespace_rhcs, //! \deprecated Do not use + + // Linux-HA compatible + st_namespace_lha, //! \deprecated Do not use }; typedef struct stonith_key_value_s { From f4c404ac6ac03694fac0ac60d2bce733e8ff16a8 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 01:06:22 -0700 Subject: [PATCH 69/75] API: libstonithd: Deprecate stonith_key_value_t And struct stonith_key_value_s Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index be4ec0deb53..c7af17c10dc 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -152,10 +152,17 @@ enum stonith_namespace { st_namespace_lha, //! \deprecated Do not use }; +/* @COMPAT Drop this and use a GList/GSList of pcmk_nvpair_t or a GHashtable as + * appropriate + */ +/*! + * \brief Key-value pair list node + * \deprecated Do not use + */ typedef struct stonith_key_value_s { char *key; char *value; - struct stonith_key_value_s *next; + struct stonith_key_value_s *next; } stonith_key_value_t; typedef struct stonith_history_s { From 5f18d917a8da8c2f928678cf7f392ff10f348ce3 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 01:08:40 -0700 Subject: [PATCH 70/75] API: libstonithd: Deprecate stonith_history_t And struct stonith_history_s Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index c7af17c10dc..d5e30711673 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -165,6 +165,11 @@ typedef struct stonith_key_value_s { struct stonith_key_value_s *next; } stonith_key_value_t; +// @TODO Keep this definition but make it internal +/*! + * \brief Fencing history entry + * \deprecated Do not use + */ typedef struct stonith_history_s { char *target; char *action; From 91841e4cbe804c6672bcb759128cc23913f1daa3 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 01:13:03 -0700 Subject: [PATCH 71/75] API: libstonithd: Deprecate stonith_event_t and struct stonith_event_s Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index d5e30711673..fc18f660e45 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -186,6 +186,11 @@ typedef struct stonith_history_s { // @TODO Keep this typedef but rename it and make it internal typedef struct stonith_s stonith_t; +// @TODO Keep this definition but make it internal +/*! + * \brief Fencing event + * \deprecated Do not use + */ typedef struct stonith_event_s { char *id; char *operation; @@ -197,10 +202,9 @@ typedef struct stonith_event_s { char *device; - /*! The name of the client that initiated the action. */ + // Name of the client that initiated the action char *client_origin; - //! \internal This field should be treated as internal to Pacemaker void *opaque; } stonith_event_t; From b083b53810b037afd704e8662d6d2bed4ed8ff4a Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Sat, 12 Apr 2025 01:15:42 -0700 Subject: [PATCH 72/75] API: libstonithd: Deprecate stonith_callback_data_t And struct stonith_callback_data_s Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index fc18f660e45..c71b3078cf8 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -208,6 +208,11 @@ typedef struct stonith_event_s { void *opaque; } stonith_event_t; +// @TODO Keep this definition but make it internal +/*! + * \brief Data for an asynchronous fencing request callback + * \deprecated Do not use + */ typedef struct stonith_callback_data_s { int rc; int call_id; From 6718368048d30494629190a3e296f487acb4ffb8 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Tue, 15 Apr 2025 10:50:53 -0700 Subject: [PATCH 73/75] Refactor: libpacemaker: Drop pcmk__fence_installed() timeout argument The list_agents method ignores it. Signed-off-by: Reid Wahl --- include/pcmki/pcmki_fence.h | 3 +-- lib/pacemaker/pcmk_fence.c | 7 +++---- tools/stonith_admin.c | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/pcmki/pcmki_fence.h b/include/pcmki/pcmki_fence.h index 208576bef28..3dec4685639 100644 --- a/include/pcmki/pcmki_fence.h +++ b/include/pcmki/pcmki_fence.h @@ -90,11 +90,10 @@ int pcmk__fence_history(pcmk__output_t *out, stonith_t *st, const char *target, * * \param[in,out] out The output functions structure * \param[in,out] st A connection to the fencer API - * \param[in] timeout How long to wait for the operation to complete (in ms) * * \return Standard Pacemaker return code */ -int pcmk__fence_installed(pcmk__output_t *out, stonith_t *st, unsigned int timeout); +int pcmk__fence_installed(pcmk__output_t *out, stonith_t *st); /*! * \brief When was a device last fenced? diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c index f8ed1569798..8febb374983 100644 --- a/lib/pacemaker/pcmk_fence.c +++ b/lib/pacemaker/pcmk_fence.c @@ -351,13 +351,12 @@ pcmk_fence_history(xmlNodePtr *xml, const char *target, unsigned int timeout, } int -pcmk__fence_installed(pcmk__output_t *out, stonith_t *st, unsigned int timeout) +pcmk__fence_installed(pcmk__output_t *out, stonith_t *st) { stonith_key_value_t *devices = NULL; int rc = pcmk_rc_ok; - rc = st->cmds->list_agents(st, st_opt_sync_call, NULL, &devices, - pcmk__timeout_ms2s(timeout)); + rc = st->cmds->list_agents(st, st_opt_sync_call, NULL, &devices, 0); // rc is a negative error code or a positive number of agents if (rc < 0) { return pcmk_legacy2rc(rc); @@ -386,7 +385,7 @@ pcmk_fence_installed(xmlNodePtr *xml, unsigned int timeout) return rc; } - rc = pcmk__fence_installed(out, st, timeout); + rc = pcmk__fence_installed(out, st); pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); st->cmds->disconnect(st); diff --git a/tools/stonith_admin.c b/tools/stonith_admin.c index bbbd7af0015..b2b72cc9412 100644 --- a/tools/stonith_admin.c +++ b/tools/stonith_admin.c @@ -570,7 +570,7 @@ main(int argc, char **argv) switch (action) { case 'I': - rc = pcmk__fence_installed(out, st, options.timeout*1000); + rc = pcmk__fence_installed(out, st); if (rc != pcmk_rc_ok) { out->err(out, "Failed to list installed devices: %s", pcmk_rc_str(rc)); } From 1c01f1d43d50ae36e7d07c1e74413b6e70499cf1 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Tue, 15 Apr 2025 10:52:07 -0700 Subject: [PATCH 74/75] API: libpacemaker: Document that pcmk_fence_installed() ignores timeout It's always ignored this argument. It likely doesn't make sense to implement a timeout, since the work currently consists of calls to libstonith (not libstonithd!) functions and to scandir(). Implementing a timeout would mean spawning one or more child processes and getting the results via a pipe, which doesn't seem worth the effort. Signed-off-by: Reid Wahl --- include/pacemaker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pacemaker.h b/include/pacemaker.h index cac2e217657..eae1e233a54 100644 --- a/include/pacemaker.h +++ b/include/pacemaker.h @@ -588,7 +588,7 @@ int pcmk_fence_history(xmlNodePtr *xml, const char *target, unsigned int timeout * * \param[in,out] xml The destination for the result, as an XML tree (if * not NULL, previous contents will be freed and lost) - * \param[in] timeout How long to wait for operation to complete (in ms) + * \param[in] timeout Ignored * * \return Standard Pacemaker return code */ From a31d92c0b0538197b49b994ede172ad7b54f839a Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Tue, 15 Apr 2025 10:56:40 -0700 Subject: [PATCH 75/75] Doc: libstonithd: Assume that list_agents() timeout will remain ignored This method has always ignored the argument since it was added in 2011 via 8d6be4b6. It likely doesn't make sense to implement a timeout, since the work currently consists of calls to libstonith (not libstonithd!) functions and to scandir(). Implementing a timeout would mean spawning one or more child processes and getting the results via a pipe, which doesn't seem worth the effort. Signed-off-by: Reid Wahl --- include/crm/stonith-ng.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h index c71b3078cf8..2f0b0e84013 100644 --- a/include/crm/stonith-ng.h +++ b/include/crm/stonith-ng.h @@ -355,8 +355,7 @@ typedef struct stonith_api_operations_s { * Pacemaker-internal devices, "heartbeat" for * LHA-style, or "any" or NULL for all) * \param[out] devices Where to store agent list - * \param[in] timeout Error if unable to complete within this - * (currently ignored) + * \param[in] timeout Ignored * * \return Number of items in list on success, or negative errno otherwise * \note The caller is responsible for freeing the returned list with