~ubuntu-branches/ubuntu/utopic/pacemaker/utopic-proposed

« back to all changes in this revision

Viewing changes to lrmd/ipc_proxy.c

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2013-07-16 16:40:24 UTC
  • mfrom: (1.1.11) (2.2.3 experimental)
  • Revision ID: package-import@ubuntu.com-20130716164024-lvwrf4xivk1wdr3c
Tags: 1.1.9+git20130321-1ubuntu1
* Resync from debian expiremental.
* debian/control:
  - Use lower version for Build-Depends on libcorosync-dev
    and libqb-dev.
  - Build-Depends on libcfg-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2012 David Vossel <dvossel@redhat.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
 
 
21
#include <crm_internal.h>
 
22
#include <lrmd_private.h>
 
23
 
 
24
#include <glib.h>
 
25
#include <unistd.h>
 
26
 
 
27
#include <crm/crm.h>
 
28
#include <crm/msg_xml.h>
 
29
#include <crm/services.h>
 
30
#include <crm/common/mainloop.h>
 
31
#include <crm/common/ipc.h>
 
32
#include <crm/common/ipcs.h>
 
33
#include <crm/cib/internal.h>
 
34
 
 
35
static qb_ipcs_service_t *cib_ro = NULL;
 
36
static qb_ipcs_service_t *cib_rw = NULL;
 
37
static qb_ipcs_service_t *cib_shm = NULL;
 
38
 
 
39
static qb_ipcs_service_t *attrd_ipcs = NULL;
 
40
static qb_ipcs_service_t *crmd_ipcs = NULL;
 
41
static qb_ipcs_service_t *stonith_ipcs = NULL;
 
42
 
 
43
/* ipc providers == crmd clients connecting from cluster nodes */
 
44
GHashTable *ipc_providers;
 
45
/* ipc clients == things like cibadmin, crm_resource, connecting locally */
 
46
GHashTable *ipc_clients;
 
47
 
 
48
static int32_t
 
49
ipc_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid, const char *ipc_channel)
 
50
{
 
51
    void *key = NULL;
 
52
    void *value = NULL;
 
53
    crm_client_t *client;
 
54
    crm_client_t *ipc_proxy = NULL;
 
55
    GHashTableIter iter;
 
56
    xmlNode *msg;
 
57
 
 
58
    crm_trace("Connection %p on channel %s", c, ipc_channel);
 
59
 
 
60
    if (g_hash_table_size(ipc_providers) == 0) {
 
61
        crm_err("No ipc providers available for uid %d gid %d", uid, gid);
 
62
        return -EREMOTEIO;
 
63
    }
 
64
 
 
65
    g_hash_table_iter_init(&iter, ipc_providers);
 
66
    if (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) {
 
67
        /* grab the first provider available, any provider in this
 
68
         * table will work. Usually there will only be one. These are
 
69
         * lrmd client connections originating for a cluster node's crmd. */
 
70
        ipc_proxy = value;
 
71
    } else {
 
72
        crm_err("No ipc providers available for uid %d gid %d", uid, gid);
 
73
        return -EREMOTEIO;
 
74
    }
 
75
 
 
76
    /* this new client is a local ipc client on a remote
 
77
     * guest wanting to access the ipc on any available cluster nodes */
 
78
    client = crm_client_new(c, uid, gid);
 
79
    if (client == NULL) {
 
80
        return -EREMOTEIO;
 
81
    }
 
82
 
 
83
    /* This ipc client is bound to a single ipc provider. If the
 
84
     * provider goes away, this client is disconnected */
 
85
    client->userdata = strdup(ipc_proxy->id);
 
86
 
 
87
    g_hash_table_insert(ipc_clients, client->id, client);
 
88
 
 
89
    msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 
90
    crm_xml_add(msg, F_LRMD_IPC_OP, "new");
 
91
    crm_xml_add(msg, F_LRMD_IPC_IPC_SERVER, ipc_channel);
 
92
    crm_xml_add(msg, F_LRMD_IPC_SESSION, client->id);
 
93
    lrmd_server_send_notify(ipc_proxy, msg);
 
94
    free_xml(msg);
 
95
    crm_debug("created new ipc proxy with session id %s", client->id);
 
96
    return 0;
 
97
}
 
