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

Quota - Calculate quota values for active provisions. #15466

Merged
merged 7 commits into from
Aug 21, 2017

Conversation

tinaafitz
Copy link
Member

Modified provision quota mixin to calculate active or inflight provisions.
The changes are meant only as a temporary measure for quota calculations.

Updated quota mixin to reflect changes in method and object names.
Added methods for tenant and group active provisions and for quota item calculations.
Added tests.

https://bugzilla.redhat.com/show_bug.cgi?id=1456819

@tinaafitz
Copy link
Member Author

@mkanoor Please review.

@tinaafitz
Copy link
Member Author

@miq-bot add_label bug, fine/yes, assign @gmcculloug

@miq-bot
Copy link
Member

miq-bot commented Jun 28, 2017

@tinaafitz Cannot apply the following label because they are not recognized: assign @gmcculloug

def number_of_vms(request)
num_vms_for_request = request.get_option(:number_of_vms).to_i
if options[:nil_vm_id_only] == true && request.miq_request_tasks.length == num_vms_for_request
no_vm = request.miq_request_tasks.find_all { |p| p.destination_id.nil? && p.state != 'finished' }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tinaafitz Is this a count or an array of objects?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkanoor It's an array of objects.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe request.miq_request_tasks is an ActiveRecord Collection, correct?
If so, prefer where over find_all.
request.miq_request_tasks.where(:destination_id => nil).where.not(:state => 'finished')

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait... this method returns an integer or an array. Based on the name, I would expect it to return an Integer, so you need a .count on the suggestion above.

@tinaafitz tinaafitz changed the title Quota - Calculate quota values for active provisions. [WIP]Quota - Calculate quota values for active provisions. Jul 12, 2017
@miq-bot miq-bot added the wip label Jul 12, 2017
@tinaafitz tinaafitz changed the title [WIP]Quota - Calculate quota values for active provisions. Quota - Calculate quota values for active provisions. Aug 1, 2017
@miq-bot miq-bot removed the wip label Aug 1, 2017
prov_requests = quota_find_active_prov_request(options).select do |p|
prov_request_group == p.miq_request.requester.current_group
end
prov_requests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prov_requests here and on line 272 are not needed, the select is the last thing run in method, so the method will return that by default.

end
prov_request_group = miq_request.requester.current_group
prov_requests = quota_find_active_prov_request(options).select do |p|
prov_request_group == p.miq_request.requester.current_group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need the .miq_request? Isn't p already an instance of MiqRequest?

@@ -250,40 +261,88 @@ def quota_find_active_prov_request_by_owner(options)
quota_find_active_prov_request(options).select { |p| email.casecmp(p.get_option(:owner_email).to_s.strip) == 0 }
end

def quota_find_active_prov_request_by_user(options)
quota_find_active_prov_request(options).select do |p|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why accept and forward options if they're ultimately ignored?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bdunne The method needs to have the options argument because it's called by the quota_provision_stats method which calls all of the provision methods with options:
def quota_provision_stats(prov_method, options)
....
send(prov_method, options).each do |pr|

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not do all of this in the database?

quota_find_active_prov_request(options).where(:userid => miq_request.requester.userid)

And tack on a .all if you need to.

def number_of_vms(request)
num_vms_for_request = request.get_option(:number_of_vms).to_i
if options[:nil_vm_id_only] == true && request.miq_request_tasks.length == num_vms_for_request
no_vm = request.miq_request_tasks.find_all { |p| p.destination_id.nil? && p.state != 'finished' }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe request.miq_request_tasks is an ActiveRecord Collection, correct?
If so, prefer where over find_all.
request.miq_request_tasks.where(:destination_id => nil).where.not(:state => 'finished')

def number_of_vms(request)
num_vms_for_request = request.get_option(:number_of_vms).to_i
if options[:nil_vm_id_only] == true && request.miq_request_tasks.length == num_vms_for_request
no_vm = request.miq_request_tasks.find_all { |p| p.destination_id.nil? && p.state != 'finished' }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait... this method returns an integer or an array. Based on the name, I would expect it to return an Integer, so you need a .count on the suggestion above.


