diff --git a/CMakeLists.txt b/CMakeLists.txt index 973aa4061..2685c7b52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ option(ICINGA2_WITH_HELLO "Build the hello module" OFF) option(ICINGA2_WITH_LIVESTATUS "Build the Livestatus module" ON) option(ICINGA2_WITH_NOTIFICATION "Build the notification module" ON) option(ICINGA2_WITH_PERFDATA "Build the perfdata module" ON) +option(ICINGA2_WITH_REDIS "Build the redis module" ON) option(ICINGA2_WITH_STUDIO "Build the Icinga Studio application" OFF) option(ICINGA2_WITH_TESTS "Run unit tests" ON) diff --git a/etc/icinga2/features-available/redis.conf b/etc/icinga2/features-available/redis.conf new file mode 100644 index 000000000..6da008437 --- /dev/null +++ b/etc/icinga2/features-available/redis.conf @@ -0,0 +1,12 @@ +/** + * The redis library implements functionality for putting Icinga + * event data into a redis database. + */ + +library "redis" + +object RedisWriter "redis" { + //host = "127.0.0.1" + //port = 6379 + //password = "xxx" +} diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index b0d702ce3..334d9709d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -62,4 +62,8 @@ if(ICINGA2_WITH_PERFDATA) add_subdirectory(perfdata) endif() +if(ICINGA2_WITH_REDIS) + add_subdirectory(redis) +endif() + set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE) diff --git a/lib/redis/CMakeLists.txt b/lib/redis/CMakeLists.txt new file mode 100644 index 000000000..1d90dd39f --- /dev/null +++ b/lib/redis/CMakeLists.txt @@ -0,0 +1,53 @@ +# Icinga 2 +# Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +mkclass_target(rediswriter.ti rediswriter.tcpp rediswriter.thpp) + +set(redis_SOURCES + rediswriter.cpp rediswriter.thpp +) + +if(ICINGA2_UNITY_BUILD) + mkunity_target(redis redis redis_SOURCES) +endif() + +add_library(redis SHARED ${redis_SOURCES}) + +target_link_libraries(redis ${Boost_LIBRARIES} base config icinga remote hiredis) + +include_directories(${icinga2_SOURCE_DIR}/third-party) +link_directories(${icinga2_BINARY_DIR}/third-party/hiredis) + +set_target_properties ( + redis PROPERTIES + INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR}/icinga2 + DEFINE_SYMBOL I2_REDIS_BUILD + FOLDER Components + VERSION ${SPEC_VERSION} +) + +install_if_not_exists( + ${PROJECT_SOURCE_DIR}/etc/icinga2/features-available/redis.conf + ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available +) + +install( + TARGETS redis + RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/icinga2 +) + diff --git a/lib/redis/rediswriter.cpp b/lib/redis/rediswriter.cpp new file mode 100644 index 000000000..1c0691bb9 --- /dev/null +++ b/lib/redis/rediswriter.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "redis/rediswriter.hpp" +#include "redis/rediswriter.tcpp" +#include "remote/eventqueue.hpp" +#include "base/json.hpp" + +using namespace icinga; + +REGISTER_TYPE(RedisWriter); + +/** + * Starts the component. + */ +void RedisWriter::Start(bool runtimeCreated) +{ + ObjectImpl::Start(runtimeCreated); + + boost::thread thread(boost::bind(&RedisWriter::HandleEvents, this)); + thread.detach(); + + String host = GetHost(); + + m_Context = redisConnect(host.CStr(), GetPort()); + + String password = GetPassword(); + + void *reply = redisCommand(m_Context, "AUTH %s", password.CStr()); + freeReplyObject(reply); +} + +void RedisWriter::HandleEvents(void) +{ + String queueName = Utility::NewUniqueID(); + EventQueue::Ptr queue = new EventQueue(queueName); + EventQueue::Register(queueName, queue); + + std::set types; + types.insert("CheckResult"); + types.insert("StateChange"); + types.insert("Notification"); + types.insert("AcknowledgementSet"); + types.insert("AcknowledgementCleared"); + types.insert("CommentAdded"); + types.insert("CommentRemoved"); + types.insert("DowntimeAdded"); + types.insert("DowntimeRemoved"); + types.insert("DowntimeStarted"); + types.insert("DowntimeTriggered"); + + queue->SetTypes(types); + + queue->AddClient(this); + + for (;;) { + Dictionary::Ptr result = queue->WaitForEvent(this); + + if (!result) + continue; + + String body = JsonEncode(result); + + //TODO: Reconnect handling + try { + void *reply = redisCommand(m_Context, "LPUSH icinga:events %s", body.CStr()); + freeReplyObject(reply); + } catch (const std::exception&) { + queue->RemoveClient(this); + EventQueue::UnregisterIfUnused(queueName, queue); + throw; + } + } +} diff --git a/lib/redis/rediswriter.hpp b/lib/redis/rediswriter.hpp new file mode 100644 index 000000000..9ee9d2b6c --- /dev/null +++ b/lib/redis/rediswriter.hpp @@ -0,0 +1,50 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef REDISWRITER_H +#define REDISWRITER_H + +#include "redis/rediswriter.thpp" +#include "remote/messageorigin.hpp" +#include "base/timer.hpp" +#include + +namespace icinga +{ + +/** + * @ingroup redis + */ +class RedisWriter : public ObjectImpl +{ +public: + DECLARE_OBJECT(RedisWriter); + DECLARE_OBJECTNAME(RedisWriter); + + virtual void Start(bool runtimeCreated) override; + +private: + void HandleEvents(void); + + redisContext *m_Context; +}; + +} + +#endif /* REDISWRITER_H */ diff --git a/lib/redis/rediswriter.ti b/lib/redis/rediswriter.ti new file mode 100644 index 000000000..dc5863b78 --- /dev/null +++ b/lib/redis/rediswriter.ti @@ -0,0 +1,38 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "base/configobject.hpp" + +library demo; + +namespace icinga +{ + +class RedisWriter : ConfigObject +{ + [config] String host { + default {{{ return "127.0.0.1"; }}} + }; + [config] int port { + default {{{ return 6379; }}} + }; + [config] String password; +}; + +} diff --git a/third-party/hiredis/CMakeLists.txt b/third-party/hiredis/CMakeLists.txt index a5317a1f4..afda9579f 100644 --- a/third-party/hiredis/CMakeLists.txt +++ b/third-party/hiredis/CMakeLists.txt @@ -17,6 +17,11 @@ add_library(hiredis SHARED net.c net.h hiredis.c hiredis.h sds.c sds.h async.c async.h read.c read.h) +if(HAVE_VISIBILITY_HIDDEN) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=default") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default") +endif() + set_target_properties ( hiredis PROPERTIES FOLDER Lib