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 "lib/events/events.h"
28 #include "../common/rb_tree.h"
32 const char *script_running;
35 static const char *call_names[] = {
47 static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *p);
50 ctdbd sends us a SIGTERM when we should time out the current script
52 static void sigterm(int sig)
54 char tbuf[100], buf[200];
57 DEBUG(DEBUG_ERR,("Timed out running script '%s' after %.1f seconds pid :%d\n",
58 child_state.script_running, timeval_elapsed(&child_state.start), getpid()));
62 strftime(tbuf, sizeof(tbuf)-1, "%Y%m%d%H%M%S", localtime(&t));
63 sprintf(buf, "pstree -p >/tmp/ctdb.event.%s.%d", tbuf, getpid());
66 DEBUG(DEBUG_ERR,("Logged timedout eventscript : %s\n", buf));
68 /* all the child processes will be running in the same process group */
69 kill(-getpgrp(), SIGKILL);
73 struct ctdb_event_script_state {
74 struct ctdb_context *ctdb;
76 /* Warning: this can free us! */
77 void (*callback)(struct ctdb_context *, int, void *);
81 enum ctdb_eventscript_call call;
83 struct timeval timeout;
87 struct ctdb_monitor_script_status {
88 struct ctdb_monitor_script_status *next;
91 struct timeval finished;
98 struct ctdb_monitor_script_status_ctx {
99 struct ctdb_monitor_script_status *scripts;
102 /* called from ctdb_logging when we have received output on STDERR from
103 * one of the eventscripts
105 int ctdb_log_event_script_output(struct ctdb_context *ctdb, char *str, uint16_t len)
107 struct ctdb_monitor_script_status *script;
109 if (ctdb->current_monitor_status_ctx == NULL) {
113 script = ctdb->current_monitor_status_ctx->scripts;
114 if (script == NULL) {
118 if (script->output == NULL) {
119 script->output = talloc_asprintf(script, "%*.*s", len, len, str);
121 script->output = talloc_asprintf_append(script->output, "%*.*s", len, len, str);
127 /* called from the event script child process when we are starting a new
130 int32_t ctdb_control_event_script_init(struct ctdb_context *ctdb)
132 DEBUG(DEBUG_INFO, ("event script init called\n"));
134 if (ctdb->current_monitor_status_ctx == NULL) {
135 DEBUG(DEBUG_ERR,(__location__ " current_monitor_status_ctx is NULL when initing script\n"));
143 /* called from the event script child process when we are star running
146 int32_t ctdb_control_event_script_start(struct ctdb_context *ctdb, TDB_DATA indata)
148 const char *name = (const char *)indata.dptr;
149 struct ctdb_monitor_script_status *script;
151 DEBUG(DEBUG_INFO, ("event script start called : %s\n", name));
153 if (ctdb->current_monitor_status_ctx == NULL) {
154 DEBUG(DEBUG_ERR,(__location__ " current_monitor_status_ctx is NULL when starting script\n"));
158 script = talloc_zero(ctdb->current_monitor_status_ctx, struct ctdb_monitor_script_status);
159 if (script == NULL) {
160 DEBUG(DEBUG_ERR,(__location__ " Failed to talloc ctdb_monitor_script_status for script %s\n", name));
164 script->next = ctdb->current_monitor_status_ctx->scripts;
165 script->name = talloc_strdup(script, name);
166 CTDB_NO_MEMORY(ctdb, script->name);
167 script->start = timeval_current();
168 ctdb->current_monitor_status_ctx->scripts = script;
173 /* called from the event script child process when we have finished running
176 int32_t ctdb_control_event_script_stop(struct ctdb_context *ctdb, TDB_DATA indata)
178 int32_t res = *((int32_t *)indata.dptr);
179 struct ctdb_monitor_script_status *script;
181 if (ctdb->current_monitor_status_ctx == NULL) {
182 DEBUG(DEBUG_ERR,(__location__ " current_monitor_status_ctx is NULL when script finished\n"));
186 script = ctdb->current_monitor_status_ctx->scripts;
187 if (script == NULL) {
188 DEBUG(DEBUG_ERR,(__location__ " script is NULL when the script had finished\n"));
192 script->finished = timeval_current();
193 script->status = res;
195 DEBUG(DEBUG_INFO, ("event script stop called for script:%s duration:%.1f status:%d\n", script->name, timeval_elapsed(&script->start), (int)res));
200 /* called from the event script child process when we have a disabled script
202 int32_t ctdb_control_event_script_disabled(struct ctdb_context *ctdb, TDB_DATA indata)
204 const char *name = (const char *)indata.dptr;
205 struct ctdb_monitor_script_status *script;
207 DEBUG(DEBUG_INFO, ("event script disabed called for script %s\n", name));
209 if (ctdb->current_monitor_status_ctx == NULL) {
210 DEBUG(DEBUG_ERR,(__location__ " current_monitor_status_ctx is NULL when script finished\n"));
214 script = ctdb->current_monitor_status_ctx->scripts;
215 if (script == NULL) {
216 DEBUG(DEBUG_ERR,(__location__ " script is NULL when the script had finished\n"));
220 script->finished = timeval_current();
222 script->disabled = 1;
227 /* called from the event script child process when we have completed a
230 int32_t ctdb_control_event_script_finished(struct ctdb_context *ctdb)
232 DEBUG(DEBUG_INFO, ("event script finished called\n"));
234 if (ctdb->current_monitor_status_ctx == NULL) {
235 DEBUG(DEBUG_ERR,(__location__ " script_status is NULL when monitoring event finished\n"));
239 if (ctdb->last_monitor_status_ctx) {
240 talloc_free(ctdb->last_monitor_status_ctx);
241 ctdb->last_monitor_status_ctx = NULL;
243 ctdb->last_monitor_status_ctx = talloc_steal(ctdb, ctdb->current_monitor_status_ctx);
244 ctdb->current_monitor_status_ctx = NULL;
249 static struct ctdb_monitoring_wire *marshall_monitoring_scripts(TALLOC_CTX *mem_ctx, struct ctdb_monitoring_wire *monitoring_scripts, struct ctdb_monitor_script_status *script)
251 struct ctdb_monitoring_script_wire script_wire;
254 if (script == NULL) {
255 return monitoring_scripts;
257 monitoring_scripts = marshall_monitoring_scripts(mem_ctx, monitoring_scripts, script->next);
258 if (monitoring_scripts == NULL) {
262 bzero(&script_wire, sizeof(struct ctdb_monitoring_script_wire));
263 strncpy(script_wire.name, script->name, MAX_SCRIPT_NAME);
264 script_wire.start = script->start;
265 script_wire.finished = script->finished;
266 script_wire.disabled = script->disabled;
267 script_wire.status = script->status;
268 script_wire.timedout = script->timedout;
269 if (script->output != NULL) {
270 strncpy(script_wire.output, script->output, MAX_SCRIPT_OUTPUT);
273 size = talloc_get_size(monitoring_scripts);
274 monitoring_scripts = talloc_realloc_size(mem_ctx, monitoring_scripts, size + sizeof(struct ctdb_monitoring_script_wire));
275 if (monitoring_scripts == NULL) {
276 DEBUG(DEBUG_ERR,(__location__ " Failed to talloc_resize monitoring_scripts blob\n"));
280 memcpy(&monitoring_scripts->scripts[monitoring_scripts->num_scripts], &script_wire, sizeof(script_wire));
281 monitoring_scripts->num_scripts++;
283 return monitoring_scripts;
286 int32_t ctdb_control_get_event_script_status(struct ctdb_context *ctdb, TDB_DATA *outdata)
288 struct ctdb_monitor_script_status_ctx *script_status = talloc_get_type(ctdb->last_monitor_status_ctx, struct ctdb_monitor_script_status_ctx);
289 struct ctdb_monitoring_wire *monitoring_scripts;
291 if (script_status == NULL) {
292 DEBUG(DEBUG_ERR,(__location__ " last_monitor_status_ctx is NULL when reading status\n"));
296 monitoring_scripts = talloc_size(outdata, offsetof(struct ctdb_monitoring_wire, scripts));
297 if (monitoring_scripts == NULL) {
298 DEBUG(DEBUG_ERR,(__location__ " failed to talloc monitoring_scripts structure\n"));
302 monitoring_scripts->num_scripts = 0;
303 monitoring_scripts = marshall_monitoring_scripts(outdata, monitoring_scripts, script_status->scripts);
304 if (monitoring_scripts == NULL) {
305 DEBUG(DEBUG_ERR,(__location__ " Monitoring scritps is NULL. can not return data to client\n"));
309 outdata->dsize = talloc_get_size(monitoring_scripts);
310 outdata->dptr = (uint8_t *)monitoring_scripts;
315 struct ctdb_script_tree_item {
320 struct ctdb_script_list {
321 struct ctdb_script_list *next;
326 static struct ctdb_script_list *ctdb_get_script_list(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx)
332 struct ctdb_script_list *head, *tail, *new_item;
333 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
334 struct ctdb_script_tree_item *tree_item;
338 the service specific event scripts
340 if (stat(ctdb->event_script_dir, &st) != 0 &&
342 DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
343 talloc_free(tmp_ctx);
347 /* create a tree to store all the script names in */
348 tree = trbt_create(tmp_ctx, 0);
350 /* scan all directory entries and insert all valid scripts into the
353 dir = opendir(ctdb->event_script_dir);
355 DEBUG(DEBUG_CRIT,("Failed to open event script directory '%s'\n", ctdb->event_script_dir));
356 talloc_free(tmp_ctx);
361 while ((de=readdir(dir)) != NULL) {
366 namlen = strlen(de->d_name);
372 if (de->d_name[namlen-1] == '~') {
373 /* skip files emacs left behind */
377 if (de->d_name[2] != '.') {
381 if (sscanf(de->d_name, "%02u.", &num) != 1) {
385 /* Make sure the event script is executable */
386 str = talloc_asprintf(tree, "%s/%s", ctdb->event_script_dir, de->d_name);
387 if (stat(str, &st) != 0) {
388 DEBUG(DEBUG_ERR,("Could not stat event script %s. Ignoring this event script\n", str));
393 tree_item = talloc(tree, struct ctdb_script_tree_item);
394 if (tree_item == NULL) {
395 DEBUG(DEBUG_ERR, (__location__ " Failed to allocate new tree item\n"));
396 talloc_free(tmp_ctx);
400 tree_item->is_enabled = 1;
401 if (!(st.st_mode & S_IXUSR)) {
402 DEBUG(DEBUG_INFO,("Event script %s is not executable. Ignoring this event script\n", str));
403 tree_item->is_enabled = 0;
406 tree_item->name = talloc_strdup(tree_item, de->d_name);
407 if (tree_item->name == NULL) {
408 DEBUG(DEBUG_ERR,(__location__ " Failed to allocate script name.\n"));
409 talloc_free(tmp_ctx);
413 /* store the event script in the tree */
414 trbt_insert32(tree, (num<<16)|count++, tree_item);
422 /* fetch the scripts from the tree one by one and add them to the linked
425 while ((tree_item=trbt_findfirstarray32(tree, 1)) != NULL) {
427 new_item = talloc(tmp_ctx, struct ctdb_script_list);
428 if (new_item == NULL) {
429 DEBUG(DEBUG_ERR, (__location__ " Failed to allocate new list item\n"));
430 talloc_free(tmp_ctx);
434 new_item->next = NULL;
435 new_item->name = talloc_steal(new_item, tree_item->name);
436 new_item->is_enabled = tree_item->is_enabled;
442 tail->next = new_item;
446 talloc_steal(mem_ctx, new_item);
448 /* remove this script from the tree */
449 talloc_free(tree_item);
452 talloc_free(tmp_ctx);
459 Actually run the event script
460 this function is called and run in the context of a forked child
461 which allows it to do blocking calls such as system()
463 static int ctdb_run_event_script(struct ctdb_context *ctdb,
464 enum ctdb_eventscript_call call,
469 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
470 struct ctdb_script_list *scripts, *current;
472 if (call == CTDB_EVENT_MONITOR) {
473 /* This is running in the forked child process. At this stage
474 * we want to switch from being a ctdb daemon into being a
475 * client and connect to the real local daemon.
477 if (switch_from_server_to_client(ctdb) != 0) {
478 DEBUG(DEBUG_CRIT, (__location__ "ERROR: failed to switch eventscript child into client mode. shutting down.\n"));
482 if (ctdb_ctrl_event_script_init(ctdb) != 0) {
483 DEBUG(DEBUG_ERR,(__location__ " Failed to init event script monitoring\n"));
484 talloc_free(tmp_ctx);
489 if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
490 /* we guarantee that only some specifically allowed event scripts are run
492 const enum ctdb_eventscript_call allowed_calls[] = {
493 CTDB_EVENT_START_RECOVERY, CTDB_EVENT_SHUTDOWN, CTDB_EVENT_RELEASE_IP, CTDB_EVENT_STOPPED };
495 for (i=0;i<ARRAY_SIZE(allowed_calls);i++) {
496 if (call == allowed_calls[i]) break;
498 if (i == ARRAY_SIZE(allowed_calls)) {
499 DEBUG(DEBUG_ERR,("Refusing to run event scripts call '%s' while in recovery\n",
501 talloc_free(tmp_ctx);
506 if (setpgid(0,0) != 0) {
507 DEBUG(DEBUG_ERR,("Failed to create process group for event scripts - %s\n",
509 talloc_free(tmp_ctx);
513 signal(SIGTERM, sigterm);
515 child_state.start = timeval_current();
516 child_state.script_running = "startup";
518 scripts = ctdb_get_script_list(ctdb, tmp_ctx);
520 /* fetch the scripts from the tree one by one and execute
523 for (current=scripts; current; current=current->next) {
524 /* Allow a setting where we run the actual monitor event
525 from an external source and replace it with
526 a "status" event that just picks up the actual
527 status of the event asynchronously.
529 if ((ctdb->tunable.use_status_events_for_monitoring != 0)
530 && call == CTDB_EVENT_MONITOR) {
531 cmdstr = talloc_asprintf(tmp_ctx, "%s/%s %s",
532 ctdb->event_script_dir,
533 current->name, "status");
535 cmdstr = talloc_asprintf(tmp_ctx, "%s/%s %s %s",
536 ctdb->event_script_dir,
537 current->name, call_names[call], options);
539 CTDB_NO_MEMORY(ctdb, cmdstr);
541 DEBUG(DEBUG_INFO,("Executing event script %s\n",cmdstr));
543 child_state.start = timeval_current();
544 child_state.script_running = cmdstr;
546 if (call == CTDB_EVENT_MONITOR) {
547 if (ctdb_ctrl_event_script_start(ctdb, current->name) != 0) {
548 DEBUG(DEBUG_ERR,(__location__ " Failed to start event script monitoring\n"));
549 talloc_free(tmp_ctx);
553 if (!current->is_enabled) {
554 if (ctdb_ctrl_event_script_disabled(ctdb, current->name) != 0) {
555 DEBUG(DEBUG_ERR,(__location__ " Failed to report disabled eventscript\n"));
556 talloc_free(tmp_ctx);
563 if (!current->is_enabled) {
567 ret = system(cmdstr);
568 /* if the system() call was successful, translate ret into the
569 return code from the command
572 ret = WEXITSTATUS(ret);
576 DEBUG(DEBUG_ERR,("Script %s returned status 127. Someone just deleted it?\n", cmdstr));
579 if (call == CTDB_EVENT_MONITOR) {
580 if (ctdb_ctrl_event_script_stop(ctdb, ret) != 0) {
581 DEBUG(DEBUG_ERR,(__location__ " Failed to stop event script monitoring\n"));
582 talloc_free(tmp_ctx);
587 /* return an error if the script failed */
589 DEBUG(DEBUG_ERR,("Event script %s failed with error %d\n", cmdstr, ret));
590 if (call == CTDB_EVENT_MONITOR) {
591 if (ctdb_ctrl_event_script_finished(ctdb) != 0) {
592 DEBUG(DEBUG_ERR,(__location__ " Failed to finish event script monitoring\n"));
593 talloc_free(tmp_ctx);
598 talloc_free(tmp_ctx);
603 child_state.start = timeval_current();
604 child_state.script_running = "finished";
606 if (call == CTDB_EVENT_MONITOR) {
607 if (ctdb_ctrl_event_script_finished(ctdb) != 0) {
608 DEBUG(DEBUG_ERR,(__location__ " Failed to finish event script monitoring\n"));
609 talloc_free(tmp_ctx);
614 talloc_free(tmp_ctx);
618 /* called when child is finished */
619 static void ctdb_event_script_handler(struct event_context *ev, struct fd_event *fde,
620 uint16_t flags, void *p)
622 struct ctdb_event_script_state *state =
623 talloc_get_type(p, struct ctdb_event_script_state);
624 struct ctdb_context *ctdb = state->ctdb;
626 if (read(state->fd[0], &state->cb_status, sizeof(state->cb_status)) !=
627 sizeof(state->cb_status)) {
628 state->cb_status = -2;
631 DEBUG(DEBUG_INFO,(__location__ " Eventscript %s %s finished with state %d\n",
632 call_names[state->call], state->options, state->cb_status));
635 ctdb->event_script_timeouts = 0;
639 static void ctdb_ban_self(struct ctdb_context *ctdb, uint32_t ban_period)
642 struct ctdb_ban_time bantime;
644 bantime.pnn = ctdb->pnn;
645 bantime.time = ban_period;
647 data.dsize = sizeof(bantime);
648 data.dptr = (uint8_t *)&bantime;
650 ctdb_control_set_ban_state(ctdb, data);
654 /* called when child times out */
655 static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te,
656 struct timeval t, void *p)
658 struct ctdb_event_script_state *state = talloc_get_type(p, struct ctdb_event_script_state);
659 struct ctdb_context *ctdb = state->ctdb;
661 DEBUG(DEBUG_ERR,("Event script timed out : %s %s count : %u pid : %d\n",
662 call_names[state->call], state->options, ctdb->event_script_timeouts, state->child));
664 if (kill(state->child, 0) != 0) {
665 DEBUG(DEBUG_ERR,("Event script child process already dead, errno %s(%d)\n", strerror(errno), errno));
671 if (state->call == CTDB_EVENT_MONITOR) {
672 /* if it is a monitor event, we allow it to "hang" a few times
673 before we declare it a failure and ban ourself (and make
676 DEBUG(DEBUG_ERR, (__location__ " eventscript for monitor event timedout.\n"));
678 ctdb->event_script_timeouts++;
680 if (ctdb->event_script_timeouts > ctdb->tunable.script_ban_count) {
681 DEBUG(DEBUG_ERR, ("Maximum timeout count %u reached for eventscript. Making node unhealthy\n", ctdb->tunable.script_ban_count));
682 state->cb_status = -ETIME;
684 state->cb_status = 0;
686 } else if (state->call == CTDB_EVENT_STARTUP) {
687 DEBUG(DEBUG_ERR, (__location__ " eventscript for startup event timedout.\n"));
688 state->cb_status = -1;
690 /* if it is not a monitor or a startup event we ban ourself
693 DEBUG(DEBUG_ERR, (__location__ " eventscript for NON-monitor/NON-startup event timedout. Immediately banning ourself for %d seconds\n", ctdb->tunable.recovery_ban_period));
695 ctdb_ban_self(ctdb, ctdb->tunable.recovery_ban_period);
697 state->cb_status = -1;
700 if (state->call == CTDB_EVENT_MONITOR || state->call == CTDB_EVENT_STATUS) {
701 struct ctdb_monitor_script_status *script;
703 if (ctdb->current_monitor_status_ctx == NULL) {
708 script = ctdb->current_monitor_status_ctx->scripts;
709 if (script != NULL) {
710 script->timedout = 1;
713 if (ctdb->last_monitor_status_ctx) {
714 talloc_free(ctdb->last_monitor_status_ctx);
715 ctdb->last_monitor_status_ctx = NULL;
717 ctdb->last_monitor_status_ctx = talloc_steal(ctdb, ctdb->current_monitor_status_ctx);
718 ctdb->current_monitor_status_ctx = NULL;
725 destroy an event script: kill it if ->child != 0.
727 static int event_script_destructor(struct ctdb_event_script_state *state)
730 DEBUG(DEBUG_ERR,(__location__ " Sending SIGTERM to child pid:%d\n", state->child));
732 if (kill(state->child, SIGTERM) != 0) {
733 DEBUG(DEBUG_ERR,("Failed to kill child process for eventscript, errno %s(%d)\n", strerror(errno), errno));
737 /* This is allowed to free us; talloc will prevent double free anyway,
738 * but beware if you call this outside the destructor! */
739 if (state->callback) {
740 state->callback(state->ctdb, state->cb_status, state->private_data);
746 static unsigned int count_words(const char *options)
748 unsigned int words = 0;
750 options += strspn(options, " \t");
753 options += strcspn(options, " \t");
754 options += strspn(options, " \t");
759 static bool check_options(enum ctdb_eventscript_call call, const char *options)
762 /* These all take no arguments. */
763 case CTDB_EVENT_STARTUP:
764 case CTDB_EVENT_START_RECOVERY:
765 case CTDB_EVENT_RECOVERED:
766 case CTDB_EVENT_STOPPED:
767 case CTDB_EVENT_MONITOR:
768 case CTDB_EVENT_STATUS:
769 case CTDB_EVENT_SHUTDOWN:
770 return count_words(options) == 0;
772 case CTDB_EVENT_TAKE_IP: /* interface, IP address, netmask bits. */
773 case CTDB_EVENT_RELEASE_IP:
774 return count_words(options) == 3;
777 DEBUG(DEBUG_ERR,(__location__ "Unknown ctdb_eventscript_call %u\n", call));
783 run the event script in the background, calling the callback when
786 static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
787 void (*callback)(struct ctdb_context *, int, void *),
789 enum ctdb_eventscript_call call,
790 const char *fmt, va_list ap)
793 struct ctdb_event_script_state *state;
796 if (call == CTDB_EVENT_MONITOR || call == CTDB_EVENT_STATUS) {
797 /* if this was a "monitor" or a status event, we recycle the
798 context to start a new monitor event
800 if (ctdb->monitor_event_script_ctx != NULL) {
801 talloc_free(ctdb->monitor_event_script_ctx);
802 ctdb->monitor_event_script_ctx = NULL;
804 ctdb->monitor_event_script_ctx = talloc_new(ctdb);
805 mem_ctx = ctdb->monitor_event_script_ctx;
807 if (ctdb->current_monitor_status_ctx != NULL) {
808 talloc_free(ctdb->current_monitor_status_ctx);
809 ctdb->current_monitor_status_ctx = NULL;
812 ctdb->current_monitor_status_ctx = talloc(ctdb, struct ctdb_monitor_script_status_ctx);
813 CTDB_NO_MEMORY(ctdb, ctdb->current_monitor_status_ctx);
814 ctdb->current_monitor_status_ctx->scripts = NULL;
816 /* any other script will first terminate any monitor event */
817 if (ctdb->monitor_event_script_ctx != NULL) {
818 talloc_free(ctdb->monitor_event_script_ctx);
819 ctdb->monitor_event_script_ctx = NULL;
821 /* and then use a context common for all non-monitor events */
822 if (ctdb->other_event_script_ctx == NULL) {
823 ctdb->other_event_script_ctx = talloc_new(ctdb);
825 mem_ctx = ctdb->other_event_script_ctx;
828 state = talloc(mem_ctx, struct ctdb_event_script_state);
829 CTDB_NO_MEMORY(ctdb, state);
832 state->callback = callback;
833 state->private_data = private_data;
835 state->options = talloc_vasprintf(state, fmt, ap);
836 state->timeout = timeval_set(ctdb->tunable.script_timeout, 0);
837 if (state->options == NULL) {
838 DEBUG(DEBUG_ERR, (__location__ " could not allocate state->options\n"));
842 if (!check_options(state->call, state->options)) {
843 DEBUG(DEBUG_ERR, ("Bad eventscript options '%s' for %s\n",
844 call_names[state->call], state->options));
849 DEBUG(DEBUG_INFO,(__location__ " Starting eventscript %s %s\n",
850 call_names[state->call], state->options));
852 ret = pipe(state->fd);
858 state->child = fork();
860 if (state->child == (pid_t)-1) {
867 if (state->child == 0) {
871 set_close_on_exec(state->fd[1]);
873 rt = ctdb_run_event_script(ctdb, state->call, state->options);
874 /* We must be able to write PIPEBUF bytes at least; if this
875 somehow fails, the read above will be short. */
876 write(state->fd[1], &rt, sizeof(rt));
882 set_close_on_exec(state->fd[0]);
883 talloc_set_destructor(state, event_script_destructor);
885 DEBUG(DEBUG_DEBUG, (__location__ " Created PIPE FD:%d to child eventscript process\n", state->fd[0]));
887 event_add_fd(ctdb->ev, state, state->fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
888 ctdb_event_script_handler, state);
890 if (!timeval_is_zero(&state->timeout)) {
891 event_add_timed(ctdb->ev, state, timeval_current_ofs(state->timeout.tv_sec, state->timeout.tv_usec), ctdb_event_script_timeout, state);
893 DEBUG(DEBUG_ERR, (__location__ " eventscript %s %s called with no timeout\n",
894 call_names[state->call], state->options));
902 run the event script in the background, calling the callback when
905 int ctdb_event_script_callback(struct ctdb_context *ctdb,
907 void (*callback)(struct ctdb_context *, int, void *),
909 enum ctdb_eventscript_call call,
910 const char *fmt, ...)
916 ret = ctdb_event_script_callback_v(ctdb, callback, private_data, call, fmt, ap);
923 struct callback_status {
929 called when ctdb_event_script() finishes
931 static void event_script_callback(struct ctdb_context *ctdb, int status, void *private_data)
933 struct callback_status *s = (struct callback_status *)private_data;
939 run the event script, waiting for it to complete. Used when the caller
940 doesn't want to continue till the event script has finished.
942 int ctdb_event_script_args(struct ctdb_context *ctdb, enum ctdb_eventscript_call call,
943 const char *fmt, ...)
947 struct callback_status status;
950 ret = ctdb_event_script_callback_v(ctdb,
951 event_script_callback, &status, call, fmt, ap);
960 while (status.done == false && event_loop_once(ctdb->ev) == 0) /* noop */;
962 return status.status;
965 int ctdb_event_script(struct ctdb_context *ctdb, enum ctdb_eventscript_call call)
967 /* GCC complains about empty format string, so use %s and "". */
968 return ctdb_event_script_args(ctdb, call, "%s", "");
971 struct eventscript_callback_state {
972 struct ctdb_req_control *c;
976 called when a forced eventscript finishes
978 static void run_eventscripts_callback(struct ctdb_context *ctdb, int status,
981 struct eventscript_callback_state *state =
982 talloc_get_type(private_data, struct eventscript_callback_state);
984 ctdb_enable_monitoring(ctdb);
987 DEBUG(DEBUG_ERR,(__location__ " Failed to forcibly run eventscripts\n"));
990 ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL);
991 /* This will free the struct ctdb_event_script_state we are in! */
997 /* Returns rest of string, or NULL if no match. */
998 static const char *get_call(const char *p, enum ctdb_eventscript_call *call)
1002 /* Skip any initial whitespace. */
1003 p += strspn(p, " \t");
1005 /* See if we match any. */
1006 for (*call = 0; *call < ARRAY_SIZE(call_names); (*call)++) {
1007 len = strlen(call_names[*call]);
1008 if (strncmp(p, call_names[*call], len) == 0) {
1009 /* If end of string or whitespace, we're done. */
1010 if (strcspn(p + len, " \t") == 0) {
1019 A control to force running of the eventscripts from the ctdb client tool
1021 int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb,
1022 struct ctdb_req_control *c,
1023 TDB_DATA indata, bool *async_reply)
1026 struct eventscript_callback_state *state;
1027 const char *options;
1028 enum ctdb_eventscript_call call;
1030 /* Figure out what call they want. */
1031 options = get_call((const char *)indata.dptr, &call);
1033 DEBUG(DEBUG_ERR, (__location__ " Invalid forced \"%s\"\n", (const char *)indata.dptr));
1037 if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
1038 DEBUG(DEBUG_ERR, (__location__ " Aborted running eventscript \"%s\" while in RECOVERY mode\n", indata.dptr));
1042 state = talloc(ctdb->other_event_script_ctx, struct eventscript_callback_state);
1043 CTDB_NO_MEMORY(ctdb, state);
1045 state->c = talloc_steal(state, c);
1047 DEBUG(DEBUG_NOTICE,("Forced running of eventscripts with arguments %s\n", indata.dptr));
1049 ctdb_disable_monitoring(ctdb);
1051 ret = ctdb_event_script_callback(ctdb,
1052 state, run_eventscripts_callback, state,
1053 call, "%s", options);
1056 ctdb_enable_monitoring(ctdb);
1057 DEBUG(DEBUG_ERR,(__location__ " Failed to run eventscripts with arguments %s\n", indata.dptr));
1062 /* tell ctdb_control.c that we will be replying asynchronously */
1063 *async_reply = true;
1070 int32_t ctdb_control_enable_script(struct ctdb_context *ctdb, TDB_DATA indata)
1075 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1077 script = (char *)indata.dptr;
1078 if (indata.dsize == 0) {
1079 DEBUG(DEBUG_ERR,(__location__ " No script specified.\n"));
1080 talloc_free(tmp_ctx);
1083 if (indata.dptr[indata.dsize - 1] != '\0') {
1084 DEBUG(DEBUG_ERR,(__location__ " String is not null terminated.\n"));
1085 talloc_free(tmp_ctx);
1088 if (index(script,'/') != NULL) {
1089 DEBUG(DEBUG_ERR,(__location__ " Script name contains '/'. Failed to enable script %s\n", script));
1090 talloc_free(tmp_ctx);
1095 if (stat(ctdb->event_script_dir, &st) != 0 &&
1097 DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
1098 talloc_free(tmp_ctx);
1103 filename = talloc_asprintf(tmp_ctx, "%s/%s", ctdb->event_script_dir, script);
1104 if (filename == NULL) {
1105 DEBUG(DEBUG_ERR,(__location__ " Failed to create script path\n"));
1106 talloc_free(tmp_ctx);
1110 if (stat(filename, &st) != 0) {
1111 DEBUG(DEBUG_ERR,("Could not stat event script %s. Failed to enable script.\n", filename));
1112 talloc_free(tmp_ctx);
1116 if (chmod(filename, st.st_mode | S_IXUSR) == -1) {
1117 DEBUG(DEBUG_ERR,("Could not chmod %s. Failed to enable script.\n", filename));
1118 talloc_free(tmp_ctx);
1122 talloc_free(tmp_ctx);
1126 int32_t ctdb_control_disable_script(struct ctdb_context *ctdb, TDB_DATA indata)
1131 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1133 script = (char *)indata.dptr;
1134 if (indata.dsize == 0) {
1135 DEBUG(DEBUG_ERR,(__location__ " No script specified.\n"));
1136 talloc_free(tmp_ctx);
1139 if (indata.dptr[indata.dsize - 1] != '\0') {
1140 DEBUG(DEBUG_ERR,(__location__ " String is not null terminated.\n"));
1141 talloc_free(tmp_ctx);
1144 if (index(script,'/') != NULL) {
1145 DEBUG(DEBUG_ERR,(__location__ " Script name contains '/'. Failed to disable script %s\n", script));
1146 talloc_free(tmp_ctx);
1151 if (stat(ctdb->event_script_dir, &st) != 0 &&
1153 DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
1154 talloc_free(tmp_ctx);
1159 filename = talloc_asprintf(tmp_ctx, "%s/%s", ctdb->event_script_dir, script);
1160 if (filename == NULL) {
1161 DEBUG(DEBUG_ERR,(__location__ " Failed to create script path\n"));
1162 talloc_free(tmp_ctx);
1166 if (stat(filename, &st) != 0) {
1167 DEBUG(DEBUG_ERR,("Could not stat event script %s. Failed to disable script.\n", filename));
1168 talloc_free(tmp_ctx);
1172 if (chmod(filename, st.st_mode & ~(S_IXUSR|S_IXGRP|S_IXOTH)) == -1) {
1173 DEBUG(DEBUG_ERR,("Could not chmod %s. Failed to disable script.\n", filename));
1174 talloc_free(tmp_ctx);
1178 talloc_free(tmp_ctx);