From e8e67ef576f3ad2d87590b5bb88ce32e7d8399bb Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Wed, 2 Apr 2008 11:13:30 +1100 Subject: [PATCH] add a mechanism to force a node to run the eventscripts with arbitrary arguments ctdb eventscript "command argument argument ..." (This used to be ctdb commit 118a16e763d8332c6ce4d8b8e194775fb874c8c8) --- ctdb/include/ctdb_private.h | 4 ++ ctdb/server/ctdb_control.c | 3 ++ ctdb/server/ctdb_monitor.c | 1 + ctdb/server/eventscript.c | 74 +++++++++++++++++++++++++++++++++++++ ctdb/tools/ctdb.c | 33 +++++++++++++++++ 5 files changed, 115 insertions(+) diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index b0b1f524054..2435b0f4a95 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -386,6 +386,7 @@ struct ctdb_context { struct ctdb_monitor_state *monitor; struct ctdb_log_state *log; int start_as_disabled; + TALLOC_CTX *eventscripts_ctx; /* a context to hold data for the RUN_EVENTSCRIPTS control */ }; struct ctdb_db_context { @@ -511,6 +512,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0, CTDB_CONTROL_DISABLE_MONITOR = 76, CTDB_CONTROL_ADD_PUBLIC_IP = 77, CTDB_CONTROL_DEL_PUBLIC_IP = 78, + CTDB_CONTROL_RUN_EVENTSCRIPTS = 79, }; /* @@ -1092,6 +1094,8 @@ void ctdb_start_tcp_tickle_update(struct ctdb_context *ctdb); void ctdb_send_keepalive(struct ctdb_context *ctdb, uint32_t destnode); void ctdb_start_keepalive(struct ctdb_context *ctdb); void ctdb_stop_keepalive(struct ctdb_context *ctdb); +int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb, struct ctdb_req_control *c, TDB_DATA data, bool *async_reply); + void ctdb_daemon_cancel_controls(struct ctdb_context *ctdb, struct ctdb_node *node); void ctdb_call_resend_all(struct ctdb_context *ctdb); diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c index bad1a3795c9..9097854e36c 100644 --- a/ctdb/server/ctdb_control.c +++ b/ctdb/server/ctdb_control.c @@ -263,6 +263,9 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, ctdb_enable_monitoring(ctdb); return 0; + case CTDB_CONTROL_RUN_EVENTSCRIPTS: + return ctdb_run_eventscripts(ctdb, c, indata, async_reply); + case CTDB_CONTROL_DISABLE_MONITOR: CHECK_CONTROL_DATA_SIZE(0); ctdb_disable_monitoring(ctdb); diff --git a/ctdb/server/ctdb_monitor.c b/ctdb/server/ctdb_monitor.c index 523d0ec5c8c..05e6643af8c 100644 --- a/ctdb/server/ctdb_monitor.c +++ b/ctdb/server/ctdb_monitor.c @@ -268,3 +268,4 @@ int32_t ctdb_monitoring_mode(struct ctdb_context *ctdb) } return ctdb->monitor->monitoring_mode; } + diff --git a/ctdb/server/eventscript.c b/ctdb/server/eventscript.c index 705cb4b9a65..f6afd47800d 100644 --- a/ctdb/server/eventscript.c +++ b/ctdb/server/eventscript.c @@ -367,3 +367,77 @@ int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) return status.status; } + + +struct eventscript_callback_state { + struct ctdb_req_control *c; +}; + +/* + called when takeip event finishes + */ +static void run_eventscripts_callback(struct ctdb_context *ctdb, int status, + void *private_data) +{ + struct eventscript_callback_state *state = + talloc_get_type(private_data, struct eventscript_callback_state); + + ctdb_enable_monitoring(ctdb); + + if (status != 0) { + DEBUG(DEBUG_ERR,(__location__ " Failed to forcibly run eventscripts\n")); + ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL); + talloc_free(state); + return; + } + + /* the control succeeded */ + ctdb_request_control_reply(ctdb, state->c, NULL, 0, NULL); + talloc_free(state); + return; +} + +/* + A control to force running of the eventscripts from the ctdb client tool +*/ +int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb, + struct ctdb_req_control *c, + TDB_DATA indata, bool *async_reply) +{ + int ret; + struct eventscript_callback_state *state; + + /* kill off any previous invokations of forced eventscripts */ + if (ctdb->eventscripts_ctx) { + talloc_free(ctdb->eventscripts_ctx); + } + ctdb->eventscripts_ctx = talloc_new(ctdb); + CTDB_NO_MEMORY(ctdb, ctdb->eventscripts_ctx); + + state = talloc(ctdb->eventscripts_ctx, struct eventscript_callback_state); + CTDB_NO_MEMORY(ctdb, state); + + state->c = talloc_steal(ctdb, c); + + DEBUG(DEBUG_NOTICE,("Forced running of eventscripts with arguments %s\n", indata.dptr)); + + ctdb_disable_monitoring(ctdb); + + ret = ctdb_event_script_callback(ctdb, + timeval_current_ofs(ctdb->tunable.script_timeout, 0), + state, run_eventscripts_callback, state, + (const char *)indata.dptr); + + if (ret != 0) { + ctdb_enable_monitoring(ctdb); + DEBUG(DEBUG_ERR,(__location__ " Failed to run eventscripts with arguments %s\n", indata.dptr)); + talloc_free(state); + return -1; + } + + /* tell ctdb_control.c that we will be replying asynchronously */ + *async_reply = true; + + return 0; +} + diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c index 537723026d0..df4b703a786 100644 --- a/ctdb/tools/ctdb.c +++ b/ctdb/tools/ctdb.c @@ -1385,6 +1385,38 @@ static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv return 0; } +/* + dump memory usage + */ +static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv) +{ + TDB_DATA data; + int ret; + int32_t res; + char *errmsg; + TALLOC_CTX *tmp_ctx = talloc_new(ctdb); + + if (argc != 1) { + DEBUG(DEBUG_ERR,("Invalid arguments\n")); + return -1; + } + + data.dptr = (unsigned char *)discard_const(argv[0]); + data.dsize = strlen((char *)data.dptr) + 1; + + DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn)); + + ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS, + 0, data, tmp_ctx, NULL, &res, NULL, &errmsg); + if (ret != 0 || res != 0) { + DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg)); + talloc_free(tmp_ctx); + return -1; + } + talloc_free(tmp_ctx); + return 0; +} + /* dump memory usage */ @@ -1576,6 +1608,7 @@ static const struct { { "moveip", control_moveip, false, "move/failover an ip address to another node", " "}, { "addip", control_addip, false, "add a ip address to a node", " "}, { "delip", control_delip, false, "delete an ip address from a node", ""}, + { "eventscript", control_eventscript, false, "run the eventscript with the given parameters on a node", ""}, }; /*