mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-11 04:58:16 +03:00
Feature #3264: New method VMPool::calculate_showback
This commit is contained in:
parent
cc1dc8cb70
commit
68bac3a897
@ -82,6 +82,17 @@ public:
|
||||
*/
|
||||
int xpath(int& value, const char * xpath_expr, const int& def);
|
||||
|
||||
/**
|
||||
* Gets and sets a xpath attribute, if the attribute is not found a default
|
||||
* is used
|
||||
* @param value to set
|
||||
* @param xpath_expr of the xml element
|
||||
* @param def default value if the element is not found
|
||||
*
|
||||
* @return -1 if default was set
|
||||
*/
|
||||
int xpath(float& value, const char * xpath_expr, const float& def);
|
||||
|
||||
/**
|
||||
* Gets and sets a xpath attribute, if the attribute is not found a default
|
||||
* is used
|
||||
|
@ -1517,10 +1517,12 @@ private:
|
||||
ostringstream oss_vm(VirtualMachine::db_bootstrap);
|
||||
ostringstream oss_monit(VirtualMachine::monit_db_bootstrap);
|
||||
ostringstream oss_hist(History::db_bootstrap);
|
||||
ostringstream oss_showback(VirtualMachine::showback_db_bootstrap);
|
||||
|
||||
rc = db->exec(oss_vm);
|
||||
rc += db->exec(oss_monit);
|
||||
rc += db->exec(oss_hist);
|
||||
rc += db->exec(oss_showback);
|
||||
|
||||
return rc;
|
||||
};
|
||||
@ -1714,6 +1716,12 @@ protected:
|
||||
|
||||
static const char * monit_db_bootstrap;
|
||||
|
||||
static const char * showback_table;
|
||||
|
||||
static const char * showback_db_names;
|
||||
|
||||
static const char * showback_db_bootstrap;
|
||||
|
||||
/**
|
||||
* Reads the Virtual Machine (identified with its OID) from the database.
|
||||
* @param db pointer to the db
|
||||
|
@ -260,6 +260,12 @@ public:
|
||||
return dump_monitoring(oss, filter.str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes all the history records, and stores the monthly cost for each
|
||||
* VM
|
||||
*/
|
||||
void calculate_showback();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Factory method to produce VM objects
|
||||
|
@ -115,6 +115,16 @@ const char * VirtualMachine::monit_db_bootstrap = "CREATE TABLE IF NOT EXISTS "
|
||||
"vm_monitoring (vmid INTEGER, last_poll INTEGER, body MEDIUMTEXT, "
|
||||
"PRIMARY KEY(vmid, last_poll))";
|
||||
|
||||
|
||||
const char * VirtualMachine::showback_table = "vm_showback";
|
||||
|
||||
const char * VirtualMachine::showback_db_names = "vmid, year, month, body";
|
||||
|
||||
const char * VirtualMachine::showback_db_bootstrap =
|
||||
"CREATE TABLE IF NOT EXISTS vm_showback "
|
||||
"(vmid INTEGER, year INTEGER, month INTEGER, body MEDIUMTEXT, "
|
||||
"PRIMARY KEY(vmid, year, month))";
|
||||
|
||||
const char * VirtualMachine::NO_NIC_DEFAULTS[] = {"NETWORK_ID", "NETWORK",
|
||||
"NETWORK_UID", "NETWORK_UNAME"};
|
||||
|
||||
|
@ -413,3 +413,210 @@ int VirtualMachinePool::dump_monitoring(
|
||||
|
||||
return PoolSQL::dump(oss, "MONITORING_DATA", cmd);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachinePool::calculate_showback()
|
||||
{
|
||||
vector<xmlNodePtr> nodes;
|
||||
vector<xmlNodePtr>::iterator node_it;
|
||||
|
||||
vector<time_t> showback_slots;
|
||||
vector<time_t>::iterator slot_it;
|
||||
|
||||
// map<vid, map<month, total_cost> >
|
||||
map<int, map<time_t, float> > vm_cost;
|
||||
map<int, map<time_t, float> >::iterator vm_it;
|
||||
map<time_t, float>::iterator vm_month_it;
|
||||
|
||||
time_t start_time;
|
||||
time_t end_time;
|
||||
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
ostringstream body;
|
||||
char * sql_body;
|
||||
|
||||
int vid;
|
||||
int h_stime;
|
||||
int h_etime;
|
||||
float cpu_cost;
|
||||
float mem_cost;
|
||||
float cpu;
|
||||
int mem;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Set start and end times for the window to process
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// TODO: min and max: from params, or absolute from SQL min(stime) from history
|
||||
start_time = 1405395340;
|
||||
end_time = time(0);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Get accounting history records
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
rc = dump_acct(oss, "", start_time, end_time);
|
||||
|
||||
ObjectXML xml(oss.str());
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Create the monthly time slots
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Reset stime to 1st of month, 00:00
|
||||
tm tmp_tm = *localtime(&start_time);
|
||||
|
||||
tmp_tm.tm_sec = 0;
|
||||
tmp_tm.tm_min = 0;
|
||||
tmp_tm.tm_hour = 0;
|
||||
tmp_tm.tm_mday = 1;
|
||||
|
||||
time_t tmp_t = mktime(&tmp_tm);
|
||||
|
||||
while(tmp_t < end_time)
|
||||
{
|
||||
showback_slots.push_back(tmp_t);
|
||||
|
||||
tmp_tm.tm_mon++;
|
||||
tmp_t = mktime(&tmp_tm);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process the history records
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
rc = xml.get_nodes("/HISTORY_RECORDS/HISTORY", nodes);
|
||||
|
||||
for ( node_it = nodes.begin(); node_it != nodes.end(); node_it++ )
|
||||
{
|
||||
ObjectXML history(*node_it);
|
||||
|
||||
history.xpath(vid, "/HISTORY/OID", -1);
|
||||
|
||||
history.xpath(h_stime, "/HISTORY/STIME", 0);
|
||||
history.xpath(h_etime, "/HISTORY/ETIME", 0);
|
||||
|
||||
history.xpath(cpu, "/HISTORY/VM/TEMPLATE/CPU", 0);
|
||||
history.xpath(mem, "/HISTORY/VM/TEMPLATE/MEMORY", 0);
|
||||
|
||||
// TODO: cpu/mem cost should be moved to TEMPLATE
|
||||
history.xpath(cpu_cost, "/HISTORY/VM/USER_TEMPLATE/CPU_COST", 0);
|
||||
history.xpath(mem_cost, "/HISTORY/VM/USER_TEMPLATE/MEMORY_COST", 0);
|
||||
|
||||
// TODO debug
|
||||
/*=====================================================================
|
||||
ostringstream st;
|
||||
|
||||
int seq;
|
||||
history.xpath(seq, "/HISTORY/SEQ", -1);
|
||||
|
||||
st << "VM " << vid << " SEQ " << seq << endl
|
||||
<< "h_stime " << h_stime << endl
|
||||
<< "h_etime " << h_etime << endl
|
||||
<< "cpu_cost " << cpu_cost << endl
|
||||
<< "mem_cost " << mem_cost << endl
|
||||
<< "cpu " << cpu << endl
|
||||
<< "mem " << mem;
|
||||
|
||||
NebulaLog::log("SHOWBACK", Log::DEBUG, st);
|
||||
//====================================================================*/
|
||||
|
||||
for ( slot_it = showback_slots.begin(); slot_it != showback_slots.end()-1; slot_it++ )
|
||||
{
|
||||
time_t t = *slot_it;
|
||||
time_t t_next = *(slot_it+1);
|
||||
|
||||
if( (h_etime > t || h_etime == 0) &&
|
||||
(h_stime != 0 && h_stime <= t_next) ) {
|
||||
|
||||
time_t stime = t;
|
||||
if(h_stime != 0){
|
||||
stime = (t < h_stime) ? h_stime : t; //max(t, h_stime);
|
||||
}
|
||||
|
||||
time_t etime = t_next;
|
||||
if(h_etime != 0){
|
||||
etime = (t_next < h_etime) ? t_next : h_etime; //min(t_next, h_etime);
|
||||
}
|
||||
|
||||
int n_hours = difftime(etime, stime) / 60 / 60;
|
||||
|
||||
int cost = 0;
|
||||
|
||||
cost += cpu_cost * cpu * n_hours;
|
||||
cost += mem_cost * mem * n_hours;
|
||||
|
||||
// Add to vm time slot.
|
||||
map<time_t, float>& total_cost = vm_cost[vid];
|
||||
|
||||
if(total_cost.count(t) == 0)
|
||||
{
|
||||
total_cost[t] = 0;
|
||||
}
|
||||
|
||||
total_cost[t] += cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml.free_nodes(nodes);
|
||||
|
||||
// Write to DB
|
||||
|
||||
for ( vm_it = vm_cost.begin(); vm_it != vm_cost.end(); vm_it++ )
|
||||
{
|
||||
map<time_t, float>& total_cost = vm_it->second;
|
||||
|
||||
for ( vm_month_it = total_cost.begin(); vm_month_it != total_cost.end(); vm_month_it++ )
|
||||
{
|
||||
tm tmp_tm = *localtime(&vm_month_it->first);
|
||||
|
||||
body.str("");
|
||||
|
||||
// TODO: truncate float values to 2 decimals?
|
||||
|
||||
body << "<SHOWBACK>"
|
||||
<< "<VMID>" << vm_it->first << "</VMID>"
|
||||
<< "<YEAR>" << tmp_tm.tm_year + 1900 << "</YEAR>"
|
||||
<< "<MONTH>" << tmp_tm.tm_mon + 1 << "</MONTH>"
|
||||
<< "<COST>" << vm_month_it->second << "</COST>"
|
||||
<< "</SHOWBACK>";
|
||||
|
||||
oss.str("");
|
||||
|
||||
sql_body = db->escape_str(body.str().c_str());
|
||||
|
||||
if ( sql_body == 0 )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
oss << "REPLACE INTO " << VirtualMachine::showback_table
|
||||
<< " ("<< VirtualMachine::showback_db_names <<") VALUES ("
|
||||
<< vm_it->first << ","
|
||||
<< tmp_tm.tm_year + 1900 << ","
|
||||
<< tmp_tm.tm_mon + 1 << ","
|
||||
<< "'" << sql_body << "')";
|
||||
|
||||
db->free_str(sql_body);
|
||||
|
||||
rc = db->exec(oss);
|
||||
|
||||
|
||||
// TODO: debug
|
||||
/*=================================================================
|
||||
ostringstream st;
|
||||
|
||||
st << "VM " << vm_it->first
|
||||
<< " cost for Y " << tmp_tm.tm_year + 1900
|
||||
<< " M " << tmp_tm.tm_mon + 1
|
||||
<< " COST " << vm_month_it->second << " €";
|
||||
|
||||
NebulaLog::log("SHOWBACK", Log::DEBUG, st);
|
||||
//================================================================*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +188,39 @@ int ObjectXML::xpath(int& value, const char * xpath_expr, const int& def)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ObjectXML::xpath(float& value, const char * xpath_expr, const float& def)
|
||||
{
|
||||
vector<string> values;
|
||||
int rc = 0;
|
||||
|
||||
values = (*this)[xpath_expr];
|
||||
|
||||
if (values.empty() == true)
|
||||
{
|
||||
value = def;
|
||||
rc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
istringstream iss;
|
||||
|
||||
iss.str(values[0]);
|
||||
|
||||
iss >> dec >> value;
|
||||
|
||||
if (iss.fail() == true)
|
||||
{
|
||||
value = def;
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ObjectXML::xpath(unsigned int& value, const char * xpath_expr,
|
||||
const unsigned int& def)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user