summaryrefslogtreecommitdiffstats
path: root/lib/fencing/st_lha.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fencing/st_lha.c')
-rw-r--r--lib/fencing/st_lha.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/lib/fencing/st_lha.c b/lib/fencing/st_lha.c
new file mode 100644
index 0000000..d477ded
--- /dev/null
+++ b/lib/fencing/st_lha.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2004-2022 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/msg_xml.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;
+
+static const char META_TEMPLATE[] =
+ "<?xml version=\"1.0\"?>\n"
+ "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
+ "<resource-agent name=\"%s\">\n"
+ " <version>1.0</version>\n"
+ " <longdesc lang=\"en\">\n"
+ "%s\n"
+ " </longdesc>\n"
+ " <shortdesc lang=\"en\">%s</shortdesc>\n"
+ "%s\n"
+ " <actions>\n"
+ " <action name=\"start\" timeout=\"20\" />\n"
+ " <action name=\"stop\" timeout=\"15\" />\n"
+ " <action name=\"status\" timeout=\"20\" />\n"
+ " <action name=\"monitor\" timeout=\"20\" interval=\"3600\"/>\n"
+ " <action name=\"meta-data\" timeout=\"15\" />\n"
+ " </actions>\n"
+ " <special tag=\"heartbeat\">\n"
+ " <version>2.0</version>\n" " </special>\n" "</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) {
+ char *xml_meta_longdesc = NULL;
+ char *xml_meta_shortdesc = NULL;
+
+ char *meta_param = NULL;
+ char *meta_longdesc = NULL;
+ char *meta_shortdesc = NULL;
+
+ stonith_obj = (*st_new_fn) (agent);
+ if (stonith_obj) {
+ (*st_log_fn) (stonith_obj, (PILLogFun) & stonith_plugin);
+ pcmk__str_update(&meta_longdesc,
+ (*st_info_fn) (stonith_obj, ST_DEVICEDESCR));
+ if (meta_longdesc == NULL) {
+ crm_warn("no long description in %s's metadata.", agent);
+ meta_longdesc = strdup(no_parameter_info);
+ }
+
+ pcmk__str_update(&meta_shortdesc,
+ (*st_info_fn) (stonith_obj, ST_DEVICEID));
+ if (meta_shortdesc == NULL) {
+ crm_warn("no short description in %s's metadata.", agent);
+ meta_shortdesc = strdup(no_parameter_info);
+ }
+
+ pcmk__str_update(&meta_param,
+ (*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 = strdup(no_parameter_info);
+ }
+ (*st_del_fn) (stonith_obj);
+ } else {
+ errno = EINVAL;
+ crm_perror(LOG_ERR, "Agent %s not found", agent);
+ return -EINVAL;
+ }
+
+ xml_meta_longdesc =
+ (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_longdesc);
+ xml_meta_shortdesc =
+ (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_shortdesc);
+
+ buffer = crm_strdup_printf(META_TEMPLATE, agent, xml_meta_longdesc,
+ xml_meta_shortdesc, meta_param);
+
+ xmlFree(xml_meta_longdesc);
+ xmlFree(xml_meta_shortdesc);
+
+ free(meta_shortdesc);
+ free(meta_longdesc);
+ 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;
+}