ctdb-scripts: Update statd-callout to try several configuration files
[vlendec/samba-autobuild/.git] / ctdb / event / event_context.c
1 /*
2    CTDB event daemon - daemon state
3
4    Copyright (C) Amitay Isaacs  2018
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/dir.h"
22
23 #include <talloc.h>
24 #include <tevent.h>
25
26 #include "lib/util/debug.h"
27 #include "lib/util/dlinklist.h"
28
29 #include "common/logging.h"
30 #include "common/run_event.h"
31 #include "common/path.h"
32
33 #include "event/event_private.h"
34
35 struct event_event {
36         struct event_event *prev, *next;
37
38         const char *name;
39         struct run_event_script_list *script_list;
40 };
41
42 struct event_component {
43         struct event_component *prev, *next;
44
45         /* component state */
46         const char *name;
47         const char *path;
48         struct run_event_context *run_ctx;
49
50         /* events list */
51         struct event_event *event;
52 };
53
54 struct event_client {
55         struct event_client *prev, *next;
56
57         struct sock_client_context *client;
58 };
59
60 struct event_context {
61         struct tevent_context *ev;
62         struct event_config *config;
63         struct run_proc_context *run_proc_ctx;
64
65         const char *script_dir;
66         const char *debug_script;
67
68         /* component list */
69         struct event_component *component;
70
71         /* client list */
72         struct event_client *client;
73 };
74
75 /*
76  * event_event functions
77  */
78
79 static struct event_event *eventd_event_find(struct event_component *comp,
80                                              const char *event_name)
81 {
82         struct event_event *event;
83
84         if (event_name == NULL) {
85                 return NULL;
86         }
87
88         for (event = comp->event; event != NULL; event = event->next) {
89                 if (strcmp(event->name, event_name) == 0) {
90                         return event;
91                 }
92         }
93
94         return NULL;
95 }
96
97 static int eventd_event_add(struct event_component *comp,
98                             const char *event_name,
99                             struct event_event **result)
100 {
101         struct event_event *event;
102
103         if (event_name == NULL) {
104                 return EINVAL;
105         }
106
107         event = eventd_event_find(comp, event_name);
108         if (event != NULL) {
109                 goto done;
110         }
111
112         event = talloc_zero(comp, struct event_event);
113         if (event == NULL) {
114                 return ENOMEM;
115         }
116
117         event->name = talloc_strdup(event, event_name);
118         if (event->name == NULL) {
119                 talloc_free(event);
120                 return ENOMEM;
121         }
122
123         DLIST_ADD_END(comp->event, event);
124
125 done:
126         if (result != NULL) {
127                 *result = event;
128         }
129         return 0;
130 }
131
132 static int eventd_event_set(struct event_component *comp,
133                             const char *event_name,
134                             struct run_event_script_list *script_list)
135 {
136         struct event_event *event = NULL;
137         int ret;
138
139         ret = eventd_event_add(comp, event_name, &event);
140         if (ret != 0) {
141                 return ret;
142         }
143
144         TALLOC_FREE(event->script_list);
145         if (script_list != NULL) {
146                 event->script_list = talloc_steal(event, script_list);
147         }
148
149         return 0;
150 }
151
152 static int eventd_event_get(struct event_component *comp,
153                             const char *event_name,
154                             struct run_event_script_list **result)
155 {
156         struct event_event *event;
157
158         event = eventd_event_find(comp, event_name);
159         if (event == NULL) {
160                 return EINVAL;
161         }
162
163         *result = event->script_list;
164         return 0;
165 }
166
167 /*
168  * event_component functions
169  */
170
171 static struct event_component *eventd_component_find(
172                                         struct event_context *eventd,
173                                         const char *comp_name)
174 {
175         struct event_component *comp;
176
177         if (comp_name == NULL) {
178                 return NULL;
179         }
180
181         for (comp = eventd->component; comp != NULL; comp = comp->next) {
182                 if (strcmp(comp->name, comp_name) == 0) {
183                         return comp;
184                 }
185         }
186
187         return NULL;
188 }
189
190 static int eventd_component_add(struct event_context *eventd,
191                                 const char *comp_name,
192                                 struct event_component **result)
193 {
194         struct event_component *comp;
195         int ret;
196
197         if (comp_name == NULL) {
198                 return EINVAL;
199         }
200
201         comp = eventd_component_find(eventd, comp_name);
202         if (comp != NULL) {
203                 goto done;
204         }
205
206         comp = talloc_zero(eventd, struct event_component);
207         if (comp == NULL) {
208                 return ENOMEM;
209         }
210
211         comp->name = talloc_strdup(comp, comp_name);
212         if (comp->name == NULL) {
213                 talloc_free(comp);
214                 return ENOMEM;
215         }
216
217         comp->path = talloc_asprintf(comp,
218                                      "%s/%s",
219                                      eventd->script_dir,
220                                      comp_name);
221         if (comp->path == NULL) {
222                 talloc_free(comp);
223                 return ENOMEM;
224         }
225
226         ret = run_event_init(eventd,
227                              eventd->run_proc_ctx,
228                              comp->path,
229                              eventd->debug_script,
230                              &comp->run_ctx);
231         if (ret != 0) {
232                 talloc_free(comp);
233                 return ret;
234         }
235
236         DLIST_ADD_END(eventd->component, comp);
237
238 done:
239         if (result != NULL) {
240                 *result = comp;
241         }
242         return 0;
243 }
244
245 /*
246  * event_client functions
247  */
248
249 static struct event_client *eventd_client_find(
250                                         struct event_context *eventd,
251                                         struct sock_client_context *client)
252 {
253         struct event_client *e;
254
255         for (e = eventd->client; e != NULL; e = e->next) {
256                 if (e->client == client) {
257                         return e;
258                 }
259         }
260
261         return NULL;
262 }
263
264 int eventd_client_add(struct event_context *eventd,
265                       struct sock_client_context *client)
266 {
267         struct event_client *e;
268
269         e = talloc_zero(eventd, struct event_client);
270         if (e == NULL) {
271                 return ENOMEM;
272         }
273
274         e->client = client;
275
276         DLIST_ADD_END(eventd->client, e);
277
278         return 0;
279 }
280
281 void eventd_client_del(struct event_context *eventd,
282                        struct sock_client_context *client)
283 {
284         struct event_client *e;
285
286         e = eventd_client_find(eventd, client);
287         if (e == NULL) {
288                 return;
289         }
290
291         DLIST_REMOVE(eventd->client, e);
292
293         talloc_free(e);
294 }
295
296 bool eventd_client_exists(struct event_context *eventd,
297                           struct sock_client_context *client)
298 {
299         struct event_client *e;
300
301         e = eventd_client_find(eventd, client);
302         if (e == NULL) {
303                 return false;
304         }
305
306         return true;
307 }
308
309 /* public functions */
310
311 int event_context_init(TALLOC_CTX *mem_ctx,
312                        struct tevent_context *ev,
313                        struct event_config *config,
314                        struct event_context **result)
315 {
316         struct event_context *eventd;
317         const char *debug_script;
318         int ret;
319
320         eventd = talloc_zero(mem_ctx, struct event_context);
321         if (eventd == NULL) {
322                 return ENOMEM;
323         }
324
325         eventd->ev = ev;
326         eventd->config = config;
327
328         ret = run_proc_init(eventd, ev, &eventd->run_proc_ctx);
329         if (ret != 0) {
330                 talloc_free(eventd);
331                 return ret;
332         }
333
334         eventd->script_dir = path_etcdir_append(eventd, "events");
335         if (eventd->script_dir == NULL) {
336                 talloc_free(eventd);
337                 return ENOMEM;
338         }
339
340         /* FIXME
341         status = directory_exist(eventd->script_dir);
342         if (! status) {
343                 talloc_free(eventd);
344                 return EINVAL;
345         }
346         */
347
348         debug_script = event_config_debug_script(config);
349         if (debug_script != NULL) {
350                 eventd->debug_script = path_etcdir_append(eventd,
351                                                           debug_script);
352                 if (eventd->debug_script == NULL) {
353                         D_WARNING("Failed to set debug script to %s\n",
354                                   debug_script);
355                 }
356         }
357
358         *result = eventd;
359         return 0;
360 }
361
362 struct event_config *eventd_config(struct event_context *eventd)
363 {
364         return eventd->config;
365 }
366
367 int eventd_run_ctx(struct event_context *eventd,
368                    const char *comp_name,
369                    struct run_event_context **result)
370 {
371         struct event_component *comp;
372         int ret;
373
374         ret = eventd_component_add(eventd, comp_name, &comp);
375         if (ret != 0) {
376                 return ret;
377         }
378
379         *result = comp->run_ctx;
380         return 0;
381 }
382
383 int eventd_set_event_result(struct event_context *eventd,
384                             const char *comp_name,
385                             const char *event_name,
386                             struct run_event_script_list *script_list)
387 {
388         struct event_component *comp;
389
390         comp = eventd_component_find(eventd, comp_name);
391         if (comp == NULL) {
392                 return ENOENT;
393         }
394
395         return eventd_event_set(comp, event_name, script_list);
396 }
397
398 int eventd_get_event_result(struct event_context *eventd,
399                             const char *comp_name,
400                             const char *event_name,
401                             struct run_event_script_list **result)
402 {
403         struct event_component *comp;
404         int ret;
405
406         ret = eventd_component_add(eventd, comp_name, &comp);
407         if (ret != 0) {
408                 return ret;
409         }
410
411         return eventd_event_get(comp, event_name, result);
412 }
413
414 struct ctdb_event_script_list *eventd_script_list(
415                                 TALLOC_CTX *mem_ctx,
416                                 struct run_event_script_list *script_list)
417 {
418         struct ctdb_event_script_list *value;
419         int num_scripts = 0;
420         int i;
421
422         value = talloc_zero(mem_ctx, struct ctdb_event_script_list);
423         if (value == NULL) {
424                 return NULL;
425         }
426
427         if (script_list != NULL) {
428                 num_scripts = script_list->num_scripts;
429         }
430
431         if (num_scripts <= 0) {
432                 return value;
433         }
434
435         value->script = talloc_array(value,
436                                      struct ctdb_event_script,
437                                      num_scripts);
438         if (value->script == NULL) {
439                 goto fail;
440         }
441
442         for (i=0; i<num_scripts; i++) {
443                 struct run_event_script *rscript = &script_list->script[i];
444                 struct ctdb_event_script *escript = &value->script[i];
445
446                 escript->name = talloc_strdup(value, rscript->name);
447                 if (escript->name == NULL) {
448                         goto fail;
449                 }
450
451                 escript->begin = rscript->begin;
452                 escript->end = rscript->end;
453                 escript->result = rscript->summary;
454
455                 if (rscript->output == NULL) {
456                         escript->output = NULL;
457                         continue;
458                 }
459
460                 escript->output = talloc_strdup(value, rscript->output);
461                 if (escript->output == NULL) {
462                         goto fail;
463                 }
464         }
465         value->num_scripts = num_scripts;
466
467         return value;
468
469 fail:
470         talloc_free(value);
471         return NULL;
472 }