pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
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 
29 typedef 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 
43 typedef 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 
63 static int
64 validate_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 
108 static int
109 validate_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 
149 static int
150 validate_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 
186 static void
187 controller_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 
220 static void
221 designated_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 
253 static void
254 node_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,
289  reply->data.node_info.have_quorum,
290  reply->data.node_info.is_remote);
291  }
292 
293  data->rc = pcmk_rc_ok;
294 }
295 
307 static void
308 pacemakerd_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 
344 static pcmk_ipc_api_t *
345 ipc_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;
382  pcmk_free_ipc_api(api);
383  return NULL;
384  }
385 
386  return api;
387 }
388 
400 static void
401 poll_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 
426  pcmk_dispatch_ipc(api);
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 
459 int
460 pcmk__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
497 int
498 pcmk_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 
529 int
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
566 int
567 pcmk_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 
616 int
617 pcmk__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
689 int
690 pcmk_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 
737 int
738 pcmk__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
785 int
786 pcmk_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 */
805 struct 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 
813 static void
814 remote_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
828 int
829 pcmk__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 
883 int
884 pcmk_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 }
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 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
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:433
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: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
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
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:501
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:90
enum pcmk_pacemakerd_api_reply reply_type
Formatted output for pacemaker tools.
#define PCMK__XP_GUEST_NODE_CONFIG
Definition: xml_internal.h:176
pcmk_ipc_server
Available IPC interfaces.
Definition: ipc.h:69
const char * crm_exit_str(crm_exit_t exit_code)
Definition: results.c:640
#define crm_debug(fmt, args...)
Definition: logging.h:386
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:447
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:2403
#define PCMK__XP_REMOTE_NODE_CONFIG
Definition: xml_internal.h:182
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:178
ISO_8601 Date handling.
Success.
Definition: results.h:240
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:783
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_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: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
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:171
int pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
Send a "node info" controller operation.
Definition: ipc_controld.c:405
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