diff --git a/lib/base/filelogger.ti b/lib/base/filelogger.ti index daaad69707f..f19b7c9d650 100644 --- a/lib/base/filelogger.ti +++ b/lib/base/filelogger.ti @@ -26,6 +26,8 @@ namespace icinga class FileLogger : StreamLogger { + activation_priority -100; + [config, required] String path; }; diff --git a/lib/base/sysloglogger.ti b/lib/base/sysloglogger.ti index ee639c25bfc..9ca92d637d6 100644 --- a/lib/base/sysloglogger.ti +++ b/lib/base/sysloglogger.ti @@ -26,6 +26,8 @@ namespace icinga class SyslogLogger : Logger { + activation_priority -100; + [config] String facility { default {{{ return "LOG_USER"; }}} }; diff --git a/lib/base/type.cpp b/lib/base/type.cpp index 19f1bb5d943..138269a87ec 100644 --- a/lib/base/type.cpp +++ b/lib/base/type.cpp @@ -154,6 +154,11 @@ std::vector Type::GetLoadDependencies() const return std::vector(); } +int Type::GetActivationPriority() const +{ + return 0; +} + void Type::RegisterAttributeHandler(int fieldId, const AttributeHandler& callback) { throw std::runtime_error("Invalid field ID."); diff --git a/lib/base/type.hpp b/lib/base/type.hpp index 10b8524fe44..ef8ce6d231a 100644 --- a/lib/base/type.hpp +++ b/lib/base/type.hpp @@ -103,6 +103,7 @@ class Type : public Object Value GetField(int id) const override; virtual std::vector GetLoadDependencies() const; + virtual int GetActivationPriority() const; typedef std::function AttributeHandler; virtual void RegisterAttributeHandler(int fieldId, const AttributeHandler& callback); diff --git a/lib/checker/checkercomponent.ti b/lib/checker/checkercomponent.ti index 119e4425255..8d74f1216be 100644 --- a/lib/checker/checkercomponent.ti +++ b/lib/checker/checkercomponent.ti @@ -26,6 +26,8 @@ namespace icinga class CheckerComponent : ConfigObject { + activation_priority 100; + [config] int concurrent_checks { get {{{ return Application::GetMaxConcurrentChecks(); diff --git a/lib/compat/checkresultreader.ti b/lib/compat/checkresultreader.ti index 96143bc990f..18b3d0ac4e7 100644 --- a/lib/compat/checkresultreader.ti +++ b/lib/compat/checkresultreader.ti @@ -27,6 +27,8 @@ namespace icinga class CheckResultReader : ConfigObject { + activation_priority 100; + [config] String spool_dir { default {{{ return Application::GetLocalStateDir() + "/lib/icinga2/spool/checkresults/"; }}} }; diff --git a/lib/compat/compatlogger.ti b/lib/compat/compatlogger.ti index c62471a07c6..322236cd848 100644 --- a/lib/compat/compatlogger.ti +++ b/lib/compat/compatlogger.ti @@ -27,6 +27,8 @@ namespace icinga class CompatLogger : ConfigObject { + activation_priority 100; + [config] String log_dir { default {{{ return Application::GetLocalStateDir() + "/log/icinga2/compat"; }}} }; diff --git a/lib/compat/externalcommandlistener.ti b/lib/compat/externalcommandlistener.ti index fe4c433a0bc..baffb7f5111 100644 --- a/lib/compat/externalcommandlistener.ti +++ b/lib/compat/externalcommandlistener.ti @@ -27,6 +27,8 @@ namespace icinga class ExternalCommandListener : ConfigObject { + activation_priority 100; + [config] String command_path { default {{{ return Application::GetRunDir() + "/icinga2/cmd/icinga2.cmd"; }}} }; diff --git a/lib/compat/statusdatawriter.ti b/lib/compat/statusdatawriter.ti index f2d3d579ad7..5ac2969a914 100644 --- a/lib/compat/statusdatawriter.ti +++ b/lib/compat/statusdatawriter.ti @@ -27,6 +27,8 @@ namespace icinga class StatusDataWriter : ConfigObject { + activation_priority 100; + [config] String status_path { default {{{ return Application::GetLocalStateDir() + "/cache/icinga2/status.dat"; }}} }; diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 289bca67f21..c790f8794eb 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -602,18 +602,35 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, const std::vectorm_Object) - continue; + /* Activate objects in priority order. */ + std::vector types = Type::GetAllTypes(); - ConfigObject::Ptr object = item->m_Object; + std::sort(types.begin(), types.end(), [](const Type::Ptr& a, const Type::Ptr& b) { + if (a->GetActivationPriority() < b->GetActivationPriority()) + return true; + return false; + }); + + for (const Type::Ptr& type : types) { + for (const ConfigItem::Ptr& item : newItems) { + if (!item->m_Object) + continue; + + ConfigObject::Ptr object = item->m_Object; + Type::Ptr objectType = object->GetReflectionType(); + + if (objectType != type) + continue; #ifdef I2_DEBUG - Log(LogDebug, "ConfigItem") - << "Activating object '" << object->GetName() << "' of type '" << object->GetReflectionType()->GetName() << "'"; + Log(LogDebug, "ConfigItem") + << "Activating object '" << object->GetName() << "' of type '" + << objectType->GetName() << "' with priority '" + << objectType->GetActivationPriority(); #endif /* I2_DEBUG */ - object->Activate(runtimeCreated); + object->Activate(runtimeCreated); + } } upq.Join(); diff --git a/lib/db_ido_mysql/idomysqlconnection.ti b/lib/db_ido_mysql/idomysqlconnection.ti index c3449093554..8a70d5668ec 100644 --- a/lib/db_ido_mysql/idomysqlconnection.ti +++ b/lib/db_ido_mysql/idomysqlconnection.ti @@ -26,6 +26,8 @@ namespace icinga class IdoMysqlConnection : DbConnection { + activation_priority 100; + [config] String host { default {{{ return "localhost"; }}} }; diff --git a/lib/db_ido_pgsql/idopgsqlconnection.ti b/lib/db_ido_pgsql/idopgsqlconnection.ti index a4657c0b1ee..ef7cf6ccb2a 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.ti +++ b/lib/db_ido_pgsql/idopgsqlconnection.ti @@ -26,6 +26,8 @@ namespace icinga class IdoPgsqlConnection : DbConnection { + activation_priority 100; + [config] String host { default {{{ return "localhost"; }}} }; diff --git a/lib/livestatus/livestatuslistener.ti b/lib/livestatus/livestatuslistener.ti index 576c04bfa4b..0742a6fb538 100644 --- a/lib/livestatus/livestatuslistener.ti +++ b/lib/livestatus/livestatuslistener.ti @@ -26,6 +26,8 @@ namespace icinga { class LivestatusListener : ConfigObject { + activation_priority 100; + [config] String socket_type { default {{{ return "unix"; }}} }; diff --git a/lib/notification/notificationcomponent.ti b/lib/notification/notificationcomponent.ti index 00852e6105e..547528d1e5d 100644 --- a/lib/notification/notificationcomponent.ti +++ b/lib/notification/notificationcomponent.ti @@ -26,6 +26,8 @@ namespace icinga class NotificationComponent : ConfigObject { + activation_priority 100; + [config] bool enable_ha (EnableHA) { default {{{ return true; }}} }; diff --git a/lib/perfdata/elasticsearchwriter.ti b/lib/perfdata/elasticsearchwriter.ti index 6961b426409..2bbdd9d6a0c 100644 --- a/lib/perfdata/elasticsearchwriter.ti +++ b/lib/perfdata/elasticsearchwriter.ti @@ -7,6 +7,8 @@ namespace icinga class ElasticsearchWriter : ConfigObject { + activation_priority 100; + [config, required] String host { default {{{ return "127.0.0.1"; }}} }; diff --git a/lib/perfdata/gelfwriter.ti b/lib/perfdata/gelfwriter.ti index 522d527e98b..facc94a6da6 100644 --- a/lib/perfdata/gelfwriter.ti +++ b/lib/perfdata/gelfwriter.ti @@ -26,6 +26,8 @@ namespace icinga class GelfWriter : ConfigObject { + activation_priority 100; + [config] String host { default {{{ return "127.0.0.1"; }}} }; diff --git a/lib/perfdata/graphitewriter.ti b/lib/perfdata/graphitewriter.ti index 9b1fc2529d2..ca04959f53a 100644 --- a/lib/perfdata/graphitewriter.ti +++ b/lib/perfdata/graphitewriter.ti @@ -26,6 +26,8 @@ namespace icinga class GraphiteWriter : ConfigObject { + activation_priority 100; + [config] String host { default {{{ return "127.0.0.1"; }}} }; diff --git a/lib/perfdata/influxdbwriter.ti b/lib/perfdata/influxdbwriter.ti index f2906614f91..5ff11675485 100644 --- a/lib/perfdata/influxdbwriter.ti +++ b/lib/perfdata/influxdbwriter.ti @@ -26,6 +26,8 @@ namespace icinga class InfluxdbWriter : ConfigObject { + activation_priority 100; + [config, required] String host { default {{{ return "127.0.0.1"; }}} }; diff --git a/lib/perfdata/opentsdbwriter.ti b/lib/perfdata/opentsdbwriter.ti index 7e2844ead70..ea9455b9e25 100644 --- a/lib/perfdata/opentsdbwriter.ti +++ b/lib/perfdata/opentsdbwriter.ti @@ -26,6 +26,8 @@ namespace icinga class OpenTsdbWriter : ConfigObject { + activation_priority 100; + [config] String host { default {{{ return "127.0.0.1"; }}} }; diff --git a/lib/perfdata/perfdatawriter.ti b/lib/perfdata/perfdatawriter.ti index 769a04431c8..c0988f339f3 100644 --- a/lib/perfdata/perfdatawriter.ti +++ b/lib/perfdata/perfdatawriter.ti @@ -27,6 +27,8 @@ namespace icinga class PerfdataWriter : ConfigObject { + activation_priority 100; + [config] String host_perfdata_path { default {{{ return Application::GetLocalStateDir() + "/spool/icinga2/perfdata/host-perfdata"; }}} }; diff --git a/lib/remote/apilistener.ti b/lib/remote/apilistener.ti index e072fcd20ce..e04fa01859e 100644 --- a/lib/remote/apilistener.ti +++ b/lib/remote/apilistener.ti @@ -28,6 +28,8 @@ namespace icinga class ApiListener : ConfigObject { + activation_priority 50; + [config, deprecated] String cert_path; [config, deprecated] String key_path; [config, deprecated] String ca_path; diff --git a/tools/mkclass/class_lexer.ll b/tools/mkclass/class_lexer.ll index 939a950b8d1..19c75b6267f 100644 --- a/tools/mkclass/class_lexer.ll +++ b/tools/mkclass/class_lexer.ll @@ -135,6 +135,7 @@ class { return T_CLASS; } namespace { return T_NAMESPACE; } code { return T_CODE; } load_after { return T_LOAD_AFTER; } +activation_priority { return T_ACTIVATION_PRIORITY; } library { return T_LIBRARY; } abstract { yylval->num = TAAbstract; return T_CLASS_ATTRIBUTE; } vararg_constructor { yylval->num = TAVarArgConstructor; return T_CLASS_ATTRIBUTE; } @@ -164,6 +165,7 @@ navigate { yylval->num = FTNavigate; return T_FIELD_ACCESSOR_TYPE; } \"[^\"]+\" { yylval->text = strdup(yytext + 1); yylval->text[strlen(yylval->text) - 1] = '\0'; return T_STRING; } \<[^ \>]*\> { yylval->text = strdup(yytext + 1); yylval->text[strlen(yylval->text) - 1] = '\0'; return T_ANGLE_STRING; } [a-zA-Z_][:a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; } +-?[0-9]+(\.[0-9]+)? { yylval->num = strtod(yytext, NULL); return T_NUMBER; } . return yytext[0]; diff --git a/tools/mkclass/class_parser.yy b/tools/mkclass/class_parser.yy index 2165549eb88..8f14ffc9de0 100644 --- a/tools/mkclass/class_parser.yy +++ b/tools/mkclass/class_parser.yy @@ -61,6 +61,7 @@ using namespace icinga; %token T_CLASS "class (T_CLASS)" %token T_CODE "code (T_CODE)" %token T_LOAD_AFTER "load_after (T_LOAD_AFTER)" +%token T_ACTIVATION_PRIORITY "activation_priority (T_ACTIVATION_PRIORITY)" %token T_LIBRARY "library (T_LIBRARY)" %token T_NAMESPACE "namespace (T_NAMESPACE)" %token T_VALIDATOR "validator (T_VALIDATOR)" @@ -77,6 +78,7 @@ using namespace icinga; %token T_SET "set (T_SET)" %token T_DEFAULT "default (T_DEFAULT)" %token T_FIELD_ACCESSOR_TYPE "field_accessor_type (T_FIELD_ACCESSOR_TYPE)" +%token T_NUMBER "number (T_NUMBER)" %type T_IDENTIFIER %type T_STRING %type T_ANGLE_STRING @@ -106,6 +108,7 @@ using namespace icinga; %type validator_rule %type validator_rules %type validator +%type T_NUMBER %{ @@ -250,6 +253,8 @@ class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier type_base_sp for (const Field& field : *$7) { if (field.Attributes & FALoadDependency) { $$->LoadDependencies.push_back(field.Name); + } else if (field.Attributes & FAActivationPriority) { + $$->ActivationPriority = field.Priority; } else $$->Fields.push_back(field); } @@ -380,6 +385,13 @@ class_field: field_attribute_list field_type identifier alternative_name_specifi std::free($2); $$ = field; } + | T_ACTIVATION_PRIORITY T_NUMBER ';' + { + auto *field = new Field(); + field->Attributes = FAActivationPriority; + field->Priority = $2; + $$ = field; + } ; alternative_name_specifier: /* empty */ diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index 1899e6d296e..374c54d1cb8 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -408,6 +408,14 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) m_Impl << "\t" << "return deps;" << std::endl << "}" << std::endl << std::endl; + /* GetActivationPriority */ + m_Header << "\t" << "int GetActivationPriority() const override;" << std::endl; + + m_Impl << "int TypeImpl<" << klass.Name << ">::GetActivationPriority() const" << std::endl + << "{" << std::endl + << "\t" << "return " << klass.ActivationPriority << ";" << std::endl + << "}" << std::endl << std::endl; + /* RegisterAttributeHandler */ m_Header << "public:" << std::endl << "\t" << "void RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback) override;" << std::endl; diff --git a/tools/mkclass/classcompiler.hpp b/tools/mkclass/classcompiler.hpp index 3f0e7d4ea91..e2124645d9d 100644 --- a/tools/mkclass/classcompiler.hpp +++ b/tools/mkclass/classcompiler.hpp @@ -76,7 +76,8 @@ enum FieldAttribute FANoUserView = 2048, FADeprecated = 4096, FAGetVirtual = 8192, - FASetVirtual = 16384 + FASetVirtual = 16384, + FAActivationPriority = 32768 }; struct FieldType @@ -122,6 +123,7 @@ struct Field std::string NavigationName; std::string NavigateAccessor; bool PureNavigateAccessor{false}; + int Priority{0}; inline std::string GetFriendlyName() const { @@ -167,6 +169,7 @@ struct Klass int Attributes; std::vector Fields; std::vector LoadDependencies; + int ActivationPriority{0}; }; enum RuleAttribute