Commit f096313b authored by Micha Mueller's avatar Micha Mueller
Browse files

Adapt IPMI plugin to sensorgroupsV2 architecture

parent c976d362
......@@ -2,14 +2,15 @@ global {
cacheInterval 60
sessiontimeout 500
retransmissiontimeout 200
mqttprefix /AABBAABBAABBAACCDDCCDDCC
mqttprefix ;empty MqttPrefix, because mqttPart of host is used as full prefix
}
sensorTemplates {
template_group energy {
interval 1000
sensor energy {
; type raw
factor 0.001
interval 1000
cmd "0x00 0x2e 0x81 0x4d 0x4f 0x00 0x00 0x01 0x82 0x00 0x08"
start 5
stop 12
......@@ -17,26 +18,25 @@ sensorTemplates {
}
}
hosts {
host localhost {
username "USERID"
password "PASSW0RD"
mqttprefix "/00/11/2233445566/778899AABB"
sensors {
sensor energySens {
default energy
MQTTsuffix 11223344
}
sensor recordSens {
recordId 4321
factor 1000
mqttsuffix 11223345
}
host localhost {
username "USERID"
password "PASSW0RD"
mqttPart "/00/11/2233445566/778899AABB"
group g1 {
default energy
}
group g2 {
sensor recordSens {
recordId 4321
factor 1000
mqttsuffix 11223345
}
}
; host test {
; username "USERID"
; password "PASSWORD"
; }
}
;host test {
; username "USERID"
; password "PASSWORD"
;}
......@@ -379,8 +379,8 @@ protected:
_cacheInterval *= 1000;
}
}
global(config.get_child("global"));
}
global(config);
return true;
}
......
......@@ -10,120 +10,66 @@
#include <boost/optional.hpp>
#include <iostream>
namespace DCDB {
IPMIConfigurator::IPMIConfigurator() {
_globalHost.sessionTimeout = 0;
_globalHost.retransmissionTimeout = 0;
_entityName = "host";
_groupName = "group";
_baseName = "sensor";
}
IPMIConfigurator::~IPMIConfigurator() {}
bool IPMIConfigurator::derivedReadConfig(boost::property_tree::iptree& cfg) {
//read global variables (if present overwrite those from global.conf)
BOOST_FOREACH(boost::property_tree::iptree::value_type &global, cfg.get_child("global")) {
if (STRCMP(global, "SessionTimeout")) {
_globalHost.sessionTimeout = stoi(global.second.data());
LOG(debug)<< " SessionTimeout " << _globalHost.sessionTimeout;
} else if (STRCMP(global, "RetransmissionTimeout")) {
_globalHost.retransmissionTimeout = stoi(global.second.data());
LOG(debug) << " RetransmissionTimeout " << _globalHost.retransmissionTimeout;
}
/* Overwritten from ConfiguratorTemplate */
void IPMIConfigurator::sensorBase(IPMISensorBase& s, CFG_VAL config) {
ADD {
ATTRIBUTE("cmd", setRawCmd);
ATTRIBUTE("start", setStart);
ATTRIBUTE("stop", setStop);
ATTRIBUTE("recordId", setRecordId);
ATTRIBUTE("factor", setFactor);
}
}
BOOST_FOREACH(boost::property_tree::iptree::value_type &host, cfg.get_child("hosts")) {
if (STRCMP(host, "host")) {
LOG(debug)<< "Host " << host.second.data();
_hosts.push_back(DCDB::IPMIHost(host.second.data(), _globalHost.retransmissionTimeout, _globalHost.sessionTimeout));
DCDB::IPMIHost &ipmiHost = _hosts.back();
ipmiHost.setMqttPrefix(_mqttPrefix);
ipmiHost.setCache(_tempdir);
if (!host.second.empty()) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &h, host.second) {
if (STRCMP(h, "username")) {
ipmiHost.setUserName(h.second.data());
LOG(debug) << " Username " << ipmiHost.getUserName();
} else if (STRCMP(h, "password")) {
ipmiHost.setPassword(h.second.data());
LOG(debug) << " Password " << ipmiHost.getPassword();
} else if (STRCMP(h, "mqttprefix")) {
ipmiHost.setMqttPrefix(h.second.data());
LOG(debug) << " MQTTPrefix " << ipmiHost.getMqttPrefix();
} else if (STRCMP(h, "sensors")) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &sensor, h.second) {
LOG(debug) << "Sensor \"" << sensor.second.data() << "\"";
if (!sensor.second.empty()) {
std::string name = host.second.data() + "_" + sensor.second.data();
DCDB::IPMISingleSensor* ipmiSensor = new DCDB::IPMISingleSensor(name);
//first check if default sensor is given
boost::optional<boost::property_tree::iptree&> defaultC = sensor.second.get_child_optional("default");
if(defaultC) {
LOG(debug) << " Using \"" << defaultC.get().data() << "\" as default.";
sensorMap_t::iterator it = _templateSensors.find(defaultC.get().data());
if(it != _templateSensors.end()) {
*ipmiSensor = it->second;
ipmiSensor->setName(name);
} else {
LOG(warning) << " Template sensor \"" << defaultC.get().data() << "\" not found! Using standard values.";
}
}
//set pointer to corresponding host
ipmiSensor->setHost(&ipmiHost);
//read remaining values
if(readSensorBase(*ipmiSensor, sensor.second)) {
_sensors.push_back(ipmiSensor);
} else {
LOG(warning) << " Sensor \"" << sensor.second.data() << "\" has bad values! Ignoring..." << std::endl;
}
}
}
}
}
}
}
void IPMIConfigurator::sensorGroup(IPMISensorGroup& s, CFG_VAL config) {
ADD {
//no group attributes currently
}
return true;
}
bool IPMIConfigurator::derivedReadSensorBase(IPMISensorBase& sensor, boost::property_tree::iptree& config) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
if (STRCMP(val, "mqttsuffix")) {
if (sensor.getHost() != NULL) {
// only workaround so that every host can define own prefix
// not guaranteed, but should actually work as long as prefix is defined before the sensors within a host
if (sensor.getHost()->getMqttPrefix() != "") {
sensor.setMqtt(sensor.getHost()->getMqttPrefix() + val.second.data());
}
} else {
sensor.setMqtt(_mqttPrefix + val.second.data());
}
} else if (STRCMP(val, "cmd")) {
sensor.setRawCmd(val.second.data());
} else if (STRCMP(val, "start")) {
sensor.setStart(stoi(val.second.data()));
} else if (STRCMP(val, "stop")) {
sensor.setStop(stoi(val.second.data()));
} else if (STRCMP(val, "recordId")) {
sensor.setRecordId(stoul(val.second.data()));
} else if (STRCMP(val, "factor")) {
sensor.setFactor(std::stod(val.second.data()));
}
void IPMIConfigurator::sensorEntity(IPMIHost& s, CFG_VAL config) {
s.setHostName(config.data());
s.setSessionTimeout(_globalHost.sessionTimeout);
s.setRetransmissionTimeout(_globalHost.retransmissionTimeout);
s.setCache(_tempdir);
ADD {
ATTRIBUTE("username", setUserName);
ATTRIBUTE("password", setPassword);
ATTRIBUTE("mqttPart", setMqttPart);
}
}
LOG(debug) << " MQTT : " << sensor.getMqtt();
LOG(debug) << " factor : " << sensor.getFactor();
if (sensor.getRecordId() != 0) {
LOG(debug) << " RecordID : " << sensor.getRecordId();
} else {
LOG(debug) << " Using raw command";
LOG(debug) << " Start : " << unsigned(sensor.getStart());
LOG(debug) << " Stop : " << unsigned(sensor.getStop());
}
return true;
bool IPMIConfigurator::isEntityOfGroup(IPMIHost& e, IPMISensorGroup& g) {
return (g.getHost() == &e);
}
void IPMIConfigurator::setEntityForGroup(IPMIHost& e, IPMISensorGroup& g) {
g.setHost(&e);
}
void IPMIConfigurator::finalizeGroup(IPMISensorGroup& g) {
g.setMqttPart(g.getHost()->getMqttPart() + g.getMqttPart());
}
void IPMIConfigurator::global(CFG_VAL config) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &global, config) {
if (boost::iequals(global.first, "SessionTimeout")) {
_globalHost.sessionTimeout = stoi(global.second.data());
LOG(debug)<< " SessionTimeout " << _globalHost.sessionTimeout;
} else if (boost::iequals(global.first, "RetransmissionTimeout")) {
_globalHost.retransmissionTimeout = stoi(global.second.data());
LOG(debug) << " RetransmissionTimeout " << _globalHost.retransmissionTimeout;
}
}
}
/* namespace DCDB */
......@@ -8,18 +8,13 @@
#ifndef IPMICONFIGURATOR_H_
#define IPMICONFIGURATOR_H_
#include "IPMIHost.h"
#include <list>
#include "../../includes/ConfiguratorTemplate.h"
#include "IPMISingleSensor.h"
namespace DCDB {
#include "IPMIHost.h"
#include "IPMISensorGroup.h"
class IPMIConfigurator: public ConfiguratorTemplate<IPMISensorBase, DCDB::IPMISingleSensor> {
class IPMIConfigurator: public ConfiguratorTemplate<IPMISensorBase, IPMISensorGroup, IPMIHost> {
typedef std::list<DCDB::IPMIHost> hostList_t;
typedef struct {
uint32_t sessionTimeout;
uint32_t retransmissionTimeout;
......@@ -30,21 +25,26 @@ public:
virtual ~IPMIConfigurator();
protected:
bool derivedReadConfig(boost::property_tree::iptree& cfg) override;
void derivedReReadConfig() override { _hosts.clear(); }
/* Overwritten from ConfiguratorTemplate */
void sensorBase(IPMISensorBase& s, CFG_VAL config) override;
void sensorGroup(IPMISensorGroup& s, CFG_VAL config) override;
void sensorEntity(IPMIHost& s, CFG_VAL config) override;
bool isEntityOfGroup(IPMIHost& e, IPMISensorGroup& g) override;
void setEntityForGroup(IPMIHost& e, IPMISensorGroup& g) override;
void finalizeGroup(IPMISensorGroup& g) override;
void global(CFG_VAL config) override;
void derivedSetGlobalSettings(const pluginSettings_t& pluginSettings) override { _tempdir = pluginSettings.tempdir; }
bool derivedReadSensorBase(IPMISensorBase& sensor, boost::property_tree::iptree& config) override;
private:
std::string _tempdir;
hostList_t _hosts;
globalHost_t _globalHost;
};
} /* namespace DCDB */
extern "C" ConfiguratorInterface* create() {
return new DCDB::IPMIConfigurator;
return new IPMIConfigurator;
}
extern "C" void destroy(ConfiguratorInterface* c) {
......
/*
* IPMIConnection.cpp
* IPMIHost.cpp
*
* Created on: 18 Jan 2017
* Author: ottmi
......@@ -21,22 +21,20 @@
#include <freeipmi/freeipmi.h>
#include <freeipmi/api/ipmi-api.h>
namespace DCDB {
IPMIHost::IPMIHost(const std::string& hostName, uint32_t retransmissionTimeout, uint32_t sessionTimeout) {
_ipmiCtx = NULL;
_sdrCtx = NULL;
_sensorReadCtx = NULL;
_hostName = hostName;
IPMIHost::IPMIHost() {
_ipmiCtx = nullptr;
_sdrCtx = nullptr;
_sensorReadCtx = nullptr;
_hostName = "";
_userName = std::string("admin");
_password = std::string("admin");
_cache = "";
_auth = IPMI_AUTHENTICATION_TYPE_MD5;
_priv = IPMI_PRIVILEGE_LEVEL_ADMIN;
_mqttPrefix = "";
_retransmissionTimeout = retransmissionTimeout;
_sessionTimeout = sessionTimeout;
_strand = NULL;
_mqttPart = "";
_retransmissionTimeout = 0;
_sessionTimeout = 0;
_strand = nullptr;
_errorCount = 0;
_delayNextReadUntil = 0;
}
......@@ -239,4 +237,3 @@ void IPMIHost::initializeStrand(boost::asio::io_service& io) {
_strand = new boost::asio::io_service::strand(io);
}
}
} /* namespace DCDB */
/*
* IPMIConnection.h
* IPMIHost.h
*
* Created on: 18 Jan 2017
* Author: ottmi
......@@ -14,126 +14,76 @@
#include <boost/asio.hpp>
#include "../../includes/Logging.h"
namespace DCDB {
class IPMIHost {
public:
IPMIHost(const std::string& hostName, uint32_t retransmissionTimeout, uint32_t sessionTimeout);
virtual ~IPMIHost();
/* Send raw command to BMC. Returns sensor reading as responded by BMC. */
uint64_t sendRawCmd(const std::vector<uint8_t>& rawCmd, uint16_t start, uint16_t stop);
/* Read the sensor specified by its record id. Returns sensor reading. */
double readSensor_recordId(uint16_t recordId);
void increaseErrorCount();
const uint64_t getDelayFactor() const;
uint8_t getAuth() const {
return _auth;
}
void setAuth(uint8_t auth) {
_auth = auth;
}
const std::string& getHostName() const {
return _hostName;
}
void setHostName(const std::string& hostName) {
_hostName = hostName;
}
const std::string& getPassword() const {
return _password;
}
void setPassword(const std::string& password) {
_password = password;
}
const std::string& getCache() const {
return _cache;
}
void setCache(const std::string& cacheDir) {
_cache = cacheDir + ".ipmiPluginSdrCache." + _hostName;
}
uint8_t getPriv() const {
return _priv;
}
void setPriv(uint8_t priv) {
_priv = priv;
}
const std::string& getUserName() const {
return _userName;
}
void setUserName(const std::string& userName) {
_userName = userName;
}
const std::string& getMqttPrefix() const {
return _mqttPrefix;
}
void setMqttPrefix(const std::string& mqttPrefix) {
_mqttPrefix = mqttPrefix;
if (_mqttPrefix.front() != '/') {
_mqttPrefix.insert(0, "/");
}
if (_mqttPrefix.back() == '/') {
_mqttPrefix.erase(_mqttPrefix.size()-1);
}
}
void initializeStrand(boost::asio::io_service& io);
boost::asio::io_service::strand* getStrand() const {
return _strand;
}
uint64_t getDelayNextReadUntil() const {
return _delayNextReadUntil;
}
void setDelayNextReadUntil(uint64_t delayNextReadUntil) {
_delayNextReadUntil = delayNextReadUntil;
}
private:
/* Open/close connection to BMC (sets/destroys _ipmiCtx) */
int connect();
int disconnect();
/* Open and create/destroy SDR cache (sets/destroys _sdrCtx and _sensorReadCtx) */
void createSdrCache();
void destroySdrCache();
/* Various context structs, required to make use of FreeIPMI */
ipmi_ctx_t _ipmiCtx;
ipmi_sdr_ctx_t _sdrCtx;
ipmi_sensor_read_ctx_t _sensorReadCtx;
std::string _hostName;
std::string _userName;
std::string _password;
std::string _cache;
uint8_t _auth;
uint8_t _priv;
std::string _mqttPrefix;
uint32_t _sessionTimeout;
uint32_t _retransmissionTimeout;
boost::asio::io_service::strand* _strand;
boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;
uint32_t _errorCount;
volatile uint64_t _delayNextReadUntil;
};
} /* namespace DCDB */
class IPMIHost {
public:
IPMIHost();
virtual ~IPMIHost();
/* Send raw command to BMC. Returns sensor reading as responded by BMC. */
uint64_t sendRawCmd(const std::vector<uint8_t>& rawCmd, uint16_t start, uint16_t stop);
/* Read the sensor specified by its record id. Returns sensor reading. */
double readSensor_recordId(uint16_t recordId);
void increaseErrorCount();
const uint64_t getDelayFactor() const;
void setAuth(uint8_t auth) { _auth = auth; }
void setHostName(const std::string& hostName) { _hostName = hostName; }
void setPassword(const std::string& password) { _password = password; }
void setCache(const std::string& cacheDir) { _cache = cacheDir + ".ipmiPluginSdrCache." + _hostName; }
void setPriv(uint8_t priv) { _priv = priv; }
void setUserName(const std::string& userName) { _userName = userName; }
void setMqttPart(const std::string& mqttPart) {
_mqttPart = mqttPart;
if (_mqttPart.front() != '/') {
_mqttPart.insert(0, "/");
}
if (_mqttPart.back() == '/') {
_mqttPart.erase(_mqttPart.size()-1);
}
}
void setSessionTimeout(uint32_t sessionTimeout) { _sessionTimeout = sessionTimeout; }
void setRetransmissionTimeout(uint32_t retransmissionTimeout) { _retransmissionTimeout = retransmissionTimeout; }
void initializeStrand(boost::asio::io_service& io);
void setDelayNextReadUntil(uint64_t delayNextReadUntil) { _delayNextReadUntil = delayNextReadUntil; }
uint8_t getAuth() const { return _auth; }
const std::string& getHostName() const { return _hostName; }
const std::string& getPassword() const { return _password; }
const std::string& getCache() const { return _cache; }
uint8_t getPriv() const { return _priv; }
const std::string& getUserName() const { return _userName; }
const std::string& getMqttPart() const { return _mqttPart; }
boost::asio::io_service::strand* getStrand() const { return _strand; }
uint64_t getDelayNextReadUntil() const { return _delayNextReadUntil; }
private:
/* Open/close connection to BMC (sets/destroys _ipmiCtx) */
int connect();
int disconnect();
/* Open and create/destroy SDR cache (sets/destroys _sdrCtx and _sensorReadCtx) */
void createSdrCache();
void destroySdrCache();
/* Various context structs, required to make use of FreeIPMI */
ipmi_ctx_t _ipmiCtx;
ipmi_sdr_ctx_t _sdrCtx;
ipmi_sensor_read_ctx_t _sensorReadCtx;
std::string _hostName;
std::string _userName;
std::string _password;
std::string _cache;
uint8_t _auth;
uint8_t _priv;
std::string _mqttPart;
uint32_t _sessionTimeout;
uint32_t _retransmissionTimeout;
boost::asio::io_service::strand* _strand;
boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;
uint32_t _errorCount;
volatile uint64_t _delayNextReadUntil;
};
#endif /* IPMIHOST_H_ */
......@@ -10,7 +10,6 @@
#include "../../includes/SensorBase.h"
#include "IPMIHost.h"
#include <boost/tokenizer.hpp>
......@@ -24,9 +23,7 @@ public:
_recordId(0),
_factor(1),
_start(0),
_stop(0) {
_host = NULL;
}
_stop(0) {}
virtual ~IPMISensorBase() {
}
......@@ -36,10 +33,9 @@ public:
const std::vector<uint8_t>& getRawCmd() const { return _rawCmd; }
uint8_t getStart() const { return _start; }
uint8_t getStop() const { return _stop; }
const DCDB::IPMIHost* getHost() const { return _host; }
void setRecordId(uint16_t recordId) { _recordId = recordId; }
void setFactor(double factor) { _factor = factor; }
void setRecordId(const std::string& recordId) { _recordId = stoul(recordId); }
void setFactor(const std::string& factor) { _factor = stod(factor); }
void setRawCmd(std::string& rawCmd) {
boost::regex expr("(?:0x)?([0-9a-fA-F]+)");
boost::regex_token_iterator<std::string::iterator> it { rawCmd.begin(), rawCmd.end(), expr, 1 };
......@@ -48,9 +44,8 @@ public:
_rawCmd.push_back(stoi(*it++, NULL, 16));
}
}
void setStart(uint8_t start) { _start = start; }
void setStop(uint8_t stop) { _stop = stop; }
void setHost(DCDB::IPMIHost* host) { _host = host; }
void setStart(const std::string& start) { _start = stoi(start); }
void setStop(const std::string& stop) { _stop = stoi(stop); }
protected:
uint16_t _recordId;
......@@ -59,7 +54,6 @@ protected:
std::vector<uint8_t> _rawCmd;
uint8_t _start;
uint8_t _stop;
DCDB::IPMIHost* _host;
};
#endif /* SRC_SENSORS_IPMI_IPMISENSORBASE_H_ */
......@@ -2,13 +2,12 @@
* IPMISingleSensor.cpp
*
* Created on: 18 Jan 2017
* Author: ottmi
* Author: Michael Ott (original), Micha Müller