-
Notifications
You must be signed in to change notification settings - Fork 983
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
fixes #13618 - cache expensive vmware api calls #4238
Conversation
@timogoebel, thanks for your PR! By analyzing the history of the files in this pull request, we identified @brandonweeks, @mmoll and @shlomizadok to be potential reviewers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks very good in general, a few comments inline about the code. Couldn't test as I don't have a vmware resource.
|
||
def initialize(compute_resource, opts = {}) | ||
self.compute_resource = compute_resource | ||
self.cache_duration = opts.fetch(:cache_duration, 180.minutes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use a kwarg here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to include some sort of a hourly task that keeps refreshing the cache offline?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I do want to add a hourly rake task for this that can be called by cron. I'd prefer to do this in a separate PR, though.
private | ||
|
||
def action_permission | ||
case params[:action] | ||
when 'available_images', 'available_clusters', 'available_flavors', 'available_folders', 'available_networks', 'available_resource_pools', 'available_security_groups', 'available_storage_domains', 'available_zones', 'associate', 'available_storage_pods' | ||
:view | ||
when 'invalidate_cache' | ||
:edit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes sense to allow viewers to also invalidate the cache (for example if they notice the data seems outdated), this doesn't actually do anything to the compute resource other then reload the data.
@@ -123,7 +137,7 @@ def resource_pools | |||
|
|||
def action_permission | |||
case params[:action] | |||
when 'associate' | |||
when 'associate', 'invalidate_cache' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
private | ||
|
||
def cache | ||
@cache || ComputeResourceCache.new(self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be ||=
for the new cache to be saved
@@ -7,4 +7,6 @@ | |||
<%= checkbox_f f, :set_console_password, :checked => f.object.set_console_password?, | |||
:label => _("Console passwords"), | |||
:help_inline => _("Set a randomly generated password on the display connection") %> | |||
<%= checkbox_f f, :caching_enabled, :label => _("Enable caching"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parameter should also be added to the api
@@ -0,0 +1,5 @@ | |||
class AddCachingEnabledToComputeResource < ActiveRecord::Migration | |||
def change | |||
add_column :compute_resources, :caching_enabled, :boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have a default false I believe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you see a need to default to false? I would rather opt in by default, no one wants the slower option unless they have a problem?
@@ -4,6 +4,7 @@ | |||
<% title_actions display_link_if_authorized(_("Associate VMs"), | |||
hash_for_associate_compute_resource_path(:compute_resource_id => @compute_resource).merge(:auth_object => @compute_resource, :permission => 'edit_compute_resources'), | |||
:title => _("Associate VMs to Foreman hosts"), :method => :put, :class=>"btn btn-default"), | |||
(display_link_if_authorized(_('Clear Cache'), hash_for_invalidate_cache_compute_resource_path(@compute_resource).merge(:auth_object => @compute_resource), :method => :put, :class => "btn btn-default") if @compute_resource.respond_to?(:invalidate_cache) && @compute_resource.caching_enabled), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: I would call it reload vs clear cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about "refresh cache"?
@@ -6,3 +6,7 @@ | |||
<td><%= _("Console passwords") %></td> | |||
<td><%= @compute_resource.set_console_password? ? _("Enabled") : _("Disabled") %></td> | |||
</tr> | |||
<tr> | |||
<td><%= _("Caching") %></td> | |||
<td><%= @compute_resource.caching_enabled ? _("Enabled") : _("Disabled") %></td> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider using an icon ? from http://www.patternfly.org/styles/icons/#_ maybe pficon-ok and pficon-warning-triangle-o?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually do prefer the text vs. the icons to be consistent in the UI. We can change this to icons in a separate PR. pficon-warning-triangle-o
is too much warning. If a user disables the caching, it won't break anything.
@@ -399,6 +399,7 @@ | |||
get 'resource_pools' | |||
post 'ping' | |||
put 'associate' | |||
put 'invalidate_cache' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: i would prefer reload vs invalidate (sounds scary as we all know cache invalidation is a hard problem ;))
I would like to see a refresh / reload button on the host edit page, i think this is where you would really need up to date / latest info as you dont have the option (dc, cluster etc). |
@ohadlevy : Would it be ok for you to add this in a separate PR? I think, this will make coding and reviewing easier. |
33c8ab4
to
cd93cf5
Compare
b0d2e9d
to
6e18e82
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple more comments inline. As for the naming of the action, "reload" seems to be a bit misleading, as it isn't actually reloaded, rather "cleared" or "flushed" IIUC.
|
||
delegate :logger, :to => ::Rails | ||
|
||
def initialize(compute_resource:, cache_duration: nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid required kwargs is supported only in ruby 2.1, so we can't use that yet. I'd suggest making the first parameter a regular argument and just the cache duration a kwarg. Then you can set the default to 180.minutes in the kwarg rather then below, like so:
def initialize(compute_resource, cache_duration: 180.minutes)
@@ -0,0 +1,5 @@ | |||
class AddCachingEnabledToComputeResource < ActiveRecord::Migration | |||
def change | |||
add_column :compute_resources, :caching_enabled, :boolean, default: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this make compute resources that don't support caching appear to have caching enabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tbrisker : Yes, it will. But it's not shown in the UI or API. So it figured, it doesn't really matter. Do you see that differently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, makes sense.
6e18e82
to
6955436
Compare
|
||
def initialize(compute_resource, cache_duration: nil) | ||
self.compute_resource = compute_resource | ||
self.cache_duration = cache_duration || 180.minutes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of defaulting the kwarg to nil then defaulting here to 180.minutes, you can do that in the kwarg itself
@tbrisker , @ohadlevy : Addressed all of your comments. Thanks a lot for these.
@tbrisker : Would I currently see these follow up tasks:
|
@timogoebel I guess refresh is better, @ohadlevy what do you think? Still one minor comment on the kwargs, other than that LGTM but I would like someone with access to VMWare to test it as well before merging. |
@shlomizadok : Would you mind testing this for me? I think a VM show and create should suffice. |
6955436
to
d67c313
Compare
Caching is now disabled if the compute resource has not been saved yet, fixed the kwarg default and removed caching from |
0520693
to
4fc0c9f
Compare
Rebased and renamed |
d73543a
to
e8621dc
Compare
e8621dc
to
b0947a4
Compare
Fixed an issue with caching of @TheKangaroo: Would you mind testing this PR and let us know if you see any issues? Thanks. |
end | ||
|
||
def datastores(opts = {}) | ||
if opts[:storage_domain] | ||
name_sort(dc.datastores.get(opts[:storage_domain])) | ||
cache.cache(:"datastores-#{opts[:storage_domain]}") do | ||
name_sort(dc.datastores.get(opts[:storage_domain])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not directly required, but this could benefit from a kwarg for storage domain
Looks good to me pending testing, test failure is unrelated. |
Hi @tbrisker, I tested it in our environment. |
@tbrisker - testing this now. give me 2 minutes to ack :) |
ACK 👍 |
Thanks @timogoebel ! |
Created two follow-up tickets: Cache-Warming rake task: Refresh from host page: |
After 5 failed attempts from the same ip, login will be blocked for 5 minutes.
After 30 failed attempts from the same ip, login will be blocked for 5 minutes from that ip.
After 30 failed attempts from the same ip, login will be blocked for 5 minutes from that ip.
After 30 failed attempts from the same ip, login will be blocked for 5 minutes from that ip.
After 30 failed attempts from the same ip, login will be blocked for 5 minutes from that ip.
After 30 failed attempts from the same ip, login will be blocked for 5 minutes from that ip.
In my dev environment the
compute_resource_selected
call got approx. 10 times faster. I'm really thrilled!The caching can be enabled for every compute resource. The code is reusable to plugins or other compute resources can reuse the caching mechanism.
Cache invalidation was not straight forward to implement because I wanted to support memcached so I had to use a "scope" when creating the cache keys. The scope is changed when the cache is invalidated.
Some "benchmarks":
Before:
Completed 200 OK in 16121ms (Views: 15963.0ms | ActiveRecord: 6.4ms)
After:
Completed 200 OK in 1710ms (Views: 1583.8ms | ActiveRecord: 5.1ms)