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
services | is_reachable
hosts | cv_is_json
services | cv_is_json
contacts | cv_is_json
hosts | check_source
services | check_source
downtimes | triggers

View File

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

View File

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

View File

@ -61,6 +61,7 @@ protected:
static Value CustomVariablesAccessor(const Value& row);
static Value ModifiedAttributesAccessor(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 "base/dynamictype.hpp"
#include "base/objectlock.hpp"
#include "base/json.hpp"
#include "base/convert.hpp"
#include "base/utility.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 + "check_source", Column(&HostsTable::CheckSourceAccessor, 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
@ -1058,10 +1060,9 @@ Value HostsTable::CustomVariableNamesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>();
String key;
Value value;
BOOST_FOREACH(tie(key, value), vars) {
cv->Add(key);
ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
cv->Add(kv.first);
}
return cv;
@ -1086,10 +1087,12 @@ Value HostsTable::CustomVariableValuesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>();
String key;
Value value;
BOOST_FOREACH(tie(key, value), vars) {
cv->Add(value);
ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
cv->Add(JsonEncode(kv.second));
else
cv->Add(kv.second);
}
return cv;
@ -1114,18 +1117,50 @@ Value HostsTable::CustomVariablesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>();
String key;
Value value;
BOOST_FOREACH(tie(key, value), vars) {
ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
Array::Ptr key_val = make_shared<Array>();
key_val->Add(key);
key_val->Add(value);
key_val->Add(kv.first);
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);
}
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)
{
Host::Ptr host = static_cast<Host::Ptr>(row);

View File

@ -143,6 +143,7 @@ protected:
static Value ServicesWithInfoAccessor(const Value& row);
static Value CheckSourceAccessor(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 "base/dynamictype.hpp"
#include "base/objectlock.hpp"
#include "base/json.hpp"
#include "base/convert.hpp"
#include "base/utility.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 + "check_source", Column(&ServicesTable::CheckSourceAccessor, 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));
}
@ -1063,8 +1065,8 @@ Value ServicesTable::CustomVariableNamesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>();
ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair kv, vars) {
cv->Add(kv.second);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
cv->Add(kv.first);
}
return cv;
@ -1091,7 +1093,10 @@ Value ServicesTable::CustomVariableValuesAccessor(const Value& row)
ObjectLock olock(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;
@ -1116,18 +1121,50 @@ Value ServicesTable::CustomVariablesAccessor(const Value& row)
Array::Ptr cv = make_shared<Array>();
String key;
Value value;
BOOST_FOREACH(tie(key, value), vars) {
ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
Array::Ptr key_val = make_shared<Array>();
key_val->Add(key);
key_val->Add(value);
key_val->Add(kv.first);
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);
}
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)
{
Service::Ptr service = static_cast<Service::Ptr>(row);

View File

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

View File

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

View File

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

View File

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