From 00fd51e6281429d457b48836f8d4cf92cb45e192 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 5 Apr 2014 22:17:20 +0200 Subject: [PATCH] Implement relative object names. Fixes #5925 --- lib/base/dynamicobject.ti | 7 ++++++ lib/config/configitem.cpp | 39 ++++++++++++++++++++++++++++--- lib/icinga/dependency-apply.cpp | 6 +---- lib/icinga/dependency.cpp | 15 ++++++++++++ lib/icinga/dependency.ti | 10 +++++++- lib/icinga/notification-apply.cpp | 6 +---- lib/icinga/notification.cpp | 15 ++++++++++++ lib/icinga/notification.ti | 10 +++++++- lib/icinga/scheduleddowntime.cpp | 15 ++++++++++++ lib/icinga/scheduleddowntime.ti | 10 +++++++- lib/icinga/service-apply.cpp | 6 +---- lib/icinga/service.cpp | 7 ++++++ lib/icinga/service.ti | 10 +++++++- tools/mkclass/class_parser.yy | 22 ++++++++++++++--- tools/mkclass/classcompiler.cpp | 9 +++++-- tools/mkclass/classcompiler.h | 1 + 16 files changed, 161 insertions(+), 27 deletions(-) diff --git a/lib/base/dynamicobject.ti b/lib/base/dynamicobject.ti index 49d2c642c..bcd7c9b15 100644 --- a/lib/base/dynamicobject.ti +++ b/lib/base/dynamicobject.ti @@ -1,6 +1,13 @@ namespace icinga { +code {{{ +class DynamicObjectNameHelper { +public: + virtual String MakeObjectName(const String& shortName, const Dictionary::Ptr props) const = 0; +}; +}}} + abstract class DynamicObject { [config] String __name (Name); diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 4889891a3..baaf0e5d7 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -117,12 +117,28 @@ Dictionary::Ptr ConfigItem::GetProperties(void) if (!m_Properties) { m_Properties = make_shared(); m_Properties->Set("type", m_Type); - m_Properties->Set("__name", m_Name); + m_Properties->Set("name", m_Name); m_Properties->Set("__parent", m_Scope); GetExpressionList()->Evaluate(m_Properties); + m_Properties->Remove("name"); m_Properties->Remove("__parent"); - VERIFY(m_Properties->Get("type") == GetType() && m_Properties->Get("__name") == GetName()); + String name = m_Name; + + if (!m_Abstract) { + const DynamicObjectNameHelper *nh = dynamic_cast(Type::GetByName(m_Type)); + + if (nh) { + String name = nh->MakeObjectName(m_Name, m_Properties); + + if (name.IsEmpty()) + BOOST_THROW_EXCEPTION(std::runtime_error("Could not determine name for object")); + } + } + + m_Properties->Set("__name", name); + + VERIFY(m_Properties->Get("type") == GetType()); } return m_Properties; @@ -175,7 +191,24 @@ DynamicObject::Ptr ConfigItem::Commit(void) */ void ConfigItem::Register(void) { - std::pair key = std::make_pair(m_Type, m_Name); + String name = m_Name; + + /* If this is a non-abstract object we need to figure out + * its real name now - or assign it a temporary name. */ + if (!m_Abstract) { + const DynamicObjectNameHelper *nh = dynamic_cast(Type::GetByName(m_Type)); + + if (nh) { + name = nh->MakeObjectName(m_Name, Dictionary::Ptr()); + + ASSERT(name.IsEmpty() || name == m_Name); + + if (name.IsEmpty()) + name = Utility::NewUniqueID(); + } + } + + std::pair key = std::make_pair(m_Type, name); ConfigItem::Ptr self = GetSelf(); boost::mutex::scoped_lock lock(m_Mutex); diff --git a/lib/icinga/dependency-apply.cpp b/lib/icinga/dependency-apply.cpp index 9be15fe94..f9134cdda 100644 --- a/lib/icinga/dependency-apply.cpp +++ b/lib/icinga/dependency-apply.cpp @@ -63,13 +63,9 @@ void Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR msgbuf2 << "Applying dependency '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di; Log(LogDebug, "icinga", msgbuf2.str()); - std::ostringstream namebuf; - namebuf << checkable->GetName() << "!" << rule.GetName(); - String name = namebuf.str(); - ConfigItemBuilder::Ptr builder = make_shared(di); builder->SetType("Dependency"); - builder->SetName(name); + builder->SetName(rule.GetName()); builder->SetScope(rule.GetScope()); builder->AddExpression(make_shared(&AExpression::OpSet, diff --git a/lib/icinga/dependency.cpp b/lib/icinga/dependency.cpp index 28d332554..4c070f80b 100644 --- a/lib/icinga/dependency.cpp +++ b/lib/icinga/dependency.cpp @@ -28,6 +28,21 @@ using namespace icinga; REGISTER_TYPE(Dependency); +String DependencyNameHelper::MakeObjectName(const String& shortName, const Dictionary::Ptr props) const +{ + if (!props) + return ""; + + String name = props->Get("child_host_name"); + + if (props->Contains("child_service_name")) + name += "!" + props->Get("child_service_name"); + + name += "!" + shortName; + + return name; +} + void Dependency::OnStateLoaded(void) { DynamicObject::Start(); diff --git a/lib/icinga/dependency.ti b/lib/icinga/dependency.ti index 94d8649c7..42a4c950f 100644 --- a/lib/icinga/dependency.ti +++ b/lib/icinga/dependency.ti @@ -4,7 +4,15 @@ namespace icinga { -class Dependency : DynamicObject +code {{{ +class I2_ICINGA_API DependencyNameHelper : public DynamicObjectNameHelper +{ +public: + virtual String MakeObjectName(const String& shortName, const Dictionary::Ptr props) const; +}; +}}} + +class Dependency : DynamicObject < DependencyNameHelper { [config] String child_host_name; [config] String child_service_name; diff --git a/lib/icinga/notification-apply.cpp b/lib/icinga/notification-apply.cpp index 5149a2aa1..8537191c2 100644 --- a/lib/icinga/notification-apply.cpp +++ b/lib/icinga/notification-apply.cpp @@ -62,13 +62,9 @@ void Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl msgbuf2 << "Applying notification '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di; Log(LogDebug, "icinga", msgbuf2.str()); - std::ostringstream namebuf; - namebuf << checkable->GetName() << "!" << rule.GetName(); - String name = namebuf.str(); - ConfigItemBuilder::Ptr builder = make_shared(di); builder->SetType("Notification"); - builder->SetName(name); + builder->SetName(rule.GetName()); builder->SetScope(rule.GetScope()); builder->AddExpression(make_shared(&AExpression::OpSet, diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index f4d47f583..22ae544b0 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -38,6 +38,21 @@ INITIALIZE_ONCE(&Notification::StaticInitialize); boost::signals2::signal Notification::OnNextNotificationChanged; +String NotificationNameHelper::MakeObjectName(const String& shortName, const Dictionary::Ptr props) const +{ + if (!props) + return ""; + + String name = props->Get("host_name"); + + if (props->Contains("service_name")) + name += "!" + props->Get("service_name"); + + name += "!" + shortName; + + return name; +} + void Notification::StaticInitialize(void) { ScriptVariable::Set("NotificationDowntimeStart", NotificationDowntimeStart, true, true); diff --git a/lib/icinga/notification.ti b/lib/icinga/notification.ti index 7449275fa..4687323b3 100644 --- a/lib/icinga/notification.ti +++ b/lib/icinga/notification.ti @@ -3,7 +3,15 @@ namespace icinga { -class Notification : DynamicObject +code {{{ +class I2_ICINGA_API NotificationNameHelper : public DynamicObjectNameHelper +{ +public: + virtual String MakeObjectName(const String& shortName, const Dictionary::Ptr props) const; +}; +}}} + +class Notification : DynamicObject < NotificationNameHelper { [config, protected] String notification_command (NotificationCommandRaw); [config] double notification_interval { diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index 826b8e376..7b8a5504f 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -37,6 +37,21 @@ INITIALIZE_ONCE(&ScheduledDowntime::StaticInitialize); static Timer::Ptr l_Timer; +String ScheduledDowntimeNameHelper::MakeObjectName(const String& shortName, const Dictionary::Ptr props) const +{ + if (!props) + return ""; + + String name = props->Get("host_name"); + + if (props->Contains("service_name")) + name += "!" + props->Get("service_name"); + + name += "!" + shortName; + + return name; +} + void ScheduledDowntime::StaticInitialize(void) { l_Timer = make_shared(); diff --git a/lib/icinga/scheduleddowntime.ti b/lib/icinga/scheduleddowntime.ti index 9f25e1cf1..72a30aa33 100644 --- a/lib/icinga/scheduleddowntime.ti +++ b/lib/icinga/scheduleddowntime.ti @@ -3,7 +3,15 @@ namespace icinga { -class ScheduledDowntime : DynamicObject +code {{{ +class I2_ICINGA_API ScheduledDowntimeNameHelper : public DynamicObjectNameHelper +{ +public: + virtual String MakeObjectName(const String& shortName, const Dictionary::Ptr props) const; +}; +}}} + +class ScheduledDowntime : DynamicObject < ScheduledDowntimeNameHelper { [config, protected] String host_name; [config, protected] String service_name; diff --git a/lib/icinga/service-apply.cpp b/lib/icinga/service-apply.cpp index 068d53494..15971a1ce 100644 --- a/lib/icinga/service-apply.cpp +++ b/lib/icinga/service-apply.cpp @@ -55,13 +55,9 @@ void Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule) msgbuf2 << "Applying service '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di; Log(LogDebug, "icinga", msgbuf2.str()); - std::ostringstream namebuf; - namebuf << host->GetName() << "!" << rule.GetName(); - String name = namebuf.str(); - ConfigItemBuilder::Ptr builder = make_shared(di); builder->SetType("Service"); - builder->SetName(name); + builder->SetName(rule.GetName()); builder->SetScope(rule.GetScope()); builder->AddExpression(make_shared(&AExpression::OpSet, diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index 04b093d6e..7bcb6c58a 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -39,6 +39,13 @@ REGISTER_TYPE(Service); INITIALIZE_ONCE(&Service::StartDowntimesExpiredTimer); +String ServiceNameHelper::MakeObjectName(const String& shortName, const Dictionary::Ptr props) const { + if (!props) + return ""; + + return props->Get("host_name") + "!" + shortName; +} + void Service::OnConfigLoaded(void) { Array::Ptr groups = GetGroups(); diff --git a/lib/icinga/service.ti b/lib/icinga/service.ti index f48033500..efdca994d 100644 --- a/lib/icinga/service.ti +++ b/lib/icinga/service.ti @@ -6,7 +6,15 @@ namespace icinga { -class Service : Checkable +code {{{ +class I2_ICINGA_API ServiceNameHelper : public DynamicObjectNameHelper +{ +public: + virtual String MakeObjectName(const String& shortName, const Dictionary::Ptr props) const; +}; +}}} + +class Service : Checkable < ServiceNameHelper { [config] String display_name { get {{{ diff --git a/tools/mkclass/class_parser.yy b/tools/mkclass/class_parser.yy index 689cd8634..cb530dd25 100644 --- a/tools/mkclass/class_parser.yy +++ b/tools/mkclass/class_parser.yy @@ -66,6 +66,7 @@ using namespace icinga; %type identifier %type alternative_name_specifier %type inherits_specifier +%type type_base_specifier %type include %type angle_include %type code @@ -166,7 +167,7 @@ code: T_CODE T_STRING } ; -class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier '{' class_fields '}' ';' +class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier type_base_specifier '{' class_fields '}' ';' { $$ = new Klass(); @@ -178,10 +179,15 @@ class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier '{' class_fi free($4); } + if ($5) { + $$->TypeBase = $5; + free($5); + } + $$->Attributes = $1; - $$->Fields = *$6; - delete $6; + $$->Fields = *$7; + delete $7; } ; @@ -208,6 +214,16 @@ inherits_specifier: /* empty */ } ; +type_base_specifier: /* empty */ + { + $$ = NULL; + } + | '<' identifier + { + $$ = $2; + } + ; + class_fields: /* empty */ { $$ = new std::vector(); diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index 725c185a5..f7ebdb0ec 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -111,8 +111,13 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp) /* TypeImpl */ std::cout << "template<>" << std::endl << "class TypeImpl<" << klass.Name << ">" - << " : public Type" << std::endl - << "{" << std::endl + << " : public Type"; + + if (!klass.TypeBase.empty()) + std::cout << ", public " + klass.TypeBase; + + std::cout << std::endl + << " {" << std::endl << "public:" << std::endl; /* GetName */ diff --git a/tools/mkclass/classcompiler.h b/tools/mkclass/classcompiler.h index c31656847..2701d534a 100644 --- a/tools/mkclass/classcompiler.h +++ b/tools/mkclass/classcompiler.h @@ -113,6 +113,7 @@ struct Klass { std::string Name; std::string Parent; + std::string TypeBase; int Attributes; std::vector Fields; };