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