CTDB_TRANS2_COMMIT_SOMEFAIL=3 /* some nodes failed the commit, some allowed it */
};
+/* different calls to event scripts. */
+enum ctdb_eventscript_call {
+ CTDB_EVENT_STARTUP, /* CTDB starting up: no args. */
+ CTDB_EVENT_START_RECOVERY, /* CTDB recovery starting: no args. */
+ CTDB_EVENT_RECOVERED, /* CTDB recovery finished: no args. */
+ CTDB_EVENT_TAKE_IP, /* IP taken: interface, IP address, netmask bits. */
+ CTDB_EVENT_RELEASE_IP, /* IP released: interface, IP address, netmask bits. */
+ CTDB_EVENT_STOPPED, /* This node is stopped: no args. */
+ CTDB_EVENT_MONITOR, /* Please check if service is healthy: no args. */
+ CTDB_EVENT_STATUS, /* Report service status: no args. */
+ CTDB_EVENT_SHUTDOWN, /* CTDB shutting down: no args. */
+ CTDB_EVENT_UNKNOWN, /* Other: manually invoked from "ctdb eventscript". */
+};
/* internal prototypes */
void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
int32_t ctdb_control_set_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata);
void ctdb_takeover_client_destructor_hook(struct ctdb_client *client);
-int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+int ctdb_event_script(struct ctdb_context *ctdb, enum ctdb_eventscript_call call);
+int ctdb_event_script_args(struct ctdb_context *ctdb, enum ctdb_eventscript_call call,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
int ctdb_event_script_callback(struct ctdb_context *ctdb,
TALLOC_CTX *mem_ctx,
void (*callback)(struct ctdb_context *, int, void *),
void *private_data,
- const char *fmt, ...) PRINTF_ATTRIBUTE(5,6);
+ enum ctdb_eventscript_call call,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(6,7);
void ctdb_release_all_ips(struct ctdb_context *ctdb);
void set_nonblocking(int fd);
if (ctdb->methods != NULL) {
ctdb->methods->shutdown(ctdb);
}
- ctdb_event_script(ctdb, "shutdown");
+ ctdb_event_script(ctdb, CTDB_EVENT_SHUTDOWN);
DEBUG(DEBUG_NOTICE,("Received SHUTDOWN command. Stopping CTDB daemon.\n"));
exit(0);
if (!ctdb->done_startup) {
ret = ctdb_event_script_callback(ctdb,
ctdb->monitor->monitor_context, ctdb_startup_callback,
- ctdb, "startup");
+ ctdb, CTDB_EVENT_STARTUP, "%s", "");
} else {
int i;
int skip_monitoring = 0;
} else {
ret = ctdb_event_script_callback(ctdb,
ctdb->monitor->monitor_context, ctdb_health_callback,
- ctdb, "monitor");
+ ctdb, CTDB_EVENT_MONITOR, "%s", "");
}
}
ret = ctdb_event_script_callback(ctdb, state,
ctdb_end_recovery_callback,
- state, "recovered");
+ state, CTDB_EVENT_RECOVERED, "%s", "");
if (ret != 0) {
ctdb_enable_monitoring(ctdb);
ret = ctdb_event_script_callback(ctdb, state,
ctdb_start_recovery_callback,
- state, "startrecovery");
+ state, CTDB_EVENT_START_RECOVERY,
+ "%s", "");
if (ret != 0) {
DEBUG(DEBUG_ERR,(__location__ " Failed to start recovery\n"));
if (ctdb->methods != NULL) {
ctdb->methods->shutdown(ctdb);
}
- ctdb_event_script(ctdb, "shutdown");
+ ctdb_event_script(ctdb, CTDB_EVENT_SHUTDOWN);
DEBUG(DEBUG_ERR, ("Recovery daemon ping timeout. Daemon has been shut down.\n"));
exit(0);
}
ret = ctdb_event_script_callback(ctdb, state,
ctdb_stop_node_callback,
- state, "stopped");
+ state, CTDB_EVENT_STOPPED, "%s", "");
if (ret != 0) {
ctdb_enable_monitoring(ctdb);
if (ctdb->methods != NULL) {
ctdb->methods->shutdown(ctdb);
}
- ctdb_event_script(ctdb, "shutdown");
+ ctdb_event_script(ctdb, CTDB_EVENT_SHUTDOWN);
exit(10);
}
ret = ctdb_event_script_callback(ctdb,
state, takeover_ip_callback, state,
- "takeip %s %s %u",
+ CTDB_EVENT_TAKE_IP,
+ "%s %s %u",
vnn->iface,
talloc_strdup(state, ctdb_addr_to_str(&pip->addr)),
vnn->public_netmask_bits);
ret = ctdb_event_script_callback(ctdb,
state, release_ip_callback, state,
- "releaseip %s %s %u",
+ CTDB_EVENT_RELEASE_IP,
+ "%s %s %u",
vnn->iface,
talloc_strdup(state, ctdb_addr_to_str(&pip->addr)),
vnn->public_netmask_bits);
if (vnn->pnn == ctdb->pnn) {
vnn->pnn = -1;
}
- ctdb_event_script(ctdb, "releaseip %s %s %u",
+ ctdb_event_script_args(ctdb, CTDB_EVENT_RELEASE_IP, "%s %s %u",
vnn->iface,
talloc_strdup(ctdb, ctdb_addr_to_str(&vnn->public_address)),
vnn->public_netmask_bits);
ret = ctdb_event_script_callback(ctdb,
mem_ctx, delete_ip_callback, mem_ctx,
- "releaseip %s %s %u",
+ CTDB_EVENT_RELEASE_IP,
+ "%s %s %u",
vnn->iface,
talloc_strdup(mem_ctx, ctdb_addr_to_str(&vnn->public_address)),
vnn->public_netmask_bits);
const char *script_running;
} child_state;
+static const char *call_names[] = {
+ "startup",
+ "startrecovery",
+ "recovered",
+ "takeip",
+ "releaseip",
+ "stopped",
+ "monitor",
+ "status",
+ "shutdown",
+ ""
+};
+
static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *p);
/*
static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
void (*callback)(struct ctdb_context *, int, void *),
void *private_data,
+ enum ctdb_eventscript_call call,
const char *fmt, va_list ap)
{
TALLOC_CTX *mem_ctx;
struct ctdb_event_script_state *state;
int ret;
- if (!strcmp(fmt, "monitor") || !strcmp(fmt, "status")) {
+ if (call == CTDB_EVENT_MONITOR || call == CTDB_EVENT_STATUS) {
/* if this was a "monitor" or a status event, we recycle the
context to start a new monitor event
*/
state->ctdb = ctdb;
state->callback = callback;
state->private_data = private_data;
- state->options = talloc_vasprintf(state, fmt, ap);
+ state->options = talloc_asprintf(state, "%s ", call_names[call]);
+ if (state->options)
+ state->options = talloc_vasprintf_append(discard_const_p(char, state->options), fmt, ap);
state->timeout = timeval_set(ctdb->tunable.script_timeout, 0);
if (state->options == NULL) {
DEBUG(DEBUG_ERR, (__location__ " could not allocate state->options\n"));
TALLOC_CTX *mem_ctx,
void (*callback)(struct ctdb_context *, int, void *),
void *private_data,
+ enum ctdb_eventscript_call call,
const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
- ret = ctdb_event_script_callback_v(ctdb, callback, private_data, fmt, ap);
+ ret = ctdb_event_script_callback_v(ctdb, callback, private_data, call, fmt, ap);
va_end(ap);
return ret;
run the event script, waiting for it to complete. Used when the caller
doesn't want to continue till the event script has finished.
*/
-int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
+int ctdb_event_script_args(struct ctdb_context *ctdb, enum ctdb_eventscript_call call,
+ const char *fmt, ...)
{
va_list ap;
int ret;
struct callback_status status;
va_start(ap, fmt);
- ret = ctdb_event_script_callback_v(ctdb,
- event_script_callback, &status, fmt, ap);
- va_end(ap);
-
+ ret = ctdb_event_script_callback_v(ctdb,
+ event_script_callback, &status, call, fmt, ap);
if (ret != 0) {
return ret;
}
+ va_end(ap);
status.status = -1;
status.done = false;
return status.status;
}
+int ctdb_event_script(struct ctdb_context *ctdb, enum ctdb_eventscript_call call)
+{
+ /* GCC complains about empty format string, so use %s and "". */
+ return ctdb_event_script_args(ctdb, call, "%s", "");
+}
struct eventscript_callback_state {
struct ctdb_req_control *c;
ret = ctdb_event_script_callback(ctdb,
state, run_eventscripts_callback, state,
- "%s", (const char *)indata.dptr);
+ CTDB_EVENT_UNKNOWN, "%s", (const char *)indata.dptr);
if (ret != 0) {
ctdb_enable_monitoring(ctdb);