1 /* 2 * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This software is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /** 20 * \file 21 * \brief Fencing aka. STONITH 22 * \ingroup fencing 23 */ 24 25 #ifndef STONITH_NG__H 26 # define STONITH_NG__H 27 28 # include <dlfcn.h> 29 # include <errno.h> 30 # include <stdbool.h> 31 32 /* TO-DO: Work out how to drop this requirement */ 33 # include <libxml/tree.h> 34 35 # define T_STONITH_NOTIFY_DISCONNECT "st_notify_disconnect" 36 # define T_STONITH_NOTIFY_FENCE "st_notify_fence" 37 38 /* *INDENT-OFF* */ 39 enum stonith_state { 40 stonith_connected_command, 41 stonith_connected_query, 42 stonith_disconnected, 43 }; 44 45 enum stonith_call_options { 46 st_opt_none = 0x00000000, 47 st_opt_verbose = 0x00000001, 48 st_opt_allow_suicide = 0x00000002, 49 50 st_opt_manual_ack = 0x00000008, 51 st_opt_discard_reply = 0x00000010, 52 /* st_opt_all_replies = 0x00000020, */ 53 st_opt_topology = 0x00000040, 54 st_opt_scope_local = 0x00000100, 55 st_opt_cs_nodeid = 0x00000200, 56 st_opt_sync_call = 0x00001000, 57 /*! Allow the timeout period for a callback to be adjusted 58 * based on the time the server reports the operation will take. */ 59 st_opt_timeout_updates = 0x00002000, 60 /*! Only report back if operation is a success in callback */ 61 st_opt_report_only_success = 0x00004000, 62 }; 63 64 /*! Order matters here, do not change values */ 65 enum op_state 66 { 67 st_query, 68 st_exec, 69 st_done, 70 st_duplicate, 71 st_failed, 72 }; 73 74 typedef struct stonith_key_value_s { 75 char *key; 76 char *value; 77 struct stonith_key_value_s *next; 78 } stonith_key_value_t; 79 80 typedef struct stonith_history_s { 81 char *target; 82 char *action; 83 char *origin; 84 char *delegate; 85 int completed; 86 int state; 87 88 struct stonith_history_s *next; 89 char *client; 90 } stonith_history_t; 91 92 typedef struct stonith_s stonith_t; 93 94 typedef struct stonith_event_s 95 { 96 char *id; 97 char *type; 98 char *message; 99 char *operation; 100 101 int result; 102 char *origin; 103 char *target; 104 char *action; 105 char *executioner; 106 107 char *device; 108 109 /*! The name of the client that initiated the action. */ 110 char *client_origin; 111 112 } stonith_event_t; 113 114 typedef struct stonith_callback_data_s 115 { 116 int rc; 117 int call_id; 118 void *userdata; 119 } stonith_callback_data_t; 120 121 typedef struct stonith_api_operations_s 122 { 123 /*! 124 * \brief Destroy the stonith api structure. 125 */ 126 int (*free) (stonith_t *st); 127 128 /*! 129 * \brief Connect to the local stonith daemon. 130 * 131 * \retval 0, success 132 * \retval negative error code on failure 133 */ 134 int (*connect) (stonith_t *st, const char *name, int *stonith_fd); 135 136 /*! 137 * \brief Disconnect from the local stonith daemon. 138 * 139 * \retval 0, success 140 * \retval negative error code on failure 141 */ 142 int (*disconnect)(stonith_t *st); 143 144 /*! 145 * \brief Remove a registered stonith device with the local stonith daemon. 146 * 147 * \note Synchronous, guaranteed to occur in daemon before function returns. 148 * 149 * \retval 0, success 150 * \retval negative error code on failure 151 */ 152 int (*remove_device)( 153 stonith_t *st, int options, const char *name); 154 155 /*! 156 * \brief Register a stonith device with the local stonith daemon. 157 * 158 * \note Synchronous, guaranteed to occur in daemon before function returns. 159 * 160 * \retval 0, success 161 * \retval negative error code on failure 162 */ 163 int (*register_device)( 164 stonith_t *st, int options, const char *id, 165 const char *namespace, const char *agent, stonith_key_value_t *params); 166 167 /*! 168 * \brief Remove a fencing level for a specific node. 169 * 170 * \note This feature is not available when stonith is in standalone mode. 171 * 172 * \retval 0, success 173 * \retval negative error code on failure 174 */ 175 int (*remove_level)( 176 stonith_t *st, int options, const char *node, int level); 177 178 /*! 179 * \brief Register a fencing level containing the fencing devices to be used 180 * at that level for a specific node. 181 * 182 * \note This feature is not available when stonith is in standalone mode. 183 * 184 * \retval 0, success 185 * \retval negative error code on failure 186 */ 187 int (*register_level)( 188 stonith_t *st, int options, const char *node, int level, stonith_key_value_t *device_list); 189 190 /*! 191 * \brief Get the metadata documentation for a resource. 192 * 193 * \note Value is returned in output. Output must be freed when set. 194 * 195 * \retval 0 success 196 * \retval negative error code on failure 197 */ 198 int (*metadata)(stonith_t *st, int options, 199 const char *device, const char *namespace, char **output, int timeout); 200 201 /*! 202 * \brief Retrieve a list of installed stonith agents 203 * 204 * \note if namespace is not provided, all known agents will be returned 205 * \note list must be freed using stonith_key_value_freeall() 206 * \note call_options parameter is not used, it is reserved for future use. 207 * 208 * \retval num items in list on success 209 * \retval negative error code on failure 210 */ 211 int (*list_agents)(stonith_t *stonith, int call_options, const char *namespace, 212 stonith_key_value_t **devices, int timeout); 213 214 /*! 215 * \brief Retrieve string listing hosts and port assignments from a local stonith device. 216 * 217 * \retval 0 on success 218 * \retval negative error code on failure 219 */ 220 int (*list)(stonith_t *st, int options, const char *id, char **list_output, int timeout); 221 222 /*! 223 * \brief Check to see if a local stonith device is reachable 224 * 225 * \retval 0 on success 226 * \retval negative error code on failure 227 */ 228 int (*monitor)(stonith_t *st, int options, const char *id, int timeout); 229 230 /*! 231 * \brief Check to see if a local stonith device's port is reachable 232 * 233 * \retval 0 on success 234 * \retval negative error code on failure 235 */ 236 int (*status)(stonith_t *st, int options, const char *id, const char *port, int timeout); 237 238 /*! 239 * \brief Retrieve a list of registered stonith devices. 240 * 241 * \note If node is provided, only devices that can fence the node id 242 * will be returned. 243 * 244 * \retval num items in list on success 245 * \retval negative error code on failure 246 */ 247 int (*query)(stonith_t *st, int options, const char *node, 248 stonith_key_value_t **devices, int timeout); 249 250 /*! 251 * \brief Issue a fencing action against a node. 252 * 253 * \note Possible actions are, 'on', 'off', and 'reboot'. 254 * 255 * \param st, stonith connection 256 * \param options, call options 257 * \param node, The target node to fence 258 * \param action, The fencing action to take 259 * \param timeout, The default per device timeout to use with each device 260 * capable of fencing the target. 261 * 262 * \retval 0 success 263 * \retval negative error code on failure. 264 */ 265 int (*fence)(stonith_t *st, int options, const char *node, const char *action, 266 int timeout, int tolerance); 267 268 /*! 269 * \brief Manually confirm that a node is down. 270 * 271 * \retval 0 success 272 * \retval negative error code on failure. 273 */ 274 int (*confirm)(stonith_t *st, int options, const char *node); 275 276 /*! 277 * \brief Retrieve a list of fencing operations that have occurred for a specific node. 278 * 279 * \note History is not available in standalone mode. 280 * 281 * \retval 0 success 282 * \retval negative error code on failure. 283 */ 284 int (*history)(stonith_t *st, int options, const char *node, stonith_history_t **output, int timeout); 285 286 int (*register_notification)( 287 stonith_t *st, const char *event, 288 void (*notify)(stonith_t *st, stonith_event_t *e)); 289 int (*remove_notification)(stonith_t *st, const char *event); 290 291 /*! 292 * \brief Register a callback to receive the result of an async call id 293 * 294 * \param call_id, The call id to register the callback for. 295 * \param timeout, The default timeout period to wait until this callback expires 296 * \param options, Option flags, st_opt_timeout_updates and st_opt_report_only_success are the 297 * only valid options for this function. 298 * \param userdate, A pointer that will be handed back in the callback. 299 * \param callback_name, Unique name given to callback 300 * \param callback, The callback function 301 * 302 * \retval 0 success 303 * \retval negative error code on failure. 304 */ 305 int (*register_callback)(stonith_t *st, 306 int call_id, 307 int timeout, 308 int options, 309 void *userdata, 310 const char *callback_name, 311 void (*callback)(stonith_t *st, stonith_callback_data_t *data)); 312 313 /*! 314 * \brief Remove a registered callback for a given call id. 315 */ 316 int (*remove_callback)(stonith_t *st, int call_id, bool all_callbacks); 317 318 /*! 319 * \brief Remove fencing level for specific node, node regex or attribute 320 * 321 * \param[in] st Stonithd connection to use 322 * \param[in] options Bitmask of stonith_call_options to pass to stonithd 323 * \param[in] node If not NULL, target level by this node name 324 * \param[in] pattern If not NULL, target by node name using this regex 325 * \param[in] attr If not NULL, target by this node attribute 326 * \param[in] value If not NULL, target by this node attribute value 327 * \param[in] level Index number of level to remove 328 * 329 * \return 0 on success, negative error code otherwise 330 * 331 * \note This feature is not available when stonith is in standalone mode. 332 * The caller should set only one of node, pattern or attr/value. 333 */ 334 int (*remove_level_full)(stonith_t *st, int options, 335 const char *node, const char *pattern, 336 const char *attr, const char *value, int level); 337 338 /*! 339 * \brief Register fencing level for specific node, node regex or attribute 340 * 341 * \param[in] st Stonithd connection to use 342 * \param[in] options Bitmask of stonith_call_options to pass to stonithd 343 * \param[in] node If not NULL, target level by this node name 344 * \param[in] pattern If not NULL, target by node name using this regex 345 * \param[in] attr If not NULL, target by this node attribute 346 * \param[in] value If not NULL, target by this node attribute value 347 * \param[in] level Index number of level to add 348 * \param[in] device_list Devices to use in level 349 * 350 * \return 0 on success, negative error code otherwise 351 * 352 * \note This feature is not available when stonith is in standalone mode. 353 * The caller should set only one of node, pattern or attr/value. 354 */ 355 int (*register_level_full)(stonith_t *st, int options, 356 const char *node, const char *pattern, 357 const char *attr, const char *value, 358 int level, stonith_key_value_t *device_list); 359 360 } stonith_api_operations_t; 361 362 struct stonith_s 363 { 364 enum stonith_state state; 365 366 int call_id; 367 int call_timeout; 368 void *private; 369 370 stonith_api_operations_t *cmds; 371 }; 372 /* *INDENT-ON* */ 373 374 /* Core functions */ 375 stonith_t *stonith_api_new(void); 376 void stonith_api_delete(stonith_t * st); 377 378 void stonith_dump_pending_callbacks(stonith_t * st); 379 380 const char *get_stonith_provider(const char *agent, const char *provider); 381 382 bool stonith_dispatch(stonith_t * st); 383 384 stonith_key_value_t *stonith_key_value_add(stonith_key_value_t * kvp, const char *key, 385 const char *value); 386 void stonith_key_value_freeall(stonith_key_value_t * kvp, int keys, int values); 387 388 /* Basic helpers that allows nodes to be fenced and the history to be 389 * queried without mainloop or the caller understanding the full API 390 * 391 * At least one of nodeid and uname are required 392 */ 393 int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off); 394 time_t stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress); 395 396 /* 397 * Helpers for using the above functions without install-time dependencies 398 * 399 * Usage: 400 * #include <crm/stonith-ng.h> 401 * 402 * To turn a node off by corosync nodeid: 403 * stonith_api_kick_helper(nodeid, 120, 1); 404 * 405 * To check the last fence date/time (also by nodeid): 406 * last = stonith_api_time_helper(nodeid, 0); 407 * 408 * To check if fencing is in progress: 409 * if(stonith_api_time_helper(nodeid, 1) > 0) { ... } 410 * 411 * eg. 412 413 #include <stdio.h> 414 #include <time.h> 415 #include <crm/stonith-ng.h> 416 int 417 main(int argc, char ** argv) 418 { 419 int rc = 0; 420 int nodeid = 102; 421 422 rc = stonith_api_time_helper(nodeid, 0); 423 printf("%d last fenced at %s\n", nodeid, ctime(rc)); 424 425 rc = stonith_api_kick_helper(nodeid, 120, 1); 426 printf("%d fence result: %d\n", nodeid, rc); 427 428 rc = stonith_api_time_helper(nodeid, 0); 429 printf("%d last fenced at %s\n", nodeid, ctime(rc)); 430 431 return 0; 432 } 433 434 */ 435 436 # define STONITH_LIBRARY "libstonithd.so.2" 437 438 static inline int 439 stonith_api_kick_helper(uint32_t nodeid, int timeout, bool off) /* */ 440 { 441 static void *st_library = NULL; 442 static int (*st_kick_fn) (int nodeid, const char *uname, int timeout, bool off) = NULL; 443 444 if (st_library == NULL) { 445 st_library = dlopen(STONITH_LIBRARY, RTLD_LAZY); 446 } 447 if (st_library && st_kick_fn == NULL) { 448 st_kick_fn = dlsym(st_library, "stonith_api_kick"); 449 } 450 if (st_kick_fn == NULL) { 451 #ifdef ELIBACC 452 return -ELIBACC; 453 #else 454 return -ENOSYS; 455 #endif 456 } 457 458 return (*st_kick_fn) (nodeid, NULL, timeout, off); 459 } 460 461 static inline time_t 462 stonith_api_time_helper(uint32_t nodeid, bool in_progress) /* */ 463 { 464 static void *st_library = NULL; 465 static time_t(*st_time_fn) (int nodeid, const char *uname, bool in_progress) = NULL; 466 467 if (st_library == NULL) { 468 st_library = dlopen(STONITH_LIBRARY, RTLD_LAZY); 469 } 470 if (st_library && st_time_fn == NULL) { 471 st_time_fn = dlsym(st_library, "stonith_api_time"); 472 } 473 if (st_time_fn == NULL) { 474 return 0; 475 } 476 477 return (*st_time_fn) (nodeid, NULL, in_progress); 478 } 479 480 #endif