boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnStopped;
boost::signals2::signal<void (const DynamicObject::Ptr&, const String&)> DynamicObject::OnStateChanged;
boost::signals2::signal<void (const DynamicObject::Ptr&, const String&, bool)> DynamicObject::OnAuthorityChanged;
+boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnVarsChanged;
void DynamicObject::StaticInitialize(void)
{
DynamicType::Ptr dtype = DynamicType::GetByName(type);
return dtype->GetObject(name);
}
+
+
+Dictionary::Ptr DynamicObject::GetVars(void) const
+{
+ if (!GetOverrideVars().IsEmpty())
+ return GetOverrideVars();
+ else
+ return GetVarsRaw();
+}
+
+void DynamicObject::SetVars(const Dictionary::Ptr& vars, const String& authority)
+{
+ Dictionary::Ptr override_vars = vars->ShallowClone();
+ SetOverrideVars(override_vars);
+
+ Log(LogDebug, "base", "Setting vars for object '" + GetName() + "'");
+
+ OnVarsChanged(GetSelf());
+}
+
+bool DynamicObject::IsVarOverridden(const String& name)
+{
+ Dictionary::Ptr vars_raw = GetVarsRaw();
+ Dictionary::Ptr vars_override = GetOverrideVars();
+
+ if (!vars_raw || !vars_override)
+ return false;
+
+ if (vars_raw->Get(name) != vars_override->Get(name))
+ return true;
+
+ return false;
+}
static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnStopped;
static boost::signals2::signal<void (const DynamicObject::Ptr&, const String&)> OnStateChanged;
static boost::signals2::signal<void (const DynamicObject::Ptr&, const String&, bool)> OnAuthorityChanged;
+ static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnVarsChanged;
Value InvokeMethod(const String& method, const std::vector<Value>& arguments);
Object::Ptr GetExtension(const String& key);
void ClearExtension(const String& key);
+ Dictionary::Ptr GetVars(void) const;
+ void SetVars(const Dictionary::Ptr& vars, const String& authority = String());
+
+ bool IsVarOverridden(const String& name);
+
void Register(void);
void Activate(void);
[config, get_protected] String type (TypeName);
[config, get_protected] Array::Ptr templates;
[config] Dictionary::Ptr methods;
- [config] Dictionary::Ptr vars;
+ [config] Dictionary::Ptr vars (VarsRaw);
[config] Array::Ptr domains;
[config] Array::Ptr authorities;
[get_protected] bool active;
[get_protected] bool stop_called;
Dictionary::Ptr authority_info;
[protected] Dictionary::Ptr extensions;
+
+ [state] Value override_vars;
};
}
static boost::mutex mutex;
return mutex;
}
+
void CommandDbObject::OnConfigUpdate(void)
{
- Command::Ptr command = static_pointer_cast<Command>(GetObject());
-
- Dictionary::Ptr vars = command->GetVars();
-
- if (!vars)
- return;
-
- Log(LogDebug, "db_ido", "Dumping command vars for '" + command->GetName() + "'");
-
- ObjectLock olock(vars);
-
- BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
- if (!kv.first.IsEmpty()) {
- Log(LogDebug, "db_ido", "command customvar key: '" + kv.first + "' value: '" + Convert::ToString(kv.second) + "'");
-
- Dictionary::Ptr fields1 = make_shared<Dictionary>();
- fields1->Set("varname", Convert::ToString(kv.first));
- fields1->Set("varvalue", Convert::ToString(kv.second));
- fields1->Set("config_type", 1);
- fields1->Set("has_been_modified", 0);
- fields1->Set("object_id", command);
- fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
-
- DbQuery query1;
- query1.Table = "customvariables";
- query1.Type = DbQueryInsert;
- query1.Category = DbCatConfig;
- query1.Fields = fields1;
- OnQuery(query1);
- }
- }
+ return;
}
#include "db_ido/dbtype.h"
#include "db_ido/dbvalue.h"
#include "icinga/service.h"
+#include "icinga/compatutility.h"
#include "remote/endpoint.h"
+#include "base/dynamicobject.h"
#include "base/dynamictype.h"
+#include "base/convert.h"
#include "base/objectlock.h"
#include "base/utility.h"
#include "base/initialize.h"
{
/* triggered in ProcessCheckResult(), requires UpdateNextCheck() to be called before */
DynamicObject::OnStateChanged.connect(boost::bind(&DbObject::StateChangedHandler, _1));
+ DynamicObject::OnVarsChanged.connect(boost::bind(&DbObject::VarsChangedHandler, _1));
}
void DbObject::SetObject(const DynamicObject::Ptr& object)
void DbObject::SendConfigUpdate(void)
{
+ /* update custom var config for all objects */
+ SendVarsConfigUpdate();
+
+ /* config objects */
Dictionary::Ptr fields = GetConfigFields();
if (!fields)
void DbObject::SendStatusUpdate(void)
{
+ /* update custom var status for all objects */
+ SendVarsStatusUpdate();
+
+ /* status objects */
Dictionary::Ptr fields = GetStatusFields();
if (!fields)
OnStatusUpdate();
}
+void DbObject::SendVarsConfigUpdate(void)
+{
+ DynamicObject::Ptr obj = GetObject();
+
+ Dictionary::Ptr vars;
+
+ vars = CompatUtility::GetCustomAttributeConfig(obj);
+
+ if (vars) {
+ Log(LogDebug, "db_ido", "Updating object vars for '" + obj->GetName() + "'");
+
+ ObjectLock olock (vars);
+
+ BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+ if (!kv.first.IsEmpty()) {
+ Log(LogDebug, "db_ido", "object customvar key: '" + kv.first + "' value: '" + Convert::ToString(kv.second) +
+ "' overridden: " + Convert::ToString(obj->IsVarOverridden(kv.first) ? 1 : 0));
+
+ Dictionary::Ptr fields = make_shared<Dictionary>();
+ fields->Set("varname", Convert::ToString(kv.first));
+ fields->Set("varvalue", Convert::ToString(kv.second));
+ fields->Set("config_type", 1);
+ fields->Set("has_been_modified", obj->IsVarOverridden(kv.first) ? 1 : 0);
+ fields->Set("object_id", obj);
+ fields->Set("instance_id", 0); /* DbConnection class fills in real ID */
+
+ DbQuery query;
+ query.Table = "customvariables";
+ query.Type = DbQueryInsert;
+ query.Category = DbCatConfig;
+ query.Fields = fields;
+ OnQuery(query);
+ }
+ }
+ }
+}
+
+void DbObject::SendVarsStatusUpdate(void)
+{
+ DynamicObject::Ptr obj = GetObject();
+
+ Dictionary::Ptr vars, vars_raw;
+
+ vars = CompatUtility::GetCustomAttributeConfig(obj);
+
+ if (vars) {
+ Log(LogDebug, "db_ido", "Updating object vars for '" + obj->GetName() + "'");
+
+ ObjectLock olock (vars);
+
+ BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+ if (!kv.first.IsEmpty()) {
+ int overridden = obj->IsVarOverridden(kv.first) ? 1 : 0;
+
+ Log(LogDebug, "db_ido", "object customvar key: '" + kv.first + "' value: '" + Convert::ToString(kv.second) +
+ "' overridden: " + Convert::ToString(overridden));
+
+ Dictionary::Ptr fields = make_shared<Dictionary>();
+ fields->Set("varname", Convert::ToString(kv.first));
+ fields->Set("varvalue", Convert::ToString(kv.second));
+ fields->Set("has_been_modified", overridden);
+ fields->Set("status_update_time", DbValue::FromTimestamp(Utility::GetTime()));
+ fields->Set("object_id", obj);
+ fields->Set("instance_id", 0); /* DbConnection class fills in real ID */
+
+ DbQuery query;
+ query.Table = "customvariablestatus";
+ query.Type = DbQueryInsert | DbQueryUpdate;
+ query.Category = DbCatState;
+ query.Fields = fields;
+
+ query.WhereCriteria = make_shared<Dictionary>();
+ query.WhereCriteria->Set("object_id", obj);
+ query.WhereCriteria->Set("varname", Convert::ToString(kv.first));
+ query.Object = GetSelf();
+
+ OnQuery(query);
+ }
+ }
+
+ }
+}
+
double DbObject::GetLastConfigUpdate(void) const
{
return m_LastConfigUpdate;
dbobj->SendStatusUpdate();
}
+
+void DbObject::VarsChangedHandler(const DynamicObject::Ptr& object)
+{
+ DbObject::Ptr dbobj = GetOrCreateByObject(object);
+
+ Log(LogDebug, "db_ido", "Vars changed for object '" + object->GetName() + "'");
+
+ if (!dbobj)
+ return;
+
+ Log(LogDebug, "db_ido", "Vars changed for db object '" + dbobj->GetName1() + ":" + dbobj->GetName2() + "'");
+
+ dbobj->SendVarsStatusUpdate();
+}
void SendConfigUpdate(void);
void SendStatusUpdate(void);
+ void SendVarsConfigUpdate(void);
+ void SendVarsStatusUpdate(void);
double GetLastConfigUpdate(void) const;
double GetLastStatusUpdate(void) const;
double m_LastStatusUpdate;
static void StateChangedHandler(const DynamicObject::Ptr& object);
+ static void VarsChangedHandler(const DynamicObject::Ptr& object);
friend class DbType;
};
#include "db_ido/hostdbobject.h"
#include "db_ido/dbtype.h"
#include "db_ido/dbvalue.h"
+#include "db_ido/dbevents.h"
#include "icinga/host.h"
#include "icinga/service.h"
#include "icinga/notification.h"
OnQuery(query_contact);
}
- /* custom variables */
- Dictionary::Ptr vars;
- {
- ObjectLock olock(host);
- vars = CompatUtility::GetCustomAttributeConfig(host);
- }
-
- if (vars) {
- Log(LogDebug, "ido", "Dumping host vars for '" + host->GetName() + "'");
-
- ObjectLock olock (vars);
-
- BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
- if (!kv.first.IsEmpty()) {
- Log(LogDebug, "db_ido", "host customvar key: '" + kv.first + "' value: '" + Convert::ToString(kv.second) + "'");
-
- Dictionary::Ptr fields3 = make_shared<Dictionary>();
- fields3->Set("varname", Convert::ToString(kv.first));
- fields3->Set("varvalue", Convert::ToString(kv.second));
- fields3->Set("config_type", 1);
- fields3->Set("has_been_modified", 0);
- fields3->Set("object_id", host);
- fields3->Set("instance_id", 0); /* DbConnection class fills in real ID */
-
- DbQuery query3;
- query3.Table = "customvariables";
- query3.Type = DbQueryInsert;
- query3.Category = DbCatConfig;
- query3.Fields = fields3;
- OnQuery(query3);
- }
- }
- }
+ /* update comments and downtimes on config change */
+ DbEvents::AddComments(host);
+ DbEvents::AddDowntimes(host);
}
void HostDbObject::OnStatusUpdate(void)
OnQuery(query_contact);
}
- /* custom variables */
- Dictionary::Ptr vars;
-
- {
- ObjectLock olock(service);
- vars = CompatUtility::GetCustomAttributeConfig(service);
- }
-
- if (vars) {
- Log(LogDebug, "db_ido", "Dumping service vars for '" + service->GetName() + "'");
-
- ObjectLock olock(vars);
-
- BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
- if (!kv.first.IsEmpty()) {
- Log(LogDebug, "db_ido", "service customvar key: '" + kv.first + "' value: '" + Convert::ToString(kv.second) + "'");
-
- Dictionary::Ptr fields2 = make_shared<Dictionary>();
- fields2->Set("varname", Convert::ToString(kv.first));
- fields2->Set("varvalue", Convert::ToString(kv.second));
- fields2->Set("config_type", 1);
- fields2->Set("has_been_modified", 0);
- fields2->Set("object_id", service);
- fields2->Set("instance_id", 0); /* DbConnection class fills in real ID */
-
- DbQuery query2;
- query2.Table = "customvariables";
- query2.Type = DbQueryInsert;
- query2.Category = DbCatConfig;
- query2.Fields = fields2;
- OnQuery(query2);
- }
- }
- }
-
/* update comments and downtimes on config change */
DbEvents::AddComments(service);
DbEvents::AddDowntimes(service);
if (!GetOverrideCheckPeriod().IsEmpty())
attrs |= ModAttrCheckTimeperiod;
+ if (!GetOverrideVars().IsEmpty())
+ attrs |= ModAttrCustomVariable;
+
// TODO: finish
return attrs;
if ((flags & ModAttrCheckTimeperiod) == 0)
SetOverrideCheckPeriod(Empty);
+
+ if ((flags & ModAttrCustomVariable) == 0) {
+ SetOverrideVars(Empty);
+ OnVarsChanged(GetSelf());
+ }
}
#include "icinga/servicegroup.h"
#include "icinga/pluginutility.h"
#include "icinga/icingaapplication.h"
+#include "icinga/checkcommand.h"
#include "icinga/eventcommand.h"
+#include "icinga/notificationcommand.h"
#include "base/convert.h"
#include "base/logger_fwd.h"
#include "base/objectlock.h"
RegisterCommand("CHANGE_MAX_SVC_CHECK_ATTEMPTS", &ExternalCommandProcessor::ChangeMaxSvcCheckAttempts, 3);
RegisterCommand("CHANGE_HOST_CHECK_TIMEPERIOD", &ExternalCommandProcessor::ChangeHostCheckTimeperiod, 2);
RegisterCommand("CHANGE_SVC_CHECK_TIMEPERIOD", &ExternalCommandProcessor::ChangeSvcCheckTimeperiod, 3);
+ RegisterCommand("CHANGE_CUSTOM_HOST_VAR", &ExternalCommandProcessor::ChangeCustomHostVar, 3);
+ RegisterCommand("CHANGE_CUSTOM_SVC_VAR", &ExternalCommandProcessor::ChangeCustomSvcVar, 4);
+ RegisterCommand("CHANGE_CUSTOM_USER_VAR", &ExternalCommandProcessor::ChangeCustomUserVar, 3);
+ RegisterCommand("CHANGE_CUSTOM_CHECKCOMMAND_VAR", &ExternalCommandProcessor::ChangeCustomCheckcommandVar, 3);
+ RegisterCommand("CHANGE_CUSTOM_EVENTCOMMAND_VAR", &ExternalCommandProcessor::ChangeCustomEventcommandVar, 3);
+ RegisterCommand("CHANGE_CUSTOM_NOTIFICATIONCOMMAND_VAR", &ExternalCommandProcessor::ChangeCustomNotificationcommandVar, 3);
+
RegisterCommand("ENABLE_HOSTGROUP_HOST_NOTIFICATIONS", &ExternalCommandProcessor::EnableHostgroupHostNotifications, 1);
RegisterCommand("ENABLE_HOSTGROUP_SVC_NOTIFICATIONS", &ExternalCommandProcessor::EnableHostgroupSvcNotifications, 1);
RegisterCommand("DISABLE_HOSTGROUP_HOST_NOTIFICATIONS", &ExternalCommandProcessor::DisableHostgroupHostNotifications, 1);
}
}
+void ExternalCommandProcessor::ChangeCustomHostVar(double time, const std::vector<String>& arguments)
+{
+ Host::Ptr host = Host::GetByName(arguments[0]);
+
+ if (!host)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent host '" + arguments[0] + "'"));
+
+ Dictionary::Ptr vars = host->GetVars();
+
+ if (!vars->Contains(arguments[1]))
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for host '" + arguments[0] + "' does not exist."));
+
+ vars->Set(arguments[1], arguments[2]);
+
+ Log(LogInformation, "icinga", "Changing custom var '" + arguments[1] + "' for host '" + arguments[0] + "' to value '" + arguments[2] + "'");
+
+ {
+ ObjectLock olock(host);
+
+ host->SetVars(vars);
+ }
+}
+
+void ExternalCommandProcessor::ChangeCustomSvcVar(double time, const std::vector<String>& arguments)
+{
+ Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
+
+ if (!service)
+ 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();
+
+ if (!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."));
+
+ vars->Set(arguments[2], arguments[3]);
+
+ Log(LogInformation, "icinga", "Changing custom var '" + arguments[2] + "' for service '" + arguments[1] + "' on host '" +
+ arguments[0] + "' to value '" + arguments[3] + "'");
+
+ {
+ ObjectLock olock(service);
+
+ service->SetVars(vars);
+ }
+}
+
+void ExternalCommandProcessor::ChangeCustomUserVar(double time, const std::vector<String>& arguments)
+{
+ User::Ptr user = User::GetByName(arguments[0]);
+
+ if (!user)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent user '" + arguments[0] + "'"));
+
+ Dictionary::Ptr vars = user->GetVars();
+
+ if (!vars->Contains(arguments[1]))
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for user '" + arguments[0] + "' does not exist."));
+
+ vars->Set(arguments[1], arguments[2]);
+
+ Log(LogInformation, "icinga", "Changing custom var '" + arguments[1] + "' for user '" + arguments[0] + "' to value '" + arguments[2] + "'");
+
+ {
+ ObjectLock olock(user);
+
+ user->SetVars(vars);
+ }
+}
+
+void ExternalCommandProcessor::ChangeCustomCheckcommandVar(double time, const std::vector<String>& arguments)
+{
+ CheckCommand::Ptr command = CheckCommand::GetByName(arguments[0]);
+
+ if (!command)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'"));
+
+ Dictionary::Ptr vars = command->GetVars();
+
+ if (!vars->Contains(arguments[1]))
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for command '" + arguments[0] + "' does not exist."));
+
+ 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(vars);
+ }
+}
+
+void ExternalCommandProcessor::ChangeCustomEventcommandVar(double time, const std::vector<String>& arguments)
+{
+ EventCommand::Ptr command = EventCommand::GetByName(arguments[0]);
+
+ if (!command)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'"));
+
+ Dictionary::Ptr vars = command->GetVars();
+
+ if (!vars->Contains(arguments[1]))
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for command '" + arguments[0] + "' does not exist."));
+
+ 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(vars);
+ }
+}
+
+void ExternalCommandProcessor::ChangeCustomNotificationcommandVar(double time, const std::vector<String>& arguments)
+{
+ NotificationCommand::Ptr command = NotificationCommand::GetByName(arguments[0]);
+
+ if (!command)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot change custom var for non-existent command '" + arguments[0] + "'"));
+
+ Dictionary::Ptr vars = command->GetVars();
+
+ if (!vars->Contains(arguments[1]))
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Custom var '" + arguments[1] + "' for command '" + arguments[0] + "' does not exist."));
+
+ 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(vars);
+ }
+}
+
void ExternalCommandProcessor::EnableHostgroupHostNotifications(double time, const std::vector<String>& arguments)
{
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
static void ChangeMaxSvcCheckAttempts(double time, const std::vector<String>& arguments);
static void ChangeHostCheckTimeperiod(double time, const std::vector<String>& arguments);
static void ChangeSvcCheckTimeperiod(double time, const std::vector<String>& arguments);
+ static void ChangeCustomHostVar(double time, const std::vector<String>& arguments);
+ static void ChangeCustomSvcVar(double time, const std::vector<String>& arguments);
+ static void ChangeCustomUserVar(double time, const std::vector<String>& arguments);
+ static void ChangeCustomCheckcommandVar(double time, const std::vector<String>& arguments);
+ static void ChangeCustomEventcommandVar(double time, const std::vector<String>& arguments);
+ static void ChangeCustomNotificationcommandVar(double time, const std::vector<String>& arguments);
+
static void EnableHostgroupHostNotifications(double time, const std::vector<String>& arguments);
static void EnableHostgroupSvcNotifications(double time, const std::vector<String>& arguments);
static void DisableHostgroupHostNotifications(double time, const std::vector<String>& arguments);