add new controls to make it possible to enable/disable individual eventscripts
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Thu, 13 Aug 2009 03:04:08 +0000 (13:04 +1000)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Thu, 13 Aug 2009 03:04:08 +0000 (13:04 +1000)
update scriptstatus output so it lists disabled scripts

client/ctdb_client.c
include/ctdb.h
include/ctdb_private.h
server/ctdb_control.c
server/eventscript.c
tools/ctdb.c

index 2e7a0936ff583f548a6b62a0e8913e6538829074..a6135c905232dea51739b51df87347e4c58c4772 100644 (file)
@@ -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;
+}
+
index a5d6639d6bf60359bcd126642a4247190e303e93..f6773598dc9568d293b72969ad5f9f2143e7248c 100644 (file)
@@ -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
index 63e3d3889bc3321b8234dc9b1ab0b5c4e77cd82a..0660dc88517dedce043156a0e2d2cd77be43f240 100644 (file)
@@ -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
index e43089ce9397d3125b03c643a3f70d2ca8e66b97..7798d526ac8edee5a220ea62e4621a5a554c3872 100644 (file)
@@ -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;
index 9ea2e120e44e1d840b6ed099f8ceb92fb7a5c360..fc933528e862871ffee07a531e6d9c83b939f438 100644 (file)
@@ -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;
+}
index 90c786291104c713a0a666e71b8feec3d8d26016..a419e23acaac76b8bf057df01d088c2e673a666a 100644 (file)
@@ -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");
@@ -755,6 +760,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
  */
@@ -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"},