Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Metering Used Hours to chargeback report #15908

Merged
merged 6 commits into from
Oct 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/models/chargeable_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class ChargeableField < ApplicationRecord
validates :group, :source, :presence => true

def measure(consumption, options)
return consumption.consumed_hours_in_interval if metering?
return 1.0 if fixed?
return 0 if consumption.none?(metric)
return consumption.send(options.method_for_allocated_metrics, metric) if allocated?
Expand All @@ -45,6 +46,10 @@ def cost_keys
'total_cost']
end

def metering?
group == 'metering' && source == 'used'
end

private

def rate_name
Expand Down
2 changes: 2 additions & 0 deletions app/models/chargeback.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class Chargeback < ActsAsArModel
:entity => :binary,
:tag_name => :string,
:fixed_compute_metric => :integer,
:metering_used_metric => :integer,
:metering_used_cost => :float
)

def self.build_results_for_report_chargeback(options)
Expand Down
2 changes: 2 additions & 0 deletions app/models/chargeback_container_image.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ def self.report_col_options
"fixed_cost" => {:grouping => [:total]},
"memory_used_cost" => {:grouping => [:total]},
"memory_used_metric" => {:grouping => [:total]},
"metering_used_metric" => {:grouping => [:total]},
"metering_used_cost" => {:grouping => [:total]},
"net_io_used_cost" => {:grouping => [:total]},
"net_io_used_metric" => {:grouping => [:total]},
"total_cost" => {:grouping => [:total]}
Expand Down
2 changes: 2 additions & 0 deletions app/models/chargeback_container_project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ def self.report_col_options
"fixed_cost" => {:grouping => [:total]},
"memory_used_cost" => {:grouping => [:total]},
"memory_used_metric" => {:grouping => [:total]},
"metering_used_metric" => {:grouping => [:total]},
"metering_used_cost" => {:grouping => [:total]},
"net_io_used_cost" => {:grouping => [:total]},
"net_io_used_metric" => {:grouping => [:total]},
"total_cost" => {:grouping => [:total]}
Expand Down
4 changes: 3 additions & 1 deletion app/models/chargeback_rate_detail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ def gratis?

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]
hourly_cost = hourly_cost(metric_value, consumption)
cost = chargeable_field.metering? ? hourly_cost : hourly_cost * consumption.consumed_hours_in_interval
[metric_value, cost]
end

def first_tier?(tier,tiers)
Expand Down
2 changes: 2 additions & 0 deletions app/models/chargeback_vm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ def self.report_col_options
"memory_cost" => {:grouping => [:total]},
"memory_used_cost" => {:grouping => [:total]},
"memory_used_metric" => {:grouping => [:total]},
"metering_used_cost" => {:grouping => [:total]},
"metering_used_metric" => {:grouping => [:total]},
"net_io_used_cost" => {:grouping => [:total]},
"net_io_used_metric" => {:grouping => [:total]},
"storage_allocated_cost" => {:grouping => [:total]},
Expand Down
5 changes: 5 additions & 0 deletions db/fixtures/chargeable_fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,8 @@
:group: fixed
:source: storage_2
:description: Fixed Storage Cost 2
- :metric: user_metering_hours
:group: metering
:source: used
:description: Metering - Hours Used

10 changes: 10 additions & 0 deletions db/fixtures/chargeback_rates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@
:finish: Infinity
:fixed_rate: 0.0
:variable_rate: 0.0
- :description: Metering - Hours Used
:metric: user_metering_hours
:per_time: hourly
:per_unit: hours
:type_currency: Dollars
:tiers:
- :start: 0
:finish: Infinity
:fixed_rate: 0.0
:variable_rate: 1
- :description: Default
:guid: 7d7aaf20-5214-11df-a888-001d09066d98
:rate_type: Storage
Expand Down
13 changes: 13 additions & 0 deletions db/fixtures/miq_report_formats.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
:memory_used_cost: :currency_precision_2
:memory_allocated_cost: :currency_precision_2
:memory_cost: :currency_precision_2
:metering_used_cost: :currency_precision_2
:storage_used_cost: :currency_precision_2
:storage_allocated_cost: :currency_precision_2
:storage_cost: :currency_precision_2
Expand Down Expand Up @@ -191,6 +192,7 @@
:memory_used_metric: :megabytes_precision_2
:memory_mb: :megabytes
:mem_cpu: :megabytes
:metering_used_metric: :hours
:min_derived_memory_used: :megabytes
:ram_size: :megabytes
:trend_derived_memory_used: :megabytes
Expand Down Expand Up @@ -474,6 +476,17 @@
:delimiter: ","
:precision: 1

