eventscript: use direct script state pointer for current monitor
[sahlberg/ctdb.git] / server / eventscript.c
1 /* 
2    event script handling
3
4    Copyright (C) Andrew Tridgell  2007
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include <time.h>
22 #include "system/filesys.h"
23 #include "system/wait.h"
24 #include "system/dir.h"
25 #include "system/locale.h"
26 #include "../include/ctdb_private.h"
27 #include "lib/events/events.h"
28 #include "../common/rb_tree.h"
29
30 static struct {
31         struct timeval start;
32         const char *script_running;
33 } child_state;
34
35 static const char *call_names[] = {
36         "startup",
37         "startrecovery",
38         "recovered",
39         "takeip",
40         "releaseip",
41         "stopped",
42         "monitor",
43         "status",
44         "shutdown",
45         "reload"
46 };
47
48 static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *p);
49
50 /*
51   ctdbd sends us a SIGTERM when we should time out the current script
52  */
53 static void sigterm(int sig)
54 {
55         char tbuf[100], buf[200];
56         time_t t;
57
58         DEBUG(DEBUG_ERR,("Timed out running script '%s' after %.1f seconds pid :%d\n", 
59                  child_state.script_running, timeval_elapsed(&child_state.start), getpid()));
60
61         t = time(NULL);
62
63         strftime(tbuf, sizeof(tbuf)-1, "%Y%m%d%H%M%S",  localtime(&t));
64         sprintf(buf, "pstree -p >/tmp/ctdb.event.%s.%d", tbuf, getpid());
65         system(buf);
66
67         DEBUG(DEBUG_ERR,("Logged timedout eventscript : %s\n", buf));
68
69         /* all the child processes will be running in the same process group */
70         kill(-getpgrp(), SIGKILL);
71         _exit(1);
72 }
73
74 struct ctdb_event_script_state {
75         struct ctdb_context *ctdb;
76         pid_t child;
77         /* Warning: this can free us! */
78         void (*callback)(struct ctdb_context *, int, void *);
79         int cb_status;
80         int fd[2];
81         void *private_data;
82         enum ctdb_eventscript_call call;
83         const char *options;
84         struct timeval timeout;
85
86         struct ctdb_monitor_script_status *scripts;
87 };
88
89
90 struct ctdb_monitor_script_status {
91         struct ctdb_monitor_script_status *next;
92         const char *name;
93         struct timeval start;
94         struct timeval finished;
95         int32_t status;
96         char *output;
97 };
98
99 /* called from ctdb_logging when we have received output on STDERR from
100  * one of the eventscripts
101  */
102 int ctdb_log_event_script_output(struct ctdb_context *ctdb, char *str, uint16_t len)
103 {
104         struct ctdb_monitor_script_status *script;
105
106         if (ctdb->current_monitor == NULL) {
107                 return -1;
108         }
109
110         script = ctdb->current_monitor->scripts;
111         if (script == NULL) {
112                 return -1;
113         }
114
115         if (script->output == NULL) {
116                 script->output = talloc_asprintf(script, "%*.*s", len, len, str);
117         } else {
118                 script->output = talloc_asprintf_append(script->output, "%*.*s", len, len, str);
119         }
120
121         return 0;
122 }
123
124 /* called from the event script child process when we are starting a new
125  * monitor event
126  */
127 int32_t ctdb_control_event_script_init(struct ctdb_context *ctdb)
128 {
129         DEBUG(DEBUG_INFO, ("event script init called\n"));
130
131         if (ctdb->current_monitor == NULL) {
132                 DEBUG(DEBUG_ERR,(__location__ " current_monitor_status_ctx is NULL when initing script\n"));
133                 return -1;
134         }
135
136         return 0;
137 }
138
139
140 /* called from the event script child process when we are star running
141  * an eventscript
142  */
143 int32_t ctdb_control_event_script_start(struct ctdb_context *ctdb, TDB_DATA indata)
144 {
145         const char *name = (const char *)indata.dptr;
146         struct ctdb_monitor_script_status *script;
147
148         DEBUG(DEBUG_INFO, ("event script start called : %s\n", name));
149
150         if (ctdb->current_monitor == NULL) {
151                 DEBUG(DEBUG_ERR,(__location__ " current_monitor_status_ctx is NULL when starting script\n"));
152                 return -1;
153         }
154
155         script = talloc_zero(ctdb->current_monitor, struct ctdb_monitor_script_status);
156         if (script == NULL) {
157                 DEBUG(DEBUG_ERR,(__location__ " Failed to talloc ctdb_monitor_script_status for script %s\n", name));
158                 return -1;
159         }
160
161         script->next  = ctdb->current_monitor->scripts;
162         script->name  = talloc_strdup(script, name);
163         CTDB_NO_MEMORY(ctdb, script->name);
164         script->start = timeval_current();
165         ctdb->current_monitor->scripts = script;
166
167         return 0;
168 }
169
170 /* called from the event script child process when we have finished running
171  * an eventscript
172  */
173 int32_t ctdb_control_event_script_stop(struct ctdb_context *ctdb, TDB_DATA indata)
174 {
175         int32_t res = *((int32_t *)indata.dptr);
176         struct ctdb_monitor_script_status *script;
177
178         if (ctdb->current_monitor == NULL) {
179                 DEBUG(DEBUG_ERR,(__location__ " current_monitor_status_ctx is NULL when script finished\n"));
180                 return -1;
181         }
182
183         script = ctdb->current_monitor->scripts;
184         if (script == NULL) {
185                 DEBUG(DEBUG_ERR,(__location__ " script is NULL when the script had finished\n"));
186                 return -1;
187         }
188
189         script->finished = timeval_current();
190         script->status   = res;
191
192         DEBUG(DEBUG_INFO, ("event script stop called for script:%s duration:%.1f status:%d\n", script->name, timeval_elapsed(&script->start), (int)res));
193
194         return 0;
195 }
196
197 static struct ctdb_monitoring_wire *marshall_monitoring_scripts(TALLOC_CTX *mem_ctx, struct ctdb_monitoring_wire *monitoring_scripts, struct ctdb_monitor_script_status *script)
198 {
199         struct ctdb_monitoring_script_wire script_wire;
200         size_t size;
201
202         if (script == NULL) {
203                 return monitoring_scripts;
204         }
205         monitoring_scripts = marshall_monitoring_scripts(mem_ctx, monitoring_scripts, script->next);
206         if (monitoring_scripts == NULL) {
207                 return NULL;
208         }
209
210         bzero(&script_wire, sizeof(struct ctdb_monitoring_script_wire));
211         strncpy(script_wire.name, script->name, MAX_SCRIPT_NAME);
212         script_wire.start    = script->start;
213         script_wire.finished = script->finished;
214         script_wire.status   = script->status;
215         if (script->output != NULL) {
216                 strncpy(script_wire.output, script->output, MAX_SCRIPT_OUTPUT);
217         }
218
219         size = talloc_get_size(monitoring_scripts);
220         monitoring_scripts = talloc_realloc_size(mem_ctx, monitoring_scripts, size + sizeof(struct ctdb_monitoring_script_wire));
221         if (monitoring_scripts == NULL) {
222                 DEBUG(DEBUG_ERR,(__location__ " Failed to talloc_resize monitoring_scripts blob\n"));
223                 return NULL;
224         }
225
226         memcpy(&monitoring_scripts->scripts[monitoring_scripts->num_scripts], &script_wire, sizeof(script_wire));
227         monitoring_scripts->num_scripts++;
228         
229         return monitoring_scripts;
230 }
231
232 /* called from the event script child process when we have completed a
233  * monitor event
234  */
235 int32_t ctdb_control_event_script_finished(struct ctdb_context *ctdb)
236 {
237         DEBUG(DEBUG_INFO, ("event script finished called\n"));
238
239         if (ctdb->current_monitor == NULL) {
240                 DEBUG(DEBUG_ERR,(__location__ " script_status is NULL when monitoring event finished\n"));
241                 return -1;
242         }
243
244         talloc_free(ctdb->last_status);
245         ctdb->last_status = talloc_size(ctdb, offsetof(struct ctdb_monitoring_wire, scripts));
246         if (ctdb->last_status == NULL) {
247                 DEBUG(DEBUG_ERR,(__location__ " failed to talloc last_status\n"));
248                 return -1;
249         }
250
251         ctdb->last_status->num_scripts = 0;
252         ctdb->last_status = marshall_monitoring_scripts(ctdb, ctdb->last_status, ctdb->current_monitor->scripts);
253         talloc_free(ctdb->current_monitor->scripts);
254         ctdb->current_monitor->scripts = NULL;
255
256         return 0;
257 }
258
259 int32_t ctdb_control_get_event_script_status(struct ctdb_context *ctdb, TDB_DATA *outdata)
260 {
261         struct ctdb_monitoring_wire *monitoring_scripts = ctdb->last_status;
262
263         if (monitoring_scripts == NULL) {
264                 DEBUG(DEBUG_ERR,(__location__ " last_monitor_status_ctx is NULL when reading status\n"));
265                 return -1;
266         }
267
268         outdata->dsize = talloc_get_size(monitoring_scripts);
269         outdata->dptr  = (uint8_t *)monitoring_scripts;
270
271         return 0;
272 }
273
274 struct ctdb_script_tree_item {
275         const char *name;
276         int error;
277 };
278
279 struct ctdb_script_list {
280         struct ctdb_script_list *next;
281         const char *name;
282         int error;
283 };
284
285 /* Return true if OK, otherwise set errno. */
286 static bool check_executable(const char *dir, const char *name)
287 {
288         char *full;
289         struct stat st;
290
291         full = talloc_asprintf(NULL, "%s/%s", dir, name);
292         if (!full)
293                 return false;
294
295         if (stat(full, &st) != 0) {
296                 DEBUG(DEBUG_ERR,("Could not stat event script %s: %s\n",
297                                  full, strerror(errno)));
298                 talloc_free(full);
299                 return false;
300         }
301
302         if (!(st.st_mode & S_IXUSR)) {
303                 DEBUG(DEBUG_INFO,("Event script %s is not executable. Ignoring this event script\n", full));
304                 errno = ENOEXEC;
305                 talloc_free(full);
306                 return false;
307         }
308
309         talloc_free(full);
310         return true;
311 }
312
313 static struct ctdb_script_list *ctdb_get_script_list(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx)
314 {
315         DIR *dir;
316         struct dirent *de;
317         struct stat st;
318         trbt_tree_t *tree;
319         struct ctdb_script_list *head, *tail, *new_item;
320         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
321         struct ctdb_script_tree_item *tree_item;
322         int count;
323
324         /*
325           the service specific event scripts 
326         */
327         if (stat(ctdb->event_script_dir, &st) != 0 && 
328             errno == ENOENT) {
329                 DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
330                 talloc_free(tmp_ctx);
331                 return NULL;
332         }
333
334         /* create a tree to store all the script names in */
335         tree = trbt_create(tmp_ctx, 0);
336
337         /* scan all directory entries and insert all valid scripts into the 
338            tree
339         */
340         dir = opendir(ctdb->event_script_dir);
341         if (dir == NULL) {
342                 DEBUG(DEBUG_CRIT,("Failed to open event script directory '%s'\n", ctdb->event_script_dir));
343                 talloc_free(tmp_ctx);
344                 return NULL;
345         }
346
347         count = 0;
348         while ((de=readdir(dir)) != NULL) {
349                 int namlen;
350                 unsigned num;
351
352                 namlen = strlen(de->d_name);
353
354                 if (namlen < 3) {
355                         continue;
356                 }
357
358                 if (de->d_name[namlen-1] == '~') {
359                         /* skip files emacs left behind */
360                         continue;
361                 }
362
363                 if (de->d_name[2] != '.') {
364                         continue;
365                 }
366
367                 if (sscanf(de->d_name, "%02u.", &num) != 1) {
368                         continue;
369                 }
370
371                 tree_item = talloc(tree, struct ctdb_script_tree_item);
372                 if (tree_item == NULL) {
373                         DEBUG(DEBUG_ERR, (__location__ " Failed to allocate new tree item\n"));
374                         talloc_free(tmp_ctx);
375                         return NULL;
376                 }
377         
378                 tree_item->error = 0;
379                 if (!check_executable(ctdb->event_script_dir, de->d_name)) {
380                         tree_item->error = errno;
381                 }
382
383                 tree_item->name = talloc_strdup(tree_item, de->d_name);
384                 if (tree_item->name == NULL) {
385                         DEBUG(DEBUG_ERR,(__location__ " Failed to allocate script name.\n"));
386                         talloc_free(tmp_ctx);
387                         return NULL;
388                 }
389
390                 /* store the event script in the tree */
391                 trbt_insert32(tree, (num<<16)|count++, tree_item);
392         }
393         closedir(dir);
394
395
396         head = NULL;
397         tail = NULL;
398
399         /* fetch the scripts from the tree one by one and add them to the linked
400            list
401          */
402         while ((tree_item=trbt_findfirstarray32(tree, 1)) != NULL) {
403
404                 new_item = talloc(tmp_ctx, struct ctdb_script_list);
405                 if (new_item == NULL) {
406                         DEBUG(DEBUG_ERR, (__location__ " Failed to allocate new list item\n"));
407                         talloc_free(tmp_ctx);
408                         return NULL;
409                 }
410
411                 new_item->next = NULL;
412                 new_item->name = talloc_steal(new_item, tree_item->name);
413                 new_item->error = tree_item->error;
414
415                 if (head == NULL) {
416                         head = new_item;
417                         tail = new_item;
418                 } else {
419                         tail->next = new_item;
420                         tail = new_item;
421                 }
422
423                 talloc_steal(mem_ctx, new_item);
424
425                 /* remove this script from the tree */
426                 talloc_free(tree_item);
427         }       
428
429         talloc_free(tmp_ctx);
430         return head;
431 }
432
433 static int child_setup(struct ctdb_context *ctdb,
434                        bool from_user,
435                        enum ctdb_eventscript_call call)
436 {
437         if (!from_user && call == CTDB_EVENT_MONITOR) {
438                 /* This is running in the forked child process. At this stage
439                  * we want to switch from being a ctdb daemon into being a
440                  * client and connect to the real local daemon.
441                  */
442                 if (switch_from_server_to_client(ctdb) != 0) {
443                         DEBUG(DEBUG_CRIT, (__location__ "ERROR: failed to switch eventscript child into client mode. shutting down.\n"));
444                         _exit(1);
445                 }
446
447                 if (ctdb_ctrl_event_script_init(ctdb) != 0) {
448                         return -EIO;
449                 }
450         }
451
452         if (setpgid(0,0) != 0) {
453                 int ret = -errno;
454                 DEBUG(DEBUG_ERR,("Failed to create process group for event scripts - %s\n",
455                          strerror(errno)));
456                 return ret;
457         }
458
459         signal(SIGTERM, sigterm);
460
461         child_state.start = timeval_current();
462         child_state.script_running = "startup";
463         return 0;
464 }
465
466 static char *child_command_string(struct ctdb_context *ctdb,
467                                        TALLOC_CTX *ctx,
468                                        bool from_user,
469                                        const char *scriptname,
470                                        enum ctdb_eventscript_call call,
471                                        const char *options)
472 {
473         const char *str = from_user ? "CTDB_CALLED_BY_USER=1 " : "";
474
475         /* Allow a setting where we run the actual monitor event
476            from an external source and replace it with
477            a "status" event that just picks up the actual
478            status of the event asynchronously.
479         */
480         if ((ctdb->tunable.use_status_events_for_monitoring != 0)
481             &&  (call == CTDB_EVENT_MONITOR)
482             &&  !from_user) {
483                 return talloc_asprintf(ctx, "%s%s/%s %s",
484                                        str,
485                                        ctdb->event_script_dir,
486                                        scriptname, "status");
487         } else {
488                 return talloc_asprintf(ctx, "%s%s/%s %s %s",
489                                        str,
490                                        ctdb->event_script_dir,
491                                        scriptname, call_names[call], options);
492         }
493 }
494
495 static int child_run_one(struct ctdb_context *ctdb,
496                          const char *scriptname, const char *cmdstr)
497 {
498         int ret;
499
500         ret = system(cmdstr);
501         /* if the system() call was successful, translate ret into the
502            return code from the command
503         */
504         if (ret != -1) {
505                 ret = WEXITSTATUS(ret);
506         } else {
507                 ret = -errno;
508         }
509
510         /* 127 could mean it does not exist, 126 non-executable. */
511         if (ret == 127 || ret == 126) {
512                 /* Re-check it... */
513                 if (!check_executable(ctdb->event_script_dir, scriptname)) {
514                         DEBUG(DEBUG_ERR,("Script %s returned status %u. Someone just deleted it?\n",
515                                          cmdstr, ret));
516                         ret = -errno;
517                 }
518         }
519         return ret;
520 }
521
522 /*
523   Actually run the event scripts
524   this function is called and run in the context of a forked child
525   which allows it to do blocking calls such as system()
526  */
527 static int child_run_scripts(struct ctdb_context *ctdb,
528                              bool from_user,
529                              enum ctdb_eventscript_call call,
530                              const char *options,
531                              struct ctdb_script_list *scripts)
532 {
533         char *cmdstr;
534         int ret;
535         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
536         struct ctdb_script_list *current;
537
538         ret = child_setup(ctdb, from_user, call);
539         if (ret != 0)
540                 goto out;
541
542         /* fetch the scripts from the tree one by one and execute
543            them
544          */
545         for (current=scripts; current; current=current->next) {
546                 cmdstr = child_command_string(ctdb, tmp_ctx, from_user,
547                                               current->name, call, options);
548                 CTDB_NO_MEMORY(ctdb, cmdstr);
549
550                 DEBUG(DEBUG_INFO,("Executing event script %s\n",cmdstr));
551
552                 child_state.start = timeval_current();
553                 child_state.script_running = cmdstr;
554
555                 if (!from_user && call == CTDB_EVENT_MONITOR) {
556                         if (ctdb_ctrl_event_script_start(ctdb, current->name) != 0) {
557                                 ret = -EIO;
558                                 goto out;
559                         }
560
561                         if (current->error) {
562                                 if (ctdb_ctrl_event_script_stop(ctdb, -current->error) != 0) {
563                                         ret = -EIO;
564                                         goto out;
565                                 }
566                         }
567                 }
568
569                 if (current->error) {
570                         continue;
571                 }
572
573                 ret = child_run_one(ctdb, current->name, cmdstr);
574
575                 if (!from_user && call == CTDB_EVENT_MONITOR) {
576                         if (ctdb_ctrl_event_script_stop(ctdb, ret) != 0) {
577                                 ret = -EIO;
578                                 goto out;
579                         }
580                 }
581
582                 /* now we've reported the per-script error, don't exit the loop
583                  * just because it vanished or was disabled. */
584                 if (ret == -ENOENT || ret == -ENOEXEC) {
585                         ret = 0;
586                 }
587
588                 /* return an error if the script failed */
589                 if (ret != 0) {
590                         break;
591                 }
592         }
593
594         child_state.start = timeval_current();
595         child_state.script_running = "finished";
596         
597         if (!from_user && call == CTDB_EVENT_MONITOR) {
598                 if (ctdb_ctrl_event_script_finished(ctdb) != 0) {
599                         ret = -EIO;
600                 }
601         }
602
603 out:
604         talloc_free(tmp_ctx);
605         return ret;
606 }
607
608 /* called when child is finished */
609 static void ctdb_event_script_handler(struct event_context *ev, struct fd_event *fde, 
610                                       uint16_t flags, void *p)
611 {
612         struct ctdb_event_script_state *state = 
613                 talloc_get_type(p, struct ctdb_event_script_state);
614         struct ctdb_context *ctdb = state->ctdb;
615         int r;
616
617         r = read(state->fd[0], &state->cb_status, sizeof(state->cb_status));
618         if (r < 0) {
619                 state->cb_status = -errno;
620         } else if (r != sizeof(state->cb_status)) {
621                 state->cb_status = -EIO;
622         }
623
624         DEBUG(DEBUG_INFO,(__location__ " Eventscript %s %s finished with state %d\n",
625                           call_names[state->call], state->options, state->cb_status));
626
627         state->child = 0;
628         ctdb->event_script_timeouts = 0;
629         talloc_free(state);
630 }
631
632 /* called when child times out */
633 static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, 
634                                       struct timeval t, void *p)
635 {
636         struct ctdb_event_script_state *state = talloc_get_type(p, struct ctdb_event_script_state);
637         struct ctdb_context *ctdb = state->ctdb;
638
639         DEBUG(DEBUG_ERR,("Event script timed out : %s %s count : %u  pid : %d\n",
640                          call_names[state->call], state->options, ctdb->event_script_timeouts, state->child));
641
642         state->cb_status = -ETIME;
643
644         if (kill(state->child, 0) != 0) {
645                 DEBUG(DEBUG_ERR,("Event script child process already dead, errno %s(%d)\n", strerror(errno), errno));
646                 state->child = 0;
647         }
648
649         if (state->call == CTDB_EVENT_MONITOR || state->call == CTDB_EVENT_STATUS) {
650                 struct ctdb_monitor_script_status *script;
651
652                 if (ctdb->current_monitor != NULL) {
653                         script = ctdb->current_monitor->scripts;
654                         if (script != NULL) {
655                                 script->status = state->cb_status;
656                         }
657
658                         ctdb_control_event_script_finished(ctdb);
659                 }
660         }
661
662         talloc_free(state);
663 }
664
665 /*
666   destroy an event script: kill it if ->child != 0.
667  */
668 static int event_script_destructor(struct ctdb_event_script_state *state)
669 {
670         if (state->child) {
671                 DEBUG(DEBUG_ERR,(__location__ " Sending SIGTERM to child pid:%d\n", state->child));
672
673                 if (kill(state->child, SIGTERM) != 0) {
674                         DEBUG(DEBUG_ERR,("Failed to kill child process for eventscript, errno %s(%d)\n", strerror(errno), errno));
675                 }
676         }
677
678         /* If we were the current monitor, we no longer are. */
679         if (state->ctdb->current_monitor == state) {
680                 state->ctdb->current_monitor = NULL;
681         }
682
683         /* This is allowed to free us; talloc will prevent double free anyway,
684          * but beware if you call this outside the destructor! */
685         if (state->callback) {
686                 state->callback(state->ctdb, state->cb_status, state->private_data);
687         }
688
689         return 0;
690 }
691
692 static unsigned int count_words(const char *options)
693 {
694         unsigned int words = 0;
695
696         options += strspn(options, " \t");
697         while (*options) {
698                 words++;
699                 options += strcspn(options, " \t");
700                 options += strspn(options, " \t");
701         }
702         return words;
703 }
704
705 static bool check_options(enum ctdb_eventscript_call call, const char *options)
706 {
707         switch (call) {
708         /* These all take no arguments. */
709         case CTDB_EVENT_STARTUP:
710         case CTDB_EVENT_START_RECOVERY:
711         case CTDB_EVENT_RECOVERED:
712         case CTDB_EVENT_STOPPED:
713         case CTDB_EVENT_MONITOR:
714         case CTDB_EVENT_STATUS:
715         case CTDB_EVENT_SHUTDOWN:
716         case CTDB_EVENT_RELOAD:
717                 return count_words(options) == 0;
718
719         case CTDB_EVENT_TAKE_IP: /* interface, IP address, netmask bits. */
720         case CTDB_EVENT_RELEASE_IP:
721                 return count_words(options) == 3;
722
723         default:
724                 DEBUG(DEBUG_ERR,(__location__ "Unknown ctdb_eventscript_call %u\n", call));
725                 return false;
726         }
727 }
728
729 /*
730   run the event script in the background, calling the callback when 
731   finished
732  */
733 static int ctdb_event_script_callback_v(struct ctdb_context *ctdb, 
734                                         void (*callback)(struct ctdb_context *, int, void *),
735                                         void *private_data,
736                                         bool from_user,
737                                         enum ctdb_eventscript_call call,
738                                         const char *fmt, va_list ap)
739 {
740         struct ctdb_event_script_state *state;
741         int ret;
742         struct ctdb_script_list *scripts;
743
744         state = talloc(ctdb->event_script_ctx, struct ctdb_event_script_state);
745         CTDB_NO_MEMORY(ctdb, state);
746
747         state->ctdb = ctdb;
748         state->callback = callback;
749         state->private_data = private_data;
750         state->call = call;
751         state->options = talloc_vasprintf(state, fmt, ap);
752         state->timeout = timeval_set(ctdb->tunable.script_timeout, 0);
753         state->scripts = NULL;
754         if (state->options == NULL) {
755                 DEBUG(DEBUG_ERR, (__location__ " could not allocate state->options\n"));
756                 talloc_free(state);
757                 return -1;
758         }
759         if (!check_options(state->call, state->options)) {
760                 DEBUG(DEBUG_ERR, ("Bad eventscript options '%s' for %s\n",
761                                   call_names[state->call], state->options));
762                 talloc_free(state);
763                 return -1;
764         }
765
766         if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
767                 /* we guarantee that only some specifically allowed event scripts are run
768                    while in recovery */
769                 const enum ctdb_eventscript_call allowed_calls[] = {
770                         CTDB_EVENT_START_RECOVERY, CTDB_EVENT_SHUTDOWN, CTDB_EVENT_RELEASE_IP, CTDB_EVENT_STOPPED };
771                 int i;
772                 for (i=0;i<ARRAY_SIZE(allowed_calls);i++) {
773                         if (call == allowed_calls[i]) break;
774                 }
775                 if (i == ARRAY_SIZE(allowed_calls)) {
776                         DEBUG(DEBUG_ERR,("Refusing to run event scripts call '%s' while in recovery\n",
777                                  call_names[call]));
778                         talloc_free(state);
779                         return -1;
780                 }
781         }
782
783         /* Kill off any running monitor events to run this event. */
784         talloc_free(ctdb->current_monitor);
785         ctdb->current_monitor = NULL;
786
787         if (!from_user && (call == CTDB_EVENT_MONITOR || call == CTDB_EVENT_STATUS)) {
788                 ctdb->current_monitor = state;
789         }
790
791         DEBUG(DEBUG_INFO,(__location__ " Starting eventscript %s %s\n",
792                           call_names[state->call], state->options));
793         
794         scripts = ctdb_get_script_list(ctdb, state);
795
796         ret = pipe(state->fd);
797         if (ret != 0) {
798                 talloc_free(state);
799                 return -1;
800         }
801
802         state->child = fork();
803
804         if (state->child == (pid_t)-1) {
805                 close(state->fd[0]);
806                 close(state->fd[1]);
807                 talloc_free(state);
808                 return -1;
809         }
810
811         if (state->child == 0) {
812                 int rt;
813
814                 close(state->fd[0]);
815                 set_close_on_exec(state->fd[1]);
816
817                 rt = child_run_scripts(ctdb, from_user, state->call, state->options, scripts);
818                 /* We must be able to write PIPEBUF bytes at least; if this
819                    somehow fails, the read above will be short. */
820                 write(state->fd[1], &rt, sizeof(rt));
821                 close(state->fd[1]);
822                 _exit(rt);
823         }
824
825         close(state->fd[1]);
826         set_close_on_exec(state->fd[0]);
827         talloc_set_destructor(state, event_script_destructor);
828
829         DEBUG(DEBUG_DEBUG, (__location__ " Created PIPE FD:%d to child eventscript process\n", state->fd[0]));
830
831         event_add_fd(ctdb->ev, state, state->fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
832                      ctdb_event_script_handler, state);
833
834         if (!timeval_is_zero(&state->timeout)) {
835                 event_add_timed(ctdb->ev, state, timeval_current_ofs(state->timeout.tv_sec, state->timeout.tv_usec), ctdb_event_script_timeout, state);
836         } else {
837                 DEBUG(DEBUG_ERR, (__location__ " eventscript %s %s called with no timeout\n",
838                                   call_names[state->call], state->options));
839         }
840
841         return 0;
842 }
843
844
845 /*
846   run the event script in the background, calling the callback when 
847   finished
848  */
849 int ctdb_event_script_callback(struct ctdb_context *ctdb, 
850                                TALLOC_CTX *mem_ctx,
851                                void (*callback)(struct ctdb_context *, int, void *),
852                                void *private_data,
853                                bool from_user,
854                                enum ctdb_eventscript_call call,
855                                const char *fmt, ...)
856 {
857         va_list ap;
858         int ret;
859
860         va_start(ap, fmt);
861         ret = ctdb_event_script_callback_v(ctdb, callback, private_data, from_user, call, fmt, ap);
862         va_end(ap);
863
864         return ret;
865 }
866
867
868 struct callback_status {
869         bool done;
870         int status;
871 };
872
873 /*
874   called when ctdb_event_script() finishes
875  */
876 static void event_script_callback(struct ctdb_context *ctdb, int status, void *private_data)
877 {
878         struct callback_status *s = (struct callback_status *)private_data;
879         s->done = true;
880         s->status = status;
881 }
882
883 /*
884   run the event script, waiting for it to complete. Used when the caller
885   doesn't want to continue till the event script has finished.
886  */
887 int ctdb_event_script_args(struct ctdb_context *ctdb, enum ctdb_eventscript_call call,
888                            const char *fmt, ...)
889 {
890         va_list ap;
891         int ret;
892         struct callback_status status;
893
894         va_start(ap, fmt);
895         ret = ctdb_event_script_callback_v(ctdb,
896                         event_script_callback, &status, false, call, fmt, ap);
897         if (ret != 0) {
898                 return ret;
899         }
900         va_end(ap);
901
902         status.status = -1;
903         status.done = false;
904
905         while (status.done == false && event_loop_once(ctdb->ev) == 0) /* noop */;
906
907         if (status.status == -ETIME) {
908                 DEBUG(DEBUG_ERR, (__location__ " eventscript for '%s' timedout."
909                                   " Immediately banning ourself for %d seconds\n",
910                                   call_names[call],
911                                   ctdb->tunable.recovery_ban_period));
912                 ctdb_ban_self(ctdb);
913         }
914
915         return status.status;
916 }
917
918 int ctdb_event_script(struct ctdb_context *ctdb, enum ctdb_eventscript_call call)
919 {
920         /* GCC complains about empty format string, so use %s and "". */
921         return ctdb_event_script_args(ctdb, call, "%s", "");
922 }
923
924 struct eventscript_callback_state {
925         struct ctdb_req_control *c;
926 };
927
928 /*
929   called when a forced eventscript run has finished
930  */
931 static void run_eventscripts_callback(struct ctdb_context *ctdb, int status, 
932                                  void *private_data)
933 {
934         struct eventscript_callback_state *state = 
935                 talloc_get_type(private_data, struct eventscript_callback_state);
936
937         ctdb_enable_monitoring(ctdb);
938
939         if (status != 0) {
940                 DEBUG(DEBUG_ERR,(__location__ " Failed to forcibly run eventscripts\n"));
941         }
942
943         ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL);
944         /* This will free the struct ctdb_event_script_state we are in! */
945         talloc_free(state);
946         return;
947 }
948
949
950 /* Returns rest of string, or NULL if no match. */
951 static const char *get_call(const char *p, enum ctdb_eventscript_call *call)
952 {
953         unsigned int len;
954
955         /* Skip any initial whitespace. */
956         p += strspn(p, " \t");
957
958         /* See if we match any. */
959         for (*call = 0; *call < ARRAY_SIZE(call_names); (*call)++) {
960                 len = strlen(call_names[*call]);
961                 if (strncmp(p, call_names[*call], len) == 0) {
962                         /* If end of string or whitespace, we're done. */
963                         if (strcspn(p + len, " \t") == 0) {
964                                 return p + len;
965                         }
966                 }
967         }
968         return NULL;
969 }
970
971 /*
972   A control to force running of the eventscripts from the ctdb client tool
973 */
974 int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb,
975                 struct ctdb_req_control *c,
976                 TDB_DATA indata, bool *async_reply)
977 {
978         int ret;
979         struct eventscript_callback_state *state;
980         const char *options;
981         enum ctdb_eventscript_call call;
982
983         /* Figure out what call they want. */
984         options = get_call((const char *)indata.dptr, &call);
985         if (!options) {
986                 DEBUG(DEBUG_ERR, (__location__ " Invalid forced \"%s\"\n", (const char *)indata.dptr));
987                 return -1;
988         }
989
990         if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
991                 DEBUG(DEBUG_ERR, (__location__ " Aborted running eventscript \"%s\" while in RECOVERY mode\n", indata.dptr));
992                 return -1;
993         }
994
995         state = talloc(ctdb->event_script_ctx, struct eventscript_callback_state);
996         CTDB_NO_MEMORY(ctdb, state);
997
998         state->c = talloc_steal(state, c);
999
1000         DEBUG(DEBUG_NOTICE,("Forced running of eventscripts with arguments %s\n", indata.dptr));
1001
1002         ctdb_disable_monitoring(ctdb);
1003
1004         ret = ctdb_event_script_callback(ctdb, 
1005                          state, run_eventscripts_callback, state,
1006                          true, call, "%s", options);
1007
1008         if (ret != 0) {
1009                 ctdb_enable_monitoring(ctdb);
1010                 DEBUG(DEBUG_ERR,(__location__ " Failed to run eventscripts with arguments %s\n", indata.dptr));
1011                 talloc_free(state);
1012                 return -1;
1013         }
1014
1015         /* tell ctdb_control.c that we will be replying asynchronously */
1016         *async_reply = true;
1017
1018         return 0;
1019 }
1020
1021
1022
1023 int32_t ctdb_control_enable_script(struct ctdb_context *ctdb, TDB_DATA indata)
1024 {
1025         const char *script;
1026         struct stat st;
1027         char *filename;
1028         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1029
1030         script = (char *)indata.dptr;
1031         if (indata.dsize == 0) {
1032                 DEBUG(DEBUG_ERR,(__location__ " No script specified.\n"));
1033                 talloc_free(tmp_ctx);
1034                 return -1;
1035         }
1036         if (indata.dptr[indata.dsize - 1] != '\0') {
1037                 DEBUG(DEBUG_ERR,(__location__ " String is not null terminated.\n"));
1038                 talloc_free(tmp_ctx);
1039                 return -1;
1040         }
1041         if (index(script,'/') != NULL) {
1042                 DEBUG(DEBUG_ERR,(__location__ " Script name contains '/'. Failed to enable script %s\n", script));
1043                 talloc_free(tmp_ctx);
1044                 return -1;
1045         }
1046
1047
1048         if (stat(ctdb->event_script_dir, &st) != 0 && 
1049             errno == ENOENT) {
1050                 DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
1051                 talloc_free(tmp_ctx);
1052                 return -1;
1053         }
1054
1055
1056         filename = talloc_asprintf(tmp_ctx, "%s/%s", ctdb->event_script_dir, script);
1057         if (filename == NULL) {
1058                 DEBUG(DEBUG_ERR,(__location__ " Failed to create script path\n"));
1059                 talloc_free(tmp_ctx);
1060                 return -1;
1061         }
1062
1063         if (stat(filename, &st) != 0) {
1064                 DEBUG(DEBUG_ERR,("Could not stat event script %s. Failed to enable script.\n", filename));
1065                 talloc_free(tmp_ctx);
1066                 return -1;
1067         }
1068
1069         if (chmod(filename, st.st_mode | S_IXUSR) == -1) {
1070                 DEBUG(DEBUG_ERR,("Could not chmod %s. Failed to enable script.\n", filename));
1071                 talloc_free(tmp_ctx);
1072                 return -1;
1073         }
1074
1075         talloc_free(tmp_ctx);
1076         return 0;
1077 }
1078
1079 int32_t ctdb_control_disable_script(struct ctdb_context *ctdb, TDB_DATA indata)
1080 {
1081         const char *script;
1082         struct stat st;
1083         char *filename;
1084         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1085
1086         script = (char *)indata.dptr;
1087         if (indata.dsize == 0) {
1088                 DEBUG(DEBUG_ERR,(__location__ " No script specified.\n"));
1089                 talloc_free(tmp_ctx);
1090                 return -1;
1091         }
1092         if (indata.dptr[indata.dsize - 1] != '\0') {
1093                 DEBUG(DEBUG_ERR,(__location__ " String is not null terminated.\n"));
1094                 talloc_free(tmp_ctx);
1095                 return -1;
1096         }
1097         if (index(script,'/') != NULL) {
1098                 DEBUG(DEBUG_ERR,(__location__ " Script name contains '/'. Failed to disable script %s\n", script));
1099                 talloc_free(tmp_ctx);
1100                 return -1;
1101         }
1102
1103
1104         if (stat(ctdb->event_script_dir, &st) != 0 && 
1105             errno == ENOENT) {
1106                 DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
1107                 talloc_free(tmp_ctx);
1108                 return -1;
1109         }
1110
1111
1112         filename = talloc_asprintf(tmp_ctx, "%s/%s", ctdb->event_script_dir, script);
1113         if (filename == NULL) {
1114                 DEBUG(DEBUG_ERR,(__location__ " Failed to create script path\n"));
1115                 talloc_free(tmp_ctx);
1116                 return -1;
1117         }
1118
1119         if (stat(filename, &st) != 0) {
1120                 DEBUG(DEBUG_ERR,("Could not stat event script %s. Failed to disable script.\n", filename));
1121                 talloc_free(tmp_ctx);
1122                 return -1;
1123         }
1124
1125         if (chmod(filename, st.st_mode & ~(S_IXUSR|S_IXGRP|S_IXOTH)) == -1) {
1126                 DEBUG(DEBUG_ERR,("Could not chmod %s. Failed to disable script.\n", filename));
1127                 talloc_free(tmp_ctx);
1128                 return -1;
1129         }
1130
1131         talloc_free(tmp_ctx);
1132         return 0;
1133 }