This source file includes following definitions.
- is_sync_point_attr
- remove_sync_point_attribute
- remove_unsupported_sync_points
- handle_unknown_request
- handle_clear_failure_request
- handle_confirm_request
- handle_flush_request
- handle_query_request
- handle_remove_request
- handle_refresh_request
- handle_sync_request
- handle_sync_response_request
- handle_update_request
- attrd_register_handlers
- attrd_unregister_handlers
- attrd_handle_request
- attrd_broadcast_protocol
- attrd_send_message
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <glib.h>
13
14 #include <crm/common/messages_internal.h>
15 #include <crm/msg_xml.h>
16
17 #include "pacemaker-attrd.h"
18
19 int minimum_protocol_version = -1;
20
21 static GHashTable *attrd_handlers = NULL;
22
23 static bool
24 is_sync_point_attr(xmlAttrPtr attr, void *data)
25 {
26 return pcmk__str_eq((const char *) attr->name, PCMK__XA_ATTR_SYNC_POINT, pcmk__str_none);
27 }
28
29 static int
30 remove_sync_point_attribute(xmlNode *xml, void *data)
31 {
32 pcmk__xe_remove_matching_attrs(xml, is_sync_point_attr, NULL);
33 pcmk__xe_foreach_child(xml, XML_ATTR_OP, remove_sync_point_attribute, NULL);
34 return pcmk_rc_ok;
35 }
36
37
38
39
40
41
42 static void
43 remove_unsupported_sync_points(pcmk__request_t *request)
44 {
45 if (request->xml->children != NULL && !ATTRD_SUPPORTS_MULTI_MESSAGE(minimum_protocol_version) &&
46 attrd_request_has_sync_point(request->xml)) {
47 crm_warn("Ignoring sync point in request from %s because not all nodes support it",
48 pcmk__request_origin(request));
49 remove_sync_point_attribute(request->xml, NULL);
50 }
51 }
52
53 static xmlNode *
54 handle_unknown_request(pcmk__request_t *request)
55 {
56 crm_err("Unknown IPC request %s from %s %s",
57 request->op, pcmk__request_origin_type(request),
58 pcmk__request_origin(request));
59 pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
60 "Unknown request type '%s' (bug?)", request->op);
61 return NULL;
62 }
63
64 static xmlNode *
65 handle_clear_failure_request(pcmk__request_t *request)
66 {
67 if (request->peer != NULL) {
68
69
70
71 attrd_peer_clear_failure(request);
72 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
73 return NULL;
74 } else {
75 remove_unsupported_sync_points(request);
76
77 if (attrd_request_has_sync_point(request->xml)) {
78
79
80
81
82
83
84
85 attrd_add_client_to_waitlist(request);
86
87 } else {
88
89
90
91
92 attrd_send_ack(request->ipc_client, request->ipc_id,
93 request->ipc_flags);
94 }
95
96 return attrd_client_clear_failure(request);
97 }
98 }
99
100 static xmlNode *
101 handle_confirm_request(pcmk__request_t *request)
102 {
103 if (request->peer != NULL) {
104 int callid;
105
106 crm_debug("Received confirmation from %s", request->peer);
107
108 if (crm_element_value_int(request->xml, XML_LRM_ATTR_CALLID, &callid) == -1) {
109 pcmk__set_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
110 "Could not get callid from XML");
111 } else {
112 attrd_handle_confirmation(callid, request->peer);
113 }
114
115 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
116 return NULL;
117 } else {
118 return handle_unknown_request(request);
119 }
120 }
121
122 static xmlNode *
123 handle_flush_request(pcmk__request_t *request)
124 {
125 if (request->peer != NULL) {
126
127
128
129 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
130 return NULL;
131 } else {
132 return handle_unknown_request(request);
133 }
134 }
135
136 static xmlNode *
137 handle_query_request(pcmk__request_t *request)
138 {
139 if (request->peer != NULL) {
140 return handle_unknown_request(request);
141 } else {
142 return attrd_client_query(request);
143 }
144 }
145
146 static xmlNode *
147 handle_remove_request(pcmk__request_t *request)
148 {
149 if (request->peer != NULL) {
150 const char *host = crm_element_value(request->xml, PCMK__XA_ATTR_NODE_NAME);
151 attrd_peer_remove(host, true, request->peer);
152 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
153 return NULL;
154 } else {
155 return attrd_client_peer_remove(request);
156 }
157 }
158
159 static xmlNode *
160 handle_refresh_request(pcmk__request_t *request)
161 {
162 if (request->peer != NULL) {
163 return handle_unknown_request(request);
164 } else {
165 return attrd_client_refresh(request);
166 }
167 }
168
169 static xmlNode *
170 handle_sync_request(pcmk__request_t *request)
171 {
172 if (request->peer != NULL) {
173 crm_node_t *peer = crm_get_peer(0, request->peer);
174
175 attrd_peer_sync(peer, request->xml);
176 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
177 return NULL;
178 } else {
179 return handle_unknown_request(request);
180 }
181 }
182
183 static xmlNode *
184 handle_sync_response_request(pcmk__request_t *request)
185 {
186 if (request->ipc_client != NULL) {
187 return handle_unknown_request(request);
188 } else {
189 if (request->peer != NULL) {
190 crm_node_t *peer = crm_get_peer(0, request->peer);
191 bool peer_won = attrd_check_for_new_writer(peer, request->xml);
192
193 if (!pcmk__str_eq(peer->uname, attrd_cluster->uname, pcmk__str_casei)) {
194 attrd_peer_sync_response(peer, peer_won, request->xml);
195 }
196 }
197
198 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
199 return NULL;
200 }
201 }
202
203 static xmlNode *
204 handle_update_request(pcmk__request_t *request)
205 {
206 if (request->peer != NULL) {
207 const char *host = crm_element_value(request->xml, PCMK__XA_ATTR_NODE_NAME);
208 crm_node_t *peer = crm_get_peer(0, request->peer);
209
210 attrd_peer_update(peer, request->xml, host, false);
211 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
212 return NULL;
213
214 } else {
215 remove_unsupported_sync_points(request);
216
217 if (attrd_request_has_sync_point(request->xml)) {
218
219
220
221
222
223
224
225 attrd_add_client_to_waitlist(request);
226
227 } else {
228
229
230
231
232
233
234
235
236 attrd_send_ack(request->ipc_client, request->ipc_id,
237 request->flags|crm_ipc_client_response);
238 }
239
240 return attrd_client_update(request);
241 }
242 }
243
244 static void
245 attrd_register_handlers(void)
246 {
247 pcmk__server_command_t handlers[] = {
248 { PCMK__ATTRD_CMD_CLEAR_FAILURE, handle_clear_failure_request },
249 { PCMK__ATTRD_CMD_CONFIRM, handle_confirm_request },
250 { PCMK__ATTRD_CMD_FLUSH, handle_flush_request },
251 { PCMK__ATTRD_CMD_PEER_REMOVE, handle_remove_request },
252 { PCMK__ATTRD_CMD_QUERY, handle_query_request },
253 { PCMK__ATTRD_CMD_REFRESH, handle_refresh_request },
254 { PCMK__ATTRD_CMD_SYNC, handle_sync_request },
255 { PCMK__ATTRD_CMD_SYNC_RESPONSE, handle_sync_response_request },
256 { PCMK__ATTRD_CMD_UPDATE, handle_update_request },
257 { PCMK__ATTRD_CMD_UPDATE_DELAY, handle_update_request },
258 { PCMK__ATTRD_CMD_UPDATE_BOTH, handle_update_request },
259 { NULL, handle_unknown_request },
260 };
261
262 attrd_handlers = pcmk__register_handlers(handlers);
263 }
264
265 void
266 attrd_unregister_handlers(void)
267 {
268 if (attrd_handlers != NULL) {
269 g_hash_table_destroy(attrd_handlers);
270 attrd_handlers = NULL;
271 }
272 }
273
274 void
275 attrd_handle_request(pcmk__request_t *request)
276 {
277 xmlNode *reply = NULL;
278 char *log_msg = NULL;
279 const char *reason = NULL;
280
281 if (attrd_handlers == NULL) {
282 attrd_register_handlers();
283 }
284
285 reply = pcmk__process_request(request, attrd_handlers);
286
287 if (reply != NULL) {
288 crm_log_xml_trace(reply, "Reply");
289
290 if (request->ipc_client != NULL) {
291 pcmk__ipc_send_xml(request->ipc_client, request->ipc_id, reply,
292 request->ipc_flags);
293 } else {
294 crm_err("Not sending CPG reply to client");
295 }
296
297 free_xml(reply);
298 }
299
300 reason = request->result.exit_reason;
301 log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s",
302 request->op, pcmk__request_origin_type(request),
303 pcmk__request_origin(request),
304 pcmk_exec_status_str(request->result.execution_status),
305 (reason == NULL)? "" : " (",
306 pcmk__s(reason, ""),
307 (reason == NULL)? "" : ")");
308
309 if (!pcmk__result_ok(&request->result)) {
310 crm_warn("%s", log_msg);
311 } else {
312 crm_debug("%s", log_msg);
313 }
314
315 free(log_msg);
316 pcmk__reset_request(request);
317 }
318
319
320
321
322
323 void
324 attrd_broadcast_protocol(void)
325 {
326 xmlNode *attrd_op = create_xml_node(NULL, __func__);
327
328 crm_xml_add(attrd_op, F_TYPE, T_ATTRD);
329 crm_xml_add(attrd_op, F_ORIG, crm_system_name);
330 crm_xml_add(attrd_op, PCMK__XA_TASK, PCMK__ATTRD_CMD_UPDATE);
331 crm_xml_add(attrd_op, PCMK__XA_ATTR_NAME, CRM_ATTR_PROTOCOL);
332 crm_xml_add(attrd_op, PCMK__XA_ATTR_VALUE, ATTRD_PROTOCOL_VERSION);
333 crm_xml_add_int(attrd_op, PCMK__XA_ATTR_IS_PRIVATE, 1);
334 pcmk__xe_add_node(attrd_op, attrd_cluster->uname, attrd_cluster->nodeid);
335
336 crm_debug("Broadcasting attrd protocol version %s for node %s",
337 ATTRD_PROTOCOL_VERSION, attrd_cluster->uname);
338
339 attrd_send_message(NULL, attrd_op, false);
340
341 free_xml(attrd_op);
342 }
343
344 gboolean
345 attrd_send_message(crm_node_t *node, xmlNode *data, bool confirm)
346 {
347 const char *op = crm_element_value(data, PCMK__XA_TASK);
348
349 crm_xml_add(data, F_TYPE, T_ATTRD);
350 crm_xml_add(data, PCMK__XA_ATTR_VERSION, ATTRD_PROTOCOL_VERSION);
351
352
353
354
355
356 if (!pcmk__str_eq(op, PCMK__ATTRD_CMD_CONFIRM, pcmk__str_none)) {
357 pcmk__xe_set_bool_attr(data, PCMK__XA_CONFIRM, confirm);
358 }
359
360 attrd_xml_add_writer(data);
361 return send_cluster_message(node, crm_msg_attrd, data, TRUE);
362 }