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

Analytics: cooling control plugin (untested)

- A plugin to control warm-water cooling systems via SNMP
- Meant for use in the DEEP-EST project
parent e0fe76e4
......@@ -75,3 +75,5 @@ libdcdboperator_smucngperf.$(LIBEXT): operators/smucngperf/SMUCNGPerfOperator.o
libdcdboperator_persystsql.$(LIBEXT): operators/persystsql/PerSystSqlOperator.o operators/persystsql/PerSystSqlConfigurator.o operators/persystsql/MariaDB.o ../common/src/sensornavigator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -L$(DCDBDEPLOYPATH)/lib/mariadb/ -lboost_log -lboost_system -lboost_regex -lmariadb
libdcdboperator_coolingcontrol.$(LIBEXT): operators/coolingcontrol/CoolingControlOperator.o operators/coolingcontrol/CoolingControlConfigurator.o operators/coolingcontrol/SNMPController.o ../dcdbpusher/sensors/snmp/SNMPConnection.o ../common/src/sensornavigator.o
$(CXX) $(LIBFLAGS)$@ -o $@ $^ -L$(DCDBDEPLOYPATH)/lib/ -lboost_log -lboost_system -lboost_regex -lnetsnmp -lnetsnmpagent
template_controller def1 {
interval 1000
streaming true
Type Agent
Host 127.0.0.1
Port 161
Community public
OIDPrefix 1.3.6.1.4.1.1000.15
}
controller c1 {
default def1
OIDSuffix .2.1.0
strategy "stepped"
maxTemperature 450
minTemperature 350
bins 5
hotThreshold 700
hotSlots 1
input {
sensor "<bottomup 1, filter esb>temp" {
scaling 0.01
}
}
}
//================================================================================
// Name : CoolingControlConfigurator.cpp
// Author : Alessio Netti
// Contact : info@dcdb.it
// Copyright : Leibniz Supercomputing Centre
// Description :
//================================================================================
//================================================================================
// This file is part of DCDB (DataCenter DataBase)
// Copyright (C) 2019-2019 Leibniz Supercomputing Centre
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//================================================================================
#include "CoolingControlConfigurator.h"
CoolingControlConfigurator::CoolingControlConfigurator() : OperatorConfiguratorTemplate() {
_operatorName = "controller";
_baseName = "sensor";
}
CoolingControlConfigurator::~CoolingControlConfigurator() {}
void CoolingControlConfigurator::sensorBase(CoolingControlSensorBase& s, CFG_VAL config) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config)
{
if (boost::iequals(val.first, "scaling")) {
s.setScaleFac(std::stod(val.second.data()));
} else if (boost::iequals(val.first, "hotThreshold")) {
s.setHotThreshold(std::stoull(val.second.data()));
}
}
}
void CoolingControlConfigurator::operatorAttributes(CoolingControlOperator& op, CFG_VAL config) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config)
{
if (boost::iequals(val.first, "OIDSuffix"))
op.getController().setOIDSuffix(val.second.data());
else if (boost::iequals(val.first, "OIDPrefix"))
op.getController().setOIDPrefix(val.second.data());
else if (boost::iequals(val.first, "Community"))
op.getController().setSNMPCommunity(val.second.data());
else if (boost::iequals(val.first, "Version"))
op.getController().setVersion(val.second.data());
else if (boost::iequals(val.first, "Host"))
op.getController().setHost(val.second.data());
else if (boost::iequals(val.first, "Username"))
op.getController().setUsername(val.second.data());
else if (boost::iequals(val.first, "SecLevel"))
op.getController().setSecurityLevel(val.second.data());
else if (boost::iequals(val.first, "AuthProto"))
op.getController().setAuthProto(val.second.data());
else if (boost::iequals(val.first, "PrivProto"))
op.getController().setPrivProto(val.second.data());
else if (boost::iequals(val.first, "AuthKey"))
op.getController().setAuthKey(val.second.data());
else if (boost::iequals(val.first, "PrivKey"))
op.getController().setPrivKey(val.second.data());
else if (boost::iequals(val.first, "maxTemperature"))
op.setMaxTemp(std::stoull(val.second.data()));
else if (boost::iequals(val.first, "minTemperature"))
op.setMinTemp(std::stoull(val.second.data()));
else if (boost::iequals(val.first, "bins"))
op.setBins(std::stoull(val.second.data()));
else if (boost::iequals(val.first, "window"))
op.setWindow(std::stoull(val.second.data()) * 1000000);
else if (boost::iequals(val.first, "hotPercentage"))
op.setHotPerc(std::stoull(val.second.data()));
else if (boost::iequals(val.first, "strategy")) {
if (val.second.data() == "continuous" || val.second.data() == "stepped") {
op.setStrategy(val.second.data());
}
}
}
}
bool CoolingControlConfigurator::unit(UnitTemplate<CoolingControlSensorBase>& u) {
if(u.isTopUnit()) {
LOG(error) << " " << _operatorName << ": This operator type only supports flat units!";
return false;
}
if(!u.getOutputs().empty()) {
LOG(error) << " " << _operatorName << ": This is a cooling control sink, no output sensors can be defined!";
return false;
}
return true;
}
//================================================================================
// Name : CoolingControlConfigurator.h
// Author : Alessio Netti
// Contact : info@dcdb.it
// Copyright : Leibniz Supercomputing Centre
// Description :
//================================================================================
//================================================================================
// This file is part of DCDB (DataCenter DataBase)
// Copyright (C) 2019-2019 Leibniz Supercomputing Centre
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//================================================================================
#ifndef PROJECT_COOLINGCONTROLCONFIGURATOR_H
#define PROJECT_COOLINGCONTROLCONFIGURATOR_H
#include "../../includes/OperatorConfiguratorTemplate.h"
#include "CoolingControlOperator.h"
/**
* @brief Configurator for the Cooling Control plugin.
*
* @ingroup coolingcontrol
*/
class CoolingControlConfigurator : virtual public OperatorConfiguratorTemplate<CoolingControlOperator, CoolingControlSensorBase> {
public:
CoolingControlConfigurator();
virtual ~CoolingControlConfigurator();
private:
void sensorBase(CoolingControlSensorBase& s, CFG_VAL config) override;
void operatorAttributes(CoolingControlOperator& op, CFG_VAL config) override;
bool unit(UnitTemplate<CoolingControlSensorBase>& u) override;
};
extern "C" OperatorConfiguratorInterface* create() {
return new CoolingControlConfigurator;
}
extern "C" void destroy(OperatorConfiguratorInterface* c) {
delete c;
}
#endif //PROJECT_COOLINGCONTROLCONFIGURATOR_H
//================================================================================
// Name : CoolingControlOperator.cpp
// Author : Alessio Netti
// Contact : info@dcdb.it
// Copyright : Leibniz Supercomputing Centre
// Description :
//================================================================================
//================================================================================
// This file is part of DCDB (DataCenter DataBase)
// Copyright (C) 2019-2019 Leibniz Supercomputing Centre
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//================================================================================
#include "CoolingControlOperator.h"
CoolingControlOperator::CoolingControlOperator(const std::string& name) : OperatorTemplate(name) {
_strategy = "stepped";
_maxTemp = 450;
_minTemp = 350;
_window = 0;
_bins = 4;
_hotPerc = 20;
_currTemp = 0;
}
CoolingControlOperator::CoolingControlOperator(const CoolingControlOperator& other) : OperatorTemplate(other) {
_strategy = other._strategy;
_maxTemp = other._maxTemp;
_minTemp = other._minTemp;
_window = other._window;
_bins = other._bins;
_hotPerc = other._hotPerc;
_currTemp = 0;
}
CoolingControlOperator::~CoolingControlOperator() {}
void CoolingControlOperator::printConfig(LOG_LEVEL ll) {
LOG_VAR(ll) << " Strategy: " << _strategy;
LOG_VAR(ll) << " Max Temperature: " << _maxTemp;
LOG_VAR(ll) << " Min Temperature: " << _minTemp;
LOG_VAR(ll) << " Window: " << _window;
LOG_VAR(ll) << " Bins: " << _bins;
LOG_VAR(ll) << " Hot Percentage: " << _hotPerc;
_controller.printEntityConfig(ll, 12);
OperatorTemplate<CoolingControlSensorBase>::printConfig(ll);
}
restResponse_t CoolingControlOperator::REST(const string& action, const unordered_map<string, string>& queries) {
restResponse_t resp;
if(action=="status") {
resp.response = "Using cooling control strategy " + _strategy + " with temperature " + std::to_string(_currTemp) + ".\n";
} else
throw invalid_argument("Unknown plugin action " + action + " requested!");
return resp;
}
void CoolingControlOperator::execOnInit() {
_controller.execOnInit();
_dummySensor.setOID(_controller.getOIDPrefix() + _controller.getOIDSuffix());
}
bool CoolingControlOperator::execOnStart() {
// Resetting the internal temperature setting at each plugin start
_currTemp = 0;
return true;
}
void CoolingControlOperator::compute(U_Ptr unit) {
// Querying input data
std::vector<std::vector<reading_t>> buffer;
for(const auto& in : unit->getInputs()) {
std::vector<reading_t> bufferInt;
if (!_queryEngine.querySensor(in->getName(), _window, 0, bufferInt, true) || bufferInt.empty()) {
LOG(debug) << "Operator " + _name + ": cannot read from sensor " + in->getName() + "!";
}
buffer.push_back(bufferInt);
}
// Establishing the new setting - needs to be a 32-bit signed integer
int newSetting=-1;
if( _strategy == "continuous" ) {
newSetting = continuousControl(buffer, unit);
} else if( _strategy == "stepped") {
newSetting = steppedControl(buffer, unit);
}
// Enacting control
if( newSetting >= 0 && _controller.open() ) {
try {
_controller.set(_dummySensor.getOID(), _dummySensor.getOIDLen(), ASN_INTEGER, (void *) &newSetting, sizeof(newSetting));
} catch (const std::runtime_error& e) {
LOG(error) << "Operator " << _name << ": SNMP set request failed!";
}
_controller.close();
}
return;
}
int CoolingControlOperator::continuousControl(std::vector<std::vector<reading_t>> &readings, U_Ptr unit) {
if( _currTemp == 0 ) {
_currTemp = (_maxTemp - _minTemp) / 2;
} else {
// If there are less hot nodes than our hot threshold, we increase the inlet temperature - and vice versa
uint64_t percHotNodes = (getNumHotNodes(readings, unit) * 100) / readings.size();
_currTemp += (_hotPerc - percHotNodes) * (_maxTemp - _minTemp) / 100;
_currTemp = clipTemperature(_currTemp);
}
return (int)_currTemp;
}
int CoolingControlOperator::steppedControl(std::vector<std::vector<reading_t>> &readings, U_Ptr unit) {
uint64_t oldTemp = _currTemp;
int ret = -1;
if(_currTemp == 0) {
_currTemp = (_maxTemp - _minTemp) / 2;
return _currTemp;
} else {
// If there are less hot nodes than our hot threshold, we increase the inlet temperature - and vice versa
uint64_t percHotNodes = (getNumHotNodes(readings, unit) * 100) / readings.size();
_currTemp += (_hotPerc - percHotNodes) * (_maxTemp - _minTemp) / 100;
_currTemp = clipTemperature(_currTemp);
// We're crossing to a new bin - assigning the new setting
if(getBinForValue(oldTemp) != getBinForValue(_currTemp)) {
uint64_t binStep = (_maxTemp - _minTemp) / _bins;
_currTemp = _minTemp + getBinForValue(_currTemp) * binStep + binStep / 2;
ret = (int)_currTemp;
}
}
return ret;
}
uint64_t CoolingControlOperator::getNumHotNodes(std::vector<std::vector<reading_t>> &readings, U_Ptr unit) {
uint64_t numHotNodes = 0;
for(size_t idx=0; idx<readings.size(); idx++) {
if (!readings[idx].empty()) {
bool hotNode = true;
for (const auto &r : readings[idx]) {
if (r.value < unit->getInputs()[idx]->getHotThreshold()) {
hotNode = false;
break;
}
}
if (hotNode) {
numHotNodes++;
}
}
}
return numHotNodes;
}
uint64_t CoolingControlOperator::getBinForValue(uint64_t temp) {
if(temp <= _minTemp) {
return 0;
} else if(temp >= _maxTemp) {
return _bins - 1;
} else {
uint64_t binStep = (_maxTemp - _minTemp) / _bins;
return (temp - _minTemp) / binStep;
}
}
uint64_t CoolingControlOperator::clipTemperature(uint64_t temp) {
if(temp > _maxTemp) {
return _maxTemp;
} else if (temp < _minTemp) {
return _minTemp;
} else {
return temp;
}
}
//================================================================================
// Name : CoolingControlOperator.h
// Author : Alessio Netti
// Contact : info@dcdb.it
// Copyright : Leibniz Supercomputing Centre
// Description :
//================================================================================
//================================================================================
// This file is part of DCDB (DataCenter DataBase)
// Copyright (C) 2019-2019 Leibniz Supercomputing Centre
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//================================================================================
#ifndef PROJECT_COOLINGCONTROLOPERATOR_H
#define PROJECT_COOLINGCONTROLOPERATOR_H
#include "../../includes/OperatorTemplate.h"
#include "CoolingControlSensorBase.h"
#include "SNMPController.h"
/**
* @brief Aggregator operator plugin.
*
* @ingroup aggregator
*/
class CoolingControlOperator : virtual public OperatorTemplate<CoolingControlSensorBase> {
public:
CoolingControlOperator(const std::string& name);
CoolingControlOperator(const CoolingControlOperator& other);
virtual ~CoolingControlOperator();
virtual restResponse_t REST(const string& action, const unordered_map<string, string>& queries) override;
virtual void execOnInit() override;
virtual bool execOnStart() override;
void setStrategy(std::string strat) { _strategy = strat; }
void setMaxTemp(uint64_t mt) { _maxTemp = mt; }
void setMinTemp(uint64_t mt) { _minTemp = mt; }
void setWindow(uint64_t w) { _window = w; }
void setBins(uint64_t b) { _bins = b; }
void setHotThreshold(uint64_t ht) { _hotThreshold = ht; }
void setHotPerc(uint64_t hp) { _hotPerc = hp; }
SNMPController &getController() { return _controller; }
std::string getStrategy() { return _strategy; }
uint64_t getMaxTemp() { return _maxTemp; }
uint64_t getMinTemp() { return _minTemp; }
uint64_t getWindow() { return _window; }
uint64_t getBins() { return _bins; }
uint64_t getHotThreshold() { return _hotThreshold; }
uint64_t getHotPerc() { return _hotPerc; }
void printConfig(LOG_LEVEL ll) override;
protected:
virtual void compute(U_Ptr unit) override;
int continuousControl(std::vector<std::vector<reading_t>> &readings, U_Ptr unit);
int steppedControl(std::vector<std::vector<reading_t>> &readings, U_Ptr unit);
uint64_t getNumHotNodes(std::vector<std::vector<reading_t>> &readings, U_Ptr unit);
uint64_t getBinForValue(uint64_t temp);
uint64_t clipTemperature(uint64_t temp);
// Control parameters
std::string _strategy;
uint64_t _currTemp;
uint64_t _maxTemp;
uint64_t _minTemp;
uint64_t _window;
uint64_t _bins;
uint64_t _hotThreshold;
uint64_t _hotPerc;
SNMPController _controller = SNMPController("SNMPControl");
SNMPSensorBase _dummySensor = SNMPSensorBase("SNMPSensor");
};
#endif //PROJECT_COOLINGCONTROLOPERATOR_H
//================================================================================
// Name : CoolingControlSensorBase.h
// Author : Alessio Netti
// Contact : info@dcdb.it
// Copyright : Leibniz Supercomputing Centre
// Description :
//================================================================================
//================================================================================
// This file is part of DCDB (DataCenter DataBase)
// Copyright (C) 2019-2019 Leibniz Supercomputing Centre
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//================================================================================
/**
* @defgroup coolingcontrol Cooling Control operator plugin.
* @ingroup operator
*
* @brief Cooling Control operator plugin.
*/
#ifndef PROJECT_COOLINGCONTROLSENSORBASE_H
#define PROJECT_COOLINGCONTROLSENSORBASE_H
#include "../../../dcdbpusher/sensors/snmp/SNMPSensorBase.h"
/**
* @brief Sensor base for Cooling Control plugin
*
* @ingroup coolingcontrol
*/
class CoolingControlSensorBase : public SNMPSensorBase {
public:
// Constructor and destructor
CoolingControlSensorBase(const std::string& name) : SNMPSensorBase(name) {
_hotThreshold = 70;
}
// Copy constructor
CoolingControlSensorBase(CoolingControlSensorBase& other) : SNMPSensorBase(other) {
_hotThreshold = 70;
}
virtual ~CoolingControlSensorBase() {}
void setHotThreshold(uint64_t t) { _hotThreshold = t; }
uint64_t getHotThreshold() { return _hotThreshold; }
void printConfig(LOG_LEVEL ll, LOGGER& lg, unsigned leadingSpaces=16) {
SNMPSensorBase::printConfig(ll, lg, leadingSpaces);
std::string leading(leadingSpaces, ' ');
LOG_VAR(ll) << leading << " Hot Threshold: " << _hotThreshold;
}
protected:
uint64_t _hotThreshold;
};
using CCSBPtr = std::shared_ptr<CoolingControlSensorBase>;
#endif //PROJECT_COOLINGCONTROLSENSORBASE_H
//================================================================================
// Name : SNMPController.cpp
// Author : Alessio Netti
// Contact : info@dcdb.it
// Copyright : Leibniz Supercomputing Centre
// Description :
//================================================================================
//================================================================================
// This file is part of DCDB (DataCenter DataBase)
// Copyright (C) 2019-2019 Leibniz Supercomputing Centre
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,