This source file includes following definitions.
- attrd_cpg_dispatch
- attrd_cpg_destroy
- attrd_cib_destroy_cb
- attrd_erase_cb
- attrd_erase_attrs
- attrd_cib_connect
- attrd_cib_init
- attrd_ipc_dispatch
- attrd_ipc_fini
- attrd_cluster_connect
- main
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <unistd.h>
17
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <fcntl.h>
21
22 #include <crm/crm.h>
23 #include <crm/cib/internal.h>
24 #include <crm/msg_xml.h>
25 #include <crm/pengine/rules.h>
26 #include <crm/common/iso8601.h>
27 #include <crm/common/ipc.h>
28 #include <crm/common/ipc_internal.h>
29 #include <crm/common/xml.h>
30 #include <crm/cluster/internal.h>
31
32 #include <crm/common/attrd_internal.h>
33 #include "pacemaker-attrd.h"
34
35 lrmd_t *the_lrmd = NULL;
36 crm_cluster_t *attrd_cluster = NULL;
37 crm_trigger_t *attrd_config_read = NULL;
38 static crm_exit_t attrd_exit_status = CRM_EX_OK;
39
40 static void
41 attrd_cpg_dispatch(cpg_handle_t handle,
42 const struct cpg_name *groupName,
43 uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
44 {
45 uint32_t kind = 0;
46 xmlNode *xml = NULL;
47 const char *from = NULL;
48 char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);
49
50 if(data == NULL) {
51 return;
52 }
53
54 if (kind == crm_class_cluster) {
55 xml = string2xml(data);
56 }
57
58 if (xml == NULL) {
59 crm_err("Bad message of class %d received from %s[%u]: '%.120s'", kind, from, nodeid, data);
60 } else {
61 crm_node_t *peer = crm_get_peer(nodeid, from);
62
63 attrd_peer_message(peer, xml);
64 }
65
66 free_xml(xml);
67 free(data);
68 }
69
70 static void
71 attrd_cpg_destroy(gpointer unused)
72 {
73 if (attrd_shutting_down()) {
74 crm_info("Corosync disconnection complete");
75
76 } else {
77 crm_crit("Lost connection to cluster layer, shutting down");
78 attrd_exit_status = CRM_EX_DISCONNECT;
79 attrd_shutdown(0);
80 }
81 }
82
83 static void
84 attrd_cib_destroy_cb(gpointer user_data)
85 {
86 cib_t *conn = user_data;
87
88 conn->cmds->signoff(conn);
89
90 if (attrd_shutting_down()) {
91 crm_info("Connection disconnection complete");
92
93 } else {
94
95 crm_crit("Lost connection to the CIB manager, shutting down");
96 attrd_exit_status = CRM_EX_DISCONNECT;
97 attrd_shutdown(0);
98 }
99
100 return;
101 }
102
103 static void
104 attrd_erase_cb(xmlNode *msg, int call_id, int rc, xmlNode *output,
105 void *user_data)
106 {
107 do_crm_log_unlikely((rc? LOG_NOTICE : LOG_DEBUG),
108 "Cleared transient attributes: %s "
109 CRM_XS " xpath=%s rc=%d",
110 pcmk_strerror(rc), (char *) user_data, rc);
111 }
112
113 #define XPATH_TRANSIENT "//node_state[@uname='%s']/" XML_TAG_TRANSIENT_NODEATTRS
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 static void
130 attrd_erase_attrs(void)
131 {
132 int call_id;
133 char *xpath = crm_strdup_printf(XPATH_TRANSIENT, attrd_cluster->uname);
134
135 crm_info("Clearing transient attributes from CIB " CRM_XS " xpath=%s",
136 xpath);
137
138 call_id = the_cib->cmds->remove(the_cib, xpath, NULL,
139 cib_quorum_override | cib_xpath);
140 the_cib->cmds->register_callback_full(the_cib, call_id, 120, FALSE, xpath,
141 "attrd_erase_cb", attrd_erase_cb,
142 free);
143 }
144
145 static int
146 attrd_cib_connect(int max_retry)
147 {
148 static int attempts = 0;
149
150 int rc = -ENOTCONN;
151
152 the_cib = cib_new();
153 if (the_cib == NULL) {
154 return -ENOTCONN;
155 }
156
157 do {
158 if(attempts > 0) {
159 sleep(attempts);
160 }
161
162 attempts++;
163 crm_debug("Connection attempt %d to the CIB manager", attempts);
164 rc = the_cib->cmds->signon(the_cib, T_ATTRD, cib_command);
165
166 } while(rc != pcmk_ok && attempts < max_retry);
167
168 if (rc != pcmk_ok) {
169 crm_err("Connection to the CIB manager failed: %s " CRM_XS " rc=%d",
170 pcmk_strerror(rc), rc);
171 goto cleanup;
172 }
173
174 crm_debug("Connected to the CIB manager after %d attempts", attempts);
175
176 rc = the_cib->cmds->set_connection_dnotify(the_cib, attrd_cib_destroy_cb);
177 if (rc != pcmk_ok) {
178 crm_err("Could not set disconnection callback");
179 goto cleanup;
180 }
181
182 rc = the_cib->cmds->add_notify_callback(the_cib, T_CIB_REPLACE_NOTIFY, attrd_cib_replaced_cb);
183 if(rc != pcmk_ok) {
184 crm_err("Could not set CIB notification callback");
185 goto cleanup;
186 }
187
188 rc = the_cib->cmds->add_notify_callback(the_cib, T_CIB_DIFF_NOTIFY, attrd_cib_updated_cb);
189 if (rc != pcmk_ok) {
190 crm_err("Could not set CIB notification callback (update)");
191 goto cleanup;
192 }
193
194 return pcmk_ok;
195
196 cleanup:
197 the_cib->cmds->signoff(the_cib);
198 cib_delete(the_cib);
199 the_cib = NULL;
200 return -ENOTCONN;
201 }
202
203
204
205
206
207 static void
208 attrd_cib_init(void)
209 {
210
211 attrd_erase_attrs();
212
213
214 attrd_config_read = mainloop_add_trigger(G_PRIORITY_HIGH, attrd_read_options, NULL);
215
216
217 mainloop_set_trigger(attrd_config_read);
218 }
219
220 static qb_ipcs_service_t *ipcs = NULL;
221
222 static int32_t
223 attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
224 {
225 uint32_t id = 0;
226 uint32_t flags = 0;
227 pcmk__client_t *client = pcmk__find_client(c);
228 xmlNode *xml = NULL;
229 const char *op;
230
231
232 CRM_CHECK((c != NULL) && (client != NULL), return 0);
233 if (data == NULL) {
234 crm_debug("No IPC data from PID %d", pcmk__client_pid(c));
235 return 0;
236 }
237 xml = pcmk__client_data2xml(client, data, &id, &flags);
238 if (xml == NULL) {
239 crm_debug("Unrecognizable IPC data from PID %d", pcmk__client_pid(c));
240 return 0;
241 }
242
243 #if ENABLE_ACL
244 CRM_ASSERT(client->user != NULL);
245 pcmk__update_acl_user(xml, PCMK__XA_ATTR_USER, client->user);
246 #endif
247
248 op = crm_element_value(xml, PCMK__XA_TASK);
249
250 if (client->name == NULL) {
251 const char *value = crm_element_value(xml, F_ORIG);
252 client->name = crm_strdup_printf("%s.%d", value?value:"unknown", client->pid);
253 }
254
255 if (pcmk__str_eq(op, PCMK__ATTRD_CMD_PEER_REMOVE, pcmk__str_casei)) {
256 attrd_send_ack(client, id, flags);
257 attrd_client_peer_remove(client->name, xml);
258
259 } else if (pcmk__str_eq(op, PCMK__ATTRD_CMD_CLEAR_FAILURE, pcmk__str_casei)) {
260 attrd_send_ack(client, id, flags);
261 attrd_client_clear_failure(xml);
262
263 } else if (pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE, pcmk__str_casei)) {
264 attrd_send_ack(client, id, flags);
265 attrd_client_update(xml);
266
267 } else if (pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_BOTH, pcmk__str_casei)) {
268 attrd_send_ack(client, id, flags);
269 attrd_client_update(xml);
270
271 } else if (pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_DELAY, pcmk__str_casei)) {
272 attrd_send_ack(client, id, flags);
273 attrd_client_update(xml);
274
275 } else if (pcmk__str_eq(op, PCMK__ATTRD_CMD_REFRESH, pcmk__str_casei)) {
276 attrd_send_ack(client, id, flags);
277 attrd_client_refresh();
278
279 } else if (pcmk__str_eq(op, PCMK__ATTRD_CMD_QUERY, pcmk__str_casei)) {
280
281 attrd_client_query(client, id, flags, xml);
282
283 } else {
284 crm_info("Ignoring request from client %s with unknown operation %s",
285 client->name, op);
286 }
287
288 free_xml(xml);
289 return 0;
290 }
291
292 void
293 attrd_ipc_fini(void)
294 {
295 if (ipcs != NULL) {
296 pcmk__drop_all_clients(ipcs);
297 qb_ipcs_destroy(ipcs);
298 ipcs = NULL;
299 }
300 }
301
302 static int
303 attrd_cluster_connect(void)
304 {
305 attrd_cluster = calloc(1, sizeof(crm_cluster_t));
306
307 attrd_cluster->destroy = attrd_cpg_destroy;
308 attrd_cluster->cpg.cpg_deliver_fn = attrd_cpg_dispatch;
309 attrd_cluster->cpg.cpg_confchg_fn = pcmk_cpg_membership;
310
311 crm_set_status_callback(&attrd_peer_change_cb);
312
313 if (crm_cluster_connect(attrd_cluster) == FALSE) {
314 crm_err("Cluster connection failed");
315 return -ENOTCONN;
316 }
317 return pcmk_ok;
318 }
319
320 static pcmk__cli_option_t long_options[] = {
321
322 {
323 "help", no_argument, NULL, '?',
324 "\tThis text", pcmk__option_default
325 },
326 {
327 "verbose", no_argument, NULL, 'V',
328 "\tIncrease debug output", pcmk__option_default
329 },
330 { 0, 0, 0, 0 }
331 };
332
333 int
334 main(int argc, char **argv)
335 {
336 int flag = 0;
337 int index = 0;
338 int argerr = 0;
339 crm_ipc_t *old_instance = NULL;
340
341 attrd_init_mainloop();
342 crm_log_preinit(NULL, argc, argv);
343 pcmk__set_cli_options(NULL, "[options]", long_options,
344 "daemon for managing Pacemaker node attributes");
345
346 mainloop_add_signal(SIGTERM, attrd_shutdown);
347
348 while (1) {
349 flag = pcmk__next_cli_option(argc, argv, &index, NULL);
350 if (flag == -1)
351 break;
352
353 switch (flag) {
354 case 'V':
355 crm_bump_log_level(argc, argv);
356 break;
357 case 'h':
358 pcmk__cli_help(flag, CRM_EX_OK);
359 break;
360 default:
361 ++argerr;
362 break;
363 }
364 }
365
366 if (optind > argc) {
367 ++argerr;
368 }
369
370 if (argerr) {
371 pcmk__cli_help('?', CRM_EX_USAGE);
372 }
373
374 crm_log_init(T_ATTRD, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
375 crm_notice("Starting Pacemaker node attribute manager");
376
377 old_instance = crm_ipc_new(T_ATTRD, 0);
378 if (crm_ipc_connect(old_instance)) {
379
380 crm_ipc_close(old_instance);
381 crm_ipc_destroy(old_instance);
382 crm_err("pacemaker-attrd is already active, aborting startup");
383 crm_exit(CRM_EX_OK);
384 } else {
385
386 crm_ipc_destroy(old_instance);
387 old_instance = NULL;
388 }
389
390 attributes = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_attribute);
391
392
393
394
395
396 if (attrd_cib_connect(10) != pcmk_ok) {
397 attrd_exit_status = CRM_EX_FATAL;
398 goto done;
399 }
400 crm_info("CIB connection active");
401
402 if (attrd_cluster_connect() != pcmk_ok) {
403 attrd_exit_status = CRM_EX_FATAL;
404 goto done;
405 }
406 crm_info("Cluster connection active");
407
408
409 attrd_election_init();
410 attrd_cib_init();
411
412
413
414
415
416
417 attrd_broadcast_protocol();
418
419 attrd_init_ipc(&ipcs, attrd_ipc_dispatch);
420 crm_notice("Pacemaker node attribute manager successfully started and accepting connections");
421 attrd_run_mainloop();
422
423 done:
424 crm_info("Shutting down attribute manager");
425
426 attrd_election_fini();
427 attrd_ipc_fini();
428 attrd_lrmd_disconnect();
429 attrd_cib_disconnect();
430 g_hash_table_destroy(attributes);
431
432 crm_exit(attrd_exit_status);
433 }