root/lib/lrmd/proxy_common.c

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

DEFINITIONS

This source file includes following definitions.
  1. remote_proxy_notify_destroy
  2. remote_proxy_ack_shutdown
  3. remote_proxy_nack_shutdown
  4. remote_proxy_relay_event
  5. remote_proxy_relay_response
  6. remote_proxy_end_session
  7. remote_proxy_free
  8. remote_proxy_dispatch
  9. remote_proxy_disconnected
  10. remote_proxy_new
  11. remote_proxy_cb

   1 /*
   2  * Copyright 2015-2021 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 <glib.h>
  13 #include <unistd.h>
  14 
  15 #include <crm/crm.h>
  16 #include <crm/msg_xml.h>
  17 #include <crm/services.h>
  18 #include <crm/common/mainloop.h>
  19 
  20 #include <crm/pengine/status.h>
  21 #include <crm/cib.h>
  22 #include <crm/lrmd.h>
  23 #include <crm/lrmd_internal.h>
  24 
  25 int lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg);
  26 GHashTable *proxy_table = NULL;
  27 
  28 static void
  29 remote_proxy_notify_destroy(lrmd_t *lrmd, const char *session_id)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31     /* sending to the remote node that an ipc connection has been destroyed */
  32     xmlNode *msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
  33     crm_xml_add(msg, F_LRMD_IPC_OP, LRMD_IPC_OP_DESTROY);
  34     crm_xml_add(msg, F_LRMD_IPC_SESSION, session_id);
  35     lrmd_internal_proxy_send(lrmd, msg);
  36     free_xml(msg);
  37 }
  38 
  39 /*!
  40  * \brief Send an acknowledgment of a remote proxy shutdown request.
  41  *
  42  * \param[in] lrmd  Connection to proxy
  43  */
  44 void
  45 remote_proxy_ack_shutdown(lrmd_t *lrmd)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47     xmlNode *msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
  48     crm_xml_add(msg, F_LRMD_IPC_OP, LRMD_IPC_OP_SHUTDOWN_ACK);
  49     lrmd_internal_proxy_send(lrmd, msg);
  50     free_xml(msg);
  51 }
  52 
  53 /*!
  54  * \brief We're not going to shutdown as response to
  55  *        a remote proxy shutdown request.
  56  *
  57  * \param[in] lrmd  Connection to proxy
  58  */
  59 void
  60 remote_proxy_nack_shutdown(lrmd_t *lrmd)
     /* [previous][next][first][last][top][bottom][index][help] */
  61 {
  62     xmlNode *msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
  63     crm_xml_add(msg, F_LRMD_IPC_OP, LRMD_IPC_OP_SHUTDOWN_NACK);
  64     lrmd_internal_proxy_send(lrmd, msg);
  65     free_xml(msg);
  66 }
  67 
  68 void
  69 remote_proxy_relay_event(remote_proxy_t *proxy, xmlNode *msg)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71     /* sending to the remote node an event msg. */
  72     xmlNode *event = create_xml_node(NULL, T_LRMD_IPC_PROXY);
  73     crm_xml_add(event, F_LRMD_IPC_OP, LRMD_IPC_OP_EVENT);
  74     crm_xml_add(event, F_LRMD_IPC_SESSION, proxy->session_id);
  75     add_message_xml(event, F_LRMD_IPC_MSG, msg);
  76     crm_log_xml_explicit(event, "EventForProxy");
  77     lrmd_internal_proxy_send(proxy->lrm, event);
  78     free_xml(event);
  79 }
  80 
  81 void
  82 remote_proxy_relay_response(remote_proxy_t *proxy, xmlNode *msg, int msg_id)
     /* [previous][next][first][last][top][bottom][index][help] */
  83 {
  84     /* sending to the remote node a response msg. */
  85     xmlNode *response = create_xml_node(NULL, T_LRMD_IPC_PROXY);
  86     crm_xml_add(response, F_LRMD_IPC_OP, LRMD_IPC_OP_RESPONSE);
  87     crm_xml_add(response, F_LRMD_IPC_SESSION, proxy->session_id);
  88     crm_xml_add_int(response, F_LRMD_IPC_MSG_ID, msg_id);
  89     add_message_xml(response, F_LRMD_IPC_MSG, msg);
  90     lrmd_internal_proxy_send(proxy->lrm, response);
  91     free_xml(response);
  92 }
  93 
  94 static void
  95 remote_proxy_end_session(remote_proxy_t *proxy)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97     if (proxy == NULL) {
  98         return;
  99     }
 100     crm_trace("ending session ID %s", proxy->session_id);
 101 
 102     if (proxy->source) {
 103         mainloop_del_ipc_client(proxy->source);
 104     }
 105 }
 106 
 107 void
 108 remote_proxy_free(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110     remote_proxy_t *proxy = data;
 111 
 112     crm_trace("freed proxy session ID %s", proxy->session_id);
 113     free(proxy->node_name);
 114     free(proxy->session_id);
 115     free(proxy);
 116 }
 117 
 118 int
 119 remote_proxy_dispatch(const char *buffer, ssize_t length, gpointer userdata)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121     // Async responses from cib and friends to clients via pacemaker-remoted
 122     xmlNode *xml = NULL;
 123     uint32_t flags = 0;
 124     remote_proxy_t *proxy = userdata;
 125 
 126     xml = string2xml(buffer);
 127     if (xml == NULL) {
 128         crm_warn("Received a NULL msg from IPC service.");
 129         return 1;
 130     }
 131 
 132     flags = crm_ipc_buffer_flags(proxy->ipc);
 133     if (flags & crm_ipc_proxied_relay_response) {
 134         crm_trace("Passing response back to %.8s on %s: %.200s - request id: %d", proxy->session_id, proxy->node_name, buffer, proxy->last_request_id);
 135         remote_proxy_relay_response(proxy, xml, proxy->last_request_id);
 136         proxy->last_request_id = 0;
 137 
 138     } else {
 139         crm_trace("Passing event back to %.8s on %s: %.200s", proxy->session_id, proxy->node_name, buffer);
 140         remote_proxy_relay_event(proxy, xml);
 141     }
 142     free_xml(xml);
 143     return 1;
 144 }
 145 
 146 
 147 void
 148 remote_proxy_disconnected(gpointer userdata)
     /* [previous][next][first][last][top][bottom][index][help] */
 149 {
 150     remote_proxy_t *proxy = userdata;
 151 
 152     crm_trace("destroying %p", proxy);
 153 
 154     proxy->source = NULL;
 155     proxy->ipc = NULL;
 156 
 157     if(proxy->lrm) {
 158         remote_proxy_notify_destroy(proxy->lrm, proxy->session_id);
 159         proxy->lrm = NULL;
 160     }
 161 
 162     g_hash_table_remove(proxy_table, proxy->session_id);
 163 }
 164 
 165 remote_proxy_t *
 166 remote_proxy_new(lrmd_t *lrmd, struct ipc_client_callbacks *proxy_callbacks,
     /* [previous][next][first][last][top][bottom][index][help] */
 167                  const char *node_name, const char *session_id, const char *channel)
 168 {
 169     remote_proxy_t *proxy = NULL;
 170 
 171     if(channel == NULL) {
 172         crm_err("No channel specified to proxy");
 173         remote_proxy_notify_destroy(lrmd, session_id);
 174         return NULL;
 175     }
 176 
 177     proxy = calloc(1, sizeof(remote_proxy_t));
 178 
 179     proxy->node_name = strdup(node_name);
 180     proxy->session_id = strdup(session_id);
 181     proxy->lrm = lrmd;
 182 
 183     if (!strcmp(pcmk__message_name(crm_system_name), CRM_SYSTEM_CRMD)
 184         && !strcmp(pcmk__message_name(channel), CRM_SYSTEM_CRMD)) {
 185         // The controller doesn't need to connect to itself
 186         proxy->is_local = TRUE;
 187 
 188     } else {
 189         proxy->source = mainloop_add_ipc_client(channel, G_PRIORITY_LOW, 0, proxy, proxy_callbacks);
 190         proxy->ipc = mainloop_get_ipc_client(proxy->source);
 191         if (proxy->source == NULL) {
 192             remote_proxy_free(proxy);
 193             remote_proxy_notify_destroy(lrmd, session_id);
 194             return NULL;
 195         }
 196     }
 197 
 198     crm_trace("new remote proxy client established to %s on %s, session id %s",
 199               channel, node_name, session_id);
 200     g_hash_table_insert(proxy_table, proxy->session_id, proxy);
 201 
 202     return proxy;
 203 }
 204 
 205 void
 206 remote_proxy_cb(lrmd_t *lrmd, const char *node_name, xmlNode *msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208     const char *op = crm_element_value(msg, F_LRMD_IPC_OP);
 209     const char *session = crm_element_value(msg, F_LRMD_IPC_SESSION);
 210     remote_proxy_t *proxy = g_hash_table_lookup(proxy_table, session);
 211     int msg_id = 0;
 212 
 213     /* sessions are raw ipc connections to IPC,
 214      * all we do is proxy requests/responses exactly
 215      * like they are given to us at the ipc level. */
 216 
 217     CRM_CHECK(op != NULL, return);
 218     CRM_CHECK(session != NULL, return);
 219 
 220     crm_element_value_int(msg, F_LRMD_IPC_MSG_ID, &msg_id);
 221     /* This is msg from remote ipc client going to real ipc server */
 222 
 223     if (pcmk__str_eq(op, LRMD_IPC_OP_DESTROY, pcmk__str_casei)) {
 224         remote_proxy_end_session(proxy);
 225 
 226     } else if (pcmk__str_eq(op, LRMD_IPC_OP_REQUEST, pcmk__str_casei)) {
 227         int flags = 0;
 228         xmlNode *request = get_message_xml(msg, F_LRMD_IPC_MSG);
 229         const char *name = crm_element_value(msg, F_LRMD_IPC_CLIENT);
 230 
 231         CRM_CHECK(request != NULL, return);
 232 
 233         if (proxy == NULL) {
 234             /* proxy connection no longer exists */
 235             remote_proxy_notify_destroy(lrmd, session);
 236             return;
 237         }
 238 
 239         // Controller requests MUST be handled by the controller, not us
 240         CRM_CHECK(proxy->is_local == FALSE,
 241                   remote_proxy_end_session(proxy); return);
 242 
 243         if (crm_ipc_connected(proxy->ipc) == FALSE) {
 244             remote_proxy_end_session(proxy);
 245             return;
 246         }
 247         proxy->last_request_id = 0;
 248         crm_element_value_int(msg, F_LRMD_IPC_MSG_FLAGS, &flags);
 249         crm_xml_add(request, XML_ACL_TAG_ROLE, "pacemaker-remote");
 250 
 251         CRM_ASSERT(node_name);
 252         pcmk__update_acl_user(request, F_LRMD_IPC_USER, node_name);
 253 
 254         if (pcmk_is_set(flags, crm_ipc_proxied)) {
 255             const char *type = crm_element_value(request, F_TYPE);
 256             int rc = 0;
 257 
 258             if (pcmk__str_eq(type, T_ATTRD, pcmk__str_casei)
 259                 && crm_element_value(request,
 260                                      PCMK__XA_ATTR_NODE_NAME) == NULL
 261                 && pcmk__str_any_of(crm_element_value(request, PCMK__XA_TASK),
 262                                     PCMK__ATTRD_CMD_UPDATE,
 263                                     PCMK__ATTRD_CMD_UPDATE_BOTH,
 264                                     PCMK__ATTRD_CMD_UPDATE_DELAY, NULL)) {
 265                 pcmk__xe_add_node(request, proxy->node_name, 0);
 266             }
 267 
 268             rc = crm_ipc_send(proxy->ipc, request, flags, 5000, NULL);
 269 
 270             if(rc < 0) {
 271                 xmlNode *op_reply = create_xml_node(NULL, "nack");
 272 
 273                 crm_err("Could not relay %s request %d from %s to %s for %s: %s (%d)",
 274                          op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name, pcmk_strerror(rc), rc);
 275 
 276                 /* Send a n'ack so the caller doesn't block */
 277                 crm_xml_add(op_reply, "function", __func__);
 278                 crm_xml_add_int(op_reply, "line", __LINE__);
 279                 crm_xml_add_int(op_reply, "rc", rc);
 280                 remote_proxy_relay_response(proxy, op_reply, msg_id);
 281                 free_xml(op_reply);
 282 
 283             } else {
 284                 crm_trace("Relayed %s request %d from %s to %s for %s",
 285                           op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name);
 286                 proxy->last_request_id = msg_id;
 287             }
 288 
 289         } else {
 290             int rc = pcmk_ok;
 291             xmlNode *op_reply = NULL;
 292             // @COMPAT pacemaker_remoted <= 1.1.10
 293 
 294             crm_trace("Relaying %s request %d from %s to %s for %s",
 295                       op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name);
 296 
 297             rc = crm_ipc_send(proxy->ipc, request, flags, 10000, &op_reply);
 298             if(rc < 0) {
 299                 crm_err("Could not relay %s request %d from %s to %s for %s: %s (%d)",
 300                          op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name, pcmk_strerror(rc), rc);
 301             } else {
 302                 crm_trace("Relayed %s request %d from %s to %s for %s",
 303                           op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name);
 304             }
 305 
 306             if(op_reply) {
 307                 remote_proxy_relay_response(proxy, op_reply, msg_id);
 308                 free_xml(op_reply);
 309             }
 310         }
 311     } else {
 312         crm_err("Unknown proxy operation: %s", op);
 313     }
 314 }

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