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
eventd_event_find(struct event_component * comp,const char * event_name)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
eventd_event_add(struct event_component * comp,const char * event_name,struct event_event ** result)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
eventd_event_set(struct event_component * comp,const char * event_name,struct run_event_script_list * script_list)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
eventd_event_get(struct event_component * comp,const char * event_name,struct run_event_script_list ** result)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
eventd_component_find(struct event_context * eventd,const char * comp_name)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
eventd_component_add(struct event_context * eventd,const char * comp_name,struct event_component ** result)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
eventd_client_find(struct event_context * eventd,struct sock_client_context * client)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
eventd_client_add(struct event_context * eventd,struct sock_client_context * client)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
eventd_client_del(struct event_context * eventd,struct sock_client_context * client)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
eventd_client_exists(struct event_context * eventd,struct sock_client_context * client)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
event_context_init(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct event_config * config,struct event_context ** result)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
eventd_config(struct event_context * eventd)362 struct event_config *eventd_config(struct event_context *eventd)
363 {
364 return eventd->config;
365 }
366
eventd_run_ctx(struct event_context * eventd,const char * comp_name,struct run_event_context ** result)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
eventd_set_event_result(struct event_context * eventd,const char * comp_name,const char * event_name,struct run_event_script_list * script_list)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
eventd_get_event_result(struct event_context * eventd,const char * comp_name,const char * event_name,struct run_event_script_list ** result)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
eventd_script_list(TALLOC_CTX * mem_ctx,struct run_event_script_list * script_list)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 }
473