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 */