:hours:
:description: Hours
:columns:
:sub_types:
- :hours
:function:
:function:
:name: number_with_delimiter
:delimiter: ","
:suffix: ! ' Hours'

:mhz_precision_2:
:description: Megahertz Avg (12.11 Mhz)
:columns:
Expand Down
7 changes: 7 additions & 0 deletions spec/factories/chargeable_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,11 @@
source 'used'
detail_measure { FactoryGirl.build(:chargeback_measure_bytes) }
end

factory :chargeable_field_metering_used, :parent => :chargeable_field do
description 'Metering Used Hours'
metric 'metering_used_hours'
group 'metering'
source 'used'
end
end
1 change: 1 addition & 0 deletions spec/factories/chargeback_rate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
chargeback_rate_detail_memory_allocated
chargeback_rate_detail_memory_used
chargeback_rate_detail_net_io_used
chargeback_rate_detail_metering_used
).each do |factory_name|
chargeback_rate.chargeback_rate_details << FactoryGirl.create(factory_name,
:tiers_with_three_intervals,
Expand Down
4 changes: 4 additions & 0 deletions spec/factories/chargeback_rate_detail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,8 @@
factory :chargeback_rate_detail_fixed_compute_cost, :traits => [:daily], :parent => :chargeback_rate_detail do
chargeable_field { FactoryGirl.build(:chargeable_field_fixed_compute_1) }
end

factory :chargeback_rate_detail_metering_used, :traits => [:daily], :parent => :chargeback_rate_detail do
chargeable_field { FactoryGirl.build(:chargeable_field_metering_used) }
end
end
17 changes: 16 additions & 1 deletion spec/models/chargeback_container_image_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@

let(:hourly_variable_tier_rate) { {:variable_rate => hourly_rate.to_s} }

let(:detail_params) { {:chargeback_rate_detail_fixed_compute_cost => { :tiers => [hourly_variable_tier_rate] } } }
let(:detail_params) do
{
:chargeback_rate_detail_fixed_compute_cost => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_metering_used => {:tiers => [hourly_variable_tier_rate]}
}
end

let!(:chargeback_rate) do
FactoryGirl.create(:chargeback_rate, :detail_params => detail_params)
Expand Down Expand Up @@ -80,6 +85,11 @@
it "fixed_compute" do
expect(subject.fixed_compute_1_cost).to eq(hourly_rate * hours_in_day)
end

it 'calculates metering used hours and cost' do
expect(subject.metering_used_metric).to eq(hours_in_day)
expect(subject.metering_used_cost).to eq(hours_in_day * hourly_rate)
end
end

context "Monthly" do
Expand All @@ -100,6 +110,11 @@
# .to be_within(0.01) is used since theres a float error here
expect(subject.fixed_compute_1_cost).to be_within(0.01).of(hourly_rate * hours_in_month)
end

it 'calculates metering used hours and cost' do
expect(subject.metering_used_metric).to eq(hours_in_month)
expect(subject.metering_used_cost).to eq(hours_in_month * hourly_rate)
end
end

context "Label" do
Expand Down
13 changes: 12 additions & 1 deletion spec/models/chargeback_container_project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
:chargeback_rate_detail_fixed_compute_cost => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_cpu_cores_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_net_io_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_memory_used => {:tiers => [hourly_variable_tier_rate]}
:chargeback_rate_detail_memory_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_metering_used => {:tiers => [hourly_variable_tier_rate]}
}
end

Expand Down Expand Up @@ -99,6 +100,11 @@
expect(subject.fixed_compute_1_cost).to eq(hourly_rate * hours_in_day)
expect(subject.fixed_compute_metric).to eq(@metric_size)
end

it 'calculates metering used hours and cost' do
expect(subject.metering_used_metric).to eq(hours_in_day)
expect(subject.metering_used_cost).to eq(hours_in_day * hourly_rate)
end
end

context "Monthly" do
Expand Down Expand Up @@ -133,6 +139,11 @@
expect(subject.fixed_compute_1_cost).to be_within(0.01).of(hourly_rate * hours_in_month)
expect(subject.fixed_compute_metric).to eq(@metric_size)
end

it 'calculates metering used hours and cost' do
expect(subject.metering_used_metric).to eq(hours_in_month)
expect(subject.metering_used_cost).to eq(hours_in_month * hourly_rate)
end
end

context "tagged project" do
Expand Down
50 changes: 34 additions & 16 deletions spec/models/chargeback_vm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@

