summaryrefslogtreecommitdiffstats
path: root/ctdb
diff options
context:
space:
mode:
authorRonnie Sahlberg <ronniesahlberg@gmail.com>2009-08-13 13:04:08 +1000
committerRonnie Sahlberg <ronniesahlberg@gmail.com>2009-08-13 13:04:08 +1000
commit1cc79905adaf15ccf5092d27af1c3827e3c7f176 (patch)
tree8d89b8dfa8d1ee4f09c9aedb2ec0d61818d41b3d /ctdb
parent8f393eb987ac34020ce116f6b4a2bb3f6f84238a (diff)
downloadsamba-1cc79905adaf15ccf5092d27af1c3827e3c7f176.tar.gz
samba-1cc79905adaf15ccf5092d27af1c3827e3c7f176.tar.xz
samba-1cc79905adaf15ccf5092d27af1c3827e3c7f176.zip
add new controls to make it possible to enable/disable individual eventscripts
update scriptstatus output so it lists disabled scripts (This used to be ctdb commit 7e799b7523c9699bd65a8a8207f7e03d668b0b81)
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/client/ctdb_client.c66
-rw-r--r--ctdb/include/ctdb.h4
-rw-r--r--ctdb/include/ctdb_private.h8
-rw-r--r--ctdb/server/ctdb_control.c9
-rw-r--r--ctdb/server/eventscript.c382
-rw-r--r--ctdb/tools/ctdb.c49
6 files changed, 440 insertions, 78 deletions
diff --git a/ctdb/client/ctdb_client.c b/ctdb/client/ctdb_client.c
index 2e7a0936ff..a6135c9052 100644
--- a/ctdb/client/ctdb_client.c
+++ b/ctdb/client/ctdb_client.c
@@ -3568,6 +3568,27 @@ int ctdb_ctrl_event_script_stop(struct ctdb_context *ctdb, int32_t result)
return 0;
}
+/*
+ tell the main daemon a script was disabled
+ */
+int ctdb_ctrl_event_script_disabled(struct ctdb_context *ctdb, const char *name)
+{
+ int ret;
+ int32_t res;
+ TDB_DATA data;
+
+ data.dptr = discard_const(name);
+ data.dsize = strlen(name)+1;
+
+ ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_EVENT_SCRIPT_DISABLED, 0, data,
+ ctdb, NULL, &res, NULL, NULL);
+ if (ret != 0 || res != 0) {
+ DEBUG(DEBUG_ERR,("Failed to send event_script_disabeld\n"));
+ return -1;
+ }
+
+ return 0;
+}
/*
get the status of running the monitor eventscripts
@@ -3776,3 +3797,48 @@ int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout
return 0;
}
+
+/* enable an eventscript
+ */
+int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
+{
+ int ret;
+ TDB_DATA data;
+ int32_t res;
+
+ data.dsize = strlen(script) + 1;
+ data.dptr = discard_const(script);
+
+ ret = ctdb_control(ctdb, destnode, 0,
+ CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
+ NULL, NULL, &res, &timeout, NULL);
+ if (ret != 0 || res != 0) {
+ DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+/* disable an eventscript
+ */
+int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
+{
+ int ret;
+ TDB_DATA data;
+ int32_t res;
+
+ data.dsize = strlen(script) + 1;
+ data.dptr = discard_const(script);
+
+ ret = ctdb_control(ctdb, destnode, 0,
+ CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
+ NULL, NULL, &res, &timeout, NULL);
+ if (ret != 0 || res != 0) {
+ DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/ctdb/include/ctdb.h b/ctdb/include/ctdb.h
index a5d6639d6b..f6773598dc 100644
--- a/ctdb/include/ctdb.h
+++ b/ctdb/include/ctdb.h
@@ -634,6 +634,7 @@ struct ctdb_monitoring_script_wire {
char name[MAX_SCRIPT_NAME+1];
struct timeval start;
struct timeval finished;
+ int32_t disabled;
int32_t status;
int32_t timedout;
char output[MAX_SCRIPT_OUTPUT+1];
@@ -665,4 +666,7 @@ int ctdb_ctrl_setnatgwstate(struct ctdb_context *ctdb, struct timeval timeout, u
int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole);
int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole);
+int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script);
+int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script);
+
#endif
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index 63e3d3889b..0660dc8851 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -584,6 +584,9 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0,
CTDB_CONTROL_SET_NATGWSTATE = 103,
CTDB_CONTROL_SET_LMASTERROLE = 104,
CTDB_CONTROL_SET_RECMASTERROLE = 105,
+ CTDB_CONTROL_EVENT_SCRIPT_DISABLED = 106,
+ CTDB_CONTROL_ENABLE_SCRIPT = 107,
+ CTDB_CONTROL_DISABLE_SCRIPT = 108,
};
/*
@@ -1444,10 +1447,12 @@ int ctdb_ctrl_event_script_init(struct ctdb_context *ctdb);
int ctdb_ctrl_event_script_start(struct ctdb_context *ctdb, const char *name);
int ctdb_ctrl_event_script_stop(struct ctdb_context *ctdb, int32_t res);
int ctdb_ctrl_event_script_finished(struct ctdb_context *ctdb);
+int ctdb_ctrl_event_script_disabled(struct ctdb_context *ctdb, const char *name);
int32_t ctdb_control_event_script_init(struct ctdb_context *ctdb);
int32_t ctdb_control_event_script_start(struct ctdb_context *ctdb, TDB_DATA indata);
int32_t ctdb_control_event_script_stop(struct ctdb_context *ctdb, TDB_DATA indata);
+int32_t ctdb_control_event_script_disabled(struct ctdb_context *ctdb, TDB_DATA indata);
int32_t ctdb_control_event_script_finished(struct ctdb_context *ctdb);
@@ -1461,4 +1466,7 @@ int32_t ctdb_control_continue_node(struct ctdb_context *ctdb);
int ctdb_vacuum_init(struct ctdb_db_context *ctdb_db);
+int32_t ctdb_control_enable_script(struct ctdb_context *ctdb, TDB_DATA indata);
+int32_t ctdb_control_disable_script(struct ctdb_context *ctdb, TDB_DATA indata);
+
#endif
diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c
index e43089ce93..7798d526ac 100644
--- a/ctdb/server/ctdb_control.c
+++ b/ctdb/server/ctdb_control.c
@@ -437,6 +437,9 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
CHECK_CONTROL_DATA_SIZE(0);
return ctdb_control_event_script_finished(ctdb);
+ case CTDB_CONTROL_EVENT_SCRIPT_DISABLED:
+ return ctdb_control_event_script_disabled(ctdb, indata);
+
case CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS:
CHECK_CONTROL_DATA_SIZE(0);
return ctdb_control_get_event_script_status(ctdb, outdata);
@@ -509,6 +512,12 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
return 0;
}
+ case CTDB_CONTROL_ENABLE_SCRIPT:
+ return ctdb_control_enable_script(ctdb, indata);
+
+ case CTDB_CONTROL_DISABLE_SCRIPT:
+ return ctdb_control_disable_script(ctdb, indata);
+
default:
DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
return -1;
diff --git a/ctdb/server/eventscript.c b/ctdb/server/eventscript.c
index 9ea2e120e4..fc933528e8 100644
--- a/ctdb/server/eventscript.c
+++ b/ctdb/server/eventscript.c
@@ -58,6 +58,7 @@ struct ctdb_monitor_script_status {
const char *name;
struct timeval start;
struct timeval finished;
+ int32_t disabled;
int32_t status;
int32_t timedout;
char *output;
@@ -188,6 +189,36 @@ int32_t ctdb_control_event_script_stop(struct ctdb_context *ctdb, TDB_DATA indat
return 0;
}
+/* called from the event script child process when we have a disabled script
+ */
+int32_t ctdb_control_event_script_disabled(struct ctdb_context *ctdb, TDB_DATA indata)
+{
+ int32_t res = *((int32_t *)indata.dptr);
+ struct ctdb_monitoring_status *monitoring_status =
+ talloc_get_type(ctdb->script_monitoring_ctx,
+ struct ctdb_monitoring_status);
+ struct ctdb_monitor_script_status *script;
+
+ DEBUG(DEBUG_INFO, ("event script disabed called : %d\n", (int)res));
+
+ if (monitoring_status == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " script_status is NULL when script finished.\n"));
+ return -1;
+ }
+
+ script = monitoring_status->scripts;
+ if (script == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " script is NULL when the script had finished\n"));
+ return -1;
+ }
+
+ script->finished = timeval_current();
+ script->status = res;
+ script->disabled = 1;
+
+ return 0;
+}
+
/* called from the event script child process when we have completed a
* monitor event
*/
@@ -232,6 +263,7 @@ static struct ctdb_monitoring_wire *marshall_monitoring_scripts(TALLOC_CTX *mem_
strncpy(script_wire.name, script->name, MAX_SCRIPT_NAME);
script_wire.start = script->start;
script_wire.finished = script->finished;
+ script_wire.disabled = script->disabled;
script_wire.status = script->status;
script_wire.timedout = script->timedout;
if (script->output != NULL) {
@@ -282,73 +314,27 @@ int32_t ctdb_control_get_event_script_status(struct ctdb_context *ctdb, TDB_DATA
return 0;
}
-/*
- run the event script - varargs version
- this function is called and run in the context of a forked child
- which allows it to do blocking calls such as system()
- */
-static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *options)
+struct ctdb_script_tree_item {
+ const char *name;
+ int32_t is_enabled;
+};
+
+struct ctdb_script_list {
+ struct ctdb_script_list *next;
+ const char *name;
+ int32_t is_enabled;
+};
+
+static struct ctdb_script_list *ctdb_get_script_list(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx)
{
- char *cmdstr;
- int ret;
- struct stat st;
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- trbt_tree_t *tree;
DIR *dir;
struct dirent *de;
- char *script;
+ struct stat st;
+ trbt_tree_t *tree;
+ struct ctdb_script_list *head, *tail, *new_item;
+ TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+ struct ctdb_script_tree_item *tree_item;
int count;
- int is_monitor = 0;
- char *d_name_dup;
-
- if (!strcmp(options, "monitor")) {
- is_monitor = 1;
- }
-
- if (is_monitor == 1) {
- /* This is running in the forked child process. At this stage
- * we want to switch from being a ctdb daemon into being a
- * client and connect to the real local daemon.
- */
- if (switch_from_server_to_client(ctdb) != 0) {
- DEBUG(DEBUG_CRIT, (__location__ "ERROR: failed to switch eventscript child into client mode. shutting down.\n"));
- _exit(1);
- }
-
- if (ctdb_ctrl_event_script_init(ctdb) != 0) {
- DEBUG(DEBUG_ERR,(__location__ " Failed to init event script monitoring\n"));
- talloc_free(tmp_ctx);
- return -1;
- }
- }
-
- if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
- /* we guarantee that only some specifically allowed event scripts are run
- while in recovery */
- const char *allowed_scripts[] = {"startrecovery", "shutdown", "releaseip", "stopped" };
- int i;
- for (i=0;i<ARRAY_SIZE(allowed_scripts);i++) {
- if (strncmp(options, allowed_scripts[i], strlen(allowed_scripts[i])) == 0) break;
- }
- if (i == ARRAY_SIZE(allowed_scripts)) {
- DEBUG(DEBUG_ERR,("Refusing to run event scripts with option '%s' while in recovery\n",
- options));
- talloc_free(tmp_ctx);
- return -1;
- }
- }
-
- if (setpgid(0,0) != 0) {
- DEBUG(DEBUG_ERR,("Failed to create process group for event scripts - %s\n",
- strerror(errno)));
- talloc_free(tmp_ctx);
- return -1;
- }
-
- signal(SIGTERM, sigterm);
-
- child_state.start = timeval_current();
- child_state.script_running = "startup";
/*
the service specific event scripts
@@ -357,7 +343,7 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *options)
errno == ENOENT) {
DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
talloc_free(tmp_ctx);
- return -1;
+ return NULL;
}
/* create a tree to store all the script names in */
@@ -370,7 +356,7 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *options)
if (dir == NULL) {
DEBUG(DEBUG_CRIT,("Failed to open event script directory '%s'\n", ctdb->event_script_dir));
talloc_free(tmp_ctx);
- return -1;
+ return NULL;
}
count = 0;
@@ -404,26 +390,145 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *options)
DEBUG(DEBUG_ERR,("Could not stat event script %s. Ignoring this event script\n", str));
continue;
}
+
+
+ tree_item = talloc(tree, struct ctdb_script_tree_item);
+ if (tree_item == NULL) {
+ DEBUG(DEBUG_ERR, (__location__ " Failed to allocate new tree item\n"));
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ tree_item->is_enabled = 1;
if (!(st.st_mode & S_IXUSR)) {
DEBUG(DEBUG_INFO,("Event script %s is not executable. Ignoring this event script\n", str));
- continue;
+ tree_item->is_enabled = 0;
}
-
-
+
+ tree_item->name = talloc_strdup(tree_item, de->d_name);
+ if (tree_item->name == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " Failed to allocate script name.\n"));
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
/* store the event script in the tree */
- d_name_dup = talloc_strdup(tree, de->d_name);
- CTDB_NO_MEMORY(ctdb, d_name_dup);
- trbt_insert32(tree, (num<<16)|count++, d_name_dup);
+ trbt_insert32(tree, (num<<16)|count++, tree_item);
}
closedir(dir);
+
+ head = NULL;
+ tail = NULL;
+
+ /* fetch the scripts from the tree one by one and add them to the linked
+ list
+ */
+ while ((tree_item=trbt_findfirstarray32(tree, 1)) != NULL) {
+
+ new_item = talloc(tmp_ctx, struct ctdb_script_list);
+ if (new_item == NULL) {
+ DEBUG(DEBUG_ERR, (__location__ " Failed to allocate new list item\n"));
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ new_item->next = NULL;
+ new_item->name = talloc_steal(new_item, tree_item->name);
+ new_item->is_enabled = tree_item->is_enabled;
+
+ if (head == NULL) {
+ head = new_item;
+ tail = new_item;
+ } else {
+ tail->next = new_item;
+ tail = new_item;
+ }
+
+ talloc_steal(mem_ctx, new_item);
+
+ /* remove this script from the tree */
+ talloc_free(tree_item);
+ }
+
+ talloc_free(tmp_ctx);
+ return head;
+}
+
+
+
+/*
+ run the event script - varargs version
+ this function is called and run in the context of a forked child
+ which allows it to do blocking calls such as system()
+ */
+static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *options)
+{
+ char *cmdstr;
+ int ret;
+ TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+ struct ctdb_script_list *scripts, *current;
+ int is_monitor = 0;
+
+ if (!strcmp(options, "monitor")) {
+ is_monitor = 1;
+ }
+
+ if (is_monitor == 1) {
+ /* This is running in the forked child process. At this stage
+ * we want to switch from being a ctdb daemon into being a
+ * client and connect to the real local daemon.
+ */
+ if (switch_from_server_to_client(ctdb) != 0) {
+ DEBUG(DEBUG_CRIT, (__location__ "ERROR: failed to switch eventscript child into client mode. shutting down.\n"));
+ _exit(1);
+ }
+
+ if (ctdb_ctrl_event_script_init(ctdb) != 0) {
+ DEBUG(DEBUG_ERR,(__location__ " Failed to init event script monitoring\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+ }
+
+ if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
+ /* we guarantee that only some specifically allowed event scripts are run
+ while in recovery */
+ const char *allowed_scripts[] = {"startrecovery", "shutdown", "releaseip", "stopped" };
+ int i;
+ for (i=0;i<ARRAY_SIZE(allowed_scripts);i++) {
+ if (strncmp(options, allowed_scripts[i], strlen(allowed_scripts[i])) == 0) break;
+ }
+ if (i == ARRAY_SIZE(allowed_scripts)) {
+ DEBUG(DEBUG_ERR,("Refusing to run event scripts with option '%s' while in recovery\n",
+ options));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+ }
+
+ if (setpgid(0,0) != 0) {
+ DEBUG(DEBUG_ERR,("Failed to create process group for event scripts - %s\n",
+ strerror(errno)));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ signal(SIGTERM, sigterm);
+
+ child_state.start = timeval_current();
+ child_state.script_running = "startup";
+
+ scripts = ctdb_get_script_list(ctdb, tmp_ctx);
+
/* fetch the scripts from the tree one by one and execute
them
*/
- while ((script=trbt_findfirstarray32(tree, 1)) != NULL) {
+ for (current=scripts; current; current=current->next) {
+ /* we dont run disabled scripts, we just report they are disabled */
cmdstr = talloc_asprintf(tmp_ctx, "%s/%s %s",
ctdb->event_script_dir,
- script, options);
+ current->name, options);
CTDB_NO_MEMORY(ctdb, cmdstr);
DEBUG(DEBUG_INFO,("Executing event script %s\n",cmdstr));
@@ -432,11 +537,24 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *options)
child_state.script_running = cmdstr;
if (is_monitor == 1) {
- if (ctdb_ctrl_event_script_start(ctdb, script) != 0) {
+ if (ctdb_ctrl_event_script_start(ctdb, current->name) != 0) {
DEBUG(DEBUG_ERR,(__location__ " Failed to start event script monitoring\n"));
talloc_free(tmp_ctx);
return -1;
}
+
+ if (!current->is_enabled) {
+ if (ctdb_ctrl_event_script_disabled(ctdb, current->name) != 0) {
+ DEBUG(DEBUG_ERR,(__location__ " Failed to report disabled eventscript\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+ }
+
+ }
+
+ if (!current->is_enabled) {
+ continue;
}
ret = system(cmdstr);
@@ -468,9 +586,6 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *options)
talloc_free(tmp_ctx);
return ret;
}
-
- /* remove this script from the tree */
- talloc_free(script);
}
child_state.start = timeval_current();
@@ -814,3 +929,116 @@ int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb,
return 0;
}
+
+
+int32_t ctdb_control_enable_script(struct ctdb_context *ctdb, TDB_DATA indata)
+{
+ const char *script;
+ struct stat st;
+ char *filename;
+ TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+
+ script = (char *)indata.dptr;
+ if (indata.dsize == 0) {
+ DEBUG(DEBUG_ERR,(__location__ " No script specified.\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+ if (indata.dptr[indata.dsize - 1] != '\0') {
+ DEBUG(DEBUG_ERR,(__location__ " String is not null terminated.\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+ if (index(script,'/') != NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " Script name contains '/'. Failed to enable script %s\n", script));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+
+ if (stat(ctdb->event_script_dir, &st) != 0 &&
+ errno == ENOENT) {
+ DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+
+ filename = talloc_asprintf(tmp_ctx, "%s/%s", ctdb->event_script_dir, script);
+ if (filename == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " Failed to create script path\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ if (stat(filename, &st) != 0) {
+ DEBUG(DEBUG_ERR,("Could not stat event script %s. Failed to enable script.\n", filename));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ if (chmod(filename, st.st_mode | S_IXUSR) == -1) {
+ DEBUG(DEBUG_ERR,("Could not chmod %s. Failed to enable script.\n", filename));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ talloc_free(tmp_ctx);
+ return 0;
+}
+
+int32_t ctdb_control_disable_script(struct ctdb_context *ctdb, TDB_DATA indata)
+{
+ const char *script;
+ struct stat st;
+ char *filename;
+ TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+
+ script = (char *)indata.dptr;
+ if (indata.dsize == 0) {
+ DEBUG(DEBUG_ERR,(__location__ " No script specified.\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+ if (indata.dptr[indata.dsize - 1] != '\0') {
+ DEBUG(DEBUG_ERR,(__location__ " String is not null terminated.\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+ if (index(script,'/') != NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " Script name contains '/'. Failed to disable script %s\n", script));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+
+ if (stat(ctdb->event_script_dir, &st) != 0 &&
+ errno == ENOENT) {
+ DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+
+ filename = talloc_asprintf(tmp_ctx, "%s/%s", ctdb->event_script_dir, script);
+ if (filename == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " Failed to create script path\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ if (stat(filename, &st) != 0) {
+ DEBUG(DEBUG_ERR,("Could not stat event script %s. Failed to disable script.\n", filename));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ if (chmod(filename, st.st_mode & ~(S_IXUSR|S_IXGRP|S_IXOTH)) == -1) {
+ DEBUG(DEBUG_ERR,("Could not chmod %s. Failed to disable script.\n", filename));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ talloc_free(tmp_ctx);
+ return 0;
+}
diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c
index 90c7862911..a419e23aca 100644
--- a/ctdb/tools/ctdb.c
+++ b/ctdb/tools/ctdb.c
@@ -734,6 +734,11 @@ static int control_scriptstatus(struct ctdb_context *ctdb, int argc, const char
printf("%d scripts were executed last monitoring cycle\n", script_status->num_scripts);
for (i=0; i<script_status->num_scripts; i++) {
+ if (script_status->scripts[i].disabled) {
+ printf("%-20s Status:DISABLED\n",
+ script_status->scripts[i].name);
+ continue;
+ }
printf("%-20s Status:%s ",
script_status->scripts[i].name,
script_status->scripts[i].timedout?"TIMEDOUT":script_status->scripts[i].status==0?"OK":"ERROR");
@@ -756,6 +761,46 @@ static int control_scriptstatus(struct ctdb_context *ctdb, int argc, const char
/*
+ enable an eventscript
+ */
+static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+ int ret;
+
+ if (argc < 1) {
+ usage();
+ }
+
+ ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ disable an eventscript
+ */
+static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+ int ret;
+
+ if (argc < 1) {
+ usage();
+ }
+
+ ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
display the pnn of the recovery master
*/
static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
@@ -3343,7 +3388,9 @@ static const struct {
{ "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
{ "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
{ "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
- { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts"},
+ { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts"},
+ { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
+ { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
{ "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
{ "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
{ "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},