]> granicus.if.org Git - icinga2/commitdiff
Implement heartbeat messages for the cluster
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 9 Dec 2014 12:17:27 +0000 (13:17 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 9 Dec 2014 12:17:27 +0000 (13:17 +0100)
fixes #7745

lib/remote/CMakeLists.txt
lib/remote/apiclient-heartbeat.cpp [new file with mode: 0644]
lib/remote/apiclient.cpp
lib/remote/apiclient.hpp

index b30b8dbfa26eb87b77fae56d1c968b1f48ea9d3e..5ed90a0ec3b4b46acdcb2a4de15b589d7f4e6f57 100644 (file)
@@ -22,7 +22,7 @@ mkclass_target(zone.ti zone.thpp)
 mkembedconfig_target(remote-type.conf remote-type.cpp)
 
 set(remote_SOURCES
-  apiclient.cpp apifunction.cpp apilistener.cpp apilistener-sync.cpp
+  apiclient.cpp apiclient-heartbeat.cpp apifunction.cpp apilistener.cpp apilistener-sync.cpp
   apilistener.thpp authority.cpp endpoint.cpp endpoint.thpp jsonrpc.cpp
   messageorigin.cpp remote-type.cpp zone.cpp zone.thpp
 )
diff --git a/lib/remote/apiclient-heartbeat.cpp b/lib/remote/apiclient-heartbeat.cpp
new file mode 100644 (file)
index 0000000..28fc850
--- /dev/null
@@ -0,0 +1,73 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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 "remote/apiclient.hpp"
+#include "remote/messageorigin.hpp"
+#include "remote/apifunction.hpp"
+#include "base/initialize.hpp"
+#include "base/dynamictype.hpp"
+#include <boost/foreach.hpp>
+
+using namespace icinga;
+
+REGISTER_APIFUNCTION(Heartbeat, event, &ApiClient::HeartbeatAPIHandler);
+
+static Timer::Ptr l_HeartbeatTimer;
+
+static void StartHeartbeatTimer(void)
+{
+       l_HeartbeatTimer = new Timer();
+       l_HeartbeatTimer->OnTimerExpired.connect(boost::bind(&ApiClient::HeartbeatTimerHandler));
+       l_HeartbeatTimer->SetInterval(10);
+       l_HeartbeatTimer->Start();
+}
+
+INITIALIZE_ONCE(StartHeartbeatTimer);
+
+void ApiClient::HeartbeatTimerHandler(void)
+{
+       BOOST_FOREACH(const Endpoint::Ptr& endpoint, DynamicType::GetObjectsByType<Endpoint>()) {
+               BOOST_FOREACH(const ApiClient::Ptr& client, endpoint->GetClients()) {
+                       if (client->m_NextHeartbeat != 0 && client->m_NextHeartbeat < Utility::GetTime()) {
+                               client->Disconnect();
+                               continue;
+                       }
+
+                       Dictionary::Ptr request = new Dictionary();
+                       request->Set("jsonrpc", "2.0");
+                       request->Set("method", "event::Heartbeat");
+
+                       Dictionary::Ptr params = new Dictionary();
+                       params->Set("timeout", 30);
+
+                       request->Set("params", params);
+
+                       client->SendMessage(request);
+               }
+       }
+}
+
+Value ApiClient::HeartbeatAPIHandler(const MessageOrigin& origin, const Dictionary::Ptr& params)
+{
+       Value vtimeout = params->Get("timeout");
+
+       if (!vtimeout.IsEmpty())
+               origin.FromClient->m_NextHeartbeat = Utility::GetTime() + vtimeout;
+}
+
index 9f54076fd9c488c4a654fef01e5e0dffe663e2c1..1cead87c3bb46fb6223df1b16f5afe660694110b 100644 (file)
@@ -35,7 +35,8 @@ static Value RequestCertificateHandler(const MessageOrigin& origin, const Dictio
 REGISTER_APIFUNCTION(RequestCertificate, pki, &RequestCertificateHandler);
 
 ApiClient::ApiClient(const String& identity, bool authenticated, const TlsStream::Ptr& stream, ConnectionRole role)
-       : m_Identity(identity), m_Authenticated(authenticated), m_Stream(stream), m_Role(role), m_Seen(Utility::GetTime())
+       : m_Identity(identity), m_Authenticated(authenticated), m_Stream(stream), m_Role(role), m_Seen(Utility::GetTime()),
+         m_NextHeartbeat(0)
 {
        if (authenticated)
                m_Endpoint = Endpoint::GetByName(identity);
index 9c05a4f1ea323fa1baa4bd2b86077c9d134b54d4..5c7bb06003f04cf34dea42030ca140f90831b980 100644 (file)
@@ -35,6 +35,8 @@ enum ClientRole
        ClientOutbound
 };
 
+class MessageOrigin;
+
 /**
  * An API client connection.
  *
@@ -60,6 +62,9 @@ public:
 
        void SendMessage(const Dictionary::Ptr& request);
 
+       static void HeartbeatTimerHandler(void);
+       static Value HeartbeatAPIHandler(const MessageOrigin& origin, const Dictionary::Ptr& params);
+
 private:
        String m_Identity;
        bool m_Authenticated;
@@ -67,6 +72,7 @@ private:
        TlsStream::Ptr m_Stream;
        ConnectionRole m_Role;
        double m_Seen;
+       double m_NextHeartbeat;
 
        WorkQueue m_WriteQueue;