From a5aa72359aba04c54cfe1cd56e453624b91549a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 6 Nov 2014 18:15:29 +0100 Subject: [PATCH] Feature #3264: calculate-showback uses month,year And lots of bugs fixed --- include/VirtualMachinePool.h | 18 ++- src/cli/one_helper/oneacct_helper.rb | 2 +- src/cli/onevm | 21 ++- .../ruby/opennebula/virtual_machine_pool.rb | 24 ++-- src/rm/RequestManagerVirtualMachine.cc | 9 +- src/vm/VirtualMachinePool.cc | 127 ++++++++++++++---- 6 files changed, 154 insertions(+), 47 deletions(-) diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index 43ddda2767..34101689b7 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -286,14 +286,20 @@ public: /** * Processes all the history records, and stores the monthly cost for each * VM - * @param start_time Time to start processing. This date will be reset to - * the first day of the month, at 00:00 - * @param end_time Time to stop processing. The data will actually be - * processed up to the month before this date. + * @param start_month First month (+year) to process. January is 1. + * Use -1 to unset + * @param start_year First year (+month) to process. e.g. 2014. + * Use -1 to unset + * @param end_month Last month (+year) to process. January is 1. + * Use -1 to unset + * @param end_year Last year (+month) to process. e.g. 2014. + * Use -1 to unset */ void calculate_showback( - time_t start_time, - time_t end_time); + int start_month, + int start_year, + int end_month, + int end_year); private: /** diff --git a/src/cli/one_helper/oneacct_helper.rb b/src/cli/one_helper/oneacct_helper.rb index 4b102cde37..5822318978 100644 --- a/src/cli/one_helper/oneacct_helper.rb +++ b/src/cli/one_helper/oneacct_helper.rb @@ -187,7 +187,7 @@ class AcctHelper < OpenNebulaHelper::OneHelper d["YEAR"] end - column :HOURS, "Hours", :size=>5 do |d| + column :HOURS, "Hours", :size=>6 do |d| d["HOURS"] end diff --git a/src/cli/onevm b/src/cli/onevm index 035d5535d2..9c0dc92e38 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -857,10 +857,25 @@ cmd=CommandParser::CmdParser.new(ARGV) do command :"calculate-showback", calculate_showback_desc, :options => [START_TIME, END_TIME] do - start_time = options[:start_time] ? options[:start_time].to_i : -1 - end_time = options[:end_time] ? options[:end_time].to_i : -1 + start_month = -1 + start_year = -1 - rc = OpenNebula::VirtualMachinePool.new(helper.client).calculate_showback(start_time, end_time) + if (options[:start_time]) + start_month = options[:start_time].month + start_year = options[:start_time].year + end + + end_month = -1 + end_year = -1 + + if (options[:end_time]) + end_month = options[:end_time].month + end_year = options[:end_time].year + end + + + rc = OpenNebula::VirtualMachinePool.new(helper.client). + calculate_showback(start_month, start_year, end_month, end_year) if OpenNebula.is_error?(rc) warn rc.message diff --git a/src/oca/ruby/opennebula/virtual_machine_pool.rb b/src/oca/ruby/opennebula/virtual_machine_pool.rb index 5e80d06999..74861aab9e 100644 --- a/src/oca/ruby/opennebula/virtual_machine_pool.rb +++ b/src/oca/ruby/opennebula/virtual_machine_pool.rb @@ -167,18 +167,22 @@ module OpenNebula # Processes all the history records, and stores the monthly cost for # each VM # - # @param [Integer] - # @param [Integer] start_time Time to start processing. This date will - # be reset to the first day of the month, at 00:00 - # @param [Integer] end_time Time to stop processing. The data will - # actually be processed up to the month before this date. - def calculate_showback(start_time, end_time) - start_time ||= -1 - end_time ||= -1 + # @param [Integer] start_month First month (+year) to process. January is 1. + # Use -1 to unset + # @param [Integer] start_year First year (+month) to process. e.g. 2014. + # Use -1 to unset + # @param [Integer] end_month Last month (+year) to process. January is 1. + # Use -1 to unset + # @param [Integer] end_year Last year (+month) to process. e.g. 2014. + # Use -1 to unset + def calculate_showback(start_month, start_year, end_month, end_year) + start_month ||= -1 + start_year ||= -1 + end_month ||= -1 + end_year ||= -1 return @client.call(VM_POOL_METHODS[:calculate_showback], - start_time, - end_time) + start_month, start_year, end_month, end_year) end # Retrieves the accounting data for all the VMs in the pool diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 53c04e7dfd..9057684a06 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -2224,8 +2224,10 @@ void VirtualMachinePoolCalculateShowback::request_execute( xmlrpc_c::paramList const& paramList, RequestAttributes& att) { - int time_start = xmlrpc_c::value_int(paramList.getInt(1)); - int time_end = xmlrpc_c::value_int(paramList.getInt(2)); + int start_month = xmlrpc_c::value_int(paramList.getInt(1)); + int start_year = xmlrpc_c::value_int(paramList.getInt(2)); + int end_month = xmlrpc_c::value_int(paramList.getInt(3)); + int end_year = xmlrpc_c::value_int(paramList.getInt(4)); ostringstream oss; string where; @@ -2240,7 +2242,8 @@ void VirtualMachinePoolCalculateShowback::request_execute( return; } - (static_cast(pool))->calculate_showback(time_start, time_end); + (static_cast(pool))->calculate_showback( + start_month, start_year, end_month, end_year); // TODO: return value? success_response("", att); diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 8ffdadc92f..6a4a41882e 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -472,7 +472,31 @@ int VirtualMachinePool::min_stime_cb(void * _min_stime, int num, char **values, return 0; } -void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) +// TODO: DEBUG +//============================================================================== + +string put_time(tm tmp_tm) +{ + ostringstream oss; + + oss << tmp_tm.tm_mday << "/" << tmp_tm.tm_mon+1 << "/" << tmp_tm.tm_year+1900 + << " " << tmp_tm.tm_hour << ":" << tmp_tm.tm_min << ":" << tmp_tm.tm_sec; + + return oss.str(); +} + +string put_time(time_t t) +{ + tm tmp_tm = *localtime(&t); + return put_time(tmp_tm); +} +//============================================================================== + +void VirtualMachinePool::calculate_showback( + int start_month, + int start_year, + int end_month, + int end_year) { vector nodes; vector::iterator node_it; @@ -492,6 +516,7 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) ostringstream body; char * sql_body; + tm tmp_tm; int vid; int h_stime; int h_etime; @@ -500,19 +525,33 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) float cpu; int mem; + // TODO: debug + //================================================================= + ostringstream debug; + //================================================================= + //-------------------------------------------------------------------------- // Set start and end times for the window to process //-------------------------------------------------------------------------- - if (end_time == -1) + time_t start_time = time(0); + time_t end_time = time(0); + + if (start_month != -1 && start_year != -1) { - end_time = time(0); + // First day of the given month + tmp_tm.tm_sec = 0; + tmp_tm.tm_min = 0; + tmp_tm.tm_hour = 0; + tmp_tm.tm_mday = 1; + tmp_tm.tm_mon = start_month - 1; + tmp_tm.tm_year = start_year - 1900; + tmp_tm.tm_isdst = -1; + + start_time = mktime(&tmp_tm); } - - if (start_time == -1) + else { - start_time = time(0); - // Set start time to the lowest stime from the history records set_callback(static_cast(&VirtualMachinePool::min_stime_cb), @@ -525,6 +564,25 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) unset_callback(); } + if (end_month != -1 && end_year != -1) + { + // First day of the next month + tmp_tm.tm_sec = 0; + tmp_tm.tm_min = 0; + tmp_tm.tm_hour = 0; + tmp_tm.tm_mday = 1; + tmp_tm.tm_mon = end_month; + tmp_tm.tm_year = end_year - 1900; + tmp_tm.tm_isdst = -1; + + time_t end_time_tmp = mktime(&tmp_tm); + + if (end_time_tmp < end_time) + { + end_time = end_time_tmp; + } + } + //-------------------------------------------------------------------------- // Get accounting history records //-------------------------------------------------------------------------- @@ -539,12 +597,13 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) //-------------------------------------------------------------------------- // Reset stime to 1st of month, 00:00 - tm tmp_tm = *localtime(&start_time); + 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; + tmp_tm.tm_isdst = -1; time_t tmp_t = mktime(&tmp_tm); @@ -552,10 +611,30 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) { showback_slots.push_back(tmp_t); + tmp_tm.tm_sec = 0; + tmp_tm.tm_min = 0; + tmp_tm.tm_hour = 0; + tmp_tm.tm_mday = 1; tmp_tm.tm_mon++; + tmp_tm.tm_isdst = -1; + tmp_t = mktime(&tmp_tm); } + // Extra slot that won't be used. Is needed only to calculate the time + // for the second-to-last slot + showback_slots.push_back(end_time); + + // TODO: debug + //*================================================================= + for ( slot_it = showback_slots.begin(); slot_it != showback_slots.end(); slot_it++ ) + { + debug.str(""); + debug << "Slot: " << put_time(*slot_it); + NebulaLog::log("SHOWBACK", Log::DEBUG, debug); + } + //================================================================*/ + //-------------------------------------------------------------------------- // Process the history records //-------------------------------------------------------------------------- @@ -580,12 +659,11 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) // TODO debug /*===================================================================== - ostringstream st; - int seq; history.xpath(seq, "/HISTORY/SEQ", -1); - st << "VM " << vid << " SEQ " << seq << endl + debug.str(""); + debug << "VM " << vid << " SEQ " << seq << endl << "h_stime " << h_stime << endl << "h_etime " << h_etime << endl << "cpu_cost " << cpu_cost << endl @@ -593,7 +671,7 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) << "cpu " << cpu << endl << "mem " << mem; - NebulaLog::log("SHOWBACK", Log::DEBUG, st); + NebulaLog::log("SHOWBACK", Log::DEBUG, debug); //====================================================================*/ for ( slot_it = showback_slots.begin(); slot_it != showback_slots.end()-1; slot_it++ ) @@ -614,9 +692,9 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) etime = (t_next < h_etime) ? t_next : h_etime; //min(t_next, h_etime); } - int n_hours = difftime(etime, stime) / 60 / 60; + float n_hours = difftime(etime, stime) / 60 / 60; - int cost = 0; + float cost = 0; cost += cpu_cost * cpu * n_hours; cost += mem_cost * mem * n_hours; @@ -668,11 +746,12 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) vm->unlock(); } - tm tmp_tm = *localtime(&vm_month_it->first); + tmp_tm = *localtime(&vm_month_it->first); body.str(""); - // TODO: truncate float values to 2 decimals? + string cost = one_util::float_to_str(vm_month_it->second.first); + string hours = one_util::float_to_str(vm_month_it->second.second); body << "" << "" << vmid << "" @@ -683,8 +762,8 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) << "" << gname << "" << "" << tmp_tm.tm_year + 1900 << "" << "" << tmp_tm.tm_mon + 1 << "" - << "" << vm_month_it->second.first << "" - << "" << vm_month_it->second.second << "" + << "" << cost << "" + << "" << hours << "" << ""; oss.str(""); @@ -709,16 +788,16 @@ void VirtualMachinePool::calculate_showback(time_t start_time, time_t end_time) // TODO: debug - /*================================================================= - ostringstream st; + //*================================================================= + debug.str(""); - st << "VM " << vm_it->first + debug << "VM " << vm_it->first << " cost for Y " << tmp_tm.tm_year + 1900 << " M " << tmp_tm.tm_mon + 1 - << " COST " << vm_month_it->second.first << " €" - << " HOURS " << vm_month_it->second.second; + << " COST " << cost << " €" + << " HOURS " << hours; - NebulaLog::log("SHOWBACK", Log::DEBUG, st); + NebulaLog::log("SHOWBACK", Log::DEBUG, debug); //================================================================*/ } }