pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
st_lha.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2023 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>
21 #include <crm/fencing/internal.h>
22 #include <crm/msg_xml.h>
23 #include <crm/common/xml.h>
24 
25 #include <stonith/stonith.h>
26 
27 #include "fencing_private.h"
28 
29 #define LHA_STONITH_LIBRARY "libstonith.so.1"
30 
31 static void *lha_agents_lib = NULL;
32 
33 static const char META_TEMPLATE[] =
34  "<?xml version=\"1.0\"?>\n"
35  "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
36  "<resource-agent name=\"%s\">\n"
37  " <version>1.0</version>\n"
38  " <longdesc lang=\"en\">\n"
39  "%s\n"
40  " </longdesc>\n"
41  " <shortdesc lang=\"en\">%s</shortdesc>\n"
42  "%s\n"
43  " <actions>\n"
44  " <action name=\"start\" timeout=\"%s\" />\n"
45  " <action name=\"stop\" timeout=\"15\" />\n"
46  " <action name=\"status\" timeout=\"%s\" />\n"
47  " <action name=\"monitor\" timeout=\"%s\" interval=\"3600\"/>\n"
48  " <action name=\"meta-data\" timeout=\"15\" />\n"
49  " </actions>\n"
50  " <special tag=\"heartbeat\">\n"
51  " <version>2.0</version>\n" " </special>\n" "</resource-agent>\n";
52 
53 static void *
54 find_library_function(void **handle, const char *lib, const char *fn)
55 {
56  void *a_function;
57 
58  if (*handle == NULL) {
59  *handle = dlopen(lib, RTLD_LAZY);
60  if ((*handle) == NULL) {
61  crm_err("Could not open %s: %s", lib, dlerror());
62  return NULL;
63  }
64  }
65 
66  a_function = dlsym(*handle, fn);
67  if (a_function == NULL) {
68  crm_err("Could not find %s in %s: %s", fn, lib, dlerror());
69  }
70 
71  return a_function;
72 }
73 
82 bool
83 stonith__agent_is_lha(const char *agent)
84 {
85  Stonith *stonith_obj = NULL;
86 
87  static bool need_init = true;
88  static Stonith *(*st_new_fn) (const char *) = NULL;
89  static void (*st_del_fn) (Stonith *) = NULL;
90 
91  if (need_init) {
92  need_init = false;
93  st_new_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
94  "stonith_new");
95  st_del_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
96  "stonith_delete");
97  }
98 
99  if (lha_agents_lib && st_new_fn && st_del_fn) {
100  stonith_obj = (*st_new_fn) (agent);
101  if (stonith_obj) {
102  (*st_del_fn) (stonith_obj);
103  return true;
104  }
105  }
106  return false;
107 }
108 
109 int
111 {
112  static gboolean need_init = TRUE;
113 
114  int count = 0;
115  char **entry = NULL;
116  char **type_list = NULL;
117  static char **(*type_list_fn) (void) = NULL;
118  static void (*type_free_fn) (char **) = NULL;
119 
120  if (need_init) {
121  need_init = FALSE;
122  type_list_fn = find_library_function(&lha_agents_lib,
124  "stonith_types");
125  type_free_fn = find_library_function(&lha_agents_lib,
127  "stonith_free_hostlist");
128  }
129 
130  if (type_list_fn) {
131  type_list = (*type_list_fn) ();
132  }
133 
134  for (entry = type_list; entry != NULL && *entry; ++entry) {
135  crm_trace("Added: %s", *entry);
136  *devices = stonith_key_value_add(*devices, NULL, *entry);
137  count++;
138  }
139  if (type_list && type_free_fn) {
140  (*type_free_fn) (type_list);
141  }
142  return count;
143 }
144 
145 static void
146 stonith_plugin(int priority, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
147 
148 static void
149 stonith_plugin(int priority, const char *format, ...)
150 {
151  int err = errno;
152 
153  va_list ap;
154  int len = 0;
155  char *string = NULL;
156 
157  va_start(ap, format);
158 
159  len = vasprintf (&string, format, ap);
160  va_end(ap);
161  CRM_ASSERT(len > 0);
162 
163  do_crm_log_alias(priority, __FILE__, __func__, __LINE__, "%s", string);
164 
165  free(string);
166  errno = err;
167 }
168 
169 int
170 stonith__lha_metadata(const char *agent, int timeout, char **output)
171 {
172  int rc = 0;
173  char *buffer = NULL;
174  static const char *no_parameter_info = "<!-- no value -->";
175 
176  Stonith *stonith_obj = NULL;
177 
178  static gboolean need_init = TRUE;
179  static Stonith *(*st_new_fn) (const char *) = NULL;
180  static const char *(*st_info_fn) (Stonith *, int) = NULL;
181  static void (*st_del_fn) (Stonith *) = NULL;
182  static void (*st_log_fn) (Stonith *, PILLogFun) = NULL;
183 
184  if (need_init) {
185  need_init = FALSE;
186  st_new_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
187  "stonith_new");
188  st_del_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
189  "stonith_delete");
190  st_log_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
191  "stonith_set_log");
192  st_info_fn = find_library_function(&lha_agents_lib, LHA_STONITH_LIBRARY,
193  "stonith_get_info");
194  }
195 
196  if (lha_agents_lib && st_new_fn && st_del_fn && st_info_fn && st_log_fn) {
197  char *xml_meta_longdesc = NULL;
198  char *xml_meta_shortdesc = NULL;
199 
200  char *meta_param = NULL;
201  char *meta_longdesc = NULL;
202  char *meta_shortdesc = NULL;
203  const char *timeout_str = NULL;
204 
205  stonith_obj = (*st_new_fn) (agent);
206  if (stonith_obj) {
207  (*st_log_fn) (stonith_obj, (PILLogFun) & stonith_plugin);
208  pcmk__str_update(&meta_longdesc,
209  (*st_info_fn) (stonith_obj, ST_DEVICEDESCR));
210  if (meta_longdesc == NULL) {
211  crm_warn("no long description in %s's metadata.", agent);
212  meta_longdesc = strdup(no_parameter_info);
213  }
214 
215  pcmk__str_update(&meta_shortdesc,
216  (*st_info_fn) (stonith_obj, ST_DEVICEID));
217  if (meta_shortdesc == NULL) {
218  crm_warn("no short description in %s's metadata.", agent);
219  meta_shortdesc = strdup(no_parameter_info);
220  }
221 
222  pcmk__str_update(&meta_param,
223  (*st_info_fn) (stonith_obj, ST_CONF_XML));
224  if (meta_param == NULL) {
225  crm_warn("no list of parameters in %s's metadata.", agent);
226  meta_param = strdup(no_parameter_info);
227  }
228  (*st_del_fn) (stonith_obj);
229  } else {
230  errno = EINVAL;
231  crm_perror(LOG_ERR, "Agent %s not found", agent);
232  return -EINVAL;
233  }
234 
235  xml_meta_longdesc =
236  (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_longdesc);
237  xml_meta_shortdesc =
238  (char *)xmlEncodeEntitiesReentrant(NULL, (const unsigned char *)meta_shortdesc);
239 
241  buffer = crm_strdup_printf(META_TEMPLATE, agent, xml_meta_longdesc,
242  xml_meta_shortdesc, meta_param,
243  timeout_str, timeout_str, timeout_str);
244 
245  xmlFree(xml_meta_longdesc);
246  xmlFree(xml_meta_shortdesc);
247 
248  free(meta_shortdesc);
249  free(meta_longdesc);
250  free(meta_param);
251  }
252  if (output) {
253  *output = buffer;
254  } else {
255  free(buffer);
256  }
257  return rc;
258 }
259 
260 /* Implement a dummy function that uses -lpils so that linkers don't drop the
261  * reference.
262  */
263 
264 #include <pils/plugin.h>
265 
266 const char *i_hate_pils(int rc);
267 
268 const char *
269 i_hate_pils(int rc)
270 {
271  return PIL_strerror(rc);
272 }
273 
274 int
275 stonith__lha_validate(stonith_t *st, int call_options, const char *target,
276  const char *agent, GHashTable *params, int timeout,
277  char **output, char **error_output)
278 {
279  errno = EOPNOTSUPP;
280  crm_perror(LOG_ERR, "Cannot validate Linux-HA fence agents");
281  return -EOPNOTSUPP;
282 }
A dumping ground.
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:275
int stonith__lha_metadata(const char *agent, int timeout, char **output)
Definition: st_lha.c:170
#define LHA_STONITH_LIBRARY
Definition: st_lha.c:29
#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:293
const char * i_hate_pils(int rc)
Definition: st_lha.c:269
int stonith__list_lha_agents(stonith_key_value_t **devices)
Definition: st_lha.c:110
stonith_key_value_t * stonith_key_value_add(stonith_key_value_t *kvp, const char *key, const char *value)
Definition: st_client.c:1927
#define PCMK_DEFAULT_ACTION_TIMEOUT_MS
Default timeout (in milliseconds) for non-metadata actions.
Definition: actions.h:38
#define crm_warn(fmt, args...)
Definition: logging.h:382
stonith_t * st
Definition: pcmk_fence.c:28
#define crm_trace(fmt, args...)
Definition: logging.h:387
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
Wrappers for and extensions to libxml2.
const char * target
Definition: pcmk_fence.c:29
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:323
#define crm_err(fmt, args...)
Definition: logging.h:381
#define CRM_ASSERT(expr)
Definition: results.h:42
Fencing aka. STONITH.
bool stonith__agent_is_lha(const char *agent)
Definition: st_lha.c:83
const char * pcmk__readable_interval(guint interval_ms)
Definition: iso8601.c:1926
unsigned int timeout
Definition: pcmk_fence.c:32