pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
ipc_server.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
12#include <stdio.h>
13#include <errno.h>
14#include <bzlib.h>
15#include <sys/stat.h>
16#include <sys/types.h>
17
18#include <crm/crm.h>
19#include <crm/common/xml.h>
20#include <crm/common/ipc.h>
22#include "crmcommon_private.h"
23
24/* Evict clients whose event queue grows this large (by default) */
25#define PCMK_IPC_DEFAULT_QUEUE_MAX 500
26
27static GHashTable *client_connections = NULL;
28
35guint
37{
38 return client_connections? g_hash_table_size(client_connections) : 0;
39}
40
50void
51pcmk__foreach_ipc_client(GHFunc func, gpointer user_data)
52{
53 if ((func != NULL) && (client_connections != NULL)) {
54 g_hash_table_foreach(client_connections, func, user_data);
55 }
56}
57
59pcmk__find_client(const qb_ipcs_connection_t *c)
60{
61 if (client_connections) {
62 return g_hash_table_lookup(client_connections, c);
63 }
64
65 crm_trace("No client found for %p", c);
66 return NULL;
67}
68
71{
72 if ((client_connections != NULL) && (id != NULL)) {
73 gpointer key;
74 pcmk__client_t *client = NULL;
75 GHashTableIter iter;
76
77 g_hash_table_iter_init(&iter, client_connections);
78 while (g_hash_table_iter_next(&iter, &key, (gpointer *) & client)) {
79 if (strcmp(client->id, id) == 0) {
80 return client;
81 }
82 }
83 }
84 crm_trace("No client found with id='%s'", pcmk__s(id, ""));
85 return NULL;
86}
87
97const char *
99{
100 if (c == NULL) {
101 return "(unspecified)";
102
103 } else if (c->name != NULL) {
104 return c->name;
105
106 } else if (c->id != NULL) {
107 return c->id;
108
109 } else {
110 return "(unidentified)";
111 }
112}
113
114void
116{
117 if (client_connections != NULL) {
118 int active = g_hash_table_size(client_connections);
119
120 if (active > 0) {
121 crm_warn("Exiting with %d active IPC client%s",
122 active, pcmk__plural_s(active));
123 }
124 g_hash_table_destroy(client_connections);
125 client_connections = NULL;
126 }
127}
128
129void
130pcmk__drop_all_clients(qb_ipcs_service_t *service)
131{
132 qb_ipcs_connection_t *c = NULL;
133
134 if (service == NULL) {
135 return;
136 }
137
138 c = qb_ipcs_connection_first_get(service);
139
140 while (c != NULL) {
141 qb_ipcs_connection_t *last = c;
142
143 c = qb_ipcs_connection_next_get(service, last);
144
145 /* There really shouldn't be anyone connected at this point */
146 crm_notice("Disconnecting client %p, pid=%d...",
147 last, pcmk__client_pid(last));
148 qb_ipcs_disconnect(last);
149 qb_ipcs_connection_unref(last);
150 }
151}
152
163static pcmk__client_t *
164client_from_connection(qb_ipcs_connection_t *c, void *key, uid_t uid_client)
165{
167
168 if (c) {
169 client->user = pcmk__uid2username(uid_client);
170 if (client->user == NULL) {
171 client->user = pcmk__str_copy("#unprivileged");
172 crm_err("Unable to enforce ACLs for user ID %d, assuming unprivileged",
173 uid_client);
174 }
175 client->ipcs = c;
177 client->pid = pcmk__client_pid(c);
178 if (key == NULL) {
179 key = c;
180 }
181 }
182
183 client->id = crm_generate_uuid();
184 if (key == NULL) {
185 key = client->id;
186 }
187 if (client_connections == NULL) {
188 crm_trace("Creating IPC client table");
189 client_connections = g_hash_table_new(g_direct_hash, g_direct_equal);
190 }
191 g_hash_table_insert(client_connections, key, client);
192 return client;
193}
194
204{
205 return client_from_connection(NULL, key, 0);
206}
207
209pcmk__new_client(qb_ipcs_connection_t *c, uid_t uid_client, gid_t gid_client)
210{
211 gid_t uid_cluster = 0;
212 gid_t gid_cluster = 0;
213
214 pcmk__client_t *client = NULL;
215
216 CRM_CHECK(c != NULL, return NULL);
217
218 if (pcmk_daemon_user(&uid_cluster, &gid_cluster) < 0) {
219 static bool need_log = TRUE;
220
221 if (need_log) {
222 crm_warn("Could not find user and group IDs for user %s",
224 need_log = FALSE;
225 }
226 }
227
228 if (uid_client != 0) {
229 crm_trace("Giving group %u access to new IPC connection", gid_cluster);
230 /* Passing -1 to chown(2) means don't change */
231 qb_ipcs_connection_auth_set(c, -1, gid_cluster, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
232 }
233
234 /* TODO: Do our own auth checking, return NULL if unauthorized */
235 client = client_from_connection(c, NULL, uid_client);
236
237 if ((uid_client == 0) || (uid_client == uid_cluster)) {
238 /* Remember when a connection came from root or hacluster */
240 }
241
242 crm_debug("New IPC client %s for PID %u with uid %d and gid %d",
243 client->id, client->pid, uid_client, gid_client);
244 return client;
245}
246
247static struct iovec *
248pcmk__new_ipc_event(void)
249{
250 return (struct iovec *) pcmk__assert_alloc(2, sizeof(struct iovec));
251}
252
258void
259pcmk_free_ipc_event(struct iovec *event)
260{
261 if (event != NULL) {
262 free(event[0].iov_base);
263 free(event[1].iov_base);
264 free(event);
265 }
266}
267
268static void
269free_event(gpointer data)
270{
271 pcmk_free_ipc_event((struct iovec *) data);
272}
273
274static void
275add_event(pcmk__client_t *c, struct iovec *iov)
276{
277 if (c->event_queue == NULL) {
278 c->event_queue = g_queue_new();
279 }
280 g_queue_push_tail(c->event_queue, iov);
281}
282
283void
285{
286 if (c == NULL) {
287 return;
288 }
289
290 if (client_connections) {
291 if (c->ipcs) {
292 crm_trace("Destroying %p/%p (%d remaining)",
293 c, c->ipcs, g_hash_table_size(client_connections) - 1);
294 g_hash_table_remove(client_connections, c->ipcs);
295
296 } else {
297 crm_trace("Destroying remote connection %p (%d remaining)",
298 c, g_hash_table_size(client_connections) - 1);
299 g_hash_table_remove(client_connections, c->id);
300 }
301 }
302
303 if (c->event_timer) {
304 g_source_remove(c->event_timer);
305 }
306
307 if (c->event_queue) {
308 crm_debug("Destroying %d events", g_queue_get_length(c->event_queue));
309 g_queue_free_full(c->event_queue, free_event);
310 }
311
312 free(c->id);
313 free(c->name);
314 free(c->user);
315 if (c->remote) {
316 if (c->remote->auth_timeout) {
317 g_source_remove(c->remote->auth_timeout);
318 }
319#ifdef HAVE_GNUTLS_GNUTLS_H
320 if (c->remote->tls_session != NULL) {
321 /* @TODO Reduce duplication at callers. Put here everything
322 * necessary to tear down and free tls_session.
323 */
324 gnutls_free(c->remote->tls_session);
325 }
326#endif // HAVE_GNUTLS_GNUTLS_H
327 free(c->remote->buffer);
328 free(c->remote);
329 }
330 free(c);
331}
332
342bool
344{
346 long long qmax_ll;
347
348 if ((pcmk__scan_ll(qmax, &qmax_ll, 0LL) == pcmk_rc_ok)
349 && (qmax_ll > 0LL) && (qmax_ll <= UINT_MAX)) {
350 client->queue_max = (unsigned int) qmax_ll;
351 return true;
352 }
353 }
354 return false;
355}
356
357int
358pcmk__client_pid(qb_ipcs_connection_t *c)
359{
360 struct qb_ipcs_connection_stats stats;
361
362 stats.client_pid = 0;
363 qb_ipcs_connection_stats_get(c, &stats, 0);
364 return stats.client_pid;
365}
366
378xmlNode *
380 uint32_t *flags)
381{
382 xmlNode *xml = NULL;
383 char *uncompressed = NULL;
384 char *text = ((char *)data) + sizeof(pcmk__ipc_header_t);
385 pcmk__ipc_header_t *header = data;
386
387 if (!pcmk__valid_ipc_header(header)) {
388 return NULL;
389 }
390
391 if (id) {
392 *id = ((struct qb_ipc_response_header *)data)->id;
393 }
394 if (flags) {
395 *flags = header->flags;
396 }
397
398 if (pcmk_is_set(header->flags, crm_ipc_proxied)) {
399 /* Mark this client as being the endpoint of a proxy connection.
400 * Proxy connections responses are sent on the event channel, to avoid
401 * blocking the controller serving as proxy.
402 */
404 }
405
406 if (header->size_compressed) {
407 int rc = 0;
408 unsigned int size_u = 1 + header->size_uncompressed;
409 uncompressed = pcmk__assert_alloc(1, size_u);
410
411 crm_trace("Decompressing message data %u bytes into %u bytes",
412 header->size_compressed, size_u);
413
414 rc = BZ2_bzBuffToBuffDecompress(uncompressed, &size_u, text, header->size_compressed, 1, 0);
415 text = uncompressed;
416
417 rc = pcmk__bzlib2rc(rc);
418
419 if (rc != pcmk_rc_ok) {
420 crm_err("Decompression failed: %s " CRM_XS " rc=%d",
421 pcmk_rc_str(rc), rc);
422 free(uncompressed);
423 return NULL;
424 }
425 }
426
427 CRM_ASSERT(text[header->size_uncompressed - 1] == 0);
428
429 xml = pcmk__xml_parse(text);
430 crm_log_xml_trace(xml, "[IPC received]");
431
432 free(uncompressed);
433 return xml;
434}
435
436static int crm_ipcs_flush_events(pcmk__client_t *c);
437
438static gboolean
439crm_ipcs_flush_events_cb(gpointer data)
440{
441 pcmk__client_t *c = data;
442
443 c->event_timer = 0;
444 crm_ipcs_flush_events(c);
445 return FALSE;
446}
447
455static inline void
456delay_next_flush(pcmk__client_t *c, unsigned int queue_len)
457{
458 /* Delay a maximum of 1.5 seconds */
459 guint delay = (queue_len < 5)? (1000 + 100 * queue_len) : 1500;
460
461 c->event_timer = g_timeout_add(delay, crm_ipcs_flush_events_cb, c);
462}
463
472static int
473crm_ipcs_flush_events(pcmk__client_t *c)
474{
475 int rc = pcmk_rc_ok;
476 ssize_t qb_rc = 0;
477 unsigned int sent = 0;
478 unsigned int queue_len = 0;
479
480 if (c == NULL) {
481 return rc;
482
483 } else if (c->event_timer) {
484 /* There is already a timer, wait until it goes off */
485 crm_trace("Timer active for %p - %d", c->ipcs, c->event_timer);
486 return rc;
487 }
488
489 if (c->event_queue) {
490 queue_len = g_queue_get_length(c->event_queue);
491 }
492 while (sent < 100) {
493 pcmk__ipc_header_t *header = NULL;
494 struct iovec *event = NULL;
495
496 if (c->event_queue) {
497 // We don't pop unless send is successful
498 event = g_queue_peek_head(c->event_queue);
499 }
500 if (event == NULL) { // Queue is empty
501 break;
502 }
503
504 qb_rc = qb_ipcs_event_sendv(c->ipcs, event, 2);
505 if (qb_rc < 0) {
506 rc = (int) -qb_rc;
507 break;
508 }
509 event = g_queue_pop_head(c->event_queue);
510
511 sent++;
512 header = event[0].iov_base;
513 if (header->size_compressed) {
514 crm_trace("Event %d to %p[%d] (%lld compressed bytes) sent",
515 header->qb.id, c->ipcs, c->pid, (long long) qb_rc);
516 } else {
517 crm_trace("Event %d to %p[%d] (%lld bytes) sent: %.120s",
518 header->qb.id, c->ipcs, c->pid, (long long) qb_rc,
519 (char *) (event[1].iov_base));
520 }
521 pcmk_free_ipc_event(event);
522 }
523
524 queue_len -= sent;
525 if (sent > 0 || queue_len) {
526 crm_trace("Sent %d events (%d remaining) for %p[%d]: %s (%lld)",
527 sent, queue_len, c->ipcs, c->pid,
528 pcmk_rc_str(rc), (long long) qb_rc);
529 }
530
531 if (queue_len) {
532
533 /* Allow clients to briefly fall behind on processing incoming messages,
534 * but drop completely unresponsive clients so the connection doesn't
535 * consume resources indefinitely.
536 */
537 if (queue_len > QB_MAX(c->queue_max, PCMK_IPC_DEFAULT_QUEUE_MAX)) {
538 if ((c->queue_backlog <= 1) || (queue_len < c->queue_backlog)) {
539 /* Don't evict for a new or shrinking backlog */
540 crm_warn("Client with process ID %u has a backlog of %u messages "
541 CRM_XS " %p", c->pid, queue_len, c->ipcs);
542 } else {
543 crm_err("Evicting client with process ID %u due to backlog of %u messages "
544 CRM_XS " %p", c->pid, queue_len, c->ipcs);
545 c->queue_backlog = 0;
546 qb_ipcs_disconnect(c->ipcs);
547 return rc;
548 }
549 }
550
551 c->queue_backlog = queue_len;
552 delay_next_flush(c, queue_len);
553
554 } else {
555 /* Event queue is empty, there is no backlog */
556 c->queue_backlog = 0;
557 }
558
559 return rc;
560}
561
574int
575pcmk__ipc_prepare_iov(uint32_t request, const xmlNode *message,
576 uint32_t max_send_size, struct iovec **result,
577 ssize_t *bytes)
578{
579 struct iovec *iov;
580 unsigned int total = 0;
581 GString *buffer = NULL;
582 pcmk__ipc_header_t *header = NULL;
583 int rc = pcmk_rc_ok;
584
585 if ((message == NULL) || (result == NULL)) {
586 rc = EINVAL;
587 goto done;
588 }
589
590 header = calloc(1, sizeof(pcmk__ipc_header_t));
591 if (header == NULL) {
592 rc = ENOMEM;
593 goto done;
594 }
595
596 buffer = g_string_sized_new(1024);
597 pcmk__xml_string(message, 0, buffer, 0);
598
599 if (max_send_size == 0) {
600 max_send_size = crm_ipc_default_buffer_size();
601 }
602 CRM_LOG_ASSERT(max_send_size != 0);
603
604 *result = NULL;
605 iov = pcmk__new_ipc_event();
606 iov[0].iov_len = sizeof(pcmk__ipc_header_t);
607 iov[0].iov_base = header;
608
609 header->version = PCMK__IPC_VERSION;
610 header->size_uncompressed = 1 + buffer->len;
611 total = iov[0].iov_len + header->size_uncompressed;
612
613 if (total < max_send_size) {
614 iov[1].iov_base = pcmk__str_copy(buffer->str);
615 iov[1].iov_len = header->size_uncompressed;
616
617 } else {
618 static unsigned int biggest = 0;
619
620 char *compressed = NULL;
621 unsigned int new_size = 0;
622
623 if (pcmk__compress(buffer->str,
624 (unsigned int) header->size_uncompressed,
625 (unsigned int) max_send_size, &compressed,
626 &new_size) == pcmk_rc_ok) {
627
628 pcmk__set_ipc_flags(header->flags, "send data", crm_ipc_compressed);
629 header->size_compressed = new_size;
630
631 iov[1].iov_len = header->size_compressed;
632 iov[1].iov_base = compressed;
633
634 biggest = QB_MAX(header->size_compressed, biggest);
635
636 } else {
637 crm_log_xml_trace(message, "EMSGSIZE");
638 biggest = QB_MAX(header->size_uncompressed, biggest);
639
640 crm_err("Could not compress %u-byte message into less than IPC "
641 "limit of %u bytes; set PCMK_ipc_buffer to higher value "
642 "(%u bytes suggested)",
643 header->size_uncompressed, max_send_size, 4 * biggest);
644
645 free(compressed);
647 rc = EMSGSIZE;
648 goto done;
649 }
650 }
651
652 header->qb.size = iov[0].iov_len + iov[1].iov_len;
653 header->qb.id = (int32_t)request; /* Replying to a specific request */
654
655 *result = iov;
656 CRM_ASSERT(header->qb.size > 0);
657 if (bytes != NULL) {
658 *bytes = header->qb.size;
659 }
660
661done:
662 if (buffer != NULL) {
663 g_string_free(buffer, TRUE);
664 }
665 return rc;
666}
667
668int
669pcmk__ipc_send_iov(pcmk__client_t *c, struct iovec *iov, uint32_t flags)
670{
671 int rc = pcmk_rc_ok;
672 static uint32_t id = 1;
673 pcmk__ipc_header_t *header = iov[0].iov_base;
674
675 if (c->flags & pcmk__client_proxied) {
676 /* _ALL_ replies to proxied connections need to be sent as events */
678 /* The proxied flag lets us know this was originally meant to be a
679 * response, even though we're sending it over the event channel.
680 */
681 pcmk__set_ipc_flags(flags, "server event",
684 }
685 }
686
687 pcmk__set_ipc_flags(header->flags, "server event", flags);
689 header->qb.id = id++; /* We don't really use it, but doesn't hurt to set one */
690
692 crm_trace("Sending the original to %p[%d]", c->ipcs, c->pid);
693 add_event(c, iov);
694
695 } else {
696 struct iovec *iov_copy = pcmk__new_ipc_event();
697
698 crm_trace("Sending a copy to %p[%d]", c->ipcs, c->pid);
699 iov_copy[0].iov_len = iov[0].iov_len;
700 iov_copy[0].iov_base = malloc(iov[0].iov_len);
701 memcpy(iov_copy[0].iov_base, iov[0].iov_base, iov[0].iov_len);
702
703 iov_copy[1].iov_len = iov[1].iov_len;
704 iov_copy[1].iov_base = malloc(iov[1].iov_len);
705 memcpy(iov_copy[1].iov_base, iov[1].iov_base, iov[1].iov_len);
706
707 add_event(c, iov_copy);
708 }
709
710 } else {
711 ssize_t qb_rc;
712
713 CRM_LOG_ASSERT(header->qb.id != 0); /* Replying to a specific request */
714
715 qb_rc = qb_ipcs_response_sendv(c->ipcs, iov, 2);
716 if (qb_rc < header->qb.size) {
717 if (qb_rc < 0) {
718 rc = (int) -qb_rc;
719 }
720 crm_notice("Response %d to pid %d failed: %s "
721 CRM_XS " bytes=%u rc=%lld ipcs=%p",
722 header->qb.id, c->pid, pcmk_rc_str(rc),
723 header->qb.size, (long long) qb_rc, c->ipcs);
724
725 } else {
726 crm_trace("Response %d sent, %lld bytes to %p[%d]",
727 header->qb.id, (long long) qb_rc, c->ipcs, c->pid);
728 }
729
732 }
733 }
734
736 rc = crm_ipcs_flush_events(c);
737 } else {
738 crm_ipcs_flush_events(c);
739 }
740
741 if ((rc == EPIPE) || (rc == ENOTCONN)) {
742 crm_trace("Client %p disconnected", c->ipcs);
743 }
744 return rc;
745}
746
747int
748pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request, const xmlNode *message,
749 uint32_t flags)
750{
751 struct iovec *iov = NULL;
752 int rc = pcmk_rc_ok;
753
754 if (c == NULL) {
755 return EINVAL;
756 }
757 rc = pcmk__ipc_prepare_iov(request, message, crm_ipc_default_buffer_size(),
758 &iov, NULL);
759 if (rc == pcmk_rc_ok) {
761 rc = pcmk__ipc_send_iov(c, iov, flags);
762 } else {
764 crm_notice("IPC message to pid %d failed: %s " CRM_XS " rc=%d",
765 c->pid, pcmk_rc_str(rc), rc);
766 }
767 return rc;
768}
769
784xmlNode *
785pcmk__ipc_create_ack_as(const char *function, int line, uint32_t flags,
786 const char *tag, const char *ver, crm_exit_t status)
787{
788 xmlNode *ack = NULL;
789
791 ack = pcmk__xe_create(NULL, tag);
792 crm_xml_add(ack, PCMK_XA_FUNCTION, function);
793 crm_xml_add_int(ack, PCMK__XA_LINE, line);
794 crm_xml_add_int(ack, PCMK_XA_STATUS, (int) status);
796 }
797 return ack;
798}
799
815int
816pcmk__ipc_send_ack_as(const char *function, int line, pcmk__client_t *c,
817 uint32_t request, uint32_t flags, const char *tag,
818 const char *ver, crm_exit_t status)
819{
820 int rc = pcmk_rc_ok;
821 xmlNode *ack = pcmk__ipc_create_ack_as(function, line, flags, tag, ver, status);
822
823 if (ack != NULL) {
824 crm_trace("Ack'ing IPC message from client %s as <%s status=%d>",
825 pcmk__client_name(c), tag, status);
826 crm_log_xml_trace(ack, "sent-ack");
827 c->request_id = 0;
828 rc = pcmk__ipc_send_xml(c, request, ack, flags);
829 free_xml(ack);
830 }
831 return rc;
832}
833
846void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro,
847 qb_ipcs_service_t **ipcs_rw,
848 qb_ipcs_service_t **ipcs_shm,
849 struct qb_ipcs_service_handlers *ro_cb,
850 struct qb_ipcs_service_handlers *rw_cb)
851{
853 QB_IPC_NATIVE, ro_cb);
854
856 QB_IPC_NATIVE, rw_cb);
857
859 QB_IPC_SHM, rw_cb);
860
861 if (*ipcs_ro == NULL || *ipcs_rw == NULL || *ipcs_shm == NULL) {
862 crm_err("Failed to create the CIB manager: exiting and inhibiting respawn");
863 crm_warn("Verify pacemaker and pacemaker_remote are not both enabled");
865 }
866}
867
879void
880pcmk__stop_based_ipc(qb_ipcs_service_t *ipcs_ro,
881 qb_ipcs_service_t *ipcs_rw,
882 qb_ipcs_service_t *ipcs_shm)
883{
884 qb_ipcs_destroy(ipcs_ro);
885 qb_ipcs_destroy(ipcs_rw);
886 qb_ipcs_destroy(ipcs_shm);
887}
888
897qb_ipcs_service_t *
898pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb)
899{
900 return mainloop_add_ipc_server(CRM_SYSTEM_CRMD, QB_IPC_NATIVE, cb);
901}
902
912void
913pcmk__serve_attrd_ipc(qb_ipcs_service_t **ipcs,
914 struct qb_ipcs_service_handlers *cb)
915{
916 *ipcs = mainloop_add_ipc_server(PCMK__VALUE_ATTRD, QB_IPC_NATIVE, cb);
917
918 if (*ipcs == NULL) {
919 crm_err("Failed to create pacemaker-attrd server: exiting and inhibiting respawn");
920 crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
922 }
923}
924
934void
935pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs,
936 struct qb_ipcs_service_handlers *cb)
937{
938 *ipcs = mainloop_add_ipc_server_with_prio("stonith-ng", QB_IPC_NATIVE, cb,
939 QB_LOOP_HIGH);
940
941 if (*ipcs == NULL) {
942 crm_err("Failed to create fencer: exiting and inhibiting respawn.");
943 crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
945 }
946}
947
957void
958pcmk__serve_pacemakerd_ipc(qb_ipcs_service_t **ipcs,
959 struct qb_ipcs_service_handlers *cb)
960{
961 *ipcs = mainloop_add_ipc_server(CRM_SYSTEM_MCP, QB_IPC_NATIVE, cb);
962
963 if (*ipcs == NULL) {
964 crm_err("Couldn't start pacemakerd IPC server");
965 crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
966 /* sub-daemons are observed by pacemakerd. Thus we exit CRM_EX_FATAL
967 * if we want to prevent pacemakerd from restarting them.
968 * With pacemakerd we leave the exit-code shown to e.g. systemd
969 * to what it was prior to moving the code here from pacemakerd.c
970 */
972 }
973}
974
984qb_ipcs_service_t *
985pcmk__serve_schedulerd_ipc(struct qb_ipcs_service_handlers *cb)
986{
987 return mainloop_add_ipc_server(CRM_SYSTEM_PENGINE, QB_IPC_NATIVE, cb);
988}
989
1000bool
1002{
1004 "attrd",
1013 "pacemaker-remoted",
1014 "stonith-ng",
1015 NULL);
1016}
char * pcmk__uid2username(uid_t uid)
Definition acl.c:769
const char * name
Definition cib.c:26
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:297
uint64_t flags
Definition remote.c:3
int pcmk_daemon_user(uid_t *uid, gid_t *gid)
Get user and group IDs of pacemaker daemon user.
Definition utils.c:125
char * crm_generate_uuid(void)
Definition utils.c:431
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:98
#define CRM_DAEMON_USER
Definition config.h:30
char data[0]
Definition cpg.c:10
A dumping ground.
#define CRM_SYSTEM_CIB
Definition crm.h:89
#define CRM_SYSTEM_CRMD
Definition crm.h:90
#define CRM_SYSTEM_DC
Definition crm.h:87
#define CRM_SYSTEM_MCP
Definition crm.h:95
#define CRM_SYSTEM_STONITHD
Definition crm.h:94
#define CRM_SYSTEM_LRMD
Definition crm.h:91
#define CRM_SYSTEM_TENGINE
Definition crm.h:93
#define CRM_SYSTEM_PENGINE
Definition crm.h:92
#define PCMK__SERVER_BASED_RO
#define PCMK__SERVER_BASED_RW
#define PCMK__SERVER_BASED_SHM
struct pcmk__ipc_header_s pcmk__ipc_header_t
G_GNUC_INTERNAL bool pcmk__valid_ipc_header(const pcmk__ipc_header_t *header)
Definition ipc_common.c:81
#define PCMK__IPC_VERSION
IPC interface to Pacemaker daemons.
unsigned int crm_ipc_default_buffer_size(void)
Return pacemaker's default IPC buffer size.
Definition ipc_common.c:62
@ crm_ipc_compressed
Definition ipc.h:167
@ crm_ipc_proxied_relay_response
Definition ipc.h:175
@ crm_ipc_server_event
Definition ipc.h:173
@ crm_ipc_client_response
Definition ipc.h:170
@ crm_ipc_proxied
Definition ipc.h:169
@ crm_ipc_server_free
Definition ipc.h:174
#define pcmk__set_client_flags(client, flags_to_set)
#define pcmk__set_ipc_flags(ipc_flags, ipc_name, flags_to_set)
@ pcmk__client_proxied
Client IPC is proxied.
@ pcmk__client_ipc
Client uses plain IPC.
@ pcmk__client_privileged
Client is run by root or cluster user.
#define PCMK__XA_IPC_PROTO_VERSION
pcmk__client_t * pcmk__find_client_by_id(const char *id)
Definition ipc_server.c:70
const char * pcmk__client_name(const pcmk__client_t *c)
Definition ipc_server.c:98
pcmk__client_t * pcmk__new_client(qb_ipcs_connection_t *c, uid_t uid_client, gid_t gid_client)
Definition ipc_server.c:209
xmlNode * pcmk__client_data2xml(pcmk__client_t *c, void *data, uint32_t *id, uint32_t *flags)
Definition ipc_server.c:379
int pcmk__client_pid(qb_ipcs_connection_t *c)
Definition ipc_server.c:358
#define PCMK_IPC_DEFAULT_QUEUE_MAX
Definition ipc_server.c:25
pcmk__client_t * pcmk__find_client(const qb_ipcs_connection_t *c)
Definition ipc_server.c:59
int pcmk__ipc_send_ack_as(const char *function, int line, pcmk__client_t *c, uint32_t request, uint32_t flags, const char *tag, const char *ver, crm_exit_t status)
Definition ipc_server.c:816
pcmk__client_t * pcmk__new_unauth_client(void *key)
Allocate a new pcmk__client_t object and generate its ID.
Definition ipc_server.c:203
void pcmk_free_ipc_event(struct iovec *event)
Free an I/O vector created by pcmk__ipc_prepare_iov()
Definition ipc_server.c:259
guint pcmk__ipc_client_count(void)
Definition ipc_server.c:36
void pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition ipc_server.c:935
int pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request, const xmlNode *message, uint32_t flags)
Definition ipc_server.c:748
qb_ipcs_service_t * pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb)
Definition ipc_server.c:898
void pcmk__stop_based_ipc(qb_ipcs_service_t *ipcs_ro, qb_ipcs_service_t *ipcs_rw, qb_ipcs_service_t *ipcs_shm)
Definition ipc_server.c:880
void pcmk__free_client(pcmk__client_t *c)
Definition ipc_server.c:284
bool pcmk__set_client_queue_max(pcmk__client_t *client, const char *qmax)
Definition ipc_server.c:343
void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro, qb_ipcs_service_t **ipcs_rw, qb_ipcs_service_t **ipcs_shm, struct qb_ipcs_service_handlers *ro_cb, struct qb_ipcs_service_handlers *rw_cb)
Definition ipc_server.c:846
xmlNode * pcmk__ipc_create_ack_as(const char *function, int line, uint32_t flags, const char *tag, const char *ver, crm_exit_t status)
Definition ipc_server.c:785
void pcmk__client_cleanup(void)
Definition ipc_server.c:115
bool crm_is_daemon_name(const char *name)
Check whether string represents a client name used by cluster daemons.
void pcmk__drop_all_clients(qb_ipcs_service_t *service)
Definition ipc_server.c:130
void pcmk__foreach_ipc_client(GHFunc func, gpointer user_data)
Definition ipc_server.c:51
int pcmk__ipc_send_iov(pcmk__client_t *c, struct iovec *iov, uint32_t flags)
Definition ipc_server.c:669
void pcmk__serve_attrd_ipc(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition ipc_server.c:913
qb_ipcs_service_t * pcmk__serve_schedulerd_ipc(struct qb_ipcs_service_handlers *cb)
Definition ipc_server.c:985
void pcmk__serve_pacemakerd_ipc(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition ipc_server.c:958
int pcmk__ipc_prepare_iov(uint32_t request, const xmlNode *message, uint32_t max_send_size, struct iovec **result, ssize_t *bytes)
Definition ipc_server.c:575
#define crm_warn(fmt, args...)
Definition logging.h:392
#define CRM_XS
Definition logging.h:56
#define CRM_LOG_ASSERT(expr)
Definition logging.h:228
#define crm_notice(fmt, args...)
Definition logging.h:395
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
#define crm_debug(fmt, args...)
Definition logging.h:400
#define crm_err(fmt, args...)
Definition logging.h:389
#define crm_log_xml_trace(xml, text)
Definition logging.h:410
#define crm_trace(fmt, args...)
Definition logging.h:402
qb_ipcs_service_t * mainloop_add_ipc_server_with_prio(const char *name, enum qb_ipc_type type, struct qb_ipcs_service_handlers *callbacks, enum qb_loop_priority prio)
Start server-side API end-point, hooked into the internal event loop.
Definition mainloop.c:646
qb_ipcs_service_t * mainloop_add_ipc_server(const char *name, enum qb_ipc_type type, struct qb_ipcs_service_handlers *callbacks)
Definition mainloop.c:639
const char * pcmk__message_name(const char *name)
Get name to be used as identifier for cluster messages.
Definition messages.c:171
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:348
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:301
#define PCMK__VALUE_ATTRD
int delay
Definition pcmk_fence.c:34
pcmk__action_result_t result
Definition pcmk_fence.c:35
#define CRM_ASSERT(expr)
Definition results.h:42
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:501
@ CRM_EX_OSERR
External (OS/environmental) problem.
Definition results.h:276
@ CRM_EX_FATAL
Do not respawn.
Definition results.h:286
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition results.c:936
@ pcmk_rc_ok
Definition results.h:162
enum crm_exit_e crm_exit_t
int pcmk__bzlib2rc(int bz2)
Map a bz2 return code to the most similar Pacemaker return code.
Definition results.c:906
#define pcmk__plural_s(i)
int pcmk__compress(const char *data, unsigned int length, unsigned int max, char **result, unsigned int *result_len)
Definition strings.c:837
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition strings.c:97
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:1050
#define pcmk__str_copy(str)
qb_ipcs_connection_t * ipcs
unsigned int queue_backlog
unsigned int pid
struct pcmk__remote_s * remote
GQueue * event_queue
unsigned int queue_max
struct qb_ipc_response_header qb
Wrappers for and extensions to libxml2.
void free_xml(xmlNode *child)
Definition xml.c:867
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition xml.c:720
void pcmk__xml_string(const xmlNode *data, uint32_t options, GString *buffer, int depth)
Definition xml_io.c:488
xmlNode * pcmk__xml_parse(const char *input)
Definition xml_io.c:244
#define PCMK_XA_FUNCTION
Definition xml_names.h:287
#define PCMK_XA_STATUS
Definition xml_names.h:405
#define PCMK__XA_LINE