4 Copyright (C) Andrew Tridgell 2007
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/filesys.h"
22 #include "system/network.h"
23 #include "system/wait.h"
24 #include "system/dir.h"
25 #include "system/locale.h"
26 #include "system/time.h"
27 #include "system/dir.h"
32 #include "lib/util/dlinklist.h"
33 #include "lib/util/debug.h"
34 #include "lib/util/samba_util.h"
35 #include "lib/util/sys_rw.h"
37 #include "ctdb_private.h"
39 #include "common/rb_tree.h"
40 #include "common/common.h"
41 #include "common/logging.h"
42 #include "common/reqid.h"
43 #include "common/sock_io.h"
45 #include "protocol/protocol_api.h"
48 * Setting up event daemon
51 struct eventd_context
{
52 struct tevent_context
*ev
;
54 const char *script_dir
;
57 const char *debug_hung_script
;
61 struct tevent_fd
*eventd_fde
;
64 struct reqid_context
*idr
;
65 struct sock_queue
*queue
;
66 struct eventd_client_state
*calls
;
69 static bool eventd_context_init(TALLOC_CTX
*mem_ctx
,
70 struct ctdb_context
*ctdb
,
71 struct eventd_context
**out
)
73 struct eventd_context
*ectx
;
74 const char *eventd
= CTDB_HELPER_BINDIR
"/ctdb_eventd";
75 const char *debug_hung_script
= CTDB_ETCDIR
"/debug-hung-script.sh";
80 ectx
= talloc_zero(mem_ctx
, struct eventd_context
);
87 value
= getenv("CTDB_EVENTD");
92 ectx
->path
= talloc_strdup(ectx
, eventd
);
93 if (ectx
->path
== NULL
) {
98 ectx
->script_dir
= ctdb
->event_script_dir
;
100 socket
= talloc_strdup(ectx
, ctdb_get_socketname(ctdb
));
101 if (socket
== NULL
) {
106 ectx
->socket
= talloc_asprintf(ectx
, "%s/eventd.sock",
108 if (ectx
->socket
== NULL
) {
115 value
= getenv("CTDB_DEBUG_HUNG_SCRIPT");
117 if (value
[0] == '\0') {
118 debug_hung_script
= NULL
;
120 debug_hung_script
= value
;
124 if (debug_hung_script
!= NULL
) {
125 ectx
->debug_hung_script
= talloc_strdup(ectx
,
127 if (ectx
->debug_hung_script
== NULL
) {
133 ret
= reqid_init(ectx
, 1, &ectx
->idr
);
139 ectx
->eventd_pid
= -1;
146 * Start and stop event daemon
149 static bool eventd_client_connect(struct eventd_context
*ectx
);
150 static void eventd_dead_handler(struct tevent_context
*ev
,
151 struct tevent_fd
*fde
, uint16_t flags
,
154 int ctdb_start_eventd(struct ctdb_context
*ctdb
)
156 struct eventd_context
*ectx
;
163 if (ctdb
->ectx
== NULL
) {
164 status
= eventd_context_init(ctdb
, ctdb
, &ctdb
->ectx
);
167 ("Failed to initialize eventd context\n"));
174 if (! sock_clean(ectx
->socket
)) {
178 argv
= talloc_array(ectx
, const char *, 14);
183 argv
[0] = ectx
->path
;
185 argv
[2] = ectx
->script_dir
;
187 argv
[4] = ectx
->socket
;
189 argv
[6] = talloc_asprintf(argv
, "%d", ctdb
->ctdbd_pid
);
191 argv
[8] = getenv("CTDB_LOGGING");
193 argv
[10] = debug_level_to_string(DEBUGLEVEL
);
194 if (ectx
->debug_hung_script
== NULL
) {
199 argv
[12] = ectx
->debug_hung_script
;
203 if (argv
[6] == NULL
) {
209 ("Starting event daemon %s %s %s %s %s %s %s %s %s %s %s\n",
210 argv
[0], argv
[1], argv
[2], argv
[3], argv
[4], argv
[5],
211 argv
[6], argv
[7], argv
[8], argv
[9], argv
[10]));
218 pid
= ctdb_fork(ctdb
);
227 ret
= execv(argv
[0], discard_const(argv
));
237 ectx
->eventd_fde
= tevent_add_fd(ctdb
->ev
, ectx
, fd
[0],
239 eventd_dead_handler
, ectx
);
240 if (ectx
->eventd_fde
== NULL
) {
241 ctdb_kill(ctdb
, pid
, SIGKILL
);
246 tevent_fd_set_auto_close(ectx
->eventd_fde
);
247 ectx
->eventd_pid
= pid
;
249 /* Wait to connect to eventd */
250 for (i
=0; i
<10; i
++) {
251 status
= eventd_client_connect(ectx
);
259 DEBUG(DEBUG_ERR
, ("Failed to initialize event daemon\n"));
260 ctdb_stop_eventd(ctdb
);
267 static void eventd_dead_handler(struct tevent_context
*ev
,
268 struct tevent_fd
*fde
, uint16_t flags
,
271 struct eventd_context
*ectx
= talloc_get_type_abort(
272 private_data
, struct eventd_context
);
274 DEBUG(DEBUG_ERR
, ("Eventd went away\n"));
276 TALLOC_FREE(ectx
->eventd_fde
);
277 ectx
->eventd_pid
= -1;
280 void ctdb_stop_eventd(struct ctdb_context
*ctdb
)
282 struct eventd_context
*ectx
= ctdb
->ectx
;
288 TALLOC_FREE(ectx
->eventd_fde
);
289 if (ectx
->eventd_pid
!= -1) {
290 kill(ectx
->eventd_pid
, SIGTERM
);
291 ectx
->eventd_pid
= -1;
293 TALLOC_FREE(ctdb
->ectx
);
297 * Connect to event daemon
300 struct eventd_client_state
{
301 struct eventd_client_state
*prev
, *next
;
303 struct eventd_context
*ectx
;
304 void (*callback
)(struct ctdb_event_reply
*reply
, void *private_data
);
312 static void eventd_client_read(uint8_t *buf
, size_t buflen
,
314 static int eventd_client_state_destructor(struct eventd_client_state
*state
);
316 static bool eventd_client_connect(struct eventd_context
*ectx
)
320 if (ectx
->queue
!= NULL
) {
324 fd
= sock_connect(ectx
->socket
);
329 ectx
->queue
= sock_queue_setup(ectx
, ectx
->ev
, fd
,
330 eventd_client_read
, ectx
);
331 if (ectx
->queue
== NULL
) {
339 static int eventd_client_write(struct eventd_context
*ectx
,
341 struct ctdb_event_request
*request
,
342 void (*callback
)(struct ctdb_event_reply
*reply
,
346 struct eventd_client_state
*state
;
349 if (! eventd_client_connect(ectx
)) {
353 state
= talloc_zero(mem_ctx
, struct eventd_client_state
);
359 state
->callback
= callback
;
360 state
->private_data
= private_data
;
362 state
->reqid
= reqid_new(ectx
->idr
, state
);
363 if (state
->reqid
== REQID_INVALID
) {
368 talloc_set_destructor(state
, eventd_client_state_destructor
);
370 ctdb_event_header_fill(&request
->header
, state
->reqid
);
371 state
->buflen
= ctdb_event_request_len(request
);
372 state
->buf
= talloc_size(state
, state
->buflen
);
373 if (state
->buf
== NULL
) {
378 ret
= ctdb_event_request_push(request
, state
->buf
, &state
->buflen
);
384 ret
= sock_queue_write(ectx
->queue
, state
->buf
, state
->buflen
);
390 DLIST_ADD(ectx
->calls
, state
);
395 static int eventd_client_state_destructor(struct eventd_client_state
*state
)
397 struct eventd_context
*ectx
= state
->ectx
;
399 reqid_remove(ectx
->idr
, state
->reqid
);
400 DLIST_REMOVE(ectx
->calls
, state
);
404 static void eventd_client_read(uint8_t *buf
, size_t buflen
,
407 struct eventd_context
*ectx
= talloc_get_type_abort(
408 private_data
, struct eventd_context
);
409 struct eventd_client_state
*state
;
410 struct ctdb_event_reply
*reply
;
414 /* connection lost */
415 TALLOC_FREE(ectx
->queue
);
419 reply
= talloc_zero(ectx
, struct ctdb_event_reply
);
424 ret
= ctdb_event_reply_pull(buf
, buflen
, reply
, reply
);
426 D_ERR("Invalid packet received, ret=%d\n", ret
);
431 if (buflen
!= reply
->header
.length
) {
432 D_ERR("Packet size mismatch %zu != %"PRIu32
"\n",
433 buflen
, reply
->header
.length
);
438 state
= reqid_find(ectx
->idr
, reply
->header
.reqid
,
439 struct eventd_client_state
);
445 if (state
->reqid
!= reply
->header
.reqid
) {
450 state
= talloc_steal(reply
, state
);
451 state
->callback(reply
, state
->private_data
);
459 struct eventd_client_run_state
{
460 struct eventd_context
*ectx
;
461 void (*callback
)(int result
, void *private_data
);
465 static void eventd_client_run_done(struct ctdb_event_reply
*reply
,
468 static int eventd_client_run(struct eventd_context
*ectx
,
470 void (*callback
)(int result
,
473 enum ctdb_event event
,
477 struct eventd_client_run_state
*state
;
478 struct ctdb_event_request request
;
479 struct ctdb_event_request_run rdata
;
482 state
= talloc_zero(mem_ctx
, struct eventd_client_run_state
);
488 state
->callback
= callback
;
489 state
->private_data
= private_data
;
492 rdata
.timeout
= timeout
;
493 rdata
.arg_str
= arg_str
;
495 request
.rdata
.command
= CTDB_EVENT_COMMAND_RUN
;
496 request
.rdata
.data
.run
= &rdata
;
498 ret
= eventd_client_write(ectx
, state
, &request
,
499 eventd_client_run_done
, state
);
508 static void eventd_client_run_done(struct ctdb_event_reply
*reply
,
511 struct eventd_client_run_state
*state
= talloc_get_type_abort(
512 private_data
, struct eventd_client_run_state
);
514 state
= talloc_steal(state
->ectx
, state
);
515 state
->callback(reply
->rdata
.result
, state
->private_data
);
520 * CTDB event script functions
523 int ctdb_event_script_run(struct ctdb_context
*ctdb
,
525 void (*callback
)(struct ctdb_context
*ctdb
,
526 int result
, void *private_data
),
528 enum ctdb_event event
,
529 const char *fmt
, va_list ap
)
530 PRINTF_ATTRIBUTE(6,0);
532 struct ctdb_event_script_run_state
{
533 struct ctdb_context
*ctdb
;
534 void (*callback
)(struct ctdb_context
*ctdb
, int result
,
537 enum ctdb_event event
;
540 static bool event_allowed_during_recovery(enum ctdb_event event
);
541 static void ctdb_event_script_run_done(int result
, void *private_data
);
542 static bool check_options(enum ctdb_event call
, const char *options
);
544 int ctdb_event_script_run(struct ctdb_context
*ctdb
,
546 void (*callback
)(struct ctdb_context
*ctdb
,
547 int result
, void *private_data
),
549 enum ctdb_event event
,
550 const char *fmt
, va_list ap
)
552 struct ctdb_event_script_run_state
*state
;
556 if ( (ctdb
->recovery_mode
!= CTDB_RECOVERY_NORMAL
) &&
557 (! event_allowed_during_recovery(event
)) ) {
559 ("Refusing to run event '%s' while in recovery\n",
560 ctdb_eventscript_call_names
[event
]));
563 state
= talloc_zero(mem_ctx
, struct ctdb_event_script_run_state
);
569 state
->callback
= callback
;
570 state
->private_data
= private_data
;
571 state
->event
= event
;
574 arg_str
= talloc_vasprintf(state
, fmt
, ap
);
575 if (arg_str
== NULL
) {
583 if (! check_options(event
, arg_str
)) {
585 ("Bad event script arguments '%s' for '%s'\n",
586 arg_str
, ctdb_eventscript_call_names
[event
]));
587 talloc_free(arg_str
);
591 ret
= eventd_client_run(ctdb
->ectx
, state
,
592 ctdb_event_script_run_done
, state
,
593 event
, arg_str
, ctdb
->tunable
.script_timeout
);
600 (__location__
" Running event %s with arguments %s\n",
601 ctdb_eventscript_call_names
[event
], arg_str
));
603 talloc_free(arg_str
);
607 static void ctdb_event_script_run_done(int result
, void *private_data
)
609 struct ctdb_event_script_run_state
*state
= talloc_get_type_abort(
610 private_data
, struct ctdb_event_script_run_state
);
612 if (result
== -ETIME
) {
613 switch (state
->event
) {
614 case CTDB_EVENT_START_RECOVERY
:
615 case CTDB_EVENT_RECOVERED
:
616 case CTDB_EVENT_TAKE_IP
:
617 case CTDB_EVENT_RELEASE_IP
:
619 ("Ignoring hung script for %s event\n",
620 ctdb_eventscript_call_names
[state
->event
]));
629 state
= talloc_steal(state
->ctdb
, state
);
630 state
->callback(state
->ctdb
, result
, state
->private_data
);
635 static unsigned int count_words(const char *options
)
637 unsigned int words
= 0;
639 if (options
== NULL
) {
643 options
+= strspn(options
, " \t");
646 options
+= strcspn(options
, " \t");
647 options
+= strspn(options
, " \t");
652 static bool check_options(enum ctdb_event call
, const char *options
)
655 /* These all take no arguments. */
656 case CTDB_EVENT_INIT
:
657 case CTDB_EVENT_SETUP
:
658 case CTDB_EVENT_STARTUP
:
659 case CTDB_EVENT_START_RECOVERY
:
660 case CTDB_EVENT_RECOVERED
:
661 case CTDB_EVENT_MONITOR
:
662 case CTDB_EVENT_SHUTDOWN
:
663 case CTDB_EVENT_IPREALLOCATED
:
664 return count_words(options
) == 0;
666 case CTDB_EVENT_TAKE_IP
: /* interface, IP address, netmask bits. */
667 case CTDB_EVENT_RELEASE_IP
:
668 return count_words(options
) == 3;
670 case CTDB_EVENT_UPDATE_IP
: /* old interface, new interface, IP address, netmask bits. */
671 return count_words(options
) == 4;
674 DEBUG(DEBUG_ERR
,(__location__
"Unknown ctdb_event %u\n", call
));
679 /* only specific events are allowed while in recovery */
680 static bool event_allowed_during_recovery(enum ctdb_event event
)
682 const enum ctdb_event allowed_events
[] = {
685 CTDB_EVENT_START_RECOVERY
,
687 CTDB_EVENT_RELEASE_IP
,
688 CTDB_EVENT_IPREALLOCATED
,
692 for (i
= 0; i
< ARRAY_SIZE(allowed_events
); i
++) {
693 if (event
== allowed_events
[i
]) {
702 run the event script in the background, calling the callback when
703 finished. If mem_ctx is freed, callback will never be called.
705 int ctdb_event_script_callback(struct ctdb_context
*ctdb
,
707 void (*callback
)(struct ctdb_context
*, int, void *),
709 enum ctdb_event call
,
710 const char *fmt
, ...)
716 ret
= ctdb_event_script_run(ctdb
, mem_ctx
, callback
, private_data
,
724 struct ctdb_event_script_args_state
{
729 static void ctdb_event_script_args_done(struct ctdb_context
*ctdb
,
730 int status
, void *private_data
)
732 struct ctdb_event_script_args_state
*s
=
733 (struct ctdb_event_script_args_state
*)private_data
;
740 run the event script, waiting for it to complete. Used when the caller
741 doesn't want to continue till the event script has finished.
743 int ctdb_event_script_args(struct ctdb_context
*ctdb
, enum ctdb_event call
,
744 const char *fmt
, ...)
748 struct ctdb_event_script_args_state state
= {
754 ret
= ctdb_event_script_run(ctdb
, ctdb
,
755 ctdb_event_script_args_done
, &state
,
762 while (! state
.done
) {
763 tevent_loop_once(ctdb
->ev
);
766 if (state
.status
== -ETIME
) {
767 /* Don't ban self if CTDB is starting up or shutting down */
768 if (call
!= CTDB_EVENT_INIT
&& call
!= CTDB_EVENT_SHUTDOWN
) {
770 (__location__
" eventscript for '%s' timed out."
771 " Immediately banning ourself for %d seconds\n",
772 ctdb_eventscript_call_names
[call
],
773 ctdb
->tunable
.recovery_ban_period
));
781 int ctdb_event_script(struct ctdb_context
*ctdb
, enum ctdb_event call
)
783 /* GCC complains about empty format string, so use %s and "". */
784 return ctdb_event_script_args(ctdb
, call
, NULL
);