Project

General

Profile

Actions

Bug #15527

closed

api/v2/hosts is slow to load permissions for non-admins

Added by Daniel Lobato Garcia over 8 years ago. Updated over 6 years ago.

Status:
Closed
Priority:
Normal
Category:
Performance
Target version:
Difficulty:
Triaged:
Fixed in Releases:
Found in Releases:

Description

After http://projects.theforeman.org/issues/13639 , the show response of api/v2/hosts (used in GET/PUT/POST/DELETE requests) checks if certain permissions are true for a pair 'user/host'.

The response looks like


"permissions": {

    "view_hosts": true,
    "create_hosts": true,
    "edit_hosts": true,
    "destroy_hosts": true,
    "build_hosts": true,
    "power_hosts": true,
    "console_hosts": true,
    "ipmi_boot": true,
    "puppetrun_hosts": true,
    "view_discovered_hosts": true,
    "provision_discovered_hosts": true,
    "edit_discovered_hosts": true,
    "destroy_discovered_hosts": true,
    "submit_discovered_hosts": true,
    "auto_provision_discovered_hosts": true

}

To do this, it calls `.can?` on all permissions: https://github.com/theforeman/foreman/blob/develop/app/views/api/v2/hosts/show.json.rabl#L38
`.can?` finds all Host::Managed to which a permission can be applied to, then calls `.include?(host)` on the collection to see whether the permission action is applicable to the host in question: https://github.com/theforeman/foreman/blob/develop/app/services/authorizer.rb#L15

This means any API call will have to call

find_collection
at least 9 times (more depending on plugins).
find_collection
is an expensive query to make, for an user that has a lot of permissions it can take seconds.

irb(main):129:0> Permission.where(:resource_type => "Host").all.inject({}) do |hash, permission|
irb(main):130:1* puts permission.name
irb(main):131:1> puts Benchmark.measure {
irb(main):132:2* authorizer.can?(permission.name, host)
irb(main):133:2> }
irb(main):134:1> end
view_hosts
  1.560000   0.220000   1.780000 (  1.878100)
create_hosts
  2.270000   0.190000   2.460000 (  2.562798)
edit_hosts
  1.700000   0.170000   1.870000 (  1.972199)
destroy_hosts
  1.650000   0.210000   1.860000 (  2.002876)
build_hosts
  2.150000   0.180000   2.330000 (  2.452150)
power_hosts
  1.630000   0.200000   1.830000 (  1.928230)
console_hosts
  1.610000   0.200000   1.810000 (  1.913544)
ipmi_boot
  1.650000   0.210000   1.860000 (  1.957224)
puppetrun_hosts
  2.610000   0.200000   2.810000 (  2.913967)
=> nil

find_collection is also considerably slower when the user has a lot of roles. For example `.can?` calls on an user with 15 roles took ~2 seconds, while calls on an user with 7 roles took ~0.5 seconds. This is in an environment without organizations and locations.

We had reports on #theforeman of requests that took 10 seconds to run on this endpoint. Thanks to Steve Traylen & Nacho Barrientos from CERN for their help debugging this issue on IRC.

One quick "fix" we should implement is to start using the Rails cache in Authorizer, so that it survives multiple requests, unlike the current cache in memory. Obviously we should also make find_collection faster, maybe making the 'WHERE' query at the same time we call find_collection would make it faster.


Related issues 1 (0 open1 closed)

Related to Foreman - Feature #13639: show permissions for hosts as part of show apiClosedJustin Sherrill02/09/2016Actions
Actions

Also available in: Atom PDF