pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
st_lha.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2025 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdio.h>
13#include <stdarg.h>
14#include <string.h>
15#include <errno.h>
16#include <glib.h>
17#include <dlfcn.h>
18
19#include <crm/crm.h>
20#include <crm/stonith-ng.h>
22#include <crm/common/xml.h>
23
24#include <stonith/stonith.h>
25
26#include "fencing_private.h"
27
28#define LHA_STONITH_LIBRARY "libstonith.so.1"
29
30static void *lha_agents_lib = NULL;
31
32// @TODO Use XML string constants and maybe a real XML object
33static const char META_TEMPLATE[] =
34 "<?xml " PCMK_XA_VERSION "=\"1.0\"?>\n"
35 "<" PCMK_XE_RESOURCE_AGENT " " PCMK_XA_NAME "=\"%s\">\n"
36 " <" PCMK_XE_VERSION ">1.1</" PCMK_XE_VERSION ">\n"
37 " <" PCMK_XE_LONGDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">\n"
38 "%s\n"
39 " </" PCMK_XE_LONGDESC ">\n"
41 "%s"
42 "</" PCMK_XE_SHORTDESC ">\n"
43 "%s\n"
44 " <" PCMK_XE_ACTIONS ">\n"
46 " " PCMK_META_TIMEOUT "=\"%s\" />\n"
48 " " PCMK_META_TIMEOUT "=\"15s\" />\n"
50 " " PCMK_META_TIMEOUT "=\"%s\" />\n"
52 " " PCMK_META_TIMEOUT "=\"%s\""
53 " " PCMK_META_INTERVAL "=\"3600s\" />\n"
55 " " PCMK_META_TIMEOUT "=\"15s\" />\n"
56 " </" PCMK_XE_ACTIONS ">\n"
57 " <" PCMK_XE_SPECIAL " " PCMK_XA_TAG "=\"heartbeat\">\n"
58 " <" PCMK_XE_VERSION ">2.0</" PCMK_XE_VERSION ">\n"
59 " </" PCMK_XE_SPECIAL ">\n"
60 "</" PCMK_XE_RESOURCE_AGENT ">\n";
61
62static void *
63find_library_function(void **handle, const char *lib, const char *fn)
64{
65 void *a_function;
66
67 if (*handle == NULL) {
68 *handle = dlopen(lib, RTLD_LAZY);
69 if ((*handle) == NULL) {
70 crm_err("Could not open %s: %s", lib, dlerror());
71 return NULL;
72 }
73 }
74
75 a_function = dlsym(*handle, fn);
76 if (a_function == NULL) {
77 crm_err("Could not find %s in %s: %s", fn, lib, dlerror());
78 }
79
80 return a_function;
81}
82
91bool
92stonith__agent_is_lha(const char *agent)
93{
94 Stonith *stonith_obj = NULL;
95
96 static bool need_init = true;
97 static Stonith *(*st_new_fn) (const char *) = NULL;
98 static void (*st_del_fn) (Stonith *) = NULL;
99
100 if (need_init) {
101 need_init = false;
102 st_new_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
103 "stonith_new");
104 st_del_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
105 "stonith_delete");
106 }
107
108 if (lha_agents_lib && st_new_fn && st_del_fn) {
109 stonith_obj = (*st_new_fn) (agent);
110 if (stonith_obj) {
111 (*st_del_fn) (stonith_obj);
112 return true;
113 }
114 }
115 return false;
116}
117
118int
120{
121 static gboolean need_init = TRUE;
122
123 int count = 0;
124 char **entry = NULL;
125 char **type_list = NULL;
126 static char **(*type_list_fn) (void) = NULL;
127 static void (*type_free_fn) (char **) = NULL;
128
129 if (need_init) {
130 need_init = FALSE;
131 type_list_fn = find_library_function(&lha_agents_lib,
133 "stonith_types");
134 type_free_fn = find_library_function(&lha_agents_lib,
136 "stonith_free_hostlist");
137 }
138
139 if (type_list_fn) {
140 type_list = (*type_list_fn) ();
141 }
142
143 for (entry = type_list; entry != NULL && *entry; ++entry) {
144 crm_trace("Added: %s", *entry);
145 *devices = stonith__key_value_add(*devices, NULL, *entry);
146 count++;
147 }
148 if (type_list && type_free_fn) {
149 (*type_free_fn) (type_list);
150 }
151 return count;
152}
153
154static void
155stonith_plugin(int priority, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
156
157static void
158stonith_plugin(int priority, const char *format, ...)
159{
160 int err = errno;
161
162 va_list ap;
163 int len = 0;
164 char *string = NULL;
165
166 va_start(ap, format);
167
168 len = vasprintf (&string, format, ap);
169 va_end(ap);
170 pcmk__assert(len > 0);
171
172 do_crm_log_alias(priority, __FILE__, __func__, __LINE__, "%s", string);
173
174 free(string);
175 errno = err;
176}
177
178int
179stonith__lha_metadata(const char *agent, int timeout, char **output)
180{
181 int rc = 0;
182 char *buffer = NULL;
183 static const char *no_parameter_info = "<!-- no value -->";
184
185 Stonith *stonith_obj = NULL;
186
187 static gboolean need_init = TRUE;
188 static Stonith *(*st_new_fn) (const char *) = NULL;
189 static const char *(*st_info_fn) (Stonith *, int) = NULL;
190 static void (*st_del_fn) (Stonith *) = NULL;
191 static void (*st_log_fn) (Stonith *, PILLogFun) = NULL;
192
193 if (need_init) {
194 need_init = FALSE;
195 st_new_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
196 "stonith_new");
197 st_del_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
198 "stonith_delete");
199 st_log_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
200 "stonith_set_log");
201 st_info_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
202 "stonith_get_info");
203 }
204
205 if (lha_agents_lib && st_new_fn && st_del_fn && st_info_fn && st_log_fn) {
206 char *meta_longdesc = NULL;
207 char *meta_shortdesc = NULL;
208 char *meta_param = NULL;
209 const char *timeout_str = NULL;
210
211 gchar *meta_longdesc_esc = NULL;
212 gchar *meta_shortdesc_esc = NULL;
213
214 stonith_obj = st_new_fn(agent);
215 if (stonith_obj != NULL) {
216 st_log_fn(stonith_obj, (PILLogFun) &stonith_plugin);
217
218 /* A st_info_fn() may free any existing output buffer every time
219 * when it's called. Copy the output every time.
220 */
221 meta_longdesc = pcmk__str_copy(st_info_fn(stonith_obj,
222 ST_DEVICEDESCR));
223 if (meta_longdesc == NULL) {
224 crm_warn("no long description in %s's metadata.", agent);
225 meta_longdesc = pcmk__str_copy(no_parameter_info);
226 }
227
228 meta_shortdesc = pcmk__str_copy(st_info_fn(stonith_obj,
229 ST_DEVICEID));
230 if (meta_shortdesc == NULL) {
231 crm_warn("no short description in %s's metadata.", agent);
232 meta_shortdesc = pcmk__str_copy(no_parameter_info);
233 }
234
235 meta_param = pcmk__str_copy(st_info_fn(stonith_obj,
236 ST_CONF_XML));
237 if (meta_param == NULL) {
238 crm_warn("no list of parameters in %s's metadata.", agent);
239 meta_param = pcmk__str_copy(no_parameter_info);
240 }
241
242 st_del_fn(stonith_obj);
243
244 } else {
245 errno = EINVAL;
246 crm_perror(LOG_ERR, "Agent %s not found", agent);
247 return -EINVAL;
248 }
249
250 if (pcmk__xml_needs_escape(meta_longdesc, pcmk__xml_escape_text)) {
251 meta_longdesc_esc = pcmk__xml_escape(meta_longdesc,
253 }
254 if (pcmk__xml_needs_escape(meta_shortdesc, pcmk__xml_escape_text)) {
255 meta_shortdesc_esc = pcmk__xml_escape(meta_shortdesc,
257 }
258
259 /* @TODO This needs a string that's parsable by crm_get_msec(). In
260 * general, pcmk__readable_interval() doesn't provide that. It works
261 * here because PCMK_DEFAULT_ACTION_TIMEOUT_MS is 20000 -> "20s".
262 */
264 buffer = crm_strdup_printf(META_TEMPLATE, agent,
265 ((meta_longdesc_esc != NULL) ?
266 meta_longdesc_esc : meta_longdesc),
267 ((meta_shortdesc_esc != NULL) ?
268 meta_shortdesc_esc : meta_shortdesc),
269 meta_param, timeout_str, timeout_str,
270 timeout_str);
271
272 g_free(meta_longdesc_esc);
273 g_free(meta_shortdesc_esc);
274
275 free(meta_longdesc);
276 free(meta_shortdesc);
277 free(meta_param);
278 }
279 if (output) {
280 *output = buffer;
281 } else {
282 free(buffer);
283 }
284 return rc;
285}
286
287/* Implement a dummy function that uses -lpils so that linkers don't drop the
288 * reference.
289 */
290
291#include <pils/plugin.h>
292
293const char *i_hate_pils(int rc);
294
295const char *
297{
298 return PIL_strerror(rc);
299}
300
301int
302stonith__lha_validate(stonith_t *st, int call_options, const char *target,
303 const char *agent, GHashTable *params, int timeout,
304 char **output, char **error_output)
305{
306 errno = EOPNOTSUPP;
307 crm_perror(LOG_ERR, "Cannot validate Linux-HA fence agents");
308 return -EOPNOTSUPP;
309}
#define PCMK_ACTION_STATUS
Definition actions.h:64
#define PCMK_ACTION_STOP
Definition actions.h:66
#define PCMK_ACTION_META_DATA
Definition actions.h:47
#define PCMK_ACTION_START
Definition actions.h:63
#define PCMK_DEFAULT_ACTION_TIMEOUT_MS
Default timeout (in milliseconds) for non-metadata actions.
Definition actions.h:33
#define PCMK_ACTION_MONITOR
Definition actions.h:51
A dumping ground.
stonith_key_value_t * stonith__key_value_add(stonith_key_value_t *head, const char *key, const char *value)
Definition st_client.c:1995
const char * pcmk__readable_interval(guint interval_ms)
Definition iso8601.c:2210
#define crm_warn(fmt, args...)
Definition logging.h:360
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition logging.h:299
#define crm_err(fmt, args...)
Definition logging.h:357
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
Definition logging.h:268
#define crm_trace(fmt, args...)
Definition logging.h:370
#define PCMK_META_INTERVAL
Definition options.h:92
#define PCMK_META_TIMEOUT
Definition options.h:115
#define PCMK__VALUE_EN
unsigned int timeout
Definition pcmk_fence.c:34
stonith_t * st
Definition pcmk_fence.c:30
const char * target
Definition pcmk_fence.c:31
#define pcmk__assert(expr)
int stonith__lha_metadata(const char *agent, int timeout, char **output)
Definition st_lha.c:179
const char * i_hate_pils(int rc)
Definition st_lha.c:296
int stonith__list_lha_agents(stonith_key_value_t **devices)
Definition st_lha.c:119
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)
Definition st_lha.c:302
#define LHA_STONITH_LIBRARY
Definition st_lha.c:28
bool stonith__agent_is_lha(const char *agent)
Definition st_lha.c:92
Fencing aka. STONITH.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk__str_copy(str)
Key-value pair list node.
Definition stonith-ng.h:162
Fencer API connection object.
Definition stonith-ng.h:657
Wrappers for and extensions to libxml2.
bool pcmk__xml_needs_escape(const char *text, enum pcmk__xml_escape_type type)
Definition xml.c:909
@ pcmk__xml_escape_text
char * pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type)
Definition xml.c:991
#define PCMK_XE_ACTIONS
Definition xml_names.h:61
#define PCMK_XE_SHORTDESC
Definition xml_names.h:199
#define PCMK_XE_VERSION
Definition xml_names.h:220
#define PCMK_XE_SPECIAL
Definition xml_names.h:201
#define PCMK_XA_LANG
Definition xml_names.h:313
#define PCMK_XA_VERSION
Definition xml_names.h:444
#define PCMK_XE_ACTION
Definition xml_names.h:60
#define PCMK_XE_RESOURCE_AGENT
Definition xml_names.h:173
#define PCMK_XA_TAG
Definition xml_names.h:417
#define PCMK_XA_NAME
Definition xml_names.h:330
#define PCMK_XE_LONGDESC
Definition xml_names.h:129