98
 
 
99
static int32_t
 
100
crmd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 
101
{
 
102
    return ipc_proxy_accept(c, uid, gid, CRM_SYSTEM_CRMD);
 
103
}
 
104
 
 
105
static int32_t
 
106
attrd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 
107
{
 
108
    return ipc_proxy_accept(c, uid, gid, T_ATTRD);
 
109
}
 
110
 
 
111
static int32_t
 
112
stonith_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 
113
{
 
114
    return ipc_proxy_accept(c, uid, gid, "stonith-ng");
 
115
}
 
116
 
 
117
static int32_t
 
118
cib_proxy_accept_rw(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 
119
{
 
120
    return ipc_proxy_accept(c, uid, gid, cib_channel_rw);
 
121
}
 
122
 
 
123
static int32_t
 
124
cib_proxy_accept_ro(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 
125
{
 
126
    return ipc_proxy_accept(c, uid, gid, cib_channel_ro);
 
127
}
 
128
 
 
129
static void
 
130
ipc_proxy_created(qb_ipcs_connection_t * c)
 
131
{
 
132
    crm_trace("Connection %p", c);
 
133
}
 
134
 
 
135
void
 
136
ipc_proxy_forward_client(crm_client_t *ipc_proxy, xmlNode *xml)
 
137
{
 
138
    const char *session = crm_element_value(xml, F_LRMD_IPC_SESSION);
 
139
    const char *msg_type = crm_element_value(xml, F_LRMD_IPC_OP);
 
140
    xmlNode *msg = get_message_xml(xml, F_LRMD_IPC_MSG);
 
141
    crm_client_t *ipc_client = crm_client_get_by_id(session);
 
142
    int rc = 0;
 
143
 
 
144
    if (ipc_client == NULL) {
 
145
        xmlNode *msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 
146
        crm_xml_add(msg, F_LRMD_IPC_OP, "destroy");
 
147
        crm_xml_add(msg, F_LRMD_IPC_SESSION, session);
 
148
        lrmd_server_send_notify(ipc_proxy, msg);
 
149
        free_xml(msg);
 
150
        return;
 
151
    }
 
152
 
 
153
    /* This is an event or response from the ipc provider
 
154
     * going to the local ipc client.
 
155
     *
 
156
     * Looking at the chain of events.
 
157
     *
 
158
     * -----remote node----------------|---- cluster node ------
 
159
     * ipc_client <--1--> this code <--2--> crmd <----3----> ipc server
 
160
     *
 
161
     * This function is receiving a msg from connection 2
 
162
     * and forwarding it to connection 1.
 
163
     */
 
164
    if (safe_str_eq(msg_type, "event")) {
 
165
        rc = crm_ipcs_send(ipc_client, 0, msg, TRUE);
 
166
    } else if (safe_str_eq(msg_type, "response")) {
 
167
        int msg_id = 0;
 
168
        crm_element_value_int(xml, F_LRMD_IPC_MSG_ID, &msg_id);
 
169
        rc = crm_ipcs_send(ipc_client, msg_id, msg, FALSE);
 
170
    } else if (safe_str_eq(msg_type, "destroy")) {
 
171
        qb_ipcs_disconnect(ipc_client->ipcs);
 
172
    } else {
 
173
        crm_err("Unknown ipc proxy msg type %s" , msg_type);
 
174
    }
 
175
 
 
176
    if (rc < 0) {
 
177
        crm_warn("IPC Proxy send to ipc client %s failed, rc = %d", ipc_client->id, rc);
 
178
    }
 
179
}
 
180
 
 
181
static int32_t
 
182
ipc_proxy_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
 
183
{
 
184
    uint32_t id = 0;
 
185
    uint32_t flags = 0;
 
186
    crm_client_t *client = crm_client_get(c);
 
187
    crm_client_t *ipc_proxy = crm_client_get_by_id(client->userdata);
 
188
    xmlNode *request = NULL;
 
189
    xmlNode *msg = NULL;
 
190
 
 
191
    if (!ipc_proxy) {
 
192
        qb_ipcs_disconnect(client->ipcs);
 
193
        return 0;
 
194
    }
 
195
 
 
196
    /* This is a request from the local ipc client going
 
197
     * to the ipc provider.
 
198
     *
 
199
     * Looking at the chain of events.
 
200
     *
 
201
     * -----remote node----------------|---- cluster node ------
 
202
     * ipc_client <--1--> this code <--2--> crmd <----3----> ipc server
 
203
     *
 
204
     * This function is receiving a request from connection
 
205
     * 1 and forwarding it to connection 2.
 
206
     */
 
207
    request = crm_ipcs_recv(client, data, size, &id, &flags);
 
208
 
 
209
    if (!request) {
 
210
        return 0;
 
211
    }
 
212
 
 
213
    CRM_CHECK(client != NULL, crm_err("Invalid client");
 
214
              return FALSE);
 
215
    CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client);
 
216
              return FALSE);
 
217
 
 
218
    msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 
219
    crm_xml_add(msg, F_LRMD_IPC_OP, "request");
 
220
    crm_xml_add(msg, F_LRMD_IPC_SESSION, client->id);
 
221
    crm_xml_add(msg, F_LRMD_IPC_USER, client->user);
 
222
    crm_xml_add_int(msg, F_LRMD_IPC_MSG_ID, id);
 
223
    crm_xml_add_int(msg, F_LRMD_IPC_MSG_FLAGS, flags);
 
224
    add_message_xml(msg, F_LRMD_IPC_MSG, request);
 
225
    lrmd_server_send_notify(ipc_proxy, msg);
 
226
    free_xml(msg);
 
227
 
 
228
    return 0;
 
229
}
 
