Livestatus: Add 'cv_is_json' and encode CV arrays/dicts as json

refs #7560
This commit is contained in:
Michael Friedrich 2014-11-04 16:44:45 +01:00
parent de080e4928
commit eeb6facdac
11 changed files with 181 additions and 50 deletions

View File

@ -212,6 +212,9 @@ New columns:
----------|-------------- ----------|--------------
hosts | is_reachable hosts | is_reachable
services | is_reachable services | is_reachable
hosts | cv_is_json
services | cv_is_json
contacts | cv_is_json
hosts | check_source hosts | check_source
services | check_source services | check_source
downtimes | triggers downtimes | triggers

View File

@ -126,7 +126,7 @@ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
Dictionary::Ptr command_vars = command->GetVars(); Dictionary::Ptr command_vars = command->GetVars();
if (command_vars) { if (command_vars) {
BOOST_FOREACH(Dictionary::Pair kv, command_vars) { BOOST_FOREACH(const Dictionary::Pair& kv, command_vars) {
String macro = "$" + kv.first + "$"; // this is too simple String macro = "$" + kv.first + "$"; // this is too simple
if (command_line.Contains(macro)) if (command_line.Contains(macro))
args->Set(kv.first, kv.second); args->Set(kv.first, kv.second);
@ -137,7 +137,7 @@ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
Dictionary::Ptr host_vars = host->GetVars(); Dictionary::Ptr host_vars = host->GetVars();
if (host_vars) { if (host_vars) {
BOOST_FOREACH(Dictionary::Pair kv, host_vars) { BOOST_FOREACH(const Dictionary::Pair& kv, host_vars) {
String macro = "$" + kv.first + "$"; // this is too simple String macro = "$" + kv.first + "$"; // this is too simple
if (command_line.Contains(macro)) if (command_line.Contains(macro))
args->Set(kv.first, kv.second); args->Set(kv.first, kv.second);
@ -151,7 +151,7 @@ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
Dictionary::Ptr service_vars = service->GetVars(); Dictionary::Ptr service_vars = service->GetVars();
if (service_vars) { if (service_vars) {
BOOST_FOREACH(Dictionary::Pair kv, service_vars) { BOOST_FOREACH(const Dictionary::Pair& kv, service_vars) {
String macro = "$" + kv.first + "$"; // this is too simple String macro = "$" + kv.first + "$"; // this is too simple
if (command_line.Contains(macro)) if (command_line.Contains(macro))
args->Set(kv.first, kv.second); args->Set(kv.first, kv.second);
@ -163,7 +163,7 @@ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
} }
String arg_string; String arg_string;
BOOST_FOREACH(Dictionary::Pair kv, args) { BOOST_FOREACH(const Dictionary::Pair& kv, args) {
arg_string += Convert::ToString(kv.first) + "=" + Convert::ToString(kv.second) + "!"; arg_string += Convert::ToString(kv.first) + "=" + Convert::ToString(kv.second) + "!";
} }
return arg_string; return arg_string;
@ -388,12 +388,15 @@ Dictionary::Ptr CompatUtility::GetCustomAttributeConfig(const CustomVarObject::P
if (!vars) if (!vars)
return Dictionary::Ptr(); return Dictionary::Ptr();
String key;
Value value;
ObjectLock olock(vars); ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) { BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
if (!kv.first.IsEmpty()) { if (kv.first.IsEmpty() || IsLegacyAttribute(object, kv.first))
if (!IsLegacyAttribute(object, kv.first)) continue;
varsvars->Set(kv.first, kv.second);
} varsvars->Set(kv.first, kv.second);
} }
return varsvars; return varsvars;

View File

@ -23,6 +23,7 @@
#include "icinga/compatutility.hpp" #include "icinga/compatutility.hpp"
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/json.hpp"
#include "base/utility.hpp" #include "base/utility.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
@ -53,6 +54,8 @@ void ContactsTable::AddColumns(Table *table, const String& prefix,
table->AddColumn(prefix + "vars_variables", Column(&ContactsTable::CustomVariablesAccessor, objectAccessor)); table->AddColumn(prefix + "vars_variables", Column(&ContactsTable::CustomVariablesAccessor, objectAccessor));
table->AddColumn(prefix + "modified_attributes", Column(&ContactsTable::ModifiedAttributesAccessor, objectAccessor)); table->AddColumn(prefix + "modified_attributes", Column(&ContactsTable::ModifiedAttributesAccessor, objectAccessor));
table->AddColumn(prefix + "modified_attributes_list", Column(&ContactsTable::ModifiedAttributesListAccessor, objectAccessor)); table->AddColumn(prefix + "modified_attributes_list", Column(&ContactsTable::ModifiedAttributesListAccessor, objectAccessor));
table->AddColumn(prefix + "cv_is_json", Column(&ContactsTable::CVIsJsonAccessor, objectAccessor));
} }
String ContactsTable::GetName(void) const String ContactsTable::GetName(void) const
@ -200,7 +203,12 @@ Value ContactsTable::CustomVariableNamesAccessor(const Value& row)
if (!user) if (!user)
return Empty; return Empty;
Dictionary::Ptr vars = user->GetVars(); Dictionary::Ptr vars;
{
ObjectLock olock(user);
vars = CompatUtility::GetCustomAttributeConfig(user);
}
if (!vars) if (!vars)
return Empty; return Empty;
@ -208,10 +216,8 @@ Value ContactsTable::CustomVariableNamesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>(); Array::Ptr cv = make_shared<Array>();
ObjectLock olock(vars); ObjectLock olock(vars);
String key; BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
Value value; cv->Add(kv.first);
BOOST_FOREACH(boost::tie(key, value), vars) {
cv->Add(key);
} }
return cv; return cv;
@ -224,7 +230,12 @@ Value ContactsTable::CustomVariableValuesAccessor(const Value& row)
if (!user) if (!user)
return Empty; return Empty;
Dictionary::Ptr vars = user->GetVars(); Dictionary::Ptr vars;
{
ObjectLock olock(user);
vars = CompatUtility::GetCustomAttributeConfig(user);
}
if (!vars) if (!vars)
return Empty; return Empty;
@ -232,10 +243,11 @@ Value ContactsTable::CustomVariableValuesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>(); Array::Ptr cv = make_shared<Array>();
ObjectLock olock(vars); ObjectLock olock(vars);
String key; BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
Value value; if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
BOOST_FOREACH(boost::tie(key, value), vars) { cv->Add(JsonEncode(kv.second));
cv->Add(value); else
cv->Add(kv.second);
} }
return cv; return cv;
@ -248,7 +260,12 @@ Value ContactsTable::CustomVariablesAccessor(const Value& row)
if (!user) if (!user)
return Empty; return Empty;
Dictionary::Ptr vars = user->GetVars(); Dictionary::Ptr vars;
{
ObjectLock olock(user);
vars = CompatUtility::GetCustomAttributeConfig(user);
}
if (!vars) if (!vars)
return Empty; return Empty;
@ -256,18 +273,49 @@ Value ContactsTable::CustomVariablesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>(); Array::Ptr cv = make_shared<Array>();
ObjectLock olock(vars); ObjectLock olock(vars);
String key; BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
Value value;
BOOST_FOREACH(boost::tie(key, value), vars) {
Array::Ptr key_val = make_shared<Array>(); Array::Ptr key_val = make_shared<Array>();
key_val->Add(key); key_val->Add(kv.first);
key_val->Add(value);
if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
key_val->Add(JsonEncode(kv.second));
else
key_val->Add(kv.second);
cv->Add(key_val); cv->Add(key_val);
} }
return cv; return cv;
} }
Value ContactsTable::CVIsJsonAccessor(const Value& row)
{
User::Ptr user = static_cast<User::Ptr>(row);
if (!user)
return Empty;
Dictionary::Ptr vars;
{
ObjectLock olock(user);
vars = CompatUtility::GetCustomAttributeConfig(user);
}
if (!vars)
return Empty;
bool cv_is_json = false;
ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
cv_is_json = true;
}
return cv_is_json;
}
Value ContactsTable::ModifiedAttributesAccessor(const Value& row) Value ContactsTable::ModifiedAttributesAccessor(const Value& row)
{ {
User::Ptr user = static_cast<User::Ptr>(row); User::Ptr user = static_cast<User::Ptr>(row);

View File

@ -61,6 +61,7 @@ protected:
static Value CustomVariablesAccessor(const Value& row); static Value CustomVariablesAccessor(const Value& row);
static Value ModifiedAttributesAccessor(const Value& row); static Value ModifiedAttributesAccessor(const Value& row);
static Value ModifiedAttributesListAccessor(const Value& row); static Value ModifiedAttributesListAccessor(const Value& row);
static Value CVIsJsonAccessor(const Value& row);
}; };
} }

