The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated 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 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,