230
 
 
231
static int32_t
 
232
ipc_proxy_closed(qb_ipcs_connection_t * c)
 
233
{
 
234
    crm_client_t *client = crm_client_get(c);
 
235
    crm_client_t *ipc_proxy = crm_client_get_by_id(client->userdata);
 
236
 
 
237
    crm_trace("Connection %p", c);
 
238
 
 
239
    if (ipc_proxy) {
 
240
        xmlNode *msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 
241
        crm_xml_add(msg, F_LRMD_IPC_OP, "destroy");
 
242
        crm_xml_add(msg, F_LRMD_IPC_SESSION, client->id);
 
243
        lrmd_server_send_notify(ipc_proxy, msg);
 
244
        free_xml(msg);
 
245
    }
 
246
 
 
247
    g_hash_table_remove(ipc_clients, client->id);
 
248
 
 
249
    free(client->userdata);
 
250
    client->userdata = NULL;
 
251
    crm_client_destroy(client);
 
252
    return 0;
 
253
}
 
254
 
 
255
static void
 
256
ipc_proxy_destroy(qb_ipcs_connection_t * c)
 
257
{
 
258
    crm_trace("Connection %p", c);
 
259
}
 
260
 
 
261
static struct qb_ipcs_service_handlers crmd_proxy_callbacks = {
 
262
    .connection_accept = crmd_proxy_accept,
 
263
    .connection_created = ipc_proxy_created,
 
264
    .msg_process = ipc_proxy_dispatch,
 
265
    .connection_closed = ipc_proxy_closed,
 
266
    .connection_destroyed = ipc_proxy_destroy
 
267
};
 
268
 
 
269
static struct qb_ipcs_service_handlers attrd_proxy_callbacks = {
 
270
    .connection_accept = attrd_proxy_accept,
 
271
    .connection_created = ipc_proxy_created,
 
272
    .msg_process = ipc_proxy_dispatch,
 
273
    .connection_closed = ipc_proxy_closed,
 
274
    .connection_destroyed = ipc_proxy_destroy
 
275
};
 
276
 
 
277
static struct qb_ipcs_service_handlers stonith_proxy_callbacks = {
 
278
    .connection_accept = stonith_proxy_accept,
 
279
    .connection_created = ipc_proxy_created,
 
280
    .msg_process = ipc_proxy_dispatch,
 
281
    .connection_closed = ipc_proxy_closed,
 
282
    .connection_destroyed = ipc_proxy_destroy
 
283
};
 
