state = 0; /* up */
fp << "hoststatus {" << "\n"
- << "\t" << "host_name=" << host->GetName() << "\n"
- << "\t" << "has_been_checked=1" << "\n"
- << "\t" << "should_be_scheduled=1" << "\n"
- << "\t" << "check_execution_time=0" << "\n"
- << "\t" << "check_latency=0" << "\n"
- << "\t" << "current_state=" << state << "\n"
- << "\t" << "state_type=1" << "\n"
- << "\t" << "last_check=" << Utility::GetTime() << "\n"
- << "\t" << "next_check=" << Utility::GetTime() << "\n"
- << "\t" << "current_attempt=1" << "\n"
- << "\t" << "max_attempts=1" << "\n"
- << "\t" << "active_checks_enabled=1" << "\n"
- << "\t" << "passive_checks_enabled=1" << "\n"
- << "\t" << "last_update=" << Utility::GetTime() << "\n"
- << "\t" << "problem_has_been_acknowledged=" << (host->GetAcknowledgement() != AcknowledgementNone ? 1 : 0) << "\n"
+ << "\t" << "host_name=" << host->GetName() << "\n";
+
+ Service::Ptr hostcheck = host->GetHostCheckService();
+
+ if (hostcheck)
+ DumpServiceStatusAttrs(fp, hostcheck, CompatStateHost);
+
+ fp << "\t" << "problem_has_been_acknowledged=" << (host->GetAcknowledgement() != AcknowledgementNone ? 1 : 0) << "\n"
<< "\t" << "acknowledgement_type=" << static_cast<int>(host->GetAcknowledgement()) << "\n"
<< "\t" << "acknowledgement_end_time=" << host->GetAcknowledgementExpiry() << "\n"
<< "\t" << "scheduled_downtime_depth=" << (host->IsInDowntime() ? 1 : 0) << "\n"
<< "\t" << "active_checks_enabled" << "\t" << 1 << "\n"
<< "\t" << "passive_checks_enabled" << "\t" << 1 << "\n";
- set<Host::Ptr> parents = host->GetParents();
+ set<Host::Ptr> parents = host->GetParentHosts();
if (!parents.empty()) {
fp << "\t" << "parents" << "\t";
<< "\n";
}
-void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& service)
+void CompatComponent::DumpServiceStatusAttrs(ofstream& fp, const Service::Ptr& service, CompatStateType type)
{
String output;
String perfdata;
if (state > StateUnknown)
state = StateUnknown;
- fp << "servicestatus {" << "\n"
- << "\t" << "host_name=" << service->GetHost()->GetName() << "\n"
- << "\t" << "service_description=" << service->GetName() << "\n"
- << "\t" << "check_interval=" << service->GetCheckInterval() / 60.0 << "\n"
+ if (type == CompatStateHost) {
+ if (state == StateOK || state == StateWarning)
+ state = 0;
+ else
+ state = 1;
+
+ if (!service->GetHost()->IsReachable())
+ state = 2;
+ }
+
+ fp << "\t" << "check_interval=" << service->GetCheckInterval() / 60.0 << "\n"
<< "\t" << "retry_interval=" << service->GetRetryInterval() / 60.0 << "\n"
<< "\t" << "has_been_checked=" << (service->GetLastCheckResult() ? 1 : 0) << "\n"
<< "\t" << "should_be_scheduled=1" << "\n"
<< "\t" << "last_hard_state_change=" << service->GetLastHardStateChange() << "\n"
<< "\t" << "last_update=" << time(NULL) << "\n"
<< "\t" << "active_checks_enabled=" << (service->GetEnableActiveChecks() ? 1 : 0) <<"\n"
- << "\t" << "passive_checks_enabled=" << (service->GetEnablePassiveChecks() ? 1 : 0) << "\n"
- << "\t" << "problem_has_been_acknowledged=" << (service->GetAcknowledgement() != AcknowledgementNone ? 1 : 0) << "\n"
+ << "\t" << "passive_checks_enabled=" << (service->GetEnablePassiveChecks() ? 1 : 0) << "\n";
+}
+
+void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& service)
+{
+ fp << "servicestatus {" << "\n"
+ << "\t" << "host_name=" << service->GetHost()->GetName() << "\n"
+ << "\t" << "service_description=" << service->GetName() << "\n";
+
+ DumpServiceStatusAttrs(fp, service, CompatStateService);
+
+ fp << "\t" << "problem_has_been_acknowledged=" << (service->GetAcknowledgement() != AcknowledgementNone ? 1 : 0) << "\n"
<< "\t" << "acknowledgement_type=" << static_cast<int>(service->GetAcknowledgement()) << "\n"
<< "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n"
<< "\t" << "scheduled_downtime_depth=" << (service->IsInDowntime() ? 1 : 0) << "\n"
<< "\t" << "}" << "\n"
<< "\n";
- Dictionary::Ptr dependencies = boost::make_shared<Dictionary>();
- service->GetDependenciesRecursive(dependencies);
-
- Value dependency;
- BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
- Service::Ptr depService = Service::GetByName(dependency);
-
- /* ignore ourselves */
- if (depService->GetName() == service->GetName())
- continue;
-
+ BOOST_FOREACH(const Service::Ptr& parent, service->GetParentServices()) {
fp << "define servicedependency {" << "\n"
<< "\t" << "dependent_host_name" << "\t" << service->GetHost()->GetName() << "\n"
<< "\t" << "dependent_service_description" << "\t" << service->GetName() << "\n"
- << "\t" << "host_name" << "\t" << depService->GetHost()->GetName() << "\n"
- << "\t" << "service_description" << "\t" << depService->GetName() << "\n"
+ << "\t" << "host_name" << "\t" << parent->GetHost()->GetName() << "\n"
+ << "\t" << "service_description" << "\t" << parent->GetName() << "\n"
<< "\t" << "execution_failure_criteria" << "\t" << "n" << "\n"
+ << "\t" << "notification_failure_criteria" << "\t" << "w,u,c" << "\n"
<< "\t" << "}" << "\n"
<< "\n";
}
objectfp.close();
if (rename(objectspathtmp.CStr(), objectspath.CStr()) < 0)
- BOOST_THROW_EXCEPTION(PosixException("rename() failed", errno));
+ BOOST_THROW_EXCEPTION(PosixException("rename() failed", errno));
}
EXPORT_COMPONENT(compat, CompatComponent);
namespace icinga
{
+enum CompatStateType
+{
+ CompatStateService,
+ CompatStateHost
+};
+
/**
* @ingroup compat
*/
void DumpHostStatus(ofstream& fp, const Host::Ptr& host);
void DumpHostObject(ofstream& fp, const Host::Ptr& host);
+ void DumpServiceStatusAttrs(ofstream& fp, const Service::Ptr& service, CompatStateType type);
+
template<typename T>
void DumpNameList(ofstream& fp, const T& list)
{
check_interval = 60,
retry_interval = 15,
- dependencies = { "localhost-ping" },
-
servicegroups = { "all-services", "snmp" },
checkers = { "*" },
hostgroups = { "all-hosts" },
- hostchecks = { "ping" },
+ hostcheck = "ping",
dependencies = { "router-ping" }
services = {
Optional. A list of host groups this host belongs to.
-Attribute: hostchecks
-^^^^^^^^^^^^^^^^^^^^^
+Attribute: hostcheck
+^^^^^^^^^^^^^^^^^^^^
-Optional. A list of services that are used to determine whether the host is up
-or down.
+Optional. A service that is used to determine whether the host is up or down.
-Attribute: dependencies
-^^^^^^^^^^^^^^^^^^^^^^^
+Attribute: hostdependencies
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Optional. A list of hosts that are used to determine whether the host is
+unreachable.
+
+Attribute: servicedependencies
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Optional. A list of services that are used to determine whether the host is
unreachable.
hostgroups = { "all-hosts" },
services = { "ping4" },
- hostchecks = { "ping4" }
+ hostcheck = "ping4"
}
type Host {
%attribute string "alias",
+ %attribute string "hostcheck",
%attribute dictionary "hostgroups" {
%attribute string "*"
},
- %attribute dictionary "dependencies" {
+ %attribute dictionary "hostdependencies" {
%attribute string "*"
},
- %attribute dictionary "hostchecks" {
+ %attribute dictionary "servicedependencies" {
%attribute string "*"
},
%attribute dictionary "services" {
%attribute dictionary "checkers" {
%attribute string "*"
},
- %attribute dictionary "dependencies" {
+ %attribute dictionary "hostdependencies" {
+ %attribute string "*"
+ },
+ %attribute dictionary "servicedependencies" {
%attribute string "*"
}
}
%attribute number "max_check_attempts",
%attribute number "check_interval",
%attribute number "retry_interval",
- %attribute dictionary "dependencies" {
+ %attribute dictionary "hostdependencies" {
+ %attribute string "*"
+ },
+ %attribute dictionary "servicedependencies" {
%attribute string "*"
},
%attribute dictionary "servicegroups" {
return Get("hostgroups");
}
-set<Host::Ptr> Host::GetParents(void)
-{
- set<Host::Ptr> parents;
-
- Dictionary::Ptr dependencies = Get("dependencies");
- if (dependencies) {
- dependencies = Service::ResolveDependencies(GetSelf(), dependencies);
-
- Value dependency;
- BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
- Service::Ptr service = Service::GetByName(dependency);
-
- Host::Ptr parent = service->GetHost();
-
- /* ignore ourselves */
- if (parent->GetName() == GetName())
- continue;
-
- parents.insert(parent);
- }
- }
-
- return parents;
-}
-
Dictionary::Ptr Host::GetMacros(void) const
{
return Get("macros");
return Get("comments");
}
+Dictionary::Ptr Host::GetHostDependencies(void) const
+{
+ return Get("hostdependencies");
+}
+
+Dictionary::Ptr Host::GetServiceDependencies(void) const
+{
+ return Get("servicedependencies");
+}
+
+String Host::GetHostCheck(void) const
+{
+ return Get("hostcheck");
+}
+
bool Host::IsReachable(void)
{
- Dictionary::Ptr dependencies = Get("dependencies");
- if (dependencies) {
- dependencies = Service::ResolveDependencies(GetSelf(), dependencies);
+ BOOST_FOREACH(const Service::Ptr& service, GetParentServices()) {
+ /* ignore pending services */
+ if (!service->GetLastCheckResult())
+ continue;
- Value dependency;
- BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
- Service::Ptr service = Service::GetByName(dependency);
+ /* ignore soft states */
+ if (service->GetStateType() == StateTypeSoft)
+ continue;
- if (!service->IsReachable() ||
- (service->GetState() != StateOK && service->GetState() != StateWarning)) {
- return false;
- }
- }
+ /* ignore services states OK and Warning */
+ if (service->GetState() == StateOK ||
+ service->GetState() == StateWarning)
+ continue;
+
+ return false;
+ }
+
+ BOOST_FOREACH(const Host::Ptr& host, GetParentHosts()) {
+ /* ignore hosts that are up */
+ if (host->IsUp())
+ continue;
+
+ return false;
}
return true;
Value checkers = serviceDesc->Get("checkers");
if (!checkers.IsEmpty())
builder->AddExpression("checkers", OperatorSet, checkers);
-
- Value dependencies = serviceDesc->Get("dependencies");
- if (!dependencies.IsEmpty())
- builder->AddExpression("dependencies", OperatorPlus,
- Service::ResolveDependencies(host, dependencies));
-
- Value hostchecks = host->Get("hostchecks");
- if (!hostchecks.IsEmpty())
- builder->AddExpression("dependencies", OperatorPlus,
- Service::ResolveDependencies(host, hostchecks));
}
void Host::ObjectCommittedHandler(const ConfigItem::Ptr& item)
task->FinishResult(Empty);
}
+
+Service::Ptr Host::ResolveService(const String& name) const
+{
+ String combinedName = GetName() + "-" + name;
+
+ if (Service::Exists(combinedName))
+ return Service::GetByName(combinedName);
+ else
+ return Service::GetByName(name);
+}
+
+set<Host::Ptr> Host::GetParentHosts(void) const
+{
+ set<Host::Ptr> parents;
+
+ Dictionary::Ptr dependencies = GetHostDependencies();
+
+ if (dependencies) {
+ String key;
+ BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
+ if (key == GetName())
+ continue;
+
+ parents.insert(Host::GetByName(key));
+ }
+ }
+
+ return parents;
+}
+
+Service::Ptr Host::GetHostCheckService(void) const
+{
+ String hostcheck = GetHostCheck();
+
+ if (hostcheck.IsEmpty())
+ return Service::Ptr();
+
+ return ResolveService(hostcheck);
+}
+
+set<Service::Ptr> Host::GetParentServices(void) const
+{
+ set<Service::Ptr> parents;
+
+ Dictionary::Ptr dependencies = GetServiceDependencies();
+
+ if (dependencies) {
+ String key;
+ BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
+ parents.insert(ResolveService(key));
+ }
+ }
+
+ return parents;
+}
+
/**
* An Icinga host.
- *
+ *
* @ingroup icinga
*/
class I2_ICINGA_API Host : public DynamicObject
String GetAlias(void) const;
Dictionary::Ptr GetGroups(void) const;
- set<Host::Ptr> GetParents(void);
Dictionary::Ptr GetMacros(void) const;
Dictionary::Ptr GetDowntimes(void) const;
Dictionary::Ptr GetComments(void) const;
+ Dictionary::Ptr GetHostDependencies(void) const;
+ Dictionary::Ptr GetServiceDependencies(void) const;
+ String GetHostCheck(void) const;
AcknowledgementType GetAcknowledgement(void);
void SetAcknowledgement(AcknowledgementType acknowledgement);
double GetAcknowledgementExpiry(void) const;
void SetAcknowledgementExpiry(double timestamp);
+ shared_ptr<Service> GetHostCheckService(void) const;
+ set<Host::Ptr> GetParentHosts(void) const;
+ set<shared_ptr<Service> > GetParentServices(void) const;
+
bool IsReachable(void);
bool IsInDowntime(void) const;
bool IsUp(void);
+ shared_ptr<Service> ResolveService(const String& name) const;
+
set<shared_ptr<Service> > GetServices(void) const;
static void InvalidateServicesCache(void);
return value;
}
-Dictionary::Ptr Service::GetDependencies(void) const
+Dictionary::Ptr Service::GetHostDependencies(void) const
{
- return Get("dependencies");
+ return Get("hostdependencies");
}
-void Service::GetDependenciesRecursive(const Dictionary::Ptr& result) const {
- assert(result);
-
- Dictionary::Ptr dependencies = GetDependencies();
-
- if (!dependencies)
- return;
-
- Value dependency;
- BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
- if (result->Contains(dependency))
- continue;
-
- result->Set(dependency, dependency);
-
- Service::Ptr service = Service::GetByName(dependency);
- service->GetDependenciesRecursive(result);
- }
+Dictionary::Ptr Service::GetServiceDependencies(void) const
+{
+ return Get("servicedependencies");
}
Dictionary::Ptr Service::GetGroups(void) const
bool Service::IsReachable(void) const
{
- Dictionary::Ptr dependencies = boost::make_shared<Dictionary>();
- GetDependenciesRecursive(dependencies);
-
- Value dependency;
- BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
- Service::Ptr service = Service::GetByName(dependency);
-
- /* ignore ourselves */
- if (service->GetName() == GetName())
- continue;
-
+ BOOST_FOREACH(const Service::Ptr& service, GetParentServices()) {
/* ignore pending services */
if (!service->GetLastCheckResult())
continue;
return false;
}
+ BOOST_FOREACH(const Host::Ptr& host, GetParentHosts()) {
+ /* ignore hosts that are up */
+ if (host->IsUp())
+ continue;
+
+ return false;
+ }
+
return true;
}
SetAcknowledgementExpiry(0);
}
- /* reschedule dependencies */
- Dictionary::Ptr dependencies = GetDependencies();
-
- if (dependencies) {
- String svc;
- BOOST_FOREACH(tie(tuples::ignore, svc), dependencies) {
- if (!Service::Exists(svc))
- continue;
+ /* reschedule service dependencies */
+ BOOST_FOREACH(const Service::Ptr& parent, GetParentServices()) {
+ parent->SetNextCheck(Utility::GetTime());
+ }
- Service::Ptr service = Service::GetByName(svc);
+ /* reschedule host dependencies */
+ BOOST_FOREACH(const Host::Ptr& parent, GetParentHosts()) {
+ String hostcheck = parent->GetHostCheck();
+ if (!hostcheck.IsEmpty()) {
+ Service::Ptr service = parent->ResolveService(hostcheck);
service->SetNextCheck(Utility::GetTime());
}
}
+
+ // TODO: notify our child services/hosts that our state has changed
}
-
+
if (GetState() != StateOK)
DowntimeProcessor::TriggerDowntimes(GetSelf());
}
EndpointManager::GetInstance()->SendMulticastMessage(rm);
}
+set<Host::Ptr> Service::GetParentHosts(void) const
+{
+ set<Host::Ptr> parents;
+
+ /* The service's host is implicitly a parent. */
+ parents.insert(GetHost());
+
+ Dictionary::Ptr dependencies = GetHostDependencies();
+
+ if (dependencies) {
+ String key;
+ BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
+ parents.insert(Host::GetByName(key));
+ }
+ }
+
+ return parents;
+}
+
+set<Service::Ptr> Service::GetParentServices(void) const
+{
+ set<Service::Ptr> parents;
+
+ Dictionary::Ptr dependencies = GetServiceDependencies();
+
+ if (dependencies) {
+ String key;
+ BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
+ Service::Ptr service = GetHost()->ResolveService(key);
+
+ if (service->GetName() == GetName())
+ continue;
+
+ parents.insert(service);
+ }
+ }
+
+ return parents;
+}
long GetMaxCheckAttempts(void) const;
long GetCheckInterval(void) const;
long GetRetryInterval(void) const;
- Dictionary::Ptr GetDependencies(void) const;
- void GetDependenciesRecursive(const Dictionary::Ptr& result) const;
+ Dictionary::Ptr GetHostDependencies(void) const;
+ Dictionary::Ptr GetServiceDependencies(void) const;
Dictionary::Ptr GetGroups(void) const;
Dictionary::Ptr GetCheckers(void) const;
+ set<Host::Ptr> GetParentHosts(void) const;
+ set<Service::Ptr> GetParentServices(void) const;
+
bool IsReachable(void) const;
bool IsInDowntime(void) const;
void SetSchedulingOffset(long offset);
void SetFirstCheck(bool first);
- bool GetFirstCheck(void) const;
+ bool GetFirstCheck(void) const;
void SetNextCheck(double nextCheck);
double GetNextCheck(void);