Implement relative object names.

Fixes #5925
This commit is contained in:
Gunnar Beutner 2014-04-05 22:17:20 +02:00
parent d3b67cf2ed
commit 00fd51e628
16 changed files with 161 additions and 27 deletions

View File

@ -1,6 +1,13 @@
namespace icinga namespace icinga
{ {
code {{{
class DynamicObjectNameHelper {
public:
virtual String MakeObjectName(const String& shortName, const Dictionary::Ptr props) const = 0;
};
}}}
abstract class DynamicObject abstract class DynamicObject
{ {
[config] String __name (Name); [config] String __name (Name);

View File

@ -117,12 +117,28 @@ Dictionary::Ptr ConfigItem::GetProperties(void)
if (!m_Properties) { if (!m_Properties) {
m_Properties = make_shared<Dictionary>(); m_Properties = make_shared<Dictionary>();
m_Properties->Set("type", m_Type); m_Properties->Set("type", m_Type);
m_Properties->Set("__name", m_Name); m_Properties->Set("name", m_Name);
m_Properties->Set("__parent", m_Scope); m_Properties->Set("__parent", m_Scope);
GetExpressionList()->Evaluate(m_Properties); GetExpressionList()->Evaluate(m_Properties);
m_Properties->Remove("name");
m_Properties->Remove("__parent"); 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<const DynamicObjectNameHelper *>(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; return m_Properties;
@ -175,7 +191,24 @@ DynamicObject::Ptr ConfigItem::Commit(void)
*/ */
void ConfigItem::Register(void) void ConfigItem::Register(void)
{ {
std::pair<String, String> 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<const DynamicObjectNameHelper *>(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<String, String> key = std::make_pair(m_Type, name);
ConfigItem::Ptr self = GetSelf(); ConfigItem::Ptr self = GetSelf();
boost::mutex::scoped_lock lock(m_Mutex); boost::mutex::scoped_lock lock(m_Mutex);

View File

@ -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; msgbuf2 << "Applying dependency '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di;
Log(LogDebug, "icinga", msgbuf2.str()); Log(LogDebug, "icinga", msgbuf2.str());
std::ostringstream namebuf;
namebuf << checkable->GetName() << "!" << rule.GetName();
String name = namebuf.str();
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di); ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("Dependency"); builder->SetType("Dependency");
builder->SetName(name); builder->SetName(rule.GetName());
builder->SetScope(rule.GetScope()); builder->SetScope(rule.GetScope());
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,

View File

@ -28,6 +28,21 @@ using namespace icinga;
REGISTER_TYPE(Dependency); 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) void Dependency::OnStateLoaded(void)
{ {
DynamicObject::Start(); DynamicObject::Start();

View File

@ -4,7 +4,15 @@
namespace icinga 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_host_name;
[config] String child_service_name; [config] String child_service_name;

View File

@ -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; msgbuf2 << "Applying notification '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di;
Log(LogDebug, "icinga", msgbuf2.str()); Log(LogDebug, "icinga", msgbuf2.str());
std::ostringstream namebuf;
namebuf << checkable->GetName() << "!" << rule.GetName();
String name = namebuf.str();
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di); ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("Notification"); builder->SetType("Notification");
builder->SetName(name); builder->SetName(rule.GetName());
builder->SetScope(rule.GetScope()); builder->SetScope(rule.GetScope());
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,

View File

@ -38,6 +38,21 @@ INITIALIZE_ONCE(&Notification::StaticInitialize);
boost::signals2::signal<void (const Notification::Ptr&, double, const String&)> Notification::OnNextNotificationChanged; boost::signals2::signal<void (const Notification::Ptr&, double, const String&)> 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) void Notification::StaticInitialize(void)
{ {
ScriptVariable::Set("NotificationDowntimeStart", NotificationDowntimeStart, true, true); ScriptVariable::Set("NotificationDowntimeStart", NotificationDowntimeStart, true, true);

View File

@ -3,7 +3,15 @@
namespace icinga 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, protected] String notification_command (NotificationCommandRaw);
[config] double notification_interval { [config] double notification_interval {

View File

@ -37,6 +37,21 @@ INITIALIZE_ONCE(&ScheduledDowntime::StaticInitialize);
static Timer::Ptr l_Timer; 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) void ScheduledDowntime::StaticInitialize(void)
{ {
l_Timer = make_shared<Timer>(); l_Timer = make_shared<Timer>();

View File

@ -3,7 +3,15 @@
namespace icinga 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 host_name;
[config, protected] String service_name; [config, protected] String service_name;

View File

@ -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; msgbuf2 << "Applying service '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di;
Log(LogDebug, "icinga", msgbuf2.str()); Log(LogDebug, "icinga", msgbuf2.str());
std::ostringstream namebuf;
namebuf << host->GetName() << "!" << rule.GetName();
String name = namebuf.str();
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di); ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("Service"); builder->SetType("Service");
builder->SetName(name); builder->SetName(rule.GetName());
builder->SetScope(rule.GetScope()); builder->SetScope(rule.GetScope());
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,

View File

@ -39,6 +39,13 @@ REGISTER_TYPE(Service);
INITIALIZE_ONCE(&Service::StartDowntimesExpiredTimer); 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) void Service::OnConfigLoaded(void)
{ {
Array::Ptr groups = GetGroups(); Array::Ptr groups = GetGroups();

View File

@ -6,7 +6,15 @@
namespace icinga 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 { [config] String display_name {
get {{{ get {{{

View File

@ -66,6 +66,7 @@ using namespace icinga;
%type <text> identifier %type <text> identifier
%type <text> alternative_name_specifier %type <text> alternative_name_specifier
%type <text> inherits_specifier %type <text> inherits_specifier
%type <text> type_base_specifier
%type <text> include %type <text> include
%type <text> angle_include %type <text> angle_include
%type <text> code %type <text> 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(); $$ = new Klass();
@ -178,10 +179,15 @@ class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier '{' class_fi
free($4); free($4);
} }
if ($5) {
$$->TypeBase = $5;
free($5);
}
$$->Attributes = $1; $$->Attributes = $1;
$$->Fields = *$6; $$->Fields = *$7;
delete $6; delete $7;
} }
; ;
@ -208,6 +214,16 @@ inherits_specifier: /* empty */
} }
; ;
type_base_specifier: /* empty */
{
$$ = NULL;
}
| '<' identifier
{
$$ = $2;
}
;
class_fields: /* empty */ class_fields: /* empty */
{ {
$$ = new std::vector<Field>(); $$ = new std::vector<Field>();

View File

@ -111,8 +111,13 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
/* TypeImpl */ /* TypeImpl */
std::cout << "template<>" << std::endl std::cout << "template<>" << std::endl
<< "class TypeImpl<" << klass.Name << ">" << "class TypeImpl<" << klass.Name << ">"
<< " : public Type" << std::endl << " : public Type";
<< "{" << std::endl
if (!klass.TypeBase.empty())
std::cout << ", public " + klass.TypeBase;
std::cout << std::endl
<< " {" << std::endl
<< "public:" << std::endl; << "public:" << std::endl;
/* GetName */ /* GetName */

View File

@ -113,6 +113,7 @@ struct Klass
{ {
std::string Name; std::string Name;
std::string Parent; std::string Parent;
std::string TypeBase;
int Attributes; int Attributes;
std::vector<Field> Fields; std::vector<Field> Fields;
}; };