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 sock_packet_header_set_reqid(&request
->header
, state
->reqid
);
372 state
->buflen
= ctdb_event_request_len(request
);
373 state
->buf
= talloc_size(state
, state
->buflen
);
374 if (state
->buf
== NULL
) {
379 ret
= ctdb_event_request_push(request
, state
->buf
, &state
->buflen
);
385 ret
= sock_queue_write(ectx
->queue
, state
->buf
, state
->buflen
);
391 DLIST_ADD(ectx
->calls
, state
);
396 static int eventd_client_state_destructor(struct eventd_client_state
*state
)
398 struct eventd_context
*ectx
= state
->ectx
;
400 reqid_remove(ectx
->idr
, state
->reqid
);
401 DLIST_REMOVE(ectx
->calls
, state
);
405 static void eventd_client_read(uint8_t *buf
, size_t buflen
,
408 struct eventd_context
*ectx
= talloc_get_type_abort(
409 private_data
, struct eventd_context
);
410 struct eventd_client_state
*state
;
411 struct ctdb_event_reply
*reply
;
415 /* connection lost */
416 TALLOC_FREE(ectx
->queue
);
420 reply
= talloc_zero(ectx
, struct ctdb_event_reply
);
425 ret
= ctdb_event_reply_pull(buf
, buflen
, reply
, reply
);
427 D_ERR("Invalid packet received, ret=%d\n", ret
);
432 if (buflen
!= reply
->header
.length
) {
433 D_ERR("Packet size mismatch %zu != %"PRIu32
"\n",
434 buflen
, reply
->header
.length
);
439 state
= reqid_find(ectx
->idr
, reply
->header
.reqid
,
440 struct eventd_client_state
);
446 if (state
->reqid
!= reply
->header
.reqid
) {
451 state
= talloc_steal(reply
, state
);
452 state
->callback(reply
, state
->private_data
);
460 struct eventd_client_run_state
{
461 struct eventd_context
*ectx
;
462 void (*callback
)(int result
, void *private_data
);
466 static void eventd_client_run_done(struct ctdb_event_reply
*reply
,
469 static int eventd_client_run(struct eventd_context
*ectx
,
471 void (*callback
)(int result
,
474 enum ctdb_event event
,
478 struct eventd_client_run_state
*state
;
479 struct ctdb_event_request request
;
480 struct ctdb_event_request_run rdata
;
483 state
= talloc_zero(mem_ctx
, struct eventd_client_run_state
);
489 state
->callback
= callback
;
490 state
->private_data
= private_data
;
493 rdata
.timeout
= timeout
;
494 rdata
.arg_str
= arg_str
;
496 request
.rdata
.command
= CTDB_EVENT_COMMAND_RUN
;
497 request
.rdata
.data
.run
= &rdata
;
499 ret
= eventd_client_write(ectx
, state
, &request
,
500 eventd_client_run_done
, state
);
509 static void eventd_client_run_done(struct ctdb_event_reply
*reply
,
512 struct eventd_client_run_state
*state
= talloc_get_type_abort(
513 private_data
, struct eventd_client_run_state
);
515 state
= talloc_steal(state
->ectx
, state
);
516 state
->callback(reply
->rdata
.result
, state
->private_data
);
521 * CTDB event script functions
524 int ctdb_event_script_run(struct ctdb_context
*ctdb
,
526 void (*callback
)(struct ctdb_context
*ctdb
,
527 int result
, void *private_data
),
529 enum ctdb_event event
,
530 const char *fmt
, va_list ap
)
531 PRINTF_ATTRIBUTE(6,0);
533 struct ctdb_event_script_run_state
{
534 struct ctdb_context
*ctdb
;
535 void (*callback
)(struct ctdb_context
*ctdb
, int result
,
538 enum ctdb_event event
;
541 static bool event_allowed_during_recovery(enum ctdb_event event
);
542 static void ctdb_event_script_run_done(int result
, void *private_data
);
543 static bool check_options(enum ctdb_event call
, const char *options
);
545 int ctdb_event_script_run(struct ctdb_context
*ctdb
,
547 void (*callback
)(struct ctdb_context
*ctdb
,
548 int result
, void *private_data
),
550 enum ctdb_event event
,
551 const char *fmt
, va_list ap
)
553 struct ctdb_event_script_run_state
*state
;
557 if ( (ctdb
->recovery_mode
!= CTDB_RECOVERY_NORMAL
) &&
558 (! event_allowed_during_recovery(event
)) ) {
560 ("Refusing to run event '%s' while in recovery\n",
561 ctdb_eventscript_call_names
[event
]));
564 state
= talloc_zero(mem_ctx
, struct ctdb_event_script_run_state
);
570 state
->callback
= callback
;
571 state
->private_data
= private_data
;
572 state
->event
= event
;
575 arg_str
= talloc_vasprintf(state
, fmt
, ap
);
576 if (arg_str
== NULL
) {
584 if (! check_options(event
, arg_str
)) {
586 ("Bad event script arguments '%s' for '%s'\n",
587 arg_str
, ctdb_eventscript_call_names
[event
]));
588 talloc_free(arg_str
);
592 ret
= eventd_client_run(ctdb
->ectx
, state
,
593 ctdb_event_script_run_done
, state
,
594 event
, arg_str
, ctdb
->tunable
.script_timeout
);
601 (__location__
" Running event %s with arguments %s\n",
602 ctdb_eventscript_call_names
[event
], arg_str
));
604 talloc_free(arg_str
);
608 static void ctdb_event_script_run_done(int result
, void *private_data
)
610 struct ctdb_event_script_run_state
*state
= talloc_get_type_abort(
611 private_data
, struct ctdb_event_script_run_state
);
613 if (result
== -ETIME
) {
614 switch (state
->event
) {
615 case CTDB_EVENT_START_RECOVERY
:
616 case CTDB_EVENT_RECOVERED
:
617 case CTDB_EVENT_TAKE_IP
:
618 case CTDB_EVENT_RELEASE_IP
:
620 ("Ignoring hung script for %s event\n",
621 ctdb_eventscript_call_names
[state
->event
]));
630 state
= talloc_steal(state
->ctdb
, state
);
631 state
->callback(state
->ctdb
, result
, state
->private_data
);
636 static unsigned int count_words(const char *options
)
638 unsigned int words
= 0;
640 if (options
== NULL
) {
644 options
+= strspn(options
, " \t");
647 options
+= strcspn(options
, " \t");
648 options
+= strspn(options
, " \t");
653 static bool check_options(enum ctdb_event call
, const char *options
)
656 /* These all take no arguments. */
657 case CTDB_EVENT_INIT
:
658 case CTDB_EVENT_SETUP
:
659 case CTDB_EVENT_STARTUP
:
660 case CTDB_EVENT_START_RECOVERY
:
661 case CTDB_EVENT_RECOVERED
:
662 case CTDB_EVENT_MONITOR
:
663 case CTDB_EVENT_SHUTDOWN
:
664 case CTDB_EVENT_IPREALLOCATED
:
665 return count_words(options
) == 0;
667 case CTDB_EVENT_TAKE_IP
: /* interface, IP address, netmask bits. */
668 case CTDB_EVENT_RELEASE_IP
:
669 return count_words(options
) == 3;
671 case CTDB_EVENT_UPDATE_IP
: /* old interface, new interface, IP address, netmask bits. */
672 return count_words(options
) == 4;
675 DEBUG(DEBUG_ERR
,(__location__
"Unknown ctdb_event %u\n", call
));
680 /* only specific events are allowed while in recovery */
681 static bool event_allowed_during_recovery(enum ctdb_event event
)
683 const enum ctdb_event allowed_events
[] = {
686 CTDB_EVENT_START_RECOVERY
,
688 CTDB_EVENT_RELEASE_IP
,
689 CTDB_EVENT_IPREALLOCATED
,
693 for (i
= 0; i
< ARRAY_SIZE(allowed_events
); i
++) {
694 if (event
== allowed_events
[i
]) {
703 run the event script in the background, calling the callback when
704 finished. If mem_ctx is freed, callback will never be called.
706 int ctdb_event_script_callback(struct ctdb_context
*ctdb
,
708 void (*callback
)(struct ctdb_context
*, int, void *),
710 enum ctdb_event call
,
711 const char *fmt
, ...)
717 ret
= ctdb_event_script_run(ctdb
, mem_ctx
, callback
, private_data
,
725 struct ctdb_event_script_args_state
{
730 static void ctdb_event_script_args_done(struct ctdb_context
*ctdb
,
731 int status
, void *private_data
)
733 struct ctdb_event_script_args_state
*s
=
734 (struct ctdb_event_script_args_state
*)private_data
;
741 run the event script, waiting for it to complete. Used when the caller
742 doesn't want to continue till the event script has finished.
744 int ctdb_event_script_args(struct ctdb_context
*ctdb
, enum ctdb_event call
,
745 const char *fmt
, ...)
749 struct ctdb_event_script_args_state state
= {
755 ret
= ctdb_event_script_run(ctdb
, ctdb
,
756 ctdb_event_script_args_done
, &state
,
763 while (! state
.done
) {
764 tevent_loop_once(ctdb
->ev
);
767 if (state
.status
== -ETIME
) {
768 /* Don't ban self if CTDB is starting up or shutting down */
769 if (call
!= CTDB_EVENT_INIT
&& call
!= CTDB_EVENT_SHUTDOWN
) {
771 (__location__
" eventscript for '%s' timed out."
772 " Immediately banning ourself for %d seconds\n",
773 ctdb_eventscript_call_names
[call
],
774 ctdb
->tunable
.recovery_ban_period
));
782 int ctdb_event_script(struct ctdb_context
*ctdb
, enum ctdb_event call
)
784 /* GCC complains about empty format string, so use %s and "". */
785 return ctdb_event_script_args(ctdb
, call
, NULL
);