diff --git a/components/compat/compatcomponent.cpp b/components/compat/compatcomponent.cpp index 3a24bc770..db0b15b04 100644 --- a/components/compat/compatcomponent.cpp +++ b/components/compat/compatcomponent.cpp @@ -278,21 +278,14 @@ void CompatComponent::DumpHostStatus(ofstream& fp, const Host::Ptr& host) 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(host->GetAcknowledgement()) << "\n" << "\t" << "acknowledgement_end_time=" << host->GetAcknowledgementExpiry() << "\n" << "\t" << "scheduled_downtime_depth=" << (host->IsInDowntime() ? 1 : 0) << "\n" @@ -314,7 +307,7 @@ void CompatComponent::DumpHostObject(ofstream& fp, const Host::Ptr& host) << "\t" << "active_checks_enabled" << "\t" << 1 << "\n" << "\t" << "passive_checks_enabled" << "\t" << 1 << "\n"; - set parents = host->GetParents(); + set parents = host->GetParentHosts(); if (!parents.empty()) { fp << "\t" << "parents" << "\t"; @@ -326,7 +319,7 @@ void CompatComponent::DumpHostObject(ofstream& fp, const Host::Ptr& host) << "\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; @@ -351,10 +344,17 @@ void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& servic 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" @@ -372,8 +372,18 @@ void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& servic << "\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(service->GetAcknowledgement()) << "\n" << "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n" << "\t" << "scheduled_downtime_depth=" << (service->IsInDowntime() ? 1 : 0) << "\n" @@ -399,23 +409,14 @@ void CompatComponent::DumpServiceObject(ofstream& fp, const Service::Ptr& servic << "\t" << "}" << "\n" << "\n"; - Dictionary::Ptr dependencies = boost::make_shared(); - 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"; } @@ -543,7 +544,7 @@ void CompatComponent::StatusTimerHandler(void) 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); diff --git a/components/compat/compatcomponent.h b/components/compat/compatcomponent.h index 94458e40c..c1d15a4b1 100644 --- a/components/compat/compatcomponent.h +++ b/components/compat/compatcomponent.h @@ -23,6 +23,12 @@ namespace icinga { +enum CompatStateType +{ + CompatStateService, + CompatStateHost +}; + /** * @ingroup compat */ @@ -52,6 +58,8 @@ private: 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 void DumpNameList(ofstream& fp, const T& list) { diff --git a/docs/icinga2-config.txt b/docs/icinga2-config.txt index 147f7b461..bc9614e5b 100644 --- a/docs/icinga2-config.txt +++ b/docs/icinga2-config.txt @@ -626,8 +626,6 @@ object Service "localhost-uptime" { check_interval = 60, retry_interval = 15, - dependencies = { "localhost-ping" }, - servicegroups = { "all-services", "snmp" }, checkers = { "*" }, @@ -722,7 +720,7 @@ object Host "localhost" { hostgroups = { "all-hosts" }, - hostchecks = { "ping" }, + hostcheck = "ping", dependencies = { "router-ping" } services = { @@ -756,14 +754,19 @@ Attribute: hostgroups 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. diff --git a/itl/host.conf b/itl/host.conf index a68983bdd..3abf30316 100644 --- a/itl/host.conf +++ b/itl/host.conf @@ -25,5 +25,5 @@ abstract object Host "itl-host" { hostgroups = { "all-hosts" }, services = { "ping4" }, - hostchecks = { "ping4" } + hostcheck = "ping4" } diff --git a/itl/types.conf b/itl/types.conf index e5b1bba15..841a9da66 100644 --- a/itl/types.conf +++ b/itl/types.conf @@ -50,13 +50,14 @@ type Logger { 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" { @@ -79,7 +80,10 @@ type Host { %attribute dictionary "checkers" { %attribute string "*" }, - %attribute dictionary "dependencies" { + %attribute dictionary "hostdependencies" { + %attribute string "*" + }, + %attribute dictionary "servicedependencies" { %attribute string "*" } } @@ -128,7 +132,10 @@ type Service { %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" { diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index e3ac52799..ab0dbb0c4 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -86,31 +86,6 @@ Dictionary::Ptr Host::GetGroups(void) const return Get("hostgroups"); } -set Host::GetParents(void) -{ - set 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"); @@ -130,21 +105,46 @@ Dictionary::Ptr Host::GetComments(void) const 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; @@ -211,16 +211,6 @@ static void CopyServiceAttributes(const Host::Ptr& host, TDict serviceDesc, 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) @@ -444,3 +434,59 @@ void Host::ValidateServiceDictionary(const ScriptTask::Ptr& task, const vectorFinishResult(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::GetParentHosts(void) const +{ + set 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 Host::GetParentServices(void) const +{ + set parents; + + Dictionary::Ptr dependencies = GetServiceDependencies(); + + if (dependencies) { + String key; + BOOST_FOREACH(tie(key, tuples::ignore), dependencies) { + parents.insert(ResolveService(key)); + } + } + + return parents; +} + diff --git a/lib/icinga/host.h b/lib/icinga/host.h index 81f8e2e9d..4c73f715a 100644 --- a/lib/icinga/host.h +++ b/lib/icinga/host.h @@ -27,7 +27,7 @@ class Service; /** * An Icinga host. - * + * * @ingroup icinga */ class I2_ICINGA_API Host : public DynamicObject @@ -45,10 +45,12 @@ public: String GetAlias(void) const; Dictionary::Ptr GetGroups(void) const; - set 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); @@ -56,10 +58,16 @@ public: double GetAcknowledgementExpiry(void) const; void SetAcknowledgementExpiry(double timestamp); + shared_ptr GetHostCheckService(void) const; + set GetParentHosts(void) const; + set > GetParentServices(void) const; + bool IsReachable(void); bool IsInDowntime(void) const; bool IsUp(void); + shared_ptr ResolveService(const String& name) const; + set > GetServices(void) const; static void InvalidateServicesCache(void); diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index dbd586771..6b0888ff8 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -159,29 +159,14 @@ long Service::GetRetryInterval(void) const 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 @@ -196,17 +181,7 @@ Dictionary::Ptr Service::GetCheckers(void) const bool Service::IsReachable(void) const { - Dictionary::Ptr dependencies = boost::make_shared(); - 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; @@ -223,6 +198,14 @@ bool Service::IsReachable(void) const return false; } + BOOST_FOREACH(const Host::Ptr& host, GetParentHosts()) { + /* ignore hosts that are up */ + if (host->IsUp()) + continue; + + return false; + } + return true; } @@ -539,21 +522,23 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr) SetAcknowledgementExpiry(0); } - /* reschedule dependencies */ - Dictionary::Ptr dependencies = GetDependencies(); + /* reschedule service dependencies */ + BOOST_FOREACH(const Service::Ptr& parent, GetParentServices()) { + parent->SetNextCheck(Utility::GetTime()); + } - if (dependencies) { - String svc; - BOOST_FOREACH(tie(tuples::ignore, svc), dependencies) { - if (!Service::Exists(svc)) - continue; - - 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()); } @@ -765,3 +750,42 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr) EndpointManager::GetInstance()->SendMulticastMessage(rm); } +set Service::GetParentHosts(void) const +{ + set 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::GetParentServices(void) const +{ + set 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; +} diff --git a/lib/icinga/service.h b/lib/icinga/service.h index d56ccc340..d579b577b 100644 --- a/lib/icinga/service.h +++ b/lib/icinga/service.h @@ -81,11 +81,14 @@ public: 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 GetParentHosts(void) const; + set GetParentServices(void) const; + bool IsReachable(void) const; bool IsInDowntime(void) const; @@ -93,7 +96,7 @@ public: void SetSchedulingOffset(long offset); void SetFirstCheck(bool first); - bool GetFirstCheck(void) const; + bool GetFirstCheck(void) const; void SetNextCheck(double nextCheck); double GetNextCheck(void);