20 #include <sys/types.h> 37 #ifdef HAVE_GNUTLS_GNUTLS_H 39 # include <gnutls/gnutls.h> 42 #include <sys/socket.h> 43 #include <netinet/in.h> 44 #include <netinet/ip.h> 45 #include <arpa/inet.h> 48 #define MAX_TLS_RECV_WAIT 10000 52 static int lrmd_api_disconnect(
lrmd_t * lrmd);
53 static int lrmd_api_is_connected(
lrmd_t * lrmd);
57 static void lrmd_internal_proxy_dispatch(
lrmd_t *lrmd, xmlNode *msg);
60 #ifdef HAVE_GNUTLS_GNUTLS_H 61 # define LRMD_CLIENT_HANDSHAKE_TIMEOUT 5000 62 gnutls_psk_client_credentials_t psk_cred_s;
63 int lrmd_tls_set_key(gnutls_datum_t * key);
64 static void lrmd_tls_disconnect(
lrmd_t * lrmd);
65 static int global_remote_msg_id = 0;
66 static void lrmd_tls_connection_destroy(gpointer userdata);
69 typedef struct lrmd_private_s {
80 char *remote_nodename;
81 #ifdef HAVE_GNUTLS_GNUTLS_H 84 gnutls_psk_client_credentials_t psk_cred_c;
94 int expected_late_replies;
95 GList *pending_notify;
102 void (*proxy_callback)(
lrmd_t *lrmd,
void *userdata, xmlNode *msg);
103 void *proxy_callback_userdata;
108 lrmd_list_add(
lrmd_list_t * head,
const char *value)
113 p->
val = strdup(value);
116 while (end && end->
next) {
135 char *val = (
char *)head->
val;
150 p->
key = strdup(key);
151 p->
value = strdup(value);
154 while (end && end->
next) {
199 if (rsc_id != NULL) {
200 event->rsc_id = strdup(rsc_id);
204 event->op_type = strdup(task);
207 event->interval_ms = interval_ms;
223 copy->
rsc_id =
event->rsc_id ? strdup(event->
rsc_id) : NULL;
226 copy->
output =
event->output ? strdup(event->
output) : NULL;
242 free((
char *)event->
rsc_id);
245 free((
char *)event->
output);
249 g_hash_table_destroy(event->
params);
255 lrmd_dispatch_internal(
lrmd_t * lrmd, xmlNode * msg)
262 if (proxy_session != NULL) {
264 lrmd_internal_proxy_dispatch(lrmd, msg);
266 }
else if (!native->callback) {
268 crm_trace(
"notify event received but client has not set callback");
272 event.remote_nodename = native->remote_nodename;
292 event.t_run = (
unsigned int) epoch;
295 event.t_rcchange = (
unsigned int) epoch;
316 native->callback(&event);
319 g_hash_table_destroy(event.params);
325 lrmd_ipc_dispatch(
const char *buffer, ssize_t length, gpointer userdata)
332 if (!native->callback) {
338 rc = lrmd_dispatch_internal(lrmd, msg);
343 #ifdef HAVE_GNUTLS_GNUTLS_H 345 lrmd_free_xml(gpointer userdata)
351 lrmd_tls_connected(
lrmd_t * lrmd)
355 if (native->remote->tls_session) {
363 lrmd_tls_dispatch(gpointer userdata)
370 if (lrmd_tls_connected(lrmd) == FALSE) {
371 crm_trace(
"TLS dispatch triggered after disconnect");
379 if (native->pending_notify) {
382 crm_trace(
"Processing pending notifies");
383 for (iter = native->pending_notify; iter; iter = iter->next) {
384 lrmd_dispatch_internal(lrmd, iter->data);
386 g_list_free_full(native->pending_notify, lrmd_free_xml);
387 native->pending_notify = NULL;
407 lrmd_dispatch_internal(lrmd, xml);
409 if (native->expected_late_replies > 0) {
410 native->expected_late_replies--;
415 crm_err(
"Got outdated Pacemaker Remote reply %d", reply_id);
422 if (
rc == ENOTCONN) {
423 crm_info(
"Lost %s executor connection while reading data",
424 (native->remote_nodename? native->remote_nodename :
"local"));
425 lrmd_tls_disconnect(lrmd);
438 switch (native->type) {
442 #ifdef HAVE_GNUTLS_GNUTLS_H 443 case pcmk__client_tls:
444 if (native->pending_notify) {
460 crm_err(
"Unsupported connection type: %d", native->type);
475 switch (private->type) {
481 lrmd_ipc_dispatch(msg, strlen(msg), lrmd);
485 #ifdef HAVE_GNUTLS_GNUTLS_H 486 case pcmk__client_tls:
487 lrmd_tls_dispatch(lrmd);
491 crm_err(
"Unsupported connection type: %d", private->type);
494 if (lrmd_api_is_connected(lrmd) == FALSE) {
503 lrmd_create_op(
const char *token,
const char *op, xmlNode *
data,
int timeout,
522 crm_trace(
"Created executor %s command with call options %.8lx (%d)",
523 op, (
long)options, options);
528 lrmd_ipc_connection_destroy(gpointer userdata)
533 crm_info(
"IPC connection destroyed");
537 native->source = NULL;
539 if (native->callback) {
542 event.remote_nodename = native->remote_nodename;
543 native->callback(&event);
547 #ifdef HAVE_GNUTLS_GNUTLS_H 549 lrmd_tls_connection_destroy(gpointer userdata)
554 crm_info(
"TLS connection destroyed");
556 if (native->remote->tls_session) {
557 gnutls_bye(*native->remote->tls_session, GNUTLS_SHUT_RDWR);
558 gnutls_deinit(*native->remote->tls_session);
559 gnutls_free(native->remote->tls_session);
561 if (native->psk_cred_c) {
562 gnutls_psk_free_client_credentials(native->psk_cred_c);
567 if (native->process_notify) {
569 native->process_notify = NULL;
571 if (native->pending_notify) {
572 g_list_free_full(native->pending_notify, lrmd_free_xml);
573 native->pending_notify = NULL;
576 free(native->remote->buffer);
577 native->remote->buffer = NULL;
580 native->psk_cred_c = NULL;
581 native->remote->tls_session = NULL;
584 if (native->callback) {
588 native->callback(&event);
596 const char *msg_type)
604 lrmd_tls_recv_reply(
lrmd_t * lrmd,
int total_timeout,
int expected_reply_id,
int *disconnected)
608 time_t start = time(NULL);
609 const char *msg_type = NULL;
611 int remaining_timeout = 0;
624 if (remaining_timeout) {
625 remaining_timeout = total_timeout - ((time(NULL) - start) * 1000);
627 remaining_timeout = total_timeout;
629 if (remaining_timeout <= 0) {
630 crm_err(
"Never received the expected reply during the timeout period, disconnecting.");
631 *disconnected = TRUE;
636 remaining_timeout) == ENOTCONN) {
637 *disconnected = TRUE;
639 *disconnected = FALSE;
643 crm_err(
"Unable to receive expected reply, disconnecting.");
644 *disconnected = TRUE;
646 }
else if (*disconnected) {
657 crm_err(
"Empty msg type received while waiting for reply");
663 native->pending_notify = g_list_append(native->pending_notify, xml);
664 if (native->process_notify) {
671 crm_err(
"Expected a reply, got %s", msg_type);
674 }
else if (reply_id != expected_reply_id) {
675 if (native->expected_late_replies > 0) {
676 native->expected_late_replies--;
678 crm_err(
"Got outdated reply, expected id %d got id %d", expected_reply_id, reply_id);
685 if (native->remote->buffer && native->process_notify) {
693 lrmd_tls_send(
lrmd_t * lrmd, xmlNode * msg)
698 global_remote_msg_id++;
699 if (global_remote_msg_id <= 0) {
700 global_remote_msg_id = 1;
705 crm_err(
"Disconnecting because TLS message could not be sent to " 707 lrmd_tls_disconnect(lrmd);
714 lrmd_tls_send_recv(
lrmd_t * lrmd, xmlNode * msg,
int timeout, xmlNode ** reply)
717 int disconnected = 0;
720 if (lrmd_tls_connected(lrmd) == FALSE) {
724 rc = lrmd_tls_send(lrmd, msg);
729 xml = lrmd_tls_recv_reply(lrmd,
timeout, global_remote_msg_id, &disconnected);
732 crm_err(
"Pacemaker Remote disconnected while waiting for reply to request id %d",
733 global_remote_msg_id);
734 lrmd_tls_disconnect(lrmd);
737 crm_err(
"Did not receive reply from Pacemaker Remote for request id %d (timeout %dms)",
738 global_remote_msg_id,
timeout);
753 lrmd_send_xml(
lrmd_t * lrmd, xmlNode * msg,
int timeout, xmlNode ** reply)
758 switch (native->type) {
762 #ifdef HAVE_GNUTLS_GNUTLS_H 763 case pcmk__client_tls:
764 rc = lrmd_tls_send_recv(lrmd, msg,
timeout, reply);
768 crm_err(
"Unsupported connection type: %d", native->type);
775 lrmd_send_xml_no_reply(
lrmd_t * lrmd, xmlNode * msg)
780 switch (native->type) {
784 #ifdef HAVE_GNUTLS_GNUTLS_H 785 case pcmk__client_tls:
786 rc = lrmd_tls_send(lrmd, msg);
791 native->expected_late_replies++;
796 crm_err(
"Unsupported connection type: %d", native->type);
803 lrmd_api_is_connected(
lrmd_t * lrmd)
807 switch (native->type) {
810 #ifdef HAVE_GNUTLS_GNUTLS_H 811 case pcmk__client_tls:
812 return lrmd_tls_connected(lrmd);
815 crm_err(
"Unsupported connection type: %d", native->type);
840 lrmd_send_command(
lrmd_t *lrmd,
const char *op, xmlNode *
data,
841 xmlNode **output_data,
int timeout,
846 xmlNode *op_msg = NULL;
847 xmlNode *op_reply = NULL;
849 if (!lrmd_api_is_connected(lrmd)) {
854 crm_err(
"No operation specified");
860 crm_trace(
"Sending %s op to executor", op);
862 op_msg = lrmd_create_op(native->token, op,
data,
timeout, options);
864 if (op_msg == NULL) {
869 rc = lrmd_send_xml(lrmd, op_msg,
timeout, &op_reply);
871 rc = lrmd_send_xml_no_reply(lrmd, op_msg);
880 }
else if(op_reply == NULL) {
895 *output_data = op_reply;
900 if (lrmd_api_is_connected(lrmd) == FALSE) {
901 crm_err(
"Executor disconnected");
910 lrmd_api_poke_connection(
lrmd_t * lrmd)
934 value = g_hash_table_lookup(hash,
"stonith-watchdog-timeout");
945 lrmd_handshake(
lrmd_t * lrmd,
const char *
name)
949 xmlNode *reply = NULL;
958 if (native->proxy_callback) {
962 rc = lrmd_send_xml(lrmd, hello, -1, &reply);
965 crm_perror(LOG_DEBUG,
"Couldn't complete registration with the executor API: %d",
rc);
967 }
else if (reply == NULL) {
968 crm_err(
"Did not receive registration reply");
978 crm_err(
"Executor protocol version mismatch between client (%s) and server (%s)",
983 crm_err(
"Invalid registration message: %s", msg_type);
986 }
else if (tmp_ticket == NULL) {
987 crm_err(
"No registration token provided");
991 crm_trace(
"Obtained registration token: %s", tmp_ticket);
992 native->token = strdup(tmp_ticket);
1002 lrmd_api_disconnect(lrmd);
1008 lrmd_ipc_connect(
lrmd_t * lrmd,
int *fd)
1015 .destroy = lrmd_ipc_connection_destroy
1018 crm_info(
"Connecting to executor");
1025 }
else if (native->ipc) {
1026 crm_perror(LOG_ERR,
"Connection to executor failed");
1034 if (native->ipc == NULL) {
1035 crm_debug(
"Could not connect to the executor API");
1042 #ifdef HAVE_GNUTLS_GNUTLS_H 1044 copy_gnutls_datum(gnutls_datum_t *dest, gnutls_datum_t *source)
1046 dest->data = gnutls_malloc(source->size);
1048 memcpy(dest->data, source->data, source->size);
1049 dest->size = source->size;
1053 clear_gnutls_datum(gnutls_datum_t *datum)
1055 gnutls_free(datum->data);
1060 #define KEY_READ_LEN 256 1063 set_key(gnutls_datum_t * key,
const char *location)
1066 size_t buf_len = KEY_READ_LEN;
1067 static gnutls_datum_t key_cache = { 0, };
1068 static time_t key_cache_updated = 0;
1070 if (location == NULL) {
1074 if (key_cache.data != NULL) {
1075 if ((time(NULL) - key_cache_updated) < 60) {
1076 copy_gnutls_datum(key, &key_cache);
1077 crm_debug(
"Using cached Pacemaker Remote key");
1080 clear_gnutls_datum(&key_cache);
1081 key_cache_updated = 0;
1082 crm_debug(
"Cleared Pacemaker Remote key cache");
1086 stream = fopen(location,
"r");
1091 key->data = gnutls_malloc(buf_len);
1093 while (!feof(stream)) {
1094 int next = fgetc(stream);
1097 if (!feof(stream)) {
1098 crm_err(
"Error reading Pacemaker Remote key; copy in memory may be corrupted");
1102 if (key->size == buf_len) {
1103 buf_len = key->size + KEY_READ_LEN;
1104 key->data = gnutls_realloc(key->data, buf_len);
1107 key->data[key->size++] = (
unsigned char) next;
1111 if (key->size == 0) {
1112 clear_gnutls_datum(key);
1116 if (key_cache.data == NULL) {
1117 copy_gnutls_datum(&key_cache, key);
1118 key_cache_updated = time(NULL);
1119 crm_debug(
"Cached Pacemaker Remote key");
1126 lrmd_tls_set_key(gnutls_datum_t * key)
1128 const char *specific_location = getenv(
"PCMK_authkey_location");
1130 if (set_key(key, specific_location) == 0) {
1131 crm_debug(
"Using custom authkey location %s", specific_location);
1134 }
else if (specific_location) {
1135 crm_err(
"No valid Pacemaker Remote key found at %s, trying default location", specific_location);
1148 lrmd_gnutls_global_init(
void)
1150 static int gnutls_init = 0;
1153 crm_gnutls_global_init();
1160 report_async_connection_result(
lrmd_t * lrmd,
int rc)
1164 if (native->callback) {
1167 event.remote_nodename = native->remote_nodename;
1168 event.connection_rc =
rc;
1169 native->callback(&event);
1173 #ifdef HAVE_GNUTLS_GNUTLS_H 1177 return pcmk__tls_client_handshake(remote, LRMD_CLIENT_HANDSHAKE_TIMEOUT);
1181 lrmd_tcp_connect_cb(
void *userdata,
int rc,
int sock)
1188 .destroy = lrmd_tls_connection_destroy,
1190 gnutls_datum_t psk_key = { NULL, 0 };
1192 native->async_timer = 0;
1195 lrmd_tls_connection_destroy(lrmd);
1196 crm_info(
"Could not connect to Pacemaker Remote at %s:%d: %s " 1207 native->sock = sock;
1209 rc = lrmd_tls_set_key(&psk_key);
1211 crm_warn(
"Could not set key for Pacemaker Remote at %s:%d " CRM_XS " rc=%d",
1212 native->server, native->port,
rc);
1213 lrmd_tls_connection_destroy(lrmd);
1214 report_async_connection_result(lrmd,
rc);
1218 gnutls_psk_allocate_client_credentials(&native->psk_cred_c);
1220 gnutls_free(psk_key.data);
1222 native->remote->tls_session = pcmk__new_tls_session(sock, GNUTLS_CLIENT,
1224 native->psk_cred_c);
1225 if (native->remote->tls_session == NULL) {
1226 lrmd_tls_connection_destroy(lrmd);
1227 report_async_connection_result(lrmd, -EPROTO);
1231 if (lrmd__tls_client_handshake(native->remote) !=
pcmk_rc_ok) {
1232 crm_warn(
"Disconnecting after TLS handshake with Pacemaker Remote server %s:%d failed",
1233 native->server, native->port);
1234 gnutls_deinit(*native->remote->tls_session);
1235 gnutls_free(native->remote->tls_session);
1236 native->remote->tls_session = NULL;
1237 lrmd_tls_connection_destroy(lrmd);
1242 crm_info(
"TLS connection to Pacemaker Remote server %s:%d succeeded",
1243 native->server, native->port);
1246 native->server, native->port);
1252 rc = lrmd_handshake(lrmd,
name);
1255 report_async_connection_result(lrmd,
rc);
1266 lrmd_gnutls_global_init();
1269 &(native->sock), lrmd, lrmd_tcp_connect_cb);
1271 crm_warn(
"Pacemaker Remote connection to %s:%s failed: %s " 1276 native->async_timer = timer_id;
1281 lrmd_tls_connect(
lrmd_t * lrmd,
int *fd)
1285 .destroy = lrmd_tls_connection_destroy,
1290 gnutls_datum_t psk_key = { NULL, 0 };
1292 lrmd_gnutls_global_init();
1296 &(native->sock), NULL, NULL);
1298 crm_warn(
"Pacemaker Remote connection to %s:%s failed: %s " 1301 lrmd_tls_connection_destroy(lrmd);
1305 rc = lrmd_tls_set_key(&psk_key);
1307 lrmd_tls_connection_destroy(lrmd);
1311 gnutls_psk_allocate_client_credentials(&native->psk_cred_c);
1313 gnutls_free(psk_key.data);
1315 native->remote->tls_session = pcmk__new_tls_session(native->sock, GNUTLS_CLIENT,
1317 native->psk_cred_c);
1318 if (native->remote->tls_session == NULL) {
1319 lrmd_tls_connection_destroy(lrmd);
1323 if (lrmd__tls_client_handshake(native->remote) !=
pcmk_rc_ok) {
1324 crm_err(
"Session creation for %s:%d failed", native->server, native->port);
1325 gnutls_deinit(*native->remote->tls_session);
1326 gnutls_free(native->remote->tls_session);
1327 native->remote->tls_session = NULL;
1328 lrmd_tls_connection_destroy(lrmd);
1332 crm_info(
"Client TLS connection established with Pacemaker Remote server %s:%d", native->server,
1339 native->server, native->port);
1351 lrmd_api_connect(
lrmd_t * lrmd,
const char *
name,
int *fd)
1356 switch (native->type) {
1358 rc = lrmd_ipc_connect(lrmd, fd);
1360 #ifdef HAVE_GNUTLS_GNUTLS_H 1361 case pcmk__client_tls:
1362 rc = lrmd_tls_connect(lrmd, fd);
1366 crm_err(
"Unsupported connection type: %d", native->type);
1370 rc = lrmd_handshake(lrmd,
name);
1382 CRM_CHECK(native && native->callback,
return -1);
1384 switch (native->type) {
1388 rc = lrmd_api_connect(lrmd,
name, NULL);
1390 report_async_connection_result(lrmd,
rc);
1393 #ifdef HAVE_GNUTLS_GNUTLS_H 1394 case pcmk__client_tls:
1395 rc = lrmd_tls_connect_async(lrmd,
timeout);
1398 report_async_connection_result(lrmd,
rc);
1403 crm_err(
"Unsupported connection type: %d", native->type);
1410 lrmd_ipc_disconnect(
lrmd_t * lrmd)
1414 if (native->source != NULL) {
1417 native->source = NULL;
1420 }
else if (native->ipc) {
1430 #ifdef HAVE_GNUTLS_GNUTLS_H 1432 lrmd_tls_disconnect(
lrmd_t * lrmd)
1436 if (native->remote->tls_session) {
1437 gnutls_bye(*native->remote->tls_session, GNUTLS_SHUT_RDWR);
1438 gnutls_deinit(*native->remote->tls_session);
1439 gnutls_free(native->remote->tls_session);
1440 native->remote->tls_session = 0;
1443 if (native->async_timer) {
1444 g_source_remove(native->async_timer);
1445 native->async_timer = 0;
1448 if (native->source != NULL) {
1451 native->source = NULL;
1453 }
else if (native->sock) {
1454 close(native->sock);
1458 if (native->pending_notify) {
1459 g_list_free_full(native->pending_notify, lrmd_free_xml);
1460 native->pending_notify = NULL;
1466 lrmd_api_disconnect(
lrmd_t * lrmd)
1470 crm_info(
"Disconnecting %s %s executor connection",
1472 (native->remote_nodename? native->remote_nodename :
"local"));
1473 switch (native->type) {
1475 lrmd_ipc_disconnect(lrmd);
1477 #ifdef HAVE_GNUTLS_GNUTLS_H 1478 case pcmk__client_tls:
1479 lrmd_tls_disconnect(lrmd);
1483 crm_err(
"Unsupported connection type: %d", native->type);
1486 free(native->token);
1487 native->token = NULL;
1489 free(native->peer_version);
1490 native->peer_version = NULL;
1495 lrmd_api_register_rsc(
lrmd_t * lrmd,
1501 xmlNode *
data = NULL;
1503 if (!
class || !
type || !rsc_id) {
1507 && (provider == NULL)) {
1540 const char *provider,
const char *
type)
1546 rsc_info->
id = strdup(rsc_id);
1550 rsc_info->
standard = strdup(standard);
1554 rsc_info->
provider = strdup(provider);
1578 free(rsc_info->
type);
1589 xmlNode *output = NULL;
1590 const char *
class = NULL;
1591 const char *provider = NULL;
1592 const char *
type = NULL;
1607 if (!
class || !
type) {
1634 lrmd_api_get_recurring_ops(
lrmd_t *lrmd,
const char *rsc_id,
int timeout_ms,
1637 xmlNode *
data = NULL;
1638 xmlNode *output_xml = NULL;
1641 if (output == NULL) {
1653 timeout_ms, options, TRUE);
1659 if ((
rc !=
pcmk_ok) || (output_xml == NULL)) {
1666 if (rsc_id == NULL) {
1667 crm_err(
"Could not parse recurring operation information from executor");
1676 op_info->
rsc_id = strdup(rsc_id);
1682 *output = g_list_prepend(*output, op_info);
1695 native->callback = callback;
1703 native->proxy_callback = callback;
1704 native->proxy_callback_userdata = userdata;
1708 lrmd_internal_proxy_dispatch(
lrmd_t *lrmd, xmlNode *msg)
1712 if (native->proxy_callback) {
1714 native->proxy_callback(lrmd, native->proxy_callback_userdata, msg);
1727 return lrmd_send_xml_no_reply(lrmd, msg);
1731 stonith_get_metadata(
const char *provider,
const char *
type,
char **output)
1736 if (stonith_api == NULL) {
1737 crm_err(
"Could not get fence agent meta-data: API memory allocation failed");
1742 provider, output, 0);
1743 if ((
rc ==
pcmk_ok) && (*output == NULL)) {
1746 stonith_api->
cmds->
free(stonith_api);
1751 lrmd_api_get_metadata(
lrmd_t *lrmd,
const char *standard,
const char *provider,
1752 const char *
type,
char **output,
1756 output, options, NULL);
1760 lrmd_api_get_metadata_params(
lrmd_t *lrmd,
const char *standard,
1761 const char *provider,
const char *
type,
1766 GHashTable *params_table = NULL;
1768 if (!standard || !
type) {
1775 return stonith_get_metadata(provider,
type, output);
1778 params_table = crm_str_table_new();
1780 g_hash_table_insert(params_table, strdup(param->key), strdup(param->value));
1789 crm_err(
"Unable to retrieve meta-data for %s:%s:%s",
1790 standard, provider,
type);
1795 crm_err(
"Failed to retrieve meta-data for %s:%s:%s",
1796 standard, provider,
type);
1801 if (!
action->stdout_data) {
1802 crm_err(
"Failed to receive meta-data for %s:%s:%s",
1803 standard, provider,
type);
1808 *output = strdup(
action->stdout_data);
1815 lrmd_api_exec(
lrmd_t *lrmd,
const char *rsc_id,
const char *
action,
1816 const char *userdata, guint interval_ms,
1834 for (tmp = params; tmp; tmp = tmp->
next) {
1847 lrmd_api_exec_alert(
lrmd_t *lrmd,
const char *alert_id,
const char *alert_path,
1860 for (tmp = params; tmp; tmp = tmp->
next) {
1873 lrmd_api_cancel(
lrmd_t *lrmd,
const char *rsc_id,
const char *
action,
1896 if (stonith_api == NULL) {
1897 crm_err(
"Could not list fence agents: API memory allocation failed");
1901 &stonith_resources, 0);
1902 stonith_api->
cmds->
free(stonith_api);
1904 for (dIter = stonith_resources; dIter; dIter = dIter->
next) {
1907 *resources = lrmd_list_add(*resources, dIter->
value);
1916 lrmd_api_list_agents(
lrmd_t * lrmd,
lrmd_list_t ** resources,
const char *
class,
1917 const char *provider)
1920 int stonith_count = 0;
1929 for (gIter = agents; gIter != NULL; gIter = gIter->next) {
1930 *resources = lrmd_list_add(*resources, (
const char *)gIter->data);
1933 g_list_free_full(agents, free);
1940 if (stonith_count) {
1942 stonith_count = list_stonith_agents(resources);
1943 if (stonith_count > 0) {
1944 rc += stonith_count;
1948 crm_notice(
"No agents found for class %s",
class);
1949 rc = -EPROTONOSUPPORT;
1955 does_provider_have_agent(
const char *agent,
const char *provider,
const char *
class)
1958 GList *agents = NULL;
1962 for (gIter2 = agents; gIter2 != NULL; gIter2 = gIter2->next) {
1967 g_list_free_full(agents, free);
1973 lrmd_api_list_ocf_providers(
lrmd_t * lrmd,
const char *agent,
lrmd_list_t ** providers)
1976 char *provider = NULL;
1977 GList *ocf_providers = NULL;
1982 for (gIter = ocf_providers; gIter != NULL; gIter = gIter->next) {
1983 provider = gIter->data;
1984 if (!agent || does_provider_have_agent(agent, provider,
1986 *providers = lrmd_list_add(*providers, (
const char *)gIter->data);
1991 g_list_free_full(ocf_providers, free);
1999 GList *standards = NULL;
2004 for (gIter = standards; gIter != NULL; gIter = gIter->next) {
2005 *supported = lrmd_list_add(*supported, (
const char *)gIter->data);
2009 if (list_stonith_agents(NULL) > 0) {
2014 g_list_free_full(standards, free);
2024 new_lrmd = calloc(1,
sizeof(
lrmd_t));
2043 new_lrmd->
cmds->
exec = lrmd_api_exec;
2057 #ifdef HAVE_GNUTLS_GNUTLS_H 2061 if (!nodename && !server) {
2066 native->type = pcmk__client_tls;
2067 native->remote_nodename = nodename ? strdup(nodename) : strdup(server);
2068 native->server = server ? strdup(server) : strdup(nodename);
2069 native->port = port;
2070 if (native->port == 0) {
2076 crm_err(
"Cannot communicate with Pacemaker Remote because GnuTLS is not enabled for this build");
2092 #ifdef HAVE_GNUTLS_GNUTLS_H 2093 free(native->server);
2095 free(native->remote_nodename);
2096 free(native->remote);
2097 free(native->token);
2098 free(native->peer_version);
#define CRM_CHECK(expr, failure_action)
#define LRMD_OP_ALERT_EXEC
int pcmk__remote_send_xml(pcmk__remote_t *remote, xmlNode *msg)
#define CRMD_METADATA_CALL_TIMEOUT
bool crm_ipc_connect(crm_ipc_t *client)
Establish an IPC connection to a Pacemaker component.
#define crm_notice(fmt, args...)
lrmd_event_data_t * lrmd_copy_event(lrmd_event_data_t *event)
int lrmd_tls_send_msg(pcmk__remote_t *session, xmlNode *msg, uint32_t id, const char *msg_type)
void services_action_free(svc_action_t *op)
int(* get_recurring_ops)(lrmd_t *lrmd, const char *rsc_id, int timeout_ms, enum lrmd_call_options options, GList **output)
Retrieve registered recurring operations.
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
#define F_LRMD_IS_IPC_PROVIDER
int pcmk_rc2legacy(int rc)
const char * crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
Create an XML attribute with specified name and unsigned value.
#define F_LRMD_IPC_SESSION
#define F_LRMD_RSC_EXEC_TIME
#define F_LRMD_RSC_ACTION
#define LRMD_OP_RSC_CANCEL
int crm_ipc_get_fd(crm_ipc_t *client)
#define F_LRMD_RSC_OUTPUT
int(* connect_async)(lrmd_t *lrmd, const char *client_name, int timeout)
Initiate an executor connection without blocking.
xmlNode * first_named_child(const xmlNode *parent, const char *name)
void(* lrmd_event_callback)(lrmd_event_data_t *event)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
struct stonith_key_value_s * next
void lrmd_key_value_freeall(lrmd_key_value_t *head)
struct mainloop_io_s mainloop_io_t
lrmd_event_data_t * lrmd_new_event(const char *rsc_id, const char *task, guint interval_ms)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
int pcmk__remote_ready(pcmk__remote_t *remote, int timeout_ms)
void mainloop_set_trigger(crm_trigger_t *source)
#define DEFAULT_REMOTE_USERNAME
svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, const char *agent, const char *action, guint interval_ms, int timeout, GHashTable *params, enum svc_action_flags flags)
Create a new resource action.
#define LRMD_OP_GET_RECURRING
#define MAX_TLS_RECV_WAIT
int lrmd_internal_proxy_send(lrmd_t *lrmd, xmlNode *msg)
lrmd_rsc_info_t * lrmd_copy_rsc_info(lrmd_rsc_info_t *rsc_info)
#define F_LRMD_ALERT_PATH
long crm_ipc_read(crm_ipc_t *client)
gboolean mainloop_destroy_trigger(crm_trigger_t *source)
int(* cancel)(lrmd_t *lrmd, const char *rsc_id, const char *action, guint interval_ms)
Cancel a recurring command.
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Add hash table entry to XML as (possibly legacy) name/value.
Wrappers for and extensions to glib mainloop.
#define F_LRMD_PROTOCOL_VERSION
lrmd_t * lrmd_remote_api_new(const char *nodename, const char *server, int port)
Create a new TLS connection to a remote executor.
stonith_t * stonith_api_new(void)
xmlNode * string2xml(const char *input)
const char * crm_ipc_buffer(crm_ipc_t *client)
int remote_proxy_check(lrmd_t *lrmd, GHashTable *hash)
#define LRMD_OP_RSC_UNREG
#define DEFAULT_REMOTE_KEY_LOCATION
struct trigger_s crm_trigger_t
struct lrmd_private_s lrmd_private_t
int(* exec)(lrmd_t *lrmd, const char *rsc_id, const char *action, const char *userdata, guint interval_ms, int timeout, int start_delay, enum lrmd_call_options options, lrmd_key_value_t *params)
Issue a command on a resource.
int(* free)(stonith_t *st)
Destroy the stonith api structure.
int(* dispatch)(gpointer userdata)
#define crm_warn(fmt, args...)
int(* exec_alert)(lrmd_t *lrmd, const char *alert_id, const char *alert_path, int timeout, lrmd_key_value_t *params)
Execute an alert agent.
int(* poke_connection)(lrmd_t *lrmd)
Poke executor connection to verify it is still capable of serving requests.
#define PCMK_RESOURCE_CLASS_OCF
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
#define crm_debug(fmt, args...)
struct crm_ipc_s crm_ipc_t
#define F_LRMD_RSC_EXIT_REASON
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
#define ALT_REMOTE_KEY_LOCATION
bool lrmd_dispatch(lrmd_t *lrmd)
Use after lrmd_poll returns 1 to read and dispatch a message.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
struct lrmd_list_s * next
gboolean services_action_sync(svc_action_t *op)
int(* metadata)(stonith_t *st, int options, const char *device, const char *provider, char **output, int timeout)
Get the metadata documentation for a resource.
#define LRMD_PROTOCOL_VERSION
void lrmd_free_op_info(lrmd_op_info_t *op_info)
lrmd_rsc_info_t *(* get_rsc_info)(lrmd_t *lrmd, const char *rsc_id, enum lrmd_call_options options)
Retrieve registration info for a rsc.
void lrmd_list_freeall(lrmd_list_t *head)
int(* connect)(lrmd_t *lrmd, const char *client_name, int *fd)
Connect to an executor.
#define crm_trace(fmt, args...)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
int pcmk__connect_remote(const char *host, int port, int timeout_ms, int *timer_id, int *sock_fd, void *userdata, void(*callback)(void *userdata, int rc, int sock))
crm_trigger_t * mainloop_add_trigger(int priority, int(*dispatch)(gpointer user_data), gpointer userdata)
#define LRMD_OP_NEW_CLIENT
xmlNode * create_xml_node(xmlNode *parent, const char *name)
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
void stonith_key_value_freeall(stonith_key_value_t *kvp, int keys, int values)
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
lrmd_rsc_info_t * lrmd_new_rsc_info(const char *rsc_id, const char *standard, const char *provider, const char *type)
void mainloop_del_ipc_client(mainloop_io_t *client)
void crm_ipc_destroy(crm_ipc_t *client)
GList * resources_list_providers(const char *standard)
Get a list of providers.
lrmd_t * lrmd_api_new(void)
Create a new connection to the local executor.
int(* get_metadata_params)(lrmd_t *lrmd, const char *standard, const char *provider, const char *agent, char **output, enum lrmd_call_options options, lrmd_key_value_t *params)
Get resource metadata for a resource agent, passing parameters.
struct lrmd_key_value_s * next
int(* list_agents)(stonith_t *stonith, int call_options, const char *provider, stonith_key_value_t **devices, int timeout)
Retrieve a list of installed stonith agents.
#define F_LRMD_RSC_USERDATA_STR
int(* list_agents)(lrmd_t *lrmd, lrmd_list_t **agents, const char *standard, const char *provider)
Retrieve a list of installed resource agents.
gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml)
void free_xml(xmlNode *child)
#define F_LRMD_RSC_INTERVAL
void lrmd_free_rsc_info(lrmd_rsc_info_t *rsc_info)
CRM_TRACE_INIT_DATA(lrmd)
int(* unregister_rsc)(lrmd_t *lrmd, const char *rsc_id, enum lrmd_call_options options)
Unregister a resource from the executor.
#define F_LRMD_RSC_START_DELAY
int(* disconnect)(lrmd_t *lrmd)
Disconnect from the executor.
bool crm_ipc_connected(crm_ipc_t *client)
int lrmd_poll(lrmd_t *lrmd, int timeout)
Poll for a specified timeout period to determine if a message is ready for dispatch.
#define PCMK_RESOURCE_CLASS_STONITH
int crm_ipc_ready(crm_ipc_t *client)
Check whether an IPC connection is ready to be read.
#define F_LRMD_RSC_RCCHANGE_TIME
#define crm_log_xml_err(xml, text)
void lrmd_api_delete(lrmd_t *lrmd)
Destroy executor connection object.
#define F_LRMD_REMOTE_MSG_ID
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
const char * remote_nodename
lrmd_api_operations_t * cmds
crm_ipc_t * mainloop_get_ipc_client(mainloop_io_t *client)
GList * resources_list_standards(void)
#define crm_err(fmt, args...)
enum lrmd_callback_event type
lrmd_key_value_t * lrmd_key_value_add(lrmd_key_value_t *head, const char *key, const char *value)
stonith_api_operations_t * cmds
int crm_ipc_send(crm_ipc_t *client, xmlNode *message, enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply)
Send an IPC XML message.
GHashTable * crm_str_table_dup(GHashTable *old_table)
int(* list_standards)(lrmd_t *lrmd, lrmd_list_t **standards)
Retrieve a list of standards supported by this machine/installation.
#define CRMD_ACTION_METADATA
crm_ipc_t * crm_ipc_new(const char *name, size_t max_size)
Create a new (legacy) object for using Pacemaker daemon IPC.
GList * resources_list_agents(const char *standard, const char *provider)
Get a list of resource agents.
GHashTable * xml2list(xmlNode *parent)
Retrieve XML attributes as a hash table.
#define F_LRMD_RSC_RUN_TIME
int(* list_ocf_providers)(lrmd_t *lrmd, const char *agent, lrmd_list_t **providers)
Retrieve a list of resource agent providers.
const char * pcmk__client_type_str(uint64_t client_type)
int(* register_rsc)(lrmd_t *lrmd, const char *rsc_id, const char *standard, const char *provider, const char *agent, enum lrmd_call_options options)
Register a resource with the executor.
void lrmd_internal_set_proxy_callback(lrmd_t *lrmd, void *userdata, void(*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg))
#define crm_log_xml_trace(xml, text)
#define F_LRMD_CLIENTNAME
mainloop_io_t * mainloop_add_ipc_client(const char *name, int priority, size_t max_size, void *userdata, struct ipc_client_callbacks *callbacks)
#define F_LRMD_RSC_QUEUE_TIME
int pcmk__read_remote_message(pcmk__remote_t *remote, int timeout_ms)
#define F_LRMD_RSC_DELETED
#define F_LRMD_CALLBACK_TOKEN
void lrmd_free_event(lrmd_event_data_t *event)
#define F_LRMD_REMOTE_MSG_TYPE
void crm_ipc_close(crm_ipc_t *client)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define crm_info(fmt, args...)
int(* is_connected)(lrmd_t *lrmd)
Is connected to lrmd daemon?
int(* get_metadata)(lrmd_t *lrmd, const char *standard, const char *provider, const char *agent, char **output, enum lrmd_call_options options)
Get resource metadata for a specified resource agent.
xmlNode * pcmk__remote_message_xml(pcmk__remote_t *remote)
int(* dispatch)(const char *buffer, ssize_t length, gpointer userdata)
int crm_default_remote_port(void)
Get the default remote connection TCP port on this host.
void(* set_callback)(lrmd_t *lrmd, lrmd_event_callback callback)
Set a callback for executor events.
enum crm_ais_msg_types type
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.