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

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