View File

@ -28,6 +28,7 @@
#include "icinga/compatutility.hpp" #include "icinga/compatutility.hpp"
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/json.hpp"
#include "base/convert.hpp" #include "base/convert.hpp"
#include "base/utility.hpp" #include "base/utility.hpp"
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
@ -160,6 +161,7 @@ void HostsTable::AddColumns(Table *table, const String& prefix,
table->AddColumn(prefix + "services_with_info", Column(&HostsTable::ServicesWithInfoAccessor, objectAccessor)); table->AddColumn(prefix + "services_with_info", Column(&HostsTable::ServicesWithInfoAccessor, objectAccessor));
table->AddColumn(prefix + "check_source", Column(&HostsTable::CheckSourceAccessor, objectAccessor)); table->AddColumn(prefix + "check_source", Column(&HostsTable::CheckSourceAccessor, objectAccessor));
table->AddColumn(prefix + "is_reachable", Column(&HostsTable::IsReachableAccessor, objectAccessor)); table->AddColumn(prefix + "is_reachable", Column(&HostsTable::IsReachableAccessor, objectAccessor));
table->AddColumn(prefix + "cv_is_json", Column(&HostsTable::CVIsJsonAccessor, objectAccessor));
} }
String HostsTable::GetName(void) const String HostsTable::GetName(void) const
@ -1058,10 +1060,9 @@ Value HostsTable::CustomVariableNamesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>(); Array::Ptr cv = make_shared<Array>();
String key; ObjectLock olock(vars);
Value value; BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
BOOST_FOREACH(tie(key, value), vars) { cv->Add(kv.first);
cv->Add(key);
} }
return cv; return cv;
@ -1086,10 +1087,12 @@ Value HostsTable::CustomVariableValuesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>(); Array::Ptr cv = make_shared<Array>();
String key; ObjectLock olock(vars);
Value value; BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
BOOST_FOREACH(tie(key, value), vars) { if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
cv->Add(value); cv->Add(JsonEncode(kv.second));
else
cv->Add(kv.second);
} }
return cv; return cv;
@ -1114,18 +1117,50 @@ Value HostsTable::CustomVariablesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>(); Array::Ptr cv = make_shared<Array>();
String key; ObjectLock olock(vars);
Value value; BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
BOOST_FOREACH(tie(key, value), vars) {
Array::Ptr key_val = make_shared<Array>(); Array::Ptr key_val = make_shared<Array>();
key_val->Add(key); key_val->Add(kv.first);
key_val->Add(value);
if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
key_val->Add(JsonEncode(kv.second));
else
key_val->Add(kv.second);
cv->Add(key_val); cv->Add(key_val);
} }
return cv; return cv;
} }
Value HostsTable::CVIsJsonAccessor(const Value& row)
{
Host::Ptr host = static_cast<Host::Ptr>(row);
if (!host)
return Empty;
Dictionary::Ptr vars;
{
ObjectLock olock(host);
vars = CompatUtility::GetCustomAttributeConfig(host);
}
if (!vars)
return Empty;
bool cv_is_json = false;
ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
cv_is_json = true;
}
return cv_is_json;
}
Value HostsTable::ParentsAccessor(const Value& row) Value HostsTable::ParentsAccessor(const Value& row)
{ {
Host::Ptr host = static_cast<Host::Ptr>(row); Host::Ptr host = static_cast<Host::Ptr>(row);

View File

@ -143,6 +143,7 @@ protected:
static Value ServicesWithInfoAccessor(const Value& row); static Value ServicesWithInfoAccessor(const Value& row);
static Value CheckSourceAccessor(const Value& row); static Value CheckSourceAccessor(const Value& row);
static Value IsReachableAccessor(const Value& row); static Value IsReachableAccessor(const Value& row);
static Value CVIsJsonAccessor(const Value& row);
}; };
} }

