Put modules in shared libraries 50/144950/10
authorPaweł Szewczyk <p.szewczyk@samsung.com>
Fri, 18 Aug 2017 11:25:50 +0000 (13:25 +0200)
committerPaweł Szewczyk <p.szewczyk@samsung.com>
Wed, 30 Aug 2017 12:38:50 +0000 (14:38 +0200)
Change-Id: Iec0a3ce3c61390b3080781ca10e4efd5f485a6c9
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
Makefile.am
configure.ac
packaging/faultd.spec
src/action/action_executor.h
src/core/database.c
src/core/database.h
src/core/module.c
src/core/module.h
src/database/ejdb.c
src/faultd.c

index b5ba3e7f8cddd46041cacd6193e585036644cba3..409144d268bf6e93ba7fda42277845f86ac95975 100644 (file)
@@ -9,6 +9,7 @@ AM_CPPFLAGS = \
        -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 \
@@ -35,11 +36,15 @@ AM_CFLAGS = \
        -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 = \
@@ -86,6 +91,7 @@ faultd_SOURCES = \
     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
@@ -94,7 +100,6 @@ EXTRA_faultd_SOURCES = \
     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 \
@@ -104,8 +109,37 @@ EXTRA_faultd_SOURCES = \
     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)
@@ -115,9 +149,13 @@ faultd_DEPENDENCIES = $(ENABLED_MODULES)
 
 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
 
index 222ef8112950fa32f266f6dae3cb73a31efa808a..295ec7ac6cececb1c17c23a4646876805e486fbe 100644 (file)
@@ -130,6 +130,7 @@ AC_CONFIG_FILES([
         Makefile
 ])
 
+LT_INIT
 AC_OUTPUT
 AC_MSG_RESULT([
         $PACKAGE $VERSION
index 34f7d97e9108fd800cc2f4da9ce6935f42a324ee..18ffe5c15cb8265d689241fdb98e90950eec57bd 100644 (file)
@@ -6,17 +6,23 @@ Source0:    %{name}-%{version}.tar.xz
 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
@@ -30,7 +36,7 @@ cp %{SOURCE1001} .
 
 %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
@@ -41,7 +47,36 @@ 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
@@ -52,6 +87,8 @@ ln -s ../faultd.service %{buildroot}/%{_unitdir}/multi-user.target.wants
 %{_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
index 7f98b9102bbc3069ad1eb2516331a5b9103400f3..383b05848d3a372d423ba795a1a2009ee66d6419 100644 (file)
@@ -52,7 +52,7 @@ static void action_ ##NAME## _cleanup(struct faultd_module *module)           \
 }                                                                                                                                              \
                                                                                                                                                \
 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,                                                              \
index c01222daa2d89baa8ccb11f4968c28e6b7f01ba1..43292fe5083e0574a637ccf9a518813f99d40d5a 100644 (file)
 #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)
index 5082d5b80889af8d89273b3dd8f43d8456cbef1b..940555d4700d62144430003946007d1526106b69 100644 (file)
@@ -49,7 +49,8 @@ struct faultd_database_adapter {
 #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);
index bc21a872783f4afe5708231eb96274d67a8caefc..7638a3c5b6ea59175bf3a38c4cda5056e85e1311 100644 (file)
@@ -16,6 +16,8 @@
  * 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)
 {
@@ -47,6 +55,7 @@ int faultd_module_register(struct faultd_module *module)
        if (!modules[0].next)
                init_heads();
 
+       log_debug("Module registered: %s", module->name);
        list_add_tail(&module->node, modules + module->type);
 
        return 0;
@@ -164,6 +173,78 @@ struct faultd_module *faultd_get_module_by_name(const char *name)
        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;
index 72060988e894a6e5fdd4f10413ee3111a659e00c..164fa7ef15a29e151db0b1ce80e6e78014817670 100644 (file)
@@ -74,6 +74,9 @@ void faultd_modules_cleanup(void);
 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
index ab29c71dcf977bc07cb5037644496f733b87c42b..c11cd99bd8e4b1198bcacadc6f253a7ee5905e62 100644 (file)
@@ -58,8 +58,13 @@ static int init_ejdb_adapter(struct faultd_module *module,
 {
        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) {
index b664f60d6e66c45f4de928fa4b480ae6afc70d17..dcb9900e0968b0006ad482c68bae3330092fcfc3 100644 (file)
@@ -31,6 +31,7 @@
 #include "module.h"
 #include "systemd_dbus.h"
 #include "faultd-config.h"
+#include "common.h"
 
 static int terminate = 0;
 static struct faultd_config config;
@@ -155,6 +156,12 @@ int main(int ac, char *av[])
        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));
@@ -180,7 +187,6 @@ int main(int ac, char *av[])
        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);
@@ -193,6 +199,7 @@ int main(int ac, char *av[])
 
        faultd_modules_cleanup();
        faultd_config_cleanup(&config);
+       faultd_modules_unload();
 
        sd_bus_close(bus);
        return 0;