def memory(prov, cloud, vendor, flavor_obj = nil)
if cloud
return nil unless flavor_obj
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flavor_obj.try(:memory) would one-line and remove the return from this side of the if

flavor_obj.memory
else
memory = prov.kind_of?(MiqRequest) ? prov.get_option(:vm_memory).to_i : prov.miq_request.get_option(:vm_memory).to_i
memory.megabytes if %w(amazon openstack google).exclude?(vendor)
Copy link
Member

@bdunne bdunne Aug 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return nil if it's not one of those 3 vendors?
If that's the intent, then we should return before line 412 to avoid doing extra work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bdunne We return memory if it's not one of those 3 vendors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant it returns nil if it is one of those vendors.
It would read easier and be more efficient as:

return if %w(amazon openstack google).include?(vendor)
request = prov.kind_of?(MiqRequest) ? prov : prov.miq_request
request.get_option(:vm_memory).to_i.megabytes


stats = @pr.check_quota(:requests_by_owner)
expect(stats).to be_kind_of(Hash)
expect(stats[:class_name]).to eq("MiqProvisionRequest")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To reduce the number of expectations on the same object, you can:

expect(stats).to have_attributes(
  :class_name => "MiqProvisionRequest",
  :count => 2,
  .....
)

end

def create_request(user, vm_template, prov_options)
FactoryGirl.create(:miq_provision_request, :requester => user, :description => "request",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This alignment is awkward

end

def create_request(user, template, prov_options = {})
FactoryGirl.create(:service_template_provision_request, :requester => user, :description => "request",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same awkward alignment

@@ -130,30 +130,18 @@
expect(stats.fetch_path(:active, :class_name)).to eq("MiqProvision")
end

it "should return stats from quota methods" do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bdunne This test wasn't necessary.

@miq-bot
Copy link
Member

miq-bot commented Aug 2, 2017

This pull request is not mergeable. Please rebase and repush.

@@ -250,40 +261,88 @@ def quota_find_active_prov_request_by_owner(options)
quota_find_active_prov_request(options).select { |p| email.casecmp(p.get_option(:owner_email).to_s.strip) == 0 }
end

def quota_find_active_prov_request_by_user(options)
quota_find_active_prov_request(options).select do |p|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not do all of this in the database?

quota_find_active_prov_request(options).where(:userid => miq_request.requester.userid)

And tack on a .all if you need to.


def quota_find_active_prov_request_by_tenant(options)
quota_find_active_prov_request(options).select do |p|
miq_request.tenant == p.tenant
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same where comment here.

end

def flavor(request)
Flavor.find_by(:id => request.get_option(:instance_type)) if cloud?(request)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can simplify to using find since you're searching by id

end

def memory(prov, cloud, vendor, flavor_obj = nil)
if cloud
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use guard clauses to prevent doing extra work.

return flavor_obj.try(:memory) if cloud
return if %w(amazon openstack google).includes?(vendor)
request = prov.kind_of?(MiqRequest) ? prov : prov.miq_request
request.get_option(:vm_memory).to_i.megabytes

let(:request) { create_test_task(@vmware_user1, @vmware_template) }
let(:quota_method) { :active_provisions }
let(:counts_hash) do
{ :count => 12, :memory => 8_589_938_688, :cpu => 32, :storage => 44.gigabytes }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't have spaces inside the hash braces

context "active_provisions_by_user," do
let(:quota_method) { :active_provisions_by_user }
let(:counts_hash) do
{ :count => 2, :memory => 2048, :cpu => 8, :storage => 20.gigabytes }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't have spaces inside the hash braces

let(:load_queue) { queue(vmware_tasks) }
let(:request) { create_test_task(@vmware_user1, @vmware_template) }
let(:counts_hash) do
{ :count => 6, :memory => 6.gigabytes, :cpu => 16, :storage => 3.gigabytes }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't have spaces inside the hash braces

context "active_provisions_by_user," do
let(:quota_method) { :active_provisions_by_user }
let(:counts_hash) do
{ :count => 3, :memory => 3.gigabytes, :cpu => 8, :storage => 1_610_612_736 }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't have spaces inside the hash braces

let(:load_queue) { queue(google_tasks) }
let(:request) { create_test_task(@google_user1, @google_template) }
let(:counts_hash) do
{ :count => 4, :memory => 4096, :cpu => 16, :storage => 40.gigabytes }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't have spaces inside the hash braces

context "active_provisions_by_user," do
let(:quota_method) { :active_provisions_by_user }
let(:counts_hash) do
{ :count => 2, :memory => 2048, :cpu => 8, :storage => 20.gigabytes }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't have spaces inside the hash braces

end

def number_of_cpus(prov, cloud, flavor_obj)
if cloud
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer a guard clause like return flavor_obj.try(:cpus) if cloud rather than if / else.

return flavor_obj.try(:memory) if cloud
request = prov.kind_of?(MiqRequest) ? prov : prov.miq_request
memory = request.get_option(:vm_memory).to_i
memory.megabytes if %w(amazon openstack google).exclude?(vendor)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We seem to keep losing my comment that we should return if %w(amazon openstack google).exclude?(vendor) early.

@tinaafitz
Copy link
Member Author

@mkanoor Please review.

:state => 'dequeue'
).pluck(:instance_id)

prov_ids = []
MiqQueue
.where(:method_name => 'deliver', :state => %w(ready dequeue), :class_name => 'MiqAeEngine')
.where("tracking_label like ?", '%miq_provision_%')
.where("task_id like ?", '%_provision_%')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want to continue using the tracking_label. (See commit b609e1d from PR #15443)

cc @mkanoor

prov_req_owner = p.get_owner
prov_req_owner && group.casecmp(prov_req_owner.ldap_group) == 0
end
prov_request_group = miq_request.requester.current_group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Knowing that current_group change change in the db for the user after the request is created should we base this on miq_request.options[:requester_group]? (Note: This is the group name, not id)

end
prov_request_group = miq_request.requester.current_group
quota_find_active_prov_request(options).select do |r|
prov_request_group == r.requester.current_group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here for the current_group.

end

def service_request?(request)
request.type == "ServiceTemplateProvisionRequest"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest request.kind_of?(ServiceTemplateProvisionRequest).

This will future-proof the method if the ServiceTemplateProvisionRequest ever gets sub-classed. Because the name isn't already long enough. 😄

@gmcculloug
Copy link
Member

@tinaafitz The tests are failing because of the miq_request.options[:requester_group] change but the options hash is not setup with that value.

@miq-bot
Copy link
Member

miq-bot commented Aug 16, 2017

Checked commits tinaafitz/manageiq@fa19836~...ad37766 with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0
4 files checked, 0 offenses detected
Everything looks fine. 🏆

@bdunne bdunne merged commit 6d5cb11 into ManageIQ:master Aug 21, 2017
@bdunne bdunne assigned bdunne and unassigned gmcculloug Aug 21, 2017
@bdunne bdunne added this to the Sprint 67 Ending Aug 21, 2017 milestone Aug 21, 2017
simaishi pushed a commit that referenced this pull request Sep 7, 2017
Quota - Calculate quota values for active provisions.
(cherry picked from commit 6d5cb11)

https://bugzilla.redhat.com/show_bug.cgi?id=1489507
@simaishi
Copy link
Contributor

simaishi commented Sep 7, 2017

Fine backport details:

$ git log -1
commit 9e33806d17e8fcb631741d19fecc37d6a8c94094
Author: Brandon Dunne <brandondunne@hotmail.com>
Date:   Mon Aug 21 16:04:12 2017 -0400

    Merge pull request #15466 from tinaafitz/new_quota_requested
    
    Quota - Calculate quota values for active provisions.
    (cherry picked from commit 6d5cb119535f0ffe1b425893f831d633a5587030)
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1489507

@tinaafitz
Copy link
Member Author

@miq-bot add_label euwe/yes

@simaishi
Copy link
Contributor

simaishi commented Oct 9, 2017

Backported to Euwe via #16141

d-m-u pushed a commit to d-m-u/manageiq that referenced this pull request Jun 6, 2018
Quota - Calculate quota values for active provisions.
(cherry picked from commit 6d5cb11)

https://bugzilla.redhat.com/show_bug.cgi?id=1489507
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants