Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit b07598c8 authored by Alessio Netti's avatar Alessio Netti
Browse files

Data analytics framework merge

parents 0b0635f1 a59764f7
......@@ -15,12 +15,13 @@ include $(DCDBCOREPATH)/common.mk
VERSION = $(shell git describe --long|sed 's/-\([0-9]*\)/.\1/')
CXXFLAGS = -std=c++11 -DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG -DBOOST_NETWORK_ENABLE_HTTPS -O2 -g -Wall -Wno-unused-function -Wno-deprecated-declarations -Wno-unused-variable -DBOOST_LOG_DYN_LINK -I$(DCDBBASEPATH)/dcdb/include -I$(DCDBDEPLOYPATH)/include -I$(DCDBDEPSPATH)/cpp-netlib-0.12.0-final/deps/asio/asio/include -DVERSION=\"$(VERSION)\"
CXXFLAGS = -std=c++11 -DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG -DBOOST_NETWORK_ENABLE_HTTPS -O2 -g -Wall -Wno-unused-function -Wno-unused-local-typedef -Wno-deprecated-declarations -Wno-unused-variable -DBOOST_LOG_DYN_LINK -I$(DCDBBASEPATH)/dcdb/include -I$(DCDBDEPLOYPATH)/include -I$(DCDBDEPSPATH)/cpp-netlib-0.12.0-final/deps/asio/asio/include -DVERSION=\"$(VERSION)\"
LIBS = -L../deps/mosquitto_build/lib -L$(DCDBDEPLOYPATH)/lib/ -ldl -lmosquitto -lboost_system -lboost_thread -lboost_log_setup -lboost_log -lboost_regex -lpthread -lcrypto -lssl -lcppnetlib-server-parsers -lcppnetlib-uri -rdynamic
OBJS = src/dcdbpusher.o src/Configuration.o src/MQTTPusher.o src/HttpsServer.o
OBJS = src/dcdbpusher.o src/Configuration.o src/MQTTPusher.o src/HttpsServer.o src/analytics/AnalyticsManager.o src/analytics/SensorNavigator.o
PLUGINS = procfs pdu sysfs ipmi bacnet snmp gpfsmon tester
ANALYZERS = average
ifeq ($(OS),Darwin)
BACNET_PORT = bsd
LIBEXT = dylib
......@@ -33,30 +34,31 @@ else
PLUGINFLAGS = -fPIC
endif
PLUGIN_LIBS = $(foreach p,$(PLUGINS),libdcdbplugin_$(p).$(LIBEXT))
ANALYZER_LIBS = $(foreach p,$(ANALYZERS),libdcdbanalyzer_$(p).$(LIBEXT))
$(TARGET): $(foreach f,$(DISTFILESPATHS),$(DCDBDEPSPATH)/$(f)/.installed) $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET) $(PLUGIN_LIBS)
all: $(TARGET) $(PLUGIN_LIBS) $(ANALYZER_LIBS)
debug: CXXFLAGS += -DDEBUG
debug: all
clean:
rm -f $(PLUGIN_LIBS) $(TARGET) $(shell find -name "*.o")
rm -f $(PLUGIN_LIBS) $(ANALYZER_LIBS) $(TARGET) $(shell find -name "*.o")
$(DCDBDEPSPATH)/bacnet-stack-$(BACNET-STACK_VERSION)/.installed: $(DCDBDEPSPATH)/bacnet-stack-$(BACNET-STACK_VERSION)/.patched
$(DCDBDEPSPATH)/bacnet-stack-$(BACNET-STACK_VERSION)/.installed: $(DCDBDEPSPATH)/bacnet-stack-$(BACNET-STACK_VERSION)/.patched
@echo ""
@echo "Building BACNet-Stack..."
cd $(@D) && BACNET_PORT=$(BACNET_PORT) MAKE_DEFINE=-fpic make -j $(MAKETHREADS) library && \
install $(DCDBDEPSPATH)/bacnet-stack-$(BACNET-STACK_VERSION)/lib/libbacnet.a /$(DCDBDEPLOYPATH)/lib/ && touch $(@)
$(DCDBDEPSPATH)/freeipmi-$(FREEIPMI_VERSION)/.installed: $(DCDBDEPSPATH)/freeipmi-$(FREEIPMI_VERSION)/.patched
$(DCDBDEPSPATH)/freeipmi-$(FREEIPMI_VERSION)/.installed: $(DCDBDEPSPATH)/freeipmi-$(FREEIPMI_VERSION)/.patched
@echo ""
@echo "Building FreeIPMI library..."
cd $(@D) && ./configure --prefix=$(DCDBDEPLOYPATH) --without-argp
cd $(@D) && make -j $(MAKETHREADS) && make install && touch $(@)
$(DCDBDEPSPATH)/net-snmp-$(NET-SNMP_VERSION)/.installed: $(DCDBDEPSPATH)/net-snmp-$(NET-SNMP_VERSION)/.patched
$(DCDBDEPSPATH)/net-snmp-$(NET-SNMP_VERSION)/.installed: $(DCDBDEPSPATH)/net-snmp-$(NET-SNMP_VERSION)/.patched
@echo ""
@echo "Building net-SNMP library..."
cd $(@D) && ./configure --prefix=$(DCDBDEPLOYPATH) --with-default-snmp-version=3 --with-sys-contact= --with-sys-location= --with-logfile=none --with-persistent-directory=$(DCDBDEPLOYPATH)/var/net-snmp --disable-embedded-perl --disable-perl-cc-checks --without-perl-modules --disable-agent --disable-applications --disable-manuals --disable-scripts --disable-mibs
......@@ -67,16 +69,19 @@ $(OBJS) : %.o : %.cpp
install_lib: $(PLUGIN_LIBS)
install $^ $(DCDBDEPLOYPATH)/lib/
install_conf: $(foreach p,global $(PLUGINS),config/$(p).conf)
install_analyzer: $(ANALYZER_LIBS)
install $^ $(DCDBDEPLOYPATH)/lib/
install_conf: $(foreach p,global $(PLUGINS) $(ANALYZERS),config/$(p).conf)
install -m 644 $^ $(DCDBDEPLOYPATH)/etc/
install: $(TARGET) install_lib
install: $(TARGET) install_lib install_analyzer
install $(TARGET) $(DCDBDEPLOYPATH)/bin/
@echo "Done with installation."
@echo "====================================="
@echo "To copy the configuration files type:"
@echo " > make install_conf"
src/Sensor.o: CXXFLAGS+= $(PLUGINFLAGS)
src/SensorGroup.o: CXXFLAGS+= $(PLUGINFLAGS)
src/sensors/%.o: CXXFLAGS+= $(PLUGINFLAGS) -I$(DCDBDEPSPATH)/bacnet-stack-$(BACNET-STACK_VERSION)/include -I$(DCDBDEPSPATH)/bacnet-stack-$(BACNET-STACK_VERSION)/ports/$(BACNET_PORT)
......@@ -86,28 +91,31 @@ libdcdbplugin_sysfs.$(LIBEXT): src/sensors/sysfs/SysfsSensorGroup.o src/sensors/
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex
libdcdbplugin_perfevent.$(LIBEXT): src/sensors/perfevent/PerfSensorGroup.o src/sensors/perfevent/PerfeventConfigurator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex
libdcdbplugin_ipmi.$(LIBEXT): src/sensors/ipmi/IPMISensorGroup.o src/sensors/ipmi/IPMIHost.o src/sensors/ipmi/IPMIConfigurator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lfreeipmi -lboost_regex
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex -lfreeipmi
libdcdbplugin_pdu.$(LIBEXT): src/sensors/pdu/PDUSensorGroup.o src/sensors/pdu/PDUUnit.o src/sensors/pdu/PDUConfigurator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lcrypto -lssl -lboost_log -lboost_system
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lcrypto -lssl -lboost_log -lboost_regex -lboost_system
libdcdbplugin_bacnet.$(LIBEXT): src/sensors/bacnet/BACnetSensorGroup.o src/sensors/bacnet/BACnetClient.o src/sensors/bacnet/BACnetConfigurator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lbacnet
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex -lbacnet
libdcdbplugin_snmp.$(LIBEXT): src/sensors/snmp/SNMPSensorGroup.o src/sensors/snmp/SNMPConnection.o src/sensors/snmp/SNMPConfigurator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lnetsnmp -lnetsnmpagent
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex -lnetsnmp -lnetsnmpagent
libdcdbplugin_procfs.$(LIBEXT): src/sensors/procfs/ProcfsSensorGroup.o src/sensors/procfs/ProcfsParser.o src/sensors/procfs/ProcfsConfigurator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex
libdcdbplugin_tester.$(LIBEXT): src/sensors/tester/TesterSensorGroup.o src/sensors/tester/TesterConfigurator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex
libdcdbplugin_gpfsmon.$(LIBEXT): src/sensors/gpfsmon/GpfsmonSensorGroup.o src/sensors/gpfsmon/GpfsmonConfigurator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex
#libdcdbplugin_opa.$(LIBEXT): src/sensors/opa/OpaSensorGroup.o src/sensors/opa/OpaConfigurator.o
# $(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lopamgt -libverbs -libumad -lssl
# $(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex -lopamgt -libverbs -libumad -lssl
libdcdbanalyzer_average.$(LIBEXT): src/analytics/analyzers/average/AverageAnalyzer.o src/analytics/analyzers/average/AverageConfigurator.o src/analytics/SensorNavigator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex
global {
mqttPrefix /FF112233445566778899AAB
}
template_average def1 {
interval 1000
minValues 3
mqttPart FF0
duplicate false
streaming true
}
average avg1 {
default def1
mqttPart FF0
mqttStart 00
input {
sensor "<unit>col_user"
sensor "<unit-1>MemFree"
}
output {
sensor "<unit, filter cpu250>sum" {
mqttsuffix 76
}
sensor "<unit, filter cpu250>max" {
mqttsuffix 77
}
sensor "<unit, filter cpu250>avg" {
mqttsuffix 78
}
}
}
average avg2 {
default def1
interval 1500
mqttPart FF1
mqttStart 00
input {
sensor "<unit>col_user"
sensor "<unit - 1>MemFree"
}
output {
sensor "<unit - 1>sum" {
mqttsuffix 76
}
sensor "<unit - 1>max" {
mqttsuffix 77
}
sensor "<unit - 1>avg" {
mqttsuffix 78
}
}
}
average avg3 {
default def1
interval 1500
mqttPart FF2
mqttStart 00
input {
all-recursive
}
output {
sensor "<unit - 1>sumall" {
mqttsuffix 80
}
sensor "<unit - 1>maxall" {
mqttsuffix 81
}
sensor "<unit - 1>avgall" {
mqttsuffix 82
}
}
}
......@@ -59,3 +59,7 @@ plugins {
}
}
analyzerPlugins {
}
......@@ -26,6 +26,7 @@ Configuration::Configuration(const std::string& cfgFilePath) :
//set default values for global variables
_global.qosLevel = 1;
_global.daemonize = 0;
_global.hierarchy = "";
_global.brokerHost = "";
_global.brokerPort = 1883;
_global.threads = 1;
......@@ -84,6 +85,8 @@ bool Configuration::readGlobal() {
}
} else if (boost::iequals(global.first, "sensorpattern")) {
_global.pluginSettings.sensorPattern = global.second.data();
} else if (boost::iequals(global.first, "hierarchy")) {
_global.hierarchy = global.second.data();
} else if (boost::iequals(global.first, "tempdir")) {
_global.pluginSettings.tempdir = global.second.data();
if (_global.pluginSettings.tempdir[_global.pluginSettings.tempdir.length()-1] != '/') {
......@@ -340,7 +343,7 @@ bool Configuration::checkMqtt(const std::string& mqtt) {
return false;
}
auto returnIt = _mqttTopics.insert(mqtt);
auto returnIt = _mqttTopics.insert(str);
if (!returnIt.second) {
LOG(error) << "MQTT-Topic \"" << mqtt << "\" used twice!";
return false;
......
......@@ -15,18 +15,19 @@
#include <boost/log/trivial.hpp>
#include "includes/PluginDefinitions.h"
typedef struct {
int daemonize;
int brokerPort;
int qosLevel;
std::string brokerHost;
uint32_t threads;
unsigned int maxMsgNum;
boost::log::trivial::severity_level logLevelFile;
boost::log::trivial::severity_level logLevelCmd;
pluginSettings_t pluginSettings;
restAPISettings_t restAPISettings;
} global_t;
typedef struct {
int daemonize;
int brokerPort;
int qosLevel;
std::string brokerHost;
std::string hierarchy;
uint32_t threads;
unsigned int maxMsgNum;
boost::log::trivial::severity_level logLevelFile;
boost::log::trivial::severity_level logLevelCmd;
pluginSettings_t pluginSettings;
restAPISettings_t restAPISettings;
} global_t;
/**
* Class responsible of reading the global configuration as well as loading and invoking required dynamic libraries.
......@@ -84,7 +85,7 @@ public:
* @return The boost::log severity level
*/
boost::log::trivial::severity_level translateLogLevel(int logLevel);
/**
* Check if the mqtt-suffix is already in use.
* @param mqtt The MQTT-suffix to check
......
......@@ -14,7 +14,7 @@
#include <string>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string/split.hpp>
#define LOGH(sev) LOG(sev) << "HttpsServer: "
......@@ -104,22 +104,25 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
if (method == "GET") {
if (pathStrs[0] == "help") {
response = "dcdbpusher RESTful API cheatsheet:\n"
" -GET: /help This help message\n"
" /plugins List of currently loaded plugins (Discovery)\n"
" /[plugin]/sensors\n"
" List of currently running sensors which belong\n"
" to the specified plugin (Discovery)\n"
" /[plugin]/[sensor]/avg?interval=[timeInSec]\n"
" Average of last sensor readings from the last\n"
" [interval] seconds or of all cached readings\n"
" if no interval is given\n"
" -PUT: /[plugin]/[start|stop|reload]\n"
" Start/stop the sensors of the plugin or\n"
" reload the plugin configuration\n"
"\n"
"All resources have to be prepended by host:port and need at\n"
"least the query ?authkey=[token] at the end. Multiple queries\n"
"need to be separated by semicolons(';')\n";
" -GET: /help This help message\n"
" /analytics/help\n"
" An help message for data analytics commands\n"
" /plugins List of currently loaded plugins (Discovery)\n"
" /[plugin]/sensors\n"
" List of currently running sensors which belong\n"
" to the specified plugin (Discovery)\n"
" /[plugin]/[sensor]/avg?interval=[timeInSec]\n"
" Average of last sensor readings from the last\n"
" [interval] seconds or of all cached readings\n"
" if no interval is given\n"
" -PUT: /[plugin]/[start|stop|reload]\n"
" Start/stop the sensors of the plugin or\n"
" reload the plugin configuration\n"
"\n";
//"All resources have to be prepended by host:port and need at\n"
//"least the query ?authkey=[token] at the end. Multiple queries\n"
//"need to be separated by semicolons(';')\n";
response += _httpsServer._manager->restCheatSheet;
} else {
//first check permission
if (!_httpsServer.check_authkey(auth_value, permission::GETReq)) {
......@@ -127,15 +130,33 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
connection->set_status(server::connection::unauthorized);
goto error;
}
if (pathStrs[0] == "plugins") {
//Managing REST GET commands to the data analytics framework
if(pathStrs[0] == "analytics") {
try {
restResponse_t reply = _httpsServer._manager->REST(pathStrs, queries, method, _httpsServer._io);
data << reply.data;
response = reply.response;
} catch(const std::invalid_argument &e) {
LOGH(warning) << e.what();
connection->set_status(server::connection::bad_request);
goto error;
} catch(const std::domain_error &e) {
response = e.what();
connection->set_status(server::connection::not_found);
} catch(const std::exception &e) {
LOGH(warning) << e.what();
connection->set_status(server::connection::internal_server_error);
goto error;
}
} else if (pathStrs[0] == "plugins") {
if (json) {
boost::property_tree::ptree root, plugins;
for(auto& p : _httpsServer._plugins) {
plugins.put(p.id, "");
}
root.add_child("plugins", plugins);
boost::property_tree::write_info(data, root);
boost::property_tree::write_json(data, root, true);
} else {
for(auto& p : _httpsServer._plugins) {
data << p.id << "\n";
......@@ -148,16 +169,16 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
connection->set_status(server::connection::bad_request);
goto error;
}
if (pathStrs[1] == "sensors") {
response = "Plugin not found!";
connection->set_status(server::connection::not_found);
for(auto& p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
if (json) {
boost::property_tree::ptree root, sensors;
for(auto g : p.configurator->getSensorGroups()) {
boost::property_tree::ptree group;
for(auto s : g->getSensors()) {
......@@ -166,7 +187,7 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
sensors.add_child(g->getGroupName(), group);
}
root.add_child(p.id, sensors);
boost::property_tree::write_info(data, root);
boost::property_tree::write_json(data, root, true);
} else {
for(auto g : p.configurator->getSensorGroups()) {
for(auto s : g->getSensors()) {
......@@ -180,23 +201,23 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
}
}
} else {
if (pathStrs.size() < 3) {
LOGH(warning) << "Received malformed request: No third path part";
connection->set_status(server::connection::bad_request);
goto error;
}
if (pathStrs[2] != "avg") {
LOGH(warning) << "Unknown action " << pathStrs[2] << " requested";
connection->set_status(server::connection::not_supported);
goto error;
}
std::string sensor = pathStrs[1];
std::string action = pathStrs[2];
uint64_t time = 0;
for (auto& p : queries) {
if (p.first == "interval") {
time = getTimestamp();
......@@ -205,15 +226,17 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
}
//process actual request
bool found = false;
response = "Plugin not found!";
connection->set_status(server::connection::not_found);
for(auto& p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
response = "Sensor not found!";
for(const auto& g : p.configurator->getSensorGroups()) {
for(const auto& s : g->getSensors()) {
if (s->getName() == sensor) {
found = true;
response = pathStrs[0] + "::" + sensor + _httpsServer.calcAvg(*s, time);
connection->set_status(server::connection::ok);
break;
......@@ -222,86 +245,145 @@ void HttpsServer::requestHandler::operator()(server::request const &request, ser
}
}
}
if(!found) {
for(auto& p : _httpsServer._manager->getPlugins())
if (p.id == pathStrs[0]) {
response = "Sensor not found!";
for(const auto& a : p.configurator->getAnalyzers())
if(a->getStreaming())
for(const auto& u : a->getUnits())
for (const auto& s : u->getBaseOutputs())
if (s->getName() == sensor) {
found = true;
response = pathStrs[0] + "::" + sensor + _httpsServer.calcAvg(*s, time);
connection->set_status(server::connection::ok);
break;
}
}
}
}
}
}
} else if (method == "PUT") {
//first check permission
if (!_httpsServer.check_authkey(auth_value, permission::PUTReq)) {
LOGH(warning) << "Provided authentication token has insufficient permissions";
connection->set_status(server::connection::unauthorized);
goto error;
}
if (pathStrs.size() < 2) {
LOGH(warning) << "Received malformed request: No second path part";
connection->set_status(server::connection::bad_request);
goto error;
}
std::string action = pathStrs[1];
//process actual request
response = "Plugin not found!";
connection->set_status(server::connection::not_found);
//switch code depending on selected action
if (action == "start") {
for(auto& p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
for(const auto& g : p.configurator->getSensorGroups()) {
g->start();
}
response = "Plugin " + pathStrs[0] + ": Sensors started";
connection->set_status(server::connection::ok);
break;
}
//Managing REST PUT commands to the data analytics framework
if(pathStrs[0] == "analytics") {
if( pathStrs.back() == "reload" ) {
_httpsServer._mqttPusher->halt();
// Wait until MQTTPusher is paused in order to reload plugins
while (!_httpsServer._mqttPusher->isHalted()) { sleep(1); }
}
} else if (action == "stop") {
for(auto& p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
for(const auto& g : p.configurator->getSensorGroups()) {
g->stop();
}
response = "Plugin " + pathStrs[0] + ": Sensors stopped";
connection->set_status(server::connection::ok);
break;
}
try {
restResponse_t reply = _httpsServer._manager->REST(pathStrs, queries, method, _httpsServer._io);
data << reply.data;
response = reply.response;
} catch(const std::invalid_argument &e) {
LOGH(warning) << e.what();
connection->set_status(server::connection::bad_request);
goto error;
} catch(const std::domain_error &e) {
response = e.what();
connection->set_status(server::connection::not_found);
} catch(const std::exception &e) {
response = e.what();
connection->set_status(server::connection::internal_server_error);
}
} else if (action == "reload") {
for(auto& p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
//before modifying the plugin we need to ensure that we have exclusive access
//therefore pause the only other concurrent user (MQTTPusher)
_httpsServer._mqttPusher->halt();
//wait until MQTTPusher is paused
while (!_httpsServer._mqttPusher->isHalted()) {
sleep(1);
// Continue MQTTPusher when a reload was performed
if( pathStrs.back() == "reload" )
_httpsServer._mqttPusher->cont();
} else {
if (pathStrs.size() < 2) {
LOGH(warning) << "Received malformed request: No second path part";
connection->set_status(server::connection::bad_request);
goto error;
}
std::string action = pathStrs[1];
//process actual request
response = "Plugin not found!";
connection->set_status(server::connection::not_found);
//switch code depending on selected action
if (action == "start") {
for (auto &p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
for (const auto &g : p.configurator->getSensorGroups()) {
g->start();
}
response = "Plugin " + pathStrs[0] + ": Sensors started";
connection->set_status(server::connection::ok);
break;
}
if (p.configurator->reReadConfig()) {
response = "Plugin " + pathStrs[0] + ": Configuration reloaded";
}
} else if (action == "stop") {
for (auto &p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
for (const auto &g : p.configurator->getSensorGroups()) {
g->stop();
}
response = "Plugin " + pathStrs[0] + ": Sensors stopped";
connection->set_status(server::connection::ok);
} else {
response = "Plugin " + pathStrs[0] + ": Could not reload configuration";
connection->set_status(server::connection::internal_server_error);
break;
}
}
} else if (action == "reload") {
for (auto &p : _httpsServer._plugins) {
if (p.id == pathStrs[0]) {
//before modifying the plugin we need to ensure that we have exclusive access
//therefore pause the only other concurrent user (MQTTPusher)
_httpsServer._mqttPusher->halt();
//wait until MQTTPusher is paused
while (!_httpsServer._mqttPusher->isHalted()) {
sleep(1);
}
if (p.configurator->reReadConfig()) {
response = "Plugin " + pathStrs[0] + ": Configuration reloaded";