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/>.
22 #include "system/filesys.h"
23 #include "system/wait.h"
24 #include "system/dir.h"
25 #include "system/locale.h"
26 #include "../include/ctdb_private.h"
27 #include "../common/rb_tree.h"
28 #include "lib/util/dlinklist.h"
30 static void ctdb_event_script_timeout(struct event_context
*ev
, struct timed_event
*te
, struct timeval t
, void *p
);
32 /* This is attached to the event script state. */
33 struct event_script_callback
{
34 struct event_script_callback
*next
, *prev
;
35 struct ctdb_context
*ctdb
;
37 /* Warning: this can free us! */
38 void (*fn
)(struct ctdb_context
*, int, void *);
42 struct ctdb_event_script_state
{
43 struct ctdb_context
*ctdb
;
44 struct event_script_callback
*callback
;
47 enum ctdb_eventscript_call call
;
49 struct timeval timeout
;
52 struct ctdb_scripts_wire
*scripts
;
55 static struct ctdb_script_wire
*get_current_script(struct ctdb_event_script_state
*state
)
57 return &state
->scripts
->scripts
[state
->current
];
60 /* called from ctdb_logging when we have received output on STDERR from
61 * one of the eventscripts
63 static void log_event_script_output(const char *str
, uint16_t len
, void *p
)
65 struct ctdb_event_script_state
*state
66 = talloc_get_type(p
, struct ctdb_event_script_state
);
67 struct ctdb_script_wire
*current
;
68 unsigned int slen
, min
;
70 /* We may have been aborted to run something else. Discard */
71 if (state
->scripts
== NULL
) {
75 current
= get_current_script(state
);
77 /* Append, but don't overfill buffer. It starts zero-filled. */
78 slen
= strlen(current
->output
);
79 min
= MIN(len
, sizeof(current
->output
) - slen
- 1);
81 memcpy(current
->output
+ slen
, str
, min
);
84 int32_t ctdb_control_get_event_script_status(struct ctdb_context
*ctdb
,
88 if (call_type
>= CTDB_EVENT_MAX
) {
92 if (ctdb
->last_status
[call_type
] == NULL
) {
93 /* If it's never been run, return nothing so they can tell. */
96 outdata
->dsize
= talloc_get_size(ctdb
->last_status
[call_type
]);
97 outdata
->dptr
= (uint8_t *)ctdb
->last_status
[call_type
];
102 /* To ignore directory entry return 0, else return non-zero */
103 static int script_filter(const struct dirent
*de
)
105 int namelen
= strlen(de
->d_name
);
107 /* Ignore . and .. */
112 /* Skip temporary files left behind by emacs */
113 if (de
->d_name
[namelen
-1] == '~') {
117 /* Filename should start with [0-9][0-9]. */
118 if (!isdigit(de
->d_name
[0]) || !isdigit(de
->d_name
[1]) ||
119 de
->d_name
[2] != '.') {
123 if (namelen
> MAX_SCRIPT_NAME
) {
130 /* Return true if OK, otherwise set errno. */
131 static bool check_executable(const char *dir
, const char *name
)
136 full
= talloc_asprintf(NULL
, "%s/%s", dir
, name
);
140 if (stat(full
, &st
) != 0) {
141 DEBUG(DEBUG_ERR
,("Could not stat event script %s: %s\n",
142 full
, strerror(errno
)));
147 if (!(st
.st_mode
& S_IXUSR
)) {
148 DEBUG(DEBUG_DEBUG
,("Event script %s is not executable. Ignoring this event script\n", full
));
158 static struct ctdb_scripts_wire
*ctdb_get_script_list(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
)
160 struct dirent
**namelist
;
161 struct ctdb_scripts_wire
*scripts
;
164 /* scan all directory entries and insert all valid scripts into the
167 count
= scandir(ctdb
->event_script_dir
, &namelist
, script_filter
, alphasort
);
169 DEBUG(DEBUG_CRIT
, ("Failed to read event script directory '%s' - %s\n",
170 ctdb
->event_script_dir
, strerror(errno
)));
174 /* Overallocates by one, but that's OK */
175 scripts
= talloc_zero_size(mem_ctx
,
177 + sizeof(scripts
->scripts
[0]) * count
);
178 if (scripts
== NULL
) {
179 DEBUG(DEBUG_ERR
, (__location__
" Failed to allocate scripts\n"));
182 scripts
->num_scripts
= count
;
184 for (i
= 0; i
< count
; i
++) {
185 struct ctdb_script_wire
*s
= &scripts
->scripts
[i
];
187 if (strlcpy(s
->name
, namelist
[i
]->d_name
, sizeof(s
->name
)) >=
189 s
->status
= -ENAMETOOLONG
;
194 if (!check_executable(ctdb
->event_script_dir
,
195 namelist
[i
]->d_name
)) {
201 for (i
=0; i
<count
; i
++) {
209 /* There cannot be more than 10 arguments to command helper. */
210 #define MAX_HELPER_ARGS (10)
212 static bool child_helper_args(TALLOC_CTX
*mem_ctx
, struct ctdb_context
*ctdb
,
213 enum ctdb_eventscript_call call
,
215 struct ctdb_script_wire
*current
, int fd
,
216 int *argc
, const char ***argv
)
220 char *t
, *saveptr
, *opt
;
222 tmp
= talloc_array(mem_ctx
, const char *, 10+1);
223 if (tmp
== NULL
) goto failed
;
225 tmp
[0] = talloc_asprintf(tmp
, "%d", fd
);
226 tmp
[1] = talloc_asprintf(tmp
, "%s/%s", ctdb
->event_script_dir
, current
->name
);
227 tmp
[2] = talloc_asprintf(tmp
, "%s", ctdb_eventscript_call_names
[call
]);
230 /* Split options into individual arguments */
231 opt
= talloc_strdup(mem_ctx
, options
);
236 t
= strtok_r(opt
, " ", &saveptr
);
238 tmp
[n
++] = talloc_strdup(tmp
, t
);
239 if (n
> MAX_HELPER_ARGS
) {
242 t
= strtok_r(NULL
, " ", &saveptr
);
245 for (i
=0; i
<n
; i
++) {
246 if (tmp
[i
] == NULL
) {
251 /* Last argument should be NULL */
260 DEBUG(DEBUG_ERR
, (__location__
" too many arguments '%s' to eventscript '%s'\n",
261 options
, ctdb_eventscript_call_names
[call
]));
271 static void ctdb_event_script_handler(struct event_context
*ev
, struct fd_event
*fde
,
272 uint16_t flags
, void *p
);
274 static char helper_prog
[PATH_MAX
+1] = "";
276 static int fork_child_for_script(struct ctdb_context
*ctdb
,
277 struct ctdb_event_script_state
*state
)
280 struct tevent_fd
*fde
;
281 struct ctdb_script_wire
*current
= get_current_script(state
);
285 if (!ctdb_set_helper("event helper", helper_prog
, sizeof(helper_prog
),
287 CTDB_HELPER_BINDIR
, "ctdb_event_helper")) {
288 ctdb_die(ctdb
, __location__
289 " Unable to set event helper\n");
292 current
->start
= timeval_current();
296 DEBUG(DEBUG_ERR
, (__location__
" pipe failed for child eventscript process\n"));
300 /* Arguments for helper */
301 if (!child_helper_args(state
, ctdb
, state
->call
, state
->options
, current
,
302 state
->fd
[1], &argc
, &argv
)) {
303 DEBUG(DEBUG_ERR
, (__location__
" failed to create arguments for eventscript helper\n"));
310 if (!ctdb_vfork_with_logging(state
, ctdb
, current
->name
,
311 helper_prog
, argc
, argv
,
312 log_event_script_output
,
313 state
, &state
->child
)) {
324 set_close_on_exec(state
->fd
[0]);
326 /* Set ourselves up to be called when that's done. */
327 fde
= event_add_fd(ctdb
->ev
, state
, state
->fd
[0], EVENT_FD_READ
,
328 ctdb_event_script_handler
, state
);
329 tevent_fd_set_auto_close(fde
);
335 Summarize status of this run of scripts.
337 static int script_status(struct ctdb_scripts_wire
*scripts
)
341 for (i
= 0; i
< scripts
->num_scripts
; i
++) {
342 switch (scripts
->scripts
[i
].status
) {
346 /* Disabled or missing; that's OK. */
352 return scripts
->scripts
[i
].status
;
360 /* called when child is finished */
361 static void ctdb_event_script_handler(struct event_context
*ev
, struct fd_event
*fde
,
362 uint16_t flags
, void *p
)
364 struct ctdb_event_script_state
*state
=
365 talloc_get_type(p
, struct ctdb_event_script_state
);
366 struct ctdb_script_wire
*current
= get_current_script(state
);
367 struct ctdb_context
*ctdb
= state
->ctdb
;
371 DEBUG(DEBUG_ERR
,("Eventscript finished but ctdb is NULL\n"));
375 r
= sys_read(state
->fd
[0], ¤t
->status
, sizeof(current
->status
));
377 current
->status
= -errno
;
379 current
->status
= -EINTR
;
380 } else if (r
!= sizeof(current
->status
)) {
381 current
->status
= -EIO
;
384 current
->finished
= timeval_current();
385 /* valgrind gets overloaded if we run next script as it's still doing
386 * post-execution analysis, so kill finished child here. */
387 if (ctdb
->valgrinding
) {
388 ctdb_kill(ctdb
, state
->child
, SIGKILL
);
393 status
= script_status(state
->scripts
);
395 /* Aborted or finished all scripts? We're done. */
396 if (status
!= 0 || state
->current
+1 == state
->scripts
->num_scripts
) {
399 ("Eventscript %s %s finished with state %d\n",
400 ctdb_eventscript_call_names
[state
->call
],
401 state
->options
, status
));
404 ctdb
->event_script_timeouts
= 0;
409 /* Forget about that old fd. */
415 current
->status
= fork_child_for_script(ctdb
, state
);
416 if (current
->status
!= 0) {
417 /* This calls the callback. */
422 struct debug_hung_script_state
{
423 struct ctdb_context
*ctdb
;
425 enum ctdb_eventscript_call call
;
428 static int debug_hung_script_state_destructor(struct debug_hung_script_state
*state
)
431 ctdb_kill(state
->ctdb
, state
->child
, SIGKILL
);
436 static void debug_hung_script_timeout(struct tevent_context
*ev
, struct tevent_timer
*te
,
437 struct timeval t
, void *p
)
439 struct debug_hung_script_state
*state
=
440 talloc_get_type(p
, struct debug_hung_script_state
);
445 static void debug_hung_script_done(struct tevent_context
*ev
, struct tevent_fd
*fde
,
446 uint16_t flags
, void *p
)
448 struct debug_hung_script_state
*state
=
449 talloc_get_type(p
, struct debug_hung_script_state
);
454 static void ctdb_run_debug_hung_script(struct ctdb_context
*ctdb
, struct debug_hung_script_state
*state
)
457 const char * debug_hung_script
= CTDB_ETCDIR
"/debug-hung-script.sh";
459 struct tevent_timer
*ttimer
;
460 struct tevent_fd
*tfd
;
465 DEBUG(DEBUG_ERR
,("Failed to create pipe fd for debug hung script\n"));
469 if (getenv("CTDB_DEBUG_HUNG_SCRIPT") != NULL
) {
470 debug_hung_script
= getenv("CTDB_DEBUG_HUNG_SCRIPT");
473 argv
= talloc_array(state
, const char *, 5);
475 argv
[0] = talloc_asprintf(argv
, "%d", fd
[1]);
476 argv
[1] = talloc_strdup(argv
, debug_hung_script
);
477 argv
[2] = talloc_asprintf(argv
, "%d", state
->child
);
478 argv
[3] = talloc_strdup(argv
, ctdb_eventscript_call_names
[state
->call
]);
481 for (i
=0; i
<4; i
++) {
482 if (argv
[i
] == NULL
) {
491 if (!ctdb_vfork_with_logging(state
, ctdb
, "Hung-script",
492 helper_prog
, 5, argv
, NULL
, NULL
, &pid
)) {
493 DEBUG(DEBUG_ERR
,("Failed to fork a child to track hung event script\n"));
503 ttimer
= tevent_add_timer(ctdb
->ev
, state
,
504 timeval_current_ofs(ctdb
->tunable
.script_timeout
, 0),
505 debug_hung_script_timeout
, state
);
506 if (ttimer
== NULL
) {
511 tfd
= tevent_add_fd(ctdb
->ev
, state
, fd
[0], EVENT_FD_READ
,
512 debug_hung_script_done
, state
);
518 tevent_fd_set_auto_close(tfd
);
521 /* called when child times out */
522 static void ctdb_event_script_timeout(struct event_context
*ev
, struct timed_event
*te
,
523 struct timeval t
, void *p
)
525 struct ctdb_event_script_state
*state
= talloc_get_type(p
, struct ctdb_event_script_state
);
526 struct ctdb_context
*ctdb
= state
->ctdb
;
527 struct ctdb_script_wire
*current
= get_current_script(state
);
528 struct debug_hung_script_state
*debug_state
;
530 DEBUG(DEBUG_ERR
,("Event script '%s %s %s' timed out after %.1fs, count: %u, pid: %d\n",
531 current
->name
, ctdb_eventscript_call_names
[state
->call
], state
->options
,
532 timeval_elapsed(¤t
->start
),
533 ctdb
->event_script_timeouts
, state
->child
));
535 /* ignore timeouts for these events */
536 switch (state
->call
) {
537 case CTDB_EVENT_START_RECOVERY
:
538 case CTDB_EVENT_RECOVERED
:
539 case CTDB_EVENT_TAKE_IP
:
540 case CTDB_EVENT_RELEASE_IP
:
541 state
->scripts
->scripts
[state
->current
].status
= 0;
542 DEBUG(DEBUG_ERR
,("Ignoring hung script for %s call %d\n", state
->options
, state
->call
));
545 state
->scripts
->scripts
[state
->current
].status
= -ETIME
;
548 debug_state
= talloc_zero(ctdb
, struct debug_hung_script_state
);
549 if (debug_state
== NULL
) {
554 /* Save information useful for running debug hung script, so
555 * eventscript state can be freed.
557 debug_state
->ctdb
= ctdb
;
558 debug_state
->child
= state
->child
;
559 debug_state
->call
= state
->call
;
561 /* This destructor will actually kill the hung event script */
562 talloc_set_destructor(debug_state
, debug_hung_script_state_destructor
);
567 ctdb_run_debug_hung_script(ctdb
, debug_state
);
571 destroy an event script: kill it if ->child != 0.
573 static int event_script_destructor(struct ctdb_event_script_state
*state
)
576 struct event_script_callback
*callback
;
579 DEBUG(DEBUG_ERR
,(__location__
" Sending SIGTERM to child pid:%d\n", state
->child
));
581 if (ctdb_kill(state
->ctdb
, state
->child
, SIGTERM
) != 0) {
582 DEBUG(DEBUG_ERR
,("Failed to kill child process for eventscript, errno %s(%d)\n", strerror(errno
), errno
));
586 /* If we were the current monitor, we no longer are. */
587 if (state
->ctdb
->current_monitor
== state
) {
588 state
->ctdb
->current_monitor
= NULL
;
591 /* Save our scripts as the last executed status, if we have them.
592 * See ctdb_event_script_callback_v where we abort monitor event. */
593 if (state
->scripts
) {
594 talloc_free(state
->ctdb
->last_status
[state
->call
]);
595 state
->ctdb
->last_status
[state
->call
] = state
->scripts
;
596 if (state
->current
< state
->ctdb
->last_status
[state
->call
]->num_scripts
) {
597 state
->ctdb
->last_status
[state
->call
]->num_scripts
= state
->current
+1;
601 /* Use last status as result, or "OK" if none. */
602 if (state
->ctdb
->last_status
[state
->call
]) {
603 status
= script_status(state
->ctdb
->last_status
[state
->call
]);
608 state
->ctdb
->active_events
--;
609 if (state
->ctdb
->active_events
< 0) {
610 ctdb_fatal(state
->ctdb
, "Active events < 0");
613 /* This is allowed to free us; talloc will prevent double free anyway,
614 * but beware if you call this outside the destructor!
615 * the callback hangs off a different context so we walk the list
616 * of "active" callbacks until we find the one state points to.
617 * if we cant find it it means the callback has been removed.
619 for (callback
= state
->ctdb
->script_callbacks
; callback
!= NULL
; callback
= callback
->next
) {
620 if (callback
== state
->callback
) {
625 state
->callback
= NULL
;
628 /* Make sure destructor doesn't free itself! */
629 talloc_steal(NULL
, callback
);
630 callback
->fn(state
->ctdb
, status
, callback
->private_data
);
631 talloc_free(callback
);
637 static unsigned int count_words(const char *options
)
639 unsigned int words
= 0;
641 options
+= strspn(options
, " \t");
644 options
+= strcspn(options
, " \t");
645 options
+= strspn(options
, " \t");
650 static bool check_options(enum ctdb_eventscript_call call
, const char *options
)
653 /* These all take no arguments. */
654 case CTDB_EVENT_INIT
:
655 case CTDB_EVENT_SETUP
:
656 case CTDB_EVENT_STARTUP
:
657 case CTDB_EVENT_START_RECOVERY
:
658 case CTDB_EVENT_RECOVERED
:
659 case CTDB_EVENT_MONITOR
:
660 case CTDB_EVENT_SHUTDOWN
:
661 case CTDB_EVENT_IPREALLOCATED
:
662 return count_words(options
) == 0;
664 case CTDB_EVENT_TAKE_IP
: /* interface, IP address, netmask bits. */
665 case CTDB_EVENT_RELEASE_IP
:
666 return count_words(options
) == 3;
668 case CTDB_EVENT_UPDATE_IP
: /* old interface, new interface, IP address, netmask bits. */
669 return count_words(options
) == 4;
672 DEBUG(DEBUG_ERR
,(__location__
"Unknown ctdb_eventscript_call %u\n", call
));
677 static int remove_callback(struct event_script_callback
*callback
)
679 DLIST_REMOVE(callback
->ctdb
->script_callbacks
, callback
);
684 run the event script in the background, calling the callback when
687 static int ctdb_event_script_callback_v(struct ctdb_context
*ctdb
,
689 void (*callback
)(struct ctdb_context
*, int, void *),
691 enum ctdb_eventscript_call call
,
692 const char *fmt
, va_list ap
)
694 struct ctdb_event_script_state
*state
;
696 if (ctdb
->recovery_mode
!= CTDB_RECOVERY_NORMAL
) {
697 /* we guarantee that only some specifically allowed event scripts are run
699 const enum ctdb_eventscript_call allowed_calls
[] = {
702 CTDB_EVENT_START_RECOVERY
,
704 CTDB_EVENT_RELEASE_IP
,
705 CTDB_EVENT_IPREALLOCATED
,
708 for (i
=0;i
<ARRAY_SIZE(allowed_calls
);i
++) {
709 if (call
== allowed_calls
[i
]) break;
711 if (i
== ARRAY_SIZE(allowed_calls
)) {
712 DEBUG(DEBUG_ERR
,("Refusing to run event scripts call '%s' while in recovery\n",
713 ctdb_eventscript_call_names
[call
]));
718 /* Do not run new monitor events if some event is already running */
719 if (call
== CTDB_EVENT_MONITOR
&& ctdb
->active_events
> 0) {
720 if (callback
!= NULL
) {
721 callback(ctdb
, -ECANCELED
, private_data
);
726 /* Kill off any running monitor events to run this event. */
727 if (ctdb
->current_monitor
) {
728 struct ctdb_event_script_state
*ms
= talloc_get_type(ctdb
->current_monitor
, struct ctdb_event_script_state
);
730 /* Cancel current monitor callback state only if monitoring
731 * context ctdb->monitor->monitor_context has not been freed */
732 if (ms
->callback
!= NULL
&& !ctdb_stopped_monitoring(ctdb
)) {
733 ms
->callback
->fn(ctdb
, -ECANCELED
, ms
->callback
->private_data
);
734 talloc_free(ms
->callback
);
737 /* Discard script status so we don't save to last_status */
738 talloc_free(ctdb
->current_monitor
->scripts
);
739 ctdb
->current_monitor
->scripts
= NULL
;
740 talloc_free(ctdb
->current_monitor
);
741 ctdb
->current_monitor
= NULL
;
744 state
= talloc(ctdb
->event_script_ctx
, struct ctdb_event_script_state
);
745 CTDB_NO_MEMORY(ctdb
, state
);
747 /* The callback isn't done if the context is freed. */
748 state
->callback
= talloc(mem_ctx
, struct event_script_callback
);
749 CTDB_NO_MEMORY(ctdb
, state
->callback
);
750 DLIST_ADD(ctdb
->script_callbacks
, state
->callback
);
751 talloc_set_destructor(state
->callback
, remove_callback
);
752 state
->callback
->ctdb
= ctdb
;
753 state
->callback
->fn
= callback
;
754 state
->callback
->private_data
= private_data
;
758 state
->options
= talloc_vasprintf(state
, fmt
, ap
);
759 state
->timeout
= timeval_set(ctdb
->tunable
.script_timeout
, 0);
760 state
->scripts
= NULL
;
761 if (state
->options
== NULL
) {
762 DEBUG(DEBUG_ERR
, (__location__
" could not allocate state->options\n"));
766 if (!check_options(state
->call
, state
->options
)) {
767 DEBUG(DEBUG_ERR
, ("Bad eventscript options '%s' for '%s'\n",
769 ctdb_eventscript_call_names
[state
->call
]));
774 DEBUG(DEBUG_INFO
,(__location__
" Starting eventscript %s %s\n",
775 ctdb_eventscript_call_names
[state
->call
],
778 /* This is not a child of state, since we save it in destructor. */
779 state
->scripts
= ctdb_get_script_list(ctdb
, ctdb
);
780 if (state
->scripts
== NULL
) {
787 if (call
== CTDB_EVENT_MONITOR
) {
788 ctdb
->current_monitor
= state
;
791 talloc_set_destructor(state
, event_script_destructor
);
793 ctdb
->active_events
++;
796 if (state
->scripts
->num_scripts
== 0) {
801 state
->scripts
->scripts
[0].status
= fork_child_for_script(ctdb
, state
);
802 if (state
->scripts
->scripts
[0].status
!= 0) {
803 /* Callback is called from destructor, with fail result. */
808 if (!timeval_is_zero(&state
->timeout
)) {
809 event_add_timed(ctdb
->ev
, state
, timeval_current_ofs(state
->timeout
.tv_sec
, state
->timeout
.tv_usec
), ctdb_event_script_timeout
, state
);
811 DEBUG(DEBUG_ERR
, (__location__
" eventscript %s %s called with no timeout\n",
812 ctdb_eventscript_call_names
[state
->call
],
821 run the event script in the background, calling the callback when
822 finished. If mem_ctx is freed, callback will never be called.
824 int ctdb_event_script_callback(struct ctdb_context
*ctdb
,
826 void (*callback
)(struct ctdb_context
*, int, void *),
828 enum ctdb_eventscript_call call
,
829 const char *fmt
, ...)
835 ret
= ctdb_event_script_callback_v(ctdb
, mem_ctx
, callback
, private_data
, call
, fmt
, ap
);
842 struct callback_status
{
848 called when ctdb_event_script() finishes
850 static void event_script_callback(struct ctdb_context
*ctdb
, int status
, void *private_data
)
852 struct callback_status
*s
= (struct callback_status
*)private_data
;
858 run the event script, waiting for it to complete. Used when the caller
859 doesn't want to continue till the event script has finished.
861 int ctdb_event_script_args(struct ctdb_context
*ctdb
, enum ctdb_eventscript_call call
,
862 const char *fmt
, ...)
866 struct callback_status status
;
869 ret
= ctdb_event_script_callback_v(ctdb
, ctdb
,
870 event_script_callback
, &status
, call
, fmt
, ap
);
879 while (status
.done
== false && event_loop_once(ctdb
->ev
) == 0) /* noop */;
881 if (status
.status
== -ETIME
) {
882 DEBUG(DEBUG_ERR
, (__location__
" eventscript for '%s' timedout."
883 " Immediately banning ourself for %d seconds\n",
884 ctdb_eventscript_call_names
[call
],
885 ctdb
->tunable
.recovery_ban_period
));
887 /* Don't ban self if CTDB is starting up or shutting down */
888 if (call
!= CTDB_EVENT_INIT
&& call
!= CTDB_EVENT_SHUTDOWN
) {
893 return status
.status
;
896 int ctdb_event_script(struct ctdb_context
*ctdb
, enum ctdb_eventscript_call call
)
898 /* GCC complains about empty format string, so use %s and "". */
899 return ctdb_event_script_args(ctdb
, call
, "%s", "");
902 struct eventscript_callback_state
{
903 struct ctdb_req_control
*c
;
907 called when a forced eventscript run has finished
909 static void run_eventscripts_callback(struct ctdb_context
*ctdb
, int status
,
912 struct eventscript_callback_state
*state
=
913 talloc_get_type(private_data
, struct eventscript_callback_state
);
916 DEBUG(DEBUG_ERR
,(__location__
" Failed to run eventscripts\n"));
919 ctdb_request_control_reply(ctdb
, state
->c
, NULL
, status
, NULL
);
920 /* This will free the struct ctdb_event_script_state we are in! */
926 /* Returns rest of string, or NULL if no match. */
927 static const char *get_call(const char *p
, enum ctdb_eventscript_call
*call
)
931 /* Skip any initial whitespace. */
932 p
+= strspn(p
, " \t");
934 /* See if we match any. */
935 for (*call
= 0; *call
< CTDB_EVENT_MAX
; (*call
)++) {
936 len
= strlen(ctdb_eventscript_call_names
[*call
]);
937 if (strncmp(p
, ctdb_eventscript_call_names
[*call
], len
) == 0) {
938 /* If end of string or whitespace, we're done. */
939 if (strcspn(p
+ len
, " \t") == 0) {
948 A control to force running of the eventscripts from the ctdb client tool
950 int32_t ctdb_run_eventscripts(struct ctdb_context
*ctdb
,
951 struct ctdb_req_control
*c
,
952 TDB_DATA indata
, bool *async_reply
)
955 struct eventscript_callback_state
*state
;
957 enum ctdb_eventscript_call call
;
959 /* Figure out what call they want. */
960 options
= get_call((const char *)indata
.dptr
, &call
);
962 DEBUG(DEBUG_ERR
, (__location__
" Invalid event name \"%s\"\n", (const char *)indata
.dptr
));
966 if (ctdb
->recovery_mode
!= CTDB_RECOVERY_NORMAL
) {
967 DEBUG(DEBUG_ERR
, (__location__
" Aborted running eventscript \"%s\" while in RECOVERY mode\n", indata
.dptr
));
971 state
= talloc(ctdb
->event_script_ctx
, struct eventscript_callback_state
);
972 CTDB_NO_MEMORY(ctdb
, state
);
974 state
->c
= talloc_steal(state
, c
);
976 DEBUG(DEBUG_NOTICE
,("Running eventscripts with arguments %s\n", indata
.dptr
));
978 ret
= ctdb_event_script_callback(ctdb
,
979 state
, run_eventscripts_callback
, state
,
980 call
, "%s", options
);
983 DEBUG(DEBUG_ERR
,(__location__
" Failed to run eventscripts with arguments %s\n", indata
.dptr
));
988 /* tell ctdb_control.c that we will be replying asynchronously */
996 int32_t ctdb_control_enable_script(struct ctdb_context
*ctdb
, TDB_DATA indata
)
1001 TALLOC_CTX
*tmp_ctx
= talloc_new(ctdb
);
1003 script
= (char *)indata
.dptr
;
1004 if (indata
.dsize
== 0) {
1005 DEBUG(DEBUG_ERR
,(__location__
" No script specified.\n"));
1006 talloc_free(tmp_ctx
);
1009 if (indata
.dptr
[indata
.dsize
- 1] != '\0') {
1010 DEBUG(DEBUG_ERR
,(__location__
" String is not null terminated.\n"));
1011 talloc_free(tmp_ctx
);
1014 if (index(script
,'/') != NULL
) {
1015 DEBUG(DEBUG_ERR
,(__location__
" Script name contains '/'. Failed to enable script %s\n", script
));
1016 talloc_free(tmp_ctx
);
1021 if (stat(ctdb
->event_script_dir
, &st
) != 0 &&
1023 DEBUG(DEBUG_CRIT
,("No event script directory found at '%s'\n", ctdb
->event_script_dir
));
1024 talloc_free(tmp_ctx
);
1029 filename
= talloc_asprintf(tmp_ctx
, "%s/%s", ctdb
->event_script_dir
, script
);
1030 if (filename
== NULL
) {
1031 DEBUG(DEBUG_ERR
,(__location__
" Failed to create script path\n"));
1032 talloc_free(tmp_ctx
);
1036 if (stat(filename
, &st
) != 0) {
1037 DEBUG(DEBUG_ERR
,("Could not stat event script %s. Failed to enable script.\n", filename
));
1038 talloc_free(tmp_ctx
);
1042 if (chmod(filename
, st
.st_mode
| S_IXUSR
) == -1) {
1043 DEBUG(DEBUG_ERR
,("Could not chmod %s. Failed to enable script.\n", filename
));
1044 talloc_free(tmp_ctx
);
1048 talloc_free(tmp_ctx
);
1052 int32_t ctdb_control_disable_script(struct ctdb_context
*ctdb
, TDB_DATA indata
)
1057 TALLOC_CTX
*tmp_ctx
= talloc_new(ctdb
);
1059 script
= (char *)indata
.dptr
;
1060 if (indata
.dsize
== 0) {
1061 DEBUG(DEBUG_ERR
,(__location__
" No script specified.\n"));
1062 talloc_free(tmp_ctx
);
1065 if (indata
.dptr
[indata
.dsize
- 1] != '\0') {
1066 DEBUG(DEBUG_ERR
,(__location__
" String is not null terminated.\n"));
1067 talloc_free(tmp_ctx
);
1070 if (index(script
,'/') != NULL
) {
1071 DEBUG(DEBUG_ERR
,(__location__
" Script name contains '/'. Failed to disable script %s\n", script
));
1072 talloc_free(tmp_ctx
);
1077 if (stat(ctdb
->event_script_dir
, &st
) != 0 &&
1079 DEBUG(DEBUG_CRIT
,("No event script directory found at '%s'\n", ctdb
->event_script_dir
));
1080 talloc_free(tmp_ctx
);
1085 filename
= talloc_asprintf(tmp_ctx
, "%s/%s", ctdb
->event_script_dir
, script
);
1086 if (filename
== NULL
) {
1087 DEBUG(DEBUG_ERR
,(__location__
" Failed to create script path\n"));
1088 talloc_free(tmp_ctx
);
1092 if (stat(filename
, &st
) != 0) {
1093 DEBUG(DEBUG_ERR
,("Could not stat event script %s. Failed to disable script.\n", filename
));
1094 talloc_free(tmp_ctx
);
1098 if (chmod(filename
, st
.st_mode
& ~(S_IXUSR
|S_IXGRP
|S_IXOTH
)) == -1) {
1099 DEBUG(DEBUG_ERR
,("Could not chmod %s. Failed to disable script.\n", filename
));
1100 talloc_free(tmp_ctx
);
1104 talloc_free(tmp_ctx
);