pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
st_rhcs.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 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 <string.h>
14 #include <sys/stat.h>
15 #include <glib.h>
16 #include <dirent.h>
17 
18 #include <crm/crm.h>
19 #include <crm/stonith-ng.h>
20 #include <crm/fencing/internal.h>
21 
30 int
32 {
33  // Essentially: ls -1 @sbin_dir@/fence_*
34 
35  int count = 0, i;
36  struct dirent **namelist;
37  const int file_num = scandir(RH_STONITH_DIR, &namelist, 0, alphasort);
38 
39 #if _POSIX_C_SOURCE < 200809L && !(defined(O_SEARCH) || defined(O_PATH))
40  char buffer[FILENAME_MAX + 1];
41 #elif defined(O_SEARCH)
42  const int dirfd = open(RH_STONITH_DIR, O_SEARCH);
43 #else
44  const int dirfd = open(RH_STONITH_DIR, O_PATH);
45 #endif
46 
47  for (i = 0; i < file_num; i++) {
48  struct stat prop;
49 
50  if (pcmk__starts_with(namelist[i]->d_name, RH_STONITH_PREFIX)) {
51 #if _POSIX_C_SOURCE < 200809L && !(defined(O_SEARCH) || defined(O_PATH))
52  snprintf(buffer, sizeof(buffer), "%s/%s", RH_STONITH_DIR,
53  namelist[i]->d_name);
54  if (stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) {
55 #else
56  if (dirfd == -1) {
57  if (i == 0) {
58  crm_notice("Problem with listing %s directory"
59  CRM_XS "errno=%d", RH_STONITH_PREFIX, errno);
60  }
61  free(namelist[i]);
62  continue;
63  }
64  /* note: we can possibly prevent following symlinks here,
65  which may be a good idea, but fall on the nose when
66  these agents are moved elsewhere & linked back */
67  if (fstatat(dirfd, namelist[i]->d_name, &prop, 0) == 0
68  && S_ISREG(prop.st_mode)) {
69 #endif
70  *devices = stonith_key_value_add(*devices, NULL,
71  namelist[i]->d_name);
72  count++;
73  }
74  }
75  free(namelist[i]);
76  }
77  if (file_num > 0) {
78  free(namelist);
79  }
80 #if _POSIX_C_SOURCE >= 200809L || defined(O_SEARCH) || defined(O_PATH)
81  if (dirfd >= 0) {
82  close(dirfd);
83  }
84 #endif
85  return count;
86 }
87 
88 static void
89 stonith_rhcs_parameter_not_required(xmlNode *metadata, const char *parameter)
90 {
91  char *xpath = NULL;
92  xmlXPathObject *xpathObj = NULL;
93 
94  CRM_CHECK(metadata != NULL, return);
95  CRM_CHECK(parameter != NULL, return);
96 
97  xpath = crm_strdup_printf("//parameter[@name='%s']", parameter);
98  /* Fudge metadata so that the parameter isn't required in config
99  * Pacemaker handles and adds it */
100  xpathObj = xpath_search(metadata, xpath);
101  if (numXpathResults(xpathObj) > 0) {
102  xmlNode *tmp = getXpathResult(xpathObj, 0);
103 
104  crm_xml_add(tmp, "required", "0");
105  }
106  freeXpathObject(xpathObj);
107  free(xpath);
108 }
109 
119 static int
120 stonith__rhcs_get_metadata(const char *agent, int timeout, xmlNode **metadata)
121 {
122  char *buffer = NULL;
123  xmlNode *xml = NULL;
124  xmlNode *actions = NULL;
125  xmlXPathObject *xpathObj = NULL;
126  stonith_action_t *action = stonith_action_create(agent, "metadata", NULL, 0,
127  5, NULL, NULL, NULL);
128  int rc = stonith__execute(action);
129 
130  if (rc < 0) {
131  crm_warn("Could not execute metadata action for %s: %s "
132  CRM_XS " rc=%d", agent, pcmk_strerror(rc), rc);
133  stonith__destroy_action(action);
134  return rc;
135  }
136 
137  stonith__action_result(action, &rc, &buffer, NULL);
138  stonith__destroy_action(action);
139  if (rc < 0) {
140  crm_warn("Metadata action for %s failed: %s " CRM_XS "rc=%d",
141  agent, pcmk_strerror(rc), rc);
142  free(buffer);
143  return rc;
144  }
145 
146  if (buffer == NULL) {
147  crm_warn("Metadata action for %s returned no data", agent);
148  return -ENODATA;
149  }
150 
151  xml = string2xml(buffer);
152  free(buffer);
153  buffer = NULL;
154  if (xml == NULL) {
155  crm_warn("Metadata for %s is invalid", agent);
157  }
158 
159  xpathObj = xpath_search(xml, "//actions");
160  if (numXpathResults(xpathObj) > 0) {
161  actions = getXpathResult(xpathObj, 0);
162  }
163  freeXpathObject(xpathObj);
164 
165  // Add start and stop (implemented by pacemaker, not agent) to meta-data
166  xpathObj = xpath_search(xml, "//action[@name='stop']");
167  if (numXpathResults(xpathObj) <= 0) {
168  xmlNode *tmp = NULL;
169 
170  tmp = create_xml_node(actions, "action");
171  crm_xml_add(tmp, "name", "stop");
172  crm_xml_add(tmp, "timeout", CRM_DEFAULT_OP_TIMEOUT_S);
173 
174  tmp = create_xml_node(actions, "action");
175  crm_xml_add(tmp, "name", "start");
176  crm_xml_add(tmp, "timeout", CRM_DEFAULT_OP_TIMEOUT_S);
177  }
178  freeXpathObject(xpathObj);
179 
180  // Fudge metadata so parameters are not required in config (pacemaker adds them)
181  stonith_rhcs_parameter_not_required(xml, "action");
182  stonith_rhcs_parameter_not_required(xml, "plug");
183  stonith_rhcs_parameter_not_required(xml, "port");
184 
185  if (metadata) {
186  *metadata = xml;
187 
188  } else {
189  free_xml(xml);
190  }
191 
192  return pcmk_ok;
193 }
194 
204 int
205 stonith__rhcs_metadata(const char *agent, int timeout, char **output)
206 {
207  char *buffer = NULL;
208  xmlNode *xml = NULL;
209 
210  int rc = stonith__rhcs_get_metadata(agent, timeout, &xml);
211 
212  if (rc != pcmk_ok) {
213  free_xml(xml);
214  return rc;
215  }
216 
217  buffer = dump_xml_formatted_with_text(xml);
218  free_xml(xml);
219  if (buffer == NULL) {
221  }
222  if (output) {
223  *output = buffer;
224  } else {
225  free(buffer);
226  }
227  return pcmk_ok;
228 }
229 
230 bool
231 stonith__agent_is_rhcs(const char *agent)
232 {
233  struct stat prop;
234  char *buffer = crm_strdup_printf(RH_STONITH_DIR "/%s", agent);
235  int rc = stat(buffer, &prop);
236 
237  free(buffer);
238  return (rc >= 0) && S_ISREG(prop.st_mode);
239 }
240 
241 int
242 stonith__rhcs_validate(stonith_t *st, int call_options, const char *target,
243  const char *agent, GHashTable *params,
244  const char * host_arg, int timeout,
245  char **output, char **error_output)
246 {
247  int rc = pcmk_ok;
248  int remaining_timeout = timeout;
249  xmlNode *metadata = NULL;
250  stonith_action_t *action = NULL;
251 
252  if (host_arg == NULL) {
253  time_t start_time = time(NULL);
254 
255  rc = stonith__rhcs_get_metadata(agent, remaining_timeout, &metadata);
256 
257  if (rc == pcmk_ok) {
258  long long device_flags = stonith__device_parameter_flags(metadata);
259 
260  if (is_set(device_flags, st_device_supports_parameter_port)) {
261  host_arg = "port";
262 
263  } else if (is_set(device_flags, st_device_supports_parameter_plug)) {
264  host_arg = "plug";
265  }
266  }
267 
268  free_xml(metadata);
269 
270  remaining_timeout -= time(NULL) - start_time;
271 
272  if (rc == -ETIME || remaining_timeout <= 0 ) {
273  return -ETIME;
274  }
275 
276  } else if (safe_str_eq(host_arg, "none")) {
277  host_arg = NULL;
278  }
279 
280  action = stonith_action_create(agent, "validate-all",
281  target, 0, remaining_timeout, params,
282  NULL, host_arg);
283 
284  rc = stonith__execute(action);
285  if (rc == pcmk_ok) {
286  stonith__action_result(action, &rc, output, error_output);
287  }
288  stonith__destroy_action(action);
289  return rc;
290 }
void stonith__destroy_action(stonith_action_t *action)
Definition: st_client.c:595
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:233
struct stonith_action_s stonith_action_t
Definition: internal.h:28
#define pcmk_err_schema_validation
Definition: results.h:72
A dumping ground.
#define crm_notice(fmt, args...)
Definition: logging.h:365
const char * pcmk_strerror(int rc)
Definition: results.c:55
#define ETIME
Definition: portability.h:162
void stonith__action_result(stonith_action_t *action, int *rc, char **output, char **error_output)
Definition: st_client.c:626
int stonith__rhcs_metadata(const char *agent, int timeout, char **output)
Execute RHCS-compatible agent&#39;s meta-data action.
Definition: st_rhcs.c:205
int stonith__execute(stonith_action_t *action)
Definition: st_client.c:905
int alphasort(const void *dirent1, const void *dirent2)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:316
stonith_action_t * stonith_action_create(const char *agent, const char *_action, const char *victim, uint32_t victim_nodeid, int timeout, GHashTable *device_args, GHashTable *port_map, const char *host_arg)
Definition: st_client.c:655
const char * action
Definition: pcmk_fence.c:29
xmlNode * string2xml(const char *input)
Definition: xml.c:2180
stonith_key_value_t * stonith_key_value_add(stonith_key_value_t *kvp, const char *key, const char *value)
Definition: st_client.c:2211
#define crm_warn(fmt, args...)
Definition: logging.h:364
bool stonith__agent_is_rhcs(const char *agent)
Definition: st_rhcs.c:231
stonith_t * st
Definition: pcmk_fence.c:27
int rc
Definition: pcmk_fence.c:34
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1976
int stonith__rhcs_validate(stonith_t *st, int call_options, const char *target, const char *agent, GHashTable *params, const char *host_arg, int timeout, char **output, char **error_output)
Definition: st_rhcs.c:242
#define CRM_DEFAULT_OP_TIMEOUT_S
Definition: util.h:138
#define RH_STONITH_PREFIX
Definition: config.h:545
void free_xml(xmlNode *child)
Definition: xml.c:2136
const char * target
Definition: pcmk_fence.c:28
#define CRM_XS
Definition: logging.h:54
#define ENODATA
Definition: portability.h:158
int stonith__list_rhcs_agents(stonith_key_value_t **devices)
Definition: st_rhcs.c:31
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:136
long long stonith__device_parameter_flags(xmlNode *metadata)
Definition: st_client.c:2635
Fencing aka. STONITH.
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition: xpath.c:55
#define pcmk_ok
Definition: results.h:67
bool pcmk__starts_with(const char *str, const char *prefix)
Check whether a string starts with a certain sequence.
Definition: strings.c:358
#define safe_str_eq(a, b)
Definition: util.h:65
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:36
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
unsigned int timeout
Definition: pcmk_fence.c:31
char * dump_xml_formatted_with_text(xmlNode *msg)
Definition: xml.c:3299
#define RH_STONITH_DIR
Definition: config.h:542