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
{
code {{{
class DynamicObjectNameHelper {
public:
virtual String MakeObjectName(const String& shortName, const Dictionary::Ptr props) const = 0;
};
}}}
abstract class DynamicObject
{
[config] String __name (Name);

View File

@ -117,12 +117,28 @@ Dictionary::Ptr ConfigItem::GetProperties(void)
if (!m_Properties) {
m_Properties = make_shared<Dictionary>();
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<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;
@ -175,7 +191,24 @@ DynamicObject::Ptr ConfigItem::Commit(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();
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;
Log(LogDebug, "icinga", msgbuf2.str());
std::ostringstream namebuf;
namebuf << checkable->GetName() << "!" << rule.GetName();
String name = namebuf.str();
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("Dependency");
builder->SetName(name);
builder->SetName(rule.GetName());
builder->SetScope(rule.GetScope());
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet,

View File

@ -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();

View File

@ -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;

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;
Log(LogDebug, "icinga", msgbuf2.str());
std::ostringstream namebuf;
namebuf << checkable->GetName() << "!" << rule.GetName();
String name = namebuf.str();
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("Notification");
builder->SetName(name);
builder->SetName(rule.GetName());
builder->SetScope(rule.GetScope());
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;
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);

View File

@ -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 {

View File

@ -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<Timer>();

View File

@ -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;

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

View File

@ -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();

View File

@ -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 {{{

View File

@ -66,6 +66,7 @@ using namespace icinga;
%type <text> identifier
%type <text> alternative_name_specifier
%type <text> inherits_specifier
%type <text> type_base_specifier
%type <text> include
%type <text> angle_include
%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();
@ -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<Field>();

View File

@ -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 */

View File

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