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