pacemaker 2.1.6-6fdc9deea29
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-2022 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 <glib.h> // gboolean, GMainLoop, etc.
13#include <libxml/tree.h> // xmlNode
14
15#include <pacemaker.h>
16#include <pacemaker-internal.h>
17
18#include <crm/crm.h>
19#include <crm/cib.h>
20#include <crm/cib/internal.h>
21#include <crm/msg_xml.h>
23#include <crm/common/xml.h>
25#include <crm/common/iso8601.h>
28
30typedef struct {
31 /* Adapted from pcmk_controld_api_reply_t:data:node_info.
32 * (char **) are convenient here for use within callbacks: we can skip
33 * copying strings unless the caller passes a non-NULL value.
34 */
35 uint32_t id;
36 char **node_name;
37 char **uuid;
38 char **state;
39 bool have_quorum;
40 bool is_remote;
41} node_info_t;
42
44typedef struct {
45 pcmk__output_t *out;
46 bool show_output;
47 int rc;
48 unsigned int message_timeout_ms;
49 enum pcmk_pacemakerd_state pcmkd_state;
50 node_info_t node_info;
51} data_t;
52
64static int
65validate_reply_event(data_t *data, const pcmk_ipc_api_t *api,
66 enum pcmk_ipc_event event_type, crm_exit_t status)
67{
68 pcmk__output_t *out = data->out;
69
70 switch (event_type) {
72 break;
73
75 if (data->rc == ECONNRESET) { // Unexpected
76 out->err(out, "error: Lost connection to %s",
77 pcmk_ipc_name(api, true));
78 }
79 // Nothing bad but not the reply we're looking for
80 return ENOTSUP;
81
82 default:
83 // Ditto
84 return ENOTSUP;
85 }
86
87 if (status != CRM_EX_OK) {
88 out->err(out, "error: Bad reply from %s: %s",
89 pcmk_ipc_name(api, true), crm_exit_str(status));
90 data->rc = EBADMSG;
91 return data->rc;
92 }
93 return pcmk_rc_ok;
94}
95
109static int
110validate_controld_reply(data_t *data, const pcmk_ipc_api_t *api,
111 enum pcmk_ipc_event event_type, crm_exit_t status,
112 const void *event_data,
113 enum pcmk_controld_api_reply expected_type)
114{
115 pcmk__output_t *out = data->out;
116 int rc = pcmk_rc_ok;
117 const pcmk_controld_api_reply_t *reply = NULL;
118
119 rc = validate_reply_event(data, api, event_type, status);
120 if (rc != pcmk_rc_ok) {
121 return rc;
122 }
123
124 reply = (const pcmk_controld_api_reply_t *) event_data;
125
126 if (reply->reply_type != expected_type) {
127 out->err(out, "error: Unexpected reply type '%s' from controller",
129 data->rc = EBADMSG;
130 return data->rc;
131 }
132
133 return pcmk_rc_ok;
134}
135
150static int
151validate_pcmkd_reply(data_t *data, const pcmk_ipc_api_t *api,
152 enum pcmk_ipc_event event_type, crm_exit_t status,
153 const void *event_data,
154 enum pcmk_pacemakerd_api_reply expected_type)
155{
156 pcmk__output_t *out = data->out;
157 const pcmk_pacemakerd_api_reply_t *reply = NULL;
158 int rc = validate_reply_event(data, api, event_type, status);
159
160 if (rc != pcmk_rc_ok) {
161 return rc;
162 }
163
164 reply = (const pcmk_pacemakerd_api_reply_t *) event_data;
165
166 if (reply->reply_type != expected_type) {
167 out->err(out, "error: Unexpected reply type '%s' from pacemakerd",
169 data->rc = EBADMSG;
170 return data->rc;
171 }
172
173 return pcmk_rc_ok;
174}
175
187static void
188controller_status_event_cb(pcmk_ipc_api_t *controld_api,
189 enum pcmk_ipc_event event_type, crm_exit_t status,
190 void *event_data, void *user_data)
191{
192 data_t *data = (data_t *) user_data;
193 pcmk__output_t *out = data->out;
194 const pcmk_controld_api_reply_t *reply = NULL;
195
196 int rc = validate_controld_reply(data, controld_api, event_type, status,
197 event_data, pcmk_controld_reply_ping);
198
199 if (rc != pcmk_rc_ok) {
200 return;
201 }
202
203 reply = (const pcmk_controld_api_reply_t *) event_data;
204 out->message(out, "health",
205 reply->data.ping.sys_from, reply->host_from,
206 reply->data.ping.fsa_state, reply->data.ping.result);
207 data->rc = pcmk_rc_ok;
208}
209
221static void
222designated_controller_event_cb(pcmk_ipc_api_t *controld_api,
223 enum pcmk_ipc_event event_type,
224 crm_exit_t status, void *event_data,
225 void *user_data)
226{
227 data_t *data = (data_t *) user_data;
228 pcmk__output_t *out = data->out;
229 const pcmk_controld_api_reply_t *reply = NULL;
230
231 int rc = validate_controld_reply(data, controld_api, event_type, status,
232 event_data, pcmk_controld_reply_ping);
233
234 if (rc != pcmk_rc_ok) {
235 return;
236 }
237
238 reply = (const pcmk_controld_api_reply_t *) event_data;
239 out->message(out, "dc", reply->host_from);
240 data->rc = pcmk_rc_ok;
241}
242
254static void
255node_info_event_cb(pcmk_ipc_api_t *controld_api, enum pcmk_ipc_event event_type,
256 crm_exit_t status, void *event_data, void *user_data)
257{
258 data_t *data = (data_t *) user_data;
259 pcmk__output_t *out = data->out;
260
261 const pcmk_controld_api_reply_t *reply = NULL;
262
263 int rc = validate_controld_reply(data, controld_api, event_type, status,
264 event_data, pcmk_controld_reply_info);
265
266 if (rc != pcmk_rc_ok) {
267 return;
268 }
269
270 reply = (const pcmk_controld_api_reply_t *) event_data;
271
272 if (reply->data.node_info.uname == NULL) {
273 out->err(out, "Node is not known to cluster");
275 return;
276 }
277
278 data->node_info.have_quorum = reply->data.node_info.have_quorum;
279 data->node_info.is_remote = reply->data.node_info.is_remote;
280 data->node_info.id = (uint32_t) reply->data.node_info.id;
281
282 pcmk__str_update(data->node_info.node_name, reply->data.node_info.uname);
283 pcmk__str_update(data->node_info.uuid, reply->data.node_info.uuid);
284 pcmk__str_update(data->node_info.state, reply->data.node_info.state);
285
286 if (data->show_output) {
287 out->message(out, "node-info",
288 reply->data.node_info.id, reply->data.node_info.uname,
289 reply->data.node_info.uuid, reply->data.node_info.state,
291 reply->data.node_info.is_remote);
292 }
293
294 data->rc = pcmk_rc_ok;
295}
296
308static void
309pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
310 enum pcmk_ipc_event event_type, crm_exit_t status,
311 void *event_data, void *user_data)
312{
313 data_t *data = user_data;
314 pcmk__output_t *out = data->out;
315 const pcmk_pacemakerd_api_reply_t *reply = NULL;
316
317 int rc = validate_pcmkd_reply(data, pacemakerd_api, event_type, status,
318 event_data, pcmk_pacemakerd_reply_ping);
319
320 if (rc != pcmk_rc_ok) {
321 return;
322 }
323
324 // Parse desired information from reply
325 reply = (const pcmk_pacemakerd_api_reply_t *) event_data;
326
327 data->pcmkd_state = reply->data.ping.state;
328 data->rc = pcmk_rc_ok;
329
330 if (!data->show_output) {
331 return;
332 }
333
334 if (reply->data.ping.status == pcmk_rc_ok) {
335 out->message(out, "pacemakerd-health",
336 reply->data.ping.sys_from, reply->data.ping.state, NULL,
337 reply->data.ping.last_good);
338 } else {
339 out->message(out, "pacemakerd-health",
340 reply->data.ping.sys_from, reply->data.ping.state,
341 "query failed", time(NULL));
342 }
343}
344
345static pcmk_ipc_api_t *
346ipc_connect(data_t *data, enum pcmk_ipc_server server, pcmk_ipc_callback_t cb,
347 enum pcmk_ipc_dispatch dispatch_type, bool eremoteio_ok)
348{
349 int rc;
350 pcmk__output_t *out = data->out;
351 pcmk_ipc_api_t *api = NULL;
352
353 rc = pcmk_new_ipc_api(&api, server);
354 if (api == NULL) {
355 out->err(out, "error: Could not connect to %s: %s",
356 pcmk_ipc_name(api, true),
357 pcmk_rc_str(rc));
358 data->rc = rc;
359 return NULL;
360 }
361 if (cb != NULL) {
363 }
364
365 rc = pcmk_connect_ipc(api, dispatch_type);
366
367 if (rc != pcmk_rc_ok) {
368 if (rc == EREMOTEIO) {
369 data->pcmkd_state = pcmk_pacemakerd_state_remote;
370 if (eremoteio_ok) {
371 /* EREMOTEIO may be expected and acceptable for some callers
372 * on a Pacemaker Remote node
373 */
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 = start_nsec;
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);
511 pcmk__xml_output_finish(out, xml);
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);
579 pcmk__xml_output_finish(out, xml);
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 CRM_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);
709 pcmk__xml_output_finish(out, xml);
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);
799 pcmk__xml_output_finish(out, xml);
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 gboolean 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 name ? name : id,
823 id,
824 data->bash_export);
825 data->found++;
826}
827
828// \return Standard Pacemaker return code
829int
830pcmk__list_nodes(pcmk__output_t *out, const char *node_types,
831 gboolean bash_export)
832{
833 xmlNode *xml_node = NULL;
834 int rc;
835
836 rc = cib__signon_query(out, NULL, &xml_node);
837
838 if (rc == pcmk_rc_ok) {
839 struct node_data data = {
840 .out = out,
841 .found = 0,
842 .bash_export = bash_export
843 };
844
845 out->begin_list(out, NULL, NULL, "nodes");
846
847 if (!pcmk__str_empty(node_types) && strstr(node_types, "all")) {
848 node_types = NULL;
849 }
850
851 if (pcmk__str_empty(node_types) || strstr(node_types, "cluster")) {
852 data.field = "id";
853 data.type = "cluster";
855 remote_node_print_helper, &data);
856 }
857
858 if (pcmk__str_empty(node_types) || strstr(node_types, "guest")) {
859 data.field = "value";
860 data.type = "guest";
862 remote_node_print_helper, &data);
863 }
864
865 if (pcmk__str_empty(node_types) || !pcmk__strcmp(node_types, ",|^remote", pcmk__str_regex)) {
866 data.field = "id";
867 data.type = "remote";
869 remote_node_print_helper, &data);
870 }
871
872 out->end_list(out);
873
874 if (data.found == 0) {
875 out->info(out, "No nodes configured");
876 }
877
878 free_xml(xml_node);
879 }
880
881 return rc;
882}
883
884int
885pcmk_list_nodes(xmlNodePtr *xml, const char *node_types)
886{
887 pcmk__output_t *out = NULL;
888 int rc = pcmk_rc_ok;
889
890 rc = pcmk__xml_output_new(&out, xml);
891 if (rc != pcmk_rc_ok) {
892 return rc;
893 }
894
896
897 rc = pcmk__list_nodes(out, node_types, FALSE);
898 pcmk__xml_output_finish(out, xml);
899 return rc;
900}
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
Definition cib_utils.c:745
const char * name
Definition cib.c:24
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:395
int pcmk_connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type)
Connect to a Pacemaker daemon via IPC.
Definition ipc_client.c:489
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:243
void pcmk_free_ipc_api(pcmk_ipc_api_t *api)
Free the contents of an IPC API object.
Definition ipc_client.c:202
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:47
void pcmk_dispatch_ipc(pcmk_ipc_api_t *api)
Dispatch available messages on an IPC connection (without main loop)
Definition ipc_client.c:428
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:616
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)
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 XML_ATTR_UNAME
Definition msg_xml.h:170
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:496
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__list_nodes(pcmk__output_t *out, const char *node_types, gboolean bash_export)
int pcmk__controller_status(pcmk__output_t *out, const char *node_name, unsigned int message_timeout_ms)
pcmk__action_result_t result
Definition pcmk_fence.c:35
void pcmk__register_lib_messages(pcmk__output_t *out)
#define EREMOTEIO
#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:488
@ CRM_EX_OK
Success.
Definition results.h:237
@ pcmk_rc_node_unknown
Definition results.h:142
@ pcmk_rc_ok
Definition results.h:151
const char * crm_exit_str(crm_exit_t exit_code)
Definition results.c:627
enum crm_exit_e crm_exit_t
void pcmk__str_update(char **str, const char *value)
Definition strings.c:1193
@ pcmk__str_regex
int pcmk__strcmp(const char *s1, const char *s2, uint32_t flags)
Definition strings.c:1108
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:173
void free_xml(xmlNode *child)
Definition xml.c:813
#define PCMK__XP_REMOTE_NODE_CONFIG
#define PCMK__XP_MEMBER_NODE_CONFIG
#define PCMK__XP_GUEST_NODE_CONFIG