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/common.h"
40 #include "common/logging.h"
41 #include "common/reqid.h"
42 #include "common/sock_io.h"
43 #include "common/path.h"
45 #include "protocol/protocol_util.h"
46 #include "event/event_protocol_api.h"
49 * Setting up event daemon
52 struct eventd_context
{
53 struct tevent_context
*ev
;
59 struct tevent_fd
*eventd_fde
;
62 struct reqid_context
*idr
;
63 struct sock_queue
*queue
;
64 struct eventd_client_state
*calls
;
67 static bool eventd_context_init(TALLOC_CTX
*mem_ctx
,
68 struct ctdb_context
*ctdb
,
69 struct eventd_context
**out
)
71 struct eventd_context
*ectx
;
72 const char *eventd
= CTDB_HELPER_BINDIR
"/ctdb-eventd";
76 ectx
= talloc_zero(mem_ctx
, struct eventd_context
);
83 value
= getenv("CTDB_EVENTD");
88 ectx
->path
= talloc_strdup(ectx
, eventd
);
89 if (ectx
->path
== NULL
) {
94 ectx
->socket
= path_socket(ectx
, "eventd");
95 if (ectx
->socket
== NULL
) {
100 ret
= reqid_init(ectx
, 1, &ectx
->idr
);
106 ectx
->eventd_pid
= -1;
112 struct eventd_startup_state
{
118 static void eventd_startup_timeout_handler(struct tevent_context
*ev
,
119 struct tevent_timer
*te
,
123 struct eventd_startup_state
*state
=
124 (struct eventd_startup_state
*) private_data
;
127 state
->ret
= ETIMEDOUT
;
130 static void eventd_startup_handler(struct tevent_context
*ev
,
131 struct tevent_fd
*fde
, uint16_t flags
,
134 struct eventd_startup_state
*state
=
135 (struct eventd_startup_state
*)private_data
;
139 num_read
= sys_read(state
->fd
, &data
, sizeof(data
));
140 if (num_read
== sizeof(data
)) {
146 } else if (num_read
== 0) {
148 } else if (num_read
== -1) {
158 static int wait_for_daemon_startup(struct tevent_context
*ev
,
162 struct tevent_timer
*timer
;
163 struct tevent_fd
*fde
;
164 struct eventd_startup_state state
= {
170 mem_ctx
= talloc_new(ev
);
171 if (mem_ctx
== NULL
) {
175 timer
= tevent_add_timer(ev
,
177 tevent_timeval_current_ofs(10, 0),
178 eventd_startup_timeout_handler
,
181 talloc_free(mem_ctx
);
185 fde
= tevent_add_fd(ev
,
189 eventd_startup_handler
,
192 talloc_free(mem_ctx
);
196 while (! state
.done
) {
197 tevent_loop_once(ev
);
200 talloc_free(mem_ctx
);
207 * Start and stop event daemon
210 static bool eventd_client_connect(struct eventd_context
*ectx
);
211 static void eventd_dead_handler(struct tevent_context
*ev
,
212 struct tevent_fd
*fde
, uint16_t flags
,
215 int ctdb_start_eventd(struct ctdb_context
*ctdb
)
217 struct eventd_context
*ectx
;
224 if (ctdb
->ectx
== NULL
) {
225 status
= eventd_context_init(ctdb
, ctdb
, &ctdb
->ectx
);
228 ("Failed to initialize eventd context\n"));
235 if (! sock_clean(ectx
->socket
)) {
244 argv
= talloc_array(ectx
, const char *, 6);
251 argv
[0] = ectx
->path
;
253 argv
[2] = talloc_asprintf(argv
, "%d", ctdb
->ctdbd_pid
);
255 argv
[4] = talloc_asprintf(argv
, "%d", fd
[1]);
258 if (argv
[2] == NULL
|| argv
[4] == NULL
) {
265 D_NOTICE("Starting event daemon %s %s %s %s %s\n",
272 pid
= ctdb_fork(ctdb
);
282 ret
= execv(argv
[0], discard_const(argv
));
292 ret
= wait_for_daemon_startup(ctdb
->ev
, fd
[0]);
294 ctdb_kill(ctdb
, pid
, SIGKILL
);
296 D_ERR("Failed to initialize event daemon (%d)\n", ret
);
300 ectx
->eventd_fde
= tevent_add_fd(ctdb
->ev
, ectx
, fd
[0],
302 eventd_dead_handler
, ectx
);
303 if (ectx
->eventd_fde
== NULL
) {
304 ctdb_kill(ctdb
, pid
, SIGKILL
);
309 tevent_fd_set_auto_close(ectx
->eventd_fde
);
310 ectx
->eventd_pid
= pid
;
312 status
= eventd_client_connect(ectx
);
314 DEBUG(DEBUG_ERR
, ("Failed to connect to event daemon\n"));
315 ctdb_stop_eventd(ctdb
);
322 static void eventd_dead_handler(struct tevent_context
*ev
,
323 struct tevent_fd
*fde
, uint16_t flags
,
326 D_ERR("Eventd went away - exiting\n");
330 void ctdb_stop_eventd(struct ctdb_context
*ctdb
)
332 struct eventd_context
*ectx
= ctdb
->ectx
;
338 TALLOC_FREE(ectx
->eventd_fde
);
339 if (ectx
->eventd_pid
!= -1) {
340 kill(ectx
->eventd_pid
, SIGTERM
);
341 ectx
->eventd_pid
= -1;
343 TALLOC_FREE(ctdb
->ectx
);
347 * Connect to event daemon
350 struct eventd_client_state
{
351 struct eventd_client_state
*prev
, *next
;
353 struct eventd_context
*ectx
;
354 void (*callback
)(struct ctdb_event_reply
*reply
, void *private_data
);
362 static void eventd_client_read(uint8_t *buf
, size_t buflen
,
364 static int eventd_client_state_destructor(struct eventd_client_state
*state
);
366 static bool eventd_client_connect(struct eventd_context
*ectx
)
370 if (ectx
->queue
!= NULL
) {
374 fd
= sock_connect(ectx
->socket
);
379 ectx
->queue
= sock_queue_setup(ectx
, ectx
->ev
, fd
,
380 eventd_client_read
, ectx
);
381 if (ectx
->queue
== NULL
) {
389 static int eventd_client_write(struct eventd_context
*ectx
,
391 struct ctdb_event_request
*request
,
392 void (*callback
)(struct ctdb_event_reply
*reply
,
396 struct ctdb_event_header header
= { 0 };
397 struct eventd_client_state
*state
;
400 if (! eventd_client_connect(ectx
)) {
404 state
= talloc_zero(mem_ctx
, struct eventd_client_state
);
410 state
->callback
= callback
;
411 state
->private_data
= private_data
;
413 state
->reqid
= reqid_new(ectx
->idr
, state
);
414 if (state
->reqid
== REQID_INVALID
) {
419 talloc_set_destructor(state
, eventd_client_state_destructor
);
421 header
.reqid
= state
->reqid
;
423 state
->buflen
= ctdb_event_request_len(&header
, request
);
424 state
->buf
= talloc_size(state
, state
->buflen
);
425 if (state
->buf
== NULL
) {
430 ret
= ctdb_event_request_push(&header
,
439 ret
= sock_queue_write(ectx
->queue
, state
->buf
, state
->buflen
);
445 DLIST_ADD(ectx
->calls
, state
);
450 static int eventd_client_state_destructor(struct eventd_client_state
*state
)
452 struct eventd_context
*ectx
= state
->ectx
;
454 reqid_remove(ectx
->idr
, state
->reqid
);
455 DLIST_REMOVE(ectx
->calls
, state
);
459 static void eventd_client_read(uint8_t *buf
, size_t buflen
,
462 struct eventd_context
*ectx
= talloc_get_type_abort(
463 private_data
, struct eventd_context
);
464 struct eventd_client_state
*state
;
465 struct ctdb_event_header header
;
466 struct ctdb_event_reply
*reply
;
470 /* connection lost */
471 TALLOC_FREE(ectx
->queue
);
475 ret
= ctdb_event_reply_pull(buf
, buflen
, &header
, ectx
, &reply
);
477 D_ERR("Invalid packet received, ret=%d\n", ret
);
481 if (buflen
!= header
.length
) {
482 D_ERR("Packet size mismatch %zu != %"PRIu32
"\n",
483 buflen
, header
.length
);
488 state
= reqid_find(ectx
->idr
, header
.reqid
,
489 struct eventd_client_state
);
495 if (state
->reqid
!= header
.reqid
) {
500 state
= talloc_steal(reply
, state
);
501 state
->callback(reply
, state
->private_data
);
509 struct eventd_client_run_state
{
510 struct eventd_context
*ectx
;
511 void (*callback
)(int result
, void *private_data
);
515 static void eventd_client_run_done(struct ctdb_event_reply
*reply
,
518 static int eventd_client_run(struct eventd_context
*ectx
,
520 void (*callback
)(int result
,
523 enum ctdb_event event
,
527 struct eventd_client_run_state
*state
;
528 struct ctdb_event_request request
;
529 struct ctdb_event_request_run rdata
;
532 state
= talloc_zero(mem_ctx
, struct eventd_client_run_state
);
538 state
->callback
= callback
;
539 state
->private_data
= private_data
;
541 rdata
.component
= "legacy";
542 rdata
.event
= ctdb_event_to_string(event
);
543 rdata
.args
= arg_str
;
544 rdata
.timeout
= timeout
;
547 request
.cmd
= CTDB_EVENT_CMD_RUN
;
548 request
.data
.run
= &rdata
;
550 ret
= eventd_client_write(ectx
, state
, &request
,
551 eventd_client_run_done
, state
);
560 static void eventd_client_run_done(struct ctdb_event_reply
*reply
,
563 struct eventd_client_run_state
*state
= talloc_get_type_abort(
564 private_data
, struct eventd_client_run_state
);
566 state
= talloc_steal(state
->ectx
, state
);
567 state
->callback(reply
->result
, state
->private_data
);
572 * CTDB event script functions
575 int ctdb_event_script_run(struct ctdb_context
*ctdb
,
577 void (*callback
)(struct ctdb_context
*ctdb
,
578 int result
, void *private_data
),
580 enum ctdb_event event
,
581 const char *fmt
, va_list ap
)
582 PRINTF_ATTRIBUTE(6,0);
584 struct ctdb_event_script_run_state
{
585 struct ctdb_context
*ctdb
;
586 void (*callback
)(struct ctdb_context
*ctdb
, int result
,
589 enum ctdb_event event
;
592 static bool event_allowed_during_recovery(enum ctdb_event event
);
593 static void ctdb_event_script_run_done(int result
, void *private_data
);
594 static bool check_options(enum ctdb_event call
, const char *options
);
596 int ctdb_event_script_run(struct ctdb_context
*ctdb
,
598 void (*callback
)(struct ctdb_context
*ctdb
,
599 int result
, void *private_data
),
601 enum ctdb_event event
,
602 const char *fmt
, va_list ap
)
604 struct ctdb_event_script_run_state
*state
;
608 if ( (ctdb
->recovery_mode
!= CTDB_RECOVERY_NORMAL
) &&
609 (! event_allowed_during_recovery(event
)) ) {
611 ("Refusing to run event '%s' while in recovery\n",
612 ctdb_event_to_string(event
)));
616 state
= talloc_zero(mem_ctx
, struct ctdb_event_script_run_state
);
622 state
->callback
= callback
;
623 state
->private_data
= private_data
;
624 state
->event
= event
;
627 arg_str
= talloc_vasprintf(state
, fmt
, ap
);
628 if (arg_str
== NULL
) {
636 if (! check_options(event
, arg_str
)) {
638 ("Bad event script arguments '%s' for '%s'\n",
639 arg_str
, ctdb_event_to_string(event
)));
640 talloc_free(arg_str
);
644 ret
= eventd_client_run(ctdb
->ectx
, state
,
645 ctdb_event_script_run_done
, state
,
646 event
, arg_str
, ctdb
->tunable
.script_timeout
);
653 (__location__
" Running event %s with arguments %s\n",
654 ctdb_event_to_string(event
), arg_str
));
656 talloc_free(arg_str
);
660 static void ctdb_event_script_run_done(int result
, void *private_data
)
662 struct ctdb_event_script_run_state
*state
= talloc_get_type_abort(
663 private_data
, struct ctdb_event_script_run_state
);
665 if (result
== ETIMEDOUT
) {
666 switch (state
->event
) {
667 case CTDB_EVENT_START_RECOVERY
:
668 case CTDB_EVENT_RECOVERED
:
669 case CTDB_EVENT_TAKE_IP
:
670 case CTDB_EVENT_RELEASE_IP
:
672 ("Ignoring hung script for %s event\n",
673 ctdb_event_to_string(state
->event
)));
682 state
= talloc_steal(state
->ctdb
, state
);
683 state
->callback(state
->ctdb
, result
, state
->private_data
);
688 static unsigned int count_words(const char *options
)
690 unsigned int words
= 0;
692 if (options
== NULL
) {
696 options
+= strspn(options
, " \t");
699 options
+= strcspn(options
, " \t");
700 options
+= strspn(options
, " \t");
705 static bool check_options(enum ctdb_event call
, const char *options
)
708 /* These all take no arguments. */
709 case CTDB_EVENT_INIT
:
710 case CTDB_EVENT_SETUP
:
711 case CTDB_EVENT_STARTUP
:
712 case CTDB_EVENT_START_RECOVERY
:
713 case CTDB_EVENT_RECOVERED
:
714 case CTDB_EVENT_MONITOR
:
715 case CTDB_EVENT_SHUTDOWN
:
716 case CTDB_EVENT_IPREALLOCATED
:
717 case CTDB_EVENT_START_IPREALLOCATE
:
718 return count_words(options
) == 0;
720 case CTDB_EVENT_TAKE_IP
: /* interface, IP address, netmask bits. */
721 case CTDB_EVENT_RELEASE_IP
:
722 return count_words(options
) == 3;
724 case CTDB_EVENT_UPDATE_IP
: /* old interface, new interface, IP address, netmask bits. */
725 return count_words(options
) == 4;
728 DEBUG(DEBUG_ERR
,(__location__
"Unknown ctdb_event %u\n", call
));
733 /* only specific events are allowed while in recovery */
734 static bool event_allowed_during_recovery(enum ctdb_event event
)
736 const enum ctdb_event allowed_events
[] = {
739 CTDB_EVENT_START_RECOVERY
,
741 CTDB_EVENT_RELEASE_IP
,
742 CTDB_EVENT_IPREALLOCATED
,
743 CTDB_EVENT_START_IPREALLOCATE
,
747 for (i
= 0; i
< ARRAY_SIZE(allowed_events
); i
++) {
748 if (event
== allowed_events
[i
]) {
757 run the event script in the background, calling the callback when
758 finished. If mem_ctx is freed, callback will never be called.
760 int ctdb_event_script_callback(struct ctdb_context
*ctdb
,
762 void (*callback
)(struct ctdb_context
*, int, void *),
764 enum ctdb_event call
,
765 const char *fmt
, ...)
771 ret
= ctdb_event_script_run(ctdb
, mem_ctx
, callback
, private_data
,
779 struct ctdb_event_script_args_state
{
784 static void ctdb_event_script_args_done(struct ctdb_context
*ctdb
,
785 int status
, void *private_data
)
787 struct ctdb_event_script_args_state
*s
=
788 (struct ctdb_event_script_args_state
*)private_data
;
795 run the event script, waiting for it to complete. Used when the caller
796 doesn't want to continue till the event script has finished.
798 int ctdb_event_script_args(struct ctdb_context
*ctdb
, enum ctdb_event call
,
799 const char *fmt
, ...)
803 struct ctdb_event_script_args_state state
= {
809 ret
= ctdb_event_script_run(ctdb
, ctdb
,
810 ctdb_event_script_args_done
, &state
,
817 while (! state
.done
) {
818 tevent_loop_once(ctdb
->ev
);
821 if (state
.status
== ETIMEDOUT
) {
822 /* Don't ban self if CTDB is starting up or shutting down */
823 if (call
!= CTDB_EVENT_INIT
&& call
!= CTDB_EVENT_SHUTDOWN
) {
825 (__location__
" eventscript for '%s' timed out."
826 " Immediately banning ourself for %d seconds\n",
827 ctdb_event_to_string(call
),
828 ctdb
->tunable
.recovery_ban_period
));
836 int ctdb_event_script(struct ctdb_context
*ctdb
, enum ctdb_event call
)
838 /* GCC complains about empty format string, so use %s and "". */
839 return ctdb_event_script_args(ctdb
, call
, NULL
);
842 void ctdb_event_reopen_logs(struct ctdb_context
*ctdb
)
844 if (ctdb
->ectx
->eventd_pid
> 0) {
845 kill(ctdb
->ectx
->eventd_pid
, SIGHUP
);