284
 
 
285
static struct qb_ipcs_service_handlers cib_proxy_callbacks_ro = {
 
286
    .connection_accept = cib_proxy_accept_ro,
 
287
    .connection_created = ipc_proxy_created,
 
288
    .msg_process = ipc_proxy_dispatch,
 
289
    .connection_closed = ipc_proxy_closed,
 
290
    .connection_destroyed = ipc_proxy_destroy
 
291
};
 
292
 
 
293
static struct qb_ipcs_service_handlers cib_proxy_callbacks_rw = {
 
294
    .connection_accept = cib_proxy_accept_rw,
 
295
    .connection_created = ipc_proxy_created,
 
296
    .msg_process = ipc_proxy_dispatch,
 
297
    .connection_closed = ipc_proxy_closed,
 
298
    .connection_destroyed = ipc_proxy_destroy
 
299
};
 
300
 
 
301
void
 
302
ipc_proxy_add_provider(crm_client_t *ipc_proxy)
 
303
{
 
304
    if (ipc_providers == NULL) {
 
305
        return;
 
306
    }
 
307
    g_hash_table_insert(ipc_providers, ipc_proxy->id, ipc_proxy);
 
308
}
 
309
 
 
310
void
 
311
ipc_proxy_remove_provider(crm_client_t *ipc_proxy)
 
312
{
 
313
    GHashTableIter iter;
 
314
    crm_client_t *ipc_client = NULL;
 
315
    char *key = NULL;
 
316
 
 
317
    if (ipc_providers == NULL) {
 
318
        return;
 
319
    }
 
320
 
 
321
    g_hash_table_remove(ipc_providers, ipc_proxy->id);
 
322
 
 
323
    g_hash_table_iter_init(&iter, ipc_clients);
 
324
    while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & ipc_client)) {
 
325
        const char *proxy_id = ipc_client->userdata;
 
326
        if (safe_str_eq(proxy_id, ipc_proxy->id)) {
 
327
            crm_info("ipc proxy connection for client %s pid %d destroyed because cluster node disconnected.",
 
328
                ipc_client->id, ipc_client->pid);
 
329
            qb_ipcs_disconnect(ipc_client->ipcs);
 
330
        }
 
331
    }
 
332
}
 
333
 
 
334
void
 
335
ipc_proxy_init(void)
 
336
{
 
337
    ipc_clients = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, NULL);
 
338
    ipc_providers = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, NULL);
 
339
 
 
340
    cib_ipc_servers_init(&cib_ro,
 
341
                         &cib_rw,
 
342
                         &cib_shm,
 
343
                         &cib_proxy_callbacks_ro,
 
344
                         &cib_proxy_callbacks_rw);
 
345
 
 
346
    attrd_ipc_server_init(&attrd_ipcs, &attrd_proxy_callbacks);
 
347
    stonith_ipc_server_init(&stonith_ipcs, &stonith_proxy_callbacks);
 
348
    crmd_ipcs = crmd_ipc_server_init(&crmd_proxy_callbacks);
 
349
    if (crmd_ipcs == NULL) {
 
350
        crm_err("Failed to create crmd server: exiting and inhibiting respawn.");
 
351
        crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
 
352
        crm_exit(100);
 
353
    }
 
354
}
 
355
 
 
356
void
 
357
ipc_proxy_cleanup(void)
 
358
{
 
359
    if (ipc_providers) {
 
360
        g_hash_table_destroy(ipc_providers);
 
361
    }
 
362
    if (ipc_clients) {
 
363
        g_hash_table_destroy(ipc_clients);
 
364
    }
 
365
    cib_ipc_servers_destroy(cib_ro, cib_rw, cib_shm);
 
366
    qb_ipcs_destroy(attrd_ipcs);
 
367
    qb_ipcs_destroy(stonith_ipcs);
 
368
    qb_ipcs_destroy(crmd_ipcs);
 
369
    cib_ro = NULL;
 
370
    cib_rw = NULL;
 
371
    cib_shm = NULL;
 
372
    ipc_providers = NULL;
 
373
    ipc_clients = NULL;
 
374
}