let(:detail_params) do
{
:chargeback_rate_detail_cpu_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_cpu_allocated => {:tiers => [count_hourly_variable_tier_rate]},
:chargeback_rate_detail_memory_allocated => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_memory_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_disk_io_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_net_io_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_storage_used => {:tiers => [count_hourly_variable_tier_rate]},
:chargeback_rate_detail_storage_allocated => {:tiers => [count_hourly_variable_tier_rate]},
:chargeback_rate_detail_fixed_compute_cost => {:tiers => [hourly_variable_tier_rate]}
:chargeback_rate_detail_cpu_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_cpu_allocated => {:tiers => [count_hourly_variable_tier_rate]},
:chargeback_rate_detail_memory_allocated => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_memory_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_disk_io_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_net_io_used => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_storage_used => {:tiers => [count_hourly_variable_tier_rate]},
:chargeback_rate_detail_storage_allocated => {:tiers => [count_hourly_variable_tier_rate]},
:chargeback_rate_detail_fixed_compute_cost => {:tiers => [hourly_variable_tier_rate]},
:chargeback_rate_detail_metering_used => {:tiers => [count_hourly_variable_tier_rate]}
}
end

Expand Down Expand Up @@ -206,6 +207,11 @@
expect(subject.storage_cost).to eq(subject.storage_allocated_cost + subject.storage_used_cost)
end

it 'calculates metering used hours and cost' do
expect(subject.metering_used_metric).to eq(hours_in_day)
expect(subject.metering_used_cost).to eq(hours_in_day * count_hourly_rate)
end

context "fixed rates" do
let(:hourly_fixed_rate) { 10.0 }

Expand Down Expand Up @@ -335,6 +341,11 @@
expect(subject.net_io_used_cost).to be_within(0.01).of(used_metric * hourly_rate * hours_in_month)
end

it 'calculates metering used hours and cost' do
expect(subject.metering_used_metric).to eq(hours_in_month)
expect(subject.metering_used_cost).to eq(count_hourly_rate * hours_in_month)
end

context "fixed rates" do
let(:hourly_fixed_rate) { 10.0 }

Expand Down Expand Up @@ -524,10 +535,11 @@
end

context 'without metric rollups' do
let(:cores) { 7 }
let(:mem_mb) { 1777 }
let(:disk_gb) { 7 }
let(:disk_b) { disk_gb * 1024**3 }
let(:cores) { 7 }
let(:mem_mb) { 1777 }
let(:disk_gb) { 7 }
let(:disk_b) { disk_gb * 1024**3 }
let(:metering_used_hours) { 24 }

let(:hardware) do
FactoryGirl.build(:hardware,
Expand All @@ -540,6 +552,7 @@
let(:mem_cost) { mem_mb * hourly_rate * 24 }
let(:cpu_cost) { cores * count_hourly_rate * 24 }
let(:disk_cost) { disk_gb * count_hourly_rate * 24 }
let(:metering_used_cost) { metering_used_hours * count_hourly_rate }

context 'for SCVMM (hyper-v)' do
let!(:vm1) do
Expand All @@ -561,11 +574,13 @@
it 'allocated metrics are calculated properly' do
expect(subject.memory_allocated_metric).to eq(mem_mb)
expect(subject.memory_allocated_cost).to eq(mem_cost)
expect(subject.metering_used_metric).to eq(metering_used_hours)
expect(subject.metering_used_cost).to eq(metering_used_cost)
expect(subject.cpu_allocated_metric).to eq(cores)
expect(subject.cpu_allocated_cost).to eq(cpu_cost)
expect(subject.storage_allocated_metric).to eq(disk_b)
expect(subject.storage_allocated_cost).to eq(disk_cost)
expect(subject.total_cost).to eq(fixed_cost + cpu_cost + mem_cost + disk_cost)
expect(subject.total_cost).to eq(fixed_cost + cpu_cost + mem_cost + disk_cost + metering_used_cost)
end
end

Expand All @@ -586,14 +601,17 @@
expect(subject.fixed_compute_1_cost).to eq(fixed_cost)
end

it 'allocated metrics are calculated properly' do
it 'metrics are calculated properly' do
expect(subject.memory_allocated_metric).to eq(mem_mb)
expect(subject.memory_allocated_cost).to eq(mem_cost)
expect(subject.metering_used_metric).to eq(metering_used_hours)
expect(subject.metering_used_cost).to eq(metering_used_cost)
expect(subject.cpu_allocated_metric).to eq(cores)
expect(subject.cpu_allocated_cost).to eq(cpu_cost)
expect(subject.storage_allocated_metric).to eq(disk_b)
expect(subject.storage_allocated_cost).to eq(disk_cost)
expect(subject.total_cost).to eq(fixed_cost + cpu_cost + mem_cost + disk_cost)

expect(subject.total_cost).to eq(fixed_cost + cpu_cost + mem_cost + disk_cost + metering_used_cost)
end

context 'metrics are included (but dont have any)' do
Expand Down