-DDBDIR=\""$(dbdir)"\" \
-DFAULTD_SERVICES_CONFIG_PATH=\""${sysconfdir}/faultd/conf.d/"\" \
-DFAULTD_DEFAULT_CONFIG_FILE=\""${sysconfdir}/faultd/faultd.conf"\" \
+ -DFAULTD_MODULES_PATH=\""${sysconfdir}/faultd/enabled-modules"\" \
-I${top_srcdir}/src \
-I${top_srcdir}/src/core \
-I${top_srcdir}/src/decision_makers \
-Wtype-limits \
-D_GNU_SOURCE=1 \
-fPIE \
+ -rdynamic \
-D"FAULTD_MODNAME_T=$(call name_fix,$(modname))"
AM_LDFLAGS = \
-Wl,--gc-sections \
-Wl,--as-needed \
+ -avoid-version \
+ -module \
+ -shared \
-pie
SED_PROCESS = \
src/util/common.c \
src/util/log.c \
src/util/notify_queue.c \
+ src/database/database_nop.c \
src/util/systemd_dbus.c
# Add here source files of modules that must have ability to enable/disable during build
src/listeners/audit.c \
src/listeners/systemd.c \
src/listeners/startup.c \
- src/database/database_nop.c \
src/database/ejdb.c \
src/decision_makers/vip_fault_dm.c \
src/decision_makers/rv_dm.c \
src/action/system_reboot_to_recovery.c \
src/action/service_recover.c
-faultd_LDADD = $(ENABLED_MODULES) $(LIBSYSTEMD_LIBS) $(AUDIT_LIBS) $(LIBEJDB_LIBS) $(JSON_C_LIBS)
-faultd_DEPENDENCIES = $(ENABLED_MODULES)
+faultd_CFLAGS = $(AM_CFLAGS)
+faultd_LDFLAGS = -ldl
+
+modulesdir = $(pkglibdir)/available-modules
+modules_LTLIBRARIES = audit_listener.la \
+ systemd_listener.la \
+ startup_listener.la \
+ ejdb_dbadapter.la \
+ vip_fault_eh.la \
+ resource_violation_eh.la \
+ standard_fault_eh.la \
+ service_restart_action.la \
+ system_reboot_action.la \
+ system_reboot_to_recovery_action.la \
+ service_recover_action.la
+
+audit_listener_la_SOURCES = src/listeners/audit.c
+audit_listener_la_LIBADD = $(AUDIT_LIBS)
+systemd_listener_la_SOURCES = src/listeners/systemd.c
+startup_listener_la_SOURCES = src/listeners/startup.c
+ejdb_dbadapter_la_SOURCES = src/database/ejdb.c
+ejdb_dbadapter_la_LIBADD = $(LIBEJDB_LIBS)
+vip_fault_eh_la_SOURCES = src/decision_makers/vip_fault_dm.c
+resource_violation_eh_la_SOURCES = src/decision_makers/rv_dm.c
+standard_fault_eh_la_SOURCES = src/decision_makers/standard_fault_dm.c
+service_restart_action_la_SOURCES = src/action/service_restart.c
+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
+
+faultd_LDADD = $(LIBSYSTEMD_LIBS) $(JSON_C_LIBS)
%.pc: %.pc.in Makefile
$(SED_PROCESS)
install-data-local:
$(MKDIR_P) $(DESTDIR)$(dbdir)
+ $(MKDIR_P) $(DESTDIR)$(pkglibdir)/available-modules
+ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/faultd/available-modules
+ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/faultd/enabled-modules
$(MKDIR_P) $(DESTDIR)$(unitdir)/display-manager.service.d
$(INSTALL) systemd-service.d/display-manager.service.conf $(DESTDIR)/$(unitdir)/display-manager.service.d/faultd.conf
+
if BUILD_TEST_PROGRAMS
bin_PROGRAMS = leaker
Makefile
])
+LT_INIT
AC_OUTPUT
AC_MSG_RESULT([
$PACKAGE $VERSION
Source1001: %{name}.manifest
Summary: Fault detection daemon
Group: System/Monitoring
-BuildRequires: pkgconfig(audit)
-BuildRequires: pkgconfig(libejdb)
BuildRequires: pkgconfig(libsystemd)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cmocka)
-
+BuildRequires: pkgconfig(libejdb)
%description
faultd monitors system services, detects their abnormal execution and
helps recover from errors.
+%package extra
+Summary: faultd extra modules
+Group: System/Monitoring
+BuildRequires: pkgconfig(audit)
+
+%description extra
+Set of modules allowing to extend faultd functionality
+
%package test-programs
Summary: faultd test program
Group: System/Monitoring
%build
%autogen
-%configure --enable-test-programs --enable-tests --enable-modules=systemd,startup,vip_fault_dm,system_reboot,database_nop
+%configure --enable-test-programs --enable-tests
make %{?_smp_mflags}
make check
mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants
ln -s ../faultd.service %{buildroot}/%{_unitdir}/multi-user.target.wants
-%files
+%define moduledir %{_libdir}/faultd/available-modules/
+%define moduleconfdir %{_sysconfdir}/faultd/available-modules/
+%define enabled_moduledir %{_sysconfdir}/faultd/enabled-modules/
+
+for mod in systemd_listener \
+ vip_fault_eh \
+ system_reboot_action
+do
+ ln -s %{moduledir}/${mod}.so %{buildroot}/%{moduleconfdir}/${mod}.so;
+ ln -s ../available-modules/${mod}.so %{buildroot}/%{enabled_moduledir}/${mod}.so;
+ echo %{moduledir}/${mod}.so >> faultd-files;
+ echo %{moduleconfdir}/${mod}.so >> faultd-files;
+ echo %{enabled_moduledir}/${mod}.so >> faultd-files;
+done
+
+for mod in audit_listener \
+ ejdb_dbadapter \
+ resource_violation_eh \
+ service_recover_action \
+ service_restart_action \
+ standard_fault_eh \
+ startup_listener \
+ system_reboot_to_recovery_action
+do
+ ln -s %{moduledir}/${mod}.so %{buildroot}/%{moduleconfdir}/${mod}.so;
+ echo %{moduledir}/${mod}.so >> faultd-extra-files;
+ echo %{moduleconfdir}/${mod}.so >> faultd-extra-files;
+done
+
+%files -f faultd-files
%license COPYING
%manifest %{name}.manifest
%{_localstatedir}/db/faultd
%{_unitdir}/multi-user.target.wants/faultd.service
%{_unitdir}/display-manager.service.d/faultd.conf
+%files extra -f faultd-extra-files
+
%files test-programs
%{_bindir}/leaker
%{_unitdir}/faultd-leaker.service
} \
\
static struct faultd_module action_ ##NAME## _module = { \
- .name = "action_" #NAME "_module", \
+ .name = #NAME, \
.type = FAULTD_MODULE_TYPE_ACTION, \
.init = action_ ##NAME## _init, \
.cleanup = action_ ##NAME## _cleanup, \
#include "log.h"
#include "module.h"
+#define DEFAULT_DBADAPTER "nop_dbadapter"
+
static struct faultd_database_adapter *database_adapter = NULL;
-void faultd_set_database_adapter(struct faultd_database_adapter *adapter)
+struct faultd_database_adapter *faultd_get_database_adapter(void)
{
+ return database_adapter;
+}
+
+int faultd_set_database_adapter(struct faultd_database_adapter *adapter)
+{
+ if (database_adapter && adapter
+ && strcmp(DEFAULT_DBADAPTER, database_adapter->module.name) != 0)
+ return -EINVAL;
+
database_adapter = adapter;
+ return 0;
}
int database_store(struct faultd_object *obj, faultd_oid_t *oid)
#define to_database_adapter(MOD) \
container_of(MOD, struct faultd_database_adapter, module)
-void faultd_set_database_adapter(struct faultd_database_adapter *adapter);
+struct faultd_database_adapter *faultd_get_database_adapter(void);
+int faultd_set_database_adapter(struct faultd_database_adapter *adapter);
int database_store(struct faultd_object *obj, faultd_oid_t *oid);
int database_get_by_oid(faultd_oid_t *oid, struct faultd_object *result);
int database_load(struct faultd_object *query, struct faultd_object *result, uint32_t *nr);
* limitations under the License.
*/
+#include <dirent.h>
+#include <dlfcn.h>
#include <errno.h>
#include <string.h>
#include "log.h"
#include "module.h"
+struct dl_module {
+ void *handle;
+ struct list_head node;
+};
+
static struct list_head modules[FAULTD_MODULE_TYPE_MAX];
static int category_disabled[FAULTD_MODULE_TYPE_MAX];
+static struct list_head dl_modules;
static void init_heads(void)
{
if (!modules[0].next)
init_heads();
+ log_debug("Module registered: %s", module->name);
list_add_tail(&module->node, modules + module->type);
return 0;
return NULL;
}
+static int module_file_filter(const struct dirent *d)
+{
+ if (d->d_name[0] == '.')
+ return 0;
+
+ return 1;
+}
+
+int faultd_modules_load()
+{
+ int ret, num;
+ struct dirent **namelist;
+ char *filename;
+ struct dl_module *mod;
+
+ num = scandir(FAULTD_MODULES_PATH, &namelist, module_file_filter, alphasort);
+ if (num < 0)
+ return num;
+
+ INIT_LIST_HEAD(&dl_modules);
+ log_debug("found %d modules to load", num);
+ while (num--) {
+ ret = asprintf(&filename, FAULTD_MODULES_PATH "/%s", namelist[num]->d_name);
+ free(namelist[num]);
+ if (ret < 0) {
+ log_error("Could not create library filename");
+ goto out;
+ }
+
+ log_debug("Opening %s library", filename);
+ mod = malloc(sizeof(*mod));
+ if (!mod) {
+ log_error("Failed to allocate data");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ mod->handle = dlopen(filename, RTLD_NOW);
+ if (!mod->handle) {
+ log_error("Could not load module: %s", dlerror());
+ ret = -ENOENT;
+ free(mod);
+ goto out;
+ }
+
+ list_add_tail(&mod->node, &dl_modules);
+ free(filename);
+ filename = NULL;
+ }
+
+ ret = 0;
+out:
+ free(filename);
+ while (num-- > 0) {
+ free(namelist[num]);
+ }
+
+ free(namelist);
+ return ret;
+}
+
+void faultd_modules_unload()
+{
+ struct dl_module *child, *next;
+
+ list_for_each_entry_safe(child, next, &dl_modules, node) {
+ list_del_init(&child->node);
+ dlclose(child->handle);
+ free(child);
+ }
+}
+
void faultd_disable_module_category(int category)
{
category_disabled[category] = 1;
struct faultd_module *faultd_get_module_by_name(const char *name);
void faultd_disable_module_category(int category);
+int faultd_modules_load(void);
+void faultd_modules_unload(void);
+
#ifndef __CONSTRUCTOR__
#define __CONSTRUCTOR__ __attribute__((constructor))
#endif
{
struct faultd_database_adapter *_da = to_database_adapter(module);
struct ejdb_adapter *da = to_ejdb_adapter(_da);
+ int ret;
- faultd_set_database_adapter(_da);
+ ret = faultd_set_database_adapter(_da);
+ if (ret < 0) {
+ log_error("Database adapter was already set. Please, enable only one database module");
+ return -1;
+ }
da->db = ejdbnew();
if (da->db == NULL) {
#include "module.h"
#include "systemd_dbus.h"
#include "faultd-config.h"
+#include "common.h"
static int terminate = 0;
static struct faultd_config config;
sd_event *loop;
sigset_t ss;
+ rc = faultd_modules_load();
+ if (rc < 0) {
+ log_error("Failed to load modules");
+ return -1;
+ }
+
rc = parse_argv(ac, av);
if (rc < 0) {
fprintf(stderr, "Failed to parse command line options: %s\n", strerror(-rc));
rc = sigprocmask(SIG_BLOCK, &ss, NULL);
rc = sd_event_add_signal(loop, NULL, SIGINT, sigint_handler, loop);
-
rc = faultd_modules_init(loop, &config);
if (rc < 0) {
log_error("Failed to initialize modules %d.", rc);
faultd_modules_cleanup();
faultd_config_cleanup(&config);
+ faultd_modules_unload();
sd_bus_close(bus);
return 0;