View File

@ -29,6 +29,7 @@
#include "icinga/compatutility.hpp" #include "icinga/compatutility.hpp"
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/json.hpp"
#include "base/convert.hpp" #include "base/convert.hpp"
#include "base/utility.hpp" #include "base/utility.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
@ -129,6 +130,7 @@ void ServicesTable::AddColumns(Table *table, const String& prefix,
table->AddColumn(prefix + "contact_groups", Column(&ServicesTable::ContactGroupsAccessor, objectAccessor)); table->AddColumn(prefix + "contact_groups", Column(&ServicesTable::ContactGroupsAccessor, objectAccessor));
table->AddColumn(prefix + "check_source", Column(&ServicesTable::CheckSourceAccessor, objectAccessor)); table->AddColumn(prefix + "check_source", Column(&ServicesTable::CheckSourceAccessor, objectAccessor));
table->AddColumn(prefix + "is_reachable", Column(&ServicesTable::IsReachableAccessor, objectAccessor)); table->AddColumn(prefix + "is_reachable", Column(&ServicesTable::IsReachableAccessor, objectAccessor));
table->AddColumn(prefix + "cv_is_json", Column(&ServicesTable::CVIsJsonAccessor, objectAccessor));
HostsTable::AddColumns(table, "host_", boost::bind(&ServicesTable::HostAccessor, _1, objectAccessor)); HostsTable::AddColumns(table, "host_", boost::bind(&ServicesTable::HostAccessor, _1, objectAccessor));
} }
@ -1063,8 +1065,8 @@ Value ServicesTable::CustomVariableNamesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>(); Array::Ptr cv = make_shared<Array>();
ObjectLock olock(vars); ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair kv, vars) { BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
cv->Add(kv.second); cv->Add(kv.first);
} }
return cv; return cv;
@ -1091,7 +1093,10 @@ Value ServicesTable::CustomVariableValuesAccessor(const Value& row)
ObjectLock olock(vars); ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) { BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
cv->Add(kv.second); if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
cv->Add(JsonEncode(kv.second));
else
cv->Add(kv.second);
} }
return cv; return cv;
@ -1116,18 +1121,50 @@ Value ServicesTable::CustomVariablesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>(); Array::Ptr cv = make_shared<Array>();
String key; ObjectLock olock(vars);
Value value; BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
BOOST_FOREACH(tie(key, value), vars) {
Array::Ptr key_val = make_shared<Array>(); Array::Ptr key_val = make_shared<Array>();
key_val->Add(key); key_val->Add(kv.first);
key_val->Add(value);
if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
key_val->Add(JsonEncode(kv.second));
else
key_val->Add(kv.second);
cv->Add(key_val); cv->Add(key_val);
} }
return cv; return cv;
} }
Value ServicesTable::CVIsJsonAccessor(const Value& row)
{
Service::Ptr service = static_cast<Service::Ptr>(row);
if (!service)
return Empty;
Dictionary::Ptr vars;
{
ObjectLock olock(service);
vars = CompatUtility::GetCustomAttributeConfig(service);
}
if (!vars)
return Empty;
bool cv_is_json = false;
ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
cv_is_json = true;
}
return cv_is_json;
}
Value ServicesTable::GroupsAccessor(const Value& row) Value ServicesTable::GroupsAccessor(const Value& row)
{ {
Service::Ptr service = static_cast<Service::Ptr>(row); Service::Ptr service = static_cast<Service::Ptr>(row);

View File

@ -126,6 +126,7 @@ protected:
static Value ContactGroupsAccessor(const Value& row); static Value ContactGroupsAccessor(const Value& row);
static Value CheckSourceAccessor(const Value& row); static Value CheckSourceAccessor(const Value& row);
static Value IsReachableAccessor(const Value& row); static Value IsReachableAccessor(const Value& row);
static Value CVIsJsonAccessor(const Value& row);
}; };
} }

