This source file includes following definitions.
- remote_proxy_notify_destroy
- remote_proxy_ack_shutdown
- remote_proxy_nack_shutdown
- remote_proxy_relay_event
- remote_proxy_relay_response
- remote_proxy_end_session
- remote_proxy_free
- remote_proxy_dispatch
- remote_proxy_disconnected
- remote_proxy_new
- remote_proxy_cb
1
2
3
4
5
6
7
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/common/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)
30 {
31
32 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
33 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_DESTROY);
34 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, session_id);
35 lrmd_internal_proxy_send(lrmd, msg);
36 free_xml(msg);
37 }
38
39
40
41
42
43
44
45 void
46 remote_proxy_ack_shutdown(lrmd_t *lrmd)
47 {
48 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
49 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_SHUTDOWN_ACK);
50 lrmd_internal_proxy_send(lrmd, msg);
51 free_xml(msg);
52 }
53
54
55
56
57
58
59
60 void
61 remote_proxy_nack_shutdown(lrmd_t *lrmd)
62 {
63 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
64 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_SHUTDOWN_NACK);
65 lrmd_internal_proxy_send(lrmd, msg);
66 free_xml(msg);
67 }
68
69 void
70 remote_proxy_relay_event(remote_proxy_t *proxy, xmlNode *msg)
71 {
72
73 xmlNode *event = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
74 xmlNode *wrapper = NULL;
75
76 crm_xml_add(event, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_EVENT);
77 crm_xml_add(event, PCMK__XA_LRMD_IPC_SESSION, proxy->session_id);
78
79 wrapper = pcmk__xe_create(event, PCMK__XE_LRMD_IPC_MSG);
80 pcmk__xml_copy(wrapper, msg);
81
82 crm_log_xml_explicit(event, "EventForProxy");
83 lrmd_internal_proxy_send(proxy->lrm, event);
84 free_xml(event);
85 }
86
87 void
88 remote_proxy_relay_response(remote_proxy_t *proxy, xmlNode *msg, int msg_id)
89 {
90
91 xmlNode *response = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
92 xmlNode *wrapper = NULL;
93
94 crm_xml_add(response, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_RESPONSE);
95 crm_xml_add(response, PCMK__XA_LRMD_IPC_SESSION, proxy->session_id);
96 crm_xml_add_int(response, PCMK__XA_LRMD_IPC_MSG_ID, msg_id);
97
98 wrapper = pcmk__xe_create(response, PCMK__XE_LRMD_IPC_MSG);
99 pcmk__xml_copy(wrapper, msg);
100
101 lrmd_internal_proxy_send(proxy->lrm, response);
102 free_xml(response);
103 }
104
105 static void
106 remote_proxy_end_session(remote_proxy_t *proxy)
107 {
108 if (proxy == NULL) {
109 return;
110 }
111 crm_trace("ending session ID %s", proxy->session_id);
112
113 if (proxy->source) {
114 mainloop_del_ipc_client(proxy->source);
115 }
116 }
117
118 void
119 remote_proxy_free(gpointer data)
120 {
121 remote_proxy_t *proxy = data;
122
123 crm_trace("freed proxy session ID %s", proxy->session_id);
124 free(proxy->node_name);
125 free(proxy->session_id);
126 free(proxy);
127 }
128
129 int
130 remote_proxy_dispatch(const char *buffer, ssize_t length, gpointer userdata)
131 {
132
133 xmlNode *xml = NULL;
134 uint32_t flags = 0;
135 remote_proxy_t *proxy = userdata;
136
137 xml = pcmk__xml_parse(buffer);
138 if (xml == NULL) {
139 crm_warn("Received a NULL msg from IPC service.");
140 return 1;
141 }
142
143 flags = crm_ipc_buffer_flags(proxy->ipc);
144 if (flags & crm_ipc_proxied_relay_response) {
145 crm_trace("Passing response back to %.8s on %s: %.200s - request id: %d", proxy->session_id, proxy->node_name, buffer, proxy->last_request_id);
146 remote_proxy_relay_response(proxy, xml, proxy->last_request_id);
147 proxy->last_request_id = 0;
148
149 } else {
150 crm_trace("Passing event back to %.8s on %s: %.200s", proxy->session_id, proxy->node_name, buffer);
151 remote_proxy_relay_event(proxy, xml);
152 }
153 free_xml(xml);
154 return 1;
155 }
156
157
158 void
159 remote_proxy_disconnected(gpointer userdata)
160 {
161 remote_proxy_t *proxy = userdata;
162
163 crm_trace("destroying %p", proxy);
164
165 proxy->source = NULL;
166 proxy->ipc = NULL;
167
168 if(proxy->lrm) {
169 remote_proxy_notify_destroy(proxy->lrm, proxy->session_id);
170 proxy->lrm = NULL;
171 }
172
173 g_hash_table_remove(proxy_table, proxy->session_id);
174 }
175
176 remote_proxy_t *
177 remote_proxy_new(lrmd_t *lrmd, struct ipc_client_callbacks *proxy_callbacks,
178 const char *node_name, const char *session_id, const char *channel)
179 {
180 remote_proxy_t *proxy = NULL;
181
182 if(channel == NULL) {
183 crm_err("No channel specified to proxy");
184 remote_proxy_notify_destroy(lrmd, session_id);
185 return NULL;
186 }
187
188 proxy = pcmk__assert_alloc(1, sizeof(remote_proxy_t));
189
190 proxy->node_name = strdup(node_name);
191 proxy->session_id = strdup(session_id);
192 proxy->lrm = lrmd;
193
194 if (!strcmp(pcmk__message_name(crm_system_name), CRM_SYSTEM_CRMD)
195 && !strcmp(pcmk__message_name(channel), CRM_SYSTEM_CRMD)) {
196
197 proxy->is_local = TRUE;
198
199 } else {
200 proxy->source = mainloop_add_ipc_client(channel, G_PRIORITY_LOW, 0, proxy, proxy_callbacks);
201 proxy->ipc = mainloop_get_ipc_client(proxy->source);
202 if (proxy->source == NULL) {
203 remote_proxy_free(proxy);
204 remote_proxy_notify_destroy(lrmd, session_id);
205 return NULL;
206 }
207 }
208
209 crm_trace("new remote proxy client established to %s on %s, session id %s",
210 channel, node_name, session_id);
211 g_hash_table_insert(proxy_table, proxy->session_id, proxy);
212
213 return proxy;
214 }
215
216 void
217 remote_proxy_cb(lrmd_t *lrmd, const char *node_name, xmlNode *msg)
218 {
219 const char *op = crm_element_value(msg, PCMK__XA_LRMD_IPC_OP);
220 const char *session = crm_element_value(msg, PCMK__XA_LRMD_IPC_SESSION);
221 remote_proxy_t *proxy = g_hash_table_lookup(proxy_table, session);
222 int msg_id = 0;
223
224
225
226
227
228 CRM_CHECK(op != NULL, return);
229 CRM_CHECK(session != NULL, return);
230
231 crm_element_value_int(msg, PCMK__XA_LRMD_IPC_MSG_ID, &msg_id);
232
233
234 if (pcmk__str_eq(op, LRMD_IPC_OP_DESTROY, pcmk__str_casei)) {
235 remote_proxy_end_session(proxy);
236
237 } else if (pcmk__str_eq(op, LRMD_IPC_OP_REQUEST, pcmk__str_casei)) {
238 uint32_t flags = 0U;
239 int rc = pcmk_rc_ok;
240 const char *name = crm_element_value(msg, PCMK__XA_LRMD_IPC_CLIENT);
241
242 xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_LRMD_IPC_MSG,
243 NULL, NULL);
244 xmlNode *request = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
245
246 CRM_CHECK(request != NULL, return);
247
248 if (proxy == NULL) {
249
250 remote_proxy_notify_destroy(lrmd, session);
251 return;
252 }
253
254
255 CRM_CHECK(proxy->is_local == FALSE,
256 remote_proxy_end_session(proxy); return);
257
258 if (!crm_ipc_connected(proxy->ipc)) {
259 remote_proxy_end_session(proxy);
260 return;
261 }
262 proxy->last_request_id = 0;
263 crm_xml_add(request, PCMK_XE_ACL_ROLE, "pacemaker-remote");
264
265 rc = pcmk__xe_get_flags(msg, PCMK__XA_LRMD_IPC_MSG_FLAGS, &flags, 0U);
266 if (rc != pcmk_rc_ok) {
267 crm_warn("Couldn't parse controller flags from remote request: %s",
268 pcmk_rc_str(rc));
269 }
270
271 pcmk__assert(node_name != NULL);
272 pcmk__update_acl_user(request, PCMK__XA_LRMD_IPC_USER, node_name);
273
274 if (pcmk_is_set(flags, crm_ipc_proxied)) {
275 const char *type = crm_element_value(request, PCMK__XA_T);
276 int rc = 0;
277
278 if (pcmk__str_eq(type, PCMK__VALUE_ATTRD, pcmk__str_none)
279 && (crm_element_value(request, PCMK__XA_ATTR_HOST) == NULL)
280 && pcmk__str_any_of(crm_element_value(request, PCMK_XA_TASK),
281 PCMK__ATTRD_CMD_UPDATE,
282 PCMK__ATTRD_CMD_UPDATE_BOTH,
283 PCMK__ATTRD_CMD_UPDATE_DELAY, NULL)) {
284 pcmk__xe_add_node(request, proxy->node_name, 0);
285 }
286
287 rc = crm_ipc_send(proxy->ipc, request, flags, 5000, NULL);
288
289 if(rc < 0) {
290 xmlNode *op_reply = pcmk__xe_create(NULL, PCMK__XE_NACK);
291
292 crm_err("Could not relay %s request %d from %s to %s for %s: %s (%d)",
293 op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name, pcmk_strerror(rc), rc);
294
295
296 crm_xml_add(op_reply, PCMK_XA_FUNCTION, __func__);
297 crm_xml_add_int(op_reply, PCMK__XA_LINE, __LINE__);
298 crm_xml_add_int(op_reply, PCMK_XA_RC, rc);
299 remote_proxy_relay_response(proxy, op_reply, msg_id);
300 free_xml(op_reply);
301
302 } else {
303 crm_trace("Relayed %s request %d from %s to %s for %s",
304 op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name);
305 proxy->last_request_id = msg_id;
306 }
307
308 } else {
309 int rc = pcmk_ok;
310 xmlNode *op_reply = NULL;
311
312
313 crm_trace("Relaying %s request %d from %s to %s for %s",
314 op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name);
315
316 rc = crm_ipc_send(proxy->ipc, request, flags, 10000, &op_reply);
317 if(rc < 0) {
318 crm_err("Could not relay %s request %d from %s to %s for %s: %s (%d)",
319 op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name, pcmk_strerror(rc), rc);
320 } else {
321 crm_trace("Relayed %s request %d from %s to %s for %s",
322 op, msg_id, proxy->node_name, crm_ipc_name(proxy->ipc), name);
323 }
324
325 if(op_reply) {
326 remote_proxy_relay_response(proxy, op_reply, msg_id);
327 free_xml(op_reply);
328 }
329 }
330 } else {
331 crm_err("Unknown proxy operation: %s", op);
332 }
333 }