pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
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 
30 typedef 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 
44 typedef 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 
64 static int
65 validate_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 
109 static int
110 validate_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 
150 static int
151 validate_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 
187 static void
188 controller_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 
221 static void
222 designated_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 
254 static void
255 node_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,
290  reply->data.node_info.have_quorum,
291  reply->data.node_info.is_remote);
292  }
293 
294  data->rc = pcmk_rc_ok;
295 }
296 
308 static void
309 pacemakerd_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 
345 static pcmk_ipc_api_t *
346 ipc_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;
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 = 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 
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, 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, 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  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 
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, 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  gboolean 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;
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
829 int
830 pcmk__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 
884 int
885 pcmk_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 }
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:55
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 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
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
int(* message)(pcmk__output_t *out, const char *message_id,...)
Launcher.
Definition: ipc.h:75
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:448
const char * pcmk__controld_api_reply2str(enum pcmk_controld_api_reply reply)
Definition: ipc_controld.c:39
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
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:428
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:135
High Level API.
enum crm_exit_e crm_exit_t
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
enum crm_ais_msg_types type
Definition: cpg.c:48
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:488
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
union pcmk_pacemakerd_api_reply_t::@5 data
Caller will poll and dispatch IPC.
Definition: ipc.h:90
enum pcmk_pacemakerd_api_reply reply_type
Formatted output for pacemaker tools.
#define PCMK__XP_GUEST_NODE_CONFIG
Definition: xml_internal.h:179
pcmk_ipc_server
Available IPC interfaces.
Definition: ipc.h:69
const char * crm_exit_str(crm_exit_t exit_code)
Definition: results.c:627
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:496
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
Definition: output.c:236
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:2329
#define PCMK__XP_REMOTE_NODE_CONFIG
Definition: xml_internal.h:185
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
Wrappers for and extensions to libxml2.
int pcmk_list_nodes(xmlNodePtr *xml, const char *node_types)
Get nodes list.
#define XML_ATTR_UNAME
Definition: msg_xml.h:170
ISO_8601 Date handling.
Success.
Definition: results.h:237
IPC commands for Pacemakerd.
void free_xml(xmlNode *child)
Definition: xml.c:813
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
IPC commands for Pacemaker controller.
uint32_t id
Definition: cpg.c:45
int pcmk__list_nodes(pcmk__output_t *out, const char *node_types, gboolean bash_export)
int pcmk_pacemakerd_api_ping(pcmk_ipc_api_t *api, const char *ipc_name)
pcmk_pacemakerd_state
pcmk_ipc_dispatch
How IPC replies should be dispatched.
Definition: ipc.h:88
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:80
Termination of IPC connection.
Definition: ipc.h:82
pcmk__action_result_t result
Definition: pcmk_fence.c:35
Controller.
Definition: ipc.h:72
struct pcmk_controld_api_reply_t::@1::@2 node_info
#define CRM_ASSERT(expr)
Definition: results.h:42
Sending a command will wait for any reply.
Definition: ipc.h:91
Cluster Configuration.
void pcmk_free_ipc_api(pcmk_ipc_api_t *api)
Free the contents of an IPC API object.
Definition: ipc_client.c:202
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:243
int pcmk__strcmp(const char *s1, const char *s2, uint32_t flags)
Definition: strings.c:1108
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:173
void pcmk__xml_output_finish(pcmk__output_t *out, xmlNodePtr *xml)
Definition: output.c:258
Daemon&#39;s reply to client IPC request.
Definition: ipc.h:83
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:174
int pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
Send a "node info" controller operation.
Definition: ipc_controld.c:420
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
pcmk_controld_api_reply
Possible types of controller replies.
Definition: ipc_controld.h:31