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

Finish adaption of SNMP plugin

parent 3b75d64f
......@@ -2,63 +2,61 @@ global {
mqttprefix /00112233445566778899AABBCC
}
sensorTemplates {
sensor temp1 {
interval 1000
minValues 3
}
template_group temp1 {
interval 1000
minValues 3
}
; Connections contains a list of connections
; So far, we only support "Agent" mode in which we connect to a
; SNMP agent and issue GET commands to read the data.
connections {
; Each connection is identified by a unique name. However, this
; name is only useful when we print error messages.
connection name1 {
Type Agent ; Type of connection
Host test.net-snmp.org ; Hostname of the SNMP agent
Port 161 ; Port of the SNMP agent
OIDPrefix 1.3.6.1.2.1.1 ; When querying OIDs, we'll
; always use this prefix
Version 3
Community public ; SNMP community string
Username MD5DESUser
SecLevel AuthPriv
AuthProto MD5
AuthKey "The UCD Demo Password"
PrivProto DES
PrivKey "The UCD Demo Password"
mqttPart BB ; When generating MQTT topics,
; we'll append this part to
; the prefix
connection name1 {
Type Agent ; Type of connection
Host test.net-snmp.org ; Hostname of the SNMP agent
Port 161 ; Port of the SNMP agent
OIDPrefix 1.3.6.1.2.1.1 ; When querying OIDs, we'll
; always use this prefix
Version 3
Community public ; SNMP community string
Username MD5DESUser
SecLevel AuthPriv
AuthProto MD5
AuthKey "The UCD Demo Password"
PrivProto DES
PrivKey "The UCD Demo Password"
mqttPart BB ; When generating MQTT topics,
; we'll append this part to
; the prefix
group g1 {
sensor sysUpTime {
OID 3.0 ; OID of the sensor
mqttsuffix 0001 ; MQTT suffix of the sensor
interval 5000 ; Read sensor every 1000ms
OID 3.0 ; OID of the sensor
mqttsuffix 0001 ; MQTT suffix of the sensor
interval 5000 ; Read sensor every 1000ms
}
}
group g2 {
default temp1
sensor SysORUpTime {
OID 9.1.4.1
mqttsuffix 0002
default temp1
}
}
}
; connection name2 {
; Type Agent
; Host HostNameOfSNMPAgent2
; Port 161
; Community public
; OIDPrefix 1.3.6.1.4.1.1000.15
; mqttPart CC
;connection name2 {
; Type Agent
; Host HostNameOfSNMPAgent2
; Port 161
; Community public
; OIDPrefix 1.3.6.1.4.1.1000.15
; mqttPart CC
;
; sensor name1 {
; OID 3
; mqttsuffix 0017
; interval 5000
; }
; sensor name1 {
; OID 3
; mqttsuffix 0017
; interval 5000
; }
}
;}
......@@ -93,8 +93,9 @@ public:
if (boost::iequals(val.first, "template_" + _entityName)) {
LOG(debug) << "Template " << _entityName << " \"" << val.second.data() << "\"";
if (!val.second.empty()) {
SEntity* entity = new SEntity(/*val.second.data()*/);
if (readSensorEntity(*entity, val.second)) {
//name of an entity is only used to identify templates and is not stored otherwise
SEntity* entity = new SEntity();
if (readSensorEntity(*entity, val.second, true)) {
auto ret = _templateSensorEntitys.insert(std::pair<std::string, SEntity*>(val.second.data(), entity));
if(!ret.second) {
LOG(warning) << "Template " << _entityName << " " << val.second.data() << " already exists! Omitting...";
......@@ -121,8 +122,8 @@ public:
} else if (boost::iequals(val.first, _entityName)) {
LOG(debug) << _entityName << " \"" << val.second.data() << "\"";
if (!val.second.empty()) {
SEntity* entity = new SEntity(/*val.second.data()*/);
if (readSensorEntity(*entity, val.second)) {
SEntity* entity = new SEntity();
if (readSensorEntity(*entity, val.second, false)) {
_sensorEntitys.push_back(entity);
} else {
LOG(warning) << _entityName << " \"" << val.second.data() << "\" has bad values! Ignoring...";
......@@ -295,10 +296,12 @@ protected:
*
* @param sEntity The aggregating entity for which to set the values
* @param config A boost property (sub-)tree containing the sensor values
* @param isTemplate Indicate if sEntity is a template. If so, also store
* the corresponding sGroups in the template map
*
* @return True on success, false otherwise
*/
bool readSensorEntity(SEntity& sEntity, CFG_VAL config) {
bool readSensorEntity(SEntity& sEntity, CFG_VAL config, bool isTemplate) {
//first check if default entity is given
boost::optional<boost::property_tree::iptree&> def = config.get_child_optional("default");
if(def) {
......@@ -307,12 +310,45 @@ protected:
auto it = _templateSensorEntitys.find(def.get().data());
if(it != _templateSensorEntitys.end()) {
sEntity = *(it->second);
//sEntity.setName(config.data());
for(auto g : _templateSensorGroups) {
if (isEntityOfGroup(*(it->second), *(g.second))) {
SGroup* group = new SGroup(*(g.second));
setEntityForGroup(sEntity, *group);
_sensorGroups.push_back(group);
}
}
} else {
LOG(warning) << "Template " << _entityName << "\"" << def.get().data() << "\" not found! Using standard values.";
}
}
sensorEntity(sEntity, config);
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
if (boost::iequals(val.first, _groupName)) {
LOG(debug) << " " << _groupName << " " << val.second.data();
SGroup* group = new SGroup(val.second.data());
if(readSensorGroup(*group, val.second)) {
setEntityForGroup(sEntity, *group);
if (isTemplate) {
auto ret = _templateSensorGroups.insert(std::pair<std::string, SGroup*>(val.second.data(), group));
if(!ret.second) {
LOG(warning) << "Template " << _groupName << " " << val.second.data() << " already exists! Omitting...";
}
} else {
_sensorGroups.push_back(group);
}
} else {
LOG(warning) << _groupName << " " << group->getGroupName() << " could not be read! Omitting";
}
}
}
for(auto g : _sensorGroups) {
if(isEntityOfGroup(sEntity, *g)) {
finalizeEntityGroup(sEntity, *g);
}
}
return true;
}
......@@ -351,7 +387,7 @@ protected:
* Pure virtual interface method, responsible for reading plugin-specific sensor
* base values.
*
* @param sBase The sensor base for which to set the values
* @param s The sensor base for which to set the values
* @param config A boost property (sub-)tree containing the sensor values
*/
virtual void sensorBase(SBase& s, CFG_VAL config) = 0;
......@@ -360,7 +396,7 @@ protected:
* Pure virtual interface method, responsible for reading plugin-specific sensor
* group values.
*
* @param sGroup The sensor group for which to set the values
* @param s The sensor group for which to set the values
* @param config A boost property (sub-)tree containing the group values
*/
virtual void sensorGroup(SGroup& s, CFG_VAL config) = 0;
......@@ -369,7 +405,7 @@ protected:
* Virtual interface method, responsible for reading plugin-specific sensor
* entity values.
*
* @param sEntity The sensor entity for which to set the values
* @param s The sensor entity for which to set the values
* @param config A boost property (sub-)tree containing the entity values
*/
virtual void sensorEntity(SEntity& s, CFG_VAL config) {
......@@ -377,6 +413,44 @@ protected:
LOG(warning) << "Method sensorEntity called, but was not overwritten! Either you have unwanted entitys in your config file or forgot to overwrite this method";
}
/**
* Check if e is the corresponding entity of g
*
* @param e
* @param g
*
* @return True if (g.entity == &e)
*/
//TODO not very convenient for writing plugins. Are there better solutions?
virtual bool isEntityOfGroup(SEntity& e, SGroup& g) {
//Overwrite if necessary
LOG(warning) << "Method isEntityOfGroup called, but was not overwritten! Either you have unwanted entitys in your config file or forgot to overwrite this method";
return false;
}
/**
* Sets e as entity for group g
*
* @param e
* @param g
*/
//TODO not very convenient for writing plugins. Are there better solutions?
virtual void setEntityForGroup(SEntity& e, SGroup& g) {
//Overwrite if necessary
LOG(warning) << "Method setEntityForGroup called, but was not overwritten! Either you have unwanted entitys in your config file or forgot to overwrite this method";
}
/**
* Finalize the group g with everything it needs from its entity (set e.g. the mqttPart for entity)
*
* @param g
*/
//TODO not very convenient for writing plugins. Are there better solutions?
virtual void finalizeGroup(SGroup& g) {
//Overwrite if necessary
LOG(warning) << "Method finalizeEntityGroup called, but was not overwritten! Either you have unwanted entitys in your config file or forgot to overwrite this method";
}
/**
* Virtual interface method, responsible for reading plugin-specific global values.
*
......
......@@ -18,7 +18,7 @@ SNMPConfigurator::SNMPConfigurator() {
SNMPConfigurator::~SNMPConfigurator() {}
void sensorBase(SNMPSensorBase& s, CFG_VAL config) {
void SNMPConfigurator::sensorBase(SNMPSensorBase& s, CFG_VAL config) {
//TODO sensor.setOID(sensor.getConnection()->getOIDPrefix() + "." + val.second.data());
ADD {
ATTRIBUTE("OID", setOID)
......@@ -26,13 +26,13 @@ void sensorBase(SNMPSensorBase& s, CFG_VAL config) {
}
void sensorGroup(SNMPSensorGroup& s, CFG_VAL config) {
void SNMPConfigurator::sensorGroup(SNMPSensorGroup& s, CFG_VAL config) {
ADD {
//no group attributes currently
}
}
void sensorEntity(SNMPConnection& s, CFG_VAL config) {
void SNMPConfigurator::sensorEntity(SNMPConnection& s, CFG_VAL config) {
ADD {
//ATTRIBUTE("Type", setType) //TODO would be relevant if we would support more than just agent mode...
//at the moment we just ignore it, as it can be only "Agent" anyways
......@@ -47,139 +47,20 @@ void sensorEntity(SNMPConnection& s, CFG_VAL config) {
ATTRIBUTE("PrivProto", setPrivProto)
ATTRIBUTE("AuthKey", setAuthKey)
ATTRIBUTE("PrivKey", setPrivKey)
//TODO MqttPart
ATTRIBUTE("MqttPart", setMqttPart)
}
}
bool SNMPConfigurator::derivedReadConfig(boost::property_tree::iptree& cfg) {
std::string mqttPartConnection;
BOOST_FOREACH(boost::property_tree::iptree::value_type &connection, cfg.get_child("connections")) {
if (STRCMP(connection, ("connection"))) {
LOG(debug) << "Connection " << connection.second.data();
_connections.push_back(SNMPConnection());
SNMPConnection &conn = _connections.back();
if (!connection.second.empty()) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &c, connection.second) {
if (STRCMP(c, "Type")) {
//TODO would be relevant if we would support more than just agent mode...
// at the moment we just ignore it, as it can be only "Agent" anyways
} else if (STRCMP(c, "Host")) {
conn.setHost(c.second.data());
LOG(debug) << " Host " << conn.getHost();
} else if (STRCMP(c, "Port")) {
conn.setPort(stoi(c.second.data()));
LOG(debug) << " Port " << conn.getPort();
} else if (STRCMP(c, "Community")) {
conn.setSNMPCommunity(c.second.data());
LOG(debug) << " Community " << conn.getSNMPCommunity();
} else if (STRCMP(c, "OIDPrefix")) {
conn.setOIDPrefix(c.second.data());
LOG(debug) << " OID-prefix " << conn.getOIDPrefix();
} else if (STRCMP(c, "Version")) {
int version = stoi(c.second.data());
switch (version) {
case 1:
conn.setVersion(SNMP_VERSION_1);
LOG(debug) << " Version 1";
break;
case 2:
conn.setVersion(SNMP_VERSION_2c);
LOG(debug) << " Version 2c";
break;
case 3:
conn.setVersion(SNMP_VERSION_3);
LOG(debug) << " Version 3";
break;
default:
conn.setVersion(-1);
LOG(warning) << "Invalid SNMP Version " << version << "!";
}
} else if (STRCMP(c, "Username")) {
conn.setUsername(c.second.data());
LOG(debug) << " Username " << conn.getUsername();
} else if (STRCMP(c, "SecLevel")) {
std::string secLvl = c.second.data();
if (boost::iequals(secLvl, "noAuthNoPriv")) {
conn.setSecurityLevel(SNMP_SEC_LEVEL_NOAUTH);
LOG(debug) << " Security Level NoAuthNoPriv";
} else if (boost::iequals(secLvl, "authNoPriv")) {
conn.setSecurityLevel(SNMP_SEC_LEVEL_AUTHNOPRIV);
LOG(debug) << " Security Level AuthNoPriv";
} else if (boost::iequals(secLvl, "authPriv")) {
conn.setSecurityLevel(SNMP_SEC_LEVEL_AUTHPRIV);
LOG(debug) << " Security Level AuthPriv";
}
} else if (STRCMP(c, "AuthProto")) {
std::string authProto = c.second.data();
if (boost::iequals(authProto, "MD5")) {
conn.setAuthProto(usmHMACMD5AuthProtocol);
conn.setAuthProtoLen(USM_AUTH_PROTO_MD5_LEN);
LOG(debug) << " Authentication protocol MD5";
} else if (boost::iequals(authProto, "SHA1")) {
conn.setAuthProto(usmHMACSHA1AuthProtocol);
conn.setAuthProtoLen(USM_AUTH_PROTO_SHA_LEN);
LOG(debug) << " Authentication protocol SHA1";
}
} else if (STRCMP(c, "PrivProto")) {
std::string privProto = c.second.data();
if (boost::iequals(privProto, "DES")) {
conn.setPrivProto(snmp_duplicate_objid(usmDESPrivProtocol, USM_PRIV_PROTO_DES_LEN));
conn.setPrivProtoLen(USM_PRIV_PROTO_DES_LEN);
LOG(debug) << " Privacy protocol DES";
} else if (boost::iequals(privProto, "AES")) {
conn.setPrivProto(snmp_duplicate_objid(usmAESPrivProtocol, USM_PRIV_PROTO_AES_LEN));
conn.setPrivProtoLen(USM_PRIV_PROTO_AES_LEN);
LOG(debug) << " Privacy protocol AES";
}
} else if (STRCMP(c, "AuthKey")) {
conn.setAuthKey(c.second.data());
LOG(debug) << " Authkey " << conn.getAuthKey();
} else if (STRCMP(c, "PrivKey")) {
conn.setPrivKey(c.second.data());
LOG(debug) << " Privkey " << conn.getPrivKey();
} else if (STRCMP(c, "mqttPart")) {
mqttPartConnection = c.second.data();
if (mqttPartConnection[mqttPartConnection.length()-1] != '/') {
mqttPartConnection.append("/");
}
LOG(debug) << " MQTTPart " << mqttPartConnection;
} else if (STRCMP(c, "sensor")) {
LOG(debug) << "Sensor \"" << c.second.data() << "\"";
if (!c.second.empty()) {
std::string name = connection.second.data() + "_" + c.second.data();
SNMPSensorGroup * snmpSensor = new SNMPSensorGroup(name);
//first check if default sensor is given
boost::optional<boost::property_tree::iptree&> defaultC = c.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()) {
*snmpSensor = it->second;
snmpSensor->setName(name);
} else {
LOG(warning) << " Template sensor \"" << defaultC.get().data() << "\" not found! Using standard values.";
}
}
bool SNMPConfigurator::isEntityOfGroup(SNMPConnection& e, SNMPSensorGroup& g) {
return (g.getConnection() == &e);
}
snmpSensor->setConnection(&conn);
snmpSensor->setMqtt(_mqttPrefix + mqttPartConnection);
void SNMPConfigurator::setEntityForGroup(SNMPConnection& e, SNMPSensorGroup& g) {
g.setConnection(&e);
}
//read remaining values
if(readSensorBase(*snmpSensor, c.second)) {
_sensors.push_back(snmpSensor);
} else {
LOG(warning) << " Sensor \"" << c.second.data() << "\" has bad values! Ignoring...";
}
}
}
}
}
conn.init();
}
}
return true;
void SNMPConfigurator::finalizeGroup(SNMPSensorGroup& g) {
g.setMqttPart(g.getConnection()->getMqttPart() + g.getMqttPart());
g.setOIDPrefix(g.getConnection()->getOIDPrefix());
g.getConnection()->init();
}
......@@ -25,8 +25,9 @@ protected:
void sensorGroup(SNMPSensorGroup& s, CFG_VAL config) override;
void sensorEntity(SNMPConnection& s, CFG_VAL config) override;
bool derivedReadConfig(boost::property_tree::iptree& cfg) override;
bool isEntityOfGroup(SNMPConnection& e, SNMPSensorGroup& g) override;
void setEntityForGroup(SNMPConnection& e, SNMPSensorGroup& g) override;
void finalizeGroup(SNMPSensorGroup& g) override;
};
extern "C" ConfiguratorInterface* create() {
......
......@@ -10,6 +10,7 @@
#include <string>
SNMPConnection::SNMPConnection() {
_isInitialized = false;
_snmpCommunity = "";
_oidPrefix = "";
_username = "";
......@@ -54,6 +55,10 @@ void SNMPConnection::initializeStrand(boost::asio::io_service& io) {
}
void SNMPConnection::init() {
if(_isInitialized) {
return;
}
snmp_sess_init(&_snmpSession);
_snmpSession.version = _version;
_snmpSession.peername = strdup(_host.c_str());
......@@ -114,6 +119,7 @@ void SNMPConnection::init() {
} else {
LOG(warning) << "SNMP Version " << _version << " not supported!";
}
_isInitialized = true;
}
uint64_t SNMPConnection::issueGet(oid* OID, size_t OIDLen) {
......
......@@ -20,9 +20,13 @@ public:
virtual ~SNMPConnection();
void setSNMPCommunity(const std::string& community) { _snmpCommunity = community; }
void setMqttPart(const std::string& mqttPart) {
if (mqttPart[mqttPart.length()-1] != '/') {
_mqttPart = mqttPart + "/";
} else {
_mqttPart = mqttPart;
}
}
void setOIDPrefix(const std::string& oidPrefix) {
/* Ensure that the oidPrefix does not contain a trailing . */
_oidPrefix = oidPrefix;
......@@ -83,6 +87,7 @@ public:
void initializeStrand(boost::asio::io_service& io);
const std::string& getSNMPCommunity() const { return _snmpCommunity; }
const std::string& getMqttPart() const { return _mqttPart; }
const std::string& getOIDPrefix() const { return _oidPrefix; }
const std::string& getUsername() const { return _username; }
const std::string& getAuthKey() const { return _authKey; }
......@@ -111,7 +116,10 @@ public:
uint64_t issueGet(oid* OID, size_t OIDLen);
private:
bool _isInitialized;
std::string _snmpCommunity;
std::string _mqttPart;
std::string _oidPrefix;
std::string _host;
std::string _username;
......
......@@ -21,6 +21,11 @@ public:
void start() override;
void stop() override;
void setOIDPrefix(const std::string& oidPrefix) {
for(auto s : _sensors) {
s->setOID(oidPrefix + s->getOIDString());
}
}
void setConnection(SNMPConnection* connection) { _connection = connection; }
SNMPConnection* getConnection() const { return _connection; }
......
Markdown is supported
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