141 lines
4.1 KiB
C++
141 lines
4.1 KiB
C++
#include "ipmi.h"
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
|
|
static constexpr size_t IPMI_RAW_MAX_ARGS = 65536*2;
|
|
|
|
static double ipmi_convert_sensor_reading(void *sensor_reading, int sensor_reading_type)
|
|
{
|
|
if(sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL)
|
|
return (double)(*((uint8_t *)sensor_reading));
|
|
else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32)
|
|
return (double)(*((uint32_t *)sensor_reading));
|
|
else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE)
|
|
return *((double *)sensor_reading);
|
|
return 0;
|
|
}
|
|
|
|
Sensor ipmi_read_sensor_from_ctx(ipmi_monitoring_ctx_t ctx)
|
|
{
|
|
Sensor sensor;
|
|
sensor.chip = "IPMI";
|
|
int record_id = ipmi_monitoring_sensor_read_record_id(ctx);
|
|
int reading_type = ipmi_monitoring_sensor_read_sensor_reading_type(ctx);
|
|
char *name = ipmi_monitoring_sensor_read_sensor_name(ctx);
|
|
void *reading = ipmi_monitoring_sensor_read_sensor_reading(ctx);
|
|
|
|
if(record_id < 0 || reading_type < 0 || !name || !reading)
|
|
return sensor;
|
|
|
|
if(reading_type != IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32 &&
|
|
reading_type != IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE)
|
|
return sensor;
|
|
|
|
sensor.name.assign(name);
|
|
sensor.reading = ipmi_convert_sensor_reading(reading, reading_type);
|
|
sensor.id = record_id;
|
|
return sensor;
|
|
}
|
|
|
|
bool ipmi_fill_sensor_ids(std::vector<Sensor>& sensors, ipmi_monitoring_ctx_t ctx, struct ipmi_monitoring_ipmi_config* config)
|
|
{
|
|
unsigned int types[] = {IPMI_MONITORING_SENSOR_TYPE_TEMPERATURE};
|
|
unsigned int types_len = sizeof(types)/sizeof(types[0]);
|
|
int sensor_count = ipmi_monitoring_sensor_readings_by_sensor_type(ctx, NULL, config, 0, types, types_len, NULL, NULL);
|
|
|
|
for(int i = 0; i < sensor_count; ++i, ipmi_monitoring_sensor_iterator_next(ctx))
|
|
{
|
|
Sensor sensor = ipmi_read_sensor_from_ctx(ctx);
|
|
|
|
auto search = std::find(sensors.begin(), sensors.end(), sensor);
|
|
if(search != sensors.end())
|
|
*search = sensor;
|
|
}
|
|
|
|
for(Sensor& sensor : sensors)
|
|
{
|
|
if(sensor.id == 0 && sensor.chip == "IPMI")
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ipmi_update_sensors(std::vector<Sensor>& sensors, ipmi_monitoring_ctx_t ctx, struct ipmi_monitoring_ipmi_config* config)
|
|
{
|
|
unsigned int *ids = new unsigned int[sensors.size()];
|
|
for(size_t i = 0; i < sensors.size(); ++i)
|
|
ids[i] = sensors[i].id;
|
|
|
|
int sensor_count = ipmi_monitoring_sensor_readings_by_record_id(ctx, NULL, config, 0, ids, sensors.size(), NULL, NULL);
|
|
delete[] ids;
|
|
if(sensor_count < static_cast<int>(sensors.size()))
|
|
return false;
|
|
|
|
for(int i = 0; i < sensor_count; ++i, ipmi_monitoring_sensor_iterator_next(ctx))
|
|
{
|
|
Sensor readsensor = ipmi_read_sensor_from_ctx(ctx);
|
|
|
|
for(Sensor& sensor : sensors)
|
|
{
|
|
if(sensor.id == readsensor.id)
|
|
sensor = readsensor;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
ipmi_monitoring_ctx_t init_ipmi_monitoring()
|
|
{
|
|
int errnum;
|
|
int ret = ipmi_monitoring_init(/*IPMI_MONITORING_FLAGS_DEBUG*/ 0, &errnum);
|
|
if(ret < 0)
|
|
{
|
|
std::cerr<<"Could not init ipmi "<<ipmi_monitoring_ctx_strerror(errnum)<<'\n';
|
|
return NULL;
|
|
}
|
|
|
|
ipmi_monitoring_ctx_t ctx = ipmi_monitoring_ctx_create();
|
|
if(!ctx)
|
|
{
|
|
std::cerr<<"failed to create montioring context\n";
|
|
return NULL;
|
|
}
|
|
|
|
return ctx;
|
|
}
|
|
|
|
ipmi_ctx_t ipmi_open_context()
|
|
{
|
|
ipmi_ctx_t ctx = ipmi_ctx_create();
|
|
if(!ctx)
|
|
{
|
|
std::cerr<<"Could not allocae raw context\n";
|
|
return nullptr;
|
|
}
|
|
|
|
ipmi_driver_type_t driver = IPMI_DEVICE_OPENIPMI;
|
|
int ret = ipmi_ctx_find_inband(ctx, &driver, false, 0, 0, nullptr, 0, 0);
|
|
if(ret < 0)
|
|
{
|
|
std::cerr<<"Could not create raw context "<<ipmi_ctx_errormsg(ctx)<<'\n';
|
|
ipmi_ctx_destroy(ctx);
|
|
return nullptr;
|
|
}
|
|
return ctx;
|
|
}
|
|
|
|
bool ipmi_set_fan_group(ipmi_ctx_t raw_ctx, uint8_t group, double speed)
|
|
{
|
|
char converted_speed = std::max(std::min(static_cast<char>(100), static_cast<char>(speed*100)), static_cast<char>(0));
|
|
char command[] = {0x70, 0x66, 0x01, static_cast<char>(group), converted_speed};
|
|
char bytesrx[IPMI_RAW_MAX_ARGS] = {0};
|
|
int rxlen = ipmi_cmd_raw(raw_ctx, 0, 0x30, command, sizeof(command), bytesrx, IPMI_RAW_MAX_ARGS);
|
|
if(rxlen < 0)
|
|
{
|
|
std::cerr<<"Raw write to ipmi failed with: "<<ipmi_ctx_errormsg(raw_ctx);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|