ctdb-daemon: CID 1435732: Argument cannot be negative
[vlendec/samba-autobuild/.git] / ctdb / 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 "replace.h"
21 #include "system/filesys.h"
22 #include "system/network.h"
23 #include "system/wait.h"
24 #include "system/dir.h"
25 #include "system/locale.h"
26 #include "system/time.h"
27 #include "system/dir.h"
28
29 #include <talloc.h>
30 #include <tevent.h>
31
32 #include "lib/util/dlinklist.h"
33 #include "lib/util/debug.h"
34 #include "lib/util/samba_util.h"
35 #include "lib/util/sys_rw.h"
36
37 #include "ctdb_private.h"
38
39 #include "common/rb_tree.h"
40 #include "common/common.h"
41 #include "common/logging.h"
42 #include "common/reqid.h"
43 #include "common/sock_io.h"
44
45 #include "protocol/protocol_api.h"
46
47 /*
48  * Setting up event daemon
49  */
50
51 struct eventd_context {
52         struct tevent_context *ev;
53         const char *path;
54         const char *script_dir;
55         const char *pidfile;
56         const char *socket;
57         const char *debug_hung_script;
58
59         /* server state */
60         pid_t eventd_pid;
61         struct tevent_fd *eventd_fde;
62
63         /* client state */
64         struct reqid_context *idr;
65         struct sock_queue *queue;
66         struct eventd_client_state *calls;
67 };
68
69 static bool eventd_context_init(TALLOC_CTX *mem_ctx,
70                                 struct ctdb_context *ctdb,
71                                 struct eventd_context **out)
72 {
73         struct eventd_context *ectx;
74         const char *eventd = CTDB_HELPER_BINDIR "/ctdb_eventd";
75         const char *debug_hung_script = CTDB_ETCDIR "/debug-hung-script.sh";
76         const char *value;
77         char *socket;
78         int ret;
79
80         ectx = talloc_zero(mem_ctx, struct eventd_context);
81         if (ectx == NULL) {
82                 return false;
83         }
84
85         ectx->ev = ctdb->ev;
86
87         value = getenv("CTDB_EVENTD");
88         if (value != NULL) {
89                 eventd = value;
90         }
91
92         ectx->path = talloc_strdup(ectx, eventd);
93         if (ectx->path == NULL) {
94                 talloc_free(ectx);
95                 return false;
96         }
97
98         ectx->script_dir = ctdb->event_script_dir;
99
100         socket = talloc_strdup(ectx, ctdb_get_socketname(ctdb));
101         if (socket == NULL) {
102                 talloc_free(ectx);
103                 return false;
104         }
105
106         ectx->socket = talloc_asprintf(ectx, "%s/eventd.sock",
107                                        dirname(socket));
108         if (ectx->socket == NULL) {
109                 talloc_free(ectx);
110                 return false;
111         }
112
113         talloc_free(socket);
114
115         value = getenv("CTDB_DEBUG_HUNG_SCRIPT");
116         if (value != NULL) {
117                 if (value[0] == '\0') {
118                         debug_hung_script = NULL;
119                 } else {
120                         debug_hung_script = value;
121                 }
122         }
123
124         if (debug_hung_script != NULL) {
125                 ectx->debug_hung_script = talloc_strdup(ectx,
126                                                         debug_hung_script);
127                 if (ectx->debug_hung_script == NULL) {
128                         talloc_free(ectx);
129                         return false;
130                 }
131         }
132
133         ret = reqid_init(ectx, 1, &ectx->idr);
134         if (ret != 0) {
135                 talloc_free(ectx);
136                 return false;
137         }
138
139         ectx->eventd_pid = -1;
140
141         *out = ectx;
142         return true;
143 }
144
145 /*
146  * Start and stop event daemon
147  */
148
149 static bool eventd_client_connect(struct eventd_context *ectx);
150 static void eventd_dead_handler(struct tevent_context *ev,
151                                 struct tevent_fd *fde, uint16_t flags,
152                                 void *private_data);
153
154 int ctdb_start_eventd(struct ctdb_context *ctdb)
155 {
156         struct eventd_context *ectx;
157         const char **argv;
158         int fd[2];
159         pid_t pid;
160         int ret, i;
161         bool status;
162
163         if (ctdb->ectx == NULL) {
164                 status = eventd_context_init(ctdb, ctdb, &ctdb->ectx);
165                 if (! status) {
166                         DEBUG(DEBUG_ERR,
167                               ("Failed to initialize eventd context\n"));
168                         return -1;
169                 }
170         }
171
172         ectx = ctdb->ectx;
173
174         if (! sock_clean(ectx->socket)) {
175                 return -1;
176         }
177
178         argv = talloc_array(ectx, const char *, 14);
179         if (argv == NULL) {
180                 return -1;
181         }
182
183         argv[0] = ectx->path;
184         argv[1] = "-e";
185         argv[2] = ectx->script_dir;
186         argv[3] = "-s";
187         argv[4] = ectx->socket;
188         argv[5] = "-P";
189         argv[6] = talloc_asprintf(argv, "%d", ctdb->ctdbd_pid);
190         argv[7] = "-l";
191         argv[8] = getenv("CTDB_LOGGING");
192         argv[9] = "-d";
193         argv[10] = debug_level_to_string(DEBUGLEVEL);
194         if (ectx->debug_hung_script == NULL) {
195                 argv[11] = NULL;
196                 argv[12] = NULL;
197         } else {
198                 argv[11] = "-D";
199                 argv[12] = ectx->debug_hung_script;
200         }
201         argv[13] = NULL;
202
203         if (argv[6] == NULL) {
204                 talloc_free(argv);
205                 return -1;
206         }
207
208         DEBUG(DEBUG_NOTICE,
209               ("Starting event daemon %s %s %s %s %s %s %s %s %s %s %s\n",
210                argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
211                argv[6], argv[7], argv[8], argv[9], argv[10]));
212
213         ret = pipe(fd);
214         if (ret != 0) {
215                 return -1;
216         }
217
218         pid = ctdb_fork(ctdb);
219         if (pid == -1) {
220                 close(fd[0]);
221                 close(fd[1]);
222                 return -1;
223         }
224
225         if (pid == 0) {
226                 close(fd[0]);
227                 ret = execv(argv[0], discard_const(argv));
228                 if (ret == -1) {
229                         _exit(errno);
230                 }
231                 _exit(0);
232         }
233
234         talloc_free(argv);
235         close(fd[1]);
236
237         ectx->eventd_fde = tevent_add_fd(ctdb->ev, ectx, fd[0],
238                                          TEVENT_FD_READ,
239                                          eventd_dead_handler, ectx);
240         if (ectx->eventd_fde == NULL) {
241                 ctdb_kill(ctdb, pid, SIGKILL);
242                 close(fd[0]);
243                 return -1;
244         }
245
246         tevent_fd_set_auto_close(ectx->eventd_fde);
247         ectx->eventd_pid = pid;
248
249         /* Wait to connect to eventd */
250         for (i=0; i<10; i++) {
251                 status = eventd_client_connect(ectx);
252                 if (status) {
253                         break;
254                 }
255                 sleep(1);
256         }
257
258         if (! status) {
259                 DEBUG(DEBUG_ERR, ("Failed to initialize event daemon\n"));
260                 ctdb_stop_eventd(ctdb);
261                 return -1;
262         }
263
264         return 0;
265 }
266
267 static void eventd_dead_handler(struct tevent_context *ev,
268                                 struct tevent_fd *fde, uint16_t flags,
269                                 void *private_data)
270 {
271         struct eventd_context *ectx = talloc_get_type_abort(
272                 private_data, struct eventd_context);
273
274         DEBUG(DEBUG_ERR, ("Eventd went away\n"));
275
276         TALLOC_FREE(ectx->eventd_fde);
277         ectx->eventd_pid = -1;
278 }
279
280 void ctdb_stop_eventd(struct ctdb_context *ctdb)
281 {
282         struct eventd_context *ectx = ctdb->ectx;
283
284         if (ectx == NULL) {
285                 return;
286         }
287
288         TALLOC_FREE(ectx->eventd_fde);
289         if (ectx->eventd_pid != -1) {
290                 kill(ectx->eventd_pid, SIGTERM);
291                 ectx->eventd_pid = -1;
292         }
293         TALLOC_FREE(ctdb->ectx);
294 }
295
296 /*
297  * Connect to event daemon
298  */
299
300 struct eventd_client_state {
301         struct eventd_client_state *prev, *next;
302
303         struct eventd_context *ectx;
304         void (*callback)(struct ctdb_event_reply *reply, void *private_data);
305         void *private_data;
306
307         uint32_t reqid;
308         uint8_t *buf;
309         size_t buflen;
310 };
311
312 static void eventd_client_read(uint8_t *buf, size_t buflen,
313                                void *private_data);
314 static int eventd_client_state_destructor(struct eventd_client_state *state);
315
316 static bool eventd_client_connect(struct eventd_context *ectx)
317 {
318         int fd;
319
320         if (ectx->queue != NULL) {
321                 return true;
322         }
323
324         fd = sock_connect(ectx->socket);
325         if (fd == -1) {
326                 return false;
327         }
328
329         ectx->queue = sock_queue_setup(ectx, ectx->ev, fd,
330                                        eventd_client_read, ectx);
331         if (ectx->queue == NULL) {
332                 close(fd);
333                 return false;
334         }
335
336         return true;
337 }
338
339 static int eventd_client_write(struct eventd_context *ectx,
340                                TALLOC_CTX *mem_ctx,
341                                struct ctdb_event_request *request,
342                                void (*callback)(struct ctdb_event_reply *reply,
343                                                 void *private_data),
344                                void *private_data)
345 {
346         struct eventd_client_state *state;
347         int ret;
348
349         if (! eventd_client_connect(ectx)) {
350                 return -1;
351         }
352
353         state = talloc_zero(mem_ctx, struct eventd_client_state);
354         if (state == NULL) {
355                 return -1;
356         }
357
358         state->ectx = ectx;
359         state->callback = callback;
360         state->private_data = private_data;
361
362         state->reqid = reqid_new(ectx->idr, state);
363         if (state->reqid == REQID_INVALID) {
364                 talloc_free(state);
365                 return -1;
366         }
367
368         talloc_set_destructor(state, eventd_client_state_destructor);
369
370         sock_packet_header_set_reqid(&request->header, state->reqid);
371
372         state->buflen = ctdb_event_request_len(request);
373         state->buf = talloc_size(state, state->buflen);
374         if (state->buf == NULL) {
375                 talloc_free(state);
376                 return -1;
377         }
378
379         ret = ctdb_event_request_push(request, state->buf, &state->buflen);
380         if (ret != 0) {
381                 talloc_free(state);
382                 return -1;
383         }
384
385         ret = sock_queue_write(ectx->queue, state->buf, state->buflen);
386         if (ret != 0) {
387                 talloc_free(state);
388                 return -1;
389         }
390
391         DLIST_ADD(ectx->calls, state);
392
393         return 0;
394 }
395
396 static int eventd_client_state_destructor(struct eventd_client_state *state)
397 {
398         struct eventd_context *ectx = state->ectx;
399
400         reqid_remove(ectx->idr, state->reqid);
401         DLIST_REMOVE(ectx->calls, state);
402         return 0;
403 }
404
405 static void eventd_client_read(uint8_t *buf, size_t buflen,
406                                void *private_data)
407 {
408         struct eventd_context *ectx = talloc_get_type_abort(
409                 private_data, struct eventd_context);
410         struct eventd_client_state *state;
411         struct ctdb_event_reply *reply;
412         int ret;
413
414         if (buf == NULL) {
415                 /* connection lost */
416                 TALLOC_FREE(ectx->queue);
417                 return;
418         }
419
420         reply = talloc_zero(ectx, struct ctdb_event_reply);
421         if (reply == NULL) {
422                 return;
423         }
424
425         ret = ctdb_event_reply_pull(buf, buflen, reply, reply);
426         if (ret != 0) {
427                 D_ERR("Invalid packet received, ret=%d\n", ret);
428                 talloc_free(reply);
429                 return;
430         }
431
432         if (buflen != reply->header.length) {
433                 D_ERR("Packet size mismatch %zu != %"PRIu32"\n",
434                       buflen, reply->header.length);
435                 talloc_free(reply);
436                 return;
437         }
438
439         state = reqid_find(ectx->idr, reply->header.reqid,
440                            struct eventd_client_state);
441         if (state == NULL) {
442                 talloc_free(reply);
443                 return;
444         }
445
446         if (state->reqid != reply->header.reqid) {
447                 talloc_free(reply);
448                 return;
449         }
450
451         state = talloc_steal(reply, state);
452         state->callback(reply, state->private_data);
453         talloc_free(reply);
454 }
455
456 /*
457  * Run an event
458  */
459
460 struct eventd_client_run_state {
461         struct eventd_context *ectx;
462         void (*callback)(int result, void *private_data);
463         void *private_data;
464 };
465
466 static void eventd_client_run_done(struct ctdb_event_reply *reply,
467                                    void *private_data);
468
469 static int eventd_client_run(struct eventd_context *ectx,
470                              TALLOC_CTX *mem_ctx,
471                              void (*callback)(int result,
472                                               void *private_data),
473                              void *private_data,
474                              enum ctdb_event event,
475                              const char *arg_str,
476                              uint32_t timeout)
477 {
478         struct eventd_client_run_state *state;
479         struct ctdb_event_request request;
480         struct ctdb_event_request_run rdata;
481         int ret;
482
483         state = talloc_zero(mem_ctx, struct eventd_client_run_state);
484         if (state == NULL) {
485                 return -1;
486         }
487
488         state->ectx = ectx;
489         state->callback = callback;
490         state->private_data = private_data;
491
492         rdata.event = event;
493         rdata.timeout = timeout;
494         rdata.arg_str = arg_str;
495
496         request.rdata.command = CTDB_EVENT_COMMAND_RUN;
497         request.rdata.data.run = &rdata;
498
499         ret = eventd_client_write(ectx, state, &request,
500                                   eventd_client_run_done, state);
501         if (ret != 0) {
502                 talloc_free(state);
503                 return ret;
504         }
505
506         return 0;
507 }
508
509 static void eventd_client_run_done(struct ctdb_event_reply *reply,
510                                    void *private_data)
511 {
512         struct eventd_client_run_state *state = talloc_get_type_abort(
513                 private_data, struct eventd_client_run_state);
514
515         state = talloc_steal(state->ectx, state);
516         state->callback(reply->rdata.result, state->private_data);
517         talloc_free(state);
518 }
519
520 /*
521  * CTDB event script functions
522  */
523
524 int ctdb_event_script_run(struct ctdb_context *ctdb,
525                           TALLOC_CTX *mem_ctx,
526                           void (*callback)(struct ctdb_context *ctdb,
527                                            int result, void *private_data),
528                           void *private_data,
529                           enum ctdb_event event,
530                           const char *fmt, va_list ap)
531                           PRINTF_ATTRIBUTE(6,0);
532
533 struct ctdb_event_script_run_state {
534         struct ctdb_context *ctdb;
535         void (*callback)(struct ctdb_context *ctdb, int result,
536                          void *private_data);
537         void *private_data;
538         enum ctdb_event event;
539 };
540
541 static bool event_allowed_during_recovery(enum ctdb_event event);
542 static void ctdb_event_script_run_done(int result, void *private_data);
543 static bool check_options(enum ctdb_event call, const char *options);
544
545 int ctdb_event_script_run(struct ctdb_context *ctdb,
546                           TALLOC_CTX *mem_ctx,
547                           void (*callback)(struct ctdb_context *ctdb,
548                                            int result, void *private_data),
549                           void *private_data,
550                           enum ctdb_event event,
551                           const char *fmt, va_list ap)
552 {
553         struct ctdb_event_script_run_state *state;
554         char *arg_str;
555         int ret;
556
557         if ( (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) &&
558              (! event_allowed_during_recovery(event)) ) {
559                 DEBUG(DEBUG_ERR,
560                       ("Refusing to run event '%s' while in recovery\n",
561                        ctdb_eventscript_call_names[event]));
562         }
563
564         state = talloc_zero(mem_ctx, struct ctdb_event_script_run_state);
565         if (state == NULL) {
566                 return -1;
567         }
568
569         state->ctdb = ctdb;
570         state->callback = callback;
571         state->private_data = private_data;
572         state->event = event;
573
574         if (fmt != NULL) {
575                 arg_str = talloc_vasprintf(state, fmt, ap);
576                 if (arg_str == NULL) {
577                         talloc_free(state);
578                         return -1;
579                 }
580         } else {
581                 arg_str = NULL;
582         }
583
584         if (! check_options(event, arg_str)) {
585                 DEBUG(DEBUG_ERR,
586                       ("Bad event script arguments '%s' for '%s'\n",
587                        arg_str, ctdb_eventscript_call_names[event]));
588                 talloc_free(arg_str);
589                 return -1;
590         }
591
592         ret = eventd_client_run(ctdb->ectx, state,
593                                 ctdb_event_script_run_done, state,
594                                 event, arg_str, ctdb->tunable.script_timeout);
595         if (ret != 0) {
596                 talloc_free(state);
597                 return ret;
598         }
599
600         DEBUG(DEBUG_INFO,
601               (__location__ " Running event %s with arguments %s\n",
602                ctdb_eventscript_call_names[event], arg_str));
603
604         talloc_free(arg_str);
605         return 0;
606 }
607
608 static void ctdb_event_script_run_done(int result, void *private_data)
609 {
610         struct ctdb_event_script_run_state *state = talloc_get_type_abort(
611                 private_data, struct ctdb_event_script_run_state);
612
613         if (result == -ETIME) {
614                 switch (state->event) {
615                 case CTDB_EVENT_START_RECOVERY:
616                 case CTDB_EVENT_RECOVERED:
617                 case CTDB_EVENT_TAKE_IP:
618                 case CTDB_EVENT_RELEASE_IP:
619                         DEBUG(DEBUG_ERR,
620                               ("Ignoring hung script for %s event\n",
621                                ctdb_eventscript_call_names[state->event]));
622                         result = 0;
623                         break;
624
625                 default:
626                         break;
627                 }
628         }
629
630         state = talloc_steal(state->ctdb, state);
631         state->callback(state->ctdb, result, state->private_data);
632         talloc_free(state);
633 }
634
635
636 static unsigned int count_words(const char *options)
637 {
638         unsigned int words = 0;
639
640         if (options == NULL) {
641                 return 0;
642         }
643
644         options += strspn(options, " \t");
645         while (*options) {
646                 words++;
647                 options += strcspn(options, " \t");
648                 options += strspn(options, " \t");
649         }
650         return words;
651 }
652
653 static bool check_options(enum ctdb_event call, const char *options)
654 {
655         switch (call) {
656         /* These all take no arguments. */
657         case CTDB_EVENT_INIT:
658         case CTDB_EVENT_SETUP:
659         case CTDB_EVENT_STARTUP:
660         case CTDB_EVENT_START_RECOVERY:
661         case CTDB_EVENT_RECOVERED:
662         case CTDB_EVENT_MONITOR:
663         case CTDB_EVENT_SHUTDOWN:
664         case CTDB_EVENT_IPREALLOCATED:
665                 return count_words(options) == 0;
666
667         case CTDB_EVENT_TAKE_IP: /* interface, IP address, netmask bits. */
668         case CTDB_EVENT_RELEASE_IP:
669                 return count_words(options) == 3;
670
671         case CTDB_EVENT_UPDATE_IP: /* old interface, new interface, IP address, netmask bits. */
672                 return count_words(options) == 4;
673
674         default:
675                 DEBUG(DEBUG_ERR,(__location__ "Unknown ctdb_event %u\n", call));
676                 return false;
677         }
678 }
679
680 /* only specific events are allowed while in recovery */
681 static bool event_allowed_during_recovery(enum ctdb_event event)
682 {
683         const enum ctdb_event allowed_events[] = {
684                 CTDB_EVENT_INIT,
685                 CTDB_EVENT_SETUP,
686                 CTDB_EVENT_START_RECOVERY,
687                 CTDB_EVENT_SHUTDOWN,
688                 CTDB_EVENT_RELEASE_IP,
689                 CTDB_EVENT_IPREALLOCATED,
690         };
691         int i;
692
693         for (i = 0; i < ARRAY_SIZE(allowed_events); i++) {
694                 if (event == allowed_events[i]) {
695                         return true;
696                 }
697         }
698
699         return false;
700 }
701
702 /*
703   run the event script in the background, calling the callback when
704   finished.  If mem_ctx is freed, callback will never be called.
705  */
706 int ctdb_event_script_callback(struct ctdb_context *ctdb,
707                                TALLOC_CTX *mem_ctx,
708                                void (*callback)(struct ctdb_context *, int, void *),
709                                void *private_data,
710                                enum ctdb_event call,
711                                const char *fmt, ...)
712 {
713         va_list ap;
714         int ret;
715
716         va_start(ap, fmt);
717         ret = ctdb_event_script_run(ctdb, mem_ctx, callback, private_data,
718                                     call, fmt, ap);
719         va_end(ap);
720
721         return ret;
722 }
723
724
725 struct ctdb_event_script_args_state {
726         bool done;
727         int status;
728 };
729
730 static void ctdb_event_script_args_done(struct ctdb_context *ctdb,
731                                         int status, void *private_data)
732 {
733         struct ctdb_event_script_args_state *s =
734                 (struct ctdb_event_script_args_state *)private_data;
735
736         s->done = true;
737         s->status = status;
738 }
739
740 /*
741   run the event script, waiting for it to complete. Used when the caller
742   doesn't want to continue till the event script has finished.
743  */
744 int ctdb_event_script_args(struct ctdb_context *ctdb, enum ctdb_event call,
745                            const char *fmt, ...)
746 {
747         va_list ap;
748         int ret;
749         struct ctdb_event_script_args_state state = {
750                 .status = -1,
751                 .done = false,
752         };
753
754         va_start(ap, fmt);
755         ret = ctdb_event_script_run(ctdb, ctdb,
756                                     ctdb_event_script_args_done, &state,
757                                     call, fmt, ap);
758         va_end(ap);
759         if (ret != 0) {
760                 return ret;
761         }
762
763         while (! state.done) {
764                 tevent_loop_once(ctdb->ev);
765         }
766
767         if (state.status == -ETIME) {
768                 /* Don't ban self if CTDB is starting up or shutting down */
769                 if (call != CTDB_EVENT_INIT && call != CTDB_EVENT_SHUTDOWN) {
770                         DEBUG(DEBUG_ERR,
771                               (__location__ " eventscript for '%s' timed out."
772                                " Immediately banning ourself for %d seconds\n",
773                                ctdb_eventscript_call_names[call],
774                                ctdb->tunable.recovery_ban_period));
775                         ctdb_ban_self(ctdb);
776                 }
777         }
778
779         return state.status;
780 }
781
782 int ctdb_event_script(struct ctdb_context *ctdb, enum ctdb_event call)
783 {
784         /* GCC complains about empty format string, so use %s and "". */
785         return ctdb_event_script_args(ctdb, call, NULL);
786 }