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"
44 #include "common/path.h"
46 #include "protocol/protocol_util.h"
47 #include "event/event_protocol_api.h"
50 * Setting up event daemon
53 struct eventd_context
{
54 struct tevent_context
*ev
;
60 struct tevent_fd
*eventd_fde
;
63 struct reqid_context
*idr
;
64 struct sock_queue
*queue
;
65 struct eventd_client_state
*calls
;
68 static bool eventd_context_init(TALLOC_CTX
*mem_ctx
,
69 struct ctdb_context
*ctdb
,
70 struct eventd_context
**out
)
72 struct eventd_context
*ectx
;
73 const char *eventd
= CTDB_HELPER_BINDIR
"/ctdb-eventd";
77 ectx
= talloc_zero(mem_ctx
, struct eventd_context
);
84 value
= getenv("CTDB_EVENTD");
89 ectx
->path
= talloc_strdup(ectx
, eventd
);
90 if (ectx
->path
== NULL
) {
95 ectx
->socket
= path_socket(ectx
, "eventd");
96 if (ectx
->socket
== NULL
) {
101 ret
= reqid_init(ectx
, 1, &ectx
->idr
);
107 ectx
->eventd_pid
= -1;
113 struct eventd_startup_state
{
119 static void eventd_startup_timeout_handler(struct tevent_context
*ev
,
120 struct tevent_timer
*te
,
124 struct eventd_startup_state
*state
=
125 (struct eventd_startup_state
*) private_data
;
128 state
->ret
= ETIMEDOUT
;
131 static void eventd_startup_handler(struct tevent_context
*ev
,
132 struct tevent_fd
*fde
, uint16_t flags
,
135 struct eventd_startup_state
*state
=
136 (struct eventd_startup_state
*)private_data
;
140 num_read
= sys_read(state
->fd
, &data
, sizeof(data
));
141 if (num_read
== sizeof(data
)) {
147 } else if (num_read
== 0) {
149 } else if (num_read
== -1) {
159 static int wait_for_daemon_startup(struct tevent_context
*ev
,
163 struct tevent_timer
*timer
;
164 struct tevent_fd
*fde
;
165 struct eventd_startup_state state
= {
171 mem_ctx
= talloc_new(ev
);
172 if (mem_ctx
== NULL
) {
176 timer
= tevent_add_timer(ev
,
178 tevent_timeval_current_ofs(10, 0),
179 eventd_startup_timeout_handler
,
182 talloc_free(mem_ctx
);
186 fde
= tevent_add_fd(ev
,
190 eventd_startup_handler
,
193 talloc_free(mem_ctx
);
197 while (! state
.done
) {
198 tevent_loop_once(ev
);
201 talloc_free(mem_ctx
);
208 * Start and stop event daemon
211 static bool eventd_client_connect(struct eventd_context
*ectx
);
212 static void eventd_dead_handler(struct tevent_context
*ev
,
213 struct tevent_fd
*fde
, uint16_t flags
,
216 int ctdb_start_eventd(struct ctdb_context
*ctdb
)
218 struct eventd_context
*ectx
;
225 if (ctdb
->ectx
== NULL
) {
226 status
= eventd_context_init(ctdb
, ctdb
, &ctdb
->ectx
);
229 ("Failed to initialize eventd context\n"));
236 if (! sock_clean(ectx
->socket
)) {
245 argv
= talloc_array(ectx
, const char *, 6);
252 argv
[0] = ectx
->path
;
254 argv
[2] = talloc_asprintf(argv
, "%d", ctdb
->ctdbd_pid
);
256 argv
[4] = talloc_asprintf(argv
, "%d", fd
[1]);
259 if (argv
[2] == NULL
|| argv
[4] == NULL
) {
266 D_NOTICE("Starting event daemon %s %s %s %s %s\n",
273 pid
= ctdb_fork(ctdb
);
283 ret
= execv(argv
[0], discard_const(argv
));
293 ret
= wait_for_daemon_startup(ctdb
->ev
, fd
[0]);
295 ctdb_kill(ctdb
, pid
, SIGKILL
);
297 D_ERR("Failed to initialize event daemon (%d)\n", ret
);
301 ectx
->eventd_fde
= tevent_add_fd(ctdb
->ev
, ectx
, fd
[0],
303 eventd_dead_handler
, ectx
);
304 if (ectx
->eventd_fde
== NULL
) {
305 ctdb_kill(ctdb
, pid
, SIGKILL
);
310 tevent_fd_set_auto_close(ectx
->eventd_fde
);
311 ectx
->eventd_pid
= pid
;
313 status
= eventd_client_connect(ectx
);
315 DEBUG(DEBUG_ERR
, ("Failed to connect to event daemon\n"));
316 ctdb_stop_eventd(ctdb
);
323 static void eventd_dead_handler(struct tevent_context
*ev
,
324 struct tevent_fd
*fde
, uint16_t flags
,
327 D_ERR("Eventd went away - exiting\n");
331 void ctdb_stop_eventd(struct ctdb_context
*ctdb
)
333 struct eventd_context
*ectx
= ctdb
->ectx
;
339 TALLOC_FREE(ectx
->eventd_fde
);
340 if (ectx
->eventd_pid
!= -1) {
341 kill(ectx
->eventd_pid
, SIGTERM
);
342 ectx
->eventd_pid
= -1;
344 TALLOC_FREE(ctdb
->ectx
);
348 * Connect to event daemon
351 struct eventd_client_state
{
352 struct eventd_client_state
*prev
, *next
;
354 struct eventd_context
*ectx
;
355 void (*callback
)(struct ctdb_event_reply
*reply
, void *private_data
);
363 static void eventd_client_read(uint8_t *buf
, size_t buflen
,
365 static int eventd_client_state_destructor(struct eventd_client_state
*state
);
367 static bool eventd_client_connect(struct eventd_context
*ectx
)
371 if (ectx
->queue
!= NULL
) {
375 fd
= sock_connect(ectx
->socket
);
380 ectx
->queue
= sock_queue_setup(ectx
, ectx
->ev
, fd
,
381 eventd_client_read
, ectx
);
382 if (ectx
->queue
== NULL
) {
390 static int eventd_client_write(struct eventd_context
*ectx
,
392 struct ctdb_event_request
*request
,
393 void (*callback
)(struct ctdb_event_reply
*reply
,
397 struct ctdb_event_header header
= { 0 };
398 struct eventd_client_state
*state
;
401 if (! eventd_client_connect(ectx
)) {
405 state
= talloc_zero(mem_ctx
, struct eventd_client_state
);
411 state
->callback
= callback
;
412 state
->private_data
= private_data
;
414 state
->reqid
= reqid_new(ectx
->idr
, state
);
415 if (state
->reqid
== REQID_INVALID
) {
420 talloc_set_destructor(state
, eventd_client_state_destructor
);
422 header
.reqid
= state
->reqid
;
424 state
->buflen
= ctdb_event_request_len(&header
, request
);
425 state
->buf
= talloc_size(state
, state
->buflen
);
426 if (state
->buf
== NULL
) {
431 ret
= ctdb_event_request_push(&header
,
440 ret
= sock_queue_write(ectx
->queue
, state
->buf
, state
->buflen
);
446 DLIST_ADD(ectx
->calls
, state
);
451 static int eventd_client_state_destructor(struct eventd_client_state
*state
)
453 struct eventd_context
*ectx
= state
->ectx
;
455 reqid_remove(ectx
->idr
, state
->reqid
);
456 DLIST_REMOVE(ectx
->calls
, state
);
460 static void eventd_client_read(uint8_t *buf
, size_t buflen
,
463 struct eventd_context
*ectx
= talloc_get_type_abort(
464 private_data
, struct eventd_context
);
465 struct eventd_client_state
*state
;
466 struct ctdb_event_header header
;
467 struct ctdb_event_reply
*reply
;
471 /* connection lost */
472 TALLOC_FREE(ectx
->queue
);
476 ret
= ctdb_event_reply_pull(buf
, buflen
, &header
, ectx
, &reply
);
478 D_ERR("Invalid packet received, ret=%d\n", ret
);
482 if (buflen
!= header
.length
) {
483 D_ERR("Packet size mismatch %zu != %"PRIu32
"\n",
484 buflen
, header
.length
);
489 state
= reqid_find(ectx
->idr
, header
.reqid
,
490 struct eventd_client_state
);
496 if (state
->reqid
!= header
.reqid
) {
501 state
= talloc_steal(reply
, state
);
502 state
->callback(reply
, state
->private_data
);
510 struct eventd_client_run_state
{
511 struct eventd_context
*ectx
;
512 void (*callback
)(int result
, void *private_data
);
516 static void eventd_client_run_done(struct ctdb_event_reply
*reply
,
519 static int eventd_client_run(struct eventd_context
*ectx
,
521 void (*callback
)(int result
,
524 enum ctdb_event event
,
528 struct eventd_client_run_state
*state
;
529 struct ctdb_event_request request
;
530 struct ctdb_event_request_run rdata
;
533 state
= talloc_zero(mem_ctx
, struct eventd_client_run_state
);
539 state
->callback
= callback
;
540 state
->private_data
= private_data
;
542 rdata
.component
= "legacy";
543 rdata
.event
= ctdb_event_to_string(event
);
544 rdata
.args
= arg_str
;
545 rdata
.timeout
= timeout
;
548 request
.cmd
= CTDB_EVENT_CMD_RUN
;
549 request
.data
.run
= &rdata
;
551 ret
= eventd_client_write(ectx
, state
, &request
,
552 eventd_client_run_done
, state
);
561 static void eventd_client_run_done(struct ctdb_event_reply
*reply
,
564 struct eventd_client_run_state
*state
= talloc_get_type_abort(
565 private_data
, struct eventd_client_run_state
);
567 state
= talloc_steal(state
->ectx
, state
);
568 state
->callback(reply
->result
, state
->private_data
);
573 * CTDB event script functions
576 int ctdb_event_script_run(struct ctdb_context
*ctdb
,
578 void (*callback
)(struct ctdb_context
*ctdb
,
579 int result
, void *private_data
),
581 enum ctdb_event event
,
582 const char *fmt
, va_list ap
)
583 PRINTF_ATTRIBUTE(6,0);
585 struct ctdb_event_script_run_state
{
586 struct ctdb_context
*ctdb
;
587 void (*callback
)(struct ctdb_context
*ctdb
, int result
,
590 enum ctdb_event event
;
593 static bool event_allowed_during_recovery(enum ctdb_event event
);
594 static void ctdb_event_script_run_done(int result
, void *private_data
);
595 static bool check_options(enum ctdb_event call
, const char *options
);
597 int ctdb_event_script_run(struct ctdb_context
*ctdb
,
599 void (*callback
)(struct ctdb_context
*ctdb
,
600 int result
, void *private_data
),
602 enum ctdb_event event
,
603 const char *fmt
, va_list ap
)
605 struct ctdb_event_script_run_state
*state
;
609 if ( (ctdb
->recovery_mode
!= CTDB_RECOVERY_NORMAL
) &&
610 (! event_allowed_during_recovery(event
)) ) {
612 ("Refusing to run event '%s' while in recovery\n",
613 ctdb_eventscript_call_names
[event
]));
617 state
= talloc_zero(mem_ctx
, struct ctdb_event_script_run_state
);
623 state
->callback
= callback
;
624 state
->private_data
= private_data
;
625 state
->event
= event
;
628 arg_str
= talloc_vasprintf(state
, fmt
, ap
);
629 if (arg_str
== NULL
) {
637 if (! check_options(event
, arg_str
)) {
639 ("Bad event script arguments '%s' for '%s'\n",
640 arg_str
, ctdb_eventscript_call_names
[event
]));
641 talloc_free(arg_str
);
645 ret
= eventd_client_run(ctdb
->ectx
, state
,
646 ctdb_event_script_run_done
, state
,
647 event
, arg_str
, ctdb
->tunable
.script_timeout
);
654 (__location__
" Running event %s with arguments %s\n",
655 ctdb_eventscript_call_names
[event
], arg_str
));
657 talloc_free(arg_str
);
661 static void ctdb_event_script_run_done(int result
, void *private_data
)
663 struct ctdb_event_script_run_state
*state
= talloc_get_type_abort(
664 private_data
, struct ctdb_event_script_run_state
);
666 if (result
== ETIMEDOUT
) {
667 switch (state
->event
) {
668 case CTDB_EVENT_START_RECOVERY
:
669 case CTDB_EVENT_RECOVERED
:
670 case CTDB_EVENT_TAKE_IP
:
671 case CTDB_EVENT_RELEASE_IP
:
673 ("Ignoring hung script for %s event\n",
674 ctdb_eventscript_call_names
[state
->event
]));
683 state
= talloc_steal(state
->ctdb
, state
);
684 state
->callback(state
->ctdb
, result
, state
->private_data
);
689 static unsigned int count_words(const char *options
)
691 unsigned int words
= 0;
693 if (options
== NULL
) {
697 options
+= strspn(options
, " \t");
700 options
+= strcspn(options
, " \t");
701 options
+= strspn(options
, " \t");
706 static bool check_options(enum ctdb_event call
, const char *options
)
709 /* These all take no arguments. */
710 case CTDB_EVENT_INIT
:
711 case CTDB_EVENT_SETUP
:
712 case CTDB_EVENT_STARTUP
:
713 case CTDB_EVENT_START_RECOVERY
:
714 case CTDB_EVENT_RECOVERED
:
715 case CTDB_EVENT_MONITOR
:
716 case CTDB_EVENT_SHUTDOWN
:
717 case CTDB_EVENT_IPREALLOCATED
:
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
,
746 for (i
= 0; i
< ARRAY_SIZE(allowed_events
); i
++) {
747 if (event
== allowed_events
[i
]) {
756 run the event script in the background, calling the callback when
757 finished. If mem_ctx is freed, callback will never be called.
759 int ctdb_event_script_callback(struct ctdb_context
*ctdb
,
761 void (*callback
)(struct ctdb_context
*, int, void *),
763 enum ctdb_event call
,
764 const char *fmt
, ...)
770 ret
= ctdb_event_script_run(ctdb
, mem_ctx
, callback
, private_data
,
778 struct ctdb_event_script_args_state
{
783 static void ctdb_event_script_args_done(struct ctdb_context
*ctdb
,
784 int status
, void *private_data
)
786 struct ctdb_event_script_args_state
*s
=
787 (struct ctdb_event_script_args_state
*)private_data
;
794 run the event script, waiting for it to complete. Used when the caller
795 doesn't want to continue till the event script has finished.
797 int ctdb_event_script_args(struct ctdb_context
*ctdb
, enum ctdb_event call
,
798 const char *fmt
, ...)
802 struct ctdb_event_script_args_state state
= {
808 ret
= ctdb_event_script_run(ctdb
, ctdb
,
809 ctdb_event_script_args_done
, &state
,
816 while (! state
.done
) {
817 tevent_loop_once(ctdb
->ev
);
820 if (state
.status
== ETIMEDOUT
) {
821 /* Don't ban self if CTDB is starting up or shutting down */
822 if (call
!= CTDB_EVENT_INIT
&& call
!= CTDB_EVENT_SHUTDOWN
) {
824 (__location__
" eventscript for '%s' timed out."
825 " Immediately banning ourself for %d seconds\n",
826 ctdb_eventscript_call_names
[call
],
827 ctdb
->tunable
.recovery_ban_period
));
835 int ctdb_event_script(struct ctdb_context
*ctdb
, enum ctdb_event call
)
837 /* GCC complains about empty format string, so use %s and "". */
838 return ctdb_event_script_args(ctdb
, call
, NULL
);