From d66b4d587e2a4110cd811757b3140769b1f9944a Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sun, 25 May 2014 17:10:57 +0200 Subject: [PATCH] Implement the "cluster-zone" check task. Fixes #6204 --- contrib/make-agent-config.py | 27 ++++++-- doc/6-configuring-icinga-2.md | 10 ++- itl/command-icinga.conf | 6 ++ itl/command.conf | 4 ++ lib/config/config_lexer.ll | 1 + lib/methods/CMakeLists.txt | 3 +- lib/methods/clusterzonechecktask.cpp | 95 ++++++++++++++++++++++++++++ lib/methods/clusterzonechecktask.hpp | 44 +++++++++++++ 8 files changed, 184 insertions(+), 6 deletions(-) create mode 100644 lib/methods/clusterzonechecktask.cpp create mode 100644 lib/methods/clusterzonechecktask.hpp diff --git a/contrib/make-agent-config.py b/contrib/make-agent-config.py index 61ec4c238..6e2acbd27 100755 --- a/contrib/make-agent-config.py +++ b/contrib/make-agent-config.py @@ -32,13 +32,32 @@ for agent, agent_info in inventory.items(): print " endpoints = [ \"%s\" ]" % (agent) print "}" print "" + + print "object Host \"%s\" {" % (agent_info["zone"]) + print " check_command = \"cluster-zone\"" + print "}" + print "" + + print "apply Dependency \"host-zone-%s\" to Host {" % (agent_info["zone"]) + print " parent_host_name = \"%s\"" % (agent_info["zone"]) + print " assign where host.@zone == \"%s\"" % (agent_info["zone"]) + print "}" + print "" + + print "apply Dependency \"service-zone-%s\" to Service {" % (agent_info["zone"]) + print " parent_host_name = \"%s\"" % (agent_info["zone"]) + print " assign where service.@zone == \"%s\"" % (agent_info["zone"]) + print "}" + print "" + print "zone \"%s\" {" % (agent_info["zone"]) for host, services in agent_info["repository"].items(): - print "object Host \"%s\" {" % (host) - print " check_command = \"dummy\"" - print "}" - print "" + if host != agent_info["zone"]: + print "object Host \"%s\" {" % (host) + print " check_command = \"dummy\"" + print "}" + print "" for service in services: print "object Service \"%s\" {" % (service) diff --git a/doc/6-configuring-icinga-2.md b/doc/6-configuring-icinga-2.md index 502bb7d93..3c20fb8c1 100644 --- a/doc/6-configuring-icinga-2.md +++ b/doc/6-configuring-icinga-2.md @@ -1678,14 +1678,22 @@ data for the current Icinga instance. The `icinga` check command does not support any vars. -#### cluster +#### cluster Check command for the built-in `cluster` check. This check returns performance data for the current Icinga instance and connected endpoints. The `cluster` check command does not support any vars. +#### cluster-zone +Check command for the built-in `cluster-zone` check. + +Cluster Attributes: + +Name | Description +-------------|--------------- +cluster_zone | **Optional.** The zone name. Defaults to "$host.name$". ## Plugin Check Commands diff --git a/itl/command-icinga.conf b/itl/command-icinga.conf index 34496366e..920053631 100644 --- a/itl/command-icinga.conf +++ b/itl/command-icinga.conf @@ -25,3 +25,9 @@ object CheckCommand "cluster" { import "cluster-check-command" } +object CheckCommand "cluster-zone" { + import "cluster-zone-check-command" + + vars.cluster_zone = "$host.name$" +} + diff --git a/itl/command.conf b/itl/command.conf index a2b272b74..97da0e657 100644 --- a/itl/command.conf +++ b/itl/command.conf @@ -27,6 +27,10 @@ template CheckCommand "cluster-check-command" { methods.execute = "ClusterCheck" } +template CheckCommand "cluster-zone-check-command" { + methods.execute = "ClusterZoneCheck" +} + template CheckCommand "plugin-check-command" { methods.execute = "PluginCheck" } diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index 3f593f373..cebb7a89a 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -244,6 +244,7 @@ in { yylval->op = &AExpression::OpIn; return T_IN; } && { yylval->op = &AExpression::OpLogicalAnd; return T_LOGICAL_AND; } \|\| { yylval->op = &AExpression::OpLogicalOr; return T_LOGICAL_OR; } [a-zA-Z_][a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; } +@[a-zA-Z_][a-zA-Z0-9\-_]* { yylval->text = strdup(yytext + 1); return T_IDENTIFIER; } \<[^\>]*\> { yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; } -?[0-9]+(\.[0-9]+)?ms { yylval->num = strtod(yytext, NULL) / 1000; return T_NUMBER; } -?[0-9]+(\.[0-9]+)?d { yylval->num = strtod(yytext, NULL) * 60 * 60 * 24; return T_NUMBER; } diff --git a/lib/methods/CMakeLists.txt b/lib/methods/CMakeLists.txt index 1ceacf793..3ec48730c 100644 --- a/lib/methods/CMakeLists.txt +++ b/lib/methods/CMakeLists.txt @@ -22,7 +22,8 @@ else() endif() add_library(methods SHARED - castfuncs.cpp clusterchecktask.cpp icingachecktask.cpp nullchecktask.cpp nulleventtask.cpp + castfuncs.cpp clusterchecktask.cpp clusterzonechecktask.cpp + icingachecktask.cpp nullchecktask.cpp nulleventtask.cpp pluginchecktask.cpp plugineventtask.cpp pluginnotificationtask.cpp randomchecktask.cpp timeperiodtask.cpp ${WindowsSources} ) diff --git a/lib/methods/clusterzonechecktask.cpp b/lib/methods/clusterzonechecktask.cpp new file mode 100644 index 000000000..b7442ac67 --- /dev/null +++ b/lib/methods/clusterzonechecktask.cpp @@ -0,0 +1,95 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "methods/clusterzonechecktask.hpp" +#include "icinga/checkcommand.hpp" +#include "icinga/macroprocessor.hpp" +#include "remote/apilistener.hpp" +#include "remote/endpoint.hpp" +#include "remote/zone.hpp" +#include "base/scriptfunction.hpp" +#include + +using namespace icinga; + +REGISTER_SCRIPTFUNCTION(ClusterZoneCheck, &ClusterZoneCheckTask::ScriptFunc); + +void ClusterZoneCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr) +{ + ApiListener::Ptr listener = ApiListener::GetInstance(); + + if (!listener) { + cr->SetOutput("No API listener is configured for this instance."); + cr->SetState(ServiceUnknown); + checkable->ProcessCheckResult(cr); + return; + } + + CheckCommand::Ptr commandObj = checkable->GetCheckCommand(); + Value raw_command = commandObj->GetCommandLine(); + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + MacroProcessor::ResolverList resolvers; + if (service) + resolvers.push_back(std::make_pair("service", service)); + resolvers.push_back(std::make_pair("host", host)); + resolvers.push_back(std::make_pair("command", commandObj)); + resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance())); + + String zoneName = MacroProcessor::ResolveMacros("$cluster_zone$", resolvers, checkable->GetLastCheckResult()); + + if (zoneName.IsEmpty()) { + cr->SetOutput("Macro 'cluster_zone' must be set."); + cr->SetState(ServiceUnknown); + checkable->ProcessCheckResult(cr); + return; + } + + Zone::Ptr zone = Zone::GetByName(zoneName); + + if (!zone) { + cr->SetOutput("Zone '" + zoneName + "' does not exist."); + cr->SetState(ServiceUnknown); + checkable->ProcessCheckResult(cr); + return; + } + + bool connected = false; + + BOOST_FOREACH(const Endpoint::Ptr& endpoint, zone->GetEndpoints()) { + if (endpoint->IsConnected()) { + connected = true; + break; + } + } + + if (!connected) { + cr->SetState(ServiceCritical); + cr->SetOutput("Zone '" + zoneName + "' is not connected."); + } else { + cr->SetState(ServiceOK); + cr->SetOutput("Zone '" + zoneName + "' is connected."); + } + + checkable->ProcessCheckResult(cr); +} + diff --git a/lib/methods/clusterzonechecktask.hpp b/lib/methods/clusterzonechecktask.hpp new file mode 100644 index 000000000..dd96717b0 --- /dev/null +++ b/lib/methods/clusterzonechecktask.hpp @@ -0,0 +1,44 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef CLUSTERZONECHECKTASK_H +#define CLUSTERZONECHECKTASK_H + +#include "icinga/service.hpp" + +namespace icinga +{ + +/** + * Cluster zone check type. + * + * @ingroup methods + */ +class ClusterZoneCheckTask +{ +public: + static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr); + +private: + ClusterZoneCheckTask(void); +}; + +} + +#endif /* CLUSTERZONECHECKTASK_H */ -- 2.40.0