Load plugins configuration from config file 86/161986/6
authorKonrad Kuchciak <k.kuchciak@samsung.com>
Tue, 28 Nov 2017 10:39:02 +0000 (11:39 +0100)
committerKonrad Kuchciak <k.kuchciak@samsung.com>
Tue, 5 Dec 2017 17:11:56 +0000 (18:11 +0100)
For now, two parameters can be loaded from config:
*n_reboots_before_recovery for standard_reboot_dm
*n_fails_before_reboot for standard_fault_dm

Change-Id: I7422ebeb37cfdab2428e6d708b290cf89229de5b
Signed-off-by: Konrad Kuchciak <k.kuchciak@samsung.com>
Makefile.am
faultd.conf [new file with mode: 0644]
packaging/faultd.spec
src/core/event_processor.h
src/decision_makers/standard_fault_dm.c
src/decision_makers/standard_reboot_dm.c
src/util/json-config.c
src/util/json-config.h

index 2786f092acbe98b8407e8cc41e8ed563975497c0..2245594725bda5b6de37b30227e65fc578bad1b9 100644 (file)
@@ -75,6 +75,9 @@ dbdir = $(localstatedir)/db/faultd
 nodist_unit_DATA = \
     faultd.service
 
+config_DATA = \
+    faultd.conf
+
 serviceconfig_DATA = \
     conf.d/dbus.service.conf \
     conf.d/display-manager.service.conf
diff --git a/faultd.conf b/faultd.conf
new file mode 100644 (file)
index 0000000..b338408
--- /dev/null
@@ -0,0 +1,8 @@
+{
+       "standard_reboot_eh" : {
+               "n_reboots_before_recovery" : 3
+       },
+       "standard_fault_eh" : {
+               "n_fails_before_reboot" : 3
+       }
+}
index 7e5b2eea26d011fcb3b9e35697455d7304c47b5c..355ffdfa744b3afcc8b4609ff491e20822e7d717 100644 (file)
@@ -97,6 +97,7 @@ done
 %manifest %{name}.manifest
 %{_localstatedir}/db/faultd
 %{_sbindir}/faultd
+%{_sysconfdir}/faultd/faultd.conf
 %{_sysconfdir}/faultd/conf.d/dbus.service.conf
 %{_sysconfdir}/faultd/conf.d/display-manager.service.conf
 %{_unitdir}/faultd.service
index e6b7668413d26812976c4104518265d18110e1e6..10b7b1968c7154a6c20fbc0592fb860d22c8aae8 100644 (file)
 
 struct faultd_event_handler {
        char *name;
+
+       int (*init)(struct faultd_event_handler *handler, struct faultd_config *config);
+       void (*cleanup)(struct faultd_event_handler *handler);
+
        /* Would you like to handle this? */
        int (*event_match)(struct faultd_event_handler *handler,
                                           struct faultd_event *ev);
@@ -50,11 +54,22 @@ static int event_handler_ ##NAME## _init(struct faultd_module *module,  \
                                                                                 struct faultd_config *config,  \
                                                                                 sd_event *event_loop)                  \
 {                                                                                                                                              \
+       int ret;                                                                                                                        \
+                                                                                                                                               \
+       if (EVENT_HANDLER.init) {                                                                                       \
+               ret = EVENT_HANDLER.init(&EVENT_HANDLER, config);                               \
+               if (ret)                                                                                                                \
+                       return ret;                                                                                                     \
+       }                                                                                                                                       \
+                                                                                                                                               \
        return event_processor_handler_register(&EVENT_HANDLER);                        \
 }                                                                                                                                              \
                                                                                                                                                \
 static void event_handler_ ##NAME## _cleanup(struct faultd_module *module) \
 {                                                                                                                                              \
+       if (EVENT_HANDLER.cleanup)                                                                                      \
+               EVENT_HANDLER.cleanup(&EVENT_HANDLER);                                                  \
+                                                                                                                                               \
        event_processor_handler_unregister(&EVENT_HANDLER);                                     \
 }                                                                                                                                              \
                                                                                                                                                \
index 5eb9e69f03dd6bdf63e1cd473dccbb11fcf12670..ce1652dad826952a92ff1b18b4bda206f5883efd 100644 (file)
 #include "service.h"
 #include "common.h"
 #include "database.h"
+#include "json-config.h"
 
 #define MODULE_NAME "standard_fault_decision_maker"
 