View File

@ -1,4 +1,4 @@
GET hosts GET hosts
Columns: custom_variable_names custom_variable_values custom_variables Columns: name custom_variable_names custom_variable_values custom_variables cv_is_json
ResponseHeader: fixed16 ResponseHeader: fixed16

View File

@ -1,4 +1,4 @@
GET services GET services
Columns: custom_variable_names custom_variable_values custom_variables Columns: host_name service_description custom_variables cv_is_json
ResponseHeader: fixed16 ResponseHeader: fixed16

View File

@ -1,5 +1,7 @@
#!/bin/bash #!/bin/bash
NC=`which nc`
LIVESTATUSSOCKET="/var/run/icinga2/cmd/livestatus"
LIVESTATUSHOST="127.0.0.1" LIVESTATUSHOST="127.0.0.1"
LIVESTATUSPORT="6558" LIVESTATUSPORT="6558"
LIVESTATUSQUERIES="./queries" LIVESTATUSQUERIES="./queries"
@ -8,14 +10,14 @@ LIVESTATUSTABLE=$1
if [ -n "$LIVESTATUSTABLE" ]; then if [ -n "$LIVESTATUSTABLE" ]; then
cat "$LIVESTATUSTABLE" cat "$LIVESTATUSTABLE"
(cat "$LIVESTATUSTABLE"; sleep 1) | netcat $LIVESTATUSHOST $LIVESTATUSPORT (cat "$LIVESTATUSTABLE"; sleep 1) | $NC -U $LIVESTATUSSOCKET
else else
echo -e "Looking into $LIVESTATUSQUERIES\n" echo -e "Looking into $LIVESTATUSQUERIES\n"
for q in $(find $LIVESTATUSQUERIES -type f) for q in $(find $LIVESTATUSQUERIES -type f)
do do
cat $q cat $q
(cat $q; sleep 1) | netcat $LIVESTATUSHOST $LIVESTATUSPORT (cat $q; sleep 1) | $NC -U $LIVESTATUSSOCKET
echo -e "================================\n\n" echo -e "================================\n\n"
done done
fi fi