pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_cluster_queries.c
Go to the documentation of this file.
1/*
2 * Copyright 2020-2025 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 <libxml/tree.h> // xmlNode
13
14#include <pacemaker.h>
15#include <pacemaker-internal.h>
16
17#include <crm/crm.h>
18#include <crm/cib.h>
19#include <crm/cib/internal.h>
21#include <crm/common/xml.h>
23#include <crm/common/iso8601.h>
26
28typedef struct {
29 /* Adapted from pcmk_controld_api_reply_t:data:node_info.
30 * (char **) are convenient here for use within callbacks: we can skip
31 * copying strings unless the caller passes a non-NULL value.
32 */
33 uint32_t id;
34 char **node_name;
35 char **uuid;
36 char **state;
37 bool have_quorum;
38 bool is_remote;
39} node_info_t;
40
42typedef struct {
43 pcmk__output_t *out;
44 bool show_output;
45 int rc;
46 unsigned int message_timeout_ms;
47 enum pcmk_pacemakerd_state pcmkd_state;
48 node_info_t node_info;
49} data_t;
50
62static int
63validate_reply_event(data_t *data, const pcmk_ipc_api_t *api,
64 enum pcmk_ipc_event event_type, crm_exit_t status)
65{
66 pcmk__output_t *out = data->out;
67
68 switch (event_type) {
70 break;
71
73 if (data->rc == ECONNRESET) { // Unexpected
74 out->err(out, "error: Lost connection to %s",
75 pcmk_ipc_name(api, true));
76 }
77 // Nothing bad but not the reply we're looking for
78 return ENOTSUP;
79
80 default:
81 // Ditto
82 return ENOTSUP;
83 }
84
85 if (status != CRM_EX_OK) {
86 out->err(out, "error: Bad reply from %s: %s",
87 pcmk_ipc_name(api, true), crm_exit_str(status));
88 data->rc = EBADMSG;
89 return data->rc;
90 }
91 return pcmk_rc_ok;
92}
93
107static int
108validate_controld_reply(data_t *data, const pcmk_ipc_api_t *api,
109 enum pcmk_ipc_event event_type, crm_exit_t status,
110 const void *event_data,
111 enum pcmk_controld_api_reply expected_type)
112{
113 pcmk__output_t *out = data->out;
114 int rc = pcmk_rc_ok;
115 const pcmk_controld_api_reply_t *reply = NULL;
116
117 rc = validate_reply_event(data, api, event_type, status);
118 if (rc != pcmk_rc_ok) {
119 return rc;
120 }
121
122 reply = (const pcmk_controld_api_reply_t *) event_data;
123
124 if (reply->reply_type != expected_type) {
125 out->err(out, "error: Unexpected reply type '%s' from controller",
127 data->rc = EBADMSG;
128 return data->rc;
129 }
130
131 return pcmk_rc_ok;
132}
133
148static int
149validate_pcmkd_reply(data_t *data, const pcmk_ipc_api_t *api,
150 enum pcmk_ipc_event event_type, crm_exit_t status,
151 const void *event_data,
152 enum pcmk_pacemakerd_api_reply expected_type)
153{
154 pcmk__output_t *out = data->out;
155 const pcmk_pacemakerd_api_reply_t *reply = NULL;
156 int rc = validate_reply_event(data, api, event_type, status);
157
158 if (rc != pcmk_rc_ok) {
159 return rc;
160 }
161
162 reply = (const pcmk_pacemakerd_api_reply_t *) event_data;
163
164 if (reply->reply_type != expected_type) {
165 out->err(out, "error: Unexpected reply type '%s' from pacemakerd",
167 data->rc = EBADMSG;
168 return data->rc;
169 }
170
171 return pcmk_rc_ok;
172}
173
185static void
186controller_status_event_cb(pcmk_ipc_api_t *controld_api,
187 enum pcmk_ipc_event event_type, crm_exit_t status,
188 void *event_data, void *user_data)
189{
190 data_t *data = (data_t *) user_data;
191 pcmk__output_t *out = data->out;
192 const pcmk_controld_api_reply_t *reply = NULL;
193
194 int rc = validate_controld_reply(data, controld_api, event_type, status,
195 event_data, pcmk_controld_reply_ping);
196
197 if (rc != pcmk_rc_ok) {
198 return;
199 }
200
201 reply = (const pcmk_controld_api_reply_t *) event_data;
202 out->message(out, "health",
203 reply->data.ping.sys_from, reply->host_from,
204 reply->data.ping.fsa_state, reply->data.ping.result);
205 data->rc = pcmk_rc_ok;
206}
207
219static void
220designated_controller_event_cb(pcmk_ipc_api_t *controld_api,
221 enum pcmk_ipc_event event_type,
222 crm_exit_t status, void *event_data,
223 void *user_data)
224{
225 data_t *data = (data_t *) user_data;
226 pcmk__output_t *out = data->out;
227 const pcmk_controld_api_reply_t *reply = NULL;
228
229 int rc = validate_controld_reply(data, controld_api, event_type, status,
230 event_data, pcmk_controld_reply_ping);
231
232 if (rc != pcmk_rc_ok) {
233 return;
234 }
235
236 reply = (const pcmk_controld_api_reply_t *) event_data;
237 out->message(out, "dc", reply->host_from);
238 data->rc = reply->host_from ? pcmk_rc_ok : pcmk_rc_no_dc;
239}
240
252static void
253node_info_event_cb(pcmk_ipc_api_t *controld_api, enum pcmk_ipc_event event_type,
254 crm_exit_t status, void *event_data, void *user_data)
255{
256 data_t *data = (data_t *) user_data;
257 pcmk__output_t *out = data->out;
258
259 const pcmk_controld_api_reply_t *reply = NULL;
260
261 int rc = validate_controld_reply(data, controld_api, event_type, status,
262 event_data, pcmk_controld_reply_info);
263
264 if (rc != pcmk_rc_ok) {
265 return;
266 }
267
268 reply = (const pcmk_controld_api_reply_t *) event_data;
269
270 if (reply->data.node_info.uname == NULL) {
271 out->err(out, "Node is not known to cluster");
273 return;
274 }
275
277 data->node_info.is_remote = reply->data.node_info.is_remote;
278 data->node_info.id = (uint32_t) reply->data.node_info.id;
279
280 pcmk__str_update(data->node_info.node_name, reply->data.node_info.uname);
281 pcmk__str_update(data->node_info.uuid, reply->data.node_info.uuid);
282 pcmk__str_update(data->node_info.state, reply->data.node_info.state);
283
284 if (data->show_output) {
285 out->message(out, "node-info",
286 (uint32_t) reply->data.node_info.id, reply->data.node_info.uname,
287 reply->data.node_info.uuid, reply->data.node_info.state,
289 reply->data.node_info.is_remote);
290 }
291
292 data->rc = pcmk_rc_ok;
293}
294
306static void
307pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
308 enum pcmk_ipc_event event_type, crm_exit_t status,
309 void *event_data, void *user_data)
310{
311 data_t *data = user_data;
312 pcmk__output_t *out = data->out;
313 const pcmk_pacemakerd_api_reply_t *reply = NULL;
314
315 int rc = validate_pcmkd_reply(data, pacemakerd_api, event_type, status,
316 event_data, pcmk_pacemakerd_reply_ping);
317
318 if (rc != pcmk_rc_ok) {
319 return;
320 }
321
322 // Parse desired information from reply
323 reply = (const pcmk_pacemakerd_api_reply_t *) event_data;
324
325 data->pcmkd_state = reply->data.ping.state;
326 data->rc = pcmk_rc_ok;
327
328 if (!data->show_output) {
329 return;
330 }
331
332 if (reply->data.ping.status == pcmk_rc_ok) {
333 out->message(out, "pacemakerd-health",
334 reply->data.ping.sys_from, reply->data.ping.state, NULL,
335 reply->data.ping.last_good);
336 } else {
337 out->message(out, "pacemakerd-health",
338 reply->data.ping.sys_from, reply->data.ping.state,
339 "query failed", time(NULL));
340 }
341}
342
343static pcmk_ipc_api_t *
344ipc_connect(data_t *data, enum pcmk_ipc_server server, pcmk_ipc_callback_t cb,
345 enum pcmk_ipc_dispatch dispatch_type, bool eremoteio_ok)
346{
347 int rc;
348 pcmk__output_t *out = data->out;
349 pcmk_ipc_api_t *api = NULL;
350
351 rc = pcmk_new_ipc_api(&api, server);
352 if (api == NULL) {
353 out->err(out, "error: Could not connect to %s: %s",
354 pcmk_ipc_name(api, true),
355 pcmk_rc_str(rc));
356 data->rc = rc;
357 return NULL;
358 }
359 if (cb != NULL) {
361 }
362
363 rc = pcmk__connect_ipc(api, dispatch_type, 5);
364 if (rc != pcmk_rc_ok) {
365 if (rc == EREMOTEIO) {
366 data->pcmkd_state = pcmk_pacemakerd_state_remote;
367 if (eremoteio_ok) {
368 /* EREMOTEIO may be expected and acceptable for some callers
369 * on a Pacemaker Remote node
370 */
371 crm_debug("Ignoring %s connection failure: No "
372 "Pacemaker Remote connection",
373 pcmk_ipc_name(api, true));
374 rc = pcmk_rc_ok;
375 } else {
376 out->err(out, "error: Could not connect to %s: %s",
377 pcmk_ipc_name(api, true), pcmk_rc_str(rc));
378 }
379 }
380 data->rc = rc;
382 return NULL;
383 }
384
385 return api;
386}
387
399static void
400poll_until_reply(data_t *data, pcmk_ipc_api_t *api, const char *on_node)
401{
402 pcmk__output_t *out = data->out;
403
404 uint64_t start_nsec = qb_util_nano_current_get();
405 uint64_t end_nsec = 0;
406 uint64_t elapsed_ms = 0;
407 uint64_t remaining_ms = data->message_timeout_ms;
408
409 while (remaining_ms > 0) {
410 int rc = pcmk_poll_ipc(api, remaining_ms);
411
412 if (rc == EAGAIN) {
413 // Poll timed out
414 break;
415 }
416
417 if (rc != pcmk_rc_ok) {
418 out->err(out, "error: Failed to poll %s API%s%s: %s",
419 pcmk_ipc_name(api, true), (on_node != NULL)? " on " : "",
420 pcmk__s(on_node, ""), pcmk_rc_str(rc));
421 data->rc = rc;
422 return;
423 }
424
426
427 if (data->rc != EAGAIN) {
428 // Received a reply
429 return;
430 }
431 end_nsec = qb_util_nano_current_get();
432 elapsed_ms = (end_nsec - start_nsec) / QB_TIME_NS_IN_MSEC;
433 remaining_ms = data->message_timeout_ms - elapsed_ms;
434 }
435
436 out->err(out,
437 "error: Timed out after %ums waiting for reply from %s API%s%s",
438 data->message_timeout_ms, pcmk_ipc_name(api, true),
439 (on_node != NULL)? " on " : "", pcmk__s(on_node, ""));
440 data->rc = EAGAIN;
441}
442
458int
459pcmk__controller_status(pcmk__output_t *out, const char *node_name,
460 unsigned int message_timeout_ms)
461{
462 data_t data = {
463 .out = out,
464 .rc = EAGAIN,
465 .message_timeout_ms = message_timeout_ms,
466 };
467 enum pcmk_ipc_dispatch dispatch_type = pcmk_ipc_dispatch_poll;
468 pcmk_ipc_api_t *controld_api = NULL;
469
470 if (message_timeout_ms == 0) {
471 dispatch_type = pcmk_ipc_dispatch_sync;
472 }
473 controld_api = ipc_connect(&data, pcmk_ipc_controld,
474 controller_status_event_cb, dispatch_type,
475 false);
476
477 if (controld_api != NULL) {
478 int rc = pcmk_controld_api_ping(controld_api, node_name);
479 if (rc != pcmk_rc_ok) {
480 out->err(out, "error: Could not ping controller API on %s: %s",
481 pcmk__s(node_name, "DC"), pcmk_rc_str(rc));
482 data.rc = rc;
483 }
484
485 if (dispatch_type == pcmk_ipc_dispatch_poll) {
486 poll_until_reply(&data, controld_api, pcmk__s(node_name, "DC"));
487 }
488 pcmk_free_ipc_api(controld_api);
489 }
490
491 return data.rc;
492}
493
494
495// Documented in header
496int
497pcmk_controller_status(xmlNodePtr *xml, const char *node_name,
498 unsigned int message_timeout_ms)
499{
500 pcmk__output_t *out = NULL;
501 int rc = pcmk_rc_ok;
502
503 rc = pcmk__xml_output_new(&out, xml);
504 if (rc != pcmk_rc_ok) {
505 return rc;
506 }
507
509
510 rc = pcmk__controller_status(out, node_name, message_timeout_ms);
512 return rc;
513}
514
528int
530 unsigned int message_timeout_ms)
531{
532 data_t data = {
533 .out = out,
534 .rc = EAGAIN,
535 .message_timeout_ms = message_timeout_ms,
536 };
537 enum pcmk_ipc_dispatch dispatch_type = pcmk_ipc_dispatch_poll;
538 pcmk_ipc_api_t *controld_api = NULL;
539
540 if (message_timeout_ms == 0) {
541 dispatch_type = pcmk_ipc_dispatch_sync;
542 }
543 controld_api = ipc_connect(&data, pcmk_ipc_controld,
544 designated_controller_event_cb, dispatch_type,
545 false);
546
547 if (controld_api != NULL) {
548 int rc = pcmk_controld_api_ping(controld_api, NULL);
549 if (rc != pcmk_rc_ok) {
550 out->err(out, "error: Could not ping controller API on DC: %s",
551 pcmk_rc_str(rc));
552 data.rc = rc;
553 }
554
555 if (dispatch_type == pcmk_ipc_dispatch_poll) {
556 poll_until_reply(&data, controld_api, "DC");
557 }
558 pcmk_free_ipc_api(controld_api);
559 }
560
561 return data.rc;
562}
563
564// Documented in header
565int
566pcmk_designated_controller(xmlNodePtr *xml, unsigned int message_timeout_ms)
567{
568 pcmk__output_t *out = NULL;
569 int rc = pcmk_rc_ok;
570
571 rc = pcmk__xml_output_new(&out, xml);
572 if (rc != pcmk_rc_ok) {
573 return rc;
574 }
575
577
578 rc = pcmk__designated_controller(out, message_timeout_ms);
580 return rc;
581}
582
615int
616pcmk__query_node_info(pcmk__output_t *out, uint32_t *node_id, char **node_name,
617 char **uuid, char **state, bool *have_quorum,
618 bool *is_remote, bool show_output,
619 unsigned int message_timeout_ms)
620{
621 data_t data = {
622 .out = out,
623 .show_output = show_output,
624 .rc = EAGAIN,
625 .message_timeout_ms = message_timeout_ms,
626 .node_info = {
627 .id = (node_id == NULL)? 0 : *node_id,
628 .node_name = node_name,
629 .uuid = uuid,
630 .state = state,
631 },
632 };
633 enum pcmk_ipc_dispatch dispatch_type = pcmk_ipc_dispatch_poll;
634 pcmk_ipc_api_t *controld_api = NULL;
635
636 if (node_name != NULL) {
637 *node_name = NULL;
638 }
639 if (uuid != NULL) {
640 *uuid = NULL;
641 }
642 if (state != NULL) {
643 *state = NULL;
644 }
645
646 if (message_timeout_ms == 0) {
647 dispatch_type = pcmk_ipc_dispatch_sync;
648 }
649 controld_api = ipc_connect(&data, pcmk_ipc_controld, node_info_event_cb,
650 dispatch_type, false);
651
652 if (controld_api != NULL) {
653 int rc = pcmk_controld_api_node_info(controld_api,
654 (node_id != NULL)? *node_id : 0);
655
656 if (rc != pcmk_rc_ok) {
657 out->err(out,
658 "error: Could not send request to controller API on local "
659 "node: %s", pcmk_rc_str(rc));
660 data.rc = rc;
661 }
662
663 if (dispatch_type == pcmk_ipc_dispatch_poll) {
664 poll_until_reply(&data, controld_api, "local node");
665 }
666 pcmk_free_ipc_api(controld_api);
667 }
668
669 if (data.rc != pcmk_rc_ok) {
670 return data.rc;
671 }
672
673 // String outputs are set in callback
674 if (node_id != NULL) {
675 *node_id = data.node_info.id;
676 }
677 if (have_quorum != NULL) {
678 *have_quorum = data.node_info.have_quorum;
679 }
680 if (is_remote != NULL) {
681 *is_remote = data.node_info.is_remote;
682 }
683
684 return data.rc;
685}
686
687// Documented in header
688int
689pcmk_query_node_info(xmlNodePtr *xml, uint32_t *node_id, char **node_name,
690 char **uuid, char **state, bool *have_quorum,
691 bool *is_remote, bool show_output,
692 unsigned int message_timeout_ms)
693{
694 pcmk__output_t *out = NULL;
695 int rc = pcmk_rc_ok;
696
697 pcmk__assert(node_name != NULL);
698
699 rc = pcmk__xml_output_new(&out, xml);
700 if (rc != pcmk_rc_ok) {
701 return rc;
702 }
703
705
706 rc = pcmk__query_node_info(out, node_id, node_name, uuid, state,
707 have_quorum, is_remote, show_output,
708 message_timeout_ms);
710 return rc;
711}
712
736int
737pcmk__pacemakerd_status(pcmk__output_t *out, const char *ipc_name,
738 unsigned int message_timeout_ms, bool show_output,
739 enum pcmk_pacemakerd_state *state)
740{
741 data_t data = {
742 .out = out,
743 .show_output = show_output,
744 .rc = EAGAIN,
745 .message_timeout_ms = message_timeout_ms,
746 .pcmkd_state = pcmk_pacemakerd_state_invalid,
747 };
748 enum pcmk_ipc_dispatch dispatch_type = pcmk_ipc_dispatch_poll;
749 pcmk_ipc_api_t *pacemakerd_api = NULL;
750
751 if (message_timeout_ms == 0) {
752 dispatch_type = pcmk_ipc_dispatch_sync;
753 }
754 pacemakerd_api = ipc_connect(&data, pcmk_ipc_pacemakerd,
755 pacemakerd_event_cb, dispatch_type, true);
756
757 if (pacemakerd_api != NULL) {
758 int rc = pcmk_pacemakerd_api_ping(pacemakerd_api, ipc_name);
759 if (rc != pcmk_rc_ok) {
760 out->err(out, "error: Could not ping launcher API: %s",
761 pcmk_rc_str(rc));
762 data.rc = rc;
763 }
764
765 if (dispatch_type == pcmk_ipc_dispatch_poll) {
766 poll_until_reply(&data, pacemakerd_api, NULL);
767 }
768 pcmk_free_ipc_api(pacemakerd_api);
769
770 } else if ((data.pcmkd_state == pcmk_pacemakerd_state_remote)
771 && show_output) {
772 // No API connection so the callback wasn't run
773 out->message(out, "pacemakerd-health",
774 NULL, data.pcmkd_state, NULL, time(NULL));
775 }
776
777 if (state != NULL) {
778 *state = data.pcmkd_state;
779 }
780 return data.rc;
781}
782
783// Documented in header
784int
785pcmk_pacemakerd_status(xmlNodePtr *xml, const char *ipc_name,
786 unsigned int message_timeout_ms)
787{
788 pcmk__output_t *out = NULL;
789 int rc = pcmk_rc_ok;
790
791 rc = pcmk__xml_output_new(&out, xml);
792 if (rc != pcmk_rc_ok) {
793 return rc;
794 }
795
797
798 rc = pcmk__pacemakerd_status(out, ipc_name, message_timeout_ms, true, NULL);
800 return rc;
801}
802
803/* user data for looping through remote node xpath searches */
804struct node_data {
805 pcmk__output_t *out;
806 int found;
807 const char *field; /* XML attribute to check for node name */
808 const char *type;
809 bool bash_export;
810};
811
812static void
813remote_node_print_helper(xmlNode *result, void *user_data)
814{
815 struct node_data *data = user_data;
816 pcmk__output_t *out = data->out;
818 const char *id = crm_element_value(result, data->field);
819
820 // node name and node id are the same for remote/guest nodes
821 out->message(out, "crmadmin-node", data->type,
822 pcmk__s(name, id), id, data->bash_export);
823 data->found++;
824}
825
826// \return Standard Pacemaker return code
827int
828pcmk__list_nodes(pcmk__output_t *out, const char *node_types, bool bash_export)
829{
830 xmlNode *xml_node = NULL;
831 int rc;
832
833 rc = cib__signon_query(out, NULL, &xml_node);
834
835 if (rc == pcmk_rc_ok) {
836 struct node_data data = {
837 .out = out,
838 .found = 0,
839 .bash_export = bash_export
840 };
841
842 /* PCMK_XE_NODES acts as the list's element name for CLI tools that
843 * use pcmk__output_enable_list_element. Otherwise PCMK_XE_NODES is
844 * the value of the list's PCMK_XA_NAME attribute.
845 */
846 out->begin_list(out, NULL, NULL, PCMK_XE_NODES);
847
848 if (!pcmk__str_empty(node_types) && strstr(node_types, "all")) {
849 node_types = NULL;
850 }
851
852 if (pcmk__str_empty(node_types) || strstr(node_types, "cluster")) {
853 data.field = PCMK_XA_ID;
854 data.type = "cluster";
855 pcmk__xpath_foreach_result(xml_node->doc,
857 remote_node_print_helper, &data);
858 }
859
860 if (pcmk__str_empty(node_types) || strstr(node_types, "guest")) {
861 data.field = PCMK_XA_VALUE;
862 data.type = "guest";
863 pcmk__xpath_foreach_result(xml_node->doc,
865 remote_node_print_helper, &data);
866 }
867
868 if (pcmk__str_empty(node_types)
869 || pcmk__str_eq(node_types, ",|^remote", pcmk__str_regex)) {
870 data.field = PCMK_XA_ID;
871 data.type = "remote";
872 pcmk__xpath_foreach_result(xml_node->doc,
874 remote_node_print_helper, &data);
875 }
876
877 out->end_list(out);
878
879 if (data.found == 0) {
880 out->info(out, "No nodes configured");
881 }
882
883 pcmk__xml_free(xml_node);
884 }
885
886 return rc;
887}
888
889int
890pcmk_list_nodes(xmlNodePtr *xml, const char *node_types)
891{
892 pcmk__output_t *out = NULL;
893 int rc = pcmk_rc_ok;
894
895 rc = pcmk__xml_output_new(&out, xml);
896 if (rc != pcmk_rc_ok) {
897 return rc;
898 }
899
901
902 rc = pcmk__list_nodes(out, node_types, FALSE);
904 return rc;
905}
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
Definition cib_utils.c:863
const char * name
Definition cib.c:26
Cluster Configuration.
char data[0]
Definition cpg.c:10
uint32_t id
Definition cpg.c:0
A dumping ground.
void(* pcmk_ipc_callback_t)(pcmk_ipc_api_t *api, enum pcmk_ipc_event event_type, crm_exit_t status, void *event_data, void *user_data)
Callback function type for Pacemaker daemon IPC APIs.
Definition ipc.h:98
int pcmk_poll_ipc(const pcmk_ipc_api_t *api, int timeout_ms)
Check whether an IPC connection has data available (without main loop)
Definition ipc_client.c:383
pcmk_ipc_event
Possible event types that an IPC event callback can be called for.
Definition ipc.h:61
@ pcmk_ipc_event_reply
Daemon's reply to client IPC request.
Definition ipc.h:68
@ pcmk_ipc_event_disconnect
Termination of IPC connection.
Definition ipc.h:65
pcmk_ipc_server
Available IPC interfaces.
Definition ipc.h:48
@ pcmk_ipc_pacemakerd
Launcher.
Definition ipc.h:55
@ pcmk_ipc_controld
Controller.
Definition ipc.h:52
const char * pcmk_ipc_name(const pcmk_ipc_api_t *api, bool for_log)
Get the IPC name used with an IPC API connection.
Definition ipc_client.c:241
void pcmk_free_ipc_api(pcmk_ipc_api_t *api)
Free the contents of an IPC API object.
Definition ipc_client.c:200
pcmk_ipc_dispatch
How IPC replies should be dispatched.
Definition ipc.h:74
@ pcmk_ipc_dispatch_sync
Sending a command will wait for any reply.
Definition ipc.h:77
@ pcmk_ipc_dispatch_poll
Caller will poll and dispatch IPC.
Definition ipc.h:76
int pcmk_new_ipc_api(pcmk_ipc_api_t **api, enum pcmk_ipc_server server)
Create a new object for using Pacemaker daemon IPC.
Definition ipc_client.c:46
void pcmk_dispatch_ipc(pcmk_ipc_api_t *api)
Dispatch available messages on an IPC connection (without main loop)
Definition ipc_client.c:423
void pcmk_register_ipc_callback(pcmk_ipc_api_t *api, pcmk_ipc_callback_t cb, void *user_data)
Register a callback for IPC API events.
Definition ipc_client.c:661
IPC commands for Pacemaker controller.
int pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
Ask the controller for status.
pcmk_controld_api_reply
Possible types of controller replies.
@ pcmk_controld_reply_ping
@ pcmk_controld_reply_info
int pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
Send a "node info" controller operation.
const char * pcmk__pcmkd_api_reply2str(enum pcmk_pacemakerd_api_reply reply)
int pcmk__connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type, int attempts)
Definition ipc_client.c:517
const char * pcmk__controld_api_reply2str(enum pcmk_controld_api_reply reply)
IPC commands for Pacemakerd.
pcmk_pacemakerd_api_reply
Possible types of pacemakerd replies.
@ pcmk_pacemakerd_reply_ping
pcmk_pacemakerd_state
@ pcmk_pacemakerd_state_invalid
@ pcmk_pacemakerd_state_remote
int pcmk_pacemakerd_api_ping(pcmk_ipc_api_t *api, const char *ipc_name)
ISO_8601 Date handling.
#define crm_debug(fmt, args...)
Definition logging.h:368
Formatted output for pacemaker tools.
void pcmk__xml_output_finish(pcmk__output_t *out, crm_exit_t exit_status, xmlNodePtr *xml)
Definition output.c:273
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
Definition output.c:246
High Level API.
int pcmk_controller_status(xmlNodePtr *xml, const char *node_name, unsigned int message_timeout_ms)
Get and output controller status.
int pcmk_designated_controller(xmlNodePtr *xml, unsigned int message_timeout_ms)
Get and output designated controller node name.
int pcmk_list_nodes(xmlNodePtr *xml, const char *node_types)
Get nodes list.
int pcmk__query_node_info(pcmk__output_t *out, uint32_t *node_id, char **node_name, char **uuid, char **state, bool *have_quorum, bool *is_remote, bool show_output, unsigned int message_timeout_ms)
int pcmk__pacemakerd_status(pcmk__output_t *out, const char *ipc_name, unsigned int message_timeout_ms, bool show_output, enum pcmk_pacemakerd_state *state)
int pcmk_pacemakerd_status(xmlNodePtr *xml, const char *ipc_name, unsigned int message_timeout_ms)
Get and output pacemakerd status.
int pcmk__designated_controller(pcmk__output_t *out, unsigned int message_timeout_ms)
int pcmk_query_node_info(xmlNodePtr *xml, uint32_t *node_id, char **node_name, char **uuid, char **state, bool *have_quorum, bool *is_remote, bool show_output, unsigned int message_timeout_ms)
Get and optionally output node info corresponding to a node ID from the controller.
int pcmk__controller_status(pcmk__output_t *out, const char *node_name, unsigned int message_timeout_ms)
int pcmk__list_nodes(pcmk__output_t *out, const char *node_types, bool bash_export)
pcmk__action_result_t result
Definition pcmk_fence.c:37
void pcmk__register_lib_messages(pcmk__output_t *out)
#define EREMOTEIO
Definition portability.h:51
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:617
@ CRM_EX_OK
Success.
Definition results.h:233
@ pcmk_rc_node_unknown
Definition results.h:149
@ pcmk_rc_no_dc
Definition results.h:114
@ pcmk_rc_ok
Definition results.h:159
const char * crm_exit_str(crm_exit_t exit_code)
Definition results.c:757
enum crm_exit_e crm_exit_t
Exit status codes for tools and daemons.
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
Definition results.c:820
#define pcmk__assert(expr)
void pcmk__str_update(char **str, const char *value)
Definition strings.c:1280
@ pcmk__str_regex
This structure contains everything that makes up a single output formatter.
void(* end_list)(pcmk__output_t *out)
int(* message)(pcmk__output_t *out, const char *message_id,...)
int int void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void(* begin_list)(pcmk__output_t *out, const char *singular_noun, const char *plural_noun, const char *format,...) G_GNUC_PRINTF(4
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
struct pcmk_controld_api_reply_t::@1::@2 node_info
const char * host_from
Name of node that sent reply.
struct pcmk_controld_api_reply_t::@1::@4 ping
enum pcmk_controld_api_reply reply_type
union pcmk_controld_api_reply_t::@1 data
enum pcmk_pacemakerd_api_reply reply_type
union pcmk_pacemakerd_api_reply_t::@5 data
struct pcmk_pacemakerd_api_reply_t::@5::@6 ping
enum pcmk_pacemakerd_state state
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
void pcmk__xml_free(xmlNode *xml)
Definition xml.c:816
#define PCMK_XA_ID
Definition xml_names.h:301
#define PCMK_XA_VALUE
Definition xml_names.h:442
#define PCMK_XE_NODES
Definition xml_names.h:142
#define PCMK_XA_UNAME
Definition xml_names.h:431
#define PCMK__XP_REMOTE_NODE_CONFIG
XPath expression matching CIB Pacemaker Remote connection resource.
#define PCMK__XP_MEMBER_NODE_CONFIG
XPath expression matching CIB node elements for cluster nodes.
#define PCMK__XP_GUEST_NODE_CONFIG
XPath expression matching CIB primitive meta-attribute defining a guest node.
void pcmk__xpath_foreach_result(xmlDoc *doc, const char *path, void(*fn)(xmlNode *, void *), void *user_data)
Definition xpath.c:170