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_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_query_request(pcmk__request_t *request)
126 {
127 if (request->peer != NULL) {
128 return handle_unknown_request(request);
129 } else {
130 return attrd_client_query(request);
131 }
132 }
133
134 static xmlNode *
135 handle_remove_request(pcmk__request_t *request)
136 {
137 if (request->peer != NULL) {
138 const char *host = crm_element_value(request->xml, PCMK__XA_ATTR_HOST);
139 bool reap = false;
140
141 if (pcmk__xe_get_bool_attr(request->xml, PCMK__XA_REAP,
142 &reap) != pcmk_rc_ok) {
143 reap = true;
144 }
145 attrd_peer_remove(host, reap, request->peer);
146 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
147 return NULL;
148 } else {
149 return attrd_client_peer_remove(request);
150 }
151 }
152
153 static xmlNode *
154 handle_refresh_request(pcmk__request_t *request)
155 {
156 if (request->peer != NULL) {
157 return handle_unknown_request(request);
158 } else {
159 return attrd_client_refresh(request);
160 }
161 }
162
163 static xmlNode *
164 handle_sync_response_request(pcmk__request_t *request)
165 {
166 if (request->ipc_client != NULL) {
167 return handle_unknown_request(request);
168 } else {
169 if (request->peer != NULL) {
170 pcmk__node_status_t *peer =
171 pcmk__get_node(0, request->peer, NULL,
172 pcmk__node_search_cluster_member);
173 bool peer_won = attrd_check_for_new_writer(peer, request->xml);
174
175 if (!pcmk__str_eq(peer->name, attrd_cluster->priv->node_name,
176 pcmk__str_casei)) {
177 attrd_peer_sync_response(peer, peer_won, request->xml);
178 }
179 }
180
181 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
182 return NULL;
183 }
184 }
185
186 static xmlNode *
187 handle_update_request(pcmk__request_t *request)
188 {
189 if (request->peer != NULL) {
190 const char *host = crm_element_value(request->xml, PCMK__XA_ATTR_HOST);
191 pcmk__node_status_t *peer =
192 pcmk__get_node(0, request->peer, NULL,
193 pcmk__node_search_cluster_member);
194
195 attrd_peer_update(peer, request->xml, host, false);
196 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
197 return NULL;
198
199 } else {
200 remove_unsupported_sync_points(request);
201
202 if (attrd_request_has_sync_point(request->xml)) {
203
204
205
206
207
208
209
210 attrd_add_client_to_waitlist(request);
211
212 } else {
213
214
215
216
217
218
219
220
221 attrd_send_ack(request->ipc_client, request->ipc_id,
222 request->flags|crm_ipc_client_response);
223 }
224
225 return attrd_client_update(request);
226 }
227 }
228
229 static void
230 attrd_register_handlers(void)
231 {
232 pcmk__server_command_t handlers[] = {
233 { PCMK__ATTRD_CMD_CLEAR_FAILURE, handle_clear_failure_request },
234 { PCMK__ATTRD_CMD_CONFIRM, handle_confirm_request },
235 { PCMK__ATTRD_CMD_PEER_REMOVE, handle_remove_request },
236 { PCMK__ATTRD_CMD_QUERY, handle_query_request },
237 { PCMK__ATTRD_CMD_REFRESH, handle_refresh_request },
238 { PCMK__ATTRD_CMD_SYNC_RESPONSE, handle_sync_response_request },
239 { PCMK__ATTRD_CMD_UPDATE, handle_update_request },
240 { PCMK__ATTRD_CMD_UPDATE_DELAY, handle_update_request },
241 { PCMK__ATTRD_CMD_UPDATE_BOTH, handle_update_request },
242 { NULL, handle_unknown_request },
243 };
244
245 attrd_handlers = pcmk__register_handlers(handlers);
246 }
247
248 void
249 attrd_unregister_handlers(void)
250 {
251 if (attrd_handlers != NULL) {
252 g_hash_table_destroy(attrd_handlers);
253 attrd_handlers = NULL;
254 }
255 }
256
257 void
258 attrd_handle_request(pcmk__request_t *request)
259 {
260 xmlNode *reply = NULL;
261 char *log_msg = NULL;
262 const char *reason = NULL;
263
264 if (attrd_handlers == NULL) {
265 attrd_register_handlers();
266 }
267
268 reply = pcmk__process_request(request, attrd_handlers);
269
270 if (reply != NULL) {
271 crm_log_xml_trace(reply, "Reply");
272
273 if (request->ipc_client != NULL) {
274 pcmk__ipc_send_xml(request->ipc_client, request->ipc_id, reply,
275 request->ipc_flags);
276 } else {
277 crm_err("Not sending CPG reply to client");
278 }
279
280 pcmk__xml_free(reply);
281 }
282
283 reason = request->result.exit_reason;
284 log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s",
285 request->op, pcmk__request_origin_type(request),
286 pcmk__request_origin(request),
287 pcmk_exec_status_str(request->result.execution_status),
288 (reason == NULL)? "" : " (",
289 pcmk__s(reason, ""),
290 (reason == NULL)? "" : ")");
291
292 if (!pcmk__result_ok(&request->result)) {
293 crm_warn("%s", log_msg);
294 } else {
295 crm_debug("%s", log_msg);
296 }
297
298 free(log_msg);
299 pcmk__reset_request(request);
300 }
301
302
303
304
305
306 void
307 attrd_broadcast_protocol(void)
308 {
309 xmlNode *attrd_op = pcmk__xe_create(NULL, __func__);
310
311 crm_xml_add(attrd_op, PCMK__XA_T, PCMK__VALUE_ATTRD);
312 crm_xml_add(attrd_op, PCMK__XA_SRC, crm_system_name);
313 crm_xml_add(attrd_op, PCMK_XA_TASK, PCMK__ATTRD_CMD_UPDATE);
314 crm_xml_add(attrd_op, PCMK__XA_ATTR_NAME, CRM_ATTR_PROTOCOL);
315 crm_xml_add(attrd_op, PCMK__XA_ATTR_VALUE, ATTRD_PROTOCOL_VERSION);
316 crm_xml_add_int(attrd_op, PCMK__XA_ATTR_IS_PRIVATE, 1);
317 pcmk__xe_add_node(attrd_op, attrd_cluster->priv->node_name,
318 attrd_cluster->priv->node_id);
319
320 crm_debug("Broadcasting attrd protocol version %s for node %s",
321 ATTRD_PROTOCOL_VERSION, attrd_cluster->priv->node_name);
322
323 attrd_send_message(NULL, attrd_op, false);
324
325 pcmk__xml_free(attrd_op);
326 }
327
328 gboolean
329 attrd_send_message(pcmk__node_status_t *node, xmlNode *data, bool confirm)
330 {
331 const char *op = crm_element_value(data, PCMK_XA_TASK);
332
333 crm_xml_add(data, PCMK__XA_T, PCMK__VALUE_ATTRD);
334 crm_xml_add(data, PCMK__XA_ATTR_VERSION, ATTRD_PROTOCOL_VERSION);
335
336
337
338
339
340 if (!pcmk__str_eq(op, PCMK__ATTRD_CMD_CONFIRM, pcmk__str_none)) {
341 pcmk__xe_set_bool_attr(data, PCMK__XA_CONFIRM, confirm);
342 }
343
344 attrd_xml_add_writer(data);
345 return pcmk__cluster_send_message(node, pcmk_ipc_attrd, data);
346 }