From 72f7537fa6f59d87511ad7efbf9bf753488f3e5e Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 17 Apr 2014 15:20:28 +0200 Subject: [PATCH] Add modified attributes for user and command vars. Fixes #6043 --- components/livestatus/commandstable.cpp | 24 ++++ components/livestatus/commandstable.h | 2 + components/livestatus/contactstable.cpp | 29 +---- doc/6.12-schemas.md | 2 + doc/6.13-external-commands-list,md | 4 + doc/8-differences-between-icinga-1x-and-2.md | 1 + lib/base/dynamicobject.h | 21 ++++ lib/db_ido/userdbobject.cpp | 2 +- lib/icinga/checkable.h | 26 ---- lib/icinga/command.cpp | 18 +++ lib/icinga/command.h | 3 + lib/icinga/externalcommandprocessor.cpp | 126 +++++++++++++------ lib/icinga/externalcommandprocessor.h | 11 ++ lib/icinga/user.cpp | 18 +++ lib/icinga/user.h | 3 + 15 files changed, 194 insertions(+), 96 deletions(-) diff --git a/components/livestatus/commandstable.cpp b/components/livestatus/commandstable.cpp index 6f5d3d22b..99f26c5d6 100644 --- a/components/livestatus/commandstable.cpp +++ b/components/livestatus/commandstable.cpp @@ -44,6 +44,8 @@ void CommandsTable::AddColumns(Table *table, const String& prefix, table->AddColumn(prefix + "custom_variable_names", Column(&CommandsTable::CustomVariableNamesAccessor, objectAccessor)); table->AddColumn(prefix + "custom_variable_values", Column(&CommandsTable::CustomVariableValuesAccessor, objectAccessor)); table->AddColumn(prefix + "custom_variables", Column(&CommandsTable::CustomVariablesAccessor, objectAccessor)); + table->AddColumn(prefix + "modified_attributes", Column(&CommandsTable::ModifiedAttributesAccessor, objectAccessor)); + table->AddColumn(prefix + "modified_attributes_list", Column(&CommandsTable::ModifiedAttributesListAccessor, objectAccessor)); } String CommandsTable::GetName(void) const @@ -202,3 +204,25 @@ Value CommandsTable::CustomVariablesAccessor(const Value& row) return cv; } + +Value CommandsTable::ModifiedAttributesAccessor(const Value& row) +{ + Command::Ptr command = static_cast(row); + + if (!command) + return Empty; + + /* not supported */ + return command->GetModifiedAttributes(); +} + +Value CommandsTable::ModifiedAttributesListAccessor(const Value& row) +{ + Command::Ptr command = static_cast(row); + + if (!command) + return Empty; + + /* not supported */ + return Empty; +} diff --git a/components/livestatus/commandstable.h b/components/livestatus/commandstable.h index 67e5a4f74..f31643baf 100644 --- a/components/livestatus/commandstable.h +++ b/components/livestatus/commandstable.h @@ -50,6 +50,8 @@ protected: static Value CustomVariableNamesAccessor(const Value& row); static Value CustomVariableValuesAccessor(const Value& row); static Value CustomVariablesAccessor(const Value& row); + static Value ModifiedAttributesAccessor(const Value& row); + static Value ModifiedAttributesListAccessor(const Value& row); }; } diff --git a/components/livestatus/contactstable.cpp b/components/livestatus/contactstable.cpp index 78f6be3f3..8a9e7549a 100644 --- a/components/livestatus/contactstable.cpp +++ b/components/livestatus/contactstable.cpp @@ -205,15 +205,6 @@ Value ContactsTable::CustomVariableNamesAccessor(const Value& row) String key; Value value; BOOST_FOREACH(boost::tie(key, value), vars) { - if (key == "notes" || - key == "action_url" || - key == "notes_url" || - key == "icon_image" || - key == "icon_image_alt" || - key == "statusmap_image" || - key == "2d_coords") - continue; - cv->Add(key); } @@ -238,15 +229,6 @@ Value ContactsTable::CustomVariableValuesAccessor(const Value& row) String key; Value value; BOOST_FOREACH(boost::tie(key, value), vars) { - if (key == "notes" || - key == "action_url" || - key == "notes_url" || - key == "icon_image" || - key == "icon_image_alt" || - key == "statusmap_image" || - key == "2d_coords") - continue; - cv->Add(value); } @@ -271,15 +253,6 @@ Value ContactsTable::CustomVariablesAccessor(const Value& row) String key; Value value; BOOST_FOREACH(boost::tie(key, value), vars) { - if (key == "notes" || - key == "action_url" || - key == "notes_url" || - key == "icon_image" || - key == "icon_image_alt" || - key == "statusmap_image" || - key == "2d_coords") - continue; - Array::Ptr key_val = make_shared(); key_val->Add(key); key_val->Add(value); @@ -297,7 +270,7 @@ Value ContactsTable::ModifiedAttributesAccessor(const Value& row) return Empty; /* not supported */ - return Empty; + return user->GetModifiedAttributes(); } Value ContactsTable::ModifiedAttributesListAccessor(const Value& row) diff --git a/doc/6.12-schemas.md b/doc/6.12-schemas.md index d2ca7b4ad..7053f8062 100644 --- a/doc/6.12-schemas.md +++ b/doc/6.12-schemas.md @@ -181,6 +181,8 @@ New columns: commands | custom_variable_names commands | custom_variable_values commands | custom_variables + commands | modified_attributes + commands | modified_attributes_list status | custom_variable_names status | custom_variable_values status | custom_variables diff --git a/doc/6.13-external-commands-list,md b/doc/6.13-external-commands-list,md index f9d3e830e..abdafbaad 100644 --- a/doc/6.13-external-commands-list,md +++ b/doc/6.13-external-commands-list,md @@ -88,6 +88,10 @@ Additional details can be found in the [Icinga 1.x Documentation](http://docs.ic STOP_EXECUTING_SVC_CHECKS | (0) | CHANGE_SVC_MODATTR | ;;; (3) | CHANGE_HOST_MODATTR | ;; (2) | + CHANGE_USER_MODATTR | ;; (2) | + CHANGE_CHECKCOMMAND_MODATTR | ;; (2) | + CHANGE_EVENTCOMMAND_MODATTR | ;; (2) | + CHANGE_NOTIFICATIONCOMMAND_MODATTR | ;; (2) | CHANGE_NORMAL_SVC_CHECK_INTERVAL | ;;; (3) | CHANGE_NORMAL_HOST_CHECK_INTERVAL | ;; (2) | CHANGE_RETRY_SVC_CHECK_INTERVAL | ;;; (3) | diff --git a/doc/8-differences-between-icinga-1x-and-2.md b/doc/8-differences-between-icinga-1x-and-2.md index 187cfc327..162724b1a 100644 --- a/doc/8-differences-between-icinga-1x-and-2.md +++ b/doc/8-differences-between-icinga-1x-and-2.md @@ -343,6 +343,7 @@ Changes to global runtime macros: ## External Commands `CHANGE_CUSTOM_CONTACT_VAR` was renamed to `CHANGE_CUSTOM_USER_VAR`. +`CHANGE_CONTACT_MODATTR` was renamed to `CHANGE_USER_MODATTR`. The following external commands are not supported: diff --git a/lib/base/dynamicobject.h b/lib/base/dynamicobject.h index 3c71c3281..8891343f5 100644 --- a/lib/base/dynamicobject.h +++ b/lib/base/dynamicobject.h @@ -41,6 +41,27 @@ enum DomainPriv DomainPrivCommand = (1<<2) }; +enum ModifiedAttributeType +{ + ModAttrNotificationsEnabled = 1, + ModAttrActiveChecksEnabled = 2, + ModAttrPassiveChecksEnabled = 4, + ModAttrEventHandlerEnabled = 8, + ModAttrFlapDetectionEnabled = 16, + ModAttrFailurePredictionEnabled = 32, + ModAttrPerformanceDataEnabled = 64, + ModAttrObsessiveHandlerEnabled = 128, + ModAttrEventHandlerCommand = 256, + ModAttrCheckCommand = 512, + ModAttrNormalCheckInterval = 1024, + ModAttrRetryCheckInterval = 2048, + ModAttrMaxCheckAttempts = 4096, + ModAttrFreshnessChecksEnabled = 8192, + ModAttrCheckTimeperiod = 16384, + ModAttrCustomVariable = 32768, + ModAttrNotificationTimeperiod = 65536 +}; + /** * A dynamic object that can be instantiated from the configuration file * and that supports attribute replication to remote application instances. diff --git a/lib/db_ido/userdbobject.cpp b/lib/db_ido/userdbobject.cpp index 3593a2e08..bccff13c7 100644 --- a/lib/db_ido/userdbobject.cpp +++ b/lib/db_ido/userdbobject.cpp @@ -72,7 +72,7 @@ Dictionary::Ptr UserDbObject::GetStatusFields(void) const fields->Set("service_notifications_enabled", user->GetEnableNotifications()); fields->Set("last_host_notification", DbValue::FromTimestamp(user->GetLastNotification())); fields->Set("last_service_notification", DbValue::FromTimestamp(user->GetLastNotification())); - fields->Set("modified_attributes", Empty); + fields->Set("modified_attributes", user->GetModifiedAttributes()); fields->Set("modified_host_attributes", Empty); fields->Set("modified_service_attributes", Empty); diff --git a/lib/icinga/checkable.h b/lib/icinga/checkable.h index b7155ca6f..8d4f1c673 100644 --- a/lib/icinga/checkable.h +++ b/lib/icinga/checkable.h @@ -48,32 +48,6 @@ enum FlappingState FlappingEnabled = 3 }; -/** - * Modified attributes. - * - * @ingroup icinga - */ -enum ModifiedAttributeType -{ - ModAttrNotificationsEnabled = 1, - ModAttrActiveChecksEnabled = 2, - ModAttrPassiveChecksEnabled = 4, - ModAttrEventHandlerEnabled = 8, - ModAttrFlapDetectionEnabled = 16, - ModAttrFailurePredictionEnabled = 32, - ModAttrPerformanceDataEnabled = 64, - ModAttrObsessiveHandlerEnabled = 128, - ModAttrEventHandlerCommand = 256, - ModAttrCheckCommand = 512, - ModAttrNormalCheckInterval = 1024, - ModAttrRetryCheckInterval = 2048, - ModAttrMaxCheckAttempts = 4096, - ModAttrFreshnessChecksEnabled = 8192, - ModAttrCheckTimeperiod = 16384, - ModAttrCustomVariable = 32768, - ModAttrNotificationTimeperiod = 65536 -}; - /** * @ingroup icinga */ diff --git a/lib/icinga/command.cpp b/lib/icinga/command.cpp index f419f52b4..ffbf0dfa0 100644 --- a/lib/icinga/command.cpp +++ b/lib/icinga/command.cpp @@ -34,3 +34,21 @@ bool Command::ResolveMacro(const String& macro, const CheckResult::Ptr&, String return false; } + +int Command::GetModifiedAttributes(void) const +{ + int attrs = 0; + + if (!GetOverrideVars().IsEmpty()) + attrs |= ModAttrCustomVariable; + + return attrs; +} + +void Command::SetModifiedAttributes(int flags) +{ + if ((flags & ModAttrCustomVariable) == 0) { + SetOverrideVars(Empty); + OnVarsChanged(GetSelf()); + } +} diff --git a/lib/icinga/command.h b/lib/icinga/command.h index e48872c80..a41c74d12 100644 --- a/lib/icinga/command.h +++ b/lib/icinga/command.h @@ -43,6 +43,9 @@ public: //virtual Dictionary::Ptr Execute(const Object::Ptr& context) = 0; virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const; + + int GetModifiedAttributes(void) const; + void SetModifiedAttributes(int flags); }; } diff --git a/lib/icinga/externalcommandprocessor.cpp b/lib/icinga/externalcommandprocessor.cpp index 72034a2e5..4b86dacf6 100644 --- a/lib/icinga/externalcommandprocessor.cpp +++ b/lib/icinga/externalcommandprocessor.cpp @@ -229,6 +229,10 @@ void ExternalCommandProcessor::Initialize(void) RegisterCommand("STOP_EXECUTING_HOST_CHECKS", &ExternalCommandProcessor::StopExecutingHostChecks); RegisterCommand("CHANGE_SVC_MODATTR", &ExternalCommandProcessor::ChangeSvcModattr, 3); RegisterCommand("CHANGE_HOST_MODATTR", &ExternalCommandProcessor::ChangeHostModattr, 2); + RegisterCommand("CHANGE_USER_MODATTR", &ExternalCommandProcessor::ChangeUserModattr, 2); + RegisterCommand("CHANGE_CHECKCOMMAND_MODATTR", &ExternalCommandProcessor::ChangeCheckcommandModattr, 2); + RegisterCommand("CHANGE_EVENTCOMMAND_MODATTR", &ExternalCommandProcessor::ChangeEventcommandModattr, 2); + RegisterCommand("CHANGE_NOTIFICATIONCOMMAND_MODATTR", &ExternalCommandProcessor::ChangeNotificationcommandModattr, 2); RegisterCommand("CHANGE_NORMAL_SVC_CHECK_INTERVAL", &ExternalCommandProcessor::ChangeNormalSvcCheckInterval, 3); RegisterCommand("CHANGE_NORMAL_HOST_CHECK_INTERVAL", &ExternalCommandProcessor::ChangeNormalHostCheckInterval, 2); RegisterCommand("CHANGE_RETRY_SVC_CHECK_INTERVAL", &ExternalCommandProcessor::ChangeRetrySvcCheckInterval, 3); @@ -1650,6 +1654,65 @@ void ExternalCommandProcessor::ChangeHostModattr(double time, const std::vector< } } +void ExternalCommandProcessor::ChangeUserModattr(double time, const std::vector& arguments) +{ + User::Ptr user = User::GetByName(arguments[0]); + + if (!user) + BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot update modified attributes for non-existent user '" + arguments[0] + "'")); + + Log(LogInformation, "icinga", "Updating modified attributes for user '" + arguments[0] + "'"); + + int modifiedAttributes = Convert::ToLong(arguments[1]); + + { + ObjectLock olock(user); + + user->SetModifiedAttributes(modifiedAttributes); + } +} + +void ExternalCommandProcessor::ChangeCheckcommandModattr(double time, const std::vector& arguments) +{ + CheckCommand::Ptr command = CheckCommand::GetByName(arguments[0]); + + if (!command) + BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot update modified attributes for non-existent command '" + arguments[0] + "'")); + + ChangeCommandModattrInternal(command, Convert::ToLong(arguments[1])); +} + +void ExternalCommandProcessor::ChangeEventcommandModattr(double time, const std::vector& arguments) +{ + EventCommand::Ptr command = EventCommand::GetByName(arguments[0]); + + if (!command) + BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot update modified attributes for non-existent command '" + arguments[0] + "'")); + + ChangeCommandModattrInternal(command, Convert::ToLong(arguments[1])); +} + +void ExternalCommandProcessor::ChangeNotificationcommandModattr(double time, const std::vector& arguments) +{ + NotificationCommand::Ptr command = NotificationCommand::GetByName(arguments[0]); + + if (!command) + BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot update modified attributes for non-existent command '" + arguments[0] + "'")); + + ChangeCommandModattrInternal(command, Convert::ToLong(arguments[1])); +} + +void ExternalCommandProcessor::ChangeCommandModattrInternal(const Command::Ptr& command, int mod_attr) +{ + Log(LogInformation, "icinga", "Updating modified attributes for command '" + command->GetName() + "'"); + + { + ObjectLock olock(command); + + command->SetModifiedAttributes(mod_attr); + } +} + void ExternalCommandProcessor::ChangeNormalSvcCheckInterval(double time, const std::vector& arguments) { Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]); @@ -1966,11 +2029,12 @@ void ExternalCommandProcessor::ChangeCustomHostVar(double time, const std::vecto BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent host '" + arguments[0] + "'")); Dictionary::Ptr vars = host->GetVars(); - Dictionary::Ptr override_vars = vars->ShallowClone(); - if (!vars->Contains(arguments[1])) + if (!vars || !vars->Contains(arguments[1])) BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for host '" + arguments[0] + "' does not exist.")); + Dictionary::Ptr override_vars = vars->ShallowClone(); + override_vars->Set(arguments[1], arguments[2]); Log(LogInformation, "icinga", "Changing custom var '" + arguments[1] + "' for host '" + arguments[0] + "' to value '" + arguments[2] + "'"); @@ -1990,12 +2054,13 @@ void ExternalCommandProcessor::ChangeCustomSvcVar(double time, const std::vector BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent service '" + arguments[1] + "' on host '" + arguments[0] + "'")); Dictionary::Ptr vars = service->GetVars(); - Dictionary::Ptr override_vars = vars->ShallowClone(); - if (!vars->Contains(arguments[2])) + if (!vars || !vars->Contains(arguments[2])) BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[2] + "' for service '" + arguments[1] + "' on host '" + arguments[0] + "' does not exist.")); + Dictionary::Ptr override_vars = vars->ShallowClone(); + override_vars->Set(arguments[2], arguments[3]); Log(LogInformation, "icinga", "Changing custom var '" + arguments[2] + "' for service '" + arguments[1] + "' on host '" + @@ -2016,11 +2081,12 @@ void ExternalCommandProcessor::ChangeCustomUserVar(double time, const std::vecto BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent user '" + arguments[0] + "'")); Dictionary::Ptr vars = user->GetVars(); - Dictionary::Ptr override_vars = vars->ShallowClone(); - if (!vars->Contains(arguments[1])) + if (!vars || !vars->Contains(arguments[1])) BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for user '" + arguments[0] + "' does not exist.")); + Dictionary::Ptr override_vars = vars->ShallowClone(); + override_vars->Set(arguments[1], arguments[2]); Log(LogInformation, "icinga", "Changing custom var '" + arguments[1] + "' for user '" + arguments[0] + "' to value '" + arguments[2] + "'"); @@ -2039,21 +2105,7 @@ void ExternalCommandProcessor::ChangeCustomCheckcommandVar(double time, const st if (!command) BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'")); - Dictionary::Ptr vars = command->GetVars(); - Dictionary::Ptr override_vars = vars->ShallowClone(); - - if (!vars->Contains(arguments[1])) - BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for command '" + arguments[0] + "' does not exist.")); - - override_vars->Set(arguments[1], arguments[2]); - - Log(LogInformation, "icinga", "Changing custom var '" + arguments[1] + "' for command '" + arguments[0] + "' to value '" + arguments[2] + "'"); - - { - ObjectLock olock(command); - - command->SetVars(override_vars); - } + ChangeCustomCommandVarInternal(command, arguments[1], arguments[2]); } void ExternalCommandProcessor::ChangeCustomEventcommandVar(double time, const std::vector& arguments) @@ -2063,21 +2115,7 @@ void ExternalCommandProcessor::ChangeCustomEventcommandVar(double time, const st if (!command) BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'")); - Dictionary::Ptr vars = command->GetVars(); - Dictionary::Ptr override_vars = vars->ShallowClone(); - - if (!vars->Contains(arguments[1])) - BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for command '" + arguments[0] + "' does not exist.")); - - override_vars->Set(arguments[1], arguments[2]); - - Log(LogInformation, "icinga", "Changing custom var '" + arguments[1] + "' for command '" + arguments[0] + "' to value '" + arguments[2] + "'"); - - { - ObjectLock olock(command); - - command->SetVars(override_vars); - } + ChangeCustomCommandVarInternal(command, arguments[1], arguments[2]); } void ExternalCommandProcessor::ChangeCustomNotificationcommandVar(double time, const std::vector& arguments) @@ -2087,15 +2125,21 @@ void ExternalCommandProcessor::ChangeCustomNotificationcommandVar(double time, c if (!command) BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'")); + ChangeCustomCommandVarInternal(command, arguments[1], arguments[2]); +} + +void ExternalCommandProcessor::ChangeCustomCommandVarInternal(const Command::Ptr& command, const String& name, const Value& value) +{ Dictionary::Ptr vars = command->GetVars(); - Dictionary::Ptr override_vars = vars->ShallowClone(); - if (!vars->Contains(arguments[1])) - BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for command '" + arguments[0] + "' does not exist.")); + if (!vars || !vars->Contains(name)) + BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + name + "' for command '" + command->GetName() + "' does not exist.")); - override_vars->Set(arguments[1], arguments[2]); + Dictionary::Ptr override_vars = vars->ShallowClone(); + + override_vars->Set(name, value); - Log(LogInformation, "icinga", "Changing custom var '" + arguments[1] + "' for command '" + arguments[0] + "' to value '" + arguments[2] + "'"); + Log(LogInformation, "icinga", "Changing custom var '" + name + "' for command '" + command->GetName() + "' to value '" + Convert::ToString(value) + "'"); { ObjectLock olock(command); diff --git a/lib/icinga/externalcommandprocessor.h b/lib/icinga/externalcommandprocessor.h index f85d2ddf3..70f317cab 100644 --- a/lib/icinga/externalcommandprocessor.h +++ b/lib/icinga/externalcommandprocessor.h @@ -21,6 +21,7 @@ #define EXTERNALCOMMANDPROCESSOR_H #include "icinga/i2-icinga.h" +#include "icinga/command.h" #include "base/qstring.h" #include #include @@ -127,6 +128,12 @@ private: static void StopExecutingHostChecks(double time, const std::vector& arguments); static void ChangeSvcModattr(double time, const std::vector& arguments); static void ChangeHostModattr(double time, const std::vector& arguments); + + static void ChangeUserModattr(double time, const std::vector& arguments); + static void ChangeCheckcommandModattr(double time, const std::vector& arguments); + static void ChangeEventcommandModattr(double time, const std::vector& arguments); + static void ChangeNotificationcommandModattr(double time, const std::vector& arguments); + static void ChangeNormalSvcCheckInterval(double time, const std::vector& arguments); static void ChangeNormalHostCheckInterval(double time, const std::vector& arguments); static void ChangeRetrySvcCheckInterval(double time, const std::vector& arguments); @@ -158,6 +165,10 @@ private: static void EnableServicegroupSvcNotifications(double time, const std::vector& arguments); static void DisableServicegroupHostNotifications(double time, const std::vector& arguments); static void DisableServicegroupSvcNotifications(double time, const std::vector& arguments); + +private: + static void ChangeCommandModattrInternal(const Command::Ptr& command, int mod_attr); + static void ChangeCustomCommandVarInternal(const Command::Ptr& command, const String& name, const Value& value); }; } diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp index bd9e9a75d..6834574bf 100644 --- a/lib/icinga/user.cpp +++ b/lib/icinga/user.cpp @@ -92,3 +92,21 @@ void User::ValidateFilters(const String& location, const Dictionary::Ptr& attrs) location + ": Type filter is invalid."); } } + +int User::GetModifiedAttributes(void) const +{ + int attrs = 0; + + if (!GetOverrideVars().IsEmpty()) + attrs |= ModAttrCustomVariable; + + return attrs; +} + +void User::SetModifiedAttributes(int flags) +{ + if ((flags & ModAttrCustomVariable) == 0) { + SetOverrideVars(Empty); + OnVarsChanged(GetSelf()); + } +} diff --git a/lib/icinga/user.h b/lib/icinga/user.h index 50417e4c7..d5b441ca6 100644 --- a/lib/icinga/user.h +++ b/lib/icinga/user.h @@ -45,6 +45,9 @@ public: static void ValidateFilters(const String& location, const Dictionary::Ptr& attrs); + int GetModifiedAttributes(void) const; + void SetModifiedAttributes(int flags); + protected: virtual void Stop(void); -- 2.40.0