pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
cib_client.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-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 #include <unistd.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <pwd.h>
17 
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 
21 #include <glib.h>
22 
23 #include <crm/crm.h>
24 #include <crm/cib/internal.h>
25 #include <crm/common/xml.h>
26 
27 static GHashTable *cib_op_callback_table = NULL;
28 
29 static gint
30 ciblib_GCompareFunc(gconstpointer a, gconstpointer b)
31 {
32  int rc = 0;
33  const cib_notify_client_t *a_client = a;
34  const cib_notify_client_t *b_client = b;
35 
36  CRM_CHECK(a_client->event != NULL && b_client->event != NULL, return 0);
37  rc = strcmp(a_client->event, b_client->event);
38  if (rc == 0) {
39  if (a_client->callback == b_client->callback) {
40  return 0;
41  } else if (((long)a_client->callback) < ((long)b_client->callback)) {
42  crm_trace("callbacks for %s are not equal: %p < %p",
43  a_client->event, a_client->callback, b_client->callback);
44  return -1;
45  }
46  crm_trace("callbacks for %s are not equal: %p > %p",
47  a_client->event, a_client->callback, b_client->callback);
48  return 1;
49  }
50  return rc;
51 }
52 
53 static int
54 cib_client_add_notify_callback(cib_t * cib, const char *event,
55  void (*callback) (const char *event,
56  xmlNode * msg))
57 {
58  GList *list_item = NULL;
59  cib_notify_client_t *new_client = NULL;
60 
61  if ((cib->variant != cib_native) && (cib->variant != cib_remote)) {
62  return -EPROTONOSUPPORT;
63  }
64 
65  crm_trace("Adding callback for %s events (%d)",
66  event, g_list_length(cib->notify_list));
67 
68  new_client = pcmk__assert_alloc(1, sizeof(cib_notify_client_t));
69  new_client->event = event;
70  new_client->callback = callback;
71 
72  list_item = g_list_find_custom(cib->notify_list, new_client,
73  ciblib_GCompareFunc);
74 
75  if (list_item != NULL) {
76  crm_warn("Callback already present");
77  free(new_client);
78  return -EINVAL;
79 
80  } else {
81  cib->notify_list = g_list_append(cib->notify_list, new_client);
82 
83  cib->cmds->register_notification(cib, event, 1);
84 
85  crm_trace("Callback added (%d)", g_list_length(cib->notify_list));
86  }
87  return pcmk_ok;
88 }
89 
90 static int
91 get_notify_list_event_count(cib_t *cib, const char *event)
92 {
93  int count = 0;
94 
95  for (GList *iter = g_list_first(cib->notify_list); iter != NULL;
96  iter = iter->next) {
97  cib_notify_client_t *client = (cib_notify_client_t *) iter->data;
98 
99  if (strcmp(client->event, event) == 0) {
100  count++;
101  }
102  }
103  crm_trace("event(%s) count : %d", event, count);
104  return count;
105 }
106 
107 static int
108 cib_client_del_notify_callback(cib_t *cib, const char *event,
109  void (*callback) (const char *event,
110  xmlNode *msg))
111 {
112  GList *list_item = NULL;
113  cib_notify_client_t *new_client = NULL;
114 
115  if (cib->variant != cib_native && cib->variant != cib_remote) {
116  return -EPROTONOSUPPORT;
117  }
118 
119  if (get_notify_list_event_count(cib, event) == 0) {
120  crm_debug("The callback of the event does not exist(%s)", event);
121  return pcmk_ok;
122  }
123 
124  crm_debug("Removing callback for %s events", event);
125 
126  new_client = pcmk__assert_alloc(1, sizeof(cib_notify_client_t));
127  new_client->event = event;
128  new_client->callback = callback;
129 
130  list_item = g_list_find_custom(cib->notify_list, new_client, ciblib_GCompareFunc);
131 
132  if (list_item != NULL) {
133  cib_notify_client_t *list_client = list_item->data;
134 
135  cib->notify_list = g_list_remove(cib->notify_list, list_client);
136  free(list_client);
137 
138  crm_trace("Removed callback");
139 
140  } else {
141  crm_trace("Callback not present");
142  }
143 
144  if (get_notify_list_event_count(cib, event) == 0) {
145  /* When there is not the registration of the event, the processing turns off a notice. */
146  cib->cmds->register_notification(cib, event, 0);
147  }
148 
149  free(new_client);
150  return pcmk_ok;
151 }
152 
153 static gboolean
154 cib_async_timeout_handler(gpointer data)
155 {
156  struct timer_rec_s *timer = data;
157 
158  crm_debug("Async call %d timed out after %ds",
159  timer->call_id, timer->timeout);
160  cib_native_callback(timer->cib, NULL, timer->call_id, -ETIME);
161 
162  // We remove the handler in remove_cib_op_callback()
163  return G_SOURCE_CONTINUE;
164 }
165 
166 static gboolean
167 cib_client_register_callback_full(cib_t *cib, int call_id, int timeout,
168  gboolean only_success, void *user_data,
169  const char *callback_name,
170  void (*callback)(xmlNode *, int, int,
171  xmlNode *, void *),
172  void (*free_func)(void *))
173 {
174  cib_callback_client_t *blob = NULL;
175 
176  if (call_id < 0) {
177  if (only_success == FALSE) {
178  callback(NULL, call_id, call_id, NULL, user_data);
179  } else {
180  crm_warn("CIB call failed: %s", pcmk_strerror(call_id));
181  }
182  if (user_data && free_func) {
183  free_func(user_data);
184  }
185  return FALSE;
186  }
187 
188  blob = pcmk__assert_alloc(1, sizeof(cib_callback_client_t));
189  blob->id = callback_name;
190  blob->only_success = only_success;
191  blob->user_data = user_data;
192  blob->callback = callback;
193  blob->free_func = free_func;
194 
195  if (timeout > 0) {
196  struct timer_rec_s *async_timer =
197  pcmk__assert_alloc(1, sizeof(struct timer_rec_s));
198 
199  blob->timer = async_timer;
200 
201  async_timer->cib = cib;
202  async_timer->call_id = call_id;
203  async_timer->timeout = timeout * 1000;
204  async_timer->ref = pcmk__create_timer(async_timer->timeout,
205  cib_async_timeout_handler,
206  async_timer);
207  }
208 
209  crm_trace("Adding callback %s for call %d", callback_name, call_id);
210  pcmk__intkey_table_insert(cib_op_callback_table, call_id, blob);
211 
212  return TRUE;
213 }
214 
215 static gboolean
216 cib_client_register_callback(cib_t *cib, int call_id, int timeout,
217  gboolean only_success, void *user_data,
218  const char *callback_name,
219  void (*callback) (xmlNode *, int, int, xmlNode *,
220  void *))
221 {
222  return cib_client_register_callback_full(cib, call_id, timeout,
223  only_success, user_data,
224  callback_name, callback, NULL);
225 }
226 
227 static int
228 cib_client_noop(cib_t * cib, int call_options)
229 {
230  return cib_internal_op(cib, PCMK__CIB_REQUEST_NOOP, NULL, NULL, NULL, NULL,
231  call_options, cib->user);
232 }
233 
234 static int
235 cib_client_ping(cib_t * cib, xmlNode ** output_data, int call_options)
236 {
237  return cib_internal_op(cib, CRM_OP_PING, NULL, NULL, NULL, output_data,
238  call_options, cib->user);
239 }
240 
241 static int
242 cib_client_query(cib_t * cib, const char *section, xmlNode ** output_data, int call_options)
243 {
244  return cib->cmds->query_from(cib, NULL, section, output_data, call_options);
245 }
246 
247 static int
248 cib_client_query_from(cib_t * cib, const char *host, const char *section,
249  xmlNode ** output_data, int call_options)
250 {
251  return cib_internal_op(cib, PCMK__CIB_REQUEST_QUERY, host, section, NULL,
252  output_data, call_options, cib->user);
253 }
254 
255 static int
256 set_secondary(cib_t *cib, int call_options)
257 {
258  return cib_internal_op(cib, PCMK__CIB_REQUEST_SECONDARY, NULL, NULL, NULL,
259  NULL, call_options, cib->user);
260 }
261 
262 static int
263 set_primary(cib_t *cib, int call_options)
264 {
265  return cib_internal_op(cib, PCMK__CIB_REQUEST_PRIMARY, NULL, NULL, NULL,
266  NULL, call_options, cib->user);
267 }
268 
269 static int
270 cib_client_bump_epoch(cib_t * cib, int call_options)
271 {
272  return cib_internal_op(cib, PCMK__CIB_REQUEST_BUMP, NULL, NULL, NULL, NULL,
273  call_options, cib->user);
274 }
275 
276 static int
277 cib_client_upgrade(cib_t * cib, int call_options)
278 {
279  return cib_internal_op(cib, PCMK__CIB_REQUEST_UPGRADE, NULL, NULL, NULL,
280  NULL, call_options, cib->user);
281 }
282 
283 static int
284 cib_client_sync(cib_t * cib, const char *section, int call_options)
285 {
286  return cib->cmds->sync_from(cib, NULL, section, call_options);
287 }
288 
289 static int
290 cib_client_sync_from(cib_t * cib, const char *host, const char *section, int call_options)
291 {
293  NULL, NULL, call_options, cib->user);
294 }
295 
296 static int
297 cib_client_create(cib_t * cib, const char *section, xmlNode * data, int call_options)
298 {
299  return cib_internal_op(cib, PCMK__CIB_REQUEST_CREATE, NULL, section, data,
300  NULL, call_options, cib->user);
301 }
302 
303 static int
304 cib_client_modify(cib_t * cib, const char *section, xmlNode * data, int call_options)
305 {
306  return cib_internal_op(cib, PCMK__CIB_REQUEST_MODIFY, NULL, section, data,
307  NULL, call_options, cib->user);
308 }
309 
310 static int
311 cib_client_replace(cib_t * cib, const char *section, xmlNode * data, int call_options)
312 {
313  return cib_internal_op(cib, PCMK__CIB_REQUEST_REPLACE, NULL, section, data,
314  NULL, call_options, cib->user);
315 }
316 
317 static int
318 cib_client_delete(cib_t * cib, const char *section, xmlNode * data, int call_options)
319 {
320  return cib_internal_op(cib, PCMK__CIB_REQUEST_DELETE, NULL, section, data,
321  NULL, call_options, cib->user);
322 }
323 
324 static int
325 cib_client_erase(cib_t * cib, xmlNode ** output_data, int call_options)
326 {
327  return cib_internal_op(cib, PCMK__CIB_REQUEST_ERASE, NULL, NULL, NULL,
328  output_data, call_options, cib->user);
329 }
330 
331 static int
332 cib_client_init_transaction(cib_t *cib)
333 {
334  int rc = pcmk_rc_ok;
335 
336  if (cib == NULL) {
337  return -EINVAL;
338  }
339 
340  if (cib->transaction != NULL) {
341  // A client can have at most one transaction at a time
342  rc = pcmk_rc_already;
343  }
344 
345  if (rc == pcmk_rc_ok) {
347  }
348 
349  if (rc != pcmk_rc_ok) {
350  const char *client_id = NULL;
351 
352  cib->cmds->client_id(cib, NULL, &client_id);
353  crm_err("Failed to initialize CIB transaction for client %s: %s",
354  client_id, pcmk_rc_str(rc));
355  }
356  return pcmk_rc2legacy(rc);
357 }
358 
359 static int
360 cib_client_end_transaction(cib_t *cib, bool commit, int call_options)
361 {
362  const char *client_id = NULL;
363  int rc = pcmk_ok;
364 
365  if (cib == NULL) {
366  return -EINVAL;
367  }
368 
369  cib->cmds->client_id(cib, NULL, &client_id);
370  client_id = pcmk__s(client_id, "(unidentified)");
371 
372  if (commit) {
373  if (cib->transaction == NULL) {
375 
376  crm_err("Failed to commit transaction for CIB client %s: %s",
377  client_id, pcmk_rc_str(rc));
378  return pcmk_rc2legacy(rc);
379  }
381  cib->transaction, NULL, call_options, cib->user);
382 
383  } else {
384  // Discard always succeeds
385  if (cib->transaction != NULL) {
386  crm_trace("Discarded transaction for CIB client %s", client_id);
387  } else {
388  crm_trace("No transaction found for CIB client %s", client_id);
389  }
390  }
392  cib->transaction = NULL;
393  return rc;
394 }
395 
396 static int
397 cib_client_fetch_schemas(cib_t *cib, xmlNode **output_data, const char *after_ver,
398  int call_options)
399 {
400  xmlNode *data = pcmk__xe_create(NULL, PCMK__XA_SCHEMA);
401  int rc = pcmk_ok;
402 
403  crm_xml_add(data, PCMK_XA_VERSION, after_ver);
404 
406  output_data, call_options, NULL);
408  return rc;
409 }
410 
411 static void
412 cib_client_set_user(cib_t *cib, const char *user)
413 {
414  pcmk__str_update(&(cib->user), user);
415 }
416 
417 static void
418 cib_destroy_op_callback(gpointer data)
419 {
420  cib_callback_client_t *blob = data;
421 
422  if (blob->timer && blob->timer->ref > 0) {
423  g_source_remove(blob->timer->ref);
424  }
425  free(blob->timer);
426 
427  if (blob->user_data && blob->free_func) {
428  blob->free_func(blob->user_data);
429  }
430 
431  free(blob);
432 }
433 
434 static void
435 destroy_op_callback_table(void)
436 {
437  if (cib_op_callback_table != NULL) {
438  g_hash_table_destroy(cib_op_callback_table);
439  cib_op_callback_table = NULL;
440  }
441 }
442 
443 char *
444 get_shadow_file(const char *suffix)
445 {
446  char *cib_home = NULL;
447  char *fullname = NULL;
448  char *name = crm_strdup_printf("shadow.%s", suffix);
449  const char *dir = getenv("CIB_shadow_dir");
450 
451  if (dir == NULL) {
452  uid_t uid = geteuid();
453  struct passwd *pwent = getpwuid(uid);
454  const char *user = NULL;
455 
456  if (pwent) {
457  user = pwent->pw_name;
458  } else {
459  user = getenv("USER");
460  crm_perror(LOG_ERR,
461  "Assuming %s because cannot get user details for user ID %d",
462  (user? user : "unprivileged user"), uid);
463  }
464 
465  if (pcmk__strcase_any_of(user, "root", CRM_DAEMON_USER, NULL)) {
466  dir = CRM_CONFIG_DIR;
467 
468  } else {
469  const char *home = NULL;
470 
471  if ((home = getenv("HOME")) == NULL) {
472  if (pwent) {
473  home = pwent->pw_dir;
474  }
475  }
476 
477  dir = pcmk__get_tmpdir();
478  if (home && home[0] == '/') {
479  int rc = 0;
480 
481  cib_home = crm_strdup_printf("%s/.cib", home);
482 
483  rc = mkdir(cib_home, 0700);
484  if (rc < 0 && errno != EEXIST) {
485  crm_perror(LOG_ERR, "Couldn't create user-specific shadow directory: %s",
486  cib_home);
487  errno = 0;
488 
489  } else {
490  dir = cib_home;
491  }
492  }
493  }
494  }
495 
496  fullname = crm_strdup_printf("%s/%s", dir, name);
497  free(cib_home);
498  free(name);
499 
500  return fullname;
501 }
502 
503 cib_t *
504 cib_shadow_new(const char *shadow)
505 {
506  cib_t *new_cib = NULL;
507  char *shadow_file = NULL;
508 
509  CRM_CHECK(shadow != NULL, return NULL);
510 
511  shadow_file = get_shadow_file(shadow);
512  new_cib = cib_file_new(shadow_file);
513  free(shadow_file);
514 
515  return new_cib;
516 }
517 
530 cib_t *
532 {
533  const char *shadow = getenv("CIB_shadow");
534  cib_t *cib = NULL;
535 
536  unsetenv("CIB_shadow");
537  cib = cib_new();
538 
539  if (shadow != NULL) {
540  setenv("CIB_shadow", shadow, 1);
541  }
542  return cib;
543 }
544 
558 /* @TODO Ensure all APIs support multiple simultaneous CIB connection objects
559  * (at least cib_free_callbacks() currently does not).
560  */
561 cib_t *
562 cib_new(void)
563 {
564  const char *value = getenv("CIB_shadow");
565  const char *server = NULL;
566  const char *user = NULL;
567  const char *pass = NULL;
568  gboolean encrypted = TRUE;
569  int port;
570 
571  if (!pcmk__str_empty(value)) {
572  return cib_shadow_new(value);
573  }
574 
575  value = getenv("CIB_file");
576  if (!pcmk__str_empty(value)) {
577  return cib_file_new(value);
578  }
579 
580  value = getenv("CIB_port");
581  if (pcmk__str_empty(value)) {
582  return cib_native_new();
583  }
584 
585  /* We don't ensure port is valid (>= 0) because cib_new() currently can't
586  * return NULL in practice, and introducing a NULL return here could cause
587  * core dumps that would previously just cause signon() failures.
588  */
589  pcmk__scan_port(value, &port);
590 
591  if (!crm_is_true(getenv("CIB_encrypted"))) {
592  encrypted = FALSE;
593  }
594 
595  server = getenv("CIB_server");
596  user = getenv("CIB_user");
597  pass = getenv("CIB_passwd");
598 
599  if (pcmk__str_empty(user)) {
600  user = CRM_DAEMON_USER;
601  }
602 
603  if (pcmk__str_empty(server)) {
604  server = "localhost";
605  }
606 
607  crm_debug("Initializing %s remote CIB access to %s:%d as user %s",
608  (encrypted? "encrypted" : "plain-text"), server, port, user);
609  return cib_remote_new(server, user, pass, port, encrypted);
610 }
611 
621 cib_t *
623 {
624  cib_t *new_cib = NULL;
625 
626  new_cib = calloc(1, sizeof(cib_t));
627 
628  if (new_cib == NULL) {
629  return NULL;
630  }
631 
632  remove_cib_op_callback(0, TRUE); /* remove all */
633 
634  new_cib->call_id = 1;
635  new_cib->variant = cib_undefined;
636 
637  new_cib->type = cib_no_connection;
638  new_cib->state = cib_disconnected;
639  new_cib->variant_opaque = NULL;
640  new_cib->notify_list = NULL;
641 
642  /* the rest will get filled in by the variant constructor */
643  new_cib->cmds = calloc(1, sizeof(cib_api_operations_t));
644 
645  if (new_cib->cmds == NULL) {
646  free(new_cib);
647  return NULL;
648  }
649 
650  new_cib->cmds->add_notify_callback = cib_client_add_notify_callback;
651  new_cib->cmds->del_notify_callback = cib_client_del_notify_callback;
652  new_cib->cmds->register_callback = cib_client_register_callback;
653  new_cib->cmds->register_callback_full = cib_client_register_callback_full;
654 
655  new_cib->cmds->noop = cib_client_noop; // Deprecated method
656  new_cib->cmds->ping = cib_client_ping;
657  new_cib->cmds->query = cib_client_query;
658  new_cib->cmds->sync = cib_client_sync;
659 
660  new_cib->cmds->query_from = cib_client_query_from;
661  new_cib->cmds->sync_from = cib_client_sync_from;
662 
663  new_cib->cmds->set_primary = set_primary;
664  new_cib->cmds->set_secondary = set_secondary;
665 
666  new_cib->cmds->upgrade = cib_client_upgrade;
667  new_cib->cmds->bump_epoch = cib_client_bump_epoch;
668 
669  new_cib->cmds->create = cib_client_create;
670  new_cib->cmds->modify = cib_client_modify;
671  new_cib->cmds->replace = cib_client_replace;
672  new_cib->cmds->remove = cib_client_delete;
673  new_cib->cmds->erase = cib_client_erase;
674 
675  new_cib->cmds->init_transaction = cib_client_init_transaction;
676  new_cib->cmds->end_transaction = cib_client_end_transaction;
677 
678  new_cib->cmds->set_user = cib_client_set_user;
679 
680  new_cib->cmds->fetch_schemas = cib_client_fetch_schemas;
681 
682  return new_cib;
683 }
684 
685 void
687 {
688 
689  if (cib) {
690  GList *list = cib->notify_list;
691 
692  while (list != NULL) {
693  cib_notify_client_t *client = g_list_nth_data(list, 0);
694 
695  list = g_list_remove(list, client);
696  free(client);
697  }
698  cib->notify_list = NULL;
699  }
700 }
701 
707 void
709 {
710  cib_free_notify(cib);
711 
712  destroy_op_callback_table();
713 }
714 
720 void
722 {
723  cib_free_callbacks(cib);
724  if (cib) {
725  cib->cmds->free(cib);
726  }
727 }
728 
729 void
730 remove_cib_op_callback(int call_id, gboolean all_callbacks)
731 {
732  if (all_callbacks) {
733  destroy_op_callback_table();
734  cib_op_callback_table = pcmk__intkey_table(cib_destroy_op_callback);
735  } else {
736  pcmk__intkey_table_remove(cib_op_callback_table, call_id);
737  }
738 }
739 
740 int
742 {
743  if (cib_op_callback_table == NULL) {
744  return 0;
745  }
746  return g_hash_table_size(cib_op_callback_table);
747 }
748 
749 static void
750 cib_dump_pending_op(gpointer key, gpointer value, gpointer user_data)
751 {
752  int call = GPOINTER_TO_INT(key);
753  cib_callback_client_t *blob = value;
754 
755  crm_debug("Call %d (%s): pending", call, pcmk__s(blob->id, "without ID"));
756 }
757 
758 void
760 {
761  if (cib_op_callback_table == NULL) {
762  return;
763  }
764  return g_hash_table_foreach(cib_op_callback_table, cib_dump_pending_op, NULL);
765 }
766 
768 cib__lookup_id (int call_id)
769 {
770  return pcmk__intkey_table_lookup(cib_op_callback_table, call_id);
771 }
pcmk__cpg_host_t host
Definition: cpg.c:52
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:213
A dumping ground.
#define PCMK__XA_SCHEMA
const char * pcmk_strerror(int rc)
Definition: results.c:257
#define ETIME
Definition: portability.h:66
gboolean(* register_callback)(cib_t *cib, int call_id, int timeout, gboolean only_success, void *user_data, const char *callback_name, void(*callback)(xmlNode *, int, int, xmlNode *, void *))
Definition: cib_types.h:180
char data[0]
Definition: cpg.c:58
cib_t * cib_remote_new(const char *server, const char *user, const char *passwd, int port, gboolean encrypted)
Definition: cib_remote.c:623
int pcmk_rc2legacy(int rc)
Definition: results.c:654
#define PCMK__CIB_REQUEST_PRIMARY
Definition: internal.h:25
void cib_dump_pending_callbacks(void)
Definition: cib_client.c:759
#define PCMK__CIB_REQUEST_CREATE
Definition: internal.h:31
const char * name
Definition: cib.c:26
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1027
gboolean(* register_callback_full)(cib_t *cib, int call_id, int timeout, gboolean only_success, void *user_data, const char *callback_name, void(*callback)(xmlNode *, int, int, xmlNode *, void *), void(*free_func)(void *))
Definition: cib_types.h:185
void(* callback)(const char *event, xmlNode *msg)
Definition: internal.h:105
#define PCMK__CIB_REQUEST_QUERY
Definition: internal.h:30
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
Definition: internal.h:41
void cib_free_callbacks(cib_t *cib)
Free all callbacks for a CIB connection.
Definition: cib_client.c:708
int call_id
Definition: internal.h:119
gboolean only_success
Definition: internal.h:113
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:609
int(* fetch_schemas)(cib_t *cib, xmlNode **output_data, const char *after_ver, int call_options)
Definition: cib_types.h:306
cib_t * cib_new(void)
Create a new CIB connection object.
Definition: cib_client.c:562
cib_t * cib_shadow_new(const char *shadow)
Definition: cib_client.c:504
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition: xml_element.c:407
int(* set_secondary)(cib_t *cib, int call_options)
Set the local CIB manager as a secondary instance.
Definition: cib_types.h:210
#define PCMK__CIB_REQUEST_ERASE
Definition: internal.h:34
int(* sync)(cib_t *cib, const char *section, int call_options)
Definition: cib_types.h:157
void pcmk__xml_free(xmlNode *xml)
Definition: xml.c:789
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: xml_element.c:1015
int timeout
Definition: internal.h:120
#define crm_warn(fmt, args...)
Definition: logging.h:362
struct timer_rec_s * timer
Definition: internal.h:114
int(* query_from)(cib_t *cib, const char *host, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:154
int pcmk__scan_port(const char *text, int *port)
Definition: strings.c:150
cib_api_operations_t * cmds
Definition: cib_types.h:325
#define crm_debug(fmt, args...)
Definition: logging.h:370
int num_cib_op_callbacks(void)
Definition: cib_client.c:741
guint pcmk__create_timer(guint interval_ms, GSourceFunc fn, gpointer data)
Definition: utils.c:401
void(* callback)(xmlNode *, int, int, xmlNode *, void *)
Definition: internal.h:110
guint ref
Definition: internal.h:121
#define crm_trace(fmt, args...)
Definition: logging.h:372
int(* modify)(cib_t *cib, const char *section, xmlNode *data, int call_options)
Definition: cib_types.h:169
char * get_shadow_file(const char *suffix)
Definition: cib_client.c:444
int(* create)(cib_t *cib, const char *section, xmlNode *data, int call_options)
Definition: cib_types.h:167
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1278
Wrappers for and extensions to libxml2.
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:151
const char * event
Definition: internal.h:102
#define CRM_DAEMON_USER
Definition: config.h:27
xmlNode * transaction
Definition: cib_types.h:327
cib_t * cib_new_no_shadow(void)
Create a new CIB connection object, ignoring any active shadow CIB.
Definition: cib_client.c:531
cib_t * cib_native_new(void)
Definition: cib_native.c:451
int(* replace)(cib_t *cib, const char *section, xmlNode *data, int call_options)
Definition: cib_types.h:172
int(* add_notify_callback)(cib_t *cib, const char *event, void(*callback)(const char *event, xmlNode *msg))
Definition: cib_types.h:132
int(* sync_from)(cib_t *cib, const char *host, const char *section, int call_options)
Definition: cib_types.h:158
#define CRM_CONFIG_DIR
Definition: config.h:14
int(* register_notification)(cib_t *cib, const char *callback, int enabled)
Definition: cib_types.h:178
int(* ping)(cib_t *cib, xmlNode **output_data, int call_options)
Definition: cib_types.h:148
void * variant_opaque
Definition: cib_types.h:319
#define PCMK__CIB_REQUEST_UPGRADE
Definition: internal.h:37
cib_t * cib_file_new(const char *filename)
Definition: cib_file.c:639
cib_callback_client_t * cib__lookup_id(int call_id)
Definition: cib_client.c:768
#define PCMK__CIB_REQUEST_BUMP
Definition: internal.h:29
int(* set_primary)(cib_t *cib, int call_options)
Set the local CIB manager as the cluster&#39;s primary instance.
Definition: cib_types.h:200
int(* noop)(cib_t *cib, int call_options)
Definition: cib_types.h:146
char * user
Definition: cib_types.h:329
const char * pcmk__get_tmpdir(void)
Definition: io.c:543
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:292
int(* del_notify_callback)(cib_t *cib, const char *event, void(*callback)(const char *event, xmlNode *msg))
Definition: cib_types.h:137
#define PCMK__CIB_REQUEST_SCHEMAS
Definition: internal.h:42
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:299
void cib_free_notify(cib_t *cib)
Definition: cib_client.c:686
#define crm_err(fmt, args...)
Definition: logging.h:359
#define PCMK__CIB_REQUEST_REPLACE
Definition: internal.h:35
const char * id
Definition: internal.h:111
cib_t * cib
Definition: internal.h:122
#define PCMK__CIB_REQUEST_SYNC_TO_ALL
Definition: internal.h:26
#define PCMK__CIB_REQUEST_SECONDARY
Definition: internal.h:24
#define PCMK__CIB_REQUEST_NOOP
Definition: internal.h:39
enum cib_variant variant
Definition: cib_types.h:315
gboolean crm_is_true(const char *s)
Definition: strings.c:490
#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:647
void(* set_user)(cib_t *cib, const char *user)
Set the user as whom all CIB requests via methods will be executed.
Definition: cib_types.h:304
int call_id
Definition: cib_types.h:317
cib_t * cib_new_variant(void)
Definition: cib_client.c:622
int(* bump_epoch)(cib_t *cib, int call_options)
Definition: cib_types.h:161
#define PCMK__CIB_REQUEST_MODIFY
Definition: internal.h:32
int(* remove)(cib_t *cib, const char *section, xmlNode *data, int call_options)
Definition: cib_types.h:174
#define CRM_OP_PING
Definition: crm.h:112
int cib_internal_op(cib_t *cib, const char *op, const char *host, const char *section, xmlNode *data, xmlNode **output_data, int call_options, const char *user_name)
Definition: cib_utils.c:755
int(* init_transaction)(cib_t *cib)
Initiate an atomic CIB transaction for this client.
Definition: cib_types.h:266
enum cib_conn_type type
Definition: cib_types.h:314
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
Definition: cib_client.c:721
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:257
enum cib_state state
Definition: cib_types.h:312
#define PCMK__XE_CIB_TRANSACTION
GList * notify_list
Definition: cib_types.h:322
int(* free)(cib_t *cib)
Definition: cib_types.h:129
void(* free_func)(void *)
Definition: internal.h:115
unsigned int timeout
Definition: pcmk_fence.c:34
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:229
int(* upgrade)(cib_t *cib, int call_options)
Definition: cib_types.h:160
int(* erase)(cib_t *cib, xmlNode **output_data, int call_options)
Definition: cib_types.h:176
void remove_cib_op_callback(int call_id, gboolean all_callbacks)
Definition: cib_client.c:730
#define PCMK__CIB_REQUEST_DELETE
Definition: internal.h:33
#define PCMK_XA_VERSION
Definition: xml_names.h:444
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1