From: Ronnie Sahlberg Date: Wed, 15 Aug 2007 04:44:03 +0000 (+1000) Subject: call the service specific event scripts directly from the forked child X-Git-Tag: tevent-0.9.20~348^2~2441^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4023576e504c327c84fb6b1e6250937184cafc9e;p=thirdparty%2Fsamba.git call the service specific event scripts directly from the forked child instead for from /etc/ctdb/events so that we can get better debugging output in the logs when something fails in the scripts (This used to be ctdb commit 4ed96b768aea1611e8002f7095d3c4d12ccf77a3) --- diff --git a/ctdb/config/ctdb.sysconfig b/ctdb/config/ctdb.sysconfig index 2ee0b8581c0..686a17af97f 100644 --- a/ctdb/config/ctdb.sysconfig +++ b/ctdb/config/ctdb.sysconfig @@ -35,11 +35,15 @@ # defaults to /var/ctdb # CTDB_DBDIR=/var/ctdb -# the script to run when ctdb needs to ask the OS for help, +# the main script to run when ctdb needs to ask the OS for help, # such as when a IP address needs to be taken or released # defaults to /etc/ctdb/events # CTDB_EVENT_SCRIPT=/etc/ctdb/events +# the directory where service specific event scripts are stored +# defaults to /etc/ctdb/events.d +# CTDB_EVENT_SCRIPT_DIR=/etc/ctdb/events.d + # the location of the local ctdb socket # defaults to /tmp/ctdb.socket # CTDB_SOCKET=/tmp/ctdb.socket diff --git a/ctdb/config/events b/ctdb/config/events index cc74a6c8715..c12d58c5424 100755 --- a/ctdb/config/events +++ b/ctdb/config/events @@ -35,17 +35,5 @@ case $cmd in ;; esac -####################################### -# call all application or local scripts -[ -d /etc/ctdb/events.d ] && { - # only accept scripts of the form NN.name - scripts=`/bin/ls /etc/ctdb/events.d | /bin/grep '^[0-9]*\.\w*$' | sort -n` - for SCRIPT in $scripts; do - [ -x /etc/ctdb/events.d/$SCRIPT ] && { - /etc/ctdb/events.d/$SCRIPT $cmd "$1" "$2" "$3" || exit 1 - } - done -} - # all OK exit 0 diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 7542b3100fc..aaf849ef441 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -301,7 +301,8 @@ enum ctdb_freeze_mode {CTDB_FREEZE_NONE, CTDB_FREEZE_PENDING, CTDB_FREEZE_FROZEN struct ctdb_takeover { bool enabled; const char *interface; - const char *event_script; + const char *main_event_script; + const char *event_script_dir; TALLOC_CTX *last_ctx; }; @@ -1040,6 +1041,7 @@ int ctdb_sys_send_tcp(int fd, int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist); int ctdb_set_event_script(struct ctdb_context *ctdb, const char *script); +int ctdb_set_event_script_dir(struct ctdb_context *ctdb, const char *script_dir); int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap); int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c index d46783b3794..bb7473ef637 100644 --- a/ctdb/server/ctdb_takeover.c +++ b/ctdb/server/ctdb_takeover.c @@ -371,8 +371,18 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, */ int ctdb_set_event_script(struct ctdb_context *ctdb, const char *script) { - ctdb->takeover.event_script = talloc_strdup(ctdb, script); - CTDB_NO_MEMORY(ctdb, ctdb->takeover.event_script); + ctdb->takeover.main_event_script = talloc_strdup(ctdb, script); + CTDB_NO_MEMORY(ctdb, ctdb->takeover.main_event_script); + return 0; +} + +/* + setup the event script directory +*/ +int ctdb_set_event_script_dir(struct ctdb_context *ctdb, const char *script_dir) +{ + ctdb->takeover.event_script_dir = talloc_strdup(ctdb, script_dir); + CTDB_NO_MEMORY(ctdb, ctdb->takeover.event_script_dir); return 0; } diff --git a/ctdb/server/ctdbd.c b/ctdb/server/ctdbd.c index 287af59616c..778eff33b08 100644 --- a/ctdb/server/ctdbd.c +++ b/ctdb/server/ctdbd.c @@ -44,6 +44,7 @@ static struct { const char *public_address_list; const char *public_interface; const char *event_script; + const char *event_script_dir; const char *logfile; const char *recovery_lock_file; const char *db_dir; @@ -52,6 +53,7 @@ static struct { .nlist = ETCDIR "/ctdb/nodes", .transport = "tcp", .event_script = ETCDIR "/ctdb/events", + .event_script_dir = ETCDIR "/ctdb/events.d", .logfile = VARDIR "/log/log.ctdb", .db_dir = VARDIR "/ctdb", }; @@ -103,6 +105,7 @@ int main(int argc, const char *argv[]) { "public-addresses", 0, POPT_ARG_STRING, &options.public_address_list, 0, "public address list file", "filename" }, { "public-interface", 0, POPT_ARG_STRING, &options.public_interface, 0, "public interface", "interface"}, { "event-script", 0, POPT_ARG_STRING, &options.event_script, 0, "event script", "filename" }, + { "event-script-dir", 0, POPT_ARG_STRING, &options.event_script_dir, 0, "event script directory", "dirname" }, { "logfile", 0, POPT_ARG_STRING, &options.logfile, 0, "log file location", "filename" }, { "nlist", 0, POPT_ARG_STRING, &options.nlist, 0, "node list file", "filename" }, { "listen", 0, POPT_ARG_STRING, &options.myaddress, 0, "address to listen on", "address" }, @@ -218,6 +221,12 @@ int main(int argc, const char *argv[]) exit(1); } + ret = ctdb_set_event_script_dir(ctdb, options.event_script_dir); + if (ret == -1) { + printf("Unable to setup event script directory\n"); + exit(1); + } + /* useful default logfile */ if (ctdb->logfile == NULL) { char *name = talloc_asprintf(ctdb, "%s/log.ctdb.vnn%u", diff --git a/ctdb/server/eventscript.c b/ctdb/server/eventscript.c index f7a312d29f4..e103cfa803d 100644 --- a/ctdb/server/eventscript.c +++ b/ctdb/server/eventscript.c @@ -22,6 +22,9 @@ #include "system/wait.h" #include "../include/ctdb_private.h" #include "lib/events/events.h" +#include "../common/rb_tree.h" +#include +#include /* run the event script - varargs version @@ -34,30 +37,141 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_li int ret; va_list ap2; struct stat st; - - if (stat(ctdb->takeover.event_script, &st) != 0 && + TALLOC_CTX *tmp_ctx = talloc_new(ctdb); + trbt_tree_t *tree; + DIR *dir; + struct dirent *de; + char *script; + + /* + run the main event script + */ + if (stat(ctdb->takeover.main_event_script, &st) != 0 && errno == ENOENT) { - DEBUG(0,("No event script found at '%s'\n", ctdb->takeover.event_script)); + DEBUG(0,("No event script found at '%s'\n", ctdb->takeover.main_event_script)); + talloc_free(tmp_ctx); return 0; } va_copy(ap2, ap); - options = talloc_vasprintf(ctdb, fmt, ap2); + options = talloc_vasprintf(tmp_ctx, fmt, ap2); va_end(ap2); CTDB_NO_MEMORY(ctdb, options); - cmdstr = talloc_asprintf(ctdb, "%s %s", ctdb->takeover.event_script, options); + cmdstr = talloc_asprintf(tmp_ctx, "%s %s", + ctdb->takeover.main_event_script, options); CTDB_NO_MEMORY(ctdb, cmdstr); + ret = system(cmdstr); + /* if the system() call was successful, translate ret into the + return code from the command + */ if (ret != -1) { ret = WEXITSTATUS(ret); } + /* return an error if the script failed */ + if (ret != 0) { + talloc_free(tmp_ctx); + return ret; + } - talloc_free(cmdstr); - talloc_free(options); - return ret; + + /* + the service specific event scripts + */ + if (stat(ctdb->takeover.event_script_dir, &st) != 0 && + errno == ENOENT) { + DEBUG(0,("No event script directory found at '%s'\n", ctdb->takeover.event_script_dir)); + talloc_free(tmp_ctx); + return 0; + } + + /* create a tree to store all the script names in */ + tree = trbt_create(tmp_ctx, 0); + + /* scan all directory entries and insert all valid scripts into the + tree + */ + dir = opendir(ctdb->takeover.event_script_dir); + if (dir == NULL) { + DEBUG(0,("Failed to open event script directory '%s'\n", ctdb->takeover.event_script_dir)); + talloc_free(tmp_ctx); + return 0; + } + while ((de=readdir(dir)) != NULL) { + int namlen; + int num; + + namlen = strlen(de->d_name); + + if (namlen < 3) { + continue; + } + + if (de->d_name[namlen-1] == '~') { + /* skip files emacs left behind */ + continue; + } + + if (de->d_name[2] != '.') { + continue; + } + + if ( (!isdigit(de->d_name[0])) || (!isdigit(de->d_name[1])) ) { + continue; + } + + sscanf(de->d_name, "%2d.", &num); + + /* store the event script in the tree */ + script = trbt_insert32(tree, num, talloc_strdup(tmp_ctx, de->d_name)); + if (script != NULL) { + DEBUG(0,("CONFIG ERROR: Multiple event scripts with the same prefix : %s and %s. Each event script MUST have a unique prefix\n", script, de->d_name)); + talloc_free(tmp_ctx); + closedir(dir); + return -1; + } + } + closedir(dir); + + + /* fetch the scripts from the tree one by one and execute + them + */ + while ((script=trbt_findfirstarray32(tree, 1)) != NULL) { + va_copy(ap2, ap); + options = talloc_vasprintf(tmp_ctx, fmt, ap2); + va_end(ap2); + CTDB_NO_MEMORY(ctdb, options); + + cmdstr = talloc_asprintf(tmp_ctx, "%s/%s %s", + ctdb->takeover.event_script_dir, + script, options); + CTDB_NO_MEMORY(ctdb, cmdstr); + + DEBUG(1,("Executing event script %s\n",cmdstr)); + + ret = system(cmdstr); + /* if the system() call was successful, translate ret into the + return code from the command + */ + if (ret != -1) { + ret = WEXITSTATUS(ret); + } + /* return an error if the script failed */ + if (ret != 0) { + DEBUG(0,("Event script %s failed with error %d\n", cmdstr, ret)); + talloc_free(tmp_ctx); + return ret; + } + + talloc_free(script); + } + + talloc_free(tmp_ctx); + return 0; } struct ctdb_event_script_state {