From 18de1f7e1102fcf76c08c9aa87f83c0faba213f8 Mon Sep 17 00:00:00 2001 From: Michael Insel Date: Thu, 29 Nov 2018 22:03:26 +0100 Subject: [PATCH 01/62] Fix state conditions in check_memory and check_swap This fixes the state conditions in check_memory and check_swap. This turns the if/else if/else statements in simple if statements, since they won't work properly when both thresholds are broken. This also implements a new function to get a given state as wstring. --- plugins/check_memory.cpp | 15 ++++++--------- plugins/check_swap.cpp | 13 +++++-------- plugins/thresholds.cpp | 9 +++++++++ plugins/thresholds.hpp | 2 ++ 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/plugins/check_memory.cpp b/plugins/check_memory.cpp index e8cb8aae9..4b71517a4 100644 --- a/plugins/check_memory.cpp +++ b/plugins/check_memory.cpp @@ -164,7 +164,7 @@ static int printOutput(printInfoStruct& printInfo) if (l_Debug) std::wcout << L"Constructing output string" << '\n'; - state state; + state state = OK; std::wcout << L"MEMORY "; @@ -175,16 +175,13 @@ static int printOutput(printInfoStruct& printInfo) else currentValue = printInfo.tRam - printInfo.aRam; - if (printInfo.warn.rend(currentValue, printInfo.tRam)) { + if (printInfo.warn.rend(currentValue, printInfo.tRam)) state = WARNING; - std::wcout << L"WARNING"; - } else if (printInfo.crit.rend(currentValue, printInfo.tRam)) { + + if (printInfo.crit.rend(currentValue, printInfo.tRam)) state = CRITICAL; - std::wcout << L"CRITICAL"; - } else { - state = OK; - std::wcout << L"OK"; - } + + std::wcout << stateToString(state); if (!printInfo.showUsed) std::wcout << " - " << printInfo.percentFree << L"% free"; diff --git a/plugins/check_swap.cpp b/plugins/check_swap.cpp index 7f6db013a..906a1017d 100644 --- a/plugins/check_swap.cpp +++ b/plugins/check_swap.cpp @@ -194,16 +194,13 @@ static int printOutput(printInfoStruct& printInfo) else currentValue = printInfo.tSwap - printInfo.aSwap; - if (printInfo.warn.rend(currentValue, printInfo.tSwap)) { + if (printInfo.warn.rend(currentValue, printInfo.tSwap)) state = WARNING; - std::wcout << L"WARNING - "; - } else if (printInfo.crit.rend(currentValue, printInfo.tSwap)) { + + if (printInfo.crit.rend(currentValue, printInfo.tSwap)) state = CRITICAL; - std::wcout << L"CRITICAL - "; - } else { - state = OK; - std::wcout << L"OK - "; - } + + std::wcout << stateToString(state) << " "; if (!printInfo.showUsed) std::wcout << printInfo.percentFree << L"% free "; diff --git a/plugins/thresholds.cpp b/plugins/thresholds.cpp index f32e6d360..acc2bcafb 100644 --- a/plugins/thresholds.cpp +++ b/plugins/thresholds.cpp @@ -281,4 +281,13 @@ std::wstring formatErrorInfo(unsigned long err) { } return out.str(); +} + +std::wstring stateToString(const state& state) { + switch (state) { + case OK: return L"OK"; + case WARNING: return L"WARNING"; + case CRITICAL: return L"CRITICAL"; + default: return L"UNKNOWN"; + } } \ No newline at end of file diff --git a/plugins/thresholds.hpp b/plugins/thresholds.hpp index 8348306f2..e7d77f745 100644 --- a/plugins/thresholds.hpp +++ b/plugins/thresholds.hpp @@ -76,4 +76,6 @@ std::wstring TunitStr(const Tunit&); void printErrorInfo(unsigned long err = 0); std::wstring formatErrorInfo(unsigned long err); +std::wstring stateToString(const state&); + #endif /* THRESHOLDS_H */ From 080f666b55a7570de68ccd6659f12766d5efe179 Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Mon, 3 Dec 2018 14:27:37 +0100 Subject: [PATCH 02/62] Restore 'Connection: close' behaviour in HTTP responses Actually the `corked` functionality caused problems with not closing connections properly. Full Analysis: https://github.com/Icinga/icinga2/issues/6799#issuecomment-443710338 Full credits to @swegener :) fixes #6799 --- lib/remote/httpresponse.cpp | 3 +++ lib/remote/httpserverconnection.cpp | 7 ------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/remote/httpresponse.cpp b/lib/remote/httpresponse.cpp index fe67052c9..ef0df7e81 100644 --- a/lib/remote/httpresponse.cpp +++ b/lib/remote/httpresponse.cpp @@ -111,6 +111,9 @@ void HttpResponse::Finish() } m_State = HttpResponseEnd; + + if (m_Request->ProtocolVersion == HttpVersion10 || m_Request->Headers->Get("connection") == "close") + m_Stream->Shutdown(); } bool HttpResponse::Parse(StreamReadContext& src, bool may_wait) diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp index 4f619d2f1..cd3e542f2 100644 --- a/lib/remote/httpserverconnection.cpp +++ b/lib/remote/httpserverconnection.cpp @@ -362,13 +362,6 @@ void HttpServerConnection::DataAvailableHandler() close = true; } - - /* Request finished, decide whether to explicitly close the connection. */ - if (m_CurrentRequest.ProtocolVersion == HttpVersion10 || - m_CurrentRequest.Headers->Get("connection") == "close") { - m_Stream->Shutdown(); - close = true; - } } else close = true; From 1c8fba182c575f44ad277fd7d777441faf812b42 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 3 Dec 2018 14:40:50 +0100 Subject: [PATCH 03/62] Add a code comment for connection: close handling --- lib/remote/httpresponse.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/remote/httpresponse.cpp b/lib/remote/httpresponse.cpp index ef0df7e81..de029b701 100644 --- a/lib/remote/httpresponse.cpp +++ b/lib/remote/httpresponse.cpp @@ -112,6 +112,12 @@ void HttpResponse::Finish() m_State = HttpResponseEnd; + /* Close the connection on + * a) HTTP/1.0 + * b) Connection: close in the sent header. + * + * Do this here and not in DataAvailableHandler - there might still be incoming data in there. + */ if (m_Request->ProtocolVersion == HttpVersion10 || m_Request->Headers->Get("connection") == "close") m_Stream->Shutdown(); } From 797ecd1539c91d3dd02dc7d164ce602c52a6f802 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Mon, 3 Dec 2018 16:38:52 +0100 Subject: [PATCH 04/62] ThreadPool#Stop(): discard non-processed queue items --- lib/base/threadpool.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/base/threadpool.cpp b/lib/base/threadpool.cpp index 1dad249bc..b6b01ea78 100644 --- a/lib/base/threadpool.cpp +++ b/lib/base/threadpool.cpp @@ -73,6 +73,7 @@ void ThreadPool::Stop() for (auto& queue : m_Queues) { boost::mutex::scoped_lock lock(queue.Mutex); queue.Stopped = true; + queue.Items.clear(); queue.CV.notify_all(); } From 1d6cec5a99abffc3c7e51084cd3401781666111b Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Mon, 3 Dec 2018 19:05:41 +0100 Subject: [PATCH 05/62] HttpServerConnection#DataAvailableHandler(): be aware of being called multiple times concurrently refs #6816 --- lib/remote/httpserverconnection.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp index cd3e542f2..c0550bfae 100644 --- a/lib/remote/httpserverconnection.cpp +++ b/lib/remote/httpserverconnection.cpp @@ -351,7 +351,11 @@ void HttpServerConnection::DataAvailableHandler() bool close = false; if (!m_Stream->IsEof()) { - boost::recursive_mutex::scoped_lock lock(m_DataHandlerMutex); + boost::recursive_mutex::scoped_try_lock lock(m_DataHandlerMutex); + if (!lock.owns_lock()) { + Log(LogInformation, "HttpServerConnection", "Unable to process available data, they're already being processed in another thread"); + return; + } try { while (ProcessMessage()) From 78e470996d4b541acdfa248e4d950a87f4dca598 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 4 Dec 2018 15:20:37 +0100 Subject: [PATCH 06/62] Only create downtimes from non-paused ScheduledDowntime objects in HA enabled cluster zones --- lib/icinga/scheduleddowntime.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index 6436487b4..978115e61 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -95,13 +95,14 @@ void ScheduledDowntime::Start(bool runtimeCreated) l_Timer->Start(); }); - Utility::QueueAsyncCallback(std::bind(&ScheduledDowntime::CreateNextDowntime, this)); + if (!IsPaused()) + Utility::QueueAsyncCallback(std::bind(&ScheduledDowntime::CreateNextDowntime, this)); } void ScheduledDowntime::TimerProc() { for (const ScheduledDowntime::Ptr& sd : ConfigType::GetObjectsByType()) { - if (sd->IsActive()) + if (sd->IsActive() && !sd->IsPaused()) sd->CreateNextDowntime(); } } @@ -167,6 +168,13 @@ std::pair ScheduledDowntime::FindNextSegment() void ScheduledDowntime::CreateNextDowntime() { + /* HA enabled zones. */ + if (IsActive() && IsPaused()) { + Log(LogNotice, "Checkable") + << "Skipping downtime creation for HA-paused Scheduled Downtime object '" << GetName() << "'"; + return; + } + for (const Downtime::Ptr& downtime : GetCheckable()->GetDowntimes()) { if (downtime->GetScheduledBy() != GetName() || downtime->GetStartTime() < Utility::GetTime()) @@ -261,4 +269,4 @@ void ScheduledDowntime::ValidateChildOptions(const Lazy& lvalue, const Va } catch (const std::exception&) { BOOST_THROW_EXCEPTION(ValidationError(this, { "child_options" }, "Invalid child_options specified")); } -} \ No newline at end of file +} From 0b03a3d8f8c2bbf6d10fc709089fa1a397fc3a79 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 24 Jul 2018 14:24:56 +0200 Subject: [PATCH 07/62] SocketEvents: inherit from Stream refs #6477 --- lib/base/socketevents.hpp | 5 ++++- lib/base/tlsstream.hpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/base/socketevents.hpp b/lib/base/socketevents.hpp index 486ec4df1..26dc77019 100644 --- a/lib/base/socketevents.hpp +++ b/lib/base/socketevents.hpp @@ -22,6 +22,7 @@ #include "base/i2-base.hpp" #include "base/socket.hpp" +#include "base/stream.hpp" #include #include @@ -37,9 +38,11 @@ namespace icinga * * @ingroup base */ -class SocketEvents +class SocketEvents : public Stream { public: + DECLARE_PTR_TYPEDEFS(SocketEvents); + ~SocketEvents(); virtual void OnEvent(int revents); diff --git a/lib/base/tlsstream.hpp b/lib/base/tlsstream.hpp index 8e4ceb08e..45519b5b1 100644 --- a/lib/base/tlsstream.hpp +++ b/lib/base/tlsstream.hpp @@ -43,7 +43,7 @@ enum TlsAction * * @ingroup base */ -class TlsStream final : public Stream, private SocketEvents +class TlsStream final : public SocketEvents { public: DECLARE_PTR_TYPEDEFS(TlsStream); From ad06c4f5ab5ef4a92288f1e6e45ae50f54ddebc6 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 24 Jul 2018 14:40:35 +0200 Subject: [PATCH 08/62] Make SocketEventDescriptor#EventInterface a SocketEvents::Ptr refs #6477 --- lib/base/socketevents.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/base/socketevents.hpp b/lib/base/socketevents.hpp index 26dc77019..45fad4617 100644 --- a/lib/base/socketevents.hpp +++ b/lib/base/socketevents.hpp @@ -82,7 +82,7 @@ private: struct SocketEventDescriptor { int Events{POLLIN}; - SocketEvents *EventInterface{nullptr}; + SocketEvents::Ptr EventInterface; Object *LifesupportObject{nullptr}; }; From f3f402fa7efc2d932e725aef914ffc8e67d3bea8 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 24 Jul 2018 15:06:55 +0200 Subject: [PATCH 09/62] Socket engine: drop life support objects refs #6477 --- lib/base/socketevents-epoll.cpp | 5 +---- lib/base/socketevents-poll.cpp | 5 +---- lib/base/socketevents.cpp | 8 ++++---- lib/base/socketevents.hpp | 12 +++++------- lib/base/tlsstream.cpp | 2 +- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/lib/base/socketevents-epoll.cpp b/lib/base/socketevents-epoll.cpp index ba2e7e25b..932323c6e 100644 --- a/lib/base/socketevents-epoll.cpp +++ b/lib/base/socketevents-epoll.cpp @@ -113,8 +113,6 @@ void SocketEventEngineEpoll::ThreadProc(int tid) EventDescription event; event.REvents = SocketEventEngineEpoll::EpollToPoll(pevents[i].events); event.Descriptor = m_Sockets[tid][pevents[i].data.fd]; - event.LifesupportReference = event.Descriptor.LifesupportObject; - VERIFY(event.LifesupportReference); events.emplace_back(std::move(event)); } @@ -134,7 +132,7 @@ void SocketEventEngineEpoll::ThreadProc(int tid) } } -void SocketEventEngineEpoll::Register(SocketEvents *se, Object *lifesupportObject) +void SocketEventEngineEpoll::Register(SocketEvents *se) { int tid = se->m_ID % SOCKET_IOTHREADS; @@ -145,7 +143,6 @@ void SocketEventEngineEpoll::Register(SocketEvents *se, Object *lifesupportObjec SocketEventDescriptor desc; desc.EventInterface = se; - desc.LifesupportObject = lifesupportObject; VERIFY(m_Sockets[tid].find(se->m_FD) == m_Sockets[tid].end()); diff --git a/lib/base/socketevents-poll.cpp b/lib/base/socketevents-poll.cpp index e46dd2c45..afb43177e 100644 --- a/lib/base/socketevents-poll.cpp +++ b/lib/base/socketevents-poll.cpp @@ -111,8 +111,6 @@ void SocketEventEnginePoll::ThreadProc(int tid) EventDescription event; event.REvents = pfds[i].revents; event.Descriptor = descriptors[i]; - event.LifesupportReference = event.Descriptor.LifesupportObject; - VERIFY(event.LifesupportReference); events.emplace_back(std::move(event)); } @@ -132,7 +130,7 @@ void SocketEventEnginePoll::ThreadProc(int tid) } } -void SocketEventEnginePoll::Register(SocketEvents *se, Object *lifesupportObject) +void SocketEventEnginePoll::Register(SocketEvents *se) { int tid = se->m_ID % SOCKET_IOTHREADS; @@ -144,7 +142,6 @@ void SocketEventEnginePoll::Register(SocketEvents *se, Object *lifesupportObject SocketEventDescriptor desc; desc.Events = 0; desc.EventInterface = se; - desc.LifesupportObject = lifesupportObject; VERIFY(m_Sockets[tid].find(se->m_FD) == m_Sockets[tid].end()); diff --git a/lib/base/socketevents.cpp b/lib/base/socketevents.cpp index 1400396a4..286460eab 100644 --- a/lib/base/socketevents.cpp +++ b/lib/base/socketevents.cpp @@ -111,12 +111,12 @@ void SocketEvents::InitializeEngine() /** * Constructor for the SocketEvents class. */ -SocketEvents::SocketEvents(const Socket::Ptr& socket, Object *lifesupportObject) +SocketEvents::SocketEvents(const Socket::Ptr& socket) : m_ID(m_NextID++), m_FD(socket->GetFD()), m_EnginePrivate(nullptr) { boost::call_once(l_SocketIOOnceFlag, &SocketEvents::InitializeEngine); - Register(lifesupportObject); + Register(); } SocketEvents::~SocketEvents() @@ -124,9 +124,9 @@ SocketEvents::~SocketEvents() VERIFY(m_FD == INVALID_SOCKET); } -void SocketEvents::Register(Object *lifesupportObject) +void SocketEvents::Register() { - l_SocketIOEngine->Register(this, lifesupportObject); + l_SocketIOEngine->Register(this); } void SocketEvents::Unregister() diff --git a/lib/base/socketevents.hpp b/lib/base/socketevents.hpp index 45fad4617..44bca3071 100644 --- a/lib/base/socketevents.hpp +++ b/lib/base/socketevents.hpp @@ -57,7 +57,7 @@ public: void SetEnginePrivate(void *priv); protected: - SocketEvents(const Socket::Ptr& socket, Object *lifesupportObject); + SocketEvents(const Socket::Ptr& socket); private: int m_ID; @@ -71,7 +71,7 @@ private: void WakeUpThread(bool wait = false); - void Register(Object *lifesupportObject); + void Register(); friend class SocketEventEnginePoll; friend class SocketEventEngineEpoll; @@ -83,14 +83,12 @@ struct SocketEventDescriptor { int Events{POLLIN}; SocketEvents::Ptr EventInterface; - Object *LifesupportObject{nullptr}; }; struct EventDescription { int REvents; SocketEventDescriptor Descriptor; - Object::Ptr LifesupportReference; }; class SocketEventEngine @@ -105,7 +103,7 @@ public: protected: virtual void InitializeThread(int tid) = 0; virtual void ThreadProc(int tid) = 0; - virtual void Register(SocketEvents *se, Object *lifesupportObject) = 0; + virtual void Register(SocketEvents *se) = 0; virtual void Unregister(SocketEvents *se) = 0; virtual void ChangeEvents(SocketEvents *se, int events) = 0; @@ -122,7 +120,7 @@ protected: class SocketEventEnginePoll final : public SocketEventEngine { public: - void Register(SocketEvents *se, Object *lifesupportObject) override; + void Register(SocketEvents *se) override; void Unregister(SocketEvents *se) override; void ChangeEvents(SocketEvents *se, int events) override; @@ -135,7 +133,7 @@ protected: class SocketEventEngineEpoll : public SocketEventEngine { public: - virtual void Register(SocketEvents *se, Object *lifesupportObject); + virtual void Register(SocketEvents *se); virtual void Unregister(SocketEvents *se); virtual void ChangeEvents(SocketEvents *se, int events); diff --git a/lib/base/tlsstream.cpp b/lib/base/tlsstream.cpp index c51530395..e3c232bd0 100644 --- a/lib/base/tlsstream.cpp +++ b/lib/base/tlsstream.cpp @@ -43,7 +43,7 @@ bool TlsStream::m_SSLIndexInitialized = false; * @param sslContext The SSL context for the client. */ TlsStream::TlsStream(const Socket::Ptr& socket, const String& hostname, ConnectionRole role, const std::shared_ptr& sslContext) - : SocketEvents(socket, this), m_Eof(false), m_HandshakeOK(false), m_VerifyOK(true), m_ErrorCode(0), + : SocketEvents(socket), m_Eof(false), m_HandshakeOK(false), m_VerifyOK(true), m_ErrorCode(0), m_ErrorOccurred(false), m_Socket(socket), m_Role(role), m_SendQ(new FIFO()), m_RecvQ(new FIFO()), m_CurrentAction(TlsActionNone), m_Retry(false), m_Shutdown(false) { From ce6ab9a9485f7d4ad8ec2c5ccd196f5ae975fb68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Thu, 18 Oct 2018 18:09:20 +0200 Subject: [PATCH 10/62] Remove dead code Remove some dead code in ScheduledDowntime::CreateNextDowntime(). --- lib/icinga/scheduleddowntime.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index 978115e61..278e3d166 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -189,15 +189,8 @@ void ScheduledDowntime::CreateNextDowntime() std::pair segment = FindNextSegment(); - if (segment.first == 0 && segment.second == 0) { - tm reference = Utility::LocalTime(Utility::GetTime()); - reference.tm_mday++; - reference.tm_hour = 0; - reference.tm_min = 0; - reference.tm_sec = 0; - + if (segment.first == 0 && segment.second == 0) return; - } String downtimeName = Downtime::AddDowntime(GetCheckable(), GetAuthor(), GetComment(), segment.first, segment.second, From e76ec0d42e706f25675748a10c660ca52f8c5405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Thu, 18 Oct 2018 18:35:14 +0200 Subject: [PATCH 11/62] Remove spurious string in debug message Remove a spurious " at " in the "Evaluating segment" debug message in ScheduledDowntime::FindNextSegment(). --- lib/icinga/scheduleddowntime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index 278e3d166..8b0be7e83 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -139,7 +139,7 @@ std::pair ScheduledDowntime::FindNextSegment() ObjectLock olock(ranges); for (const Dictionary::Pair& kv : ranges) { Log(LogDebug, "ScheduledDowntime") - << "Evaluating segment: " << kv.first << ": " << kv.second << " at "; + << "Evaluating segment: " << kv.first << ": " << kv.second; Dictionary::Ptr segment = LegacyTimePeriod::FindNextSegment(kv.first, kv.second, &reference); From 3b4dc854cffc55e53be0e593fad4d1f0ec9e0b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Thu, 18 Oct 2018 18:42:21 +0200 Subject: [PATCH 12/62] Put running downtimes in effect If Icinga2 was restarted with a newly configured downtime that should be in effect at the time of restart, the should-be-running segment of it was not put into effect. Add new LegacyTimePeriod::FindRunningSegment() and ScheduledDowntime::FindRunningSegment() functions, call the latter in ScheduledDowntime::CreateNextDowntime() before trying the old ScheduledDowntime::FindNextSegment(). --- lib/icinga/legacytimeperiod.cpp | 50 ++++++++++++++++ lib/icinga/legacytimeperiod.hpp | 1 + lib/icinga/scheduleddowntime.cpp | 100 +++++++++++++++++++++++++++---- lib/icinga/scheduleddowntime.hpp | 1 + 4 files changed, 140 insertions(+), 12 deletions(-) diff --git a/lib/icinga/legacytimeperiod.cpp b/lib/icinga/legacytimeperiod.cpp index 427f6903a..eea88e2ca 100644 --- a/lib/icinga/legacytimeperiod.cpp +++ b/lib/icinga/legacytimeperiod.cpp @@ -388,6 +388,56 @@ void LegacyTimePeriod::ProcessTimeRanges(const String& timeranges, tm *reference } } +Dictionary::Ptr LegacyTimePeriod::FindRunningSegment(const String& daydef, const String& timeranges, tm *reference) +{ + tm begin, end, iter; + time_t tsend, tsiter, tsref; + int stride; + + tsref = mktime(reference); + + ParseTimeRange(daydef, &begin, &end, &stride, reference); + + iter = begin; + + tsend = mktime(&end); + + do { + if (IsInTimeRange(&begin, &end, stride, &iter)) { + Array::Ptr segments = new Array(); + ProcessTimeRanges(timeranges, &iter, segments); + + Dictionary::Ptr bestSegment; + double bestEnd; + + ObjectLock olock(segments); + for (const Dictionary::Ptr& segment : segments) { + double begin = segment->Get("begin"); + double end = segment->Get("end"); + + if (begin >= tsref || end < tsref) + continue; + + if (!bestSegment || end > bestEnd) { + bestSegment = segment; + bestEnd = end; + } + } + + if (bestSegment) + return bestSegment; + } + + iter.tm_mday++; + iter.tm_hour = 0; + iter.tm_min = 0; + iter.tm_sec = 0; + tsiter = mktime(&iter); + } while (tsiter < tsend); + + return nullptr; +} + Dictionary::Ptr LegacyTimePeriod::FindNextSegment(const String& daydef, const String& timeranges, tm *reference) { tm begin, end, iter, ref; diff --git a/lib/icinga/legacytimeperiod.hpp b/lib/icinga/legacytimeperiod.hpp index 28f1e8052..9e6ee257a 100644 --- a/lib/icinga/legacytimeperiod.hpp +++ b/lib/icinga/legacytimeperiod.hpp @@ -48,6 +48,7 @@ public: static Dictionary::Ptr ProcessTimeRange(const String& timerange, tm *reference); static void ProcessTimeRanges(const String& timeranges, tm *reference, const Array::Ptr& result); static Dictionary::Ptr FindNextSegment(const String& daydef, const String& timeranges, tm *reference); + static Dictionary::Ptr FindRunningSegment(const String& daydef, const String& timeranges, tm *reference); private: LegacyTimePeriod(); diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index 8b0be7e83..449507e0c 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -117,6 +117,67 @@ Checkable::Ptr ScheduledDowntime::GetCheckable() const return host->GetServiceByShortName(GetServiceName()); } +std::pair ScheduledDowntime::FindRunningSegment(double minEnd) +{ + time_t refts = Utility::GetTime(); + tm reference = Utility::LocalTime(refts); + + Log(LogDebug, "ScheduledDowntime") + << "Finding running scheduled downtime segment for time " << refts + << " (minEnd " << (minEnd > 0 ? Utility::FormatDateTime("%c", minEnd) : "-") << ")"; + + Dictionary::Ptr ranges = GetRanges(); + + if (!ranges) + return std::make_pair(0, 0); + + Array::Ptr segments = new Array(); + + Dictionary::Ptr bestSegment; + double bestBegin, bestEnd; + double now = Utility::GetTime(); + + ObjectLock olock(ranges); + + /* Find the longest lasting (and longer than minEnd, if given) segment that's already running */ + for (const Dictionary::Pair& kv : ranges) { + Log(LogDebug, "ScheduledDowntime") + << "Evaluating (running?) segment: " << kv.first << ": " << kv.second; + + Dictionary::Ptr segment = LegacyTimePeriod::FindRunningSegment(kv.first, kv.second, &reference); + + if (!segment) + continue; + + double begin = segment->Get("begin"); + double end = segment->Get("end"); + + Log(LogDebug, "ScheduledDowntime") + << "Considering (running?) segment: " << Utility::FormatDateTime("%c", begin) << " -> " << Utility::FormatDateTime("%c", end); + + if (begin >= now || end < now) { + Log(LogDebug, "ScheduledDowntime") << "not running."; + continue; + } + if (minEnd && end <= minEnd) { + Log(LogDebug, "ScheduledDowntime") << "ending too early."; + continue; + } + + if (!bestSegment || end > bestEnd) { + Log(LogDebug, "ScheduledDowntime") << "(best match yet)"; + bestSegment = segment; + bestBegin = begin; + bestEnd = end; + } + } + + if (bestSegment) + return std::make_pair(bestBegin, bestEnd); + + return std::make_pair(0, 0); +} + std::pair ScheduledDowntime::FindNextSegment() { time_t refts = Utility::GetTime(); @@ -133,10 +194,12 @@ std::pair ScheduledDowntime::FindNextSegment() Array::Ptr segments = new Array(); Dictionary::Ptr bestSegment; - double bestBegin; + double bestBegin, bestEnd; double now = Utility::GetTime(); ObjectLock olock(ranges); + + /* Find the segment starting earliest */ for (const Dictionary::Pair& kv : ranges) { Log(LogDebug, "ScheduledDowntime") << "Evaluating segment: " << kv.first << ": " << kv.second; @@ -146,24 +209,29 @@ std::pair ScheduledDowntime::FindNextSegment() if (!segment) continue; - Log(LogDebug, "ScheduledDowntime") - << "Considering segment: " << Utility::FormatDateTime("%c", segment->Get("begin")) << " -> " << Utility::FormatDateTime("%c", segment->Get("end")); - double begin = segment->Get("begin"); + double end = segment->Get("end"); - if (begin < now) + Log(LogDebug, "ScheduledDowntime") + << "Considering segment: " << Utility::FormatDateTime("%c", begin) << " -> " << Utility::FormatDateTime("%c", end); + + if (begin < now) { + Log(LogDebug, "ScheduledDowntime") << "already running."; continue; + } if (!bestSegment || begin < bestBegin) { + Log(LogDebug, "ScheduledDowntime") << "(best match yet)"; bestSegment = segment; bestBegin = begin; + bestEnd = end; } } if (bestSegment) - return std::make_pair(bestSegment->Get("begin"), bestSegment->Get("end")); - else - return std::make_pair(0, 0); + return std::make_pair(bestBegin, bestEnd); + + return std::make_pair(0, 0); } void ScheduledDowntime::CreateNextDowntime() @@ -175,7 +243,13 @@ void ScheduledDowntime::CreateNextDowntime() return; } + double minEnd = 0; + for (const Downtime::Ptr& downtime : GetCheckable()->GetDowntimes()) { + double end = downtime->GetEndTime(); + if (end > minEnd) + minEnd = end; + if (downtime->GetScheduledBy() != GetName() || downtime->GetStartTime() < Utility::GetTime()) continue; @@ -187,10 +261,12 @@ void ScheduledDowntime::CreateNextDowntime() Log(LogDebug, "ScheduledDowntime") << "Creating new Downtime for ScheduledDowntime \"" << GetName() << "\""; - std::pair segment = FindNextSegment(); - - if (segment.first == 0 && segment.second == 0) - return; + std::pair segment = FindRunningSegment(minEnd); + if (segment.first == 0 && segment.second == 0) { + segment = FindNextSegment(); + if (segment.first == 0 && segment.second == 0) + return; + } String downtimeName = Downtime::AddDowntime(GetCheckable(), GetAuthor(), GetComment(), segment.first, segment.second, diff --git a/lib/icinga/scheduleddowntime.hpp b/lib/icinga/scheduleddowntime.hpp index c3891676f..158349291 100644 --- a/lib/icinga/scheduleddowntime.hpp +++ b/lib/icinga/scheduleddowntime.hpp @@ -58,6 +58,7 @@ protected: private: static void TimerProc(); + std::pair FindRunningSegment(double minEnd = 0); std::pair FindNextSegment(); void CreateNextDowntime(); From 173455de229d0d207c9ce6c802dcb198a8aefed7 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 10 Sep 2018 16:10:16 +0200 Subject: [PATCH 13/62] Call SSL_shutdown() at least twice --- lib/base/tlsstream.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/base/tlsstream.cpp b/lib/base/tlsstream.cpp index e3c232bd0..a694f86bf 100644 --- a/lib/base/tlsstream.cpp +++ b/lib/base/tlsstream.cpp @@ -398,7 +398,20 @@ void TlsStream::CloseInternal(bool inDestructor) if (!m_SSL) return; - (void)SSL_shutdown(m_SSL.get()); + /* https://www.openssl.org/docs/manmaster/man3/SSL_shutdown.html + * + * It is recommended to do a bidirectional shutdown by checking + * the return value of SSL_shutdown() and call it again until + * it returns 1 or a fatal error. A maximum of 2x pending + 2x data + * is recommended. + */ + int rc = 0; + + for (int i = 0; i < 4; i++) { + if ((rc = SSL_shutdown(m_SSL.get()))) + break; + } + m_SSL.reset(); m_Socket->Close(); From a5659e469afa477b5dbc99508a67f30b184a7a85 Mon Sep 17 00:00:00 2001 From: Leon Stringer Date: Wed, 31 Oct 2018 11:46:12 +0000 Subject: [PATCH 14/62] Doc fix: error in example path. --- doc/05-service-monitoring.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/05-service-monitoring.md b/doc/05-service-monitoring.md index cdaa8ed1a..eda3089ae 100644 --- a/doc/05-service-monitoring.md +++ b/doc/05-service-monitoring.md @@ -16,7 +16,7 @@ and create a new global constant, e.g. `CustomPluginDir` in your [constants.conf configuration file: # cp check_snmp_int.pl /opt/monitoring/plugins - # chmod +x /opt/plugins/check_snmp_int.pl + # chmod +x /opt/monitoring/plugins/check_snmp_int.pl # cat /etc/icinga2/constants.conf /** From 62fcbe3c015499f36d8333103143c13d005d110b Mon Sep 17 00:00:00 2001 From: David Lublink Date: Thu, 1 Nov 2018 18:51:42 -0400 Subject: [PATCH 15/62] * BugFix : Wrong operator on stride variable causing incorrect behaviour ( #6749 ) --- lib/icinga/legacytimeperiod.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/icinga/legacytimeperiod.cpp b/lib/icinga/legacytimeperiod.cpp index eea88e2ca..6433d0d6c 100644 --- a/lib/icinga/legacytimeperiod.cpp +++ b/lib/icinga/legacytimeperiod.cpp @@ -42,7 +42,7 @@ bool LegacyTimePeriod::IsInTimeRange(tm *begin, tm *end, int stride, tm *referen int daynumber = (tsref - tsbegin) / (24 * 60 * 60); - if (stride > 1 && daynumber % stride == 0) + if (stride > 1 && daynumber % stride > 0) return false; return true; From 9800e69f9f553c1edf7a85b0efb320cfba6dd86e Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 2 Nov 2018 07:45:48 +0100 Subject: [PATCH 16/62] Doc fix: documentation link for apt Fixes `check_apt` documentation link to point to the right man page. --- doc/10-icinga-template-library.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/10-icinga-template-library.md b/doc/10-icinga-template-library.md index a9a861651..382e9b52d 100644 --- a/doc/10-icinga-template-library.md +++ b/doc/10-icinga-template-library.md @@ -182,7 +182,7 @@ which contains the path of the plugins from the Monitoring Plugins project. ### apt -The plugin [apt](https://www.monitoring-plugins.org/doc/index.html) checks for software updates on systems that use +The plugin [apt](https://www.monitoring-plugins.org/doc/man/check_apt.html) checks for software updates on systems that use package management systems based on the apt-get(8) command found in Debian based systems. Custom attributes passed as [command parameters](03-monitoring-basics.md#command-passing-parameters): From 29a3a6d4d79e000504316bb57495066c2efdf711 Mon Sep 17 00:00:00 2001 From: fluxX04 Date: Thu, 15 Nov 2018 09:54:58 +0100 Subject: [PATCH 17/62] update apache status command to be identical according the itl --- doc/05-service-monitoring.md | 2 +- doc/08-advanced-topics.md | 2 +- doc/10-icinga-template-library.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/05-service-monitoring.md b/doc/05-service-monitoring.md index eda3089ae..b8e7375c0 100644 --- a/doc/05-service-monitoring.md +++ b/doc/05-service-monitoring.md @@ -226,7 +226,7 @@ Instead, choose a plugin and configure its parameters and thresholds. The follow * [ftp](10-icinga-template-library.md#plugin-check-command-ftp) * [webinject](10-icinga-template-library.md#plugin-contrib-command-webinject) * [squid](10-icinga-template-library.md#plugin-contrib-command-squid) -* [apache_status](10-icinga-template-library.md#plugin-contrib-command-apache_status) +* [apache-status](10-icinga-template-library.md#plugin-contrib-command-apache-status) * [nginx_status](10-icinga-template-library.md#plugin-contrib-command-nginx_status) * [kdc](10-icinga-template-library.md#plugin-contrib-command-kdc) * [rbl](10-icinga-template-library.md#plugin-contrib-command-rbl) diff --git a/doc/08-advanced-topics.md b/doc/08-advanced-topics.md index 58ce96310..de87c40da 100644 --- a/doc/08-advanced-topics.md +++ b/doc/08-advanced-topics.md @@ -521,7 +521,7 @@ Database | MySQL | [mysql_health](10-icinga-template-library.md#plugin-contri Database | PostgreSQL | [postgres](10-icinga-template-library.md#plugin-contrib-command-postgres) Database | Housekeeping | Check the database size and growth and analyse metrics to examine trends. Database | DB IDO | [ido](10-icinga-template-library.md#itl-icinga-ido) (more below) -Webserver | Apache2, Nginx, etc. | [http](10-icinga-template-library.md#plugin-check-command-http), [apache_status](10-icinga-template-library.md#plugin-contrib-command-apache_status), [nginx_status](10-icinga-template-library.md#plugin-contrib-command-nginx_status) +Webserver | Apache2, Nginx, etc. | [http](10-icinga-template-library.md#plugin-check-command-http), [apache-status](10-icinga-template-library.md#plugin-contrib-command-apache-status), [nginx_status](10-icinga-template-library.md#plugin-contrib-command-nginx_status) Webserver | Certificates | [http](10-icinga-template-library.md#plugin-check-command-http) Webserver | Authorization | [http](10-icinga-template-library.md#plugin-check-command-http) Notifications | Mail (queue) | [smtp](10-icinga-template-library.md#plugin-check-command-smtp), [mailq](10-icinga-template-library.md#plugin-check-command-mailq) diff --git a/doc/10-icinga-template-library.md b/doc/10-icinga-template-library.md index 382e9b52d..45172ac78 100644 --- a/doc/10-icinga-template-library.md +++ b/doc/10-icinga-template-library.md @@ -1667,8 +1667,8 @@ Thresholds will always be "1". > **Note** > -> If they are enabled, performance data will be shown in the web interface. -> If run without the optional parameters, the plugin will output critical if any important updates are available. +> If they are enabled, performance data will be shown in the web interface. +> If run without the optional parameters, the plugin will output critical if any important updates are available. ### uptime-windows @@ -5138,7 +5138,7 @@ vmware_multiline | **Optional.** Multiline output in overview. This mean This category includes all plugins for web-based checks. -#### apache_status +#### apache-status The [check_apache_status.pl](https://github.com/lbetz/check_apache_status) plugin uses the [/server-status](https://httpd.apache.org/docs/current/mod/mod_status.html) From 190f381c7acc7a47e98aa75eaf34cb8eca2f0ecb Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 21 Nov 2018 11:20:54 +0100 Subject: [PATCH 18/62] Docs: Add a section for DB IDO Cleanup refs #6784 --- doc/14-features.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/doc/14-features.md b/doc/14-features.md index 378161acd..0ecafd62c 100644 --- a/doc/14-features.md +++ b/doc/14-features.md @@ -87,6 +87,30 @@ status_update_time A detailed list on the available table attributes can be found in the [DB IDO Schema documentation](24-appendix.md#schema-db-ido). +### DB IDO Cleanup + +Objects get deactivated when they are deleted from the configuration. +This is visible with the `is_active` column in the `icinga_objects` table. +Therefore all queries need to join this table and add `WHERE is_active=1` as +condition. Deleted objects preserve their history table entries for later SLA +reporting. + +Historical data isn't purged by default. You can enable the least +kept data age inside the `cleanup` configuration attribute for the +IDO features [IdoMysqlConnection](09-object-types.md#objecttype-idomysqlconnection) +and [IdoPgsqlConnection](09-object-types.md#objecttype-idopgsqlconnection). + +Example if you prefer to keep notification history for 30 days: + +``` + cleanup = { + notifications_age = 30d + contactnotifications_age = 30d + } +``` + +The historical tables are populated depending on the data `categories` specified. +Some tables are empty by default. ### DB IDO Tuning From c8a1155e3d3a3723befdbef553db4a00c0a4239b Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 29 Nov 2018 17:51:53 +0100 Subject: [PATCH 19/62] Remove redundand check for object existence on creation via API refs #3937 --- lib/remote/configobjectutility.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/remote/configobjectutility.cpp b/lib/remote/configobjectutility.cpp index 1fc8dcb92..708ec0303 100644 --- a/lib/remote/configobjectutility.cpp +++ b/lib/remote/configobjectutility.cpp @@ -120,11 +120,6 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full String path = GetObjectConfigPath(type, fullName); Utility::MkDirP(Utility::DirName(path), 0700); - if (Utility::PathExists(path)) { - errors->Add("Cannot create object '" + fullName + "'. Configuration file '" + path + "' already exists."); - return false; - } - std::ofstream fp(path.CStr(), std::ofstream::out | std::ostream::trunc); fp << config; fp.close(); From ea64467c65d0e5f6dc684fdb6fed20801f33abb8 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 6 Dec 2018 09:55:42 +0100 Subject: [PATCH 20/62] Revert "ThreadPool#Stop(): discard non-processed queue items" This reverts commit 797ecd1539c91d3dd02dc7d164ce602c52a6f802. --- lib/base/threadpool.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/base/threadpool.cpp b/lib/base/threadpool.cpp index b6b01ea78..1dad249bc 100644 --- a/lib/base/threadpool.cpp +++ b/lib/base/threadpool.cpp @@ -73,7 +73,6 @@ void ThreadPool::Stop() for (auto& queue : m_Queues) { boost::mutex::scoped_lock lock(queue.Mutex); queue.Stopped = true; - queue.Items.clear(); queue.CV.notify_all(); } From 3b14c733ed97a7fb0b44721a1fb83dbf82937480 Mon Sep 17 00:00:00 2001 From: Markus Frosch Date: Tue, 18 Dec 2018 11:52:06 +0100 Subject: [PATCH 21/62] tools/win32: Invalidate CMake cache on build (cherry picked from commit fcfde9ac22ff6bfde73ecfe1672bb686e1559e28) --- tools/win32/configure.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/win32/configure.ps1 b/tools/win32/configure.ps1 index 1f40875ce..57fc03188 100644 --- a/tools/win32/configure.ps1 +++ b/tools/win32/configure.ps1 @@ -53,6 +53,11 @@ cd "$env:ICINGA2_BUILDPATH" #-DCMAKE_INSTALL_PREFIX="C:\Program Files\Icinga2" ` +# Invalidate cache in case something in the build environment changed +if (Test-Path CMakeCache.txt) { + Remove-Item -Force CMakeCache.txt | Out-Null +} + & cmake.exe "$sourcePath" ` -DCMAKE_BUILD_TYPE=RelWithDebInfo ` -G $env:CMAKE_GENERATOR -DCPACK_GENERATOR=WIX ` From 9f22300cf74fef1ab8d0f84406fce2a862e2aeb3 Mon Sep 17 00:00:00 2001 From: Markus Frosch Date: Tue, 18 Dec 2018 12:08:41 +0100 Subject: [PATCH 22/62] appveyor: Run Debug builds [skip travis] (cherry picked from commit ace12db110e565b20f8b1141e62e488b9c4abc8f) --- appveyor.yml | 1 + tools/win32/configure.ps1 | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 6e7f09b73..9d1150f72 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,6 +11,7 @@ environment: BOOST_LIBRARYDIR: 'C:\Libraries\boost_1_65_1\lib64-msvc-14.1' BISON_BINARY: 'C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_bison.exe' FLEX_BINARY: 'C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_flex.exe' + CMAKE_BUILD_TYPE: Debug branches: only: diff --git a/tools/win32/configure.ps1 b/tools/win32/configure.ps1 index 57fc03188..0ea0a50cb 100644 --- a/tools/win32/configure.ps1 +++ b/tools/win32/configure.ps1 @@ -2,6 +2,9 @@ if (-not (Test-Path env:ICINGA2_BUILDPATH)) { $env:ICINGA2_BUILDPATH = '.\build' } +if (-not (Test-Path env:CMAKE_BUILD_TYPE)) { + $env:CMAKE_BUILD_TYPE = 'RelWithDebInfo' +} if (-not (Test-Path "$env:ICINGA2_BUILDPATH")) { mkdir "$env:ICINGA2_BUILDPATH" | out-null } @@ -59,7 +62,7 @@ if (Test-Path CMakeCache.txt) { } & cmake.exe "$sourcePath" ` - -DCMAKE_BUILD_TYPE=RelWithDebInfo ` + -DCMAKE_BUILD_TYPE="$env:CMAKE_BUILD_TYPE" ` -G $env:CMAKE_GENERATOR -DCPACK_GENERATOR=WIX ` -DICINGA2_WITH_MYSQL=OFF -DICINGA2_WITH_PGSQL=OFF ` -DOPENSSL_ROOT_DIR="$env:OPENSSL_ROOT_DIR" ` From 7c71218d88edf1bc663443a5d7b35e4feb5e5bae Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 6 Dec 2018 12:41:49 +0100 Subject: [PATCH 23/62] Implement ScheduledDowntime::AllConfigIsLoaded() refs #6542 (cherry picked from commit bbcf469af1c584a92d028446c6ff1f558950cd97) --- lib/icinga/scheduleddowntime.cpp | 9 +++++++++ lib/icinga/scheduleddowntime.hpp | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index 449507e0c..37c3693bd 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -80,6 +80,8 @@ void ScheduledDowntime::OnAllConfigLoaded() if (!GetCheckable()) BOOST_THROW_EXCEPTION(ScriptError("ScheduledDowntime '" + GetName() + "' references a host/service which doesn't exist.", GetDebugInfo())); + + m_AllConfigLoaded.store(true); } void ScheduledDowntime::Start(bool runtimeCreated) @@ -339,3 +341,10 @@ void ScheduledDowntime::ValidateChildOptions(const Lazy& lvalue, const Va BOOST_THROW_EXCEPTION(ValidationError(this, { "child_options" }, "Invalid child_options specified")); } } + +bool ScheduledDowntime::AllConfigIsLoaded() +{ + return m_AllConfigLoaded.load(); +} + +std::atomic ScheduledDowntime::m_AllConfigLoaded (false); diff --git a/lib/icinga/scheduleddowntime.hpp b/lib/icinga/scheduleddowntime.hpp index 158349291..4322999b7 100644 --- a/lib/icinga/scheduleddowntime.hpp +++ b/lib/icinga/scheduleddowntime.hpp @@ -23,6 +23,7 @@ #include "icinga/i2-icinga.hpp" #include "icinga/scheduleddowntime-ti.hpp" #include "icinga/checkable.hpp" +#include namespace icinga { @@ -47,6 +48,7 @@ public: static void EvaluateApplyRules(const intrusive_ptr& host); static void EvaluateApplyRules(const intrusive_ptr& service); + static bool AllConfigIsLoaded(); void ValidateRanges(const Lazy& lvalue, const ValidationUtils& utils) override; void ValidateChildOptions(const Lazy& lvalue, const ValidationUtils& utils) override; @@ -62,6 +64,8 @@ private: std::pair FindNextSegment(); void CreateNextDowntime(); + static std::atomic m_AllConfigLoaded; + static bool EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule); static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule); }; From a24256993c2dab8d85a4171896dc4805e6da00e7 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 6 Dec 2018 12:50:48 +0100 Subject: [PATCH 24/62] Downtime#HasValidConfigOwner(): wait for ScheduledDowntimes refs #6542 (cherry picked from commit 39e0d787e82c187de64b29e4979f4caac0907441) --- lib/icinga/downtime.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index 336329bc2..4180747ac 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -210,6 +210,10 @@ bool Downtime::IsExpired() const bool Downtime::HasValidConfigOwner() const { + if (!ScheduledDowntime::AllConfigIsLoaded()) { + return true; + } + String configOwner = GetConfigOwner(); return configOwner.IsEmpty() || GetObject(configOwner); } From 53248a70c2c6b016e7dd1824fd3cc653f5c34231 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 4 Dec 2018 17:44:42 +0100 Subject: [PATCH 25/62] Add and populate Downtime#authoritative_zone refs #6542 (cherry picked from commit 5431eae116df92d0b856e7f856da24df5a948144) --- lib/icinga/downtime.cpp | 4 ++++ lib/icinga/downtime.ti | 1 + 2 files changed, 5 insertions(+) diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index 4180747ac..11b38d416 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -251,6 +251,10 @@ String Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& auth attrs->Set("config_owner", scheduledDowntime); attrs->Set("entry_time", Utility::GetTime()); + if (!scheduledDowntime.IsEmpty()) { + attrs->Set("authoritative_zone", Zone::GetLocalZone()->GetName()); + } + Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); diff --git a/lib/icinga/downtime.ti b/lib/icinga/downtime.ti index 17c8cfe91..fe80e0e77 100644 --- a/lib/icinga/downtime.ti +++ b/lib/icinga/downtime.ti @@ -84,6 +84,7 @@ class Downtime : ConfigObject < DowntimeNameComposer [state] int legacy_id; [state] bool was_cancelled; [config] String config_owner; + [config] String authoritative_zone; }; } From b888e06682d909a224674cde655d2ba3ac033009 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 4 Dec 2018 17:45:54 +0100 Subject: [PATCH 26/62] Downtime#HasValidConfigOwner(): respect Downtime#authoritative_zone refs #6542 (cherry picked from commit c98d6a52545bf0e10b9b0d644b0d15813ab7de48) --- lib/icinga/downtime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index 11b38d416..d9b24a3d3 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -215,7 +215,7 @@ bool Downtime::HasValidConfigOwner() const } String configOwner = GetConfigOwner(); - return configOwner.IsEmpty() || GetObject(configOwner); + return configOwner.IsEmpty() || Zone::GetByName(GetAuthoritativeZone()) != Zone::GetLocalZone() || GetObject(configOwner); } int Downtime::GetNextDowntimeID() From b93ad277a179b870ed32a46716443fd8ff02fd80 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 30 Jan 2019 14:23:57 +0100 Subject: [PATCH 27/62] Add a unit test for Convert::ToLong(double) - fails (cherry picked from commit b1362aeb9b6822a88ce4e3a187974f5ef20a4bad) --- test/base-convert.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/base-convert.cpp b/test/base-convert.cpp index 26919b61f..48499b1cb 100644 --- a/test/base-convert.cpp +++ b/test/base-convert.cpp @@ -33,6 +33,8 @@ BOOST_AUTO_TEST_CASE(tolong) BOOST_CHECK_THROW(Convert::ToLong("7a"), boost::exception); BOOST_CHECK(Convert::ToLong(Value(-7)) == -7); + + BOOST_CHECK(Convert::ToLong(3.141386593) == 3); } BOOST_AUTO_TEST_CASE(todouble) From 4fb444d3b7e95780c80fe0953e3b313a2fd67054 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 30 Jan 2019 14:47:59 +0100 Subject: [PATCH 28/62] Fix Convert::ToLong(double val) (cherry picked from commit b58cb17e4b389c6bd703e2334cb0bb2739213f62) --- lib/base/convert.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/base/convert.hpp b/lib/base/convert.hpp index 8b9000d05..bb7bd3e5c 100644 --- a/lib/base/convert.hpp +++ b/lib/base/convert.hpp @@ -64,6 +64,11 @@ public: return val; } + static long ToLong(double val) + { + return static_cast(val); + } + static double ToDouble(const Value& val) { return val; From ab947d7c3bb2da59d88896695497851c17535e8d Mon Sep 17 00:00:00 2001 From: Michael Insel Date: Wed, 30 Jan 2019 19:41:24 +0100 Subject: [PATCH 29/62] Fix check_swap formatting This fixes a small formatting mistake introduced by #6811. To keep the check_swap output in sync with all other plugins I fixed the formatting. --- plugins/check_swap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/check_swap.cpp b/plugins/check_swap.cpp index 906a1017d..302f20b46 100644 --- a/plugins/check_swap.cpp +++ b/plugins/check_swap.cpp @@ -200,7 +200,7 @@ static int printOutput(printInfoStruct& printInfo) if (printInfo.crit.rend(currentValue, printInfo.tSwap)) state = CRITICAL; - std::wcout << stateToString(state) << " "; + std::wcout << stateToString(state) << " - "; if (!printInfo.showUsed) std::wcout << printInfo.percentFree << L"% free "; From f6a62e71d83393bce148d17fd15b4338627a4063 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 28 Jan 2019 17:29:46 +0100 Subject: [PATCH 30/62] ClusterEvents::AcknowledgementSet event should forward 'persistent' attribute (cherry picked from commit 9f2ccfbaa0fd35e33a002dd48c7b429636dc806c) --- lib/icinga/clusterevents.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/icinga/clusterevents.cpp b/lib/icinga/clusterevents.cpp index db8102729..6c54be340 100644 --- a/lib/icinga/clusterevents.cpp +++ b/lib/icinga/clusterevents.cpp @@ -445,6 +445,7 @@ void ClusterEvents::AcknowledgementSetHandler(const Checkable::Ptr& checkable, params->Set("comment", comment); params->Set("acktype", type); params->Set("notify", notify); + params->Set("persistent", persistent); params->Set("expiry", expiry); Dictionary::Ptr message = new Dictionary(); From 362c7eb28a99b5a482fa3df393bc82970e795d4e Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 17 Jan 2019 12:13:44 +0100 Subject: [PATCH 31/62] TcpSocket#Bind(): also set SO_REUSEPORT refs #6898 (cherry picked from commit 984f7be03060f89235ccee1a1ef3e5fba652a9df) --- lib/base/tcpsocket.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/base/tcpsocket.cpp b/lib/base/tcpsocket.cpp index 7ac935bf8..2c3f6c7c3 100644 --- a/lib/base/tcpsocket.cpp +++ b/lib/base/tcpsocket.cpp @@ -91,6 +91,9 @@ void TcpSocket::Bind(const String& node, const String& service, int family) const int optTrue = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&optTrue), sizeof(optTrue)); +#ifndef _WIN32 + setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast(&optTrue), sizeof(optTrue)); +#endif /* _WIN32 */ int rc = bind(fd, info->ai_addr, info->ai_addrlen); From df68e65f0553f9ad314249930a08fb35cb065774 Mon Sep 17 00:00:00 2001 From: Michael Insel Date: Fri, 8 Feb 2019 16:57:19 +0100 Subject: [PATCH 32/62] Fix check_swap percentage calculation This fixes the check_swap percentage calculation. When the pagefile is turned off the available swap and total swap are 0 which leads to a wrong calculation and misformated output. refs #6913 (cherry picked from commit 4961e9ba62eebcfc1cf22e1840b289e4eab067d2) --- plugins/check_swap.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/check_swap.cpp b/plugins/check_swap.cpp index 302f20b46..7579073b7 100644 --- a/plugins/check_swap.cpp +++ b/plugins/check_swap.cpp @@ -229,7 +229,10 @@ static int check_swap(printInfoStruct& printInfo) printInfo.aSwap += round(pageFiles.at(i).availableSpwap / pow(1024.0, printInfo.unit)); } - printInfo.percentFree = 100.0 * printInfo.aSwap / printInfo.tSwap; + if (printInfo.aSwap > 0 && printInfo.tSwap > 0) + printInfo.percentFree = 100.0 * printInfo.aSwap / printInfo.tSwap; + else + printInfo.percentFree = 0; return -1; } From 29ff90a791d7ededd85bfa2153402a28e6d20e58 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 11 Feb 2019 13:17:52 +0100 Subject: [PATCH 33/62] Update AUTHORS --- AUTHORS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AUTHORS b/AUTHORS index f5c909682..a26d0fcce 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,7 @@ Adam Bolte Adam James Alan Jenkins +Alex Alexander A. Klimov Alexander Fuhr Alexander Schomburg @@ -40,6 +41,7 @@ Daniel Helgenberger Daniel Kesselberg Daniil Yaroslavtsev David Beck +David Lublink Denis Dinesh Majrekar Dirk Goetz @@ -99,6 +101,7 @@ Lars Krüger Leah Oswald Lee Clemens Lennart Betz +Leon Stringer Louis Sautier Luca Lesinigo Lucas Fairchild-Madar @@ -173,6 +176,7 @@ Steve McMaster Strajan Sebastian Ioan Strix <660956+MrStrix@users.noreply.github.com> Sven Nierlein +Sven Wegener T. Mulyana Thomas Forrer Thomas Gelf @@ -202,6 +206,7 @@ ctrlaltca dh.harald dominik-r-s <43005480+dominik-r-s@users.noreply.github.com> fbachmann +fluxX04 gitmopp jre3brg krishna From 146d055f4b9b4b7f266db3f78e64481e69c5c3e5 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 14 Nov 2018 14:25:37 +0100 Subject: [PATCH 34/62] Add technical docs for the check scheduler (general, initial check, offsets) David asked me about initial check offsets, so I wrote something :) (cherry picked from commit 9409e93bc798ffbe497c97cd110b492d533ce9dc) --- doc/19-technical-concepts.md | 190 +++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) diff --git a/doc/19-technical-concepts.md b/doc/19-technical-concepts.md index 278b2231f..b9021a28d 100644 --- a/doc/19-technical-concepts.md +++ b/doc/19-technical-concepts.md @@ -6,6 +6,7 @@ into specific Icinga 2 components such as: * [Application](19-technical-concepts.md#technical-concepts-application) * [Configuration](19-technical-concepts.md#technical-concepts-configuration) * [Features](19-technical-concepts.md#technical-concepts-features) +* [Check Scheduler](19-technical-concepts.md#technical-concepts-check-scheduler) * [Cluster](19-technical-concepts.md#technical-concepts-cluster) * [TLS Network IO](19-technical-concepts.md#technical-concepts-tls-network-io) @@ -196,6 +197,195 @@ to InfluxDB's HTTP API. +## Check Scheduler + +The check scheduler starts a thread which loops forever. It waits for +check events being inserted into `m_IdleCheckables`. + +If the current pending check event number is larger than the configured +max concurrent checks, the thread waits up until it there's slots again. + +In addition, further checks on enabled checks, check periods, etc. are +performed. Once all conditions have passed, the next check timestamp is +calculated and updated. This also is the timestamp where Icinga expects +a new check result ("freshness check"). + +The object is removed from idle checkables, and inserted into the +pending checkables list. This can be seen via REST API metrics for the +checker component feature as well. + +The actual check execution happens asynchronously using the application's +thread pool. + +Once the check returns, it is removed from pending checkables and again +inserted into idle checkables. This ensures that the scheduler takes this +checkable event into account in the next iteration. + +### Start + +When checkable objects get activated during the startup phase, +the checker feature registers a handler for this event. This is due +to the fact that the `checker` feature is fully optional, and e.g. not +used on command endpoint clients. + +Whenever such an object activation signal is triggered, Icinga 2 checks +whether it is [authoritative for this object](19-technical-concepts.md#technical-concepts-cluster-ha-object-authority). +This means that inside an HA enabled zone with two endpoints, only non-paused checkable objects are +actively inserted into the idle checkable list for the check scheduler. + +### Initial Check + +When a new checkable object (host or service) is initially added to the +configuration, Icinga 2 performs the following during startup: + +* `Checkable::Start()` is called and calculates the first check time +* With a spread delta, the next check time is actually set. + +If the next check should happen within a time frame of 60 seconds, +Icinga 2 calculates a delta from a random value. The minimum of `check_interval` +and 60 seconds is used as basis, multiplied with a random value between 0 and 1. + +In the best case, this check gets immediately executed after application start. +The worst case scenario is that the check is scheduled 60 seconds after start +the latest. + +The reasons for delaying and spreading checks during startup is that +the application typically needs more resources at this time (cluster connections, +feature warmup, initial syncs, etc.). Immediate check execution with +thousands of checks could lead into performance problems, and additional +events for each received check results. + +Therefore the initial check window is 60 seconds on application startup, +random seed for all checkables. This is not predictable over multiple restarts +for specific checkable objects, the delta changes every time. + +### Scheduling Offset + +There's a high chance that many checkable objects get executed at the same time +and interval after startup. The initial scheduling spreads that a little, but +Icinga 2 also attempts to ensure to keep fixed intervals, even with high check latency. + +During startup, Icinga 2 calculates the scheduling offset from a random number: + +* `Checkable::Checkable()` calls `SetSchedulingOffset()` with `Utility::Random()` +* The offset is a pseudo-random integral value between `0` and `RAND_MAX`. + +Whenever the next check time is updated with `Checkable::UpdateNextCheck()`, +the scheduling offset is taken into account. + +Depending on the state type (SOFT or HARD), either the `retry_interval` or `check_interval` +is used. If the interval is greater than 1 second, the time adjustment is calculated in the +following way: + +`now * 100 + offset` divided by `interval * 100`, using the remainder (that's what `fmod()` is for) +and dividing this again onto base 100. + +Example: offset is 6500, interval 300, now is 1542190472. + +``` +1542190472 * 100 + 6500 = 154219053714 +300 * 100 = 30000 +154219053714 / 30000 = 5140635.1238 + +(5140635.1238 - 5140635.0) * 30000 = 3714 +3714 / 100 = 37.14 +``` + +37.15 seconds as an offset would be far too much, so this is again used as a calculation divider for the +real offset with the base of 5 times the actual interval. + +Again, the remainder is calculated from the offset and `interval * 5`. This is divided onto base 100 again, +with an additional 0.5 seconds delay. + +Example: offset is 6500, interval 300. + +``` +6500 / 300 = 21.666666666666667 +(21.666666666666667 - 21.0) * 300 = 200 +200 / 100 = 2 +2 + 0.5 = 2.5 +``` + +The minimum value between the first adjustment and the second offset calculation based on the interval is +taken, in the above example `2.5` wins. + +The actual next check time substracts the adjusted time from the future interval addition to provide +a more widespread scheduling time among all checkable objects. + +`nextCheck = now - adj + interval` + +You may ask, what other values can happen with this offset calculation. Consider calculating more examples +with different interval settings. + +Example: offset is 34567, interval 60, now is 1542190472. + +``` +1542190472 * 100 + 34567 = 154219081767 +60 * 100 = 6000 +154219081767 / 6000 = 25703180.2945 +(25703180.2945 - 25703180.0) * 6000 / 100 = 17.67 + +34567 / 60 = 576.116666666666667 +(576.116666666666667 - 576.0) * 60 / 100 + 0.5 = 1.2 +``` + +`1m` interval starts at `now + 1.2s`. + +Example: offset is 12345, interval 86400, now is 1542190472. + +``` +1542190472 * 100 + 12345 = 154219059545 +86400 * 100 = 8640000 +154219059545 / 8640000 = 17849.428188078703704 +(17849.428188078703704 - 17849) * 8640000 = 3699545 +3699545 / 100 = 36995.45 + +12345 / 86400 = 0.142881944444444 +0.142881944444444 * 86400 / 100 + 0.5 = 123.95 +``` + +`1d` interval starts at `now + 2m4s`. + +> **Note** +> +> In case you have a better algorithm at hand, feel free to discuss this in a PR on GitHub. +> It needs to fulfill two things: 1) spread and shuffle execution times on each `next_check` update +> 2) not too narrowed window for both long and short intervals +> Application startup and initial checks need to be handled with care in a slightly different +> fashion. + +When `SetNextCheck()` is called, there are signals registered. One of them sits +inside the `CheckerComponent` class whose handler `CheckerComponent::NextCheckChangedHandler()` +deletes/inserts the next check event from the scheduling queue. This basically +is a list with multiple indexes with the keys for scheduling info and the object. + + +### Check Latency and Execution Time + +Each check command execution logs the start and end time where +Icinga 2 (and the end user) is able to calculate the plugin execution time from it. + +``` +GetExecutionEnd() - GetExecutionStart() +``` + +The higher the execution time, the higher the command timeout must be set. Furthermore +users and developers are encouraged to look into plugin optimizations to minimize the +execution time. Sometimes it is better to let an external daemon/script do the checks +and feed them back via REST API. + +Icinga 2 stores the scheduled start and end time for a check. If the actual +check execution time differs from the scheduled time, e.g. due to performance +problems or limited execution slots (concurrent checks), this value is stored +and computed from inside the check result. + +The difference between the two deltas is called `check latency`. + +``` +(GetScheduleEnd() - GetScheduleStart()) - CalculateExecutionTime() +``` + + ## Cluster ### Communication From ac80444129c5940c9e817f3ba48e1780be630213 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 3 Dec 2018 09:49:27 +0100 Subject: [PATCH 35/62] Docs: First draft for development docs (cherry picked from commit 4382b87baa0f4fa433772b2b38814fce0d443200) --- doc/21-development.md | 1571 +++++++++++++++++++++++++++++++++++------ 1 file changed, 1350 insertions(+), 221 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index d90d50def..1ff183434 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -1,14 +1,19 @@ -# Develop Icinga 2 +# Development This chapter provides hints on Icinga 2 development -especially for debugging purposes. +and debugging. -> **Note** -> -> If you are planning to build your own development environment, -> please consult the `INSTALL.md` file from the source tree. +## Debug Icinga 2 -## Debug Requirements +This chapter targets all users who have been asked by developers to provide +a stack trace or coredump if the application crashed. It is also useful +for developers working with different debuggers. + +> **Note:** +> This is intentionally mentioned before any development insights +> as debugging is a more frequent and commonly asked question. + +### Debug Requirements Make sure that the debug symbols are available for Icinga 2. The Icinga 2 packages provide a debug package which must be @@ -17,43 +22,1364 @@ or `icinga2-ido-mysql`. Debian/Ubuntu: - # apt-get install icinga2-dbg +``` +apt-get install icinga2-dbg +``` RHEL/CentOS: - # yum install icinga2-debuginfo +``` +yum install icinga2-debuginfo +``` Fedora: - # dnf install icinga2-debuginfo icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo +``` +dnf install icinga2-debuginfo icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo +``` SLES/openSUSE: - # zypper install icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo +``` +zypper install icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo +``` - -Furthermore, you may also have to install debug symbols for Boost and your C library. +Furthermore, you may also have to install debug symbols for Boost and your C++ library. If you're building your own binaries, you should use the `-DCMAKE_BUILD_TYPE=Debug` cmake build flag for debug builds. -## GDB +### GDB as Debugger -Install gdb: +Install GDB in your development environment. Debian/Ubuntu: - # apt-get install gdb +``` +apt-get install gdb +``` RHEL/CentOS/Fedora: - # yum install gdb +``` +yum install gdb +``` SLES/openSUSE: - # zypper install gdb +``` +zypper install gdb +``` +#### GDB Run + +Call GDB with the binary (`/usr/sbin/icinga2` is a wrapper script calling +`/usr/lib64/icinga2/sbin/icinga2` since 2.4) and all arguments and run it in foreground. + +``` +gdb --args /usr/lib64/icinga2/sbin/icinga2 daemon -x debug +``` + +The exact path to the Icinga 2 binary differs on each distribution. On Ubuntu +it is installed into `/usr/lib/x86_64-linux-gnu/icinga2/sbin/icinga2` on 64-bit systems +for example. + +> **Note** +> +> If gdb tells you it's missing debug symbols, quit gdb and install +> them: `Missing separate debuginfos, use: debuginfo-install ...` + +Run/restart the application. + +``` +(gdb) r +``` + +Kill the running application. + +``` +(gdb) k +``` + +Continue after breakpoint. + +``` +(gdb) c +``` + +#### GDB Core Dump + +Either attach to the running process using `gdb -p PID` or start +a new gdb run. + +``` +(gdb) r +(gdb) generate-core-file +``` + +#### GDB Backtrace + +If Icinga 2 aborted its operation abnormally, generate a backtrace. +`thread apply all` is important here since this includes all running threads. +We need this information when e.g. debugging dead locks and hanging features. + +``` +(gdb) bt +(gdb) thread apply all bt full +``` + +If gdb stops at a SIGPIPE signal please disable the signal before +running Icinga 2. This isn't an error, but we need to workaround it. + +``` +(gdb) handle SIGPIPE nostop noprint pass +(gdb) r +``` + +If you create a [new issue](https://github.com/Icinga/icinga2/issues), +make sure to attach as much detail as possible. + +#### GDB Backtrace from Running Process + +If Icinga 2 is still running, generate a full backtrace from the running +process and store it into a new file (e.g. for debugging dead locks). + +Icinga 2 runs with 2 processes: main and command executor, therefore generate two backtrace logs +and add them to the GitHub issue. + +``` +for pid in $(pidof icinga2); do gdb -p $pid -batch -ex "thread apply all bt full" -ex "detach" -ex "q" > gdb_bt_${pid}_`date +%s`.log; done +``` + +#### GDB Thread List from Running Process + +Instead of a full backtrace, you sometimes just need a list of running threads. + +``` +for pid in $(pidof icinga2); do gdb -p $pid -batch -ex "info threads" -ex "detach" -ex "q" > gdb_threads_${pid}_`date +%s`.log; done +``` + +#### GDB Backtrace Stepping + +Identifying the problem may require stepping into the backtrace, analysing +the current scope, attributes, and possible unmet requirements. `p` prints +the value of the selected variable or function call result. + +``` +(gdb) up +(gdb) down +(gdb) p checkable +(gdb) p checkable.px->m_Name +``` + +#### GDB Breakpoints + +To set a breakpoint to a specific function call, or file specific line. + +``` +(gdb) b checkable.cpp:125 +(gdb) b icinga::Checkable::SetEnablePerfdata +``` + +GDB will ask about loading the required symbols later, select `yes` instead +of `no`. + +Then run Icinga 2 until it reaches the first breakpoint. Continue with `c` +afterwards. + +``` +(gdb) run +(gdb) c +``` + +In case you want to step into the next line of code, use `n`. If there is a +function call where you want to step into, use `s`. + +``` +(gdb) n + +(gdb) s +``` + +If you want to delete all breakpoints, use `d` and select `yes`. + +``` +(gdb) d +``` + +> **Tip** +> +> When debugging exceptions, set your breakpoint like this: `b __cxa_throw`. + +Breakpoint Example: + + (gdb) b __cxa_throw + (gdb) r + (gdb) up + .... + (gdb) up + #11 0x00007ffff7cbf9ff in icinga::Utility::GlobRecursive(icinga::String const&, icinga::String const&, boost::function const&, int) (path=..., pattern=..., callback=..., type=1) + at /home/michi/coding/icinga/icinga2/lib/base/utility.cpp:609 + 609 callback(cpath); + (gdb) l + 604 + 605 #endif /* _WIN32 */ + 606 + 607 std::sort(files.begin(), files.end()); + 608 BOOST_FOREACH(const String& cpath, files) { + 609 callback(cpath); + 610 } + 611 + 612 std::sort(dirs.begin(), dirs.end()); + 613 BOOST_FOREACH(const String& cpath, dirs) { + (gdb) p files + $3 = std::vector of length 11, capacity 16 = {{static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/agent.conf"}, {static NPos = 18446744073709551615, + m_Data = "/etc/icinga2/conf.d/commands.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/downtimes.conf"}, {static NPos = 18446744073709551615, + m_Data = "/etc/icinga2/conf.d/groups.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/notifications.conf"}, {static NPos = 18446744073709551615, + m_Data = "/etc/icinga2/conf.d/satellite.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/services.conf"}, {static NPos = 18446744073709551615, + m_Data = "/etc/icinga2/conf.d/templates.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/test.conf"}, {static NPos = 18446744073709551615, + m_Data = "/etc/icinga2/conf.d/timeperiods.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/users.conf"}} + + +### Core Dump + +When the Icinga 2 daemon crashes with a `SIGSEGV` signal +a core dump file should be written. This will help +developers to analyze and fix the problem. + +#### Core Dump File Size Limit + +This requires setting the core dump file size to `unlimited`. + +Example for Systemd: + +``` +vim /usr/lib/systemd/system/icinga2.service + +[Service] +... +LimitCORE=infinity + +systemctl daemon-reload + +systemctl restart icinga2 +``` + +Example for init script: + +``` +vim /etc/init.d/icinga2 +... +ulimit -c unlimited + +service icinga2 restart +``` + +Verify that the Icinga 2 process core file size limit is set to `unlimited`. + +``` +cat /proc/`pidof icinga2`/limits +... +Max core file size unlimited unlimited bytes +``` + + +#### Core Dump Kernel Format + +The Icinga 2 daemon runs with the SUID bit set. Therefore you need +to explicitly enable core dumps for SUID on Linux. + +``` +sysctl -w fs.suid_dumpable=1 +``` + +Adjust the coredump kernel format and file location on Linux: + +``` +sysctl -w kernel.core_pattern=/var/lib/cores/core.%e.%p + +install -m 1777 -d /var/lib/cores +``` + +MacOS: + +``` +sysctl -w kern.corefile=/cores/core.%P + +chmod 777 /cores +``` + +#### Core Dump Analysis + +Once Icinga 2 crashes again a new coredump file will be written. Please +attach this file to your bug report in addition to the general details. + +Simple test case for a `SIGSEGV` simulation with `sleep`: + +``` +ulimit -c unlimited +sleep 1800& +[1] +kill -SEGV +gdb `which sleep` /var/lib/cores/core.sleep. +(gdb) bt +rm /var/lib/cores/core.sleep.* +``` + +Analyzing Icinga 2: + +``` +gdb /usr/lib64/icinga2/sbin/icinga2 core.icinga2. +(gdb) bt +``` + +### LLDB as Debugger + +LLDB is available on macOS with the Xcode command line tools. + +``` +$ xcode-select --install +``` + +In order to run Icinga 2 with LLDB you need to pass the binary as argument. + +``` +lldb -- /usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon +``` + +Full backtrace: + +``` +> bt all +``` + +Select thread: + +``` +> thr sel 5 +``` + +Step into: + +``` +> s +``` + +Next step: + +``` +> n +``` + +Continue: + +``` +> c +``` + +Up/down in stacktrace: + +``` +> up +> down +``` + + + +## Develop Icinga 2 + +Icinga 2 can be built on many platforms such as Linux, Unix and Windows. +There are limitations in terms of support, e.g. Windows is only supported for clients, +not a full-featured master or satellite. + +Before you start with actual development, there is a couple of pre-requisites. + +### Choose your Editor + +Icinga 2 can be developed with your favorite editor. Icinga developers prefer to use +the tools below: + +- vim +- CLion (macOS, Linux) +- MS Visual Studio (Windows) +- Atom + +Editors differ on the functionality. The more helpers you get for C++ development, +the faster your development workflow will be. + + +#### Whitespace Cleanup + +Patches must be cleaned up and follow the indent style (tabs instead of spaces). +You should also remove any training whitespaces. + +`git diff` allows to highlight such. + +``` +vim $HOME/.gitconfig + +[color "diff"] + whitespace = red reverse +[core] + whitespace=fix,-indent-with-non-tab,trailing-space,cr-at-eol +``` + +`vim` also can match these and visually alert you to remove them. + +``` +vim $HOME/.vimrc + +highlight ExtraWhitespace ctermbg=red guibg=red +match ExtraWhitespace /\s\+$/ +autocmd BufWinEnter * match ExtraWhitespace /\s\+$/ +autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@ + +Icinga 2 can run standalone or in distributed environments. It contains a whole lot +more than a simple check execution engine. + +Read more about it in the [Technical Concepts](#technical-concepts) chapter. + +### Get to know the code + +First off, you really need to know C++ and portions of C++11 and the boost libraries. +Best is to start with a book or online tutorial to get into the basics. +Icinga developers gained their knowledge through studies, training and self-teaching +code by trying it out and asking senior developers for guidance. + +Here's a few books we can recommend: + +* [Accelerated C++: Practical Programming by Example](https://www.amazon.com/Accelerated-C-Practical-Programming-Example/dp/020170353X) (Andrew Koenig, Barbara E. Moo) +* [Effective C++](https://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876) (Scott Meyers) +* [Der C++ Programmierer](https://www.amazon.de/Programmierer-lernen-Professionell-anwenden-L%C3%B6sungen/dp/3446416447), German (Ulrich Breymann) +* [C++11 programmieren](https://www.amazon.de/gp/product/3836217325/), German (Torsten T. Will) + +In addition, it is a good bet to also know SQL when diving into backend development. + +* [SQL Performance Explained](https://www.amazon.de/gp/product/3950307826/) (Markus Winand) + +Last but not least, if you are developing on Windows, get to know the internals about services and the Win32 API. + + +### Design Patterns + +Icinga 2 heavily relies on object-oriented programming and encapsulates common +functionality into classes and objects. It also uses modern programming techniques +to e.g. work with shared pointer memory management. + +Icinga 2 consists of libraries bundled into the main binary. Therefore you'll +find many code parts in the `lib/` directory wheras the actual application is +built from `icinga-app/`. Accompanied with Icinga 2, there's the Windows plugins +which are standalone and compiled from `plugins/`. + +Library | Description +---------------|------------------------------------ +base | Objects, values, types, streams, tockets, TLS, utilities, etc. +config | Configuration compiler, expressions, etc. +cli | CLI (sub) commands and helpers. +icinga | Icinga specific objects and event handling. +remote | Cluster and HTTP client/server and REST API related code. +checker | Checker feature, check scheduler. +notification | Notification feature, notification scheduler. +methods | Command execution methods, plugins and built-in checks. +perfdata | Performance data related, including Graphite, Elastic, etc. +db\_ido | IDO database abstraction layer. +db\_ido\_mysql | IDO database driver for MySQL. +db\_ido\_pgsql | IDO database driver for PgSQL. +mysql\_shin | Library stub for linking against the MySQL client libraries. +pgsql\_shim | Library stub for linking against the PgSQL client libraries. + +Another thing you will recognize are the `.ti` files which are compiled +by our own class compiler into actual source code. The meta language allows +developers to easily add object attributes and specify their behaviour. + +Some object attributes need to be stored over restarts in the state file +and therefore have the `state` attribute set. Others are treated as `config` +attribute and automatically get configuration validation functions created. +Hidden or read-only REST API attributes are marked with `no_user_view` and +`no_user_modify`. + +The most beneficial thing are getters and setters being generated. The actual object +inherits from `ObjectImpl` and therefore gets them "for free". + +Example: + +``` +vim lib/perfdata/gelfwriter.ti + + [config] enable_tls; + +vim lib/perfdata/gelfwriter.cpp + + if (GetEnableTls()) { +``` + +The logic is hidden in `tools/mkclass/` in case you want to learn more about it. +The first steps during CMake & make also tell you about code generation. + + +### Build Tool: CMake + +In its early development stages in 2012, Icinga 2 was built with autoconf/automake +and separate Windows project files. We've found this very fragile, and have changed +this into CMake as our build tool. + +The most common benefits: + +* Everything is described in CMakeLists.txt in each directory +* CMake only needs to know that a sub directory needs to be included. +* The global CMakeLists.txt acts as main entry point for requirement checks and library/header includes. +* Separate binary build directories, the actual source tree stays clean. +* CMake automatically generates a Visual Studio project file `icinga2.sln` on Windows. + +### Builds: Unity Builds + +Another thing you should be aware of: Unity builds on and off. + +Typically, we already use caching mechanisms to reduce recompile time with ccache. +For release builds, there's always a new build needed as the difference is huge compared +to a previous (major) release. + +Therefore we've invented the Unity builds, which basically concatenates all source files +into one big library source code file. The compiler then doesn't need to load the many small +files but compiles and links this huge one. + +Unity builds require more memory which is why you should disable them for development +builds in small sized VMs (Linux, Windows) and also Docker containers. + +There's a couple of header files which are included everywhere. If you touch/edit them, +the cache is invalidated and you need to recompile a lot more files then. `base/utility.hpp` +and `remote/zone.hpp` are good candidates for this. + + +### Linux Dev Environment + +Based on CentOS 7, we have an early draft available inside the Icinga Vagrant boxes: +[centos7-dev](https://github.com/Icinga/icinga-vagrant/tree/master/centos7-dev). + +If you're compiling Icinga 2 natively without any virtualization layer in between, +this usually is faster. This is also the reason why developers on macOS prefer native builds +over Linux or Windows VMs. Don't forget to test the actual code on Linux later! Socket specific +stuff like `epoll` is not available on Unix kernels. + +Depending on your workstation and environment, you may either develop and run locally, +use a container deployment pipeline or put everything in a high end resource remote VM. + +#### Prepare Linux Dev Environment + +Create two build directories for different binary builds. + +* `debug` contains the debug build binaries. They contain more debug information and run tremendously slower than release builds from packages. Don't use them for benchmarks. +* `release` contains the release build binaries, as you would install them on a live system. This helps comparing specific scenarios for race conditions and more. + +``` +mkdir -p release debug +``` + +Next, check the required packages to build Icinga 2, and install them. + +CentOS: + +``` + +``` + +Debian/Ubuntu: + +``` + +``` + +##### Debian Stretch + +``` +apt-get -y install gdb vim git cmake make ccache build-essential libssl-dev libboost-all-dev bison flex default-libmysqlclient-dev libpq-dev libyajl-dev libedit-dev monitoring-plugins + +ln -s /usr/bin/ccache /usr/local/bin/g++ + +groupadd icinga +groupadd icingacmd +useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga + +git clone https://github.com/icinga/icinga2.git && cd icinga2 + +mkdir debug release +cd debug +cmake .. -DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF -DCMAKE_INSTALL_PREFIX=/usr/local/icinga2 -DICINGA2_PLUGINDIR=/usr/local/sbin +cd .. +make -j2 install -C debug +``` + + +``` +chown -R icinga:icinga /usr/local/icinga2/var/ + +cd /usr/local/icinga2 +./lib/icinga2/prepare-dirs etc/sysconfig/icinga2 +icinga2 api setup +vim etc/icinga2/conf.d/api-users.conf + +gdb --args ./lib/icinga2/sbin/icinga2 daemon +``` + + + +### macOS Dev Environment + +It is advised to use Homebrew to install all required build dependencies. +Macports have been reported to work as well, typically you'll get more help +with Homebrew. + +We will also build two different flavors. + +``` +mkdir -p release debug +``` + + + +### Windows Dev Environment + +The following sections explain how to setup the required build tools +and how to run and debug the code. + +#### Chocolatey + +Open an administrative command prompt (Win key, type “cmd”, right-click and “run as administrator”) and paste the following instructions: + +``` +@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin +``` + +#### Visual Studio + +Thanks to Microsoft they’ll now provide their Professional Edition of Visual Studio 2017 +as community version, free for use for open source projects such as Icinga. +The installation requires ~9GB disk space. [Download](https://www.visualstudio.com/downloads/) +the web installer and start the installation. + +You need a free Microsoft account to download and also store your preferences. + +Choose the following minimal set: + +* .NET Framework 4.x SDK +* C# Compiler +* Visual Studio C++ core features +* VC++ toolset +* Windows 10 SDK (10.0.10240.0 - required) +* Just-in-time debugger +* Windows 8 SDK (includes mscoree.lib required by clrchecktask) +* C++/CLI support +* Windows Universal C Runtime +* Git for Windows +* .NET Framework 3.5 development tools +* Github extension for Visual Studio + +After a while, Visual Studio will be ready. + +#### Flex and Bison + +Install it using [chocolatey](https://www.wireshark.org/docs/wsdg_html_chunked/ChSetupWin32.html): + +``` +choco install -y winflexbison +``` + +Chocolatey installs these tools into the hidden directory `C:\ProgramData\chocolatey\lib\winflexbison\tools`. + +#### OpenSSL + +Icinga 2 requires the OpenSSL library. [Download](http://slproweb.com/products/Win32OpenSSL.html) +and install it into the default path. + +Once asked for `Copy OpenSSLs DLLs to` select `The Windows system directory`. That way CMake/Visual Studio +will automatically detect them for builds and packaging. + +> **Note** +> +> We cannot use the chocolatey package as this one does not provide any development headers. +> +> Choose 1.0.2 LTS from manual downloads for best compatibility if unsure. + +#### Boost + +In order to use the boost development header and library files you need to [download](http://www.boost.org/users/download/) +Boost and then extract it to e.g. `C:\boost_1_65_1`. + +> **Note** +> +> Just use `C:`, the zip file already contains the sub folder. Extraction takes a while, +> the archive contains more than 10k files. + +For integrating Boost into Visual Studio 2017, open the `Developer Command Prompt` from the start menu, +and navigate to `C:\boost_1_65_1`. + +Execute `bootstrap.bat` first. + +``` +cd C:\boost_1_65_1 +bootstrap.bat +``` + +Once finished, specify the required `toolset` to compile boost against Visual Studio. +This takes quite some time in a Windows VM. + +Visual Studio 2015: + +``` +b2 --toolset=msvc-14.0 +``` + +Visual Studio 2017: + +``` +b2 --toolset=msvc-14.1 +``` + +#### TortoiseGit + +TortoiseGit provides a graphical integration into the Windows explorer. This makes it easier to checkout, commit +and whatnot. + +[Download](https://tortoisegit.org/download/) TortoiseGit on your system. + +In order to clone via Git SSH you also need to create a new directory called `.ssh` +inside your user's home directory. +Therefore open a command prompt (win key, type `cmd`, enter) and run `mkdir .ssh`. +Add your `id_rsa` private key and `id_rsa.pub` public key files into that directory. + +Start the setup routine and choose `OpenSSH` as default secure transport when asked. + +Open a Windows Explorer window and navigate into + +Version | Project Location +--------------------|------------------------------ +Visual Studio 2015 | `C:\Users\michi\Documents\Visual Studio 2015\Projects` +Visual Studio 2017+ | `C:\Users\michi\source\repos` + +Right click and select `Git Clone` from the context menu. + +Use `ssh://git@github.com/icinga/icinga2.git` for SSH clones, `https://github.com/icinga/icinga2.git` otherwise. + +#### CMake + +Icinga 2 uses CMake to manage the build environment. You can generate the Visual Studio project files +using CMake. [Download](https://cmake.org/download/) and install CMake. Select to add it to PATH for all users +when asked. + +Once setup is completed, open a command prompt and navigate to + +Visual Studio 2015 + +``` +cd C:\Users\\Documents\Visual Studio 2015\Projects\icinga2 +``` + +Visual Studio 2017 + +``` +cd C:\Users\michi\source\repos +``` + +Run CMake with the following command. This generates a new Visual Studio project file called `icinga2.sln`. + +You need to specify the previously installed component paths: + +Variable | Value | Description +----------------------|----------------------------------------------------------------------| +BOOST_ROOT | `C:\boost_1_65_1` | Root path where you've extracted and compiled Boost. +BISON_EXECUTABLE | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe` | Path to the Bison executable. +FLEX_EXECUTABLE | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe` | Path to the Flex executable. +ICINGA2_WITH_MYSQL | OFF | Requires extra setup for MySQL if set to `ON`. Not supported for client setups. +ICINGA2_WITH_PGSQL | OFF | Requires extra setup for PgSQL if set to `ON`. Not supported for client setups. +ICINGA2_UNITY_BUILD | OFF | Disable unity builds for development environments. + +Tip: If you have previously opened a terminal, run `refreshenv` to re-read updated PATH variables. + +``` +cmake . -DBOOST_ROOT=C:\boost_1_65_1 -DBISON_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe -DFLEX_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe -DICINGA2_WITH_MYSQL=OFF -DICINGA2_WITH_PGSQL=OFF -DICINGA2_UNITY_BUILD=OFF +``` + +Best is write a small batch/Powershell script which just executes these lines. + + +#### Icinga 2 in Visual Studio + +Navigate to + +Version | Project location +--------------------|------------------------- +Visual Studio 2015 | `C:\Users\michi\Documents\Visual Studio 2015\Projects\icinga2` +Visual Studio 2017+ | `C:\Users\michi\source\repos\icinga2` + +Open `icinga2.sln`. Log into Visual Studio when asked. + +On the right panel, select to build the `Bin/icinga-app` solution. + +The executable binaries are located in `Bin\Release\Debug` in your `icinga2` +project directory. + +Navigate there and run `icinga2.exe --version`. + +Example for Visual Studio 2017: + +``` +cd C:\Users\michi\source\repos\icinga2\Bin\Release\Debug +icinga2.exe --version +``` + + +#### Release Package + +CMake uses CPack and NSIS to create the setup executable including all binaries and libraries +in addition to setup dialogues and configuration. Therefore we’ll need to install [NSIS](http://nsis.sourceforge.net/Download) +first. + +We also need to install the Windows Installer XML (WIX) toolset. + +``` +choco install -y wixtoolset +``` + +Once completed open an administrative shell and navigate to your Visual Studio project. +Let CMake to build a release package. + +``` +cd "c:\Users\michi\Documents\Visual Studio 2015\Projects\icinga2" +cmake --build . --target PACKAGE --config Release +``` + +Note: This will still use the debug builds. A yet more clean approach +is to run CMake with changed release parameters beforehand and then +re-run the release package builder. + +``` +C:\Users\michi\Documents\Visual Studio 2015\Projects\icinga2> +cmake . -DCPACK_GENERATOR=WIX -DCMAKE_BUILD_TYPE=Release -DBOOST_ROOT=C:\boost_1_65_1 -DBISON_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe -DFLEX_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe -DICINGA2_WITH_MYSQL=OFF -DICINGA2_WITH_PGSQL=OFF -DICINGA2_UNITY_BUILD=OFF + +cmake --build . --target PACKAGE --config Release +``` + +Again, put these lines into a batch/Powershell script and execute that. + + + +### Embedded Dev Env: Pi + +> **Note** +> +> This isn't officially supported yet, just a few hints how you can do it yourself. + +armhf on Raspberry Pi, ccache: + +``` +apt install -y ccache + +/usr/sbin/update-ccache-symlinks + +echo 'export PATH="/usr/lib/ccache:$PATH"' | tee -a ~/.bashrc + +source ~/.bashrc && echo $PATH +``` + +## Package Builds + +This documentation is explicitly meant for packagers and the Icinga +build infrastructure. + +The following requirements need to be fulfilled in order to build the +Icinga application using a dist tarball (including notes for distributions): + +* cmake >= 2.6 +* GNU make (make) or ninja-build +* C++ compiler which supports C++11 + - RHEL/Fedora/SUSE: gcc-c++ >= 4.7 (extra Developer Tools on RHEL5/6 see below) + - Debian/Ubuntu: build-essential + - Alpine: build-base + - you can also use clang++ +* pkg-config +* OpenSSL library and header files >= 1.0.1 + - RHEL/Fedora: openssl-devel + - SUSE: libopenssl-devel (for SLES 11: libopenssl1-devel) + - Debian/Ubuntu: libssl-dev + - Alpine: libressl-dev +* Boost library and header files >= 1.48.0 + - RHEL/Fedora: boost148-devel + - Debian/Ubuntu: libboost-all-dev + - Alpine: boost-dev +* GNU bison (bison) +* GNU flex (flex) >= 2.5.35 +* Systemd headers + - Only required when using Systemd + - Debian/Ubuntu: libsystemd-dev + - RHEL/Fedora: systemd-devel + +### Optional features + +* MySQL (disable with CMake variable `ICINGA2_WITH_MYSQL` to `OFF`) + - RHEL/Fedora: mysql-devel + - SUSE: libmysqlclient-devel + - Debian/Ubuntu: default-libmysqlclient-dev | libmysqlclient-dev + - Alpine: mariadb-dev +* PostgreSQL (disable with CMake variable `ICINGA2_WITH_PGSQL` to `OFF`) + - RHEL/Fedora: postgresql-devel + - Debian/Ubuntu: libpq-dev + - postgresql-dev on Alpine +* YAJL (Faster JSON library) + - RHEL/Fedora: yajl-devel + - Debian: libyajl-dev + - Alpine: yajl-dev +* libedit (CLI console) + - RHEL/Fedora: libedit-devel on CentOS (RHEL requires rhel-7-server-optional-rpms) + - Debian/Ubuntu/Alpine: libedit-dev +* Termcap (only required if libedit doesn't already link against termcap/ncurses) + - RHEL/Fedora: libtermcap-devel + - Debian/Ubuntu: (not necessary) + +### Special requirements + +**FreeBSD**: libexecinfo (automatically used when Icinga 2 is installed via port or package) + +**RHEL6**: Requires a newer boost version which is available on packages.icinga.com +with a version suffixed name. + +### Runtime user environment + +By default Icinga will run as user `icinga` and group `icinga`. Additionally the +external command pipe and livestatus features require a dedicated command group +`icingacmd`. You can choose your own user/group names and pass them to CMake +using the `ICINGA2_USER`, `ICINGA2_GROUP` and `ICINGA2_COMMAND_GROUP` variables. + +``` +# groupadd icinga +# groupadd icingacmd +# useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga +``` + +On Alpine (which uses ash busybox) you can run: + +``` +# addgroup -S icinga +# addgroup -S icingacmd +# adduser -S -D -H -h /var/spool/icinga2 -s /sbin/nologin -G icinga -g icinga icinga +# adduser icinga icingacmd +``` + +Add the web server user to the icingacmd group in order to grant it write +permissions to the external command pipe and livestatus socket: +``` +# usermod -a -G icingacmd www-data +``` + +Make sure to replace "www-data" with the name of the user your web server +is running as. + +### Building Icinga 2: Example + +Once you have installed all the necessary build requirements you can build +Icinga 2 using the following commands: + +``` +$ mkdir release && cd release +$ cmake .. +$ cd .. +$ make -C release +$ make install -C release +``` + +You can specify an alternative installation prefix using `-DCMAKE_INSTALL_PREFIX`: + +``` +$ cmake .. -DCMAKE_INSTALL_PREFIX=/tmp/icinga2 +``` + +### CMake Variables + +In addition to `CMAKE_INSTALL_PREFIX` here are most of the supported Icinga-specific cmake variables. + +For all variables regarding defaults paths on in CMake, see +[GNUInstallDirs](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html). + +Also see `CMakeLists.txt` for details. + +**System Environment** +- `CMAKE_INSTALL_SYSCONFDIR`: The configuration directory; defaults to `CMAKE_INSTALL_PREFIX/etc` +- `CMAKE_INSTALL_LOCALSTATEDIR`: The state directory; defaults to `CMAKE_INSTALL_PREFIX/var` +- `ICINGA2_CONFIGDIR`: Main config directory; defaults to `CMAKE_INSTALL_SYSCONFDIR/icinga2` usually `/etc/icinga2` +- `ICINGA2_CACHEDIR`: Directory for cache files; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/cache/icinga2` usually `/var/cache/icinga2` +- `ICINGA2_DATADIR`: Data directory for the daemon; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/lib/icinga2` usually `/var/lib/icinga2` +- `ICINGA2_LOGDIR`: Logfiles of the daemon; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/log/icinga2 usually `/var/log/icinga2` +- `ICINGA2_SPOOLDIR`: Spooling directory ; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/spool/icinga2` usually `/var/spool/icinga2` +- `ICINGA2_INITRUNDIR`: Runtime data for the init system; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/run/icinga2` usually `/run/icinga2` +- `ICINGA2_GIT_VERSION_INFO`: Whether to use Git to determine the version number; defaults to `ON` +- `ICINGA2_USER`: The user Icinga 2 should run as; defaults to `icinga` +- `ICINGA2_GROUP`: The group Icinga 2 should run as; defaults to `icinga` +- `ICINGA2_COMMAND_GROUP`: The command group Icinga 2 should use; defaults to `icingacmd` +- `ICINGA2_SYSCONFIGFILE`: Where to put the config file the initscript/systemd pulls it's dirs from; + defaults to `CMAKE_INSTALL_PREFIX/etc/sysconfig/icinga2` +- `ICINGA2_PLUGINDIR`: The path for the Monitoring Plugins project binaries; defaults to `/usr/lib/nagios/plugins` + +**Build Optimization** +- `ICINGA2_UNITY_BUILD`: Whether to perform a unity build; defaults to `ON`. Note: This requires additional memory and is not advised for building VMs, Docker for Mac and embedded hardware. +- `ICINGA2_LTO_BUILD`: Whether to use link time optimization (LTO); defaults to `OFF` + +**Init System** +- `USE_SYSTEMD=ON|OFF`: Use systemd or a classic SysV initscript; defaults to `OFF` +- `INSTALL_SYSTEMD_SERVICE_AND_INITSCRIPT=ON|OFF` Force install both the systemd service definition file + and the SysV initscript in parallel, regardless of how `USE_SYSTEMD` is set. + Only use this for special packaging purposes and if you know what you are doing. + Defaults to `OFF`. + +**Features:** +- `ICINGA2_WITH_CHECKER`: Determines whether the checker module is built; defaults to `ON` +- `ICINGA2_WITH_COMPAT`: Determines whether the compat module is built; defaults to `ON` +- `ICINGA2_WITH_DEMO`: Determines whether the demo module is built; defaults to `OFF` +- `ICINGA2_WITH_HELLO`: Determines whether the hello module is built; defaults to `OFF` +- `ICINGA2_WITH_LIVESTATUS`: Determines whether the Livestatus module is built; defaults to `ON` +- `ICINGA2_WITH_NOTIFICATION`: Determines whether the notification module is built; defaults to `ON` +- `ICINGA2_WITH_PERFDATA`: Determines whether the perfdata module is built; defaults to `ON` +- `ICINGA2_WITH_TESTS`: Determines whether the unit tests are built; defaults to `ON` + +**MySQL or MariaDB:** + +The following settings can be tuned for the MySQL / MariaDB IDO feature. + +- `ICINGA2_WITH_MYSQL`: Determines whether the MySQL IDO module is built; defaults to `ON` +- `MYSQL_CLIENT_LIBS`: Client implementation used (mysqlclient / mariadbclient); defaults searches for `mysqlclient` and `mariadbclient` +- `MYSQL_INCLUDE_DIR`: Directory containing include files for the mysqlclient; default empty - + checking multiple paths like `/usr/include/mysql` + +See [FindMySQL.cmake](third-party/cmake/FindMySQL.cmake) for the implementation. + +**PostgreSQL:** + +The following settings can be tuned for the PostgreSQL IDO feature. + +- `ICINGA2_WITH_PGSQL`: Determines whether the PostgreSQL IDO module is built; defaults to `ON` +- `PostgreSQL_INCLUDE_DIR`: Top-level directory containing the PostgreSQL include directories +- `PostgreSQL_LIBRARY`: File path to PostgreSQL library : libpq.so (or libpq.so.[ver] file) + +See [FindMySQL.cmake](third-party/cmake/FindPostgreSQL.cmake) for the implementation. + +**Version detection:** + +CMake determines the Icinga 2 version number using `git describe` if the +source directory is contained in a Git repository. Otherwise the version number +is extracted from the [VERSION](VERSION) file. This behavior can be +overridden by creating a file called `icinga-version.h.force` in the source +directory. Alternatively the `-DICINGA2_GIT_VERSION_INFO=OFF` option for CMake +can be used to disable the usage of `git describe`. + + +### Building RPMs + +#### Build Environment on RHEL, CentOS, Fedora, Amazon Linux + +Setup your build environment: +``` +yum -y install rpmdevtools +``` + +#### Build Environment on SuSE/SLES + +SLES: +``` +zypper addrepo http://download.opensuse.org/repositories/devel:tools/SLE_12_SP3/devel:tools.repo +zypper refresh +zypper install rpmdevtools spectool +``` + +OpenSuSE: +``` +zypper addrepo http://download.opensuse.org/repositories/devel:tools/openSUSE_Leap_15.0/devel:tools.repo +zypper refresh +zypper install rpmdevtools spectool +``` + +#### Package Builds + +Prepare the rpmbuild directory tree: +``` +cd $HOME +rpmdev-setuptree +``` + +Copy the icinga2.spec file to `rpmbuild/SPEC` or fetch the latest version: +``` +curl https://raw.githubusercontent.com/Icinga/rpm-icinga2/master/icinga2.spec -o $HOME/rpmbuild/SPECS/icinga2.spec +``` + +> **Note** +> +> The above command builds snapshot packages. Change to the `release` branch +> for release package builds. + +Copy the tarball to `rpmbuild/SOURCES` e.g. by using the `spectool` binary +provided with `rpmdevtools`: +``` +cd $HOME/rpmbuild/SOURCES +spectool -g ../SPECS/icinga2.spec + +cd $HOME/rpmbuild +``` + +Install the build dependencies. Example for CentOS 7: +``` +yum -y install libedit-devel ncurses-devel gcc-c++ libstdc++-devel openssl-devel \ +cmake flex bison boost-devel systemd mysql-devel postgresql-devel httpd \ +selinux-policy-devel checkpolicy selinux-policy selinux-policy-doc +``` + +Note: If you are using Amazon Linux, systemd is not required. + +A shorter way is available using the `yum-builddep` command on RHEL based systems: +``` +yum-builddep SPECS/icinga2.spec +``` + +Build the RPM: +``` +rpmbuild -ba SPECS/icinga2.spec +``` + +#### Additional Hints + +##### SELinux policy module + +The following packages are required to build the SELinux policy module: + +* checkpolicy +* selinux-policy (selinux-policy on CentOS 6, selinux-policy-devel on CentOS 7) +* selinux-policy-doc + +##### RHEL/CentOS 6 + +The RedHat Developer Toolset is required for building Icinga 2 beforehand. +This contains a modern version of flex and a C++ compiler which supports +C++11 features. +``` +cat >/etc/yum.repos.d/devtools-2.repo <$HOME/.rpmmacros < **WARNING:** This information is outdated! + +Setup your build environment on Debian/Ubuntu, copy the 'debian' directory from +the Debian packaging Git repository (https://github.com/Icinga/deb-icinga2) +into your source tree and run the following command: +``` +$ dpkg-buildpackage -uc -us +``` + +## Build Alpine Linux packages + +A simple way to setup a build environment is installing Alpine in a chroot. +In this way, you can set up an Alpine build environment in a chroot under a +different Linux distro. +There is a script that simplifies these steps with just two commands, and +can be found [here](https://github.com/alpinelinux/alpine-chroot-install). + +Once the build environment is installed, you can setup the system to build +the packages by following [this document](https://wiki.alpinelinux.org/wiki/Creating_an_Alpine_package). + +# Build Post Install Tasks + +After building Icinga 2 yourself, your package build system should at least run the following post +install requirements: + +* enable the `checker`, `notification` and `mainlog` feature by default +* run 'icinga2 api setup' in order to enable the `api` feature and generate SSL certificates for the node + +## Run Icinga 2 + +Icinga 2 comes with a binary that takes care of loading all the relevant +components (e.g. for check execution, notifications, etc.): +``` +# icinga2 daemon +[2016-12-08 16:44:24 +0100] information/cli: Icinga application loader (version: v2.5.4-231-gb10a6b7; debug) +[2016-12-08 16:44:24 +0100] information/cli: Loading configuration file(s). +[2016-12-08 16:44:25 +0100] information/ConfigItem: Committing config item(s). +... +``` + +### Init Script + +Icinga 2 can be started as a daemon using the provided init script: +``` +# /etc/init.d/icinga2 +Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} +``` + +### Systemd + +If your distribution uses Systemd: +``` +# systemctl {start|stop|reload|status|enable|disable} icinga2 +``` + +In case the distribution is running Systemd >227, you'll also +need to package and install the `etc/initsystem/icinga2.service.limits.conf` +file into `/etc/systemd/system/icinga2.service.d`. + +### openrc + +Or if your distribution uses openrc (like Alpine): +``` +# rc-service icinga2 +Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} + ``` + +Note: the openrc's init.d is not shipped by default. +A working init.d with openrc can be found here: (https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd). If you have customized some path, edit the file and adjust it according with your setup. +Those few steps can be followed: +``` +# wget https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd +# mv icinga2.initd /etc/init.d/icinga2 +# chmod +x /etc/init.d/icinga2 +``` + +Icinga 2 reads a single configuration file which is used to specify all +configuration settings (global settings, hosts, services, etc.). The +configuration format is explained in detail in the [doc/](doc/) directory. + +By default `make install` installs example configuration files in +`/usr/local/etc/icinga2` unless you have specified a different prefix or +sysconfdir. + + +### Windows + +The Windows MSI packages are located at https://packages.icinga.com/windows/ + +#### Requirements + +* 32 or 64-bit system +* Visual Studio >= 14 2015 +* CMake >= 2.6 +* OpenSSL >= 1.0.1 +* Flex and Bison + +##### Visual Studio + +Download the community edition from [visualstudio.com](https://www.visualstudio.com/en/downloads/) + +Workloads to install: +* C++ Desktop +* .NET Desktop + +##### OpenSSL for Icinga + +Download custom OpenSSL builds from [openssl-windows GitHub project](https://github.com/Icinga/openssl-windows/releases). + +You need to install a binary dist version to 'C:\\Program Files\\OpenSSL'. + +The Powershell script `.\tools\win32\download-openssl.ps1` can be used for automated downloads. + +##### Chocolatey + +A simple package manager for Windows, please see [install instructions](https://chocolatey.org/install). + +##### Git + +Use Chocolatey, see [package details](https://chocolatey.org/packages/git). + +``` +choco install git +``` + +##### Flex / Bison + +Use Chocolatey, see [package details](https://chocolatey.org/packages/winflexbison3). + +``` +choco install winflexbison3 +``` + +##### CMake + +Use Chocolatey, see [package details](https://chocolatey.org/packages/cmake) +or download from: [cmake.org](https://cmake.org/download/) + +``` +choco install cmake +``` + +##### WIX + +Use Chocolatey, see [package details](https://chocolatey.org/packages/wixtoolset). + +``` +choco install wixtoolset +``` + +##### Boost + +Download third party Windows binaries from: [boost.org](http://www.boost.org/users/download/) + +For example: `https://dl.bintray.com/boostorg/release/1.65.1/binaries/boost_1_65_1-msvc-14.1-64.exe` + +*Warning:* +* Must match your Visual Studio version! +* CMake might not support the latest Boost version (we used CMake 3.10 and Boost 1_65_1) + +Run the installer exe. + + +#### Build Icinga 2 + +Run with VC Native x64 Command Prompt: + +``` +powershell .\tools\win32\configure.ps1 +powershell .\tools\win32\build.ps1 +powershell .\tools\win32\test.ps1 +``` + +See these scripts for details. + +#### CI: AppVeyor + +We are building [Icinga 2 with AppVeyor](https://ci.appveyor.com/project/icinga/icinga2) for testing and CI integration. + +Please check `appveyor.yml` for instructions. + + + +## Advanced Development Tips + +### GDB Pretty Printers Install the `boost`, `python` and `icinga2` pretty printers. Absolute paths are required, so please make sure to update the installation paths accordingly (`pwd`). @@ -118,217 +1444,20 @@ the duplicate import in your `~/.gdbinit` file. RuntimeError: pretty-printer already registered: libstdc++-v6 -### GDB Run -Call GDB with the binary (`/usr/sbin/icinga2` is a wrapper script calling -`/usr/lib64/icinga2/sbin/icinga2` since 2.4) and all arguments and run it in foreground. +## Development Tests - # gdb --args /usr/lib64/icinga2/sbin/icinga2 daemon -x debug --no-stack-rlimit +Build the binaries and run the tests. -The exact path to the Icinga 2 binary differs on each distribution. On Ubuntu -it is installed into `/usr/lib/x86_64-linux-gnu/icinga2/sbin/icinga2` on 64-bit systems -for example. - -> **Note** -> -> If gdb tells you it's missing debug symbols, quit gdb and install -> them: `Missing separate debuginfos, use: debuginfo-install ...` - -Run the application. - - (gdb) r - -Kill the running application. - - (gdb) k - -Continue after breakpoint. - - (gdb) c - -### GDB Core Dump - -Either attach to the running process using `gdb -p PID` or start -a new gdb run. - - (gdb) r - (gdb) generate-core-file - -### GDB Backtrace - -If Icinga 2 aborted its operation abnormally, generate a backtrace. - - (gdb) bt - (gdb) thread apply all bt full - -If gdb stops at a SIGPIPE signal please disable the signal before -running Icinga 2. - - (gdb) handle SIGPIPE nostop noprint pass - (gdb) r - -If you create a [new issue](https://github.com/Icinga/icinga2/issues), -make sure to attach as much detail as possible. - -### GDB Backtrace from Running Process - -If Icinga 2 is still running, generate a full backtrace from the running -process and store it into a new file (e.g. for debugging dead locks): - -Icinga 2 runs with 2 processes, therefore generate two backtrace logs -and add them to the GitHub issue. ``` -for pid in $(pidof icinga2); do gdb -p $pid -batch -ex "thread apply all bt full" -ex "detach" -ex "q" > gdb_bt_${pid}_`date +%s`.log; done +make -j4 -C debug +make test -C debug ``` -### GDB Thread List from Running Process - -Instead of a full backtrace, you sometimes just need a list of running threads. +Run a specific boost test: ``` -for pid in $(pidof icinga2); do gdb -p $pid -batch -ex "info threads" -ex "detach" -ex "q" > gdb_threads_${pid}_`date +%s`.log; done +debug/Bin/Debug/boosttest-test-base --run_test=remote_url ``` -### GDB Backtrace Stepping - -Identifying the problem may require stepping into the backtrace, analysing -the current scope, attributes, and possible unmet requirements. `p` prints -the value of the selected variable or function call result. - - (gdb) up - (gdb) down - (gdb) p checkable - (gdb) p checkable.px->m_Name - - -### GDB Breakpoints - -To set a breakpoint to a specific function call, or file specific line. - - (gdb) b checkable.cpp:125 - (gdb) b icinga::Checkable::SetEnablePerfdata - -GDB will ask about loading the required symbols later, select `yes` instead -of `no`. - -Then run Icinga 2 until it reaches the first breakpoint. Continue with `c` -afterwards. - - (gdb) run - (gdb) c - -If you want to delete all breakpoints, use `d` and select `yes`. - - (gdb) d - -> **Tip** -> -> When debugging exceptions, set your breakpoint like this: `b __cxa_throw`. - -Breakpoint Example: - - (gdb) b __cxa_throw - (gdb) r - (gdb) up - .... - (gdb) up - #11 0x00007ffff7cbf9ff in icinga::Utility::GlobRecursive(icinga::String const&, icinga::String const&, boost::function const&, int) (path=..., pattern=..., callback=..., type=1) - at /home/michi/coding/icinga/icinga2/lib/base/utility.cpp:609 - 609 callback(cpath); - (gdb) l - 604 - 605 #endif /* _WIN32 */ - 606 - 607 std::sort(files.begin(), files.end()); - 608 BOOST_FOREACH(const String& cpath, files) { - 609 callback(cpath); - 610 } - 611 - 612 std::sort(dirs.begin(), dirs.end()); - 613 BOOST_FOREACH(const String& cpath, dirs) { - (gdb) p files - $3 = std::vector of length 11, capacity 16 = {{static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/agent.conf"}, {static NPos = 18446744073709551615, - m_Data = "/etc/icinga2/conf.d/commands.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/downtimes.conf"}, {static NPos = 18446744073709551615, - m_Data = "/etc/icinga2/conf.d/groups.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/notifications.conf"}, {static NPos = 18446744073709551615, - m_Data = "/etc/icinga2/conf.d/satellite.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/services.conf"}, {static NPos = 18446744073709551615, - m_Data = "/etc/icinga2/conf.d/templates.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/test.conf"}, {static NPos = 18446744073709551615, - m_Data = "/etc/icinga2/conf.d/timeperiods.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/users.conf"}} - - -## Core Dump - -When the Icinga 2 daemon crashes with a `SIGSEGV` signal -a core dump file should be written. This will help -developers to analyze and fix the problem. - -### Core Dump File Size Limit - -This requires setting the core dump file size to `unlimited`. - -Example for Systemd: - - vim /usr/lib/systemd/system/icinga2.service - - [Service] - ... - LimitCORE=infinity - - systemctl daemon-reload - - systemctl restart icinga2 - -Example for init script: - - vim /etc/init.d/icinga2 - ... - ulimit -c unlimited - - service icinga2 restart - -Verify that the Icinga 2 process core file size limit is set to `unlimited`. - - cat /proc/`pidof icinga2`/limits - ... - Max core file size unlimited unlimited bytes - - -### Core Dump Kernel Format - -The Icinga 2 daemon runs with the SUID bit set. Therefore you need -to explicitly enable core dumps for SUID on Linux. - - sysctl -w fs.suid_dumpable=1 - -Adjust the coredump kernel format and file location on Linux: - - sysctl -w kernel.core_pattern=/var/lib/cores/core.%e.%p - - install -m 1777 -d /var/lib/cores - -MacOS: - - sysctl -w kern.corefile=/cores/core.%P - - chmod 777 /cores - -### Core Dump Analysis - -Once Icinga 2 crashes again a new coredump file will be written. Please -attach this file to your bug report in addition to the general details. - -Simple test case for a `SIGSEGV` simulation with `sleep`: - - ulimit -c unlimited - sleep 1800& - [1] - kill -SEGV - gdb `which sleep` /var/lib/cores/core.sleep. - (gdb) bt - rm /var/lib/cores/core.sleep.* - -Analyzing Icinga 2: - - gdb /usr/lib64/icinga2/sbin/icinga2 core.icinga2. - (gdb) bt - From 0fa9947561a759cef8a4dfeb2f0a6f41225e6347 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 3 Dec 2018 09:49:42 +0100 Subject: [PATCH 36/62] Docs: Delete extra docs for windows builds This should be visible in icinga.com/docs, no extra docs needed. (cherry picked from commit c6fc144102eada72ff8146f4be00fd48ceb0d423) --- BUILD_WINDOWS.md | 103 ----------------------------------------------- 1 file changed, 103 deletions(-) delete mode 100644 BUILD_WINDOWS.md diff --git a/BUILD_WINDOWS.md b/BUILD_WINDOWS.md deleted file mode 100644 index 28e75259e..000000000 --- a/BUILD_WINDOWS.md +++ /dev/null @@ -1,103 +0,0 @@ -# Build Icinga 2 on Windows - -The Icinga Project is providing Windows MSI packages under https://packages.icinga.com/windows/ - -> **Note:** -> This is a developer documentation on how to build Icinga 2 on Windows! - -Also see [INSTALL.md](INSTALL.md) for Linux build instructions. - -## Requirements - -* 32 or 64-bit system -* Visual Studio >= 14 2015 -* CMake >= 2.6 -* OpenSSL >= 1.0.1 -* Flex and Bison - -## Install Requirements - -**Visual Studio** - -Download from [visualstudio.com](https://www.visualstudio.com/en/downloads/) - -The Community Edition is available for free, and is what we use to build. - -Workloads to install: -* C++ Desktop -* .NET Desktop - -**OpenSSL for Icinga** - -See our [openssl-windows GitHub project](https://github.com/Icinga/openssl-windows). - -You will need to install a binary dist version to 'C:\\Program Files\\OpenSSL'. - -There is a Powershell script to help you downloading: `.\tools\win32\download-openssl.ps1` - -**Chocolatey** - -A simple package manager for Windows, please see [install instructions](https://chocolatey.org/install). - -**Git** - -Best to use Chocolatey, see [package details](https://chocolatey.org/packages/git). - -``` -choco install git -``` - -**Flex / Bison** - -Best to use Chocolatey, see [package details](https://chocolatey.org/packages/winflexbison3). - -``` -choco install winflexbison3 -``` - -**CMake** - -Best to use Chocolatey, see [package details](https://chocolatey.org/packages/cmake) -or download from: [cmake.org](https://cmake.org/download/) - -``` -choco install cmake -``` - -**WIX** - -Best to use Chocolatey, see [package details](https://chocolatey.org/packages/wixtoolset). - -``` -choco install wixtoolset -``` - -**Boost** - -Download third party Windows binaries from: [boost.org](http://www.boost.org/users/download/) - -For example: `https://dl.bintray.com/boostorg/release/1.65.1/binaries/boost_1_65_1-msvc-14.1-64.exe` - -*Warnings:* -* Must match your Visual Studio version! -* CMake might not support the latest Boost version (we used CMake 3.10 and Boost 1_65_1) - -Run the installer exe. - -## Build Icinga 2 - -Run with VC Native x64 Command Prompt: - -``` -powershell .\tools\win32\configure.ps1 -powershell .\tools\win32\build.ps1 -powershell .\tools\win32\test.ps1 -``` - -See these scripts for details. - -## AppVeyor - -We are building [Icinga 2 with AppVeyor](https://ci.appveyor.com/project/icinga/icinga2) for testing and CI integration. - -Please check `appveyor.yml` for our instructions. From 8f3c97dfef2b4ddd9e69a022dc685017474d3a6c Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 3 Dec 2018 09:50:39 +0100 Subject: [PATCH 37/62] Docs: Simplify INSTALL.md and point to icinga.com/docs (cherry picked from commit 3827e15c4abf49b4ecdbd23d36e76cb4fdab67a0) --- INSTALL.md | 396 +---------------------------------------------------- 1 file changed, 2 insertions(+), 394 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index e0573e0ec..d6121e999 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -16,398 +16,6 @@ not use the official packages it is advisable to build your own Debian or RPM packages. You can use the source packages from [packages.icinga.com](https://packages.icinga.com) for this purpose. -> **Disclaimer** -> -> This information is intended for developers and packagers. It might be incomplete or unclear -> in some cases. Ensure to check our [packaging scripts on GitHub](https://github.com/Icinga/icinga-packaging) too! +For a more detailed introduction into developing Icinga and building +packages, please visit the [online documentation](https://icinga.com/docs/icinga2/latest/doc/21-development/). -# Build Requirements - -The following requirements need to be fulfilled in order to build the -application using a dist tarball (including notes for distributions): - -* cmake >= 2.6 -* GNU make (make) or ninja-build -* C++ compiler which supports C++11 - - RHEL/Fedora/SUSE: gcc-c++ >= 4.7 (extra Developer Tools on RHEL5/6 see below) - - Debian/Ubuntu: build-essential - - Alpine: build-base - - you can also use clang++ -* pkg-config -* OpenSSL library and header files >= 1.0.1 - - RHEL/Fedora: openssl-devel - - SUSE: libopenssl-devel (for SLES 11: libopenssl1-devel) - - Debian/Ubuntu: libssl-dev - - Alpine: libressl-dev -* Boost library and header files >= 1.48.0 - - RHEL/Fedora: boost148-devel - - Debian/Ubuntu: libboost-all-dev - - Alpine: boost-dev -* GNU bison (bison) -* GNU flex (flex) >= 2.5.35 -* Systemd headers - - Only required when using Systemd - - Debian/Ubuntu: libsystemd-dev - - RHEL/Fedora: systemd-devel - -## Optional features - -* MySQL (disable with CMake variable `ICINGA2_WITH_MYSQL` to `OFF`) - - RHEL/Fedora: mysql-devel - - SUSE: libmysqlclient-devel - - Debian/Ubuntu: default-libmysqlclient-dev | libmysqlclient-dev - - Alpine: mariadb-dev -* PostgreSQL (disable with CMake variable `ICINGA2_WITH_PGSQL` to `OFF`) - - RHEL/Fedora: postgresql-devel - - Debian/Ubuntu: libpq-dev - - postgresql-dev on Alpine -* YAJL (Faster JSON library) - - RHEL/Fedora: yajl-devel - - Debian: libyajl-dev - - Alpine: yajl-dev -* libedit (CLI console) - - RHEL/Fedora: libedit-devel on CentOS (RHEL requires rhel-7-server-optional-rpms) - - Debian/Ubuntu/Alpine: libedit-dev -* Termcap (only required if libedit doesn't already link against termcap/ncurses) - - RHEL/Fedora: libtermcap-devel - - Debian/Ubuntu: (not necessary) - -## Special requirements - -**FreeBSD**: libexecinfo (automatically used when Icinga 2 is installed via port or package) - -**RHEL6**: Requires a newer boost version which is available on packages.icinga.com -with a version suffixed name. - -## Runtime user environment - -By default Icinga will run as user `icinga` and group `icinga`. Additionally the -external command pipe and livestatus features require a dedicated command group -`icingacmd`. You can choose your own user/group names and pass them to CMake -using the `ICINGA2_USER`, `ICINGA2_GROUP` and `ICINGA2_COMMAND_GROUP` variables. - -``` -# groupadd icinga -# groupadd icingacmd -# useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga -``` - -On Alpine (which uses ash busybox) you can run: - -``` -# addgroup -S icinga -# addgroup -S icingacmd -# adduser -S -D -H -h /var/spool/icinga2 -s /sbin/nologin -G icinga -g icinga icinga -# adduser icinga icingacmd -``` - -Add the web server user to the icingacmd group in order to grant it write -permissions to the external command pipe and livestatus socket: -``` -# usermod -a -G icingacmd www-data -``` - -Make sure to replace "www-data" with the name of the user your web server -is running as. - -# Building Icinga 2 - -Once you have installed all the necessary build requirements you can build -Icinga 2 using the following commands: - -``` -$ mkdir release && cd release -$ cmake .. -$ cd .. -$ make -C release -$ make install -C release -``` - -You can specify an alternative installation prefix using `-DCMAKE_INSTALL_PREFIX`: - -``` -$ cmake .. -DCMAKE_INSTALL_PREFIX=/tmp/icinga2 -``` - -## CMake Variables - -In addition to `CMAKE_INSTALL_PREFIX` here are most of the supported Icinga-specific cmake variables. - -For all variables regarding defaults paths on in CMake, see -[GNUInstallDirs](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html). - -Also see `CMakeLists.txt` for details. - -**System Environment** -- `CMAKE_INSTALL_SYSCONFDIR`: The configuration directory; defaults to `CMAKE_INSTALL_PREFIX/etc` -- `CMAKE_INSTALL_LOCALSTATEDIR`: The state directory; defaults to `CMAKE_INSTALL_PREFIX/var` -- `ICINGA2_CONFIGDIR`: Main config directory; defaults to `CMAKE_INSTALL_SYSCONFDIR/icinga2` usually `/etc/icinga2` -- `ICINGA2_CACHEDIR`: Directory for cache files; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/cache/icinga2` usually `/var/cache/icinga2` -- `ICINGA2_DATADIR`: Data directory for the daemon; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/lib/icinga2` usually `/var/lib/icinga2` -- `ICINGA2_LOGDIR`: Logfiles of the daemon; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/log/icinga2 usually `/var/log/icinga2` -- `ICINGA2_SPOOLDIR`: Spooling directory ; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/spool/icinga2` usually `/var/spool/icinga2` -- `ICINGA2_INITRUNDIR`: Runtime data for the init system; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/run/icinga2` usually `/run/icinga2` -- `ICINGA2_GIT_VERSION_INFO`: Whether to use Git to determine the version number; defaults to `ON` -- `ICINGA2_USER`: The user Icinga 2 should run as; defaults to `icinga` -- `ICINGA2_GROUP`: The group Icinga 2 should run as; defaults to `icinga` -- `ICINGA2_COMMAND_GROUP`: The command group Icinga 2 should use; defaults to `icingacmd` -- `ICINGA2_SYSCONFIGFILE`: Where to put the config file the initscript/systemd pulls it's dirs from; - defaults to `CMAKE_INSTALL_PREFIX/etc/sysconfig/icinga2` -- `ICINGA2_PLUGINDIR`: The path for the Monitoring Plugins project binaries; defaults to `/usr/lib/nagios/plugins` - -**Build Optimization** -- `ICINGA2_UNITY_BUILD`: Whether to perform a unity build; defaults to `ON`. Note: This requires additional memory and is not advised for building VMs, Docker for Mac and embedded hardware. -- `ICINGA2_LTO_BUILD`: Whether to use link time optimization (LTO); defaults to `OFF` - -**Init System** -- `USE_SYSTEMD=ON|OFF`: Use systemd or a classic SysV initscript; defaults to `OFF` -- `INSTALL_SYSTEMD_SERVICE_AND_INITSCRIPT=ON|OFF` Force install both the systemd service definition file - and the SysV initscript in parallel, regardless of how `USE_SYSTEMD` is set. - Only use this for special packaging purposes and if you know what you are doing. - Defaults to `OFF`. - -**Features:** -- `ICINGA2_WITH_CHECKER`: Determines whether the checker module is built; defaults to `ON` -- `ICINGA2_WITH_COMPAT`: Determines whether the compat module is built; defaults to `ON` -- `ICINGA2_WITH_DEMO`: Determines whether the demo module is built; defaults to `OFF` -- `ICINGA2_WITH_HELLO`: Determines whether the hello module is built; defaults to `OFF` -- `ICINGA2_WITH_LIVESTATUS`: Determines whether the Livestatus module is built; defaults to `ON` -- `ICINGA2_WITH_NOTIFICATION`: Determines whether the notification module is built; defaults to `ON` -- `ICINGA2_WITH_PERFDATA`: Determines whether the perfdata module is built; defaults to `ON` -- `ICINGA2_WITH_TESTS`: Determines whether the unit tests are built; defaults to `ON` - -**MySQL or MariaDB:** - -The following settings can be tuned for the MySQL / MariaDB IDO feature. - -- `ICINGA2_WITH_MYSQL`: Determines whether the MySQL IDO module is built; defaults to `ON` -- `MYSQL_CLIENT_LIBS`: Client implementation used (mysqlclient / mariadbclient); defaults searches for `mysqlclient` and `mariadbclient` -- `MYSQL_INCLUDE_DIR`: Directory containing include files for the mysqlclient; default empty - - checking multiple paths like `/usr/include/mysql` - -See [FindMySQL.cmake](third-party/cmake/FindMySQL.cmake) for the implementation. - -**PostgreSQL:** - -The following settings can be tuned for the PostgreSQL IDO feature. - -- `ICINGA2_WITH_PGSQL`: Determines whether the PostgreSQL IDO module is built; defaults to `ON` -- `PostgreSQL_INCLUDE_DIR`: Top-level directory containing the PostgreSQL include directories -- `PostgreSQL_LIBRARY`: File path to PostgreSQL library : libpq.so (or libpq.so.[ver] file) - -See [FindMySQL.cmake](third-party/cmake/FindPostgreSQL.cmake) for the implementation. - -**Version detection:** - -CMake determines the Icinga 2 version number using `git describe` if the -source directory is contained in a Git repository. Otherwise the version number -is extracted from the [VERSION](VERSION) file. This behavior can be -overridden by creating a file called `icinga-version.h.force` in the source -directory. Alternatively the `-DICINGA2_GIT_VERSION_INFO=OFF` option for CMake -can be used to disable the usage of `git describe`. - -# Building packages - -> **WARNING:** Some of this information is outdated! - -## Building RPMs - -### Build Environment on RHEL, CentOS, Fedora, Amazon Linux - -Setup your build environment: -``` -yum -y install rpmdevtools -``` - -### Build Environment on SuSE/SLES - -SLES: -``` -zypper addrepo http://download.opensuse.org/repositories/devel:tools/SLE_12_SP2/devel:tools.repo -zypper refresh -zypper install rpmdevtools spectool -``` - -OpenSuSE: -``` -zypper addrepo http://download.opensuse.org/repositories/devel:tools/openSUSE_Leap_42.3/devel:tools.repo -zypper refresh -zypper install rpmdevtools spectool -``` - -### Package Builds - -Prepare the rpmbuild directory tree: -``` -cd $HOME -rpmdev-setuptree -``` - -Copy the icinga2.spec file to `rpmbuild/SPEC` or fetch the latest version: -``` -curl https://raw.githubusercontent.com/Icinga/rpm-icinga2/master/icinga2.spec -o $HOME/rpmbuild/SPECS/icinga2.spec -``` - -> **Note** -> -> The above command builds snapshot packages. Change to the `release` branch -> for release package builds. - -Copy the tarball to `rpmbuild/SOURCES` e.g. by using the `spectool` binary -provided with `rpmdevtools`: -``` -cd $HOME/rpmbuild/SOURCES -spectool -g ../SPECS/icinga2.spec - -cd $HOME/rpmbuild -``` - -Install the build dependencies. Example for CentOS 7: -``` -yum -y install libedit-devel ncurses-devel gcc-c++ libstdc++-devel openssl-devel \ -cmake flex bison boost-devel systemd mysql-devel postgresql-devel httpd \ -selinux-policy-devel checkpolicy selinux-policy selinux-policy-doc -``` - -Note: If you are using Amazon Linux, systemd is not required. - -A shorter way is available using the `yum-builddep` command on RHEL based systems: -``` -yum-builddep SPECS/icinga2.spec -``` - -Build the RPM: -``` -rpmbuild -ba SPECS/icinga2.spec -``` - -### Additional Hints - -#### SELinux policy module - -The following packages are required to build the SELinux policy module: - -* checkpolicy -* selinux-policy (selinux-policy on CentOS 6, selinux-policy-devel on CentOS 7) -* selinux-policy-doc - -#### RHEL/CentOS 6 - -The RedHat Developer Toolset is required for building Icinga 2 beforehand. -This contains a modern version of flex and a C++ compiler which supports -C++11 features. -``` -cat >/etc/yum.repos.d/devtools-2.repo <$HOME/.rpmmacros < **WARNING:** This information is outdated! - -Setup your build environment on Debian/Ubuntu, copy the 'debian' directory from -the Debian packaging Git repository (https://github.com/Icinga/deb-icinga2) -into your source tree and run the following command: -``` -$ dpkg-buildpackage -uc -us -``` - -## Build Alpine Linux packages - -A simple way to setup a build environment is installing Alpine in a chroot. -In this way, you can set up an Alpine build environment in a chroot under a -different Linux distro. -There is a script that simplifies these steps with just two commands, and -can be found [here](https://github.com/alpinelinux/alpine-chroot-install). - -Once the build environment is installed, you can setup the system to build -the packages by following [this document](https://wiki.alpinelinux.org/wiki/Creating_an_Alpine_package). - -# Build Post Install Tasks - -After building Icinga 2 yourself, your package build system should at least run the following post -install requirements: - -* enable the `checker`, `notification` and `mainlog` feature by default -* run 'icinga2 api setup' in order to enable the `api` feature and generate SSL certificates for the node - -## Run Icinga 2 - -Icinga 2 comes with a binary that takes care of loading all the relevant -components (e.g. for check execution, notifications, etc.): -``` -# icinga2 daemon -[2016-12-08 16:44:24 +0100] information/cli: Icinga application loader (version: v2.5.4-231-gb10a6b7; debug) -[2016-12-08 16:44:24 +0100] information/cli: Loading configuration file(s). -[2016-12-08 16:44:25 +0100] information/ConfigItem: Committing config item(s). -... -``` - -### Init Script - -Icinga 2 can be started as a daemon using the provided init script: -``` -# /etc/init.d/icinga2 -Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} -``` - -### Systemd - -If your distribution uses Systemd: -``` -# systemctl {start|stop|reload|status|enable|disable} icinga2 -``` - -In case the distribution is running Systemd >227, you'll also -need to package and install the `etc/initsystem/icinga2.service.limits.conf` -file into `/etc/systemd/system/icinga2.service.d`. - -### openrc - -Or if your distribution uses openrc (like Alpine): -``` -# rc-service icinga2 -Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} - ``` - -Note: the openrc's init.d is not shipped by default. -A working init.d with openrc can be found here: (https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd). If you have customized some path, edit the file and adjust it according with your setup. -Those few steps can be followed: -``` -# wget https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd -# mv icinga2.initd /etc/init.d/icinga2 -# chmod +x /etc/init.d/icinga2 -``` - -Icinga 2 reads a single configuration file which is used to specify all -configuration settings (global settings, hosts, services, etc.). The -configuration format is explained in detail in the [doc/](doc/) directory. - -By default `make install` installs example configuration files in -`/usr/local/etc/icinga2` unless you have specified a different prefix or -sysconfdir. From 5dbc9dc0e83ae693dd9d45019fba2a02efc380d2 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 3 Dec 2018 11:11:16 +0100 Subject: [PATCH 38/62] Docs: More updates on dev environments, add mini TOC (cherry picked from commit ec39a74453f673032cd52edb29eb747d80cb5fe9) --- doc/21-development.md | 297 +++++++++++++++++++++++++++++++++++------- 1 file changed, 250 insertions(+), 47 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index 1ff183434..ff672fe1e 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -1,7 +1,17 @@ # Development -This chapter provides hints on Icinga 2 development -and debugging. +This chapter provides hints on Icinga 2 debugging, +development, package builds and tests. + +* [Debug Icinga 2](#development-debug) +* [Develop Icinga 2](#development-develop) + * [Linux Dev Environment](#development-linux-dev-env) + * [macOS Dev Environment](#development-macos-dev-env) + * [Windows Dev Environment](#development-windows-dev-env) +* [Package Builds](#development-package-builds) +* [Advanced Tips](#development-advanced) +* [Tests](#development-tests) + ## Debug Icinga 2 @@ -348,6 +358,13 @@ In order to run Icinga 2 with LLDB you need to pass the binary as argument. lldb -- /usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon ``` +Breakpoint: + +``` +> b checkable.cpp:57 +> b icinga::Checkable::ProcessCheckResult +``` + Full backtrace: ``` @@ -494,6 +511,8 @@ db\_ido\_pgsql | IDO database driver for PgSQL. mysql\_shin | Library stub for linking against the MySQL client libraries. pgsql\_shim | Library stub for linking against the PgSQL client libraries. +#### Class Compiler + Another thing you will recognize are the `.ti` files which are compiled by our own class compiler into actual source code. The meta language allows developers to easily add object attributes and specify their behaviour. @@ -570,7 +589,7 @@ stuff like `epoll` is not available on Unix kernels. Depending on your workstation and environment, you may either develop and run locally, use a container deployment pipeline or put everything in a high end resource remote VM. -#### Prepare Linux Dev Environment +Fork https://github.com/Icinga/icinga2 into your own repository, e.g. `https://github.com/dnsmichi/icinga2`. Create two build directories for different binary builds. @@ -581,25 +600,55 @@ Create two build directories for different binary builds. mkdir -p release debug ``` -Next, check the required packages to build Icinga 2, and install them. +Proceed with the specific distribution examples below. -CentOS: +* [CentOS 7](#development-linux-dev-env-centos) +* [Debian 9](#development-linux-dev-env-debian) + +#### CentOS 7 + +``` +yum -y install gdb git bash-completion htop rpmdevtools \ + ccache cmake make gcc-c++ flex bison \ + openssl-devel boost-devel systemd-devel mysql-devel \ + postgresql-devel libedit-devel libstdc++-devel + +groupadd icinga +groupadd icingacmd +useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga + +ln -s /bin/ccache /usr/local/bin/gcc +ln -s /bin/ccache /usr/local/bin/g++ + +git clone https://github.com/icinga/icinga2.git && cd icinga2 + +mkdir debug release +cd debug +cmake .. -DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF -DCMAKE_INSTALL_PREFIX=/usr/local/icinga2 -DICINGA2_PLUGINDIR=/usr/local/sbin +cd .. +make -j2 install -C debug +``` + + +``` +chown -R icinga:icinga /usr/local/icinga2/var/ + +/usr/local/icinga2/lib/icinga2/prepare-dirs /usr/local/icinga2/etc/sysconfig/icinga2 +/usr/local/icinga2/sbin/icinga2 api setup +vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf + +gdb --args /usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon ``` ``` -Debian/Ubuntu: - -``` - -``` - -##### Debian Stretch +##### Debian 9 ``` apt-get -y install gdb vim git cmake make ccache build-essential libssl-dev libboost-all-dev bison flex default-libmysqlclient-dev libpq-dev libyajl-dev libedit-dev monitoring-plugins +ln -s /usr/bin/ccache /usr/local/bin/gcc ln -s /usr/bin/ccache /usr/local/bin/g++ groupadd icinga @@ -619,31 +668,154 @@ make -j2 install -C debug ``` chown -R icinga:icinga /usr/local/icinga2/var/ -cd /usr/local/icinga2 -./lib/icinga2/prepare-dirs etc/sysconfig/icinga2 -icinga2 api setup -vim etc/icinga2/conf.d/api-users.conf +/usr/local/icinga2/lib/icinga2/prepare-dirs /usr/local/icinga2/etc/sysconfig/icinga2 +/usr/local/icinga2/sbin/icinga2 api setup +vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf -gdb --args ./lib/icinga2/sbin/icinga2 daemon +gdb --args /usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon ``` ### macOS Dev Environment -It is advised to use Homebrew to install all required build dependencies. +It is advised to use Homebrew to install required build dependencies. Macports have been reported to work as well, typically you'll get more help -with Homebrew. +with Homebrew from Icinga developers. -We will also build two different flavors. +#### Users and Groups + +First off, create the following from `Settings - Users & Groups`: + +* Users: `icinga` +* Groups: `icinga` with `icinga` as member +* Groups: `icingaweb2` + +Then disallow login for these users. + +``` +dscl +list Local/Default/Users +read Local/Default/Users/icinga +change Local/Default/Users/icinga UserShell /bin/bash /usr/bin/false +sudo dscl . create /Users/icinga IsHidden 1 +sudo dseditgroup -o edit -a _www -t user icingaweb2 +``` + +#### Requirements + +OpenSSL 1.0.x doesn't build anymore, so we're explicitly using 1.1.x here. + +``` +brew install ccache boost cmake bison flex yajl openssl@1.1 mysql-connector-c++ postgresql libpq +``` + +##### ccache + +``` +sudo mkdir /opt/ccache + +sudo ln -s `which ccache` /opt/ccache/clang +sudo ln -s `which ccache` /opt/ccache/clang++ + +vim $HOME/.bashrc + +# ccache is managed with symlinks to avoid collision with cgo +export PATH="/opt/ccache:$PATH" + +source $HOME/.bashrc +``` + +#### Builds + +We will build two different flavors on macOS. ``` mkdir -p release debug + +cd debug +cmake -DICINGA2_UNITY_BUILD=OFF -DICINGA2_WITH_STUDIO=ON -DCMAKE_INSTALL_PREFIX=/usr/local/icinga2 -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@1.1/include -DOPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.dylib -DOPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.dylib .. +cd .. + +make -j4 -C debug +sudo make -j4 install -C debug +``` + +##### Build Aliases + +This is derived from dnsmichi's flavour and not generally best practice. + +``` +vim $HOME/.bashrc + +export PATH=/usr/local/icinga2/sbin/:$PATH +source /usr/local/icinga2/etc/bash_completion.d/icinga2 + +export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga2 -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@1.1/include -DOPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.dylib -DOPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.dylib -DICINGA2_PLUGINDIR=/usr/local/sbin" + +export I2_DEBUG="-DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF $I2_GENERIC" +export I2_RELEASE="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DICINGA2_WITH_TESTS=ON -DICINGA2_UNITY_BUILD=ON $I2_GENERIC" + +alias i2_debug="mkdir -p debug; cd debug; cmake $I2_DEBUG ..; make -j4; sudo make -j4 install; cd .." +alias i2_release="mkdir -p release; cd release; cmake $I2_RELEASE ..; make -j4; sudo make -j4 install; cd .." + +source $HOME/.bashrc +``` + +#### Run + +``` +chown -R icinga:icinga /usr/local/icinga2 +chown -R icinga:_www /usr/local/icinga2/var/run/icinga2/cmd + +icinga2 daemon +``` + +#### Plugins + +``` +brew install nagios-plugins + +sudo vim /usr/local/icinga2/etc/icinga2/constants.conf +const PluginDir = "/usr/local/sbin" +``` + +#### Databases: MariaDB + +``` +brew install mariadb +ln -sfv /usr/local/opt/mariadb/*.plist ~/Library/LaunchAgents +launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist +mysql_secure_installation +``` + +``` +vim $HOME/.my.cnf + +[client] +user = root +password = supersecurerootpassword + +sudo -i +ln -s /Users/michi/.my.cnf $HOME/.my.cnf +exit +``` + +``` +cd $HOME/coding/icinga/icinga2 + +sudo mysql + +CREATE DATABASE icinga; +GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON icinga.* TO 'icinga'@'localhost' IDENTIFIED BY 'icinga'; +quit +sudo mysql icinga < lib/db_ido_mysql/schema/mysql.sql ``` -### Windows Dev Environment + +### Windows Dev Environment The following sections explain how to setup the required build tools and how to run and debug the code. @@ -791,7 +963,7 @@ Run CMake with the following command. This generates a new Visual Studio project You need to specify the previously installed component paths: Variable | Value | Description -----------------------|----------------------------------------------------------------------| +----------------------|----------------------------------------------------------------------|------------------------------------------------------- BOOST_ROOT | `C:\boost_1_65_1` | Root path where you've extracted and compiled Boost. BISON_EXECUTABLE | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe` | Path to the Bison executable. FLEX_EXECUTABLE | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe` | Path to the Flex executable. @@ -875,7 +1047,9 @@ Again, put these lines into a batch/Powershell script and execute that. > > This isn't officially supported yet, just a few hints how you can do it yourself. -armhf on Raspberry Pi, ccache: +The following examples source from armhf on Raspberry Pi. + +#### ccache ``` apt install -y ccache @@ -887,6 +1061,20 @@ echo 'export PATH="/usr/lib/ccache:$PATH"' | tee -a ~/.bashrc source ~/.bashrc && echo $PATH ``` +#### Build + +Copy the icinga2 source code into `$HOME/icinga2`. Clone the `deb-icinga2` repository into `debian/`. + +``` +git clone https://github.com/Icinga/icinga2 $HOME/icinga2 +git clone https://github.com/Icinga/deb-icinga2 $HOME/icinga2/debian +``` + +Then build a Debian package and install it like normal. +``` +dpkg-buildpackage -uc -us +``` + ## Package Builds This documentation is explicitly meant for packagers and the Icinga @@ -919,7 +1107,7 @@ Icinga application using a dist tarball (including notes for distributions): - Debian/Ubuntu: libsystemd-dev - RHEL/Fedora: systemd-devel -### Optional features +### Optional features * MySQL (disable with CMake variable `ICINGA2_WITH_MYSQL` to `OFF`) - RHEL/Fedora: mysql-devel @@ -941,14 +1129,14 @@ Icinga application using a dist tarball (including notes for distributions): - RHEL/Fedora: libtermcap-devel - Debian/Ubuntu: (not necessary) -### Special requirements +### Special requirements **FreeBSD**: libexecinfo (automatically used when Icinga 2 is installed via port or package) **RHEL6**: Requires a newer boost version which is available on packages.icinga.com with a version suffixed name. -### Runtime user environment +### Runtime user environment By default Icinga will run as user `icinga` and group `icinga`. Additionally the external command pipe and livestatus features require a dedicated command group @@ -972,6 +1160,7 @@ On Alpine (which uses ash busybox) you can run: Add the web server user to the icingacmd group in order to grant it write permissions to the external command pipe and livestatus socket: + ``` # usermod -a -G icingacmd www-data ``` @@ -979,7 +1168,7 @@ permissions to the external command pipe and livestatus socket: Make sure to replace "www-data" with the name of the user your web server is running as. -### Building Icinga 2: Example +### Building Icinga 2: Example Once you have installed all the necessary build requirements you can build Icinga 2 using the following commands: @@ -998,7 +1187,7 @@ You can specify an alternative installation prefix using `-DCMAKE_INSTALL_PREFIX $ cmake .. -DCMAKE_INSTALL_PREFIX=/tmp/icinga2 ``` -### CMake Variables +### CMake Variables In addition to `CMAKE_INSTALL_PREFIX` here are most of the supported Icinga-specific cmake variables. @@ -1076,11 +1265,12 @@ directory. Alternatively the `-DICINGA2_GIT_VERSION_INFO=OFF` option for CMake can be used to disable the usage of `git describe`. -### Building RPMs +### Building RPMs #### Build Environment on RHEL, CentOS, Fedora, Amazon Linux Setup your build environment: + ``` yum -y install rpmdevtools ``` @@ -1088,28 +1278,32 @@ yum -y install rpmdevtools #### Build Environment on SuSE/SLES SLES: + ``` -zypper addrepo http://download.opensuse.org/repositories/devel:tools/SLE_12_SP3/devel:tools.repo +zypper addrepo http://download.opensuse.org/repositories/devel:tools/SLE_12_SP4/devel:tools.repo zypper refresh zypper install rpmdevtools spectool ``` OpenSuSE: + ``` zypper addrepo http://download.opensuse.org/repositories/devel:tools/openSUSE_Leap_15.0/devel:tools.repo zypper refresh zypper install rpmdevtools spectool ``` -#### Package Builds +#### Package Builds Prepare the rpmbuild directory tree: + ``` cd $HOME rpmdev-setuptree ``` -Copy the icinga2.spec file to `rpmbuild/SPEC` or fetch the latest version: +Snapshot builds: + ``` curl https://raw.githubusercontent.com/Icinga/rpm-icinga2/master/icinga2.spec -o $HOME/rpmbuild/SPECS/icinga2.spec ``` @@ -1121,6 +1315,7 @@ curl https://raw.githubusercontent.com/Icinga/rpm-icinga2/master/icinga2.spec -o Copy the tarball to `rpmbuild/SOURCES` e.g. by using the `spectool` binary provided with `rpmdevtools`: + ``` cd $HOME/rpmbuild/SOURCES spectool -g ../SPECS/icinga2.spec @@ -1129,6 +1324,7 @@ cd $HOME/rpmbuild ``` Install the build dependencies. Example for CentOS 7: + ``` yum -y install libedit-devel ncurses-devel gcc-c++ libstdc++-devel openssl-devel \ cmake flex bison boost-devel systemd mysql-devel postgresql-devel httpd \ @@ -1138,16 +1334,18 @@ selinux-policy-devel checkpolicy selinux-policy selinux-policy-doc Note: If you are using Amazon Linux, systemd is not required. A shorter way is available using the `yum-builddep` command on RHEL based systems: + ``` yum-builddep SPECS/icinga2.spec ``` Build the RPM: + ``` rpmbuild -ba SPECS/icinga2.spec ``` -#### Additional Hints +#### Additional Hints ##### SELinux policy module @@ -1182,28 +1380,27 @@ cat >$HOME/.rpmmacros < **WARNING:** This information is outdated! +### Build Debian/Ubuntu packages Setup your build environment on Debian/Ubuntu, copy the 'debian' directory from the Debian packaging Git repository (https://github.com/Icinga/deb-icinga2) into your source tree and run the following command: + ``` $ dpkg-buildpackage -uc -us ``` -## Build Alpine Linux packages +### Build Alpine Linux packages A simple way to setup a build environment is installing Alpine in a chroot. In this way, you can set up an Alpine build environment in a chroot under a @@ -1214,7 +1411,7 @@ can be found [here](https://github.com/alpinelinux/alpine-chroot-install). Once the build environment is installed, you can setup the system to build the packages by following [this document](https://wiki.alpinelinux.org/wiki/Creating_an_Alpine_package). -# Build Post Install Tasks +### Build Post Install Tasks After building Icinga 2 yourself, your package build system should at least run the following post install requirements: @@ -1222,29 +1419,33 @@ install requirements: * enable the `checker`, `notification` and `mainlog` feature by default * run 'icinga2 api setup' in order to enable the `api` feature and generate SSL certificates for the node -## Run Icinga 2 +### Run Icinga 2 Icinga 2 comes with a binary that takes care of loading all the relevant components (e.g. for check execution, notifications, etc.): + ``` -# icinga2 daemon +icinga2 daemon + [2016-12-08 16:44:24 +0100] information/cli: Icinga application loader (version: v2.5.4-231-gb10a6b7; debug) [2016-12-08 16:44:24 +0100] information/cli: Loading configuration file(s). [2016-12-08 16:44:25 +0100] information/ConfigItem: Committing config item(s). ... ``` -### Init Script +#### Init Script Icinga 2 can be started as a daemon using the provided init script: + ``` # /etc/init.d/icinga2 Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} ``` -### Systemd +### Systemd If your distribution uses Systemd: + ``` # systemctl {start|stop|reload|status|enable|disable} icinga2 ``` @@ -1253,9 +1454,10 @@ In case the distribution is running Systemd >227, you'll also need to package and install the `etc/initsystem/icinga2.service.limits.conf` file into `/etc/systemd/system/icinga2.service.d`. -### openrc +### openrc Or if your distribution uses openrc (like Alpine): + ``` # rc-service icinga2 Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} @@ -1264,6 +1466,7 @@ Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} Note: the openrc's init.d is not shipped by default. A working init.d with openrc can be found here: (https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd). If you have customized some path, edit the file and adjust it according with your setup. Those few steps can be followed: + ``` # wget https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd # mv icinga2.initd /etc/init.d/icinga2 @@ -1279,11 +1482,11 @@ By default `make install` installs example configuration files in sysconfdir. -### Windows +### Windows Builds The Windows MSI packages are located at https://packages.icinga.com/windows/ -#### Requirements +#### Requirements * 32 or 64-bit system * Visual Studio >= 14 2015 From 7abed414eab607fc16a77bbe0585e7a14643bbd1 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 3 Dec 2018 11:15:04 +0100 Subject: [PATCH 39/62] Docs: Update anchors (cherry picked from commit ac9ed41537b36d7a41e26e8535e208579cccbfc2) --- doc/21-development.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index ff672fe1e..6bd13e939 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -3,14 +3,14 @@ This chapter provides hints on Icinga 2 debugging, development, package builds and tests. -* [Debug Icinga 2](#development-debug) -* [Develop Icinga 2](#development-develop) - * [Linux Dev Environment](#development-linux-dev-env) - * [macOS Dev Environment](#development-macos-dev-env) - * [Windows Dev Environment](#development-windows-dev-env) -* [Package Builds](#development-package-builds) -* [Advanced Tips](#development-advanced) -* [Tests](#development-tests) +* [Debug Icinga 2](21-development.md#development-debug) +* [Develop Icinga 2](21-development.md#development-develop) + * [Linux Dev Environment](21-development.md#development-linux-dev-env) + * [macOS Dev Environment](21-development.md#development-macos-dev-env) + * [Windows Dev Environment](21-development.md#development-windows-dev-env) +* [Package Builds](21-development.md#development-package-builds) +* [Advanced Tips](21-development.md#development-advanced) +* [Tests](21-development.md#development-tests) ## Debug Icinga 2 @@ -460,7 +460,7 @@ autocmd BufWinLeave * call clearmatches() Icinga 2 can run standalone or in distributed environments. It contains a whole lot more than a simple check execution engine. -Read more about it in the [Technical Concepts](#technical-concepts) chapter. +Read more about it in the [Technical Concepts](19-technical-concepts.md#technical-concepts) chapter. ### Get to know the code @@ -511,7 +511,7 @@ db\_ido\_pgsql | IDO database driver for PgSQL. mysql\_shin | Library stub for linking against the MySQL client libraries. pgsql\_shim | Library stub for linking against the PgSQL client libraries. -#### Class Compiler +#### Class Compiler Another thing you will recognize are the `.ti` files which are compiled by our own class compiler into actual source code. The meta language allows @@ -542,7 +542,7 @@ The logic is hidden in `tools/mkclass/` in case you want to learn more about it. The first steps during CMake & make also tell you about code generation. -### Build Tool: CMake +### Builds: CMake In its early development stages in 2012, Icinga 2 was built with autoconf/automake and separate Windows project files. We've found this very fragile, and have changed @@ -556,7 +556,7 @@ The most common benefits: * Separate binary build directories, the actual source tree stays clean. * CMake automatically generates a Visual Studio project file `icinga2.sln` on Windows. -### Builds: Unity Builds +### Builds: Unity Builds Another thing you should be aware of: Unity builds on and off. @@ -602,8 +602,8 @@ mkdir -p release debug Proceed with the specific distribution examples below. -* [CentOS 7](#development-linux-dev-env-centos) -* [Debian 9](#development-linux-dev-env-debian) +* [CentOS 7](21-development.md#development-linux-dev-env-centos) +* [Debian 9](21-development.md#development-linux-dev-env-debian) #### CentOS 7 From 8313a1b2a95c8eaa1996c4edc363b44e2fc31d28 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 3 Dec 2018 11:28:39 +0100 Subject: [PATCH 40/62] Docs: Update README.md with a better description and direct URLs to icinga.com/docs (cherry picked from commit e0b3e05c636db082da264c92fc02593f7ff44ded) --- README.md | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 1935d12d4..b0bcd681e 100644 --- a/README.md +++ b/README.md @@ -8,27 +8,42 @@ #### Table of Contents 1. [About][About] -2. [License][License] -3. [Installation][Installation] -4. [Documentation][Documentation] -5. [Support][Support] +2. [Installation][Installation] +3. [Documentation][Documentation] +4. [Support][Support] +5. [License][License] 6. [Contributing][Contributing] ## About -Icinga 2 is an open source monitoring system which checks the availability of your -network resources, notifies users of outages, and generates performance data for reporting. +[Icinga 2](https://icinga.com/products/icinga-2/) is a monitoring system which checks +the availability of your network resources, notifies users of outages, and generates +performance data for reporting. Scalable and extensible, Icinga 2 can monitor large, complex environments across multiple locations. -Icinga 2 as monitoring core works best with [Icinga Web 2](https://icinga.com/products/icinga-web-2/) -as web interface. +Icinga 2 as core requires [Icinga Web 2](https://icinga.com/products/icinga-web-2/) +on top in your Icinga Stack. -More information can be found at [icinga.com](https://icinga.com/products/icinga-2/) -and inside the [documentation](https://icinga.com/docs/icinga2/latest/). +![Icinga Dashboard](https://icinga.com/wp-content/uploads/2017/12/icingaweb2-2.5.0-dashboard.png) -## Licensing +## Installation + +For installing Icinga please check the [installation chapter](https://icinga.com/docs/icinga2/latest/doc/02-getting-started/) +in the documentation. + +## Documentation + +The documentation is available on [icinga.com/docs](https://icinga.com/docs/icinga2/latest/). + +## Support + +Check the [project website](https://icinga.com) for status updates. Join the +[community channels](https://icinga.com/community/) for questions +or ask an Icinga partner for [professional support](https://icinga.com/support/). + +## License Icinga 2 and the Icinga 2 documentation are licensed under the terms of the GNU General Public License Version 2, you will find a copy of this license in the @@ -48,21 +63,6 @@ so, delete this exception statement from your version. If you delete this exception statement from all source files in the program, then also delete it here. -## Installation - -Read the [INSTALL.md](INSTALL.md) file for more information about how to install it. - -## Documentation - -The documentation is located in the [doc/](doc/) directory. The latest documentation -is also available on https://docs.icinga.com - -## Support - -Check the project website at https://icinga.com for status updates. Join the -[community channels](https://icinga.com/community) for questions -or ask an Icinga partner for [professional support](https://icinga.com/services/support/). - ## Contributing There are many ways to contribute to Icinga -- whether it be sending patches, From 47c44fe641ff761284242e42ae77e0790823e646 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 4 Dec 2018 10:51:04 +0100 Subject: [PATCH 41/62] Fix formatting in dev docs (cherry picked from commit 8cbe286e676a56c536cee517b898cbe2f25b2547) --- doc/21-development.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index 6bd13e939..b6ae7eca4 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -407,15 +407,15 @@ Up/down in stacktrace: ## Develop Icinga 2 Icinga 2 can be built on many platforms such as Linux, Unix and Windows. -There are limitations in terms of support, e.g. Windows is only supported for clients, +There are limitations in terms of support, e.g. Windows is only supported for agents, not a full-featured master or satellite. Before you start with actual development, there is a couple of pre-requisites. ### Choose your Editor -Icinga 2 can be developed with your favorite editor. Icinga developers prefer to use -the tools below: +Icinga 2 can be developed with your favorite editor. Icinga developers prefer +these tools: - vim - CLion (macOS, Linux) @@ -641,8 +641,6 @@ vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf gdb --args /usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon ``` -``` - ##### Debian 9 ``` From d9b5fe0ace0b0458b52245a9610d8103f6992b46 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 4 Dec 2018 10:54:39 +0100 Subject: [PATCH 42/62] Purge INSTALL.md and add packager info to README.md Everything is located in the online documentation, where the README.md points to. (cherry picked from commit 9801b8b7a040fd4c91aa05d596ec644ddd294bdc) --- INSTALL.md | 21 --------------------- README.md | 3 +++ 2 files changed, 3 insertions(+), 21 deletions(-) delete mode 100644 INSTALL.md diff --git a/INSTALL.md b/INSTALL.md deleted file mode 100644 index d6121e999..000000000 --- a/INSTALL.md +++ /dev/null @@ -1,21 +0,0 @@ -# Installing Icinga 2 - -The recommended way of installing Icinga 2 is to use [packages](https://packages.icinga.com). -The Icinga project provides both release and development packages for a number -of operating systems. - -Please check the documentation in the [doc/](doc/) directory for a current list -of available packages and detailed installation instructions. - -The online documentation is available on [icinga.com/docs](https://icinga.com/docs/) -and will guide you step by step. - -There are a number of known caveats when installing from source such as -incorrect directory and file permissions. So even if you're planning to -not use the official packages it is advisable to build your own Debian -or RPM packages. You can use the source packages from [packages.icinga.com](https://packages.icinga.com) -for this purpose. - -For a more detailed introduction into developing Icinga and building -packages, please visit the [online documentation](https://icinga.com/docs/icinga2/latest/doc/21-development/). - diff --git a/README.md b/README.md index b0bcd681e..f81f6c940 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ on top in your Icinga Stack. For installing Icinga please check the [installation chapter](https://icinga.com/docs/icinga2/latest/doc/02-getting-started/) in the documentation. +If you are a packager, please read the [development chapter](https://icinga.com/docs/icinga2/latest/doc/21-development/) +for more details. + ## Documentation The documentation is available on [icinga.com/docs](https://icinga.com/docs/icinga2/latest/). From 242a7f5705a2c721cf6b4045ef25d30ac0e79048 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 4 Dec 2018 10:58:44 +0100 Subject: [PATCH 43/62] Update TOC (cherry picked from commit 01d2a17683659e17b0cc311135937e0d5748a05d) --- doc/21-development.md | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index b6ae7eca4..1b43724fe 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -4,11 +4,16 @@ This chapter provides hints on Icinga 2 debugging, development, package builds and tests. * [Debug Icinga 2](21-development.md#development-debug) + * [GDB Backtrace](21-development.md#development-debug-gdb-backtrace) + * [Core Dump](21-development.md#development-debug-core-dump) * [Develop Icinga 2](21-development.md#development-develop) - * [Linux Dev Environment](21-development.md#development-linux-dev-env) - * [macOS Dev Environment](21-development.md#development-macos-dev-env) - * [Windows Dev Environment](21-development.md#development-windows-dev-env) + * [Linux Dev Environment](21-development.md#development-linux-dev-env) + * [macOS Dev Environment](21-development.md#development-macos-dev-env) + * [Windows Dev Environment](21-development.md#development-windows-dev-env) * [Package Builds](21-development.md#development-package-builds) + * [RPM](21-development.md#development-package-builds-rpms) + * [DEB](21-development.md#development-package-builds-deb) + * [Windows](21-development.md#development-package-builds-windows) * [Advanced Tips](21-development.md#development-advanced) * [Tests](21-development.md#development-tests) @@ -20,6 +25,7 @@ a stack trace or coredump if the application crashed. It is also useful for developers working with different debuggers. > **Note:** +> > This is intentionally mentioned before any development insights > as debugging is a more frequent and commonly asked question. @@ -131,6 +137,12 @@ a new gdb run. #### GDB Backtrace If Icinga 2 aborted its operation abnormally, generate a backtrace. + +> **Note** +> +> Please install the [required debug symbols](21-development.md#debug-requirements) +> prior to generating a backtrace. + `thread apply all` is important here since this includes all running threads. We need this information when e.g. debugging dead locks and hanging features. @@ -155,6 +167,11 @@ make sure to attach as much detail as possible. If Icinga 2 is still running, generate a full backtrace from the running process and store it into a new file (e.g. for debugging dead locks). +> **Note** +> +> Please install the [required debug symbols](21-development.md#debug-requirements) +> prior to generating a backtrace. + Icinga 2 runs with 2 processes: main and command executor, therefore generate two backtrace logs and add them to the GitHub issue. @@ -1395,7 +1412,7 @@ the Debian packaging Git repository (https://github.com/Icinga/deb-icinga2) into your source tree and run the following command: ``` -$ dpkg-buildpackage -uc -us +dpkg-buildpackage -uc -us ``` ### Build Alpine Linux packages From 07d949a6a0552a7446bebd1d4deb2d50bf5bc2af Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 4 Dec 2018 12:14:01 +0100 Subject: [PATCH 44/62] Minor updates for core dumps The main parts are discussed in #6723 (cherry picked from commit 43c171056f826cf08b4155472ad9a6a4d14ba8a9) --- doc/21-development.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index 1b43724fe..1d08add4e 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -279,10 +279,11 @@ developers to analyze and fix the problem. This requires setting the core dump file size to `unlimited`. -Example for Systemd: + +##### Systemd ``` -vim /usr/lib/systemd/system/icinga2.service +systemctl edit icinga2.service [Service] ... @@ -293,7 +294,7 @@ systemctl daemon-reload systemctl restart icinga2 ``` -Example for init script: +##### Init Script ``` vim /etc/init.d/icinga2 @@ -303,10 +304,13 @@ ulimit -c unlimited service icinga2 restart ``` +##### Verify + Verify that the Icinga 2 process core file size limit is set to `unlimited`. ``` -cat /proc/`pidof icinga2`/limits +for pid in $(pidof icinga2); do cat /proc/$pid/limits; done + ... Max core file size unlimited unlimited bytes ``` @@ -318,7 +322,7 @@ The Icinga 2 daemon runs with the SUID bit set. Therefore you need to explicitly enable core dumps for SUID on Linux. ``` -sysctl -w fs.suid_dumpable=1 +sysctl -w fs.suid_dumpable=2 ``` Adjust the coredump kernel format and file location on Linux: From d68a565c1926bac4c2ac429d15483806fde2e78d Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 4 Dec 2018 12:21:54 +0100 Subject: [PATCH 45/62] Docs: Formatting for dev requirements (cherry picked from commit 00673cd75911e56cf977fdb5c14c809a97c01e6d) --- doc/21-development.md | 64 ++++++++++++------------------------------- 1 file changed, 18 insertions(+), 46 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index 1d08add4e..9abf3df4c 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -36,29 +36,12 @@ The Icinga 2 packages provide a debug package which must be installed separately for all involved binaries, like `icinga2-bin` or `icinga2-ido-mysql`. -Debian/Ubuntu: - -``` -apt-get install icinga2-dbg -``` - -RHEL/CentOS: - -``` -yum install icinga2-debuginfo -``` - -Fedora: - -``` -dnf install icinga2-debuginfo icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo -``` - -SLES/openSUSE: - -``` -zypper install icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo -``` +Distribution | Command +-------------------|------------------------------------------ +Debian/Ubuntu | `apt-get install icinga2-dbg` +RHEL/CentOS | `yum install icinga2-debuginfo` +Fedora | `dnf install icinga2-debuginfo icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo` +SLES/openSUSE | `zypper install icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo` Furthermore, you may also have to install debug symbols for Boost and your C++ library. @@ -70,23 +53,12 @@ build flag for debug builds. Install GDB in your development environment. -Debian/Ubuntu: - -``` -apt-get install gdb -``` - -RHEL/CentOS/Fedora: - -``` -yum install gdb -``` - -SLES/openSUSE: - -``` -zypper install gdb -``` +Distribution | Command +-------------------|------------------------------------------ +Debian/Ubuntu | `apt-get install gdb` +RHEL/CentOS | `yum install gdb` +Fedora | `dnf install gdb` +SLES/openSUSE | `zypper install gdb` #### GDB Run @@ -983,12 +955,12 @@ You need to specify the previously installed component paths: Variable | Value | Description ----------------------|----------------------------------------------------------------------|------------------------------------------------------- -BOOST_ROOT | `C:\boost_1_65_1` | Root path where you've extracted and compiled Boost. -BISON_EXECUTABLE | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe` | Path to the Bison executable. -FLEX_EXECUTABLE | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe` | Path to the Flex executable. -ICINGA2_WITH_MYSQL | OFF | Requires extra setup for MySQL if set to `ON`. Not supported for client setups. -ICINGA2_WITH_PGSQL | OFF | Requires extra setup for PgSQL if set to `ON`. Not supported for client setups. -ICINGA2_UNITY_BUILD | OFF | Disable unity builds for development environments. +`BOOST_ROOT` | `C:\boost_1_65_1` | Root path where you've extracted and compiled Boost. +`BISON_EXECUTABLE` | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe` | Path to the Bison executable. +`FLEX_EXECUTABLE` | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe` | Path to the Flex executable. +`ICINGA2_WITH_MYSQL` | OFF | Requires extra setup for MySQL if set to `ON`. Not supported for client setups. +`ICINGA2_WITH_PGSQL` | OFF | Requires extra setup for PgSQL if set to `ON`. Not supported for client setups. +`ICINGA2_UNITY_BUILD` | OFF | Disable unity builds for development environments. Tip: If you have previously opened a terminal, run `refreshenv` to re-read updated PATH variables. From 26db9728590b89b7227772a95c2eb5ced5c75072 Mon Sep 17 00:00:00 2001 From: Max Rosin Date: Wed, 5 Dec 2018 16:28:03 +0100 Subject: [PATCH 46/62] Document that retry_interval is only used after an active check result fixes #6795 (cherry picked from commit 00757919b322bc930360694c30485977cfb5506a) --- doc/09-object-types.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/09-object-types.md b/doc/09-object-types.md index bd6572c15..b785d1f60 100644 --- a/doc/09-object-types.md +++ b/doc/09-object-types.md @@ -719,7 +719,7 @@ Configuration Attributes: check\_period | Object name | **Optional.** The name of a time period which determines when this host should be checked. Not set by default. check\_timeout | Duration | **Optional.** Check command timeout in seconds. Overrides the CheckCommand's `timeout` attribute. check\_interval | Duration | **Optional.** The check interval (in seconds). This interval is used for checks when the host is in a `HARD` state. Defaults to `5m`. - retry\_interval | Duration | **Optional.** The retry interval (in seconds). This interval is used for checks when the host is in a `SOFT` state. Defaults to `1m`. + retry\_interval | Duration | **Optional.** The retry interval (in seconds). This interval is used for checks when the host is in a `SOFT` state. Defaults to `1m`. Note: This does not affect the scheduling [after a passive check result](08-advanced-topics.md#check-result-freshness). enable\_notifications | Boolean | **Optional.** Whether notifications are enabled. Defaults to true. enable\_active\_checks | Boolean | **Optional.** Whether active checks are enabled. Defaults to true. enable\_passive\_checks | Boolean | **Optional.** Whether passive checks are enabled. Defaults to true. @@ -1447,7 +1447,7 @@ Configuration Attributes: check\_period | Object name | **Optional.** The name of a time period which determines when this service should be checked. Not set by default. check\_timeout | Duration | **Optional.** Check command timeout in seconds. Overrides the CheckCommand's `timeout` attribute. check\_interval | Duration | **Optional.** The check interval (in seconds). This interval is used for checks when the service is in a `HARD` state. Defaults to `5m`. - retry\_interval | Duration | **Optional.** The retry interval (in seconds). This interval is used for checks when the service is in a `SOFT` state. Defaults to `1m`. + retry\_interval | Duration | **Optional.** The retry interval (in seconds). This interval is used for checks when the service is in a `SOFT` state. Defaults to `1m`. Note: This does not affect the scheduling [after a passive check result](08-advanced-topics.md#check-result-freshness). enable\_notifications | Boolean | **Optional.** Whether notifications are enabled. Defaults to `true`. enable\_active\_checks | Boolean | **Optional.** Whether active checks are enabled. Defaults to `true`. enable\_passive\_checks | Boolean | **Optional.** Whether passive checks are enabled. Defaults to `true`. From 9040c9b5127dea2a435fd22b78a1653754d862d5 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 9 Jan 2019 11:27:33 +0100 Subject: [PATCH 47/62] Allow Checkable#retry_interval to be 0 refs #6871 (cherry picked from commit 9ae738d17fa6220d988001e4c56155aa6535992c) --- lib/icinga/checkable-check.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/icinga/checkable-check.cpp b/lib/icinga/checkable-check.cpp index e70648d89..b159247a9 100644 --- a/lib/icinga/checkable-check.cpp +++ b/lib/icinga/checkable-check.cpp @@ -79,7 +79,8 @@ void Checkable::UpdateNextCheck(const MessageOrigin::Ptr& origin) if (interval > 1) adj = fmod(now * 100 + GetSchedulingOffset(), interval * 100) / 100.0; - adj = std::min(0.5 + fmod(GetSchedulingOffset(), interval * 5) / 100.0, adj); + if (adj != 0.0) + adj = std::min(0.5 + fmod(GetSchedulingOffset(), interval * 5) / 100.0, adj); double nextCheck = now - adj + interval; From a557f47e2a98c769b309ba1dae3b71c799952026 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 16 Jan 2019 17:27:38 +0100 Subject: [PATCH 48/62] Log: Ensure not to pass negative values to localtime() refs #6887 (cherry picked from commit 2fc33996b620d97e54d75b0d8c101fb3d9ba791c) --- lib/icinga/checkable-check.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/icinga/checkable-check.cpp b/lib/icinga/checkable-check.cpp index b159247a9..0b8917b77 100644 --- a/lib/icinga/checkable-check.cpp +++ b/lib/icinga/checkable-check.cpp @@ -83,10 +83,11 @@ void Checkable::UpdateNextCheck(const MessageOrigin::Ptr& origin) adj = std::min(0.5 + fmod(GetSchedulingOffset(), interval * 5) / 100.0, adj); double nextCheck = now - adj + interval; + double lastCheck = GetLastCheck(); Log(LogDebug, "Checkable") << "Update checkable '" << GetName() << "' with check interval '" << GetCheckInterval() - << "' from last check time at " << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", GetLastCheck()) + << "' from last check time at " << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", (lastCheck < 0 ? 0 : lastCheck)) << " (" << GetLastCheck() << ") to next check time at " << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", nextCheck) << "(" << nextCheck << ")."; SetNextCheck(nextCheck, false, origin); From ee915ed5d2ad0ff99775615c497e0c835273c198 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 15 Jan 2019 19:23:20 +0100 Subject: [PATCH 49/62] Validate Zone::GetLocalZone() before using (cherry picked from commit b09e7b287e6b4bbc277c9ef7828e34f884927f82) --- lib/icinga/downtime.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index d9b24a3d3..9f0adf708 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -252,7 +252,11 @@ String Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& auth attrs->Set("entry_time", Utility::GetTime()); if (!scheduledDowntime.IsEmpty()) { - attrs->Set("authoritative_zone", Zone::GetLocalZone()->GetName()); + auto localZone (Zone::GetLocalZone()); + + if (localZone) { + attrs->Set("authoritative_zone", localZone->GetName()); + } } Host::Ptr host; From fb72633c5eb081e3356046b922ce4f35246614dd Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Mon, 28 Jan 2019 18:29:57 +0100 Subject: [PATCH 50/62] Downtime::AddDowntime(): place Downtimes in the same zone as the origin ScheduledDowntimes (cherry picked from commit ce847324bc8abe4f36071633b999fa88ba2213f3) --- lib/icinga/downtime.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index 9f0adf708..0f0a74ceb 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -267,7 +267,23 @@ String Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& auth if (service) attrs->Set("service_name", service->GetShortName()); - String zone = checkable->GetZoneName(); + String zone; + + if (!scheduledDowntime.IsEmpty()) { + auto sdt (ScheduledDowntime::GetByName(scheduledDowntime)); + + if (sdt) { + auto sdtZone (sdt->GetZone()); + + if (sdtZone) { + zone = sdtZone->GetName(); + } + } + } + + if (zone.IsEmpty()) { + zone = checkable->GetZoneName(); + } if (!zone.IsEmpty()) attrs->Set("zone", zone); From 92fba8c64f6ed525ace1cc95533ae5664b00a45b Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 28 Jan 2019 17:33:05 +0100 Subject: [PATCH 51/62] Don't allow retry_interval <= 0 (cherry picked from commit 8cbd4820725655e3c4ae06aef78308183be016da) --- lib/icinga/checkable.cpp | 8 ++++++++ lib/icinga/checkable.hpp | 1 + 2 files changed, 9 insertions(+) diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index fe2fed9e3..e745d76cb 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -198,6 +198,14 @@ void Checkable::ValidateCheckInterval(const Lazy& lvalue, const Validati BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0.")); } +void Checkable::ValidateRetryInterval(const Lazy& lvalue, const ValidationUtils& utils) +{ + ObjectImpl::ValidateRetryInterval(lvalue, utils); + + if (lvalue() <= 0) + BOOST_THROW_EXCEPTION(ValidationError(this, { "retry_interval" }, "Interval must be greater than 0.")); +} + void Checkable::ValidateMaxCheckAttempts(const Lazy& lvalue, const ValidationUtils& utils) { ObjectImpl::ValidateMaxCheckAttempts(lvalue, utils); diff --git a/lib/icinga/checkable.hpp b/lib/icinga/checkable.hpp index 141d0a43c..824f41b8d 100644 --- a/lib/icinga/checkable.hpp +++ b/lib/icinga/checkable.hpp @@ -192,6 +192,7 @@ public: std::vector > GetReverseDependencies() const; void ValidateCheckInterval(const Lazy& lvalue, const ValidationUtils& value) final; + void ValidateRetryInterval(const Lazy& lvalue, const ValidationUtils& value) final; void ValidateMaxCheckAttempts(const Lazy& lvalue, const ValidationUtils& value) final; static void IncreasePendingChecks(); From 9259e7adfdb4b90cbe79fbc3e0d7ce2b1bf389e4 Mon Sep 17 00:00:00 2001 From: Michael Insel Date: Fri, 1 Feb 2019 16:46:28 +0100 Subject: [PATCH 52/62] Doc: Add .NET 3.5 to the windows build stack The Windows Agent Wizard is currently build on .NET Framework 2.0, which is not installed by default on Windows 10. This adds a note to the development documentation to install the .NET Framework 3.5 (which includes .NET Framework 2.0) component on Windows 10. (cherry picked from commit 52d81d0af522956fec4ef63c0e3c06158cbefbf9) --- doc/21-development.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/21-development.md b/doc/21-development.md index 9abf3df4c..d26c8dbae 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -845,6 +845,12 @@ Choose the following minimal set: After a while, Visual Studio will be ready. +#### .NET Framework 3.5 + +Windows 10 only have .NET Framework >= 4.6 installed by default, the Icinga Agent Wizard is built on .NET Framework 2.0 which is not included in .NET Framework 4.6. Thankfully Windows 10 have .NET Framework 3.5 (which includes .NET Framework 2.0) as a component on board, you just need to activate it. + +Go to `Control Panel` -> `Programs` -> `Turn Windows features on or off`. Tick `.NET Framework 3.5 (includes .NET 2.0 and 3.0)` and wait until the installation process succseded. + #### Flex and Bison Install it using [chocolatey](https://www.wireshark.org/docs/wsdg_html_chunked/ChSetupWin32.html): From dc27bcc8a3ad7f6ce2183c00e8b1af9a1892dafb Mon Sep 17 00:00:00 2001 From: Jean Flach Date: Fri, 11 Jan 2019 16:16:45 +0100 Subject: [PATCH 53/62] Fix checkresults from the future breaking checks (cherry picked from commit c97f3c80f550320abcbc3bcbaa0a3673c2091c34) --- lib/icinga/checkable-check.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/icinga/checkable-check.cpp b/lib/icinga/checkable-check.cpp index 0b8917b77..09fa901e1 100644 --- a/lib/icinga/checkable-check.cpp +++ b/lib/icinga/checkable-check.cpp @@ -170,8 +170,8 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig long old_attempt = GetCheckAttempt(); bool recovery = false; - /* Ignore check results older than the current one. */ - if (old_cr && cr->GetExecutionStart() < old_cr->GetExecutionStart()) + /* Ignore check results older than the current one, except if the previous check result is from the future. */ + if (old_cr && cr->GetExecutionStart() < old_cr->GetExecutionStart() && old_cr->GetExecutionStart() < now) return; /* The ExecuteCheck function already sets the old state, but we need to do it again From c77092081800adb7868c9ca760def6f4cfee10ab Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Fri, 8 Feb 2019 13:32:13 +0100 Subject: [PATCH 54/62] Refactor conditions and add debug log messages for future crs and skipped crs (cherry picked from commit d1fb1a8eda05018c5f665fceeb52569e243a7b65) --- lib/icinga/checkable-check.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/icinga/checkable-check.cpp b/lib/icinga/checkable-check.cpp index 09fa901e1..2437aa787 100644 --- a/lib/icinga/checkable-check.cpp +++ b/lib/icinga/checkable-check.cpp @@ -170,9 +170,34 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig long old_attempt = GetCheckAttempt(); bool recovery = false; - /* Ignore check results older than the current one, except if the previous check result is from the future. */ - if (old_cr && cr->GetExecutionStart() < old_cr->GetExecutionStart() && old_cr->GetExecutionStart() < now) - return; + /* When we have an check result already (not after fresh start), + * prevent to accept old check results and allow overrides for + * CRs happened in the future. + */ + if (old_cr) { + double currentCRTimestamp = old_cr->GetExecutionStart(); + double newCRTimestamp = cr->GetExecutionStart(); + + /* Our current timestamp may be from the future (wrong server time adjusted again). Allow overrides here. */ + if (currentCRTimestamp > now) { + /* our current CR is from the future, let the new CR override it. */ + Log(LogDebug, "Checkable") + << std::fixed << std::setprecision(6) << "Processing check result for checkable '" << GetName() << "' from " + << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", newCRTimestamp) << " (" << newCRTimestamp + << "). Overriding since ours is from the future at " + << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", currentCRTimestamp) << " (" << currentCRTimestamp << ")."; + } else { + /* Current timestamp is from the past, but the new timestamp is even more in the past. Skip it. */ + if (newCRTimestamp < currentCRTimestamp) { + Log(LogDebug, "Checkable") + << std::fixed << std::setprecision(6) << "Skipping check result for checkable '" << GetName() << "' from " + << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", newCRTimestamp) << " (" << newCRTimestamp + << "). It is in the past compared to ours at " + << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", currentCRTimestamp) << " (" << currentCRTimestamp << ")."; + return; + } + } + } /* The ExecuteCheck function already sets the old state, but we need to do it again * in case this was a passive check result. */ From 4f494b9a91fb33d571aef8639fd630318ac33ebb Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 11 Feb 2019 14:32:02 +0100 Subject: [PATCH 55/62] Troubleshooting: Add notes on ephemeral port range blocking on Windows agents (cherry picked from commit 6558287da03bb526ba2728201ff7d558a09faf46) --- doc/15-troubleshooting.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/doc/15-troubleshooting.md b/doc/15-troubleshooting.md index 8ccfda895..eb44ac995 100644 --- a/doc/15-troubleshooting.md +++ b/doc/15-troubleshooting.md @@ -1058,3 +1058,33 @@ Check the following: * Check your [connection](15-troubleshooting.md#troubleshooting-cluster-connection-errors) in general. * Does the log replay work, e.g. are all events processed and the directory gets cleared up over time? * Decrease the `log_duration` attribute value for that specific [endpoint](09-object-types.md#objecttype-endpoint). + + + +### Cluster Troubleshooting: Windows Agents + +#### Windows blocking Icinga 2 with ephemeral port range + +When you see a message like this in your Windows agent logs: + +``` +critical/TcpSocket: Invalid socket: 10055, "An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full." +``` + +Windows is blocking Icinga 2 and as such, no more TCP connection handling is possible. + +Depending on the version, patch level and installed applications, Windows is changing its +range of [ephemeral ports](https://en.wikipedia.org/wiki/Ephemeral_port#Range). + +In order to solve this, raise the the `MaxUserPort` value in the registry. + +``` +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters + +Value Name: MaxUserPort Value +Type: DWORD +Value data: 65534 +``` + +More details in [this blogpost](https://www.netways.de/blog/2019/01/24/windows-blocking-icinga-2-with-ephemeral-port-range/) +and this [MS help entry](https://support.microsoft.com/en-us/help/196271/when-you-try-to-connect-from-tcp-ports-greater-than-5000-you-receive-t). From 466096a6a4d1c61f83886c0de88c4ee45df6f49c Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 19 Feb 2019 13:49:52 +0100 Subject: [PATCH 56/62] Debug: Log calls to ConfigObject::Deactivate() Only available in debug builds. (cherry picked from commit d98c0704c446b0fd47b18b610a92ac75de180853) --- lib/base/configobject.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/base/configobject.cpp b/lib/base/configobject.cpp index 9d44db60a..b73285bc5 100644 --- a/lib/base/configobject.cpp +++ b/lib/base/configobject.cpp @@ -624,6 +624,10 @@ void ConfigObject::StopObjects() continue; for (const ConfigObject::Ptr& object : dtype->GetObjects()) { +#ifdef I2_DEBUG + Log(LogDebug, "ConfigObject") + << "Deactivate() called for config object '" << object->GetName() << "' with type '" << type->GetName() << "'."; +#endif /* I2_DEBUG */ object->Deactivate(); } } From 82c0197aae9ae11b820e32a4561dca68b9769081 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 20 Feb 2019 13:56:15 +0100 Subject: [PATCH 57/62] Activate downtimes before any checkable object (cherry picked from commit 7936a147ba82ce7e19de43ccb5f4c830edd8d235) --- lib/icinga/downtime.ti | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/icinga/downtime.ti b/lib/icinga/downtime.ti index fe80e0e77..d2880421f 100644 --- a/lib/icinga/downtime.ti +++ b/lib/icinga/downtime.ti @@ -37,6 +37,8 @@ public: class Downtime : ConfigObject < DowntimeNameComposer { + activation_priority -10; + load_after Host; load_after Service; From f98e40d880ca7886b4dad475e041b0e8825c8ba3 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 22 Feb 2019 11:37:07 +0100 Subject: [PATCH 58/62] Secure ApiUser::GetByAuthHeader() against timing attacks (cherry picked from commit 9558ebc0f46febc7692bbb65394708b78b276d46) --- lib/base/utility.cpp | 36 ++++++++++++++++++++++++++++++++++++ lib/base/utility.hpp | 2 ++ lib/remote/apiuser.cpp | 3 ++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index cf8bc588f..bf50159e5 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -26,6 +26,7 @@ #include "base/utility.hpp" #include "base/json.hpp" #include "base/objectlock.hpp" +#include #include #include #include @@ -1949,3 +1950,38 @@ String Utility::GetFromEnvironment(const String& env) return String(); #endif /* _WIN32 */ } + +/** + * Compare the password entered by a client with the actual password. + * The comparision is safe against timing attacks. + */ +bool Utility::ComparePasswords(const String& enteredPassword, const String& actualPassword) +{ + volatile const char * volatile enteredPasswordCStr = enteredPassword.CStr(); + volatile size_t enteredPasswordLen = enteredPassword.GetLength(); + + volatile const char * volatile actualPasswordCStr = actualPassword.CStr(); + volatile size_t actualPasswordLen = actualPassword.GetLength(); + + volatile uint_fast8_t result = enteredPasswordLen == actualPasswordLen; + + if (result) { + auto cStr (actualPasswordCStr); + auto len (actualPasswordLen); + + actualPasswordCStr = cStr; + actualPasswordLen = len; + } else { + auto cStr (enteredPasswordCStr); + auto len (enteredPasswordLen); + + actualPasswordCStr = cStr; + actualPasswordLen = len; + } + + for (volatile size_t i = 0; i < enteredPasswordLen; ++i) { + result &= uint_fast8_t(enteredPasswordCStr[i] == actualPasswordCStr[i]); + } + + return result; +} diff --git a/lib/base/utility.hpp b/lib/base/utility.hpp index e75ebfefa..0adfc9e5c 100644 --- a/lib/base/utility.hpp +++ b/lib/base/utility.hpp @@ -149,6 +149,8 @@ public: static String GetFromEnvironment(const String& env); + static bool ComparePasswords(const String& enteredPassword, const String& actualPassword); + #ifdef I2_DEBUG static void SetTime(double); static void IncrementTime(double); diff --git a/lib/remote/apiuser.cpp b/lib/remote/apiuser.cpp index 346aadbef..320935a07 100644 --- a/lib/remote/apiuser.cpp +++ b/lib/remote/apiuser.cpp @@ -22,6 +22,7 @@ #include "base/configtype.hpp" #include "base/base64.hpp" #include "base/tlsutility.hpp" +#include "base/utility.hpp" using namespace icinga; @@ -63,7 +64,7 @@ ApiUser::Ptr ApiUser::GetByAuthHeader(const String& auth_header) */ if (!user || password.IsEmpty()) return nullptr; - else if (user && user->GetPassword() != password) + else if (user && !Utility::ComparePasswords(password, user->GetPassword())) return nullptr; return user; From a4f774aa9487d90278ad5596dc4f1b8cce52ed23 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 22 Feb 2019 16:58:26 +0100 Subject: [PATCH 59/62] Test Utility::ComparePasswords() (cherry picked from commit 1b00331a88c396ab8c94188855074ed907a5bd66) --- test/CMakeLists.txt | 3 ++ test/base-utility.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 test/base-utility.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c78f2732d..714d6a768 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,6 +36,7 @@ set(base_test_SOURCES base-string.cpp base-timer.cpp base-type.cpp + base-utility.cpp base-value.cpp config-ops.cpp icinga-checkresult.cpp @@ -120,6 +121,8 @@ add_boost_test(base base_type/assign base_type/byname base_type/instantiate + base_utility/comparepasswords_works + base_utility/comparepasswords_issafe base_value/scalar base_value/convert base_value/format diff --git a/test/base-utility.cpp b/test/base-utility.cpp new file mode 100644 index 000000000..fdc1a17d2 --- /dev/null +++ b/test/base-utility.cpp @@ -0,0 +1,70 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2018 Icinga Development Team (https://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/utility.hpp" +#include +#include + +using namespace icinga; + +BOOST_AUTO_TEST_SUITE(base_utility) + +BOOST_AUTO_TEST_CASE(comparepasswords_works) +{ + BOOST_CHECK(Utility::ComparePasswords("", "")); + + BOOST_CHECK(!Utility::ComparePasswords("x", "")); + BOOST_CHECK(!Utility::ComparePasswords("", "x")); + + BOOST_CHECK(Utility::ComparePasswords("x", "x")); + BOOST_CHECK(!Utility::ComparePasswords("x", "y")); + + BOOST_CHECK(Utility::ComparePasswords("abcd", "abcd")); + BOOST_CHECK(!Utility::ComparePasswords("abc", "abcd")); + BOOST_CHECK(!Utility::ComparePasswords("abcde", "abcd")); +} + +BOOST_AUTO_TEST_CASE(comparepasswords_issafe) +{ + using std::chrono::duration_cast; + using std::chrono::microseconds; + using std::chrono::steady_clock; + + String a, b; + + a.Append(200000001, 'a'); + b.Append(200000002, 'b'); + + auto start1 (steady_clock::now()); + + Utility::ComparePasswords(a, a); + + auto duration1 (steady_clock::now() - start1); + + auto start2 (steady_clock::now()); + + Utility::ComparePasswords(a, b); + + auto duration2 (steady_clock::now() - start2); + + double diff = (double)duration_cast(duration1).count() / (double)duration_cast(duration2).count(); + BOOST_CHECK(0.9 <= diff && diff <= 1.1); +} + +BOOST_AUTO_TEST_SUITE_END() From 14ef7cbc1f146e985724cbce3bfe505470cabd93 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 25 Feb 2019 13:40:58 +0100 Subject: [PATCH 60/62] Fix formatting in development docs (cherry picked from commit 710e4fa55e919032bd3b45c774130e1f938d3f81) --- doc/21-development.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/21-development.md b/doc/21-development.md index d26c8dbae..e95307207 100644 --- a/doc/21-development.md +++ b/doc/21-development.md @@ -1435,39 +1435,39 @@ icinga2 daemon Icinga 2 can be started as a daemon using the provided init script: ``` -# /etc/init.d/icinga2 +/etc/init.d/icinga2 Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} ``` -### Systemd +#### Systemd If your distribution uses Systemd: ``` -# systemctl {start|stop|reload|status|enable|disable} icinga2 +systemctl {start|stop|reload|status|enable|disable} icinga2 ``` In case the distribution is running Systemd >227, you'll also need to package and install the `etc/initsystem/icinga2.service.limits.conf` file into `/etc/systemd/system/icinga2.service.d`. -### openrc +#### openrc Or if your distribution uses openrc (like Alpine): ``` -# rc-service icinga2 +rc-service icinga2 Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} - ``` +``` Note: the openrc's init.d is not shipped by default. A working init.d with openrc can be found here: (https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd). If you have customized some path, edit the file and adjust it according with your setup. Those few steps can be followed: ``` -# wget https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd -# mv icinga2.initd /etc/init.d/icinga2 -# chmod +x /etc/init.d/icinga2 +wget https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd +mv icinga2.initd /etc/init.d/icinga2 +chmod +x /etc/init.d/icinga2 ``` Icinga 2 reads a single configuration file which is used to specify all From 47c969eadc21de59afd2101d26676e15ccca200b Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 7 Jan 2019 15:59:24 +0100 Subject: [PATCH 61/62] Dynamically print current copyright year in `--version` output (cherry picked from commit c1fedab7aea73f6aa9c9357c54c409665239d698) --- icinga-app/icinga.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index b97e79e83..1f8f635cc 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -543,7 +543,8 @@ static int Main() } if (vm.count("version")) { - std::cout << "Copyright (c) 2012-2018 Icinga Development Team (https://icinga.com/)" << std::endl + std::cout << "Copyright (c) 2012-" << Utility::FormatDateTime("%Y", Utility::GetTime()) + << " Icinga GmbH (https://icinga.com/)" << std::endl << "License GPLv2+: GNU GPL version 2 or later " << std::endl << "This is free software: you are free to change and redistribute it." << std::endl << "There is NO WARRANTY, to the extent permitted by law."; From 101783d7efe3050d68d2370db7b14a088bc1f413 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 25 Feb 2019 16:53:13 +0100 Subject: [PATCH 62/62] Release version 2.10.3 --- CHANGELOG.md | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ VERSION | 2 +- changelog.py | 3 +- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ca748fde..8ba579778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,95 @@ # Icinga 2.x CHANGELOG +## 2.10.3 (2019-02-26) + +### Notes + +Bugfixes: + +- Stalled TLS connections on reload/Director deployments (#6816 #6898 ref/NC/588119) +- 'Connection: close' header leading to unstable instance, affects Ruby clients (#6799) +- Server time in the future breaks check result processing (#6797 ref/NC/595861) +- ScheduledDowntimes: Generate downtime objects only on one HA endpoint (#2844 ref/IC/9673 ref/NC/590167 ref/NC/591721) +- Improve activation & syncing for downtime objects generated from ScheduledDowntimes (#6826 ref/IC/9673 ref/NC/585559) +- Generate a runtime downtime object from already running ScheduledDowntime objects (#6704) +- DB IDO: Don't enqueue queries when the feature is paused in HA zones (#5876) +- Crashes with localtime_r errors (#6887) + +Documentation updates: + +- Ephemeral port range blocking on Windows agents (ref/NC/597307) +- Technical concepts for the check scheduler (#6775) +- DB IDO cleanup (#6791) +- Unified development docs (#6819) + +### Bug + +* [#6971](https://github.com/icinga/icinga2/issues/6971) (Notifications, PR): Activate downtimes before any checkable object +* [#6968](https://github.com/icinga/icinga2/issues/6968) (API, PR): Secure ApiUser::GetByAuthHeader\(\) against timing attacks +* [#6940](https://github.com/icinga/icinga2/issues/6940) (Plugins, Windows, PR): Fix check\_swap percentage calculation +* [#6925](https://github.com/icinga/icinga2/issues/6925) (Plugins, Windows, PR): Fix check\_swap formatting +* [#6924](https://github.com/icinga/icinga2/issues/6924) (PR): Fix double to long conversions +* [#6922](https://github.com/icinga/icinga2/issues/6922) (API, DB IDO): IDO MySQL fails on start if check\_interval is a float \(Icinga 2.9.2\) +* [#6920](https://github.com/icinga/icinga2/issues/6920) (PR): Downtime::AddDowntime\(\): place Downtimes in the same zone as the origin ScheduledDowntimes +* [#6917](https://github.com/icinga/icinga2/issues/6917) (Cluster, Log, PR): Cluster: Delete object message should log that +* [#6916](https://github.com/icinga/icinga2/issues/6916) (PR): Don't allow retry\_interval \<= 0 +* [#6914](https://github.com/icinga/icinga2/issues/6914) (Cluster, PR): ClusterEvents::AcknowledgementSet event should forward 'persistent' attribute +* [#6913](https://github.com/icinga/icinga2/issues/6913) (Plugins, Windows): check\_swap return value wrong when no swap file configured +* [#6901](https://github.com/icinga/icinga2/issues/6901) (API, PR): TcpSocket\#Bind\(\): also set SO\_REUSEPORT +* [#6899](https://github.com/icinga/icinga2/issues/6899) (PR): Log: Ensure not to pass negative values to localtime\(\) +* [#6898](https://github.com/icinga/icinga2/issues/6898) (API): API action restart-process fails on FreeBSD +* [#6894](https://github.com/icinga/icinga2/issues/6894) (Check Execution, PR): Fix checkresults from the future breaking checks +* [#6887](https://github.com/icinga/icinga2/issues/6887) (Check Execution, Windows): Icinga2 Windows Service does not start critical/checker: Exception occurred while checking 'hostname.tld' +* [#6883](https://github.com/icinga/icinga2/issues/6883) (Check Execution, PR): Allow Checkable\#retry\_interval to be 0 +* [#6871](https://github.com/icinga/icinga2/issues/6871): Icinga2 crashes after localtime\_r call +* [#6857](https://github.com/icinga/icinga2/issues/6857) (Plugins, Windows, PR): Url\#m\_Query: preserve order +* [#6826](https://github.com/icinga/icinga2/issues/6826) (Configuration, PR): Downtime\#HasValidConfigOwner\(\): wait for ScheduledDowntimes +* [#6821](https://github.com/icinga/icinga2/issues/6821) (Cluster, Configuration, PR): Don't delete downtimes in satellite zones +* [#6820](https://github.com/icinga/icinga2/issues/6820) (Cluster, PR): Only create downtimes from non-paused ScheduledDowntime objects in HA enabled cluster zones +* [#6817](https://github.com/icinga/icinga2/issues/6817) (API, PR): HttpServerConnection\#DataAvailableHandler\(\): be aware of being called multiple times concurrently +* [#6816](https://github.com/icinga/icinga2/issues/6816) (API, Cluster): Stalled TLS connections and lock waits in SocketEventEngine +* [#6814](https://github.com/icinga/icinga2/issues/6814) (API, PR): Restore 'Connection: close' behaviour in HTTP responses +* [#6811](https://github.com/icinga/icinga2/issues/6811) (Plugins, Windows, PR): Fix state conditions in check\_memory and check\_swap +* [#6810](https://github.com/icinga/icinga2/issues/6810) (Plugins, Windows): Windows check\_memory never gets critical +* [#6808](https://github.com/icinga/icinga2/issues/6808) (API, PR): Remove redundand check for object existence on creation via API +* [#6807](https://github.com/icinga/icinga2/issues/6807) (API): \[2.10.2\] Director deploy crashes the Icinga service \[FreeBSD\] +* [#6799](https://github.com/icinga/icinga2/issues/6799) (API): "Connection: close" header leads to unstable instance +* [#6797](https://github.com/icinga/icinga2/issues/6797) (Check Execution): Servertime in the future breaks check results processing +* [#6750](https://github.com/icinga/icinga2/issues/6750) (Configuration, PR): \#6749 Wrong operator on stride variable causing incorrect behaviour +* [#6749](https://github.com/icinga/icinga2/issues/6749) (Configuration): Stride is misinterpreted in multi-date legacydatetime +* [#6748](https://github.com/icinga/icinga2/issues/6748) (CLI, PR): Fix api setup to automatically create the conf.d directory +* [#6718](https://github.com/icinga/icinga2/issues/6718) (API, Cluster, PR): Call SSL\_shutdown\(\) at least twice +* [#6704](https://github.com/icinga/icinga2/issues/6704) (Notifications, PR): Put newly configured already running ScheduledDowntime immediately in effect +* [#6542](https://github.com/icinga/icinga2/issues/6542) (Configuration, Log): /var/log/icinga2/icinga2.log is growing very fast on satellites +* [#6536](https://github.com/icinga/icinga2/issues/6536) (Windows, help wanted): check\_nscp\_api: Query arguments are sorted on Url::Format\(\) +* [#4790](https://github.com/icinga/icinga2/issues/4790) (Notifications): Newly configured already running ScheduledDowntime not put into effect +* [#3937](https://github.com/icinga/icinga2/issues/3937) (API): Icinga2 API: PUT request fails at 0-byte file +* [#2844](https://github.com/icinga/icinga2/issues/2844) (Cluster): Duplicated scheduled downtimes created in cluster HA zone + +### Documentation + +* [#6956](https://github.com/icinga/icinga2/issues/6956) (Documentation, PR): Escape pipe symbol in api documentation +* [#6944](https://github.com/icinga/icinga2/issues/6944) (Documentation, PR): Troubleshooting: Add notes on ephemeral port range blocking on Windows agents +* [#6928](https://github.com/icinga/icinga2/issues/6928) (Documentation, PR): Doc: Add .NET 3.5 to the windows build stack +* [#6825](https://github.com/icinga/icinga2/issues/6825) (Documentation, PR): Document that retry\_interval is only used after an active check result +* [#6819](https://github.com/icinga/icinga2/issues/6819) (Documentation, PR): Enhance and unify development docs for debug, develop, package +* [#6791](https://github.com/icinga/icinga2/issues/6791) (Documentation, PR): Docs: Add a section for DB IDO Cleanup +* [#6776](https://github.com/icinga/icinga2/issues/6776) (Documentation, PR): Doc fix: update apache section +* [#6775](https://github.com/icinga/icinga2/issues/6775) (Documentation, PR): Add technical docs for the check scheduler \(general, initial check, offsets\) +* [#6751](https://github.com/icinga/icinga2/issues/6751) (Documentation, PR): Doc fix: documentation link for apt +* [#6743](https://github.com/icinga/icinga2/issues/6743) (Documentation, PR): Doc fix: error in example path. +* [#5341](https://github.com/icinga/icinga2/issues/5341) (Documentation): Enhance development documentation + +### Support + +* [#6972](https://github.com/icinga/icinga2/issues/6972) (PR): Fix formatting in development docs +* [#6958](https://github.com/icinga/icinga2/issues/6958) (code-quality, PR): Debug: Log calls to ConfigObject::Deactivate\(\) +* [#6897](https://github.com/icinga/icinga2/issues/6897) (PR): Validate Zone::GetLocalZone\(\) before using +* [#6872](https://github.com/icinga/icinga2/issues/6872) (Windows): 2.10 is unstable \(Windows Agent\) +* [#6843](https://github.com/icinga/icinga2/issues/6843) (Tests, Windows, PR): Improve AppVeyor builds +* [#6479](https://github.com/icinga/icinga2/issues/6479) (code-quality, PR): SocketEvents: inherit from Stream +* [#6477](https://github.com/icinga/icinga2/issues/6477) (code-quality): SocketEvents: inherit from Object + ## 2.10.2 (2018-11-14) ### Bug diff --git a/VERSION b/VERSION index 4320bb9a9..723a7afee 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -Version: 2.10.2 +Version: 2.10.3 Revision: 1 diff --git a/changelog.py b/changelog.py index a6bf2afbc..79bdb0c8b 100755 --- a/changelog.py +++ b/changelog.py @@ -198,8 +198,7 @@ for milestone in sorted(milestones.values(), key=lambda ms: (ms["due_on"], ms["t continue if milestone["due_on"] == None: - print "Milestone", milestone["title"], "does not have a due date." - sys.exit(1) + print "Warning: Milestone", milestone["title"], "does not have a due date." ms_due_on = datetime.strptime(milestone["due_on"], "%Y-%m-%dT%H:%M:%SZ")