metal/mtce-common/src/common/pgdbUtil.cpp.OBS

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) ;
}