Commit b4035c1f authored by Micha Müller's avatar Micha Müller
Browse files

Merge branch 'CommonRestServer' into 'master'

Common rest server

See merge request !3
parents 72b1ca02 9f44fe66
...@@ -6,7 +6,7 @@ install/ ...@@ -6,7 +6,7 @@ install/
*.o *.o
*.so *.so
*.dylib *.dylib
collectagent collectagent/collectagent
dcdbpusher/dcdbpusher dcdbpusher/dcdbpusher
tools/dcdbconfig/dcdbconfig tools/dcdbconfig/dcdbconfig
tools/dcdbcsvimport/dcdbcsvimport tools/dcdbcsvimport/dcdbcsvimport
......
...@@ -4,30 +4,38 @@ MAKEFILENAME := $(lastword $(MAKEFILE_LIST)) ...@@ -4,30 +4,38 @@ MAKEFILENAME := $(lastword $(MAKEFILE_LIST))
SUB_DIRS = lib collectagent dcdbpusher analytics tools scripts SUB_DIRS = lib collectagent dcdbpusher analytics tools scripts
SOURCEFORGE_MROR = vorboss
CASSANDRA_VERSION = 3.0.18 CASSANDRA_VERSION = 3.0.18
MOSQUITTO_VERSION = 1.5.5 MOSQUITTO_VERSION = 1.5.5
BOOST_VERSION = 1.58.0 BOOST_VERSION = 1.70.0
OPENSSL_VERSION = 1.0.2l OPENSSL_VERSION = 1.0.2l
CPPDRV_VERSION = 2.10.0 CPPDRV_VERSION = 2.10.0
LIBUV_VERSION = 1.24.0 LIBUV_VERSION = 1.24.0
SOURCEFORGE_MROR = vorboss
CPPNET_VERSION = 0.12.0-final
BACNET-STACK_VERSION = 0.8.5 BACNET-STACK_VERSION = 0.8.5
FREEIPMI_VERSION = 1.5.5 FREEIPMI_VERSION = 1.5.5
NET-SNMP_VERSION = 5.8 NET-SNMP_VERSION = 5.8
BOOST_VERSION_U = $(subst .,_,$(BOOST_VERSION)) BOOST_VERSION_U = $(subst .,_,$(BOOST_VERSION))
DISTFILES = apache-cassandra-$(CASSANDRA_VERSION).tar.gz;http://archive.apache.org/dist/cassandra/$(CASSANDRA_VERSION)/apache-cassandra-$(CASSANDRA_VERSION)-bin.tar.gz \ DISTFILES = apache-cassandra-$(CASSANDRA_VERSION).tar.gz;http://archive.apache.org/dist/cassandra/$(CASSANDRA_VERSION)/apache-cassandra-$(CASSANDRA_VERSION)-bin.tar.gz \
mosquitto-$(MOSQUITTO_VERSION).tar.gz;http://mosquitto.org/files/source/mosquitto-$(MOSQUITTO_VERSION).tar.gz \ mosquitto-$(MOSQUITTO_VERSION).tar.gz;http://mosquitto.org/files/source/mosquitto-$(MOSQUITTO_VERSION).tar.gz \
boost_$(BOOST_VERSION_U).tar.gz;http://$(SOURCEFORGE_MROR).dl.sourceforge.net/project/boost/boost/$(BOOST_VERSION)/boost_$(BOOST_VERSION_U).tar.gz \ boost_$(BOOST_VERSION_U).tar.gz;http://$(SOURCEFORGE_MROR).dl.sourceforge.net/project/boost/boost/$(BOOST_VERSION)/boost_$(BOOST_VERSION_U).tar.gz \
openssl-$(OPENSSL_VERSION).tar.gz;https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz \ openssl-$(OPENSSL_VERSION).tar.gz;https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz \
libuv-v$(LIBUV_VERSION).tar.gz;https://dist.libuv.org/dist/v$(LIBUV_VERSION)/libuv-v$(LIBUV_VERSION).tar.gz \ libuv-v$(LIBUV_VERSION).tar.gz;https://dist.libuv.org/dist/v$(LIBUV_VERSION)/libuv-v$(LIBUV_VERSION).tar.gz \
cpp-driver-$(CPPDRV_VERSION).tar.gz;https://github.com/datastax/cpp-driver/archive/$(CPPDRV_VERSION).tar.gz \ cpp-driver-$(CPPDRV_VERSION).tar.gz;https://github.com/datastax/cpp-driver/archive/$(CPPDRV_VERSION).tar.gz \
cpp-netlib-$(CPPNET_VERSION).tar.gz;http://downloads.cpp-netlib.org/0.12.0/cpp-netlib-$(CPPNET_VERSION).tar.gz \
bacnet-stack-$(BACNET-STACK_VERSION).tgz;https://downloads.sourceforge.net/project/bacnet/bacnet-stack/bacnet-stack-$(BACNET-STACK_VERSION)/bacnet-stack-$(BACNET-STACK_VERSION).tgz \ bacnet-stack-$(BACNET-STACK_VERSION).tgz;https://downloads.sourceforge.net/project/bacnet/bacnet-stack/bacnet-stack-$(BACNET-STACK_VERSION)/bacnet-stack-$(BACNET-STACK_VERSION).tgz \
freeipmi-$(FREEIPMI_VERSION).tar.gz;http://ftp.gnu.org/gnu/freeipmi/freeipmi-$(FREEIPMI_VERSION).tar.gz \ freeipmi-$(FREEIPMI_VERSION).tar.gz;http://ftp.gnu.org/gnu/freeipmi/freeipmi-$(FREEIPMI_VERSION).tar.gz \
net-snmp-$(NET-SNMP_VERSION).tar.gz;https://sourceforge.net/projects/net-snmp/files/net-snmp/$(NET-SNMP_VERSION)/net-snmp-$(NET-SNMP_VERSION).tar.gz/download net-snmp-$(NET-SNMP_VERSION).tar.gz;https://sourceforge.net/projects/net-snmp/files/net-snmp/$(NET-SNMP_VERSION)/net-snmp-$(NET-SNMP_VERSION).tar.gz/download
DISTFILES_HASHES = apache-cassandra-3.0.18.tar.gz|94dbdaa58b366166c53f881b8e266bc8;mosquitto-1.5.5.tar.gz|a17dffc6f63b2a4ab2eb5c51139e60e9;boost_1_58_0.tar.gz|5a5d5614d9a07672e1ab2a250b5defc5;openssl-1.0.2l.tar.gz|f85123cd390e864dfbe517e7616e6566;cpp-driver-2.10.0.tar.gz|6d15dd2cccd2efd1fdc86089d26971d0;libuv-v1.24.0.tar.gz|90320330757253b07404d2a97f59c66b;cpp-netlib-0.12.0-final.tar.gz|29b87c0e8c1a9e7fbdea5afcec947d53;bacnet-stack-$(BACNET-STACK_VERSION).tgz|66b69111d91432fa67a7c6c1a653434d;freeipmi-$(FREEIPMI_VERSION).tar.gz|b8abfefee0b757f351d8fab777e3c1bb;net-snmp-$(NET-SNMP_VERSION).tar.gz|63bfc65fbb86cdb616598df1aff6458a
DISTFILES_HASHES = apache-cassandra-3.0.18.tar.gz|94dbdaa58b366166c53f881b8e266bc8;\
mosquitto-1.5.5.tar.gz|a17dffc6f63b2a4ab2eb5c51139e60e9;\
boost_1_70_0.tar.gz|fea771fe8176828fabf9c09242ee8c26;\
openssl-1.0.2l.tar.gz|f85123cd390e864dfbe517e7616e6566;\
cpp-driver-2.10.0.tar.gz|6d15dd2cccd2efd1fdc86089d26971d0;\
libuv-v1.24.0.tar.gz|90320330757253b07404d2a97f59c66b;\
bacnet-stack-0.8.5.tgz|66b69111d91432fa67a7c6c1a653434d;\
freeipmi-1.5.5.tar.gz|b8abfefee0b757f351d8fab777e3c1bb;\
net-snmp-5.8.tar.gz|63bfc65fbb86cdb616598df1aff6458a
include common.mk include common.mk
...@@ -149,7 +157,7 @@ $(DCDBDEPSPATH)/boost_$(BOOST_VERSION_U)/.built: $(DCDBDEPSPATH)/boost_$(BOOST_V ...@@ -149,7 +157,7 @@ $(DCDBDEPSPATH)/boost_$(BOOST_VERSION_U)/.built: $(DCDBDEPSPATH)/boost_$(BOOST_V
$(DCDBDEPSPATH)/boost_$(BOOST_VERSION_U)/.installed: $(DCDBDEPSPATH)/boost_$(BOOST_VERSION_U)/.built $(DCDBDEPSPATH)/boost_$(BOOST_VERSION_U)/.installed: $(DCDBDEPSPATH)/boost_$(BOOST_VERSION_U)/.built
cd $(@D) && ./b2 -j $(MAKETHREADS) install && touch $(@) cd $(@D) && ./b2 -j $(MAKETHREADS) --no-cmake-config install && touch $(@)
$(DCDBDEPSPATH)/libuv-v$(LIBUV_VERSION)/.built: $(DCDBDEPSPATH)/libuv-v$(LIBUV_VERSION)/.patched $(DCDBDEPSPATH)/libuv-v$(LIBUV_VERSION)/.built: $(DCDBDEPSPATH)/libuv-v$(LIBUV_VERSION)/.patched
@echo "Building libuv..." @echo "Building libuv..."
...@@ -184,24 +192,6 @@ $(DCDBDEPSPATH)/cpp-driver-$(CPPDRV_VERSION)/.installed: $(DCDBDEPSPATH)/cpp-dri ...@@ -184,24 +192,6 @@ $(DCDBDEPSPATH)/cpp-driver-$(CPPDRV_VERSION)/.installed: $(DCDBDEPSPATH)/cpp-dri
@echo "Installing cpp-driver..." @echo "Installing cpp-driver..."
cd $(@D)/build && make install && touch $(@) cd $(@D)/build && make install && touch $(@)
$(DCDBDEPSPATH)/cpp-netlib-$(CPPNET_VERSION)/.built: $(DCDBDEPSPATH)/cpp-netlib-$(CPPNET_VERSION)/.patched
@echo "Building cpp-netlib..."
mkdir -p $(DCDBDEPSPATH)/cpp-netlib_build
cd $(DCDBDEPSPATH)/cpp-netlib_build && \
CC=$(FULL_CC) CXX=$(FULL_CXX) cmake $(CMAKE_CROSS_FLAGS) \
-DCPP-NETLIB_ENABLE_HTTPS=off \
-DCPP-NETLIB_BUILD_TESTS=OFF \
-DCPP-NETLIB_BUILD_EXAMPLES=OFF \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_INSTALL_PREFIX=$(DCDBDEPLOYPATH)/ \
-DBOOST_ROOT=$(DCDBDEPSPATH)/boost_$(BOOST_VERSION_U)/ \
$(@D) && \
make -j $(MAKETHREADS) && touch $(@)
$(DCDBDEPSPATH)/cpp-netlib-$(CPPNET_VERSION)/.installed: $(DCDBDEPSPATH)/cpp-netlib-$(CPPNET_VERSION)/.built | $(DCDBDEPLOYPATH)
@echo "Installing cpp-netlib..."
cd $(DCDBDEPSPATH)/cpp-netlib_build && make install && touch $(@)
$(DCDBDEPSPATH)/apache-cassandra-$(CASSANDRA_VERSION)/.built: $(DCDBDEPSPATH)/apache-cassandra-$(CASSANDRA_VERSION)/.patched $(DCDBDEPSPATH)/apache-cassandra-$(CASSANDRA_VERSION)/.built: $(DCDBDEPSPATH)/apache-cassandra-$(CASSANDRA_VERSION)/.patched
@touch $(DCDBDEPSPATH)/apache-cassandra-$(CASSANDRA_VERSION)/.built @touch $(DCDBDEPSPATH)/apache-cassandra-$(CASSANDRA_VERSION)/.built
......
...@@ -262,239 +262,389 @@ bool AnalyticsManager::stop(const string& plugin, const string& analyzer) { ...@@ -262,239 +262,389 @@ bool AnalyticsManager::stop(const string& plugin, const string& analyzer) {
return out; return out;
} }
restResponse_t AnalyticsManager::REST(const vector<string>& pathStrs, const vector<pair<string,string>>& queries, const string& method, boost::asio::io_service& io) { /******************************************************************************/
// Some preliminary checks /* Rest API endpoint methods */
if(_status != LOADED) /******************************************************************************/
throw runtime_error("Cannot forward REST command, AnalyticsManager is not loaded!");
if (method != "GET" && method != "PUT") #define stdBind(fun) std::bind(&AnalyticsManager::fun, \
throw invalid_argument("Unsupported REST method!"); this, \
if(pathStrs.size() < 2 || pathStrs[0] != "analytics") std::placeholders::_1, \
throw invalid_argument("Received malformed request!"); std::placeholders::_2)
// Determining if JSON output was requested void AnalyticsManager::addRestEndpoints(RESTHttpsServer* restServer) {
bool json = false; restServer->addEndpoint("/analytics/help", {http::verb::get, stdBind(GET_analytics_help)});
for (auto& p : queries) restServer->addEndpoint("/analytics/plugins", {http::verb::get, stdBind(GET_analytics_plugins)});
if (p.first == "json") restServer->addEndpoint("/analytics/sensors", {http::verb::get, stdBind(GET_analytics_sensors)});
json = stoi(p.second) > 0; restServer->addEndpoint("/analytics/units", {http::verb::get, stdBind(GET_analytics_units)});
restServer->addEndpoint("/analytics/analyzers", {http::verb::get, stdBind(GET_analytics_analyzers)});
restResponse_t reply;
restServer->addEndpoint("/analytics/start", {http::verb::put, stdBind(PUT_analytics_start)});
restServer->addEndpoint("/analytics/stop", {http::verb::put, stdBind(PUT_analytics_stop)});
restServer->addEndpoint("/analytics/reload", {http::verb::put, stdBind(PUT_analytics_reload)});
restServer->addEndpoint("/analytics/compute", {http::verb::put, stdBind(PUT_analytics_compute)});
restServer->addEndpoint("/analytics/analyzer", {http::verb::put, stdBind(PUT_analytics_analyzer)});
}
void AnalyticsManager::GET_analytics_help(endpointArgs){
if (!managerLoaded(res)) {
return;
}
res.body() = restCheatSheet;
res.result(http::status::ok);
}
void AnalyticsManager::GET_analytics_plugins(endpointArgs) {
if (!managerLoaded(res)) {
return;
}
std::ostringstream data; std::ostringstream data;
if (getQuery("json", queries) == "true") {
boost::property_tree::ptree root, plugins;
for(const auto& p : _plugins) {
plugins.put(p.id, "");
}
root.add_child("plugins", plugins);
boost::property_tree::write_json(data, root, true);
} else {
for(const auto& p : _plugins) {
data << p.id << "\n";
}
}
res.body() = data.str();
res.result(http::status::ok);
}
// GET block of commands void AnalyticsManager::GET_analytics_sensors(endpointArgs) {
if (method == "GET") { if (!managerLoaded(res)) {
// Help cheatsheet command return;
if (pathStrs[1] == "help") { }
reply.response = restCheatSheet;
// Command to list data analytics plugins const std::string plugin = getQuery("plugin", queries);
} else if (pathStrs[1] == "plugins") { const std::string analyzer = getQuery("analyzer", queries);
if (json) {
boost::property_tree::ptree root, plugins; if (!hasPlugin(plugin, res)) {
for(auto& p : _plugins) return;
plugins.put(p.id, ""); }
root.add_child("plugins", plugins);
boost::property_tree::write_json(data, root, true); bool found = false;
} else std::ostringstream data;
for(auto& p : _plugins)
data << p.id << "\n"; for (const auto& p : _plugins) {
reply.data = data.str(); if (p.id == plugin) {
// Managing commands that have a path length greater than 2 if (getQuery("json", queries) == "true") {
} else { boost::property_tree::ptree root, sensors;
if (pathStrs.size() < 3)
throw invalid_argument("Received malformed request, no second path part!"); // In JSON mode, sensors are arranged hierarchically by plugin->analyzer->sensor
for (const auto& a : p.configurator->getAnalyzers()) {
string analyzer = pathStrs.size() > 3 ? pathStrs[2] : ""; if (a->getStreaming() && (analyzer == "" || analyzer == a->getName())) {
string action = pathStrs[pathStrs.size() - 1]; found = true;
string plugin = pathStrs[1]; boost::property_tree::ptree group;
for (const auto& u : a->getUnits()) {
// Listing all sensors in one or all analyzers of a plugin; the [analyzer] block is optional for (const auto& s : u->getBaseOutputs()) {
if (action == "sensors") { // Explicitly adding nodes to the ptree as to prevent BOOST from performing
bool found = false; // parsing on the node names
for (auto &p : _plugins) { group.push_back(boost::property_tree::ptree::value_type(s->getName(), boost::property_tree::ptree(s->getMqtt())));
if (p.id == plugin) { }
if (json) {
boost::property_tree::ptree root, sensors;
// In JSON mode, sensors are arranged hierarchically by plugin->analyzer->sensor
for (auto &a : p.configurator->getAnalyzers())
if (a->getStreaming() && (analyzer == "" || analyzer == a->getName())) {
found = true;
boost::property_tree::ptree group;
for (auto &u : a->getUnits())
for (auto &s : u->getBaseOutputs())
// Explicitly adding nodes to the ptree as to prevent BOOST from performing
// parsing on the node names
group.push_back(boost::property_tree::ptree::value_type(s->getName(), boost::property_tree::ptree(s->getMqtt())));
sensors.add_child(a->getName(), group);
}
root.add_child(p.id, sensors);
boost::property_tree::write_json(data, root, true);
} else {
for (auto &a : p.configurator->getAnalyzers())
if (a->getStreaming() && (analyzer == "" || analyzer == a->getName())) {
found = true;
for (auto &u : a->getUnits())
for (auto &s : u->getBaseOutputs())
data << a->getName() << "." << s->getName() << " " << s->getMqtt() << "\n";
}
} }
reply.data = data.str(); sensors.add_child(a->getName(), group);
break;
} }
} }
if (!found) root.add_child(p.id, sensors);
throw domain_error("Plugin or analyzer not found!"); boost::property_tree::write_json(data, root, true);
} else if (action == "units") { } else {
bool found = false; for (const auto& a : p.configurator->getAnalyzers()) {
for (auto &p : _plugins) { if (a->getStreaming() && (analyzer == "" || analyzer == a->getName())) {
if (p.id == plugin) { found = true;
if (json) { for (const auto& u : a->getUnits()) {
boost::property_tree::ptree root, units; for (const auto& s : u->getBaseOutputs()) {
data << a->getName() << "." << s->getName() << " " << s->getMqtt() << "\n";
// In JSON mode, units are arranged hierarchically by plugin->analyzer->unit }
for (auto &a : p.configurator->getAnalyzers())
if (a->getStreaming() && (analyzer == "" || analyzer == a->getName())) {
found = true;
boost::property_tree::ptree group;
for (auto &u : a->getUnits())
group.push_back(boost::property_tree::ptree::value_type(u->getName(), boost::property_tree::ptree()));
units.add_child(a->getName(), group);
}
root.add_child(p.id, units);
boost::property_tree::write_json(data, root, true);
} else {
for (auto &a : p.configurator->getAnalyzers())
if (a->getStreaming() && (analyzer == "" || analyzer == a->getName())) {
found = true;
for (auto &u : a->getUnits())
data << a->getName() << "." << u->getName() << "\n";
}
} }
reply.data = data.str();
break;
} }
} }
if (!found) }
throw domain_error("Plugin or analyzer not found!"); res.body() = data.str();
} else if (action == "analyzers") { res.result(http::status::ok);
if(analyzer != "") break;
throw invalid_argument("Analyzers GET command does not support analyzer names!"); }
bool found = false; }
for (auto &p : _plugins) { if (!found) {
if (p.id == plugin) { res.body() = "Plugin or analyzer not found!\n";
if (json) { res.result(http::status::not_found);
boost::property_tree::ptree root, analyzers; }
}
// For each analyzer, we output its type as well
for (auto &a : p.configurator->getAnalyzers()) void AnalyticsManager::GET_analytics_units(endpointArgs) {
analyzers.push_back(boost::property_tree::ptree::value_type(a->getName(), boost::property_tree::ptree(a->getStreaming() ? "streaming" : "on-demand"))); if (!managerLoaded(res)) {
root.add_child(p.id, analyzers); return;
boost::property_tree::write_json(data, root, true); }
} else {
for (auto &a : p.configurator->getAnalyzers()) const std::string plugin = getQuery("plugin", queries);
data << a->getName() << " " << (a->getStreaming() ? "streaming\n" : "on-demand\n"); const std::string analyzer = getQuery("analyzer", queries);
if (!hasPlugin(plugin, res)) {
return;
}
bool found = false;
std::ostringstream data;
for (const auto& p : _plugins) {
if (p.id == plugin) {
if (getQuery("json", queries) == "true") {
boost::property_tree::ptree root, units;
// In JSON mode, sensors are arranged hierarchically by plugin->analyzer->sensor
for (const auto& a : p.configurator->getAnalyzers())
if (a->getStreaming() && (analyzer == "" || analyzer == a->getName())) {
found = true;
boost::property_tree::ptree group;
for (const auto& u : a->getUnits()) {
group.push_back(boost::property_tree::ptree::value_type(u->getName(), boost::property_tree::ptree()));
} }
units.add_child(a->getName(), group);
}
root.add_child(p.id, units);
boost::property_tree::write_json(data, root, true);
} else {
for (const auto& a : p.configurator->getAnalyzers()) {
if (a->getStreaming() && (analyzer == "" || analyzer == a->getName())) {
found = true; found = true;
reply.data = data.str(); for (const auto& u : a->getUnits()) {
break; data << a->getName() << "." << u->getName() << "\n";
}
} }
} }
if (!found) }
throw domain_error("Plugin not found!"); res.body() = data.str();
} else res.result(http::status::ok);
throw invalid_argument("Unknown action " + action + " requested"); break;
} }
// PUT block of commands }
} else if (method == "PUT") { if (!found) {
res.body() = "Plugin or analyzer not found!\n";
res.result(http::status::not_found);
}
}
void AnalyticsManager::GET_analytics_analyzers(endpointArgs) {
if (!managerLoaded(res)) {
return;
}
if (pathStrs.size() < 3) const std::string plugin = getQuery("plugin", queries);
throw invalid_argument("Received malformed request, no second path part!");
string analyzer = pathStrs.size() > 3 ? pathStrs[2] : ""; if (!hasPlugin(plugin, res)) {
string action = pathStrs[pathStrs.size() - 1]; return;
string plugin = pathStrs[1]; }
// Managing generic plugin PUT actions std::ostringstream data;
if (action == "start") {
if( start(plugin, analyzer) ) { for (const auto& p : _plugins) {
reply.response = "Plugin " + plugin + " " + analyzer + ": Sensors started"; if (p.id == plugin) {
} else if (getQuery("json", queries) == "true") {
throw domain_error("Plugin or analyzer not found!"); boost::property_tree::ptree root, analyzers;
} else if (action == "stop") {
if( stop(plugin, analyzer) ) { // For each analyzer, we output its type as well
reply.response = "Plugin " + plugin + " " + analyzer + ": Sensors stopped"; for (const auto& a : p.configurator->getAnalyzers()) {
} else analyzers.push_back(boost::property_tree::ptree::value_type(a->getName(), boost::property_tree::ptree(a->getStreaming() ? "streaming" : "on-demand")));
throw domain_error("Plugin or analyzer not found!"); }
} else if (action == "reload") { root.add_child(p.id, analyzers);
if(!reload(io, plugin)) boost::property_tree::write_json(data, root, true);
throw domain_error("Plugin not found or reload failed, please check the config files and MQTT topics!"); } else {
else if(!start(plugin)) for (const auto& a : p.configurator->getAnalyzers()) {
throw runtime_error("Plugin cannot be restarted!"); data << a->getName() << " " << (a->getStreaming() ? "streaming\n" : "on-demand\n");
reply.response = "Plugin " + plugin + ": Sensors reloaded"; }
} else if (action == "compute") { }
if(pathStrs.size() < 4) res.body() = data.str();
throw invalid_argument("Received malformed request, no third path part!"); res.result(http::status::ok);
return;
string unit = SensorNavigator::rootKey; }
for (auto& p : queries) }
if (p.first == "unit") }
unit = p.second;
bool found=false, unitFound=false; void AnalyticsManager::PUT_analytics_start(endpointArgs) {
for (auto &p : _plugins) if (!managerLoaded(res)) {
if (p.id == plugin) return;
for (auto &a : p.configurator->getAnalyzers()) }
if( a->getName() == analyzer ) {
found = true; const std::string plugin = getQuery("plugin", queries);
map <string, reading_t> outMap; const std::string analyzer = getQuery("analyzer", queries);
try {
outMap = a->computeOnDemand(unit); if (start(plugin, analyzer)) {
unitFound = true; res.body() = "Plugin " + plugin + " " + analyzer + ": Sensors started!\n";
} catch(const domain_error& e) { res.result(http::status::ok);
// In the particular case where an analyzer is duplicated, it could be that the right } else {
// unit is found only after a few tries. Therefore, we handle the domain_error res.body() = "Plugin or analyzer not found!\n";
// exception raised in AnalyzerTemplate, and allow the search to continue res.result(http::status::not_found);
if(a->getStreaming() && a->getDuplicate()) }
continue; }
else
throw; void AnalyticsManager::PUT_analytics_stop(endpointArgs) {
} if (!managerLoaded(res)) {
if (json) { return;
boost::property_tree::ptree root, outputs; }
// Iterating through the outputs of the on-demand computation and adding them to a JSON
for (const auto& kv : outMap) { const std::string plugin = getQuery("plugin", queries);
boost::property_tree::ptree sensor; const std::string analyzer = getQuery("analyzer", queries);
sensor.push_back(boost::property_tree::ptree::value_type("timestamp", boost::property_tree::ptree(to_string(kv.second.timestamp))));
sensor.push_back(boost::property_tree::ptree::value_type("value", boost::property_tree::ptree(to_string(kv.second.value)))); if (stop(plugin, analyzer)) {
outputs.push_back(boost::property_tree::ptree::value_type(kv.first, sensor)); res.body() = "Plugin " + plugin + " " + analyzer + ": Sensors stopped!\n";
} res.result(http::status::ok);
root.add_child(a->getName(), outputs); } else {
boost::property_tree::write_json(data, root, true); res.body() = "Plugin or analyzer not found!\n";
} else { res.result(http::status::not_found);
for (const auto& kv : outMap) }
data << kv.first << " ts: " << kv.second.timestamp << " v: " << kv.second.value << "\n"; }
}
reply.data = data.str(); void AnalyticsManager::PUT_analytics_reload(endpointArgs) {
break; if (!managerLoaded(res)) {
return;
}
/*
* This endpoint must either be overwritten (by adding a custom
* "analyzer/reload" endpoint) or must not be used. A reload requires
* an external io_service object and can therefore not be conducted by the
* AnalyticsManager itself.
*/
res.body() = "Sorry! It seems like this endpoint was not properly implemented.\n";
res.result(http::status::not_implemented);
/*
const std::string plugin = getQuery("plugin", queries);
if (!reload(_io, plugin)) {
res.body() = "Plugin not found or reload failed, please check the config files and MQTT topics!\n";
res.result(http::status::not_found);
} else if (!start(plugin)){
res.body() = "Plugin cannot be restarted!\n";
res.result(http::status::internal_server_error);
} else {
res.body() = "Plugin " + plugin + ": Sensors reloaded";
res.result(http::status::ok);
}
*/
}
void AnalyticsManager::PUT_analytics_compute(endpointArgs) {
if (!managerLoaded(res)) {
return;
}
const std::string plugin = getQuery("plugin", queries);
const std::string analyzer = getQuery("analyzer", queries);
std::string unit = getQuery("unit", queries);
if (plugin == "" || analyzer == "") {
res.body() = "Request malformed: plugin or analyzer query missing\n";
res.result(http::status::bad_request);
return;
}