diff options
author | Ronnie Sahlberg <ronniesahlberg@gmail.com> | 2009-03-31 14:23:31 +1100 |
---|---|---|
committer | Ronnie Sahlberg <ronniesahlberg@gmail.com> | 2009-03-31 14:23:31 +1100 |
commit | ad40ee25f99520e6119f386864cd8eb377da6a95 (patch) | |
tree | 9f257e14609f7dede3566e920d3e7e9f8f01749e | |
parent | df9d401d8c2342674e8836758c7c3a5a8a8847a7 (diff) | |
download | samba-ad40ee25f99520e6119f386864cd8eb377da6a95.tar.gz samba-ad40ee25f99520e6119f386864cd8eb377da6a95.tar.xz samba-ad40ee25f99520e6119f386864cd8eb377da6a95.zip |
add a mechanism where the ctdb daemon will run a usercontrolled script when the node status changes to/from UNHEALTHY state.
This would allow a sysadmin to set up ctdb to send an email/snmptrap/... when the status of the node changes.
(This used to be ctdb commit ce534a83a05dbd40238e4eee0669d60ff396f935)
-rwxr-xr-x | ctdb/config/ctdb.init | 1 | ||||
-rw-r--r-- | ctdb/config/ctdb.sysconfig | 3 | ||||
-rw-r--r-- | ctdb/include/ctdb_private.h | 2 | ||||
-rw-r--r-- | ctdb/server/ctdb_monitor.c | 71 | ||||
-rw-r--r-- | ctdb/server/ctdbd.c | 10 |
5 files changed, 87 insertions, 0 deletions
diff --git a/ctdb/config/ctdb.init b/ctdb/config/ctdb.init index e263855812..24a206dbbf 100755 --- a/ctdb/config/ctdb.init +++ b/ctdb/config/ctdb.init @@ -64,6 +64,7 @@ CTDB_OPTIONS="$CTDB_OPTIONS --reclock=$CTDB_RECOVERY_LOCK" [ -z "$CTDB_EVENT_SCRIPT_DIR" ] || CTDB_OPTIONS="$CTDB_OPTIONS --event-script-dir $CTDB_EVENT_SCRIPT_DIR" [ -z "$CTDB_TRANSPORT" ] || CTDB_OPTIONS="$CTDB_OPTIONS --transport $CTDB_TRANSPORT" [ -z "$CTDB_DEBUGLEVEL" ] || CTDB_OPTIONS="$CTDB_OPTIONS -d $CTDB_DEBUGLEVEL" +[ -z "$CTDB_NOTIFY_SCRIPT" ] || CTDB_OPTIONS="$CTDB_OPTIONS --notification-script=$CTDB_NOTIFY_SCRIPT" [ -z "$CTDB_START_AS_DISABLED" ] || [ "$CTDB_START_AS_DISABLED" != "yes" ] || { CTDB_OPTIONS="$CTDB_OPTIONS --start-as-disabled" } diff --git a/ctdb/config/ctdb.sysconfig b/ctdb/config/ctdb.sysconfig index ef3b0dc3e0..f1f367636f 100644 --- a/ctdb/config/ctdb.sysconfig +++ b/ctdb/config/ctdb.sysconfig @@ -95,6 +95,9 @@ # defaults to /etc/ctdb/nodes # CTDB_NODES=/etc/ctdb/nodes +# a script to run when node health changes +# CTDB_NOTIFY_SCRIPT=/etc/ctdb/notify.sh + # the directory to put the local ctdb database files in # defaults to /var/ctdb # CTDB_DBDIR=/var/ctdb diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index cbd97d75d5..cf93eed132 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -400,6 +400,7 @@ struct ctdb_context { void *saved_scheduler_param; struct _trbt_tree_t *server_ids; const char *event_script_dir; + const char *notification_script; const char *default_public_interface; pid_t ctdbd_pid; pid_t recoverd_pid; @@ -1241,6 +1242,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, 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_set_notification_script(struct ctdb_context *ctdb, const char *script); 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_monitor.c b/ctdb/server/ctdb_monitor.c index 21f0382d6b..46d9c63229 100644 --- a/ctdb/server/ctdb_monitor.c +++ b/ctdb/server/ctdb_monitor.c @@ -34,6 +34,74 @@ static void ctdb_check_health(struct event_context *ev, struct timed_event *te, struct timeval t, void *private_data); /* + setup the notification script +*/ +int ctdb_set_notification_script(struct ctdb_context *ctdb, const char *script) +{ + ctdb->notification_script = talloc_strdup(ctdb, script); + CTDB_NO_MEMORY(ctdb, ctdb->notification_script); + return 0; +} + +static int ctdb_run_notification_script_child(struct ctdb_context *ctdb, const char *event) +{ + struct stat st; + int ret; + char *cmd; + + if (stat(ctdb->notification_script, &st) != 0) { + DEBUG(DEBUG_ERR,("Could not stat notification script %s. Can not send notifications.\n", ctdb->notification_script)); + return -1; + } + if (!(st.st_mode & S_IXUSR)) { + DEBUG(DEBUG_ERR,("Notification script %s is not executable.\n", ctdb->notification_script)); + return -1; + } + + cmd = talloc_asprintf(ctdb, "%s %s\n", ctdb->notification_script, event); + CTDB_NO_MEMORY(ctdb, cmd); + + ret = system(cmd); + /* if the system() call was successful, translate ret into the + return code from the command + */ + if (ret != -1) { + ret = WEXITSTATUS(ret); + } + if (ret != 0) { + DEBUG(DEBUG_ERR,("Notification script \"%s\" failed with error %d\n", cmd, ret)); + } + + return ret; +} + +static void ctdb_run_notification_script(struct ctdb_context *ctdb, const char *event) +{ + pid_t child; + + if (ctdb->notification_script == NULL) { + return; + } + + child = fork(); + if (child == (pid_t)-1) { + DEBUG(DEBUG_ERR,("Failed to fork() a notification child process\n")); + return; + } + if (child == 0) { + int ret; + + ret = ctdb_run_notification_script_child(ctdb, event); + if (ret != 0) { + DEBUG(DEBUG_ERR,(__location__ " Notification script failed\n")); + } + _exit(0); + } + + return; +} + +/* called when a health monitoring event script finishes */ static void ctdb_health_callback(struct ctdb_context *ctdb, int status, void *p) @@ -55,10 +123,13 @@ static void ctdb_health_callback(struct ctdb_context *ctdb, int status, void *p) node->flags |= NODE_FLAGS_DISABLED; } + ctdb_run_notification_script(ctdb, "unhealthy"); } else if (status == 0 && (node->flags & NODE_FLAGS_UNHEALTHY)) { DEBUG(DEBUG_NOTICE,("monitor event OK - node re-enabled\n")); node->flags &= ~NODE_FLAGS_UNHEALTHY; ctdb->monitor->next_interval = 1; + + ctdb_run_notification_script(ctdb, "healthy"); } next_interval = ctdb->monitor->next_interval; diff --git a/ctdb/server/ctdbd.c b/ctdb/server/ctdbd.c index 5670b9387d..de6c39fbca 100644 --- a/ctdb/server/ctdbd.c +++ b/ctdb/server/ctdbd.c @@ -33,6 +33,7 @@ static struct { const char *myaddress; const char *public_address_list; const char *event_script_dir; + const char *notification_script; const char *logfile; const char *recovery_lock_file; const char *db_dir; @@ -119,6 +120,7 @@ int main(int argc, const char *argv[]) { "logfile", 0, POPT_ARG_STRING, &options.logfile, 0, "log file location", "filename" }, { "nlist", 0, POPT_ARG_STRING, &options.nlist, 0, "node list file", "filename" }, { "node-ip", 0, POPT_ARG_STRING, &options.node_ip, 0, "node ip", "ip-address"}, + { "notification-script", 0, POPT_ARG_STRING, &options.notification_script, 0, "notification script", "filename" }, { "listen", 0, POPT_ARG_STRING, &options.myaddress, 0, "address to listen on", "address" }, { "transport", 0, POPT_ARG_STRING, &options.transport, 0, "protocol transport", NULL }, { "dbdir", 0, POPT_ARG_STRING, &options.db_dir, 0, "directory for the tdb files", NULL }, @@ -302,6 +304,14 @@ int main(int argc, const char *argv[]) exit(1); } + if (options.notification_script != NULL) { + ret = ctdb_set_notification_script(ctdb, options.notification_script); + if (ret == -1) { + DEBUG(DEBUG_ALERT,("Unable to setup notification script\n")); + exit(1); + } + } + ctdb->do_setsched = !options.no_setsched; ctdb->do_checkpublicip = !options.no_publicipcheck; |