nodist_unit_DATA = \
faultd.service
+config_DATA = \
+ faultd.conf
+
serviceconfig_DATA = \
conf.d/dbus.service.conf \
conf.d/display-manager.service.conf
--- /dev/null
+{
+ "standard_reboot_eh" : {
+ "n_reboots_before_recovery" : 3
+ },
+ "standard_fault_eh" : {
+ "n_fails_before_reboot" : 3
+ }
+}
%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
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);
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); \
} \
\
#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)
{
{
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 = {
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,
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)
#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)
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,
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);
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)
#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,
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);
#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 */