root/daemons/pacemakerd/pcmkd_messages.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. handle_node_cache_request
  2. handle_ping_request
  3. handle_shutdown_request
  4. handle_unknown_request
  5. pcmkd_register_handlers
  6. pcmk_ipc_accept
  7. pcmk_ipc_closed
  8. pcmk_ipc_destroy
  9. pcmk_ipc_dispatch

   1 /*
   2  * Copyright 2010-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 General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 #include "pacemakerd.h"
  12 
  13 #include <crm/crm.h>
  14 #include <crm/common/xml.h>
  15 
  16 #include <errno.h>
  17 #include <stdbool.h>
  18 #include <stdint.h>
  19 #include <string.h>
  20 #include <time.h>
  21 #include <sys/types.h>
  22 
  23 static GHashTable *pcmkd_handlers = NULL;
  24 
  25 static xmlNode *
  26 handle_node_cache_request(pcmk__request_t *request)
     /* [previous][next][first][last][top][bottom][index][help] */
  27 {
  28     crm_trace("Ignoring request from client %s to purge node "
  29               "because peer cache is not used",
  30               pcmk__client_name(request->ipc_client));
  31 
  32     pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
  33                        PCMK__XE_ACK, NULL, CRM_EX_OK);
  34     return NULL;
  35 }
  36 
  37 static xmlNode *
  38 handle_ping_request(pcmk__request_t *request)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40     xmlNode *msg = request->xml;
  41 
  42     const char *value = NULL;
  43     xmlNode *ping = NULL;
  44     xmlNode *reply = NULL;
  45     const char *from = crm_element_value(msg, PCMK__XA_CRM_SYS_FROM);
  46 
  47     /* Pinged for status */
  48     crm_trace("Pinged from " PCMK__XA_CRM_SYS_FROM "='%s' "
  49               PCMK_XA_ORIGIN "='%s'",
  50               pcmk__s(from, ""),
  51               pcmk__s(crm_element_value(msg, PCMK_XA_ORIGIN), ""));
  52 
  53     pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
  54                        PCMK__XE_ACK, NULL, CRM_EX_INDETERMINATE);
  55 
  56     ping = pcmk__xe_create(NULL, PCMK__XE_PING_RESPONSE);
  57     value = crm_element_value(msg, PCMK__XA_CRM_SYS_TO);
  58     crm_xml_add(ping, PCMK__XA_CRM_SUBSYSTEM, value);
  59     crm_xml_add(ping, PCMK__XA_PACEMAKERD_STATE, pacemakerd_state);
  60     crm_xml_add_ll(ping, PCMK_XA_CRM_TIMESTAMP,
  61                    (long long) subdaemon_check_progress);
  62     crm_xml_add(ping, PCMK_XA_RESULT, "ok");
  63     reply = create_reply(msg, ping);
  64 
  65     free_xml(ping);
  66 
  67     if (reply == NULL) {
  68         pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
  69                             "Failed building ping reply for client %s",
  70                             pcmk__client_name(request->ipc_client));
  71     } else {
  72         pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
  73     }
  74 
  75     /* just proceed state on sbd pinging us */
  76     if (from && strstr(from, "sbd")) {
  77         if (pcmk__str_eq(pacemakerd_state, PCMK__VALUE_SHUTDOWN_COMPLETE,
  78                          pcmk__str_none)) {
  79             if (pcmk__get_sbd_sync_resource_startup()) {
  80                 crm_notice("Shutdown-complete-state passed to SBD.");
  81             }
  82 
  83             shutdown_complete_state_reported_to = request->ipc_client->pid;
  84 
  85         } else if (pcmk__str_eq(pacemakerd_state, PCMK__VALUE_WAIT_FOR_PING,
  86                                 pcmk__str_none)) {
  87             crm_notice("Received startup-trigger from SBD.");
  88             pacemakerd_state = PCMK__VALUE_STARTING_DAEMONS;
  89             mainloop_set_trigger(startup_trigger);
  90         }
  91     }
  92 
  93     return reply;
  94 }
  95 
  96 static xmlNode *
  97 handle_shutdown_request(pcmk__request_t *request)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99     xmlNode *msg = request->xml;
 100 
 101     xmlNode *shutdown = NULL;
 102     xmlNode *reply = NULL;
 103 
 104     /* Only allow privileged users (i.e. root or hacluster) to shut down
 105      * Pacemaker from the command line (or direct IPC), so that other users
 106      * are forced to go through the CIB and have ACLs applied.
 107      */
 108     bool allowed = pcmk_is_set(request->ipc_client->flags, pcmk__client_privileged);
 109 
 110     pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
 111                        PCMK__XE_ACK, NULL, CRM_EX_INDETERMINATE);
 112 
 113     shutdown = pcmk__xe_create(NULL, PCMK__XE_SHUTDOWN);
 114 
 115     if (allowed) {
 116         crm_notice("Shutting down in response to IPC request %s from %s",
 117                    crm_element_value(msg, PCMK_XA_REFERENCE),
 118                    crm_element_value(msg, PCMK_XA_ORIGIN));
 119         crm_xml_add_int(shutdown, PCMK__XA_OP_STATUS, CRM_EX_OK);
 120     } else {
 121         crm_warn("Ignoring shutdown request from unprivileged client %s",
 122                  pcmk__client_name(request->ipc_client));
 123         crm_xml_add_int(shutdown, PCMK__XA_OP_STATUS, CRM_EX_INSUFFICIENT_PRIV);
 124     }
 125 
 126     reply = create_reply(msg, shutdown);
 127     free_xml(shutdown);
 128 
 129     if (reply == NULL) {
 130         pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
 131                             "Failed building shutdown reply for client %s",
 132                             pcmk__client_name(request->ipc_client));
 133     } else {
 134         pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
 135     }
 136 
 137     if (allowed) {
 138         pcmk_shutdown(15);
 139     }
 140 
 141     return reply;
 142 }
 143 
 144 static xmlNode *
 145 handle_unknown_request(pcmk__request_t *request)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147     pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
 148                        PCMK__XE_ACK, NULL, CRM_EX_INVALID_PARAM);
 149 
 150     pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
 151                         "Unknown IPC request type '%s' (bug?)",
 152                         pcmk__client_name(request->ipc_client));
 153     return NULL;
 154 }
 155 
 156 static void
 157 pcmkd_register_handlers(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159     pcmk__server_command_t handlers[] = {
 160         { CRM_OP_RM_NODE_CACHE, handle_node_cache_request },
 161         { CRM_OP_PING, handle_ping_request },
 162         { CRM_OP_QUIT, handle_shutdown_request },
 163         { NULL, handle_unknown_request },
 164     };
 165 
 166     pcmkd_handlers = pcmk__register_handlers(handlers);
 167 }
 168 
 169 static int32_t
 170 pcmk_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172     crm_trace("Connection %p", c);
 173     if (pcmk__new_client(c, uid, gid) == NULL) {
 174         return -ENOMEM;
 175     }
 176     return 0;
 177 }
 178 
 179 /* Error code means? */
 180 static int32_t
 181 pcmk_ipc_closed(qb_ipcs_connection_t * c)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183     pcmk__client_t *client = pcmk__find_client(c);
 184 
 185     if (client == NULL) {
 186         return 0;
 187     }
 188     crm_trace("Connection %p", c);
 189     if (shutdown_complete_state_reported_to == client->pid) {
 190         shutdown_complete_state_reported_client_closed = TRUE;
 191         if (shutdown_trigger) {
 192             mainloop_set_trigger(shutdown_trigger);
 193         }
 194     }
 195     pcmk__free_client(client);
 196     return 0;
 197 }
 198 
 199 static void
 200 pcmk_ipc_destroy(qb_ipcs_connection_t * c)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202     crm_trace("Connection %p", c);
 203     pcmk_ipc_closed(c);
 204 }
 205 
 206 /* Exit code means? */
 207 static int32_t
 208 pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
     /* [previous][next][first][last][top][bottom][index][help] */
 209 {
 210     uint32_t id = 0;
 211     uint32_t flags = 0;
 212     xmlNode *msg = NULL;
 213     pcmk__client_t *c = pcmk__find_client(qbc);
 214 
 215     CRM_CHECK(c != NULL, return 0);
 216 
 217     if (pcmkd_handlers == NULL) {
 218         pcmkd_register_handlers();
 219     }
 220 
 221     msg = pcmk__client_data2xml(c, data, &id, &flags);
 222     if (msg == NULL) {
 223         pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL, CRM_EX_PROTOCOL);
 224         return 0;
 225 
 226     } else {
 227         char *log_msg = NULL;
 228         const char *reason = NULL;
 229         xmlNode *reply = NULL;
 230 
 231         pcmk__request_t request = {
 232             .ipc_client     = c,
 233             .ipc_id         = id,
 234             .ipc_flags      = flags,
 235             .peer           = NULL,
 236             .xml            = msg,
 237             .call_options   = 0,
 238             .result         = PCMK__UNKNOWN_RESULT,
 239         };
 240 
 241         request.op = crm_element_value_copy(request.xml, PCMK__XA_CRM_TASK);
 242         CRM_CHECK(request.op != NULL, return 0);
 243 
 244         reply = pcmk__process_request(&request, pcmkd_handlers);
 245 
 246         if (reply != NULL) {
 247             pcmk__ipc_send_xml(c, id, reply, crm_ipc_server_event);
 248             free_xml(reply);
 249         }
 250 
 251         reason = request.result.exit_reason;
 252 
 253         log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s",
 254                                     request.op, pcmk__request_origin_type(&request),
 255                                     pcmk__request_origin(&request),
 256                                     pcmk_exec_status_str(request.result.execution_status),
 257                                     (reason == NULL)? "" : " (",
 258                                     (reason == NULL)? "" : reason,
 259                                     (reason == NULL)? "" : ")");
 260 
 261         if (!pcmk__result_ok(&request.result)) {
 262             crm_warn("%s", log_msg);
 263         } else {
 264             crm_debug("%s", log_msg);
 265         }
 266 
 267         free(log_msg);
 268         pcmk__reset_request(&request);
 269     }
 270 
 271     free_xml(msg);
 272     return 0;
 273 }
 274 
 275 struct qb_ipcs_service_handlers pacemakerd_ipc_callbacks = {
 276     .connection_accept = pcmk_ipc_accept,
 277     .connection_created = NULL,
 278     .msg_process = pcmk_ipc_dispatch,
 279     .connection_closed = pcmk_ipc_closed,
 280     .connection_destroyed = pcmk_ipc_destroy
 281 };

/* [previous][next][first][last][top][bottom][index][help] */