Implement service shortnames.

Refs #3660
This commit is contained in:
Gunnar Beutner 2013-02-08 15:38:22 +01:00
parent 39008eff4e
commit 3458b7d9d1
8 changed files with 83 additions and 109 deletions

View File

@ -127,7 +127,7 @@ void CheckerComponent::CheckTimerHandler(void)
if (tasks > 0) {
stringstream msgbuf;
msgbuf << "CheckTimerHandler: created " << tasks << " task(s)";
Logger::Write(LogInformation, "checker", msgbuf.str());
Logger::Write(LogDebug, "checker", msgbuf.str());
}
RescheduleCheckTimer();

View File

@ -200,7 +200,7 @@ void CompatComponent::DumpComments(ofstream& fp, const DynamicObject::Ptr& owner
fp << "hostcomment {" << "\n";
else
fp << "servicecomment {" << "\n"
<< "\t" << "service_description=" << service->GetAlias() << "\n";
<< "\t" << "service_description=" << service->GetShortName() << "\n";
fp << "\t" << "host_name=" << host->GetName() << "\n"
<< "\t" << "comment_id=" << static_cast<String>(comment->Get("legacy_id")) << "\n"
@ -245,7 +245,7 @@ void CompatComponent::DumpDowntimes(ofstream& fp, const DynamicObject::Ptr& owne
fp << "hostdowntime {" << "\n";
else
fp << "servicedowntime {" << "\n"
<< "\t" << "service_description=" << service->GetAlias() << "\n";
<< "\t" << "service_description=" << service->GetShortName() << "\n";
Dictionary::Ptr triggeredByObj = DowntimeProcessor::GetDowntimeByID(downtime->Get("triggered_by"));
int triggeredByLegacy = 0;
@ -381,7 +381,7 @@ void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& servic
{
fp << "servicestatus {" << "\n"
<< "\t" << "host_name=" << service->GetHost()->GetName() << "\n"
<< "\t" << "service_description=" << service->GetName() << "\n";
<< "\t" << "service_description=" << service->GetShortName() << "\n";
DumpServiceStatusAttrs(fp, service, CompatStateService);
@ -400,7 +400,7 @@ void CompatComponent::DumpServiceObject(ofstream& fp, const Service::Ptr& servic
{
fp << "define service {" << "\n"
<< "\t" << "host_name" << "\t" << service->GetHost()->GetName() << "\n"
<< "\t" << "service_description" << "\t" << service->GetName() << "\n"
<< "\t" << "service_description" << "\t" << service->GetShortName() << "\n"
<< "\t" << "display_name" << "\t" << service->GetAlias() << "\n"
<< "\t" << "check_command" << "\t" << "check_i2" << "\n"
<< "\t" << "check_interval" << "\t" << service->GetCheckInterval() / 60.0 << "\n"
@ -414,9 +414,9 @@ void CompatComponent::DumpServiceObject(ofstream& fp, const Service::Ptr& servic
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" << "dependent_service_description" << "\t" << service->GetShortName() << "\n"
<< "\t" << "host_name" << "\t" << parent->GetHost()->GetName() << "\n"
<< "\t" << "service_description" << "\t" << parent->GetName() << "\n"
<< "\t" << "service_description" << "\t" << parent->GetShortName() << "\n"
<< "\t" << "execution_failure_criteria" << "\t" << "n" << "\n"
<< "\t" << "notification_failure_criteria" << "\t" << "w,u,c" << "\n"
<< "\t" << "}" << "\n"

View File

@ -124,6 +124,8 @@ type Service {
%require "host_name",
%attribute string "host_name",
%attribute string "short_name",
%attribute string "alias",
%attribute dictionary "macros" {
%attribute string "*"

View File

@ -122,10 +122,7 @@ void ExternalCommandProcessor::ProcessServiceCheckResult(double time, const vect
if (arguments.size() < 4)
BOOST_THROW_EXCEPTION(invalid_argument("Expected 4 arguments."));
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
if (!service->GetEnablePassiveChecks())
BOOST_THROW_EXCEPTION(invalid_argument("Got passive check result for service '" + arguments[1] + "' which has passive checks disabled."));
@ -154,10 +151,7 @@ void ExternalCommandProcessor::ScheduleSvcCheck(double, const vector<String>& ar
if (arguments.size() < 3)
BOOST_THROW_EXCEPTION(invalid_argument("Expected 3 arguments."));
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
double planned_check = Convert::ToDouble(arguments[2]);
@ -176,10 +170,7 @@ void ExternalCommandProcessor::ScheduleForcedSvcCheck(double, const vector<Strin
if (arguments.size() < 3)
BOOST_THROW_EXCEPTION(invalid_argument("Expected 3 arguments."));
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + arguments[1] + "'");
service->SetForceNextCheck(true);
@ -191,10 +182,7 @@ void ExternalCommandProcessor::EnableSvcCheck(double, const vector<String>& argu
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + arguments[1] + "'");
service->SetEnableActiveChecks(true);
@ -205,10 +193,7 @@ void ExternalCommandProcessor::DisableSvcCheck(double, const vector<String>& arg
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + arguments[1] + "'");
service->SetEnableActiveChecks(false);
@ -305,7 +290,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const vector<String
bool sticky = Convert::ToBool(arguments[2]);
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
if (service->GetState() == StateOK)
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' is OK."));
@ -326,7 +311,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const vector<
bool sticky = Convert::ToBool(arguments[2]);
double timestamp = Convert::ToDouble(arguments[5]);
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
if (service->GetState() == StateOK)
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' is OK."));
@ -480,10 +465,7 @@ void ExternalCommandProcessor::EnablePassiveSvcChecks(double, const vector<Strin
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + arguments[1] + "'");
service->SetEnablePassiveChecks(true);
@ -494,10 +476,7 @@ void ExternalCommandProcessor::DisablePassiveSvcChecks(double, const vector<Stri
if (arguments.size() < 2)
BOOST_THROW_EXCEPTION(invalid_argument("Expected 2 arguments."));
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + arguments[1] + "'");
service->SetEnablePassiveChecks(false);
@ -610,10 +589,7 @@ void ExternalCommandProcessor::ScheduleSvcDowntime(double, const vector<String>&
if (arguments.size() < 9)
BOOST_THROW_EXCEPTION(invalid_argument("Expected 9 arguments."));
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
String triggeredBy;
int triggeredByLegacy = Convert::ToLong(arguments[5]);
@ -844,7 +820,7 @@ void ExternalCommandProcessor::AddSvcComment(double, const vector<String>& argum
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Creating comment for service " + service->GetName());
(void) CommentProcessor::AddComment(service, Comment_User, arguments[3], arguments[4], 0);
@ -884,9 +860,8 @@ void ExternalCommandProcessor::DelAllSvcComments(double, const vector<String>& a
if (!Service::Exists(arguments[1]))
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' does not exist."));
Service::Ptr service = Service::GetByName(arguments[1]);
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Removing all comments for service " + service->GetName());
CommentProcessor::RemoveAllComments(service);
}

View File

@ -21,7 +21,7 @@
using namespace icinga;
map<String, vector<Service::WeakPtr> > Host::m_ServicesCache;
map<String, map<String, weak_ptr<Service> > > Host::m_ServicesCache;
bool Host::m_ServicesCacheValid = true;
REGISTER_SCRIPTFUNCTION("native::ValidateServiceDictionary", &Host::ValidateServiceDictionary);
@ -166,28 +166,14 @@ bool Host::IsInDowntime(void) const
return false;
}
bool Host::IsUp(void)
bool Host::IsUp(void) const
{
Dictionary::Ptr hostchecks = Get("hostchecks");
if (hostchecks) {
hostchecks = Service::ResolveDependencies(GetSelf(), hostchecks);
Value hostcheck;
BOOST_FOREACH(tie(tuples::ignore, hostcheck), hostchecks) {
Service::Ptr service = Service::GetByName(hostcheck);
if (service->GetState() != StateOK && service->GetState() != StateWarning) {
return false;
}
}
}
return true;
Service::Ptr service = GetHostCheckService();
return (!service || service->GetState() == StateOK || service->GetState() == StateWarning);
}
template<typename TDict>
static void CopyServiceAttributes(const Host::Ptr& host, TDict serviceDesc,
const ConfigItemBuilder::Ptr& builder)
static void CopyServiceAttributes(TDict serviceDesc, const ConfigItemBuilder::Ptr& builder)
{
/* TODO: we only need to copy macros if this is an inline definition,
* i.e. host->GetProperties() != service, however for now we just
@ -244,8 +230,9 @@ void Host::ObjectCommittedHandler(const ConfigItem::Ptr& item)
builder->SetName(name);
builder->AddExpression("host_name", OperatorSet, item->GetName());
builder->AddExpression("alias", OperatorSet, svcname);
builder->AddExpression("short_name", OperatorSet, svcname);
CopyServiceAttributes(host, host, builder);
CopyServiceAttributes(host, builder);
if (svcdesc.IsScalar()) {
builder->AddParent(svcdesc);
@ -258,7 +245,7 @@ void Host::ObjectCommittedHandler(const ConfigItem::Ptr& item)
builder->AddParent(parent);
CopyServiceAttributes(host, service, builder);
CopyServiceAttributes(service, builder);
} else {
BOOST_THROW_EXCEPTION(invalid_argument("Service description must be either a string or a dictionary."));
}
@ -319,8 +306,10 @@ set<Service::Ptr> Host::GetServices(void) const
ValidateServicesCache();
BOOST_FOREACH(const Service::WeakPtr& svc, m_ServicesCache[GetName()]) {
Service::Ptr service = svc.lock();
String key;
Service::WeakPtr wservice;
BOOST_FOREACH(tie(key, wservice), m_ServicesCache[GetName()]) {
Service::Ptr service = wservice.lock();
if (!service)
continue;
@ -391,7 +380,9 @@ void Host::ValidateServicesCache(void)
BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
const Service::Ptr& service = static_pointer_cast<Service>(object);
m_ServicesCache[service->GetHost()->GetName()].push_back(service);
// TODO: assert for duplicate short_names
m_ServicesCache[service->GetHost()->GetName()][service->GetShortName()] = service;
}
m_ServicesCacheValid = true;
@ -435,13 +426,19 @@ void Host::ValidateServiceDictionary(const ScriptTask::Ptr& task, const vector<V
task->FinishResult(Empty);
}
Service::Ptr Host::ResolveService(const String& name) const
Service::Ptr Host::GetServiceByShortName(const String& name) const
{
String combinedName = GetName() + "-" + name;
ValidateServicesCache();
map<String, weak_ptr<Service> >& services = m_ServicesCache[GetName()];
map<String, weak_ptr<Service> >::iterator it = services.find(name);
if (it != services.end()) {
Service::Ptr service = it->second.lock();
assert(service);
return service;
}
if (Service::Exists(combinedName))
return Service::GetByName(combinedName);
else
return Service::GetByName(name);
}
@ -471,7 +468,7 @@ Service::Ptr Host::GetHostCheckService(void) const
if (hostcheck.IsEmpty())
return Service::Ptr();
return ResolveService(hostcheck);
return GetServiceByShortName(hostcheck);
}
set<Service::Ptr> Host::GetParentServices(void) const
@ -483,10 +480,10 @@ set<Service::Ptr> Host::GetParentServices(void) const
if (dependencies) {
String key;
BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
parents.insert(ResolveService(key));
// TODO(#3660): look up { host = "name", service = "name" } pairs
parents.insert(GetServiceByShortName(key));
}
}
return parents;
}

View File

@ -64,9 +64,9 @@ public:
bool IsReachable(void);
bool IsInDowntime(void) const;
bool IsUp(void);
bool IsUp(void) const;
shared_ptr<Service> ResolveService(const String& name) const;
shared_ptr<Service> GetServiceByShortName(const String& name) const;
set<shared_ptr<Service> > GetServices(void) const;
static void InvalidateServicesCache(void);
@ -80,7 +80,7 @@ protected:
private:
static bool m_InitializerDone;
static map<String, vector<weak_ptr<Service> > > m_ServicesCache;
static map<String, map<String, weak_ptr<Service> > > m_ServicesCache;
static bool m_ServicesCacheValid;
static void ObjectCommittedHandler(const ConfigItem::Ptr& item);

View File

@ -91,6 +91,16 @@ Service::Ptr Service::GetByName(const String& name)
return dynamic_pointer_cast<Service>(configObject);
}
Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName)
{
if (!hostName.IsEmpty()) {
Host::Ptr host = Host::GetByName(hostName);
return host->GetServiceByShortName(serviceName);
} else {
return Service::GetByName(serviceName);
}
}
Host::Ptr Service::GetHost(void) const
{
String hostname = Get("host_name");
@ -175,6 +185,16 @@ Dictionary::Ptr Service::GetCheckers(void) const
return Get("checkers");
}
String Service::GetShortName(void) const
{
Value value = Get("short_name");
if (value.IsEmpty())
return GetName();
return value;
}
bool Service::IsReachable(void) const
{
BOOST_FOREACH(const Service::Ptr& service, GetParentServices()) {
@ -529,12 +549,11 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
/* reschedule host dependencies */
BOOST_FOREACH(const Host::Ptr& parent, GetParentHosts()) {
String hostcheck = parent->GetHostCheck();
if (!hostcheck.IsEmpty()) {
Service::Ptr service = parent->ResolveService(hostcheck);
Service::Ptr service = parent->GetHostCheckService();
if (service)
service->SetNextCheck(Utility::GetTime());
}
}
// TODO: notify our child services/hosts that our state has changed
}
@ -606,27 +625,6 @@ bool Service::IsAllowedChecker(const String& checker) const
return false;
}
Dictionary::Ptr Service::ResolveDependencies(const Host::Ptr& host, const Dictionary::Ptr& dependencies)
{
Dictionary::Ptr services = host->Get("services");
Dictionary::Ptr result = boost::make_shared<Dictionary>();
Value dependency;
BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
String name;
if (services && services->Contains(dependency))
name = host->GetName() + "-" + static_cast<String>(dependency);
else
name = static_cast<String>(dependency);
result->Set(name, name);
}
return result;
}
void Service::OnAttributeChanged(const String& name, const Value& oldValue)
{
if (name == "checker")
@ -635,7 +633,7 @@ void Service::OnAttributeChanged(const String& name, const Value& oldValue)
OnNextCheckChanged(GetSelf(), oldValue);
else if (name == "servicegroups")
ServiceGroup::InvalidateMembersCache();
else if (name == "host_name")
else if (name == "host_name" || name == "short_name")
Host::InvalidateServicesCache();
else if (name == "downtimes")
DowntimeProcessor::InvalidateDowntimeCache();
@ -780,7 +778,8 @@ set<Service::Ptr> Service::GetParentServices(void) const
if (dependencies) {
String key;
BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
Service::Ptr service = GetHost()->ResolveService(key);
// TODO(#3660): look up { host = "name", service = "name" } pairs
Service::Ptr service = GetHost()->GetServiceByShortName(key);
if (service->GetName() == GetName())
continue;

View File

@ -67,6 +67,8 @@ public:
static bool Exists(const String& name);
static Service::Ptr GetByName(const String& name);
static Service::Ptr GetByNamePair(const String& hostName, const String& serviceName);
static const int DefaultMaxCheckAttempts;
static const int DefaultCheckInterval;
static const int CheckIntervalDivisor;
@ -84,6 +86,7 @@ public:
Dictionary::Ptr GetServiceDependencies(void) const;
Dictionary::Ptr GetGroups(void) const;
Dictionary::Ptr GetCheckers(void) const;
String GetShortName(void) const;
set<Host::Ptr> GetParentHosts(void) const;
set<Service::Ptr> GetParentServices(void) const;
@ -150,8 +153,6 @@ public:
static ServiceStateType StateTypeFromString(const String& state);
static String StateTypeToString(ServiceStateType state);
static Dictionary::Ptr ResolveDependencies(const Host::Ptr& host, const Dictionary::Ptr& dependencies);
static boost::signal<void (const Service::Ptr& service, const CheckResultMessage&)> OnCheckResultReceived;
static boost::signal<void (const Service::Ptr&, const String&)> OnCheckerChanged;
static boost::signal<void (const Service::Ptr&, const Value&)> OnNextCheckChanged;