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