+struct standard_fault_decision_maker {
+       struct faultd_event_handler eh;
+       int n_fails_before_reboot;
+};
+
 static int sf_event_match(struct faultd_event_handler *handler,
                                                  struct faultd_event *ev)
 {
@@ -43,6 +49,7 @@ static int sf_make_decision(struct faultd_event_handler *handler)
 {
        struct faultd_event *ev = pop_faultd_event(&handler->event_queue);
        struct service_failed_event *sf_ev = to_service_failed_event(ev);
+       struct standard_fault_decision_maker *sf_dm = container_of(handler, struct standard_fault_decision_maker, eh);
        struct system_booted_event *boot_event;
        struct faultd_event *new_ev;
        struct dm_event_data ev_data = {
@@ -96,7 +103,7 @@ static int sf_make_decision(struct faultd_event_handler *handler)
                goto unref_ev;
        }
 
-       if (nr < 3) {
+       if (nr < (uint32_t) sf_dm->n_fails_before_reboot) {
                ev_data.action = FAULTD_ACTION_SERVICE_RECOVER_ID;
                ret = faultd_fill_for_srv_recover(ev_data.action_data,
                                                                  sf_ev->service.dbus_path,
@@ -131,14 +138,34 @@ unref_ev:
        return 0;
 }
 
-static struct faultd_event_handler standard_fault_event_handler = {
-       .name = MODULE_NAME,
-       .event_match = sf_event_match,
-       .handle_event = sf_make_decision,
+static int sf_init(struct faultd_event_handler *handler, struct faultd_config *config)
+{
+       struct standard_fault_decision_maker *sf_dm = container_of(handler,
+                                                                                                                          struct standard_fault_decision_maker,
+                                                                                                                          eh);
+       int ret;
+
+       if (config == NULL)
+               return 0;
+
+       ret = get_config_field(config->root, "n_fails_before_reboot",
+                                                  &sf_dm->n_fails_before_reboot,
+                                                  json_type_int);
+       return ret;
+};
+
+static struct standard_fault_decision_maker standard_fault_dm = {
+       .eh = {
+               .name = MODULE_NAME,
+               .init = sf_init,
+               .event_match = sf_event_match,
+               .handle_event = sf_make_decision,
 
-       .node = LIST_HEAD_INIT(standard_fault_event_handler.node),
+               .node = LIST_HEAD_INIT(standard_fault_dm.eh.node),
+       },
+       .n_fails_before_reboot = 3,
 };
 
-FAULTD_EVENT_HANDLER_REGISTER(standard_fault_event_handler,
+FAULTD_EVENT_HANDLER_REGISTER(standard_fault_dm.eh,
                                                          standard_fault_eh,
                                                          FAULTD_MODULE_TYPE_DECISION_MAKER)
index c234e6936ce489a4eb521b5405853061c94ff7c1..40f783aaad084ea456e21882115d19ee9dd7e897 100644 (file)
 #include "event_processor.h"
 #include "log.h"
 #include "service.h"
+#include "json-config.h"
 
 #define MODULE_NAME "standard_reboot_decision_maker"
-#define REBOOTS_BEFORE_RECOVERY 3
+
+struct standard_reboot_decision_maker {
+       struct faultd_event_handler eh;
+       int n_reboots_before_recovery;
+};
 
 static int sr_event_match(struct faultd_event_handler *handler,
                                                  struct faultd_event *ev)
@@ -106,6 +111,9 @@ unref_query:
 static int sr_make_decision(struct faultd_event_handler *handler)
 {
        struct faultd_event *ev = pop_faultd_event(&handler->event_queue);
+       struct standard_reboot_decision_maker *sr_dm = container_of(handler,
+                                                                                                                               struct standard_reboot_decision_maker,
+                                                                                                                               eh);
        struct faultd_event *new_ev = NULL;
        struct dm_event_data ev_data = {
                .reason = ev,
@@ -118,13 +126,16 @@ static int sr_make_decision(struct faultd_event_handler *handler)
        char *last_service_name = NULL;
        int ret;
 
+       if (sr_dm->n_reboots_before_recovery < 0)
+               goto unref_ev;
+
        sb_ev = get_boot_event();
        if (sb_ev == NULL) {
                log_error("Unable to get current boot event");
                goto unref_ev;
        }
 
-       for (int i = 0; i < REBOOTS_BEFORE_RECOVERY; ++i) {
+       for (int i = 0; i < sr_dm->n_reboots_before_recovery; ++i) {
                /* get prev boot event */
                ret = database_get_event(&sb_ev->prev_boot_event, &tmp_ev);
                faultd_event_unref(&sb_ev->event);
@@ -199,14 +210,34 @@ unref_ev:
        return 0;
 }
 
-static struct faultd_event_handler standard_reboot_event_handler = {
-       .name = MODULE_NAME,
-       .event_match = sr_event_match,
-       .handle_event = sr_make_decision,
+static int sr_init(struct faultd_event_handler *handler, struct faultd_config *config)
+{
+       struct standard_reboot_decision_maker *sr_dm = container_of(handler,
+                                                                                                                               struct standard_reboot_decision_maker,
+                                                                                                                               eh);
+       int ret;
+
+       if (config == NULL)
+               return 0;
+
+       ret = get_config_field(config->root, "n_reboots_before_recovery",
+                                                  &sr_dm->n_reboots_before_recovery,
+                                                  json_type_int);
+       return ret;
+};
+
+static struct standard_reboot_decision_maker standard_reboot_dm = {
+       .eh = {
+               .name = MODULE_NAME,
+               .init = sr_init,
+               .event_match = sr_event_match,
+               .handle_event = sr_make_decision,
 
-       .node = LIST_HEAD_INIT(standard_reboot_event_handler.node),
+               .node = LIST_HEAD_INIT(standard_reboot_dm.eh.node),
+       },
+       .n_reboots_before_recovery = 3,
 };
 
-FAULTD_EVENT_HANDLER_REGISTER(standard_reboot_event_handler,
+FAULTD_EVENT_HANDLER_REGISTER(standard_reboot_dm.eh,
                                                          standard_reboot_eh,
                                                          FAULTD_MODULE_TYPE_DECISION_MAKER)
index ace02bd50db1910c513241d120fcb5eddee47bde..980eecca8320e34da700864e16e779f381a9f3e8 100644 (file)
 #include "json-config.h"
 #include "log.h"
 
-static int get_config_field(struct json_object *root,
-                                                       const char *key, char **value)
+int get_config_field(struct json_object *root, const char *key, void *value, int type)
 {
-       struct json_object *node;
-       const char *node_value;
-       json_bool rc;
-       int ret = 0;
-
-       /* if there is no such node let's skip it */
-       rc = json_object_object_get_ex(root, key, &node);
-       if (!rc)
+       struct json_object *node = NULL;
+
+       if (!json_object_object_get_ex(root, key, &node)) {
+               log_debug("Config does not contain %s parameter. "
+                                 "Using default value", key);
                return 0;
+       }
+
+       if (!json_object_is_type(node, type)) {
+               int t = json_object_get_type(node);
 
-       if (!json_object_is_type(node, json_type_string)) {
-               log_error("Option %s has to be a string", key);
+               log_error("Option %s has to be a %s, but is %s",
+                                 key, json_type_to_name(type), json_type_to_name(t));
                return -EINVAL;
        }
 
-       node_value = json_object_get_string(node);
+       switch (type) {
+       case json_type_int: {
+               int node_value;
 
-       *value = strdup(node_value);
-       if (*value == NULL) {
-               log_error("Failed to duplicate string");
-               ret = -ENOMEM;
+               errno = 0;
+               node_value = json_object_get_int(node);
+               if (node_value == 0 && errno != 0) {
+                       log_error("Failed to get %s parameter from config file", key);
+                       return -EINVAL;
+               }
+
+               *(int *) value = node_value;
+               break;
        }
 
-       return ret;
+       case json_type_string: {
+               const char *node_value;
+               char *str;
+
+               node_value = json_object_get_string(node);
+               str = strdup(node_value);
+               if (str == NULL) {
+                       log_error("Failed to duplicate string");
+                       return -ENOMEM;
+               }
+
+               *(char **) value = str;
+               break;
+       }
+       }
+
+       return 0;
 }
 
 int parse_service_config(const char *config_path,
@@ -64,11 +87,11 @@ int parse_service_config(const char *config_path,
                return -1;
        }
 
-       ret = get_config_field(root, "RecoveryUnit", &s->recovery_unit);
+       ret = get_config_field(root, "RecoveryUnit", &s->recovery_unit, json_type_string);
        if (ret < 0)
                goto out;
 
-       ret = get_config_field(root, "ServiceType", &s->service_type);
+       ret = get_config_field(root, "ServiceType", &s->service_type, json_type_string);
 
 out:
        json_object_put(root);
index 06fa98cce71571b3da45f375466d3960232fd0db..55c2049599336a5623d3fe7e90096f72aaac6811 100644 (file)
 #ifndef FAULTD_JSON_CONFIG_H
 #define FAULTD_JSON_CONFIG_H
 
+#include <json-c/json.h>
+
 #include "service.h"
 
+int get_config_field(struct json_object *root, const char *key, void *value, int type);
 int parse_service_config(const char *config_path, struct systemd_service *s);
 
 #endif /* FAULTD_JSON_CONFIG_H */