Commit 331b92ee authored by Micha Mueller's avatar Micha Mueller
Browse files

Implement first draft of PDU-Reader (XML)

Remaining TODOs:
network logic to obtain XML-file
use appropriate lock when sensor accesses PDUUnit
make reading XML more generic?
Test it!
parent 3b257c4d
......@@ -12,7 +12,12 @@ plugins {
config
}
plugin perfevent {
; plugin perfevent {
; path ./
; config
; }
plugin pdu {
path ./
config
}
......
......@@ -12,15 +12,14 @@ SensorTemplate {
pdus {
pdu rack1 {
networkAddress ?
cooldown 500 //Time interval at which the energy.xml is refreshed. If empty use smallest sensor-interval
mqttprefix ? //give every pdu own prefix (like IPMI-hosts)?
; networkAddress ?
cooldown 500 ;Time interval at which the energy.xml is refreshed. If empty use smallest sensor-interval
total {
interval 500
mqttsuffix 0000
minValues 1
}
; total {
; interval 500
; mqttsuffix 0000
; minValues 1
; }
sensors {
sensor pcs1 {
......@@ -45,6 +44,6 @@ pdus {
}
pdu rack2 {
....
; ....
}
}
......@@ -37,3 +37,7 @@ libs:
# $(CXX) $(LIBFLAGS) sensors/ipmi/IPMIHost.cpp
# $(CXX) $(LIBFLAGS) sensors/ipmi/IPMIConfigurator.cpp
# $(CXX) -shared -Wl,-soname,libdcdbplugin_ipmi.so.1 -o libdcdbplugin_ipmi.so.1.0 IPMISensor.o IPMIHost.o IPMIConfigurator.o
$(CXX) $(LIBFLAGS) sensors/pdu/PDUSensor.cpp
$(CXX) $(LIBFLAGS) sensors/pdu/PDUUnit.cpp
$(CXX) $(LIBFLAGS) sensors/pdu/PDUConfigurator.cpp
$(CXX) -shared -Wl,-soname,libdcdbplugin_pdu.so.1 -o libdcdbplugin_pdu.so.1.0 PDUSensor.o PDUUnit.o PDUConfigurator.o
......@@ -7,10 +7,14 @@
#include "PDUConfigurator.h"
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/algorithm/string.hpp>
using namespace std;
PDUConfigurator::PDUConfigurator() {
// TODO Auto-generated constructor stub
......@@ -23,10 +27,117 @@ PDUConfigurator::~PDUConfigurator() {
}
std::vector<Sensor*>& PDUConfigurator::readConfig(std::string cfgPath) {
//read template counters
boost::property_tree::iptree cfg;
boost::property_tree::read_info(cfgPath, cfg);
//read global variables (if present overwrite those from global.conf)
//currently only overwriting of mqttPrefix is supported
boost::optional<boost::property_tree::iptree&> globalVals = cfg.get_child_optional("global");
if (globalVals) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &global, cfg.get_child("global")) {
if(boost::iequals(global.first, "mqttprefix")) {
_mqttPrefix = global.second.data();
if (_mqttPrefix[_mqttPrefix.length()-1] != '/') {
_mqttPrefix.append("/");
}
cout << " Using own MQTT-Prefix " << _mqttPrefix << endl;
} else {
cout << " Value \"" << global.first << "\" not recognized. Omitting..." << endl;
}
}
}
//read template sensors
BOOST_FOREACH(boost::property_tree::iptree::value_type &sensor, cfg.get_child("SensorTemplate")) {
if (boost::iequals(sensor.first, "sensor")) {
cout << "Template Sensor \"" << sensor.second.data() << "\"" << endl;
if (!sensor.second.empty()) {
PDUSensor pduSensor(sensor.second.data());
if(readSensor(pduSensor, sensor.second)) {
_templateSensors.insert(sensorMap_t::value_type(pduSensor.getName(), pduSensor));
} else {
cout << "Template sensor \"" << sensor.second.data() << "\" has bad values! Ignoring..." << endl;
}
}
}
}
//read one pdu at a time
BOOST_FOREACH(boost::property_tree::iptree::value_type &pdu, cfg.get_child("pdus")) {
if (boost::iequals(pdu.first, "pdu")) {
cout << "PDU \"" << pdu.second.data() << "\"" << endl;
if (!pdu.second.empty()) {
//create PDU at end of list
_pdus.push_back(PDUUnit());
PDUUnit& pduUnit = _pdus.back();
//read PDU-values
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, pdu.second) {
if (boost::iequals(val.first, "cooldown")) {
pduUnit.setCooldown(stoull(val.second.data()));
} else if (boost::iequals(val.first, "sensors")) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &sensor, val.second) {
cout << "sensor \"" << sensor.second.data() << "\"" << endl;
if (!sensor.second.empty()) {
PDUSensor pduSensor(sensor.second.data());
//first check if default sensor is given
boost::optional<boost::property_tree::iptree&> defaultC = sensor.second.get_child_optional("default");
if(defaultC) {
cout << " Using \"" << defaultC.get().data() << "\" as default." << endl;
sensorMap_t::iterator it = _templateSensors.find(defaultC.get().data());
if(it != _templateSensors.end()) {
pduSensor = it->second;
pduSensor.setName(sensor.second.data());
} else {
cout << " Template sensor \"" << defaultC.get().data() << "\" not found! Using standard values." << endl;
}
}
//read remaining values
if(readSensor(pduSensor, sensor.second)) {
//set pointer to corresponding pdu
pduSensor.setPdu(&pduUnit);
_sensors.push_back(&pduSensor);
} else {
cout << " Counter \"" << sensor.second.data() << "\" has bad values! Ignoring..." << endl;
}
}
}
}
}
}
}
}
return _sensors;
}
bool PDUConfigurator::readSensor(PDUSensor& sensor, boost::property_tree::iptree& config) {
return 0;
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
if (boost::iequals(val.first, "interval")) {
sensor.setInterval(stoull(val.second.data()));
} else if (boost::iequals(val.first, "mqttsuffix")) {
sensor.setMqtt(_mqttPrefix + val.second.data());
} else if (boost::iequals(val.first, "minValues")) {
sensor.setMinValues(stoull(val.second.data()));
} else if (boost::iequals(val.first, "clustsafeID")) {
sensor.setClustsafeID(stoull(val.second.data()));
} else if (boost::iequals(val.first, "outletID")) {
sensor.setOutletID(stoull(val.second.data()));
} else if (boost::iequals(val.first, "default")) {
//avoid unnecessary "Value not recognized" message
} else {
cout << " Value \"" << val.first << "\" not recognized. Omitting..." << endl;
}
}
cout << " MQTT : " << sensor.getMqtt() << endl;
cout << " Interval : " << sensor.getInterval() << endl;
cout << " minValues: " << sensor.getMinValues() << endl;
cout << " ClustID : " << sensor.getClustsafeID() << endl;
cout << " OutletID : " << sensor.getOutletID() << endl;
return true;
}
......@@ -5,11 +5,13 @@
* Author: Micha Mueller
*/
#include "PDUSensor.h"
#include "../../Configurator.h"
#include "PDUSensor.h"
#include "PDUUnit.h"
#include <string>
#include <vector>
#include <map>
#include <list>
#include <boost/property_tree/ptree.hpp>
#ifndef SRC_SENSORS_PDU_PDUCONFIGURATOR_H_
......@@ -18,6 +20,7 @@
class PDUConfigurator: public Configurator {
typedef std::map<std::string, PDUSensor> sensorMap_t;
typedef std::list<PDUUnit> pduList_t;
public:
......@@ -41,6 +44,7 @@ private:
std::vector<Sensor*> _sensors;
sensorMap_t _templateSensors;
pduList_t _pdus;
};
extern "C" Configurator* create() {
......
......@@ -7,12 +7,18 @@
#include "PDUSensor.h"
#include "timestamp.h"
#include <string>
//#include <functional>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>
extern volatile int keepRunning;
PDUSensor::PDUSensor(const std::string& name) :
Sensor(name) {
_clustsafeID = 0;
_outletID = 0;
_pdu = NULL;
}
PDUSensor::~PDUSensor() {
......@@ -20,7 +26,28 @@ PDUSensor::~PDUSensor() {
}
void PDUSensor::read() {
//TODO
reading_t reading;
reading.timestamp = getTimestamp();
boost::property_tree::ptree tree = _pdu->getPTree();
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, tree.get_child("clustsafeResponse.energy")) {
if (v.first == "clustsafe") {
int csId = stoi(v.second.get_child("<xmlattr>.id").data());
if (csId == _clustsafeID) {
BOOST_FOREACH(boost::property_tree::ptree::value_type &o, v.second.get_child("outlets")) {
int outId = stoi(o.second.get_child("<xmlattr>.id").data());
if (outId == _outletID) {
reading.value = stoul(o.second.data());
_readingQueue->push(reading);
_latestValue.value = reading.value;
_latestValue.timestamp = reading.timestamp;
return;
}
}
}
}
}
}
void PDUSensor::readAsync() {
......
......@@ -9,6 +9,7 @@
#define SRC_SENSORS_PDU_PDUSENSOR_H_
#include "../../Sensor.h"
#include "PDUUnit.h"
class PDUSensor: public Sensor {
......@@ -16,6 +17,14 @@ public:
PDUSensor(const std::string& name);
virtual ~PDUSensor();
void setPdu(PDUUnit* pdu) {
_pdu = pdu;
}
PDUUnit* getPdu() const {
return _pdu;
}
void setClustsafeID(unsigned clustsafeID) {
_clustsafeID = clustsafeID;
}
......@@ -37,6 +46,8 @@ public:
void startPolling(boost::asio::io_service& io);
private:
PDUUnit* _pdu;
unsigned int _clustsafeID;
unsigned int _outletID;
};
......
/*
* PDUUnit.cpp
*
* Created on: 26.02.2018
* Author: Micha Mueller
*/
#include "PDUUnit.h"
#include "timestamp.h"
#include <boost/property_tree/xml_parser.hpp>
PDUUnit::PDUUnit() {
_cooldown = 1000;
_lastRefresh = 0;
}
PDUUnit::~PDUUnit() {
// TODO Auto-generated destructor stub
}
boost::property_tree::ptree& PDUUnit::getPTree() {
//TODO use appropriate lock
uint64_t now = getTimestamp();
if (now >= _lastRefresh + _cooldown) {
std::string file = refresh();
boost::property_tree::read_xml(file, _ptree);
_lastRefresh = now;
}
return _ptree;
}
std::string PDUUnit::refresh() {
//TODO
return "/home/micha/LRZ/energy.xml";
}
/*
* PDUUnit.h
*
* Created on: 26.02.2018
* Author: Micha Mueller
*/
#ifndef SRC_SENSORS_PDU_PDUUNIT_H_
#define SRC_SENSORS_PDU_PDUUNIT_H_
#include <boost/property_tree/ptree.hpp>
class PDUUnit {
public:
PDUUnit();
virtual ~PDUUnit();
void setCooldown(unsigned cooldown) {
_cooldown = cooldown;
}
unsigned getCooldown() const {
return _cooldown;
}
/**
* Return _ptree which holds the current data from the XML-sensor file.
* Checks if _ptree is still up to date.
* If not: calls refresh() and overwrites _ptree with a current version.
*
* @return A boost property tree which represents the XML-sensor file
*/
boost::property_tree::ptree& getPTree();
private:
/**
* Gets a current version of the XML-file with sensor data.
*
* @return Filename referencing the refreshed XML-file
*/
std::string refresh();
uint64_t _lastRefresh;
unsigned int _cooldown;
boost::property_tree::ptree _ptree;
};
#endif /* SRC_SENSORS_PDU_PDUUNIT_H_ */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment