Do not allow "ctdb eventscript" to start new eventscripts while we are in recovery...
[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 "system/filesys.h"
22 #include "system/wait.h"
23 #include "system/dir.h"
24 #include "system/locale.h"
25 #include "../include/ctdb_private.h"
26 #include "lib/events/events.h"
27 #include "../common/rb_tree.h"
28
29 static struct {
30         struct timeval start;
31         const char *script_running;
32 } child_state;
33
34 /*
35   ctdbd sends us a SIGTERM when we should time out the current script
36  */
37 static void sigterm(int sig)
38 {
39         DEBUG(DEBUG_ERR,("Timed out running script '%s' after %.1f seconds\n", 
40                  child_state.script_running, timeval_elapsed(&child_state.start)));
41         /* all the child processes will be running in the same process group */
42         kill(-getpgrp(), SIGKILL);
43         exit(1);
44 }
45
46 struct ctdb_event_script_state {
47         struct ctdb_context *ctdb;
48         pid_t child;
49         void (*callback)(struct ctdb_context *, int, void *);
50         int fd[2];
51         void *private_data;
52         const char *options;
53 };
54
55 /*
56   run the event script - varargs version
57   this function is called and run in the context of a forked child
58   which allows it to do blocking calls such as system()
59  */
60 static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *options)
61 {
62         char *cmdstr;
63         int ret;
64         struct stat st;
65         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
66         trbt_tree_t *tree;
67         DIR *dir;
68         struct dirent *de;
69         char *script;
70
71         if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
72                 /* we guarantee that only some specifically allowed event scripts are run
73                    while in recovery */
74                 const char *allowed_scripts[] = {"startrecovery", "shutdown" };
75                 int i;
76                 for (i=0;i<ARRAY_SIZE(allowed_scripts);i++) {
77                         if (strcmp(options, allowed_scripts[i]) == 0) break;
78                 }
79                 if (i == ARRAY_SIZE(allowed_scripts)) {
80                         DEBUG(0,("Refusing to run event scripts with option '%s' while in recovery\n",
81                                  options));
82                         return -1;
83                 }
84         }
85
86         if (setpgid(0,0) != 0) {
87                 DEBUG(DEBUG_ERR,("Failed to create process group for event scripts - %s\n",
88                          strerror(errno)));
89                 talloc_free(tmp_ctx);
90                 return -1;              
91         }
92
93         signal(SIGTERM, sigterm);
94
95         child_state.start = timeval_current();
96         child_state.script_running = "startup";
97
98         /*
99           the service specific event scripts 
100         */
101         if (stat(ctdb->event_script_dir, &st) != 0 && 
102             errno == ENOENT) {
103                 DEBUG(DEBUG_CRIT,("No event script directory found at '%s'\n", ctdb->event_script_dir));
104                 talloc_free(tmp_ctx);
105                 return -1;
106         }
107
108         /* create a tree to store all the script names in */
109         tree = trbt_create(tmp_ctx, 0);
110
111         /* scan all directory entries and insert all valid scripts into the 
112            tree
113         */
114         dir = opendir(ctdb->event_script_dir);
115         if (dir == NULL) {
116                 DEBUG(DEBUG_CRIT,("Failed to open event script directory '%s'\n", ctdb->event_script_dir));
117                 talloc_free(tmp_ctx);
118                 return -1;
119         }
120
121         while ((de=readdir(dir)) != NULL) {
122                 int namlen;
123                 unsigned num;
124                 char *str;
125
126                 namlen = strlen(de->d_name);
127
128                 if (namlen < 3) {
129                         continue;
130                 }
131
132                 if (de->d_name[namlen-1] == '~') {
133                         /* skip files emacs left behind */
134                         continue;
135                 }
136
137                 if (de->d_name[2] != '.') {
138                         continue;
139                 }
140
141                 if (sscanf(de->d_name, "%02u.", &num) != 1) {
142                         continue;
143                 }
144
145                 /* Make sure the event script is executable */
146                 str = talloc_asprintf(tree, "%s/%s", ctdb->event_script_dir, de->d_name);
147                 if (stat(str, &st) != 0) {
148                         DEBUG(DEBUG_ERR,("Could not stat event script %s. Ignoring this event script\n", str));
149                         continue;
150                 }
151                 if (!(st.st_mode & S_IXUSR)) {
152                         DEBUG(DEBUG_ERR,("Event script %s is not executable. Ignoring this event script\n", str));
153                         continue;
154                 }
155                 
156                 
157                 /* store the event script in the tree */                
158                 script = trbt_insert32(tree, num, talloc_strdup(tree, de->d_name));
159                 if (script != NULL) {
160                         DEBUG(DEBUG_CRIT,("CONFIG ERROR: Multiple event scripts with the same prefix : '%s' and '%s'. Each event script MUST have a unique prefix\n", script, de->d_name));
161                         talloc_free(tmp_ctx);
162                         closedir(dir);
163                         return -1;
164                 }
165         }
166         closedir(dir);
167
168         /* fetch the scripts from the tree one by one and execute
169            them
170          */
171         while ((script=trbt_findfirstarray32(tree, 1)) != NULL) {
172                 cmdstr = talloc_asprintf(tmp_ctx, "%s/%s %s", 
173                                 ctdb->event_script_dir,
174                                 script, options);
175                 CTDB_NO_MEMORY(ctdb, cmdstr);
176
177                 DEBUG(DEBUG_INFO,("Executing event script %s\n",cmdstr));
178
179                 child_state.start = timeval_current();
180                 child_state.script_running = cmdstr;
181
182                 ret = system(cmdstr);
183                 /* if the system() call was successful, translate ret into the
184                    return code from the command
185                 */
186                 if (ret != -1) {
187                         ret = WEXITSTATUS(ret);
188                 }
189                 /* return an error if the script failed */
190                 if (ret != 0) {
191                         DEBUG(DEBUG_ERR,("Event script %s failed with error %d\n", cmdstr, ret));
192                         talloc_free(tmp_ctx);
193                         return ret;
194                 }
195
196                 /* remove this script from the tree */
197                 talloc_free(script);
198         }
199
200         child_state.start = timeval_current();
201         child_state.script_running = "finished";
202         
203         talloc_free(tmp_ctx);
204         return 0;
205 }
206
207 /* called when child is finished */
208 static void ctdb_event_script_handler(struct event_context *ev, struct fd_event *fde, 
209                                       uint16_t flags, void *p)
210 {
211         struct ctdb_event_script_state *state = 
212                 talloc_get_type(p, struct ctdb_event_script_state);
213         void (*callback)(struct ctdb_context *, int, void *) = state->callback;
214         void *private_data = state->private_data;
215         struct ctdb_context *ctdb = state->ctdb;
216         signed char rt = -1;
217
218         read(state->fd[0], &rt, sizeof(rt));
219
220         talloc_set_destructor(state, NULL);
221         talloc_free(state);
222         callback(ctdb, rt, private_data);
223
224         ctdb->event_script_timeouts = 0;
225 }
226
227 static void ctdb_ban_self(struct ctdb_context *ctdb, uint32_t ban_period)
228 {
229         int ret;
230         struct ctdb_ban_info b;
231         TDB_DATA data;
232
233         b.pnn      = ctdb->pnn;
234         b.ban_time = ban_period;
235
236         data.dptr = (uint8_t *)&b;
237         data.dsize = sizeof(b);
238
239         ret = ctdb_daemon_send_message(ctdb, CTDB_BROADCAST_CONNECTED,
240                 CTDB_SRVID_BAN_NODE, data);
241         if (ret != 0) {
242                 DEBUG(DEBUG_ERR,(__location__ " Failed to send ban message\n"));
243         }
244 }
245
246
247 /* called when child times out */
248 static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, 
249                                       struct timeval t, void *p)
250 {
251         struct ctdb_event_script_state *state = talloc_get_type(p, struct ctdb_event_script_state);
252         void (*callback)(struct ctdb_context *, int, void *) = state->callback;
253         void *private_data = state->private_data;
254         struct ctdb_context *ctdb = state->ctdb;
255         char *options;
256
257         DEBUG(DEBUG_ERR,("Event script timed out : %s count : %u\n", state->options, ctdb->event_script_timeouts));
258
259         options = talloc_strdup(ctdb, state->options);
260         CTDB_NO_MEMORY_VOID(ctdb, options);
261
262         talloc_free(state);
263         if (!strcmp(options, "monitor")) {
264                 /* if it is a monitor event, we allow it to "hang" a few times
265                    before we declare it a failure and ban ourself (and make
266                    ourself unhealthy)
267                 */
268                 DEBUG(DEBUG_ERR, (__location__ " eventscript for monitor event timedout.\n"));
269
270                 ctdb->event_script_timeouts++;
271                 if (ctdb->event_script_timeouts > ctdb->tunable.script_ban_count) {
272                         ctdb->event_script_timeouts = 0;
273                         DEBUG(DEBUG_ERR, ("Maximum timeout count %u reached for eventscript. Banning self for %d seconds\n", ctdb->tunable.script_ban_count, ctdb->tunable.recovery_ban_period));
274                         ctdb_ban_self(ctdb, ctdb->tunable.recovery_ban_period);
275                         callback(ctdb, -1, private_data);
276                 } else {
277                         callback(ctdb, 0, private_data);
278                 }
279         } else if (!strcmp(options, "startup")) {
280                 DEBUG(DEBUG_ERR, (__location__ " eventscript for startup event timedout.\n"));
281                 callback(ctdb, -1, private_data);
282         } else {
283                 /* if it is not a monitor event we ban ourself immediately */
284                 DEBUG(DEBUG_ERR, (__location__ " eventscript for NON-monitor/NON-startup event timedout. Immediately banning ourself for %d seconds\n", ctdb->tunable.recovery_ban_period));
285                 ctdb_ban_self(ctdb, ctdb->tunable.recovery_ban_period);
286                 callback(ctdb, -1, private_data);
287         }
288
289         talloc_free(options);
290 }
291
292 /*
293   destroy a running event script
294  */
295 static int event_script_destructor(struct ctdb_event_script_state *state)
296 {
297         DEBUG(DEBUG_ERR,(__location__ " Sending SIGTERM to child pid:%d\n", state->child));
298         kill(state->child, SIGTERM);
299         return 0;
300 }
301
302 /*
303   run the event script in the background, calling the callback when 
304   finished
305  */
306 static int ctdb_event_script_callback_v(struct ctdb_context *ctdb, 
307                                         struct timeval timeout,
308                                         TALLOC_CTX *mem_ctx,
309                                         void (*callback)(struct ctdb_context *, int, void *),
310                                         void *private_data,
311                                         const char *fmt, va_list ap)
312 {
313         struct ctdb_event_script_state *state;
314         int ret;
315
316         state = talloc(mem_ctx, struct ctdb_event_script_state);
317         CTDB_NO_MEMORY(ctdb, state);
318
319         state->ctdb = ctdb;
320         state->callback = callback;
321         state->private_data = private_data;
322         state->options = talloc_vasprintf(state, fmt, ap);
323         CTDB_NO_MEMORY(ctdb, state->options);
324         
325         ret = pipe(state->fd);
326         if (ret != 0) {
327                 talloc_free(state);
328                 return -1;
329         }
330
331         state->child = fork();
332
333         if (state->child == (pid_t)-1) {
334                 close(state->fd[0]);
335                 close(state->fd[1]);
336                 talloc_free(state);
337                 return -1;
338         }
339
340         if (state->child == 0) {
341                 signed char rt;
342
343                 close(state->fd[0]);
344                 if (ctdb->do_setsched) {
345                         ctdb_restore_scheduler(ctdb);
346                 }
347                 set_close_on_exec(state->fd[1]);
348                 rt = ctdb_event_script_v(ctdb, state->options);
349                 while ((ret = write(state->fd[1], &rt, sizeof(rt))) != sizeof(rt)) {
350                         sleep(1);
351                 }
352                 _exit(rt);
353         }
354
355         talloc_set_destructor(state, event_script_destructor);
356
357         close(state->fd[1]);
358
359         event_add_fd(ctdb->ev, state, state->fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
360                      ctdb_event_script_handler, state);
361
362         if (!timeval_is_zero(&timeout)) {
363                 event_add_timed(ctdb->ev, state, timeout, ctdb_event_script_timeout, state);
364         } else {
365                 DEBUG(DEBUG_ERR, (__location__ " eventscript %s called with no timeout\n", state->options));
366         }
367
368         return 0;
369 }
370
371
372 /*
373   run the event script in the background, calling the callback when 
374   finished
375  */
376 int ctdb_event_script_callback(struct ctdb_context *ctdb, 
377                                struct timeval timeout,
378                                TALLOC_CTX *mem_ctx,
379                                void (*callback)(struct ctdb_context *, int, void *),
380                                void *private_data,
381                                const char *fmt, ...)
382 {
383         va_list ap;
384         int ret;
385
386         va_start(ap, fmt);
387         ret = ctdb_event_script_callback_v(ctdb, timeout, mem_ctx, callback, private_data, fmt, ap);
388         va_end(ap);
389
390         return ret;
391 }
392
393
394 struct callback_status {
395         bool done;
396         int status;
397 };
398
399 /*
400   called when ctdb_event_script() finishes
401  */
402 static void event_script_callback(struct ctdb_context *ctdb, int status, void *private_data)
403 {
404         struct callback_status *s = (struct callback_status *)private_data;
405         s->done = true;
406         s->status = status;
407 }
408
409 /*
410   run the event script, waiting for it to complete. Used when the caller doesn't want to 
411   continue till the event script has finished.
412  */
413 int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
414 {
415         va_list ap;
416         int ret;
417         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
418         struct callback_status status;
419
420         va_start(ap, fmt);
421         ret = ctdb_event_script_callback_v(ctdb, timeval_zero(), tmp_ctx, event_script_callback, &status, fmt, ap);
422         va_end(ap);
423
424         if (ret != 0) {
425                 talloc_free(tmp_ctx);
426                 return ret;
427         }
428
429         status.status = -1;
430         status.done = false;
431
432         while (status.done == false && event_loop_once(ctdb->ev) == 0) /* noop */;
433
434         talloc_free(tmp_ctx);
435
436         return status.status;
437 }
438
439
440 struct eventscript_callback_state {
441         struct ctdb_req_control *c;
442 };
443
444 /*
445   called when takeip event finishes
446  */
447 static void run_eventscripts_callback(struct ctdb_context *ctdb, int status, 
448                                  void *private_data)
449 {
450         struct eventscript_callback_state *state = 
451                 talloc_get_type(private_data, struct eventscript_callback_state);
452
453         ctdb_enable_monitoring(ctdb);
454
455         if (status != 0) {
456                 DEBUG(DEBUG_ERR,(__location__ " Failed to forcibly run eventscripts\n"));
457                 ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL);
458                 talloc_free(state);
459                 return;
460         }
461
462         /* the control succeeded */
463         ctdb_request_control_reply(ctdb, state->c, NULL, 0, NULL);
464         talloc_free(state);
465         return;
466 }
467
468 /*
469   A control to force running of the eventscripts from the ctdb client tool
470 */
471 int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb,
472                 struct ctdb_req_control *c,
473                 TDB_DATA indata, bool *async_reply)
474 {
475         int ret;
476         struct eventscript_callback_state *state;
477
478         /* kill off any previous invokations of forced eventscripts */
479         if (ctdb->eventscripts_ctx) {
480                 talloc_free(ctdb->eventscripts_ctx);
481         }
482         ctdb->eventscripts_ctx = talloc_new(ctdb);
483         CTDB_NO_MEMORY(ctdb, ctdb->eventscripts_ctx);
484
485         state = talloc(ctdb->eventscripts_ctx, struct eventscript_callback_state);
486         CTDB_NO_MEMORY(ctdb, state);
487
488         state->c = talloc_steal(state, c);
489
490         DEBUG(DEBUG_NOTICE,("Forced running of eventscripts with arguments %s\n", indata.dptr));
491
492         if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
493                 DEBUG(DEBUG_ERR, (__location__ " Aborted running eventscript \"%s\" while in RECOVERY mode\n", indata.dptr));
494                 return -1;
495         }
496
497         ctdb_disable_monitoring(ctdb);
498
499         ret = ctdb_event_script_callback(ctdb, 
500                          timeval_current_ofs(ctdb->tunable.script_timeout, 0),
501                          state, run_eventscripts_callback, state,
502                          (const char *)indata.dptr);
503
504         if (ret != 0) {
505                 ctdb_enable_monitoring(ctdb);
506                 DEBUG(DEBUG_ERR,(__location__ " Failed to run eventscripts with arguments %s\n", indata.dptr));
507                 talloc_free(state);
508                 return -1;
509         }
510
511         /* tell ctdb_control.c that we will be replying asynchronously */
512         *async_reply = true;
513
514         return 0;
515 }
516