Skip to content

Commit

Permalink
Merge pull request #15565 from lpichler/optionable_allocated_calculation
Browse files Browse the repository at this point in the history
Add average calculation for allocated costs and metrics optionally in chargeback
  • Loading branch information
gtanzillo authored Jul 21, 2017
2 parents ba2e326 + 02a9a47 commit d7be775
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 7 deletions.
4 changes: 2 additions & 2 deletions app/models/chargeable_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ class ChargeableField < ApplicationRecord
validates :metric, :uniqueness => true, :presence => true
validates :group, :source, :presence => true

def measure(consumption)
def measure(consumption, options)
return 1.0 if fixed?
return 0 if consumption.none?(metric)
return consumption.max(metric) if allocated?
return consumption.send(options.method_for_allocated_metrics, metric) if allocated?
return consumption.avg(metric) if used?
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/chargeback.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def calculate_costs(consumption, rates)

rates.each do |rate|
rate.rate_details_relevant_to(relevant_fields).each do |r|
r.charge(relevant_fields, consumption).each do |field, value|
r.charge(relevant_fields, consumption, @options).each do |field, value|
next unless self.class.attribute_names.include?(field)
self[field] = (self[field] || 0) + value
end
Expand Down
13 changes: 13 additions & 0 deletions app/models/chargeback/report_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,24 @@ class Chargeback
:userid,
:ext_options,
:include_metrics, # enable charging allocated resources with C & U
:method_for_allocated_metrics
) do
def self.new_from_h(hash)
new(*hash.values_at(*members))
end

ALLOCATED_METHODS_WHITELIST = %i(max avg).freeze

def method_for_allocated_metrics
method = self[:method_for_allocated_metrics] || :max

unless ALLOCATED_METHODS_WHITELIST.include?(method)
raise "Invalid method for allocated calculations #{method}"
end

method
end

# include_metrics = nil is default value(true)
def include_metrics?
include_metrics.nil? || include_metrics
Expand Down
8 changes: 4 additions & 4 deletions app/models/chargeback_rate_detail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ class ChargebackRateDetail < ApplicationRecord
'yearly' => _('Yearly')
}.freeze

def charge(relevant_fields, consumption)
def charge(relevant_fields, consumption, options)
result = {}
if (relevant_fields & [metric_key, cost_keys[0]]).present?
metric_value, cost = metric_and_cost_by(consumption)
metric_value, cost = metric_and_cost_by(consumption, options)
if !consumption.chargeback_fields_present && chargeable_field.fixed?
cost = 0
end
Expand Down Expand Up @@ -162,8 +162,8 @@ def gratis?
chargeback_tiers.all?(&:gratis?)
end

def metric_and_cost_by(consumption)
metric_value = chargeable_field.measure(consumption)
def metric_and_cost_by(consumption, options)
metric_value = chargeable_field.measure(consumption, options)
[metric_value, hourly_cost(metric_value, consumption) * consumption.consumed_hours_in_interval]
end

Expand Down
21 changes: 21 additions & 0 deletions spec/models/chargeback_vm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,27 @@
end
end

context "Monthly" do
context "calculation of allocated metrics by average" do
let(:start_time) { report_run_time - 17.hours }
let(:finish_time) { report_run_time - 14.hours }
let(:options) { base_options.merge(:interval => 'monthly', :method_for_allocated_metrics => :avg) }

before do
mid_point = month_beginning + 10.days
add_metric_rollups_for(@vm1, month_beginning...mid_point, 1.hour, metric_rollup_params)
add_metric_rollups_for(@vm1, mid_point...month_end, 1.hour, metric_rollup_params.merge!(:derived_vm_numvcpus => 2))
end

subject { ChargebackVm.build_results_for_report_ChargebackVm(options).first.first }

it "calculates cpu allocated metric" do
expect(subject.cpu_allocated_metric).to eq(1.6666666666666667)
expect(subject.cpu_allocated_cost).to eq(1200) # ?
end
end
end

context "Monthly" do
let(:options) { base_options.merge(:interval => 'monthly') }
before do
Expand Down

0 comments on commit d7be775

Please sign in to comment.