pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
st_rhcs.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 #include <glib.h>
14 #include <dirent.h>
15 
16 #include <crm/crm.h>
17 #include <crm/stonith-ng.h>
18 #include <crm/fencing/internal.h>
19 
28 int
30 {
31  // Essentially: ls -1 @sbin_dir@/fence_*
32 
33  int count = 0;
34  struct dirent **namelist;
35  int file_num = scandir(RH_STONITH_DIR, &namelist, 0, alphasort);
36 
37  if (file_num > 0) {
38  struct stat prop;
39  char buffer[FILENAME_MAX + 1];
40 
41  while (file_num--) {
42  if ('.' == namelist[file_num]->d_name[0]) {
43  free(namelist[file_num]);
44  continue;
45 
46  } else if (!crm_starts_with(namelist[file_num]->d_name,
48  free(namelist[file_num]);
49  continue;
50  }
51 
52  snprintf(buffer, FILENAME_MAX, "%s/%s", RH_STONITH_DIR,
53  namelist[file_num]->d_name);
54  if (stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) {
55  *devices = stonith_key_value_add(*devices, NULL,
56  namelist[file_num]->d_name);
57  count++;
58  }
59 
60  free(namelist[file_num]);
61  }
62  free(namelist);
63  }
64  return count;
65 }
66 
67 static void
68 stonith_rhcs_parameter_not_required(xmlNode *metadata, const char *parameter)
69 {
70  char *xpath = NULL;
71  xmlXPathObject *xpathObj = NULL;
72 
73  CRM_CHECK(metadata != NULL, return);
74  CRM_CHECK(parameter != NULL, return);
75 
76  xpath = crm_strdup_printf("//parameter[@name='%s']", parameter);
77  /* Fudge metadata so that the parameter isn't required in config
78  * Pacemaker handles and adds it */
79  xpathObj = xpath_search(metadata, xpath);
80  if (numXpathResults(xpathObj) > 0) {
81  xmlNode *tmp = getXpathResult(xpathObj, 0);
82 
83  crm_xml_add(tmp, "required", "0");
84  }
85  freeXpathObject(xpathObj);
86  free(xpath);
87 }
88 
98 static int
99 stonith__rhcs_get_metadata(const char *agent, int timeout, xmlNode **metadata)
100 {
101  char *buffer = NULL;
102  xmlNode *xml = NULL;
103  xmlNode *actions = NULL;
104  xmlXPathObject *xpathObj = NULL;
105  stonith_action_t *action = stonith_action_create(agent, "metadata", NULL, 0,
106  5, NULL, NULL, NULL);
107  int rc = stonith__execute(action);
108 
109  if (rc < 0) {
110  crm_warn("Could not execute metadata action for %s: %s "
111  CRM_XS " rc=%d", agent, pcmk_strerror(rc), rc);
112  stonith__destroy_action(action);
113  return rc;
114  }
115 
116  stonith__action_result(action, &rc, &buffer, NULL);
117  stonith__destroy_action(action);
118  if (rc < 0) {
119  crm_warn("Metadata action for %s failed: %s " CRM_XS "rc=%d",
120  agent, pcmk_strerror(rc), rc);
121  free(buffer);
122  return rc;
123  }
124 
125  if (buffer == NULL) {
126  crm_warn("Metadata action for %s returned no data", agent);
127  return -ENODATA;
128  }
129 
130  xml = string2xml(buffer);
131  free(buffer);
132  buffer = NULL;
133  if (xml == NULL) {
134  crm_warn("Metadata for %s is invalid", agent);
136  }
137 
138  xpathObj = xpath_search(xml, "//actions");
139  if (numXpathResults(xpathObj) > 0) {
140  actions = getXpathResult(xpathObj, 0);
141  }
142  freeXpathObject(xpathObj);
143 
144  // Add start and stop (implemented by pacemaker, not agent) to meta-data
145  xpathObj = xpath_search(xml, "//action[@name='stop']");
146  if (numXpathResults(xpathObj) <= 0) {
147  xmlNode *tmp = NULL;
148 
149  tmp = create_xml_node(actions, "action");
150  crm_xml_add(tmp, "name", "stop");
151  crm_xml_add(tmp, "timeout", CRM_DEFAULT_OP_TIMEOUT_S);
152 
153  tmp = create_xml_node(actions, "action");
154  crm_xml_add(tmp, "name", "start");
155  crm_xml_add(tmp, "timeout", CRM_DEFAULT_OP_TIMEOUT_S);
156  }
157  freeXpathObject(xpathObj);
158 
159  // Fudge metadata so parameters are not required in config (pacemaker adds them)
160  stonith_rhcs_parameter_not_required(xml, "action");
161  stonith_rhcs_parameter_not_required(xml, "plug");
162  stonith_rhcs_parameter_not_required(xml, "port");
163 
164  if (metadata) {
165  *metadata = xml;
166 
167  } else {
168  free_xml(xml);
169  }
170 
171  return pcmk_ok;
172 }
173 
183 int
184 stonith__rhcs_metadata(const char *agent, int timeout, char **output)
185 {
186  char *buffer = NULL;
187  xmlNode *xml = NULL;
188 
189  int rc = stonith__rhcs_get_metadata(agent, timeout, &xml);
190 
191  if (rc != pcmk_ok) {
192  free_xml(xml);
193  return rc;
194  }
195 
196  buffer = dump_xml_formatted_with_text(xml);
197  free_xml(xml);
198  if (buffer == NULL) {
200  }
201  if (output) {
202  *output = buffer;
203  } else {
204  free(buffer);
205  }
206  return pcmk_ok;
207 }
208 
209 bool
210 stonith__agent_is_rhcs(const char *agent)
211 {
212  struct stat prop;
213  char *buffer = crm_strdup_printf(RH_STONITH_DIR "/%s", agent);
214  int rc = stat(buffer, &prop);
215 
216  free(buffer);
217  return (rc >= 0) && S_ISREG(prop.st_mode);
218 }
219 
220 int
221 stonith__rhcs_validate(stonith_t *st, int call_options, const char *target,
222  const char *agent, GHashTable *params,
223  const char * host_arg, int timeout,
224  char **output, char **error_output)
225 {
226  int rc = pcmk_ok;
227  int remaining_timeout = timeout;
228  xmlNode *metadata = NULL;
229  stonith_action_t *action = NULL;
230 
231  if (host_arg == NULL) {
232  time_t start_time = time(NULL);
233 
234  rc = stonith__rhcs_get_metadata(agent, remaining_timeout, &metadata);
235 
236  if (rc == pcmk_ok) {
237  long long device_flags = stonith__device_parameter_flags(metadata);
238 
239  if (is_set(device_flags, st_device_supports_parameter_port)) {
240  host_arg = "port";
241 
242  } else if (is_set(device_flags, st_device_supports_parameter_plug)) {
243  host_arg = "plug";
244  }
245  }
246 
247  free_xml(metadata);
248 
249  remaining_timeout -= time(NULL) - start_time;
250 
251  if (rc == -ETIME || remaining_timeout <= 0 ) {
252  return -ETIME;
253  }
254 
255  } else if (safe_str_eq(host_arg, "none")) {
256  host_arg = NULL;
257  }
258 
259  action = stonith_action_create(agent, "validate-all",
260  target, 0, remaining_timeout, params,
261  NULL, host_arg);
262 
263  rc = stonith__execute(action);
264  if (rc == pcmk_ok) {
265  stonith__action_result(action, &rc, output, error_output);
266  }
267  stonith__destroy_action(action);
268  return rc;
269 }
void stonith__destroy_action(stonith_action_t *action)
Definition: st_client.c:700
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:190
struct stonith_action_s stonith_action_t
Definition: internal.h:24
A dumping ground.
bool stonith__agent_is_rhcs(const char *agent)
Definition: st_rhcs.c:210
#define ETIME
Definition: portability.h:250
void stonith__action_result(stonith_action_t *action, int *rc, char **output, char **error_output)
Definition: st_client.c:731
int stonith__execute(stonith_action_t *action)
Definition: st_client.c:1010
const char * pcmk_strerror(int rc)
Definition: logging.c:1017
#define pcmk_ok
Definition: error.h:45
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:216
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:760
int stonith__rhcs_metadata(const char *agent, int timeout, char **output)
Execute RHCS-compatible agent&#39;s meta-data action.
Definition: st_rhcs.c:184
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:221
bool crm_starts_with(const char *str, const char *prefix)
Check whether a string starts with a certain sequence.
Definition: strings.c:284
xmlNode * string2xml(const char *input)
Definition: xml.c:2152
stonith_key_value_t * stonith_key_value_add(stonith_key_value_t *kvp, const char *key, const char *value)
Definition: st_client.c:2265
#define crm_warn(fmt, args...)
Definition: logging.h:275
#define pcmk_err_schema_validation
Definition: error.h:50
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1977
#define CRM_DEFAULT_OP_TIMEOUT_S
Definition: util.h:137
#define RH_STONITH_PREFIX
Definition: config.h:694
void free_xml(xmlNode *child)
Definition: xml.c:2108
#define CRM_XS
Definition: logging.h:42
#define ENODATA
Definition: portability.h:246
int stonith__list_rhcs_agents(stonith_key_value_t **devices)
Definition: st_rhcs.c:29
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:145
long long stonith__device_parameter_flags(xmlNode *metadata)
Definition: st_client.c:2433
Fencing aka. STONITH.
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition: xpath.c:64
#define safe_str_eq(a, b)
Definition: util.h:74
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:45
char * dump_xml_formatted_with_text(xmlNode *msg)
Definition: xml.c:3200
#define RH_STONITH_DIR
Definition: config.h:691