pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
pcmk_cluster_queries.c
Go to the documentation of this file.
1 /*
2  * Copyright 2020-2024 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 
28 typedef 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 
42 typedef 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 
62 static int
63 validate_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 
107 static int
108 validate_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 
148 static int
149 validate_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 
185 static void
186 controller_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 
219 static void
220 designated_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 = pcmk_rc_ok;
239 }
240 
252 static void
253 node_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 
276  data->node_info.have_quorum = reply->data.node_info.have_quorum;
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,
288  reply->data.node_info.have_quorum,
289  reply->data.node_info.is_remote);
290  }
291 
292  data->rc = pcmk_rc_ok;
293 }
294 
306 static void
307 pacemakerd_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 
343 static pcmk_ipc_api_t *
344 ipc_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;
381  pcmk_free_ipc_api(api);
382  return NULL;
383  }
384 
385  return api;
386 }
387 
399 static void
400 poll_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 
425  pcmk_dispatch_ipc(api);
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 
458 int
459 pcmk__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
496 int
497 pcmk_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, pcmk_rc2exitc(rc), xml);
512  return rc;
513 }
514 
528 int
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
565 int
566 pcmk_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, pcmk_rc2exitc(rc), xml);
580  return rc;
581 }
582 
615 int
616 pcmk__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
688 int
689 pcmk_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);
709  pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
710  return rc;
711 }
712 
736 int
737 pcmk__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
784 int
785 pcmk_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, pcmk_rc2exitc(rc), xml);
800  return rc;
801 }
802 
803 /* user data for looping through remote node xpath searches */
804 struct 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 
812 static void
813 remote_node_print_helper(xmlNode *result, void *user_data)
814 {
815  struct node_data *data = user_data;
816  pcmk__output_t *out = data->out;
817  const char *name = crm_element_value(result, PCMK_XA_UNAME);
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
827 int
828 pcmk__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";
856  remote_node_print_helper, &data);
857  }
858 
859  if (pcmk__str_empty(node_types) || strstr(node_types, "guest")) {
860  data.field = PCMK_XA_VALUE;
861  data.type = "guest";
863  remote_node_print_helper, &data);
864  }
865 
866  if (pcmk__str_empty(node_types)
867  || pcmk__str_eq(node_types, ",|^remote", pcmk__str_regex)) {
868  data.field = PCMK_XA_ID;
869  data.type = "remote";
871  remote_node_print_helper, &data);
872  }
873 
874  out->end_list(out);
875 
876  if (data.found == 0) {
877  out->info(out, "No nodes configured");
878  }
879 
880  free_xml(xml_node);
881  }
882 
883  return rc;
884 }
885 
886 int
887 pcmk_list_nodes(xmlNodePtr *xml, const char *node_types)
888 {
889  pcmk__output_t *out = NULL;
890  int rc = pcmk_rc_ok;
891 
892  rc = pcmk__xml_output_new(&out, xml);
893  if (rc != pcmk_rc_ok) {
894  return rc;
895  }
896 
898 
899  rc = pcmk__list_nodes(out, node_types, FALSE);
900  pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
901  return rc;
902 }
void(* end_list)(pcmk__output_t *out)
A dumping ground.
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)
struct pcmk_controld_api_reply_t::@1::@4 ping
union pcmk_controld_api_reply_t::@1 data
char data[0]
Definition: cpg.c:58
enum pcmk_controld_api_reply reply_type
Definition: ipc_controld.h:59
int pcmk_designated_controller(xmlNodePtr *xml, unsigned int message_timeout_ms)
Get and output designated controller node name.
const char * pcmk__pcmkd_api_reply2str(enum pcmk_pacemakerd_api_reply reply)
int pcmk__designated_controller(pcmk__output_t *out, unsigned int message_timeout_ms)
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
Definition: cib_utils.c:970
const char * name
Definition: cib.c:26
int(* message)(pcmk__output_t *out, const char *message_id,...)
Launcher.
Definition: ipc.h:83
const char * host_from
Name of node that sent reply.
Definition: ipc_controld.h:61
int pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
Ask the controller for status.
Definition: ipc_controld.c:441
const char * pcmk__controld_api_reply2str(enum pcmk_controld_api_reply reply)
Definition: ipc_controld.c:41
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
int pcmk_controller_status(xmlNodePtr *xml, const char *node_name, unsigned int message_timeout_ms)
Get and output controller status.
void pcmk_dispatch_ipc(pcmk_ipc_api_t *api)
Dispatch available messages on an IPC connection (without main loop)
Definition: ipc_client.c:439
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
Definition: results.c:704
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.
#define EREMOTEIO
Definition: portability.h:96
High Level API.
enum crm_exit_e crm_exit_t
void pcmk__xml_output_finish(pcmk__output_t *out, crm_exit_t exit_status, xmlNodePtr *xml)
Definition: output.c:271
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
enum crm_ais_msg_types type
Definition: cpg.c:51
struct pcmk_pacemakerd_api_reply_t::@5::@6 ping
pcmk_pacemakerd_api_reply
Possible types of pacemakerd replies.
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:503
int pcmk__connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type, int attempts)
Definition: ipc_client.c:501
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
union pcmk_pacemakerd_api_reply_t::@5 data
Caller will poll and dispatch IPC.
Definition: ipc.h:104
enum pcmk_pacemakerd_api_reply reply_type
Formatted output for pacemaker tools.
#define PCMK__XP_GUEST_NODE_CONFIG
Definition: xml_internal.h:181
pcmk_ipc_server
Available IPC interfaces.
Definition: ipc.h:77
const char * crm_exit_str(crm_exit_t exit_code)
Definition: results.c:642
#define crm_debug(fmt, args...)
Definition: logging.h:402
#define PCMK_XA_UNAME
Definition: xml_names.h:431
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:458
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
Definition: output.c:244
int(*) int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void pcmk__register_lib_messages(pcmk__output_t *out)
Definition: pcmk_output.c:2680
#define PCMK__XP_REMOTE_NODE_CONFIG
Definition: xml_internal.h:187
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1289
Wrappers for and extensions to libxml2.
int pcmk_list_nodes(xmlNodePtr *xml, const char *node_types)
Get nodes list.
ISO_8601 Date handling.
#define PCMK_XA_ID
Definition: xml_names.h:301
Success.
Definition: results.h:251
#define PCMK_XA_VALUE
Definition: xml_names.h:442
IPC commands for Pacemakerd.
int pcmk__list_nodes(pcmk__output_t *out, const char *node_types, bool bash_export)
void free_xml(xmlNode *child)
Definition: xml.c:958
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:126
IPC commands for Pacemaker controller.
uint32_t id
Definition: cpg.c:48
int pcmk_pacemakerd_api_ping(pcmk_ipc_api_t *api, const char *ipc_name)
#define pcmk__assert(expr)
pcmk_pacemakerd_state
pcmk_ipc_dispatch
How IPC replies should be dispatched.
Definition: ipc.h:102
int pcmk__controller_status(pcmk__output_t *out, const char *node_name, unsigned int message_timeout_ms)
pcmk_ipc_event
Possible event types that an IPC event callback can be called for.
Definition: ipc.h:89
Termination of IPC connection.
Definition: ipc.h:93
pcmk__action_result_t result
Definition: pcmk_fence.c:35
Controller.
Definition: ipc.h:80
struct pcmk_controld_api_reply_t::@1::@2 node_info
Sending a command will wait for any reply.
Definition: ipc.h:105
Cluster Configuration.
void pcmk_free_ipc_api(pcmk_ipc_api_t *api)
Free the contents of an IPC API object.
Definition: ipc_client.c:206
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)
This structure contains everything that makes up a single output formatter.
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(* begin_list)(pcmk__output_t *out, const char *singular_noun, const char *plural_noun, const char *format,...) G_GNUC_PRINTF(4
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
#define PCMK_XE_NODES
Definition: xml_names.h:142
Daemon&#39;s reply to client IPC request.
Definition: ipc.h:96
int pcmk_pacemakerd_status(xmlNodePtr *xml, const char *ipc_name, unsigned int message_timeout_ms)
Get and output pacemakerd status.
#define PCMK__XP_MEMBER_NODE_CONFIG
Definition: xml_internal.h:175
int pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
Send a "node info" controller operation.
Definition: ipc_controld.c:413
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
pcmk_controld_api_reply
Possible types of controller replies.
Definition: ipc_controld.h:31