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

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