diff options
author | Paweł Szewczyk <p.szewczyk@samsung.com> | 2019-01-29 17:35:00 +0100 |
---|---|---|
committer | Paweł Szewczyk <p.szewczyk@samsung.com> | 2019-01-29 17:40:56 +0100 |
commit | 35c32ec730c92905c97b576ae9f2d3f710fc3bcd (patch) | |
tree | fd31bdf8628d463e6bc95752f45fc3bc62e521c2 | |
parent | 0cf917c014cf42747fa5990205f752ba833bd7c3 (diff) | |
download | faultd-sandbox/pszewczyk/master.tar.gz faultd-sandbox/pszewczyk/master.tar.bz2 faultd-sandbox/pszewczyk/master.zip |
dm: Add configurable 'activation' decision makersandbox/pszewczyk/master
This module allows to bind events to specific actions by using a
configuration file.
Change-Id: I4d406f739df4788d03d9ba99bf247e69409564a3
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | packaging/faultd.spec | 3 | ||||
-rw-r--r-- | src/decision_makers/activation_dm.c | 174 |
3 files changed, 181 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index 95a249e..d6b7829 100644 --- a/Makefile.am +++ b/Makefile.am @@ -131,7 +131,8 @@ EXTRA_faultd_SOURCES = \ src/action/system_reboot.c \ src/action/system_reboot_to_recovery.c \ src/action/service_recover.c \ - src/action/unit_start.c + src/action/unit_start.c \ + src/decision_makers/activation_dm.c faultd_CFLAGS = $(AM_CFLAGS) faultd_LDFLAGS = -ldl @@ -149,7 +150,8 @@ modules_LTLIBRARIES = audit_listener.la \ system_reboot_action.la \ system_reboot_to_recovery_action.la \ service_recover_action.la \ - unit_start_action.la + unit_start_action.la \ + activation_eh.la audit_listener_la_SOURCES = src/listeners/audit.c audit_listener_la_LIBADD = $(AUDIT_LIBS) @@ -170,6 +172,7 @@ system_reboot_action_la_SOURCES = src/action/system_reboot.c system_reboot_to_recovery_action_la_SOURCES = src/action/system_reboot_to_recovery.c service_recover_action_la_SOURCES = src/action/service_recover.c unit_start_action_la_SOURCES = src/action/unit_start.c +activation_eh_la_SOURCES = src/decision_makers/activation_dm.c if USE_EJDB EXTRA_faultd_SOURCES += src/database/ejdb.c diff --git a/packaging/faultd.spec b/packaging/faultd.spec index d1d78cd..462acca 100644 --- a/packaging/faultd.spec +++ b/packaging/faultd.spec @@ -86,7 +86,8 @@ for mod in audit_listener \ standard_reboot_eh \ startup_listener \ system_reboot_to_recovery_action \ - unit_start_action + unit_start_action \ + activation_eh do ln -s %{moduledir}/${mod}.so %{buildroot}/%{moduleconfdir}/${mod}.so; ln -s ../available-modules/${mod}.so %{buildroot}/%{enabled_moduledir}/${mod}.so; diff --git a/src/decision_makers/activation_dm.c b/src/decision_makers/activation_dm.c new file mode 100644 index 0000000..5b508da --- /dev/null +++ b/src/decision_makers/activation_dm.c @@ -0,0 +1,174 @@ +/* + * This file is part of faultd. + * + * Copyright © 2017 Samsung Electronics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <malloc.h> +#include <errno.h> + +#include "decision_made_event.h" +#include "action.h" +#include "event_processor.h" +#include "log.h" +#include "service.h" +#include "common.h" +#include "database.h" +#include "json-config.h" + +#define MODULE_NAME "activation_decision_maker" + +struct activation_decision_maker { + struct faultd_event_handler eh; + struct list_head rules; +}; + +struct rule { + char *ev_name; + char *action_name; + struct fault_object *action_data; + + struct list_head node; +}; + +static int activation_event_match(struct faultd_event_handler *handler, + struct faultd_event *ev) +{ + struct activation_decision_maker *dm = container_of(handler, + struct activation_decision_maker, eh); + struct rule *r; + + /* TODO separate list for existing types to avoid looping for every event */ + list_for_each_entry(r, &dm->rules, node) { + if (strcmp(r->ev_name, ev->type->name) == 0) + return 1; + } + + return 0; +} + +static int activation_make_decision(struct faultd_event_handler *handler) +{ + struct faultd_event *ev = pop_faultd_event(&handler->event_queue); + struct activation_decision_maker *dm = container_of(handler, + struct activation_decision_maker, eh); + int ret; + struct rule *r; + struct faultd_event *new_ev; + struct dm_event_data ev_data = { + .reason = ev, + .who_made = MODULE_NAME, + }; + + list_for_each_entry(r, &dm->rules, node) { + if (strcmp(r->ev_name, ev->type->name)) + continue; + + ev_data.action_data = r->action_data; /* action data is already initalized */ + ret = faultd_event_create(DECISION_MADE_EVENT_ID, &ev_data, &new_ev); + if (ret) { + log_error("Unable to create event"); + goto out; + } + + ret = event_processor_report_event(new_ev); + faultd_event_unref(new_ev); + if (ret) { + log_error("Unable to report event"); + goto out; + } + } + + return 0; + +out: + return ret; +} + +static int add_rule(struct activation_decision_maker *dm, json_object *root) +{ + int ret; + struct rule *r; + char *str; + + r = malloc(sizeof(*r)); + + ret = get_config_field(root, "event", &str, json_type_string); + if (ret < 0) + goto out; + + r->ev_name = str; + + ret = get_config_field(root, "action", &str, json_type_string); + if (ret < 0) + goto out; + + r->action_name = str; + + /* + ret = get_config_field(root, "data", &obj, json_type_obj); + if (ret < 0) + goto out; + TODO get data + */ + + list_add_tail(&r->node, &dm->rules); + +out: + free(r); + return ret; +} + +static int activation_init(struct faultd_event_handler *handler, struct faultd_config *config) +{ + struct activation_decision_maker *dm = container_of(handler, + struct activation_decision_maker, eh); + int ret; + int len; + int i; + json_object *array, *obj; + + INIT_LIST_HEAD(&dm->rules); + + if (config == NULL) + return 0; + + ret = get_config_field(config->root, "rules", + &array, + json_type_array); + if (ret < 0) + return ret; + + len = json_object_array_length(array); + for (i = 0; i < len; ++i) { + obj = json_object_array_get_idx(array, i); + add_rule(dm, obj); + } + + return ret; +}; + +static struct activation_decision_maker activation_dm = { + .eh = { + .name = MODULE_NAME, + .init = activation_init, + .event_match = activation_event_match, + .handle_event = activation_make_decision, + + .node = LIST_HEAD_INIT(activation_dm.eh.node), + }, +}; + +FAULTD_EVENT_HANDLER_REGISTER(activation_dm.eh, activation_eh, + FAULTD_MODULE_TYPE_DECISION_MAKER) |