pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
cib_remote.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008-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 <unistd.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <netdb.h>
18 #include <termios.h>
19 #include <sys/socket.h>
20 
21 #include <glib.h>
22 
23 #include <crm/crm.h>
24 #include <crm/cib/internal.h>
26 #include <crm/common/mainloop.h>
27 #include <crm/common/xml.h>
30 
31 #ifdef HAVE_GNUTLS_GNUTLS_H
32 
33 # include <gnutls/gnutls.h>
34 
35 // GnuTLS handshake timeout in seconds
36 #define TLS_HANDSHAKE_TIMEOUT 5
37 
38 static gnutls_anon_client_credentials_t anon_cred_c;
39 static gboolean remote_gnutls_credentials_init = FALSE;
40 
41 #endif // HAVE_GNUTLS_GNUTLS_H
42 
43 #include <arpa/inet.h>
44 
45 typedef struct cib_remote_opaque_s {
46  int port;
47  char *server;
48  char *user;
49  char *passwd;
50  gboolean encrypted;
51  pcmk__remote_t command;
52  pcmk__remote_t callback;
53  pcmk__output_t *out;
54  time_t start_time;
55  int timeout_sec;
57 
58 static int
59 cib_remote_perform_op(cib_t *cib, const char *op, const char *host,
60  const char *section, xmlNode *data,
61  xmlNode **output_data, int call_options,
62  const char *user_name)
63 {
64  int rc;
65  int remaining_time = 0;
66  time_t start_time;
67 
68  xmlNode *op_msg = NULL;
69  xmlNode *op_reply = NULL;
70 
71  cib_remote_opaque_t *private = cib->variant_opaque;
72 
73  if (cib->state == cib_disconnected) {
74  return -ENOTCONN;
75  }
76 
77  if (output_data != NULL) {
78  *output_data = NULL;
79  }
80 
81  if (op == NULL) {
82  crm_err("No operation specified");
83  return -EINVAL;
84  }
85 
86  rc = cib__create_op(cib, op, host, section, data, call_options, user_name,
87  NULL, &op_msg);
88  if (rc != pcmk_ok) {
89  return rc;
90  }
91 
92  if (pcmk_is_set(call_options, cib_transaction)) {
93  rc = cib__extend_transaction(cib, op_msg);
94  free_xml(op_msg);
95  return rc;
96  }
97 
98  crm_trace("Sending %s message to the CIB manager", op);
99  if (!(call_options & cib_sync_call)) {
100  pcmk__remote_send_xml(&private->callback, op_msg);
101  } else {
102  pcmk__remote_send_xml(&private->command, op_msg);
103  }
104  free_xml(op_msg);
105 
106  if ((call_options & cib_discard_reply)) {
107  crm_trace("Discarding reply");
108  return pcmk_ok;
109 
110  } else if (!(call_options & cib_sync_call)) {
111  return cib->call_id;
112  }
113 
114  crm_trace("Waiting for a synchronous reply");
115 
116  start_time = time(NULL);
117  remaining_time = cib->call_timeout ? cib->call_timeout : 60;
118 
119  rc = pcmk_rc_ok;
120  while (remaining_time > 0 && (rc != ENOTCONN)) {
121  int reply_id = -1;
122  int msg_id = cib->call_id;
123 
124  rc = pcmk__read_remote_message(&private->command,
125  remaining_time * 1000);
126  op_reply = pcmk__remote_message_xml(&private->command);
127 
128  if (!op_reply) {
129  break;
130  }
131 
132  crm_element_value_int(op_reply, PCMK__XA_CIB_CALLID, &reply_id);
133 
134  if (reply_id == msg_id) {
135  break;
136 
137  } else if (reply_id < msg_id) {
138  crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id);
139  crm_log_xml_trace(op_reply, "Old reply");
140 
141  } else if ((reply_id - 10000) > msg_id) {
142  /* wrap-around case */
143  crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id);
144  crm_log_xml_trace(op_reply, "Old reply");
145  } else {
146  crm_err("Received a __future__ reply:" " %d (wanted %d)", reply_id, msg_id);
147  }
148 
149  free_xml(op_reply);
150  op_reply = NULL;
151 
152  /* wasn't the right reply, try and read some more */
153  remaining_time = time(NULL) - start_time;
154  }
155 
156  if (rc == ENOTCONN) {
157  crm_err("Disconnected while waiting for reply.");
158  return -ENOTCONN;
159  } else if (op_reply == NULL) {
160  crm_err("No reply message - empty");
161  return -ENOMSG;
162  }
163 
164  crm_trace("Synchronous reply received");
165 
166  /* Start processing the reply... */
167  if (crm_element_value_int(op_reply, PCMK__XA_CIB_RC, &rc) != 0) {
168  rc = -EPROTO;
169  }
170 
171  if (rc == -pcmk_err_diff_resync) {
172  /* This is an internal value that clients do not and should not care about */
173  rc = pcmk_ok;
174  }
175 
176  if (rc == pcmk_ok || rc == -EPERM) {
177  crm_log_xml_debug(op_reply, "passed");
178 
179  } else {
180  crm_err("Call failed: %s", pcmk_strerror(rc));
181  crm_log_xml_warn(op_reply, "failed");
182  }
183 
184  if (output_data == NULL) {
185  /* do nothing more */
186 
187  } else if (!(call_options & cib_discard_reply)) {
188  xmlNode *wrapper = pcmk__xe_first_child(op_reply, PCMK__XE_CIB_CALLDATA,
189  NULL, NULL);
190  xmlNode *tmp = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
191 
192  if (tmp == NULL) {
193  crm_trace("No output in reply to \"%s\" command %d", op, cib->call_id - 1);
194  } else {
195  *output_data = pcmk__xml_copy(NULL, tmp);
196  }
197  }
198 
199  free_xml(op_reply);
200 
201  return rc;
202 }
203 
204 static int
205 cib_remote_callback_dispatch(gpointer user_data)
206 {
207  int rc;
208  cib_t *cib = user_data;
209  cib_remote_opaque_t *private = cib->variant_opaque;
210 
211  xmlNode *msg = NULL;
212  const char *type = NULL;
213 
214  /* If start time is 0, we've previously handled a complete message and this
215  * connection is being reused for a new message. Reset the start_time,
216  * giving this new message timeout_sec from now to complete.
217  */
218  if (private->start_time == 0) {
219  private->start_time = time(NULL);
220  }
221 
222  rc = pcmk__read_available_remote_data(&private->callback);
223  switch (rc) {
224  case pcmk_rc_ok:
225  /* We have the whole message so process it */
226  break;
227 
228  case EAGAIN:
229  /* Have we timed out? */
230  if (time(NULL) >= private->start_time + private->timeout_sec) {
231  crm_info("Error reading from CIB manager connection: %s",
232  pcmk_rc_str(ETIME));
233  return -1;
234  }
235 
236  /* We haven't read the whole message yet */
237  return 0;
238 
239  default:
240  /* Error */
241  crm_info("Error reading from CIB manager connection: %s",
242  pcmk_rc_str(rc));
243  return -1;
244  }
245 
246  msg = pcmk__remote_message_xml(&private->callback);
247  if (msg == NULL) {
248  private->start_time = 0;
249  return 0;
250  }
251 
253 
254  crm_trace("Activating %s callbacks...", type);
255 
256  if (pcmk__str_eq(type, PCMK__VALUE_CIB, pcmk__str_none)) {
257  cib_native_callback(cib, msg, 0, 0);
258  } else if (pcmk__str_eq(type, PCMK__VALUE_CIB_NOTIFY, pcmk__str_none)) {
259  g_list_foreach(cib->notify_list, cib_native_notify, msg);
260  } else {
261  crm_err("Unknown message type: %s", type);
262  }
263 
264  free_xml(msg);
265  private->start_time = 0;
266  return 0;
267 }
268 
269 static int
270 cib_remote_command_dispatch(gpointer user_data)
271 {
272  int rc;
273  cib_t *cib = user_data;
274  cib_remote_opaque_t *private = cib->variant_opaque;
275 
276  /* See cib_remote_callback_dispatch */
277  if (private->start_time == 0) {
278  private->start_time = time(NULL);
279  }
280 
281  rc = pcmk__read_available_remote_data(&private->command);
282  if (rc == EAGAIN) {
283  /* Have we timed out? */
284  if (time(NULL) >= private->start_time + private->timeout_sec) {
285  crm_info("Error reading from CIB manager connection: %s",
286  pcmk_rc_str(ETIME));
287  return -1;
288  }
289 
290  /* We haven't read the whole message yet */
291  return 0;
292  }
293 
294  free(private->command.buffer);
295  private->command.buffer = NULL;
296  crm_err("received late reply for remote cib connection, discarding");
297 
298  if (rc != pcmk_rc_ok) {
299  crm_info("Error reading from CIB manager connection: %s",
300  pcmk_rc_str(rc));
301  return -1;
302  }
303 
304  private->start_time = 0;
305  return 0;
306 }
307 
308 static int
309 cib_tls_close(cib_t *cib)
310 {
311  cib_remote_opaque_t *private = cib->variant_opaque;
312 
313 #ifdef HAVE_GNUTLS_GNUTLS_H
314  if (private->encrypted) {
315  if (private->command.tls_session) {
316  gnutls_bye(*(private->command.tls_session), GNUTLS_SHUT_RDWR);
317  gnutls_deinit(*(private->command.tls_session));
318  gnutls_free(private->command.tls_session);
319  }
320 
321  if (private->callback.tls_session) {
322  gnutls_bye(*(private->callback.tls_session), GNUTLS_SHUT_RDWR);
323  gnutls_deinit(*(private->callback.tls_session));
324  gnutls_free(private->callback.tls_session);
325  }
326  private->command.tls_session = NULL;
327  private->callback.tls_session = NULL;
328  if (remote_gnutls_credentials_init) {
329  gnutls_anon_free_client_credentials(anon_cred_c);
330  gnutls_global_deinit();
331  remote_gnutls_credentials_init = FALSE;
332  }
333  }
334 #endif
335 
336  if (private->command.tcp_socket) {
337  shutdown(private->command.tcp_socket, SHUT_RDWR); /* no more receptions */
338  close(private->command.tcp_socket);
339  }
340  if (private->callback.tcp_socket) {
341  shutdown(private->callback.tcp_socket, SHUT_RDWR); /* no more receptions */
342  close(private->callback.tcp_socket);
343  }
344  private->command.tcp_socket = 0;
345  private->callback.tcp_socket = 0;
346 
347  free(private->command.buffer);
348  free(private->callback.buffer);
349  private->command.buffer = NULL;
350  private->callback.buffer = NULL;
351 
352  return 0;
353 }
354 
355 static void
356 cib_remote_connection_destroy(gpointer user_data)
357 {
358  crm_err("Connection destroyed");
359 #ifdef HAVE_GNUTLS_GNUTLS_H
360  cib_tls_close(user_data);
361 #endif
362 }
363 
364 static int
365 cib_tls_signon(cib_t *cib, pcmk__remote_t *connection, gboolean event_channel)
366 {
367  cib_remote_opaque_t *private = cib->variant_opaque;
368  int rc;
369 
370  xmlNode *answer = NULL;
371  xmlNode *login = NULL;
372 
373  static struct mainloop_fd_callbacks cib_fd_callbacks = { 0, };
374 
375  cib_fd_callbacks.dispatch =
376  event_channel ? cib_remote_callback_dispatch : cib_remote_command_dispatch;
377  cib_fd_callbacks.destroy = cib_remote_connection_destroy;
378 
379  connection->tcp_socket = -1;
380 #ifdef HAVE_GNUTLS_GNUTLS_H
381  connection->tls_session = NULL;
382 #endif
383  rc = pcmk__connect_remote(private->server, private->port, 0, NULL,
384  &(connection->tcp_socket), NULL, NULL);
385  if (rc != pcmk_rc_ok) {
386  crm_info("Remote connection to %s:%d failed: %s " CRM_XS " rc=%d",
387  private->server, private->port, pcmk_rc_str(rc), rc);
388  return -ENOTCONN;
389  }
390 
391  if (private->encrypted) {
392  int tls_rc = GNUTLS_E_SUCCESS;
393 
394  /* initialize GnuTls lib */
395 #ifdef HAVE_GNUTLS_GNUTLS_H
396  if (remote_gnutls_credentials_init == FALSE) {
397  crm_gnutls_global_init();
398  gnutls_anon_allocate_client_credentials(&anon_cred_c);
399  remote_gnutls_credentials_init = TRUE;
400  }
401 
402  /* bind the socket to GnuTls lib */
403  connection->tls_session = pcmk__new_tls_session(connection->tcp_socket,
404  GNUTLS_CLIENT,
405  GNUTLS_CRD_ANON,
406  anon_cred_c);
407  if (connection->tls_session == NULL) {
408  cib_tls_close(cib);
409  return -1;
410  }
411 
412  rc = pcmk__tls_client_handshake(connection, TLS_HANDSHAKE_TIMEOUT,
413  &tls_rc);
414  if (rc != pcmk_rc_ok) {
415  crm_err("Remote CIB session creation for %s:%d failed: %s",
416  private->server, private->port,
417  (rc == EPROTO)? gnutls_strerror(tls_rc) : pcmk_rc_str(rc));
418  gnutls_deinit(*connection->tls_session);
419  gnutls_free(connection->tls_session);
420  connection->tls_session = NULL;
421  cib_tls_close(cib);
422  return -1;
423  }
424 #else
425  return -EPROTONOSUPPORT;
426 #endif
427  }
428 
429  /* login to server */
430  login = pcmk__xe_create(NULL, PCMK__XE_CIB_COMMAND);
431  crm_xml_add(login, PCMK_XA_OP, "authenticate");
432  crm_xml_add(login, PCMK_XA_USER, private->user);
433  crm_xml_add(login, PCMK__XA_PASSWORD, private->passwd);
435 
436  pcmk__remote_send_xml(connection, login);
437  free_xml(login);
438 
439  rc = pcmk_ok;
440  if (pcmk__read_remote_message(connection, -1) == ENOTCONN) {
441  rc = -ENOTCONN;
442  }
443 
444  answer = pcmk__remote_message_xml(connection);
445 
446  crm_log_xml_trace(answer, "Reply");
447  if (answer == NULL) {
448  rc = -EPROTO;
449 
450  } else {
451  /* grab the token */
452  const char *msg_type = crm_element_value(answer, PCMK__XA_CIB_OP);
453  const char *tmp_ticket = crm_element_value(answer,
455 
456  if (!pcmk__str_eq(msg_type, CRM_OP_REGISTER, pcmk__str_casei)) {
457  crm_err("Invalid registration message: %s", msg_type);
458  rc = -EPROTO;
459 
460  } else if (tmp_ticket == NULL) {
461  rc = -EPROTO;
462 
463  } else {
464  connection->token = strdup(tmp_ticket);
465  }
466  }
467  free_xml(answer);
468  answer = NULL;
469 
470  if (rc != 0) {
471  cib_tls_close(cib);
472  return rc;
473  }
474 
475  crm_trace("remote client connection established");
476  private->timeout_sec = 60;
477  connection->source = mainloop_add_fd("cib-remote", G_PRIORITY_HIGH,
478  connection->tcp_socket, cib,
479  &cib_fd_callbacks);
480  return rc;
481 }
482 
483 static int
484 cib_remote_signon(cib_t *cib, const char *name, enum cib_conn_type type)
485 {
486  int rc = pcmk_ok;
487  cib_remote_opaque_t *private = cib->variant_opaque;
488  xmlNode *hello = NULL;
489 
490  if (private->passwd == NULL) {
491  if (private->out == NULL) {
492  /* If no pcmk__output_t is set, just assume that a text prompt
493  * is good enough.
494  */
495  pcmk__text_prompt("Password", false, &(private->passwd));
496  } else {
497  private->out->prompt("Password", false, &(private->passwd));
498  }
499  }
500 
501  if (private->server == NULL || private->user == NULL) {
502  rc = -EINVAL;
503  }
504 
505  if (rc == pcmk_ok) {
506  rc = cib_tls_signon(cib, &(private->command), FALSE);
507  }
508 
509  if (rc == pcmk_ok) {
510  rc = cib_tls_signon(cib, &(private->callback), TRUE);
511  }
512 
513  if (rc == pcmk_ok) {
514  rc = cib__create_op(cib, CRM_OP_REGISTER, NULL, NULL, NULL, cib_none,
515  NULL, name, &hello);
516  }
517 
518  if (rc == pcmk_ok) {
519  rc = pcmk__remote_send_xml(&private->command, hello);
520  rc = pcmk_rc2legacy(rc);
521  free_xml(hello);
522  }
523 
524  if (rc == pcmk_ok) {
525  crm_info("Opened connection to %s:%d for %s",
526  private->server, private->port, name);
528  cib->type = cib_command;
529 
530  } else {
531  crm_info("Connection to %s:%d for %s failed: %s\n",
532  private->server, private->port, name, pcmk_strerror(rc));
533  }
534 
535  return rc;
536 }
537 
538 static int
539 cib_remote_signoff(cib_t *cib)
540 {
541  int rc = pcmk_ok;
542 
543  crm_debug("Disconnecting from the CIB manager");
544 #ifdef HAVE_GNUTLS_GNUTLS_H
545  cib_tls_close(cib);
546 #endif
547 
548  cib->cmds->end_transaction(cib, false, cib_none);
549  cib->state = cib_disconnected;
550  cib->type = cib_no_connection;
551 
552  return rc;
553 }
554 
555 static int
556 cib_remote_free(cib_t *cib)
557 {
558  int rc = pcmk_ok;
559 
560  crm_warn("Freeing CIB");
561  if (cib->state != cib_disconnected) {
562  rc = cib_remote_signoff(cib);
563  if (rc == pcmk_ok) {
564  cib_remote_opaque_t *private = cib->variant_opaque;
565 
566  free(private->server);
567  free(private->user);
568  free(private->passwd);
569  free(cib->cmds);
570  free(cib->user);
571  free(private);
572  free(cib);
573  }
574  }
575 
576  return rc;
577 }
578 
579 static int
580 cib_remote_inputfd(cib_t * cib)
581 {
582  cib_remote_opaque_t *private = cib->variant_opaque;
583 
584  return private->callback.tcp_socket;
585 }
586 
587 static int
588 cib_remote_register_notification(cib_t * cib, const char *callback, int enabled)
589 {
590  xmlNode *notify_msg = pcmk__xe_create(NULL, PCMK__XE_CIB_COMMAND);
591  cib_remote_opaque_t *private = cib->variant_opaque;
592 
594  crm_xml_add(notify_msg, PCMK__XA_CIB_NOTIFY_TYPE, callback);
595  crm_xml_add_int(notify_msg, PCMK__XA_CIB_NOTIFY_ACTIVATE, enabled);
596  pcmk__remote_send_xml(&private->callback, notify_msg);
597  free_xml(notify_msg);
598  return pcmk_ok;
599 }
600 
601 static int
602 cib_remote_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data))
603 {
604  return -EPROTONOSUPPORT;
605 }
606 
624 static int
625 cib_remote_client_id(const cib_t *cib, const char **async_id,
626  const char **sync_id)
627 {
628  cib_remote_opaque_t *private = cib->variant_opaque;
629 
630  if (async_id != NULL) {
631  // private->callback is the channel for async requests
632  *async_id = private->callback.token;
633  }
634  if (sync_id != NULL) {
635  // private->command is the channel for sync requests
636  *sync_id = private->command.token;
637  }
638  return pcmk_ok;
639 }
640 
641 cib_t *
642 cib_remote_new(const char *server, const char *user, const char *passwd, int port,
643  gboolean encrypted)
644 {
645  cib_remote_opaque_t *private = NULL;
646  cib_t *cib = cib_new_variant();
647 
648  if (cib == NULL) {
649  return NULL;
650  }
651 
652  private = calloc(1, sizeof(cib_remote_opaque_t));
653 
654  if (private == NULL) {
655  free(cib);
656  return NULL;
657  }
658 
659  cib->variant = cib_remote;
660  cib->variant_opaque = private;
661 
662  private->server = pcmk__str_copy(server);
663  private->user = pcmk__str_copy(user);
664  private->passwd = pcmk__str_copy(passwd);
665  private->port = port;
666  private->encrypted = encrypted;
667 
668  /* assign variant specific ops */
669  cib->delegate_fn = cib_remote_perform_op;
670  cib->cmds->signon = cib_remote_signon;
671  cib->cmds->signoff = cib_remote_signoff;
672  cib->cmds->free = cib_remote_free;
673  cib->cmds->inputfd = cib_remote_inputfd; // Deprecated method
674 
675  cib->cmds->register_notification = cib_remote_register_notification;
676  cib->cmds->set_connection_dnotify = cib_remote_set_connection_dnotify;
677 
678  cib->cmds->client_id = cib_remote_client_id;
679 
680  return cib;
681 }
682 
683 void
685 {
686  cib_remote_opaque_t *private;
687 
688  if (cib->variant != cib_remote) {
689  return;
690  }
691 
692  private = cib->variant_opaque;
693  private->out = out;
694 }
pcmk__cpg_host_t host
Definition: cpg.c:52
void cib__set_output(cib_t *cib, pcmk__output_t *out)
Definition: cib_remote.c:684
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition: xml.c:974
#define PCMK__VALUE_PASSWORD
A dumping ground.
const char * pcmk_strerror(int rc)
Definition: results.c:151
#define ETIME
Definition: portability.h:111
char data[0]
Definition: cpg.c:58
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
Definition: mainloop.c:958
int call_timeout
Definition: cib_types.h:388
int pcmk_rc2legacy(int rc)
Definition: results.c:548
void void void void void pcmk__text_prompt(const char *prompt, bool echo, char **dest)
Definition: output_text.c:470
const char * name
Definition: cib.c:26
void(* destroy)(gpointer userdata)
Destroy function for mainloop file descriptor client data.
Definition: mainloop.h:155
#define PCMK__XA_CIB_CLIENTID
int(* signoff)(cib_t *cib)
Definition: cib_types.h:166
#define PCMK__XE_CIB_COMMAND
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:360
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:313
int(* inputfd)(cib_t *cib)
Definition: cib_types.h:189
enum crm_ais_msg_types type
Definition: cpg.c:51
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:503
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:494
#define PCMK__XA_CIB_NOTIFY_TYPE
Wrappers for and extensions to glib mainloop.
#define CRM_OP_REGISTER
Definition: crm.h:129
int pcmk__read_available_remote_data(pcmk__remote_t *remote)
Definition: remote.c:718
void cib_native_notify(gpointer data, gpointer user_data)
Definition: cib_utils.c:824
int(* dispatch)(gpointer userdata)
Dispatch function for mainloop file descriptor with data ready.
Definition: mainloop.h:148
cib_t * cib_new_variant(void)
Definition: cib_client.c:656
#define PCMK_XA_OP
Definition: xml_names.h:347
int(* set_connection_dnotify)(cib_t *cib, void(*dnotify)(gpointer user_data))
Definition: cib_types.h:185
#define crm_warn(fmt, args...)
Definition: logging.h:394
Formatted output for pacemaker tools.
cib_api_operations_t * cmds
Definition: cib_types.h:399
#define crm_debug(fmt, args...)
Definition: logging.h:402
cib_conn_type
Definition: cib_types.h:50
int(* signon)(cib_t *cib, const char *name, enum cib_conn_type type)
Definition: cib_types.h:159
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:458
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:481
#define crm_trace(fmt, args...)
Definition: logging.h:404
#define PCMK__XA_HIDDEN
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:94
#define PCMK__XE_CIB_CALLDATA
int pcmk__connect_remote(const char *host, int port, int timeout_ms, int *timer_id, int *sock_fd, void *userdata, void(*callback)(void *userdata, int rc, int sock))
Definition: remote.c:1096
#define crm_log_xml_debug(xml, text)
Definition: logging.h:411
#define PCMK__VALUE_CIB
Wrappers for and extensions to libxml2.
struct cib_remote_opaque_s cib_remote_opaque_t
#define crm_log_xml_warn(xml, text)
Definition: logging.h:408
int pcmk__remote_send_xml(pcmk__remote_t *remote, const xmlNode *msg)
Definition: remote.c:517
void free_xml(xmlNode *child)
Definition: xml.c:958
int cib__create_op(cib_t *cib, const char *op, const char *host, const char *section, xmlNode *data, int call_options, const char *user_name, const char *client_name, xmlNode **op_msg)
Definition: cib_utils.c:661
#define pcmk__str_copy(str)
int(* register_notification)(cib_t *cib, const char *callback, int enabled)
Definition: cib_types.h:248
void * variant_opaque
Definition: cib_types.h:389
mainloop_io_t * source
Definition: ipc_internal.h:117
#define CRM_XS
Definition: logging.h:56
char * user
Definition: cib_types.h:403
#define pcmk_err_diff_resync
Definition: results.h:79
int(* end_transaction)(cib_t *cib, bool commit, int call_options)
End and optionally commit this client&#39;s CIB transaction.
Definition: cib_types.h:362
#define crm_err(fmt, args...)
Definition: logging.h:391
#define PCMK__XA_CIB_RC
int cib__extend_transaction(cib_t *cib, xmlNode *request)
Definition: cib_utils.c:744
#define PCMK__XA_CIB_OP
#define PCMK__XA_PASSWORD
This structure contains everything that makes up a single output formatter.
#define PCMK_XA_USER
Definition: xml_names.h:439
enum cib_variant variant
Definition: cib_types.h:385
#define pcmk_ok
Definition: results.h:65
void cib_native_callback(cib_t *cib, xmlNode *msg, int call_id, int rc)
Definition: cib_utils.c:772
int call_id
Definition: cib_types.h:387
#define crm_log_xml_trace(xml, text)
Definition: logging.h:412
#define PCMK__XA_T
int pcmk__read_remote_message(pcmk__remote_t *remote, int timeout_ms)
Definition: remote.c:824
cib_t * cib_remote_new(const char *server, const char *user, const char *passwd, int port, gboolean encrypted)
Definition: cib_remote.c:642
enum cib_conn_type type
Definition: cib_types.h:384
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition: xml.c:770
#define PCMK__XA_CIB_NOTIFY_ACTIVATE
enum cib_state state
Definition: cib_types.h:382
GList * notify_list
Definition: cib_types.h:392
int(* free)(cib_t *cib)
Definition: cib_types.h:168
int(* client_id)(const cib_t *cib, const char **async_id, const char **sync_id)
Get the given CIB connection&#39;s unique client identifier(s)
Definition: cib_types.h:299
#define PCMK__XA_CIB_CALLID
#define crm_info(fmt, args...)
Definition: logging.h:399
Process request when the client commits the active transaction.
Definition: cib_types.h:108
xmlNode * pcmk__remote_message_xml(pcmk__remote_t *remote)
Definition: remote.c:570
void * delegate_fn
Definition: cib_types.h:390
#define PCMK__VALUE_CIB_NOTIFY