Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/lib/fencing/st_lha.c b/lib/fencing/st_lha.c
index a379c10810..3f31412b51 100644
--- a/lib/fencing/st_lha.c
+++ b/lib/fencing/st_lha.c
@@ -1,297 +1,305 @@
/*
* Copyright 2004-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <dlfcn.h>
#include <crm/crm.h>
#include <crm/stonith-ng.h>
#include <crm/fencing/internal.h>
#include <crm/common/xml.h>
#include <stonith/stonith.h>
#include "fencing_private.h"
#define LHA_STONITH_LIBRARY "libstonith.so.1"
static void *lha_agents_lib = NULL;
// @TODO Use XML string constants and maybe a real XML object
static const char META_TEMPLATE[] =
"<?xml " PCMK_XA_VERSION "=\"1.0\"?>\n"
"<" PCMK_XE_RESOURCE_AGENT " " PCMK_XA_NAME "=\"%s\">\n"
" <" PCMK_XE_VERSION ">1.1</" PCMK_XE_VERSION ">\n"
" <" PCMK_XE_LONGDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">\n"
"%s\n"
" </" PCMK_XE_LONGDESC ">\n"
" <" PCMK_XE_SHORTDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">"
"%s"
"</" PCMK_XE_SHORTDESC ">\n"
"%s\n"
" <" PCMK_XE_ACTIONS ">\n"
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_START "\""
" " PCMK_META_TIMEOUT "=\"%s\" />\n"
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_STOP "\""
" " PCMK_META_TIMEOUT "=\"15s\" />\n"
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_STATUS "\""
" " PCMK_META_TIMEOUT "=\"%s\" />\n"
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_MONITOR "\""
" " PCMK_META_TIMEOUT "=\"%s\""
" " PCMK_META_INTERVAL "=\"3600s\" />\n"
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_META_DATA "\""
" " PCMK_META_TIMEOUT "=\"15s\" />\n"
" </" PCMK_XE_ACTIONS ">\n"
" <" PCMK_XE_SPECIAL " " PCMK_XA_TAG "=\"heartbeat\">\n"
" <" PCMK_XE_VERSION ">2.0</" PCMK_XE_VERSION ">\n"
" </" PCMK_XE_SPECIAL ">\n"
"</" PCMK_XE_RESOURCE_AGENT ">\n";
static void *
find_library_function(void **handle, const char *lib, const char *fn)
{
void *a_function;
if (*handle == NULL) {
*handle = dlopen(lib, RTLD_LAZY);
if ((*handle) == NULL) {
crm_err("Could not open %s: %s", lib, dlerror());
return NULL;
}
}
a_function = dlsym(*handle, fn);
if (a_function == NULL) {
crm_err("Could not find %s in %s: %s", fn, lib, dlerror());
}
return a_function;
}
/*!
* \internal
* \brief Check whether a given fence agent is an LHA agent
*
* \param[in] agent Fence agent type
*
* \return true if \p agent is an LHA agent, otherwise false
*/
bool
stonith__agent_is_lha(const char *agent)
{
Stonith *stonith_obj = NULL;
static bool need_init = true;
static Stonith *(*st_new_fn) (const char *) = NULL;
static void (*st_del_fn) (Stonith *) = NULL;
if (need_init) {
need_init = false;
st_new_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
"stonith_new");
st_del_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
"stonith_delete");
}
if (lha_agents_lib && st_new_fn && st_del_fn) {
stonith_obj = (*st_new_fn) (agent);
if (stonith_obj) {
(*st_del_fn) (stonith_obj);
return true;
}
}
return false;
}
int
stonith__list_lha_agents(stonith_key_value_t **devices)
{
static gboolean need_init = TRUE;
int count = 0;
char **entry = NULL;
char **type_list = NULL;
static char **(*type_list_fn) (void) = NULL;
static void (*type_free_fn) (char **) = NULL;
if (need_init) {
need_init = FALSE;
type_list_fn = find_library_function(&lha_agents_lib,
LHA_STONITH_LIBRARY,
"stonith_types");
type_free_fn = find_library_function(&lha_agents_lib,
LHA_STONITH_LIBRARY,
"stonith_free_hostlist");
}
if (type_list_fn) {
type_list = (*type_list_fn) ();
}
for (entry = type_list; entry != NULL && *entry; ++entry) {
crm_trace("Added: %s", *entry);
*devices = stonith_key_value_add(*devices, NULL, *entry);
count++;
}
if (type_list && type_free_fn) {
(*type_free_fn) (type_list);
}
return count;
}
static void
stonith_plugin(int priority, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
static void
stonith_plugin(int priority, const char *format, ...)
{
int err = errno;
va_list ap;
int len = 0;
char *string = NULL;
va_start(ap, format);
len = vasprintf (&string, format, ap);
va_end(ap);
CRM_ASSERT(len > 0);
do_crm_log_alias(priority, __FILE__, __func__, __LINE__, "%s", string);
free(string);
errno = err;
}
int
stonith__lha_metadata(const char *agent, int timeout, char **output)
{
int rc = 0;
char *buffer = NULL;
static const char *no_parameter_info = "<!-- no value -->";
Stonith *stonith_obj = NULL;
static gboolean need_init = TRUE;
static Stonith *(*st_new_fn) (const char *) = NULL;
static const char *(*st_info_fn) (Stonith *, int) = NULL;
static void (*st_del_fn) (Stonith *) = NULL;
static void (*st_log_fn) (Stonith *, PILLogFun) = NULL;
if (need_init) {
need_init = FALSE;
st_new_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
"stonith_new");
st_del_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
"stonith_delete");
st_log_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
"stonith_set_log");
st_info_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
"stonith_get_info");
}
if (lha_agents_lib && st_new_fn && st_del_fn && st_info_fn && st_log_fn) {
- const char *meta_longdesc = NULL;
- const char *meta_shortdesc = NULL;
- const char *meta_param = NULL;
+ char *meta_longdesc = NULL;
+ char *meta_shortdesc = NULL;
+ char *meta_param = NULL;
const char *timeout_str = NULL;
- gchar *meta_longdesc_esc = NULL;
- gchar *meta_shortdesc_esc = NULL;
-
stonith_obj = st_new_fn(agent);
if (stonith_obj != NULL) {
st_log_fn(stonith_obj, (PILLogFun) &stonith_plugin);
- meta_longdesc = st_info_fn(stonith_obj, ST_DEVICEDESCR);
+ /* A st_info_fn() may free any existing output buffer every time
+ * when it's called. Copy the output every time.
+ */
+ meta_longdesc = pcmk__str_copy(st_info_fn(stonith_obj,
+ ST_DEVICEDESCR));
if (meta_longdesc == NULL) {
crm_warn("no long description in %s's metadata.", agent);
- meta_longdesc = no_parameter_info;
+ meta_longdesc = pcmk__str_copy(no_parameter_info);
}
- meta_shortdesc = st_info_fn(stonith_obj, ST_DEVICEID);
+ meta_shortdesc = pcmk__str_copy(st_info_fn(stonith_obj,
+ ST_DEVICEID));
if (meta_shortdesc == NULL) {
crm_warn("no short description in %s's metadata.", agent);
- meta_shortdesc = no_parameter_info;
+ meta_shortdesc = pcmk__str_copy(no_parameter_info);
}
- meta_param = st_info_fn(stonith_obj, ST_CONF_XML);
+ meta_param = pcmk__str_copy(st_info_fn(stonith_obj,
+ ST_CONF_XML));
if (meta_param == NULL) {
crm_warn("no list of parameters in %s's metadata.", agent);
- meta_param = no_parameter_info;
+ meta_param = pcmk__str_copy(no_parameter_info);
}
st_del_fn(stonith_obj);
} else {
errno = EINVAL;
crm_perror(LOG_ERR, "Agent %s not found", agent);
return -EINVAL;
}
if (pcmk__xml_needs_escape(meta_longdesc, pcmk__xml_escape_text)) {
- meta_longdesc_esc = pcmk__xml_escape(meta_longdesc,
- pcmk__xml_escape_text);
+ gchar *meta_longdesc_esc = pcmk__xml_escape(meta_longdesc,
+ pcmk__xml_escape_text);
+
+ free(meta_longdesc);
meta_longdesc = meta_longdesc_esc;
}
if (pcmk__xml_needs_escape(meta_shortdesc, pcmk__xml_escape_text)) {
- meta_shortdesc_esc = pcmk__xml_escape(meta_shortdesc,
- pcmk__xml_escape_text);
+ gchar *meta_shortdesc_esc = pcmk__xml_escape(meta_shortdesc,
+ pcmk__xml_escape_text);
+
+ free(meta_shortdesc);
meta_shortdesc = meta_shortdesc_esc;
}
/* @TODO This needs a string that's parsable by crm_get_msec(). In
* general, pcmk__readable_interval() doesn't provide that. It works
* here because PCMK_DEFAULT_ACTION_TIMEOUT_MS is 20000 -> "20s".
*/
timeout_str = pcmk__readable_interval(PCMK_DEFAULT_ACTION_TIMEOUT_MS);
buffer = crm_strdup_printf(META_TEMPLATE, agent, meta_longdesc,
meta_shortdesc, meta_param,
timeout_str, timeout_str, timeout_str);
- g_free(meta_longdesc_esc);
- g_free(meta_shortdesc_esc);
+ free(meta_longdesc);
+ free(meta_shortdesc);
+ free(meta_param);
}
if (output) {
*output = buffer;
} else {
free(buffer);
}
return rc;
}
/* Implement a dummy function that uses -lpils so that linkers don't drop the
* reference.
*/
#include <pils/plugin.h>
const char *i_hate_pils(int rc);
const char *
i_hate_pils(int rc)
{
return PIL_strerror(rc);
}
int
stonith__lha_validate(stonith_t *st, int call_options, const char *target,
const char *agent, GHashTable *params, int timeout,
char **output, char **error_output)
{
errno = EOPNOTSUPP;
crm_perror(LOG_ERR, "Cannot validate Linux-HA fence agents");
return -EOPNOTSUPP;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 23, 2:34 PM (1 d, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018791
Default Alt Text
(11 KB)

Event Timeline