20 #include <sys/types.h>
36 struct stonith_action_s {
45 void (*done_cb) (GPid
pid, gint status,
const char *output, gpointer user_data);
46 void (*fork_cb) (GPid
pid, gpointer user_data);
51 time_t initial_start_time;
53 int remaining_timeout;
63 typedef struct stonith_private_s {
67 GHashTable *stonith_op_callback_table;
76 typedef struct stonith_notify_client_s {
85 typedef struct stonith_callback_client_s {
89 gboolean only_success;
90 gboolean allow_timeout_updates;
95 struct notify_blob_s {
107 typedef int (*
stonith_op_t) (
const char *, int,
const char *, xmlNode *,
108 xmlNode *, xmlNode *, xmlNode **, xmlNode **);
113 static int stonith_send_command(
stonith_t *stonith,
const char *op,
114 xmlNode *
data, xmlNode **output_data,
115 int call_options,
int timeout);
117 static void stonith_connection_destroy(gpointer user_data);
118 static void stonith_send_notification(gpointer
data, gpointer user_data);
135 }
else if (!strcmp(namespace_s,
"redhat")
136 || !strcmp(namespace_s,
"stonith-ng")) {
139 }
else if (!strcmp(namespace_s,
"internal")) {
142 }
else if (!strcmp(namespace_s,
"heartbeat")) {
158 switch (st_namespace) {
165 return "unsupported";
187 #if HAVE_STONITH_STONITH_H
193 crm_err(
"Unknown fence agent: %s", agent);
226 private->notify_refcnt++;
227 g_list_foreach(private->notify_list, func, user_data);
228 private->notify_refcnt--;
229 if ((private->notify_refcnt == 0) &&
230 private->notify_deletes) {
231 GList *list_item =
private->notify_list;
233 private->notify_deletes = FALSE;
234 while (list_item != NULL)
237 GList *next = g_list_next(list_item);
239 if (list_client->delete) {
241 private->notify_list =
242 g_list_delete_link(private->notify_list, list_item);
250 stonith_connection_destroy(gpointer user_data)
254 struct notify_blob_s blob;
256 crm_trace(
"Sending destroyed notification");
257 blob.stonith = stonith;
262 native->source = NULL;
264 free(native->token); native->token = NULL;
269 foreach_notify_entry(native, stonith_send_notification, &blob);
276 const char *rsc_provides)
281 #if HAVE_STONITH_STONITH_H
286 hash2field((gpointer)
"plugin", (gpointer) agent, args);
287 agent =
"fence_legacy";
301 for (; params; params = params->
next) {
309 stonith_api_register_device(
stonith_t *
st,
int call_options,
310 const char *
id,
const char *
namespace,
const char *agent,
314 xmlNode *
data = NULL;
317 agent, params, NULL);
326 stonith_api_remove_device(
stonith_t *
st,
int call_options,
const char *
name)
329 xmlNode *
data = NULL;
341 stonith_api_remove_level_full(
stonith_t *
st,
int options,
342 const char *node,
const char *pattern,
343 const char *attr,
const char *value,
int level)
346 xmlNode *
data = NULL;
348 CRM_CHECK(node || pattern || (attr && value),
return -EINVAL);
356 }
else if (pattern) {
372 stonith_api_remove_level(
stonith_t *
st,
int options,
const char *node,
int level)
374 return stonith_api_remove_level_full(
st, options, node,
375 NULL, NULL, NULL, level);
395 const char *attr,
const char *value,
402 CRM_CHECK(node || pattern || (attr && value),
return NULL);
414 }
else if (pattern) {
424 for (; device_list; device_list = device_list->
next) {
435 stonith_api_register_level_full(
stonith_t *
st,
int options,
const char *node,
437 const char *attr,
const char *value,
452 stonith_api_register_level(
stonith_t *
st,
int options,
const char *node,
int level,
455 return stonith_api_register_level_full(
st, options, node, NULL, NULL, NULL,
460 append_arg(
const char *key,
const char *value, GHashTable **args)
466 if (strstr(key,
"pcmk_")) {
475 *args = crm_str_table_new();
479 crm_trace(
"Appending: %s=%s", key, value);
480 g_hash_table_replace(*args, strdup(key), strdup(value));
484 append_config_arg(gpointer key, gpointer value, gpointer user_data)
491 append_arg(key, value, user_data);
497 make_args(
const char *agent,
const char *
action,
const char *victim,
498 uint32_t victim_nodeid, GHashTable * device_args,
499 GHashTable * port_map,
const char *host_arg)
502 GHashTable *arg_list = NULL;
503 const char *value = NULL;
507 snprintf(buffer,
sizeof(buffer),
"pcmk_%s_action",
action);
509 value = g_hash_table_lookup(device_args, buffer);
512 crm_debug(
"Substituting action '%s' for requested operation '%s'", value,
action);
517 if (victim && device_args) {
518 const char *alias = victim;
521 if (port_map && g_hash_table_lookup(port_map, victim)) {
522 alias = g_hash_table_lookup(port_map, victim);
528 append_arg(
"nodename", victim, &arg_list);
530 char nodeid_str[33] = { 0, };
531 if (snprintf(nodeid_str, 33,
"%u", (
unsigned int)victim_nodeid)) {
532 crm_info(
"For stonith action (%s) for victim %s, adding nodeid (%s) to parameters",
533 action, victim, nodeid_str);
534 append_arg(
"nodeid", nodeid_str, &arg_list);
542 }
else if (param == NULL) {
544 if (host_arg == NULL) {
551 value = g_hash_table_lookup(device_args, param);
557 value = g_hash_table_lookup(device_args, param);
562 crm_debug(
"Performing '%s' action targeting '%s' as '%s=%s'",
action, victim, param,
564 append_arg(param, alias, &arg_list);
569 g_hash_table_foreach(device_args, append_config_arg, &arg_list);
587 g_hash_table_destroy(
action->args);
623 *error_output = NULL;
629 if (output &&
action->output) {
633 if (error_output &&
action->error) {
634 *error_output =
action->error;
640 #define FAILURE_MAX_RETRIES 2
645 uint32_t victim_nodeid,
646 int timeout, GHashTable * device_args,
647 GHashTable * port_map,
const char *host_arg)
652 action->args = make_args(agent, _action, victim, victim_nodeid,
653 device_args, port_map, host_arg);
654 crm_debug(
"Preparing '%s' action for %s using agent %s",
655 _action, (victim? victim :
"no target"), agent);
656 action->agent = strdup(agent);
657 action->action = strdup(_action);
659 action->victim = strdup(victim);
666 const char *value = NULL;
668 snprintf(buffer,
sizeof(buffer),
"pcmk_%s_retries", _action);
669 value = g_hash_table_lookup(device_args, buffer);
672 action->max_retries = atoi(value);
682 int diff = time(NULL) -
action->initial_start_time;
685 crm_info(
"Attempted to execute agent %s (%s) the maximum number of times (%d) allowed",
687 action->remaining_timeout = 0;
693 action->remaining_timeout = 0;
695 return action->remaining_timeout ? TRUE : FALSE;
702 if (svc_action->
rc > 0) {
712 }
else if (strstr(svc_action->
stderr_data,
"imed out")) {
716 }
else if (strstr(svc_action->
stderr_data,
"Unrecognised action")) {
731 action->rc = svc_action_to_errno(svc_action);
737 svc_action->
params = NULL;
739 crm_debug(
"Child process %d performing action '%s' exited with rc %d",
745 int rc = internal_stonith_action_execute(
action);
755 action->svc_action = NULL;
765 action->svc_action = svc_action;
771 crm_trace(
"Child process %d performing action '%s' successfully forked",
781 static int stonith_sequence = 0;
785 action->initial_start_time = time(NULL);
790 crm_info(
"Attempt %d to execute %s (%s). remaining timeout is %d",
806 svc_action->
sequence = stonith_sequence++;
809 svc_action->
flags = pcmk__set_flags_as(__func__, __LINE__,
811 svc_action->
id, svc_action->
flags,
813 "SVC_ACTION_NON_BLOCKED");
827 &stonith_action_async_done,
828 &stonith_action_async_forked) == FALSE) {
839 action->rc = svc_action_to_errno(svc_action);
845 action->rc = -ECONNABORTED;
849 svc_action->
params = NULL;
871 void (*done) (GPid
pid,
int rc,
const char *output,
873 void (*fork_cb) (GPid
pid, gpointer user_data))
879 action->userdata = userdata;
881 action->fork_cb = fork_cb;
884 return internal_stonith_action_execute(
action);
904 rc = internal_stonith_action_execute(
action);
911 stonith_api_device_list(
stonith_t * stonith,
int call_options,
const char *
namespace,
917 if (devices == NULL) {
918 crm_err(
"Parameter error: stonith_api_device_list");
922 #if HAVE_STONITH_STONITH_H
938 stonith_api_device_metadata(
stonith_t * stonith,
int call_options,
const char *agent,
939 const char *
namespace,
char **output,
int timeout)
947 crm_trace(
"Looking up metadata for %s agent %s",
954 #if HAVE_STONITH_STONITH_H
960 crm_err(
"Can't get fence agent '%s' meta-data: No such agent",
968 stonith_api_query(
stonith_t * stonith,
int call_options,
const char *
target,
971 int rc = 0, lpc = 0, max = 0;
973 xmlNode *
data = NULL;
974 xmlNode *output = NULL;
975 xmlXPathObjectPtr xpathObj = NULL;
977 CRM_CHECK(devices != NULL,
return -EINVAL);
991 max = numXpathResults(xpathObj);
993 for (lpc = 0; lpc < max; lpc++) {
998 xmlChar *match_path = xmlGetNodePath(match);
1000 crm_info(
"%s[%d] = %s",
"//@agent", lpc, match_path);
1018 const char *
action,
const char *victim,
int timeout, xmlNode ** output)
1021 xmlNode *
data = NULL;
1036 stonith_api_list(
stonith_t * stonith,
int call_options,
const char *
id,
char **list_info,
1040 xmlNode *output = NULL;
1042 rc = stonith_api_call(stonith, call_options,
id,
"list", NULL,
timeout, &output);
1044 if (output && list_info) {
1045 const char *list_str;
1050 *list_info = strdup(list_str);
1062 stonith_api_monitor(
stonith_t * stonith,
int call_options,
const char *
id,
int timeout)
1064 return stonith_api_call(stonith, call_options,
id,
"monitor", NULL,
timeout, NULL);
1068 stonith_api_status(
stonith_t * stonith,
int call_options,
const char *
id,
const char *port,
1071 return stonith_api_call(stonith, call_options,
id,
"status", port,
timeout, NULL);
1075 stonith_api_fence_with_delay(
stonith_t * stonith,
int call_options,
const char *node,
1079 xmlNode *
data = NULL;
1095 stonith_api_fence(
stonith_t * stonith,
int call_options,
const char *node,
const char *
action,
1098 return stonith_api_fence_with_delay(stonith, call_options, node,
action,
1103 stonith_api_confirm(
stonith_t * stonith,
int call_options,
const char *
target)
1106 return stonith_api_fence(stonith, call_options,
target,
"off", 0, 0);
1110 stonith_api_history(
stonith_t * stonith,
int call_options,
const char *node,
1114 xmlNode *
data = NULL;
1115 xmlNode *output = NULL;
1135 for (op = pcmk__xml_first_child(reply); op != NULL;
1136 op = pcmk__xml_next(op)) {
1138 long long completed;
1168 for (hp = history; hp; hp_old = hp, hp = hp->
next, free(hp_old)) {
1178 stonithlib_GCompareFunc(gconstpointer a, gconstpointer b)
1184 if (a_client->delete || b_client->delete) {
1188 CRM_CHECK(a_client->event != NULL && b_client->event != NULL,
return 0);
1189 rc = strcmp(a_client->event, b_client->event);
1191 if (a_client->notify == NULL || b_client->notify == NULL) {
1194 }
else if (a_client->notify == b_client->notify) {
1197 }
else if (((
long)a_client->notify) < ((
long)b_client->notify)) {
1198 crm_err(
"callbacks for %s are not equal: %p vs. %p",
1199 a_client->event, a_client->notify, b_client->notify);
1202 crm_err(
"callbacks for %s are not equal: %p vs. %p",
1203 a_client->event, a_client->notify, b_client->notify);
1223 crm_trace(
"Sending call options: %.8lx, %d", (
long)call_options, call_options);
1234 stonith_destroy_op_callback(gpointer
data)
1238 if (blob->timer && blob->timer->ref > 0) {
1239 g_source_remove(blob->timer->ref);
1246 stonith_api_signoff(
stonith_t * stonith)
1250 crm_debug(
"Disconnecting from the fencer");
1252 if (native->source != NULL) {
1255 native->source = NULL;
1258 }
else if (native->ipc) {
1267 free(native->token); native->token = NULL;
1273 stonith_api_del_callback(
stonith_t * stonith,
int call_id,
bool all_callbacks)
1277 if (all_callbacks) {
1278 private->op_callback = NULL;
1279 g_hash_table_destroy(private->stonith_op_callback_table);
1280 private->stonith_op_callback_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1282 stonith_destroy_op_callback);
1284 }
else if (call_id == 0) {
1285 private->op_callback = NULL;
1288 g_hash_table_remove(private->stonith_op_callback_table, GINT_TO_POINTER(call_id));
1294 invoke_callback(
stonith_t *
st,
int call_id,
int rc,
void *userdata,
1299 data.call_id = call_id;
1301 data.userdata = userdata;
1307 stonith_perform_callback(
stonith_t * stonith, xmlNode * msg,
int call_id,
int rc)
1318 local_blob.id = NULL;
1319 local_blob.callback = NULL;
1320 local_blob.user_data = NULL;
1321 local_blob.only_success = FALSE;
1330 blob = g_hash_table_lookup(private->stonith_op_callback_table, GINT_TO_POINTER(call_id));
1336 stonith_api_del_callback(stonith, call_id, FALSE);
1339 crm_trace(
"No callback found for call %d", call_id);
1340 local_blob.callback = NULL;
1343 if (local_blob.callback != NULL && (
rc ==
pcmk_ok || local_blob.only_success == FALSE)) {
1344 crm_trace(
"Invoking callback %s for call %d",
crm_str(local_blob.id), call_id);
1345 invoke_callback(stonith, call_id,
rc, local_blob.user_data, local_blob.callback);
1347 }
else if (private->op_callback == NULL &&
rc !=
pcmk_ok) {
1352 if (private->op_callback != NULL) {
1353 crm_trace(
"Invoking global callback for call %d", call_id);
1354 invoke_callback(stonith, call_id,
rc, NULL, private->op_callback);
1360 stonith_async_timeout_handler(gpointer
data)
1377 struct timer_rec_s *async_timer = callback->timer;
1384 async_timer = calloc(1,
sizeof(
struct timer_rec_s));
1385 callback->timer = async_timer;
1394 if (async_timer->
ref) {
1395 g_source_remove(async_timer->
ref);
1398 g_timeout_add(async_timer->
timeout, stonith_async_timeout_handler, async_timer);
1407 callback = g_hash_table_lookup(private->stonith_op_callback_table, GINT_TO_POINTER(
call_id));
1408 if (!callback || !callback->allow_timeout_updates) {
1416 stonith_dispatch_internal(
const char *buffer, ssize_t length, gpointer userdata)
1418 const char *
type = NULL;
1419 struct notify_blob_s blob;
1429 if (blob.xml == NULL) {
1430 crm_warn(
"Received malformed message from fencer: %s", buffer);
1439 stonith_perform_callback(
st, blob.xml, 0, 0);
1442 foreach_notify_entry(
private, stonith_send_notification, &blob);
1450 update_callback_timeout(call_id,
timeout,
st);
1461 stonith_api_signon(
stonith_t * stonith,
const char *
name,
int *stonith_fd)
1465 const char *display_name =
name?
name :
"client";
1468 .
dispatch = stonith_dispatch_internal,
1469 .destroy = stonith_connection_destroy
1472 CRM_CHECK(stonith != NULL,
return -EINVAL);
1477 crm_debug(
"Attempting fencer connection by %s with%s mainloop",
1478 display_name, (stonith_fd?
"out" :
""));
1487 }
else if (native->ipc) {
1500 if (native->ipc == NULL) {
1503 xmlNode *reply = NULL;
1512 crm_debug(
"Couldn't register with the fencer: %s "
1516 }
else if (reply == NULL) {
1517 crm_debug(
"Couldn't register with the fencer: no reply");
1525 crm_debug(
"Couldn't register with the fencer: invalid reply type '%s'",
1526 (msg_type? msg_type :
"(missing)"));
1530 }
else if (native->token == NULL) {
1531 crm_debug(
"Couldn't register with the fencer: no token in reply");
1536 #if HAVE_MSGFROMIPC_TIMEOUT
1539 crm_debug(
"Connection to fencer by %s succeeded (registration token: %s)",
1540 display_name, native->token);
1550 crm_debug(
"Connection attempt to fencer by %s failed: %s "
1558 stonith_set_notification(
stonith_t * stonith,
const char *callback,
int enabled)
1575 crm_perror(LOG_DEBUG,
"Couldn't register for fencing notifications: %d",
rc);
1587 stonith_api_add_notification(
stonith_t * stonith,
const char *event,
1590 GList *list_item = NULL;
1595 crm_trace(
"Adding callback for %s events (%d)", event, g_list_length(private->notify_list));
1598 new_client->event = event;
1599 new_client->notify = callback;
1601 list_item = g_list_find_custom(private->notify_list, new_client, stonithlib_GCompareFunc);
1603 if (list_item != NULL) {
1604 crm_warn(
"Callback already present");
1609 private->notify_list = g_list_append(private->notify_list, new_client);
1611 stonith_set_notification(stonith, event, 1);
1613 crm_trace(
"Callback added (%d)", g_list_length(private->notify_list));
1619 stonith_api_del_notification(
stonith_t * stonith,
const char *event)
1621 GList *list_item = NULL;
1625 crm_debug(
"Removing callback for %s events", event);
1629 new_client->event = event;
1630 new_client->notify = NULL;
1632 list_item = g_list_find_custom(private->notify_list, new_client, stonithlib_GCompareFunc);
1634 stonith_set_notification(stonith, event, 0);
1636 if (list_item != NULL) {
1639 if (private->notify_refcnt) {
1640 list_client->delete = TRUE;
1641 private->notify_deletes = TRUE;
1643 private->notify_list = g_list_remove(private->notify_list, list_client);
1657 stonith_api_add_callback(
stonith_t * stonith,
int call_id,
int timeout,
int options,
1658 void *user_data,
const char *callback_name,
1664 CRM_CHECK(stonith != NULL,
return -EINVAL);
1669 private->op_callback = callback;
1671 }
else if (call_id < 0) {
1674 invoke_callback(stonith, call_id, call_id, user_data, callback);
1682 blob->id = callback_name;
1684 blob->user_data = user_data;
1685 blob->callback = callback;
1689 set_callback_timeout(blob, stonith, call_id,
timeout);
1692 g_hash_table_insert(private->stonith_op_callback_table, GINT_TO_POINTER(call_id), blob);
1693 crm_trace(
"Added callback to %s for call %d", callback_name, call_id);
1699 stonith_dump_pending_op(gpointer key, gpointer value, gpointer user_data)
1701 int call = GPOINTER_TO_INT(key);
1712 if (private->stonith_op_callback_table == NULL) {
1715 return g_hash_table_foreach(private->stonith_op_callback_table, stonith_dump_pending_op, NULL);
1738 xml_to_event(xmlNode * msg)
1762 crm_err(
"No data for %s event", ntype);
1788 stonith_send_notification(gpointer
data, gpointer user_data)
1790 struct notify_blob_s *blob = user_data;
1793 const char *
event = NULL;
1795 if (blob->xml == NULL) {
1796 crm_warn(
"Skipping callback - NULL message");
1802 if (entry == NULL) {
1803 crm_warn(
"Skipping callback - NULL callback client");
1806 }
else if (entry->delete) {
1807 crm_trace(
"Skipping callback - marked for deletion");
1810 }
else if (entry->notify == NULL) {
1811 crm_warn(
"Skipping callback - NULL callback");
1815 crm_trace(
"Skipping callback - event mismatch %p/%s vs. %s", entry, entry->event, event);
1819 st_event = xml_to_event(blob->xml);
1821 crm_trace(
"Invoking callback for %p/%s event...", entry, event);
1822 entry->notify(blob->stonith, st_event);
1825 event_free(st_event);
1843 stonith_send_command(
stonith_t * stonith,
const char *op, xmlNode *
data, xmlNode ** output_data,
1844 int call_options,
int timeout)
1849 xmlNode *op_msg = NULL;
1850 xmlNode *op_reply = NULL;
1856 if (output_data != NULL) {
1857 *output_data = NULL;
1874 if (op_msg == NULL) {
1897 1000 * (
timeout + 60), &op_reply);
1918 if (reply_id == stonith->
call_id) {
1919 crm_trace(
"Synchronous reply %d received", reply_id);
1929 *output_data = op_reply;
1933 }
else if (reply_id <= 0) {
1934 crm_err(
"Received bad reply: No id set");
1940 crm_err(
"Received bad reply: %d (wanted %d)", reply_id, stonith->
call_id);
1948 crm_err(
"Fencer disconnected");
1949 free(native->token); native->token = NULL;
1961 gboolean stay_connected = TRUE;
1972 stonith_dispatch_internal(msg, strlen(msg),
st);
1977 stay_connected = FALSE;
1981 return stay_connected;
1992 crm_trace(
"Disconnecting %p first", stonith);
1999 crm_trace(
"Removing %d callbacks", g_hash_table_size(private->stonith_op_callback_table));
2000 g_hash_table_destroy(private->stonith_op_callback_table);
2002 crm_trace(
"Destroying %d notification clients", g_list_length(private->notify_list));
2003 g_list_free_full(private->notify_list, free);
2006 free(stonith->
cmds);
2026 stonith_api_validate(
stonith_t *
st,
int call_options,
const char *rsc_id,
2027 const char *namespace_s,
const char *agent,
2029 char **error_output)
2042 const char *
target =
"node1";
2043 const char *host_arg = NULL;
2045 GHashTable *params_table = crm_str_table_new();
2048 for (; params; params = params->
next) {
2050 host_arg = params->
value;
2055 && strcmp(params->
key,
"provides")
2056 && strcmp(params->
key,
"stonith-timeout")) {
2057 g_hash_table_insert(params_table, strdup(params->
key),
2058 strdup(params->
value));
2062 #if SUPPORT_CIBSECRETS
2065 crm_warn(
"Could not replace secret parameters for validation of %s: %s",
2075 *error_output = NULL;
2081 params_table, host_arg,
timeout,
2082 output, error_output);
2085 #if HAVE_STONITH_STONITH_H
2088 params_table,
timeout, output,
2097 "Agent %s not found or does not support validation",
2101 g_hash_table_destroy(params_table);
2111 new_stonith = calloc(1,
sizeof(
stonith_t));
2112 if (new_stonith == NULL) {
2117 if (
private == NULL) {
2123 private->stonith_op_callback_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2124 NULL, stonith_destroy_op_callback);
2125 private->notify_list = NULL;
2126 private->notify_refcnt = 0;
2127 private->notify_deletes = FALSE;
2133 if (new_stonith->
cmds == NULL) {
2140 new_stonith->
cmds->
free = stonith_api_free;
2144 new_stonith->
cmds->
list = stonith_api_list;
2146 new_stonith->
cmds->
status = stonith_api_status;
2147 new_stonith->
cmds->
fence = stonith_api_fence;
2153 new_stonith->
cmds->
metadata = stonith_api_device_metadata;
2155 new_stonith->
cmds->
query = stonith_api_query;
2189 for (
int attempt = 1; attempt <= max_attempts; attempt++) {
2193 }
else if (attempt < max_attempts) {
2194 crm_notice(
"Fencer connection attempt %d of %d failed (retrying in 2s): %s "
2212 p->
key = strdup(key);
2215 p->
value = strdup(value);
2219 while (end && end->
next) {
2250 #define api_log_open() openlog("stonith-api", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON)
2251 #define api_log(level, fmt, args...) syslog(level, "%s: "fmt, __func__, args)
2258 const char *
action = off?
"off" :
"reboot";
2262 api_log(LOG_ERR,
"API initialization failed, could not kick (%s) node %u/%s",
2269 api_log(LOG_ERR,
"Connection failed, could not kick (%s) node %u/%s : %s (%d)",
2277 if ((
uname == NULL) && (nodeid > 0)) {
2284 api_log(LOG_ERR,
"Could not kick (%s) node %u/%s : %s (%d)",
2304 api_log(LOG_ERR,
"Could not retrieve fence history for %u/%s: "
2305 "API initialization failed", nodeid,
uname);
2320 if ((
uname == NULL) && (nodeid > 0)) {
2326 for (hp = history; hp; hp = hp->
next) {
2334 }
else if (hp->state ==
st_done) {
2336 if (hp->completed > when) {
2337 when = hp->completed;
2345 api_log(LOG_INFO,
"Found %d entries for %u/%s: %d in progress, %d completed", entries, nodeid,
uname, progress, completed);
2354 api_log(LOG_INFO,
"Node %u/%s last kicked at: %ld", nodeid,
uname, (
long int)when);
2367 if (agent == NULL) {
2373 crm_err(
"Could not list fence agents: API memory allocation failed");
2378 for (dIter = devices; dIter != NULL; dIter = dIter->
next) {
2395 }
else if (!strcmp(
action,
"on")) {
2397 }
else if (!strcmp(
action,
"off")) {
2398 return "turning off";
2413 parse_list_line(
const char *line,
int len, GList **output)
2416 size_t entry_start = 0;
2422 if (strstr(line,
"invalid") || strstr(line,
"variable")) {
2423 crm_debug(
"Skipping list output line: %s", line);
2428 for (i = 0; i <= len; i++) {
2430 if (isspace(line[i]) || (line[i] ==
',') || (line[i] ==
';')
2431 || (line[i] ==
'\0')) {
2437 if (i == entry_start) {
2439 entry_start = i + 1;
2443 entry = calloc(i - entry_start + 1,
sizeof(
char));
2450 rc = sscanf(line + entry_start,
"%[a-zA-Z0-9_-.]", entry);
2452 crm_warn(
"Could not parse list output entry: %s "
2453 CRM_XS " entry_start=%d position=%d",
2454 line + entry_start, entry_start, i);
2470 *output = g_list_append(*output, entry);
2472 entry_start = i + 1;
2501 GList *targets = NULL;
2503 if (target_spec != NULL) {
2504 size_t out_len = strlen(target_spec);
2505 size_t line_start = 0;
2507 for (
size_t i = 0; i <= out_len; ++i) {
2508 if ((target_spec[i] ==
'\n') || (target_spec[i] ==
'\0')
2509 || ((target_spec[i] ==
'\\') && (target_spec[i + 1] ==
'n'))) {
2512 int len = i - line_start;
2515 char *line =
strndup(target_spec + line_start, len);
2518 parse_list_line(line, len, &targets);
2521 if (target_spec[i] ==
'\\') {
2541 gboolean ret = FALSE;
2544 if (prev_hp == event) {
2548 if ((prev_hp->state ==
st_done) &&
2552 (event->
completed < prev_hp->completed)) {
2574 for (hp = history; hp; ) {
2578 if ((!
new) || (hp->completed > new->completed)) {
2584 if ((!np->next) || (hp->completed > np->next->completed)) {
2604 while (last_pending->
next) {
2605 last_pending = last_pending->
next;
2608 last_pending->
next =
new;
2620 if (matching_fn(hp, user_data)) {
2637 return history->
state == GPOINTER_TO_INT(user_data);
2643 return history->
state != GPOINTER_TO_INT(user_data);
2662 xmlXPathObjectPtr xpath = NULL;
2666 CRM_CHECK((device_flags != NULL) && (metadata != NULL),
return);
2669 max = numXpathResults(xpath);
2676 for (lpc = 0; lpc < max; lpc++) {
2677 const char *parameter = NULL;
2681 if (match == NULL) {