428 lines
16 KiB
Plaintext
428 lines
16 KiB
Plaintext
/*
|
|
* Copyright (c) 2015 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* Wind River CGTS Platform PostgreSQL Database Access Utility module.
|
|
**/
|
|
|
|
#include "pgdbClass.h"
|
|
#include "jsonUtil.h"
|
|
|
|
#define CONF_FILE ((const char *)("/etc/ceilometer/ceilometer.conf"))
|
|
|
|
/* Cleanup exit handler */
|
|
void daemon_exit ( void )
|
|
{
|
|
exit (0);
|
|
}
|
|
|
|
void daemon_sigchld_hdlr ( void )
|
|
{
|
|
dlog("Received SIGCHLD ...\n");
|
|
}
|
|
|
|
|
|
static daemon_config_type _config ;
|
|
static opts_type * opts_ptr ;
|
|
|
|
|
|
/* Ceilometer config read */
|
|
int _config_handler ( void * user,
|
|
const char * section,
|
|
const char * name,
|
|
const char * value)
|
|
{
|
|
daemon_config_type* config_ptr = (daemon_config_type*)user;
|
|
if (MATCH("database", "connection"))
|
|
{
|
|
config_ptr->ceilometer_url = strdup(value);
|
|
if ( config_ptr->ceilometer_url )
|
|
{
|
|
ilog ("Ceilometer URL: %s\n", config_ptr->ceilometer_url );
|
|
}
|
|
}
|
|
return (PASS);
|
|
}
|
|
|
|
|
|
|
|
daemon_config_type * daemon_get_cfg_ptr (void)
|
|
{
|
|
return (&_config);
|
|
}
|
|
|
|
int daemon_configure ( void )
|
|
{
|
|
int rc = PASS ;
|
|
opts_ptr = daemon_get_opts_ptr();
|
|
|
|
daemon_files_init ();
|
|
|
|
ilog("Config File : %s\n", CONF_FILE );
|
|
if (ini_parse ( CONF_FILE, _config_handler, &_config ) < 0)
|
|
{
|
|
elog("Failed to load '%s'\n", CONF_FILE );
|
|
}
|
|
return (rc) ;
|
|
}
|
|
|
|
int daemon_init ( string iface , string nodetype )
|
|
{
|
|
UNUSED(iface);
|
|
UNUSED(nodetype);
|
|
|
|
daemon_configure ();
|
|
|
|
// get_debug_options ( CONF_FILE, &_config );
|
|
return (PASS);
|
|
}
|
|
|
|
pgdbClass dbConn ;
|
|
|
|
#define EXACT_MATCH (0)
|
|
#define POSITION_ZERO (0)
|
|
|
|
/************************************************************************************
|
|
*
|
|
* Ceilometer Database: Sensor Value Correlation
|
|
*
|
|
* 1. The METER table lists valid meter_ids
|
|
* - hardware.ipmi.*
|
|
*
|
|
* 2. The RESOURCE table lists all the sensors based on internal id
|
|
* - hostname-{sensor number-}<sensor name>_<???>
|
|
* ... nokia-2-temp_psu2_(0x94)
|
|
* ... controller-1-37-system_board_(0x33)
|
|
*
|
|
* 3. The SAMPLE table lists sample data as volume based on specified unit type
|
|
* - sensor resource lookup
|
|
* ... SAMPLE:resource_id == RESOURCE:internal_id
|
|
* - SAMPLE:meter_id is used to know it is a valid meter to monitor
|
|
* ... METER:id is valid if METER:name has hardware.ipmi in it
|
|
* ... hardware.ipmi.current
|
|
*
|
|
**************************************************************************************/
|
|
|
|
/* Valid meter ids */
|
|
#define PQ_TABLE_INDEX__METER_ID (0)
|
|
#define PQ_TABLE_INDEX__METER_NAME (1)
|
|
#define PQ_TABLE_INDEX__METER_TYPE (2)
|
|
#define PQ_TABLE_INDEX__METER_UNIT (3)
|
|
|
|
#define VALID_METER_PREFIX ((const char *)("hardware.ipmi."))
|
|
typedef struct
|
|
{
|
|
int id ;
|
|
string scope; /* ipmi - VALID_METER_PREFIX */
|
|
string name ;
|
|
string unit ;
|
|
string type ;
|
|
} hwmon_meter_type ;
|
|
std::map<int, hwmon_meter_type> global_meter_list ;
|
|
|
|
#define PQ_TABLE_INDEX__RESOURCE__INTERNAL_ID (0)
|
|
#define PQ_TABLE_INDEX__RESOURCE__RESOURCE_ID (1)
|
|
#define PQ_TABLE_INDEX__RESOURCE__METADATA (2)
|
|
typedef struct
|
|
{
|
|
int id ;
|
|
string hostname ;
|
|
string sensorname ;
|
|
string somevalue ;
|
|
} hwmon_resource_type ;
|
|
std::map<int, hwmon_resource_type> global_sensor_list ;
|
|
std::map<int, hwmon_resource_type> excluded_resource_list ;
|
|
|
|
// mtc_key_value_type ipmi_sensor_group
|
|
void daemon_service_run ( void )
|
|
{
|
|
int rc = PASS ;
|
|
pgdbUtil_get_version ();
|
|
if ( ! _config.ceilometer_url )
|
|
{
|
|
rc = FAIL_NULL_POINTER ;
|
|
}
|
|
else
|
|
{
|
|
PGresult * pqResult_ptr ;
|
|
string pqCommand_str;
|
|
|
|
ilog ("URI:%s\n", _config.ceilometer_url );
|
|
|
|
// check_connection:
|
|
for ( ; ; )
|
|
{
|
|
if ( dbConn.pg.connected == false )
|
|
{
|
|
elog ("not connected\n");
|
|
sleep (2);
|
|
dbConn.connect ( _config.ceilometer_url );
|
|
continue ;
|
|
// goto check_connection ;
|
|
}
|
|
else if ( dbConn.monitor() != PASS )
|
|
{
|
|
sleep (2);
|
|
continue ;
|
|
}
|
|
global_meter_list.clear();
|
|
|
|
// ilog ("max number of meters allowed: %zu\n", global_meter_list.max_size());
|
|
|
|
/* PARSE METER - hwmon_get_ipmi_sensor_meters () ; */
|
|
pqCommand_str = "SELECT * FROM meter" ;
|
|
pqResult_ptr = PQexec ( dbConn.pg.conn, pqCommand_str.data());
|
|
|
|
// +----+-------------------------------------+------------+---------
|
|
// | id | name | type | unit
|
|
// +----+-------------------------------------+------------+---------
|
|
// | 1 | hardware.ipmi.current | gauge | W
|
|
// | 2 | hardware.ipmi.temperature | gauge | C
|
|
// | 3 | hardware.ipmi.fan | gauge | percent
|
|
|
|
if ( PQresultStatus( pqResult_ptr ) == PGRES_TUPLES_OK)
|
|
{
|
|
hwmon_meter_type meter ;
|
|
meter.scope = VALID_METER_PREFIX ;
|
|
int rows = PQntuples(pqResult_ptr);
|
|
for(int i=0; i<rows; i++)
|
|
{
|
|
string
|
|
meter_id = PQgetvalue(pqResult_ptr, i, PQ_TABLE_INDEX__METER_ID );
|
|
meter.name = PQgetvalue(pqResult_ptr, i, PQ_TABLE_INDEX__METER_NAME);
|
|
meter.type = PQgetvalue(pqResult_ptr, i, PQ_TABLE_INDEX__METER_TYPE);
|
|
meter.unit = PQgetvalue(pqResult_ptr, i, PQ_TABLE_INDEX__METER_UNIT);
|
|
dlog ("%s %s %s %s\n", meter_id.c_str(), meter.name.c_str(), meter.type.c_str(), meter.unit.c_str() );
|
|
|
|
/* We care abount hardware IPMI gauges */
|
|
if ( meter.type.compare("gauge") == EXACT_MATCH )
|
|
{
|
|
if ( meter.name.find ( meter.scope, POSITION_ZERO ) == POSITION_ZERO )
|
|
{
|
|
/* Ok, this is a valid group ; extract the group name and id */
|
|
meter.name = meter.name.substr(meter.scope.size(), meter.scope.size()+meter.name.size());
|
|
if ( ! (meter_id.size() > sizeof(int)) )
|
|
{
|
|
meter.id = atoi(meter_id.data());
|
|
global_meter_list.insert (std::make_pair(meter.id, meter ));
|
|
dlog3 ("ipmi sensor group %d '%s' (%s:%s)\n",
|
|
meter.id, meter.name.c_str(),
|
|
meter.type.c_str(), meter.unit.c_str());
|
|
}
|
|
}
|
|
}
|
|
} /* end 'meters rows parse' for loop */
|
|
|
|
if ( global_meter_list.size() )
|
|
{
|
|
// ************** Testing *********************
|
|
#define WANT_QUERY_AUTO_ITERATOR_TEST
|
|
|
|
#ifdef WANT_QUERY_DECLARED_ITERATOR_TEST
|
|
/* TEST: Query Meters using declared iterator */
|
|
std::map<int, hwmon_meter_type>::const_iterator global_meter_list_iter = global_meter_list.begin();
|
|
while ( global_meter_list_iter != global_meter_list.end() )
|
|
{
|
|
ilog ("ipmi sensor group %d '%s' (%s:%s)\n",
|
|
global_meter_list_iter->second.id,
|
|
global_meter_list_iter->second.name.c_str(),
|
|
global_meter_list_iter->second.type.c_str(),
|
|
global_meter_list_iter->second.unit.c_str());
|
|
|
|
++global_meter_list_iter ;
|
|
}
|
|
#endif
|
|
|
|
#ifdef WANT_QUERY_AUTO_ITERATOR_TEST
|
|
/* TEST: Loop Over meter List using C++11 auto iterator */
|
|
for ( auto _iter = global_meter_list.begin() ; _iter != global_meter_list.end() ; _iter++ )
|
|
{
|
|
dlog ("ipmi sensor group %d '%s' (%s:%s)\n",
|
|
_iter->second.id,
|
|
_iter->second.name.c_str(),
|
|
_iter->second.type.c_str(),
|
|
_iter->second.unit.c_str());
|
|
}
|
|
#endif
|
|
|
|
#ifdef WANT_FIND_TEST
|
|
/* TEST: Find meters test */
|
|
for ( int i = 0 ; i < 1000 ; i++ )
|
|
{
|
|
global_meter_list_iter = global_meter_list.find(i);
|
|
if ( global_meter_list_iter != global_meter_list.end() )
|
|
{
|
|
ilog ("ipmi sensor group query test - %d:%d '%s' (%s:%s)\n",
|
|
i,
|
|
global_meter_list_iter->second.id,
|
|
global_meter_list_iter->second.name.c_str(),
|
|
global_meter_list_iter->second.type.c_str(),
|
|
global_meter_list_iter->second.unit.c_str());
|
|
}
|
|
}
|
|
#endif
|
|
ilog ( "%zu sensor groups total\n", global_meter_list.size() );
|
|
|
|
|
|
/* PARSE RESOURCE - hwmon_get_ipmi_sensor_list () ; */
|
|
pqCommand_str = "SELECT internal_id,resource_id,resource_metadata FROM resource" ;
|
|
pqResult_ptr = PQexec ( dbConn.pg.conn, pqCommand_str.data());
|
|
|
|
// +-------------+--------------------------------------+-----------------------------+
|
|
// | internal_id | resource_id | resource_metadata
|
|
// | 1 | controller-0-power_meter_(0x40) | {"node": "controller-0"}
|
|
// | 2 | controller-0-26-ilo_zone_(0x26) | {"node": "controller-0"}
|
|
// | 3 | controller-0-fan_2_(0x7) | {"node": "controller-0"}
|
|
|
|
if ( PQresultStatus( pqResult_ptr ) == PGRES_TUPLES_OK)
|
|
{
|
|
hwmon_resource_type resource ;
|
|
|
|
int rows = PQntuples(pqResult_ptr);
|
|
for(int i=0; i<rows; i++)
|
|
{
|
|
bool added = false ;
|
|
string hostname ;
|
|
string internal_id = PQgetvalue(pqResult_ptr, i, PQ_TABLE_INDEX__RESOURCE__INTERNAL_ID);
|
|
string resource_id = PQgetvalue(pqResult_ptr, i, PQ_TABLE_INDEX__RESOURCE__RESOURCE_ID);
|
|
string metadata = PQgetvalue(pqResult_ptr, i, PQ_TABLE_INDEX__RESOURCE__METADATA );
|
|
dlog ("%s %s %s\n", internal_id.c_str(), resource_id.c_str(), metadata.c_str());
|
|
|
|
/* get map key as int version of internal_id */
|
|
if ( ! (internal_id.size() > sizeof(int)) )
|
|
{
|
|
resource.id = atoi(internal_id.data());
|
|
}
|
|
else
|
|
{
|
|
elog ("failed to convert internal_id:%s to integer ; excluded '%s'\n", internal_id.c_str(), resource_id.c_str());
|
|
continue ;
|
|
}
|
|
|
|
/* Add those that have a valid hostname as metadata key:value pair { node: "<hostname>" } */
|
|
|
|
if ( metadata.size() && ( jsonUtil_get_key_val ( (char*)metadata.data(), "node", hostname ) == PASS ))
|
|
{
|
|
resource.hostname = hostname ;
|
|
if ( resource_id.find (hostname, POSITION_ZERO ) == POSITION_ZERO )
|
|
{
|
|
/* Get somevalue */
|
|
resource.somevalue.clear();
|
|
resource.sensorname = resource_id.substr ( hostname.length());
|
|
size_t index = resource.sensorname.find ("_(0x");
|
|
if ( index != std::string::npos )
|
|
{
|
|
resource.somevalue = resource.sensorname.substr (index+1);
|
|
}
|
|
resource.sensorname = resource_id.substr ( hostname.length()+1, index-1 );
|
|
global_sensor_list.insert (std::make_pair(resource.id, resource ));
|
|
added = true ;
|
|
dlog ("added - %s %s\n", hostname.c_str(), resource.sensorname.c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
elog ("no valid metadata node:hostname key value pair (%s) ; excluded %s\n", metadata.c_str(), resource_id.c_str() );
|
|
}
|
|
|
|
if ( added == false )
|
|
{
|
|
resource.hostname = "none" ;
|
|
resource.sensorname = resource_id ;
|
|
resource.somevalue = metadata ;
|
|
excluded_resource_list.insert(std::make_pair(resource.id, resource ));
|
|
}
|
|
} /* end 'resource rows parse' for loop */
|
|
}
|
|
if ( global_sensor_list.size() )
|
|
{
|
|
/* Loop over meter List using C++11 auto iterator */
|
|
for ( auto _iter = global_sensor_list.begin() ; _iter != global_sensor_list.end() ; _iter++ )
|
|
{
|
|
dlog ("%s %d sensor '%s' %s\n",
|
|
_iter->second.hostname.c_str(),
|
|
_iter->second.id,
|
|
_iter->second.sensorname.c_str(),
|
|
_iter->second.somevalue.c_str());
|
|
}
|
|
}
|
|
#ifdef WANT_DISPLAY_EXCLUDED_METERS_LIST
|
|
if ( excluded_resource_list.size() )
|
|
{
|
|
/* Loop over meter List using C++11 auto iterator */
|
|
for ( auto _iter = excluded_resource_list.begin() ; _iter != excluded_resource_list.end() ; _iter++ )
|
|
{
|
|
ilog ("excluded %d '%s' (%s)\n",
|
|
_iter->second.id,
|
|
_iter->second.sensorname.c_str(),
|
|
_iter->second.somevalue.c_str());
|
|
}
|
|
}
|
|
#endif
|
|
ilog ("%zu sensors ; system wide and %zu meter resources excluded\n",
|
|
global_sensor_list.size(),
|
|
excluded_resource_list.size());
|
|
|
|
/* SELECT id,volume,timestamp,meter_id,resource_id FROM sample WHERE timestamp >= '2016-11-22 21:57:45' AND resource_id = 149; */
|
|
/* PARSE RESOURCE - hwmon_get_ipmi_sensor_list () ;
|
|
pqCommand_str = "SELECT internal_id,resource_id,resource_metadata FROM resource" ;
|
|
pqResult_ptr = PQexec ( dbConn.pg.conn, pqCommand_str.data());
|
|
*/
|
|
// +-------------+--------------------------------------+-----------------------------+
|
|
// | internal_id | resource_id | resource_metadata
|
|
// | 1 | controller-0-power_meter_(0x40) | {"node": "controller-0"}
|
|
// | 2 | controller-0-26-ilo_zone_(0x26) | {"node": "controller-0"}
|
|
// | 3 | controller-0-fan_2_(0x7) | {"node": "controller-0"}
|
|
|
|
//if ( PQresultStatus( pqResult_ptr ) == PGRES_TUPLES_OK)
|
|
//{
|
|
|
|
// Query all samples based on the last <audit period>
|
|
// - keep track of sample ID numbers to discard already managed samples
|
|
// for each host
|
|
// for each sensor
|
|
|
|
}
|
|
else
|
|
{
|
|
elog ("no data retrieved for command '%s'\n", pqCommand_str.c_str());
|
|
}
|
|
|
|
PQclear (pqResult_ptr);
|
|
|
|
/* TODO: Group these 2 commands into an _fini proc */
|
|
//PQfinish(dbConn.pg.conn);
|
|
//dbConn.pg.conn = NULL ;
|
|
}
|
|
}
|
|
}
|
|
ilog ("RC:%d\n", rc );
|
|
}
|
|
|
|
/* STUBS */
|
|
|
|
/* Push daemon state to log file */
|
|
void daemon_dump_info ( void )
|
|
{
|
|
daemon_dump_membuf_banner ();
|
|
daemon_dump_membuf();
|
|
}
|
|
|
|
|
|
int daemon_run_testhead ( void )
|
|
{
|
|
return PASS ;
|
|
}
|
|
|
|
|
|
const char * dummy = "empty" ;
|
|
const char * daemon_stream_info ( void )
|
|
{
|
|
return (dummy) ;
|
|
}
|