This source file includes following definitions.
- stonith_connection_destroy_cb
- get_stonith_connection
- lrmd_ipc_accept
- lrmd_ipc_created
- lrmd_ipc_dispatch
- lrmd_client_destroy
- lrmd_ipc_closed
- lrmd_ipc_destroy
- lrmd_server_send_reply
- lrmd_server_send_notify
- lrmd_exit
- lrmd_shutdown
- handle_shutdown_ack
- handle_shutdown_nack
- main
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <glib.h>
13 #include <signal.h>
14 #include <sys/types.h>
15
16 #include <crm/crm.h>
17 #include <crm/msg_xml.h>
18 #include <crm/services.h>
19 #include <crm/common/mainloop.h>
20 #include <crm/common/ipc.h>
21 #include <crm/common/ipc_internal.h>
22 #include <crm/common/remote_internal.h>
23 #include <crm/lrmd_internal.h>
24
25 #include "pacemaker-execd.h"
26
27 #if defined(HAVE_GNUTLS_GNUTLS_H) && defined(SUPPORT_REMOTE)
28 # define ENABLE_PCMK_REMOTE
29 #endif
30
31 static GMainLoop *mainloop = NULL;
32 static qb_ipcs_service_t *ipcs = NULL;
33 static stonith_t *stonith_api = NULL;
34 int lrmd_call_id = 0;
35
36 #ifdef ENABLE_PCMK_REMOTE
37
38 static sig_atomic_t shutting_down = FALSE;
39
40
41 static guint shutdown_ack_timer = 0;
42
43 static gboolean lrmd_exit(gpointer data);
44 #endif
45
46 static void
47 stonith_connection_destroy_cb(stonith_t * st, stonith_event_t * e)
48 {
49 stonith_api->state = stonith_disconnected;
50 crm_err("Connection to fencer lost");
51 stonith_connection_failed();
52 }
53
54 stonith_t *
55 get_stonith_connection(void)
56 {
57 if (stonith_api && stonith_api->state == stonith_disconnected) {
58 stonith_api_delete(stonith_api);
59 stonith_api = NULL;
60 }
61
62 if (stonith_api == NULL) {
63 int rc = pcmk_ok;
64
65 stonith_api = stonith_api_new();
66 if (stonith_api == NULL) {
67 crm_err("Could not connect to fencer: API memory allocation failed");
68 return NULL;
69 }
70 rc = stonith_api_connect_retry(stonith_api, crm_system_name, 10);
71 if (rc != pcmk_ok) {
72 crm_err("Could not connect to fencer in 10 attempts: %s "
73 CRM_XS " rc=%d", pcmk_strerror(rc), rc);
74 stonith_api_delete(stonith_api);
75 stonith_api = NULL;
76 } else {
77 stonith_api->cmds->register_notification(stonith_api,
78 T_STONITH_NOTIFY_DISCONNECT,
79 stonith_connection_destroy_cb);
80 }
81 }
82 return stonith_api;
83 }
84
85 static int32_t
86 lrmd_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
87 {
88 crm_trace("Connection %p", c);
89 if (pcmk__new_client(c, uid, gid) == NULL) {
90 return -EIO;
91 }
92 return 0;
93 }
94
95 static void
96 lrmd_ipc_created(qb_ipcs_connection_t * c)
97 {
98 pcmk__client_t *new_client = pcmk__find_client(c);
99
100 crm_trace("Connection %p", c);
101 CRM_ASSERT(new_client != NULL);
102
103
104
105 notify_of_new_client(new_client);
106 }
107
108 static int32_t
109 lrmd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
110 {
111 uint32_t id = 0;
112 uint32_t flags = 0;
113 pcmk__client_t *client = pcmk__find_client(c);
114 xmlNode *request = pcmk__client_data2xml(client, data, &id, &flags);
115
116 CRM_CHECK(client != NULL, crm_err("Invalid client");
117 return FALSE);
118 CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client);
119 return FALSE);
120
121 CRM_CHECK(flags & crm_ipc_client_response, crm_err("Invalid client request: %p", client);
122 return FALSE);
123
124 if (!request) {
125 return 0;
126 }
127
128 if (!client->name) {
129 const char *value = crm_element_value(request, F_LRMD_CLIENTNAME);
130
131 if (value == NULL) {
132 client->name = crm_itoa(pcmk__client_pid(c));
133 } else {
134 client->name = strdup(value);
135 }
136 }
137
138 lrmd_call_id++;
139 if (lrmd_call_id < 1) {
140 lrmd_call_id = 1;
141 }
142
143 crm_xml_add(request, F_LRMD_CLIENTID, client->id);
144 crm_xml_add(request, F_LRMD_CLIENTNAME, client->name);
145 crm_xml_add_int(request, F_LRMD_CALLID, lrmd_call_id);
146
147 process_lrmd_message(client, id, request);
148
149 free_xml(request);
150 return 0;
151 }
152
153
154
155
156
157
158
159 void
160 lrmd_client_destroy(pcmk__client_t *client)
161 {
162 pcmk__free_client(client);
163
164 #ifdef ENABLE_PCMK_REMOTE
165
166
167
168 if (shutting_down && (ipc_proxy_get_provider() == NULL)) {
169 lrmd_exit(NULL);
170 }
171 #endif
172 }
173
174 static int32_t
175 lrmd_ipc_closed(qb_ipcs_connection_t * c)
176 {
177 pcmk__client_t *client = pcmk__find_client(c);
178
179 if (client == NULL) {
180 return 0;
181 }
182
183 crm_trace("Connection %p", c);
184 client_disconnect_cleanup(client->id);
185 #ifdef ENABLE_PCMK_REMOTE
186 ipc_proxy_remove_provider(client);
187 #endif
188 lrmd_client_destroy(client);
189 return 0;
190 }
191
192 static void
193 lrmd_ipc_destroy(qb_ipcs_connection_t * c)
194 {
195 lrmd_ipc_closed(c);
196 crm_trace("Connection %p", c);
197 }
198
199 static struct qb_ipcs_service_handlers lrmd_ipc_callbacks = {
200 .connection_accept = lrmd_ipc_accept,
201 .connection_created = lrmd_ipc_created,
202 .msg_process = lrmd_ipc_dispatch,
203 .connection_closed = lrmd_ipc_closed,
204 .connection_destroyed = lrmd_ipc_destroy
205 };
206
207
208 int
209 lrmd_server_send_reply(pcmk__client_t *client, uint32_t id, xmlNode *reply)
210 {
211 crm_trace("Sending reply (%d) to client (%s)", id, client->id);
212 switch (PCMK__CLIENT_TYPE(client)) {
213 case pcmk__client_ipc:
214 return pcmk__ipc_send_xml(client, id, reply, FALSE);
215 #ifdef ENABLE_PCMK_REMOTE
216 case pcmk__client_tls:
217 return lrmd_tls_send_msg(client->remote, reply, id, "reply");
218 #endif
219 default:
220 crm_err("Could not send reply: unknown client type for %s "
221 CRM_XS " flags=0x%llx",
222 pcmk__client_name(client), client->flags);
223 }
224 return ENOTCONN;
225 }
226
227
228 int
229 lrmd_server_send_notify(pcmk__client_t *client, xmlNode *msg)
230 {
231 crm_trace("Sending notification to client (%s)", client->id);
232 switch (PCMK__CLIENT_TYPE(client)) {
233 case pcmk__client_ipc:
234 if (client->ipcs == NULL) {
235 crm_trace("Could not notify local client: disconnected");
236 return ENOTCONN;
237 }
238 return pcmk__ipc_send_xml(client, 0, msg, crm_ipc_server_event);
239 #ifdef ENABLE_PCMK_REMOTE
240 case pcmk__client_tls:
241 if (client->remote == NULL) {
242 crm_trace("Could not notify remote client: disconnected");
243 return ENOTCONN;
244 } else {
245 return lrmd_tls_send_msg(client->remote, msg, 0, "notify");
246 }
247 #endif
248 default:
249 crm_err("Could not notify client %s with unknown transport "
250 CRM_XS " flags=0x%llx",
251 pcmk__client_name(client), client->flags);
252 }
253 return ENOTCONN;
254 }
255
256
257
258
259
260
261
262
263
264
265 static gboolean
266 lrmd_exit(gpointer data)
267 {
268 crm_info("Terminating with %d clients", pcmk__ipc_client_count());
269 if (stonith_api) {
270 stonith_api->cmds->remove_notification(stonith_api, T_STONITH_NOTIFY_DISCONNECT);
271 stonith_api->cmds->disconnect(stonith_api);
272 stonith_api_delete(stonith_api);
273 }
274 if (ipcs) {
275 mainloop_del_ipc_server(ipcs);
276 }
277
278 #ifdef ENABLE_PCMK_REMOTE
279 lrmd_tls_server_destroy();
280 ipc_proxy_cleanup();
281 #endif
282
283 pcmk__client_cleanup();
284 g_hash_table_destroy(rsc_list);
285
286 if (mainloop) {
287 lrmd_drain_alerts(mainloop);
288 }
289
290 crm_exit(CRM_EX_OK);
291 return FALSE;
292 }
293
294
295
296
297
298
299
300 static void
301 lrmd_shutdown(int nsig)
302 {
303 #ifdef ENABLE_PCMK_REMOTE
304 pcmk__client_t *ipc_proxy = ipc_proxy_get_provider();
305
306
307
308
309 if (ipc_proxy) {
310 if (shutting_down) {
311 crm_notice("Waiting for cluster to stop resources before exiting");
312 return;
313 }
314
315 crm_info("Sending shutdown request to cluster");
316 if (ipc_proxy_shutdown_req(ipc_proxy) < 0) {
317 crm_crit("Shutdown request failed, exiting immediately");
318
319 } else {
320
321
322
323
324
325 shutting_down = TRUE;
326
327
328 lrmd_tls_server_destroy();
329
330
331
332
333
334 shutdown_ack_timer = g_timeout_add_seconds(20, lrmd_exit, NULL);
335
336
337
338
339
340
341 return;
342 }
343 }
344 #endif
345 lrmd_exit(NULL);
346 }
347
348
349
350
351
352 void handle_shutdown_ack()
353 {
354 #ifdef ENABLE_PCMK_REMOTE
355 if (shutting_down) {
356 crm_info("Received shutdown ack");
357 if (shutdown_ack_timer > 0) {
358 g_source_remove(shutdown_ack_timer);
359 shutdown_ack_timer = 0;
360 }
361 return;
362 }
363 #endif
364 crm_debug("Ignoring unexpected shutdown ack");
365 }
366
367
368
369
370
371 void handle_shutdown_nack()
372 {
373 #ifdef ENABLE_PCMK_REMOTE
374 if (shutting_down) {
375 crm_info("Received shutdown nack");
376 if (shutdown_ack_timer > 0) {
377 g_source_remove(shutdown_ack_timer);
378 shutdown_ack_timer = g_timeout_add(0, lrmd_exit, NULL);
379 }
380 return;
381 }
382 #endif
383 crm_debug("Ignoring unexpected shutdown nack");
384 }
385
386 static pcmk__cli_option_t long_options[] = {
387
388 {
389 "help", no_argument, NULL, '?',
390 "\tThis text", pcmk__option_default
391 },
392 {
393 "version", no_argument, NULL, '$',
394 "\tVersion information", pcmk__option_default
395 },
396 {
397 "verbose", no_argument, NULL, 'V',
398 "\tIncrease debug output", pcmk__option_default
399 },
400 {
401 "logfile", required_argument, NULL, 'l',
402 "\tSend logs to the additional named logfile", pcmk__option_default
403 },
404 #ifdef ENABLE_PCMK_REMOTE
405 {
406 "port", required_argument, NULL, 'p',
407 "\tPort to listen on", pcmk__option_default
408 },
409 #endif
410 { 0, 0, 0, 0 }
411 };
412
413 #ifdef ENABLE_PCMK_REMOTE
414 # define EXECD_TYPE "remote"
415 # define EXECD_NAME "pacemaker-remoted"
416 # define EXECD_DESC "resource agent executor daemon for Pacemaker Remote nodes"
417 #else
418 # define EXECD_TYPE "local"
419 # define EXECD_NAME "pacemaker-execd"
420 # define EXECD_DESC "resource agent executor daemon for Pacemaker cluster nodes"
421 #endif
422
423 int
424 main(int argc, char **argv, char **envp)
425 {
426 int flag = 0;
427 int index = 0;
428 int bump_log_num = 0;
429 const char *option = NULL;
430
431 #ifdef ENABLE_PCMK_REMOTE
432
433 remoted_spawn_pidone(argc, argv, envp);
434 #endif
435
436 crm_log_preinit(EXECD_NAME, argc, argv);
437 pcmk__set_cli_options(NULL, "[options]", long_options, EXECD_DESC);
438
439 while (1) {
440 flag = pcmk__next_cli_option(argc, argv, &index, NULL);
441 if (flag == -1) {
442 break;
443 }
444
445 switch (flag) {
446 case 'l':
447 crm_add_logfile(optarg);
448 break;
449 case 'p':
450 setenv("PCMK_remote_port", optarg, 1);
451 break;
452 case 'V':
453 bump_log_num++;
454 break;
455 case '?':
456 case '$':
457 pcmk__cli_help(flag, CRM_EX_OK);
458 break;
459 default:
460 pcmk__cli_help('?', CRM_EX_USAGE);
461 break;
462 }
463 }
464
465 crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
466
467 while (bump_log_num > 0) {
468 crm_bump_log_level(argc, argv);
469 bump_log_num--;
470 }
471
472 option = pcmk__env_option("logfacility");
473 if (option && !pcmk__strcase_any_of(option, "none", "/dev/null", NULL)) {
474 setenv("HA_LOGFACILITY", option, 1);
475 }
476
477 option = pcmk__env_option("logfile");
478 if(option && !pcmk__str_eq(option, "none", pcmk__str_casei)) {
479 setenv("HA_LOGFILE", option, 1);
480
481 if (pcmk__env_option_enabled(crm_system_name, "debug")) {
482 setenv("HA_DEBUGLOG", option, 1);
483 }
484 }
485
486 crm_notice("Starting Pacemaker " EXECD_TYPE " executor");
487
488
489
490
491
492 unsetenv("NOTIFY_SOCKET");
493
494
495 crm_build_path(CRM_RSCTMP_DIR, 0755);
496
497 rsc_list = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_rsc);
498 ipcs = mainloop_add_ipc_server(CRM_SYSTEM_LRMD, QB_IPC_SHM, &lrmd_ipc_callbacks);
499 if (ipcs == NULL) {
500 crm_err("Failed to create IPC server: shutting down and inhibiting respawn");
501 crm_exit(CRM_EX_FATAL);
502 }
503
504 #ifdef ENABLE_PCMK_REMOTE
505 if (lrmd_init_remote_tls_server() < 0) {
506 crm_err("Failed to create TLS listener: shutting down and staying down");
507 crm_exit(CRM_EX_FATAL);
508 }
509 ipc_proxy_init();
510 #endif
511
512 mainloop_add_signal(SIGTERM, lrmd_shutdown);
513 mainloop = g_main_loop_new(NULL, FALSE);
514 crm_notice("Pacemaker " EXECD_TYPE " executor successfully started and accepting connections");
515 g_main_loop_run(mainloop);
516
517
518 lrmd_exit(NULL);
519 return CRM_EX_OK;
520 }