From 1c5c56d0bc97249ae1e88539ea563a7e8c00c45e Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Thu, 4 Dec 2014 20:55:00 +0100 Subject: [PATCH] facter plugin: Added a plugin collecting local facter values. The plugin uses libfacter from the cfacter project. libfacter is a C++ library, so the plugin is implemented in C++ as well using a small shim to talk to SysDB. --- configure.ac | 48 +++++++++++++++ src/Makefile.am | 8 +++ src/plugins/backend/facter.cc | 112 ++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 src/plugins/backend/facter.cc diff --git a/configure.ac b/configure.ac index 10c18c9..088a4b5 100644 --- a/configure.ac +++ b/configure.ac @@ -132,6 +132,16 @@ if test "x$enable_standards" = "xyes"; then done fi +dnl We need C++11 for facter. +AC_MSG_CHECKING([whether $CXX accepts -std=c++11]) +if test_cxx_flags -std=c++11; then + CXXFLAGS="$CXXFLAGS -std=c++11" + AC_MSG_RESULT([yes]) +else + # Oh well, the header check will determine if it works anyway. + AC_MSG_RESULT([no]) +fi + dnl Hardening (see e.g. http://wiki.debian.org/Hardening for a motivation). AC_DEFINE([_FORTIFY_SOURCE], 2, [Define to enable protection against static sized buffer overflows.]) @@ -454,6 +464,37 @@ AC_SUBST([READLINE_LIBS]) AC_SUBST([READLINE_CFLAGS]) AM_CONDITIONAL([BUILD_CLIENT], test "x$readline_support" != "no") +AC_LANG_PUSH(C++) +AC_ARG_WITH([libfacter], + [AS_HELP_STRING([--with-libfacter], [libfacter support (default: auto)])], + [with_libfacter="$withval"], + [with_libfacter="yes"]) +if test "x$with_libfacter" = "xyes" || test "x$with_libfacter" = "xauto"; then + AC_CHECK_HEADERS([facter/facts/collection.hpp], + [have_libfacter="yes"], + [have_libfacter="no (facter/facts/collection.hpp not found)"]) +else if test "x$with_libfacter" = "xno"; then + have_libfacter="$with_libfacter (disabled on command-line)" +else + AC_MSG_ERROR([Invalid value for option --with-libfacter=$with_libfacter (expected "yes", "no", or "auto")]) +fi; fi +if test "x$have_libfacter" = "xyes"; then + AC_MSG_CHECKING([for facter::facts::collection in -lfacter]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[[ #include ]]], + [[[ + facter::facts::collection facts; + facts.add_default_facts(); + ]]] + )], + [TEST_LIBS=$TEST_LIBS -lfacter], + [have_libfacter="yes"], + [have_libfacter="no (libfacter not found)"]) + AC_MSG_RESULT([$have_libfacter]) +fi +AC_LANG_POP(C++) + AC_ARG_WITH([librrd], [AS_HELP_STRING([--with-librrd], [librrd support (default: auto)])], [with_librrd="$withval"], @@ -500,6 +541,10 @@ fi AM_CONDITIONAL([INTEGRATION_TESTING], test "x$integration_tests" = "xyes") dnl Plugin checks. +facter_default=$have_libfacter +if test "x$facter_default" != "xyes"; then + facter_default="no (requires libfacter)" +fi puppet_storeconfigs_default=$with_libdbi if test "x$puppet_storeconfigs_default" != "xyes"; then puppet_storeconfigs_default="no (requires libdbi)" @@ -515,6 +560,8 @@ Backends:]) AC_SDB_PLUGIN_INIT AC_SDB_PLUGIN([collectd-unixsock], [yes], [backend accessing the system statistics collection daemon]) +AC_SDB_PLUGIN([facter], [$facter_default], + [backend retrieving local facter facts]) AC_SDB_PLUGIN([mk-livestatus], [yes], [backend accessing Nagios/Icinga/Shinken using MK Livestatus]) AC_SDB_PLUGIN([puppet-storeconfigs], [$puppet_storeconfigs_default], @@ -573,6 +620,7 @@ AC_MSG_RESULT([ librrd: . . . . . . . . . . $have_librrd]) AC_MSG_RESULT() AC_MSG_RESULT([ Backends:]) AC_MSG_RESULT([ collectd::unixsock: . . . . $enable_collectd_unixsock]) +AC_MSG_RESULT([ facter . . . . . . . . . . $enable_facter]) AC_MSG_RESULT([ mk-livestatus: . . . . . . $enable_mk_livestatus]) AC_MSG_RESULT([ puppet::storeconfigs: . . . $enable_puppet_storeconfigs]) AC_MSG_RESULT() diff --git a/src/Makefile.am b/src/Makefile.am index 1583217..3472b6f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -171,6 +171,14 @@ sysdbd_LDADD += -dlopen plugins/backend/collectd/unixsock.la sysdbd_DEPENDENCIES += plugins/backend/collectd/unixsock.la endif +if BUILD_PLUGIN_FACTER +pkgbackendlib_LTLIBRARIES += plugins/backend/facter.la +plugins_backend_facter_la_SOURCES = plugins/backend/facter.cc +plugins_backend_facter_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version -lfacter +sysdbd_LDADD += -dlopen plugins/backend/facter.la +sysdbd_DEPENDENCIES += plugins/backend/facter.la +endif + if BUILD_PLUGIN_MKLIVESTATUS pkgbackendlib_LTLIBRARIES += plugins/backend/mk-livestatus.la plugins_backend_mk_livestatus_la_SOURCES = plugins/backend/mk-livestatus.c diff --git a/src/plugins/backend/facter.cc b/src/plugins/backend/facter.cc new file mode 100644 index 0000000..98f7f57 --- /dev/null +++ b/src/plugins/backend/facter.cc @@ -0,0 +1,112 @@ +/* + * SysDB - src/plugins/backend/facter.cc + * Copyright (C) 2014 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "sysdb.h" +#include "core/plugin.h" +#include "core/store.h" +#include "utils/error.h" + +#include +#include +#include + +static const char *hostname; +static sdb_time_t now; + +static bool +fact_iter(std::string const &k, facter::facts::value const *v) +{ + /* Don't ignore hidden values for now; they also provide the old, + * non-structured facts. */ + + std::stringstream ss; + v->write(ss, false); + std::string s = ss.str(); + char *str = const_cast(s.c_str()); + + /* Ignore non-structured facts for now. */ + if (str[0] == '{') + return true; + + sdb_data_t value = { SDB_TYPE_STRING, { .string = str } }; + sdb_store_attribute(hostname, k.c_str(), &value, now); + return true; +} /* fact_iter */ + +/* SysDB interface */ +extern "C" { + + SDB_PLUGIN_MAGIC; + + static int + facter_collect(sdb_object_t __attribute__((unused)) *user_data) + { + facter::facts::collection facts; + + /* XXX: this may execute other programs; can we be sure that works + * reasonably well in a multi-threaded program? */ + facts.add_default_facts(); + facts.add_external_facts(); + + now = sdb_gettime(); + facter::facts::value const *v = facts["fqdn"]; + std::stringstream ss; + v->write(ss, false); + std::string s = ss.str(); + hostname = s.c_str(); + + sdb_store_host(hostname, now); + facts.each(fact_iter); + sdb_log(SDB_LOG_DEBUG, "facter backend: Processed %zu facts " + "for host '%s'", facts.size(), hostname); + return 0; + } /* main */ + + int + sdb_module_init(sdb_plugin_info_t *info) + { + sdb_plugin_set_info(info, SDB_PLUGIN_INFO_DESC, + "backend retrieving local facter facts"); + sdb_plugin_set_info(info, SDB_PLUGIN_INFO_COPYRIGHT, + "Copyright (C) 2014 Sebastian 'tokkee' Harl "); + sdb_plugin_set_info(info, SDB_PLUGIN_INFO_LICENSE, "BSD"); + sdb_plugin_set_info(info, SDB_PLUGIN_INFO_VERSION, SDB_VERSION); + sdb_plugin_set_info(info, SDB_PLUGIN_INFO_PLUGIN_VERSION, SDB_VERSION); + + sdb_plugin_register_collector("main", facter_collect, + /* interval */ NULL, /* user_data */ NULL); + return 0; + } /* sdb_module_init */ + +} /* extern C */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + -- 2.30.2