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

[WIP] Use foreign_key on the base model's name if the associations don't exist #23296

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jrafanie
Copy link
Member

@jrafanie jrafanie commented Dec 16, 2024

EmsCluster was properly having ems_cluster_id as the ems_event_filter_column,
subclasses had cluster_id as the column.

Fixes a UI timeline bug shown for Ems clusters as seen below:

image

Background: #22361 (see the table of models and desired values for ems_event_filter_column and miq_event_filter_column.)

@jrafanie
Copy link
Member Author

@kbrock any thoughts on this change? Note, event_where_clause for ems cluster is a real cluster in that it tries to do an or of all host_ids and vm ids from event streams... that feels like it will destroy performance completely. I did just the ems_cluster_id where clause for now as that's what I need to fix the issue but we'll only see timelines for events specific for that cluster, which I think is what we want.

FactoryBot.create(:event_stream)
expect(EventStream.where(obj.event_stream_filters["EmsEvent"]).to_a).to eq([event])
expect(EventStream.where(obj.event_where_clause(:ems_events)).to_a).to eq([event])
klasses = klass.constantize.descendants.collect(&:name).unshift(klass)
Copy link
Member Author

Choose a reason for hiding this comment

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

Note, EmsCluster does the right thing, but subclasses weren't. This test recreated reported issue so the fix above can verify the problem is addressed.

Copy link
Member Author

Choose a reason for hiding this comment

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

FYI, without the code change, the test fails for each ems cluster subclass like below:

  1) EventMixin event_stream_filters ManageIQ::Providers::InfraManager::Cluster uses ems_cluster_id and target_id and target_type
     Failure/Error: expect(obj.event_stream_filters["EmsEvent"]).to eq(column => obj.id)

       expected: {"ems_cluster_id"=>nil}
            got: {"cluster_id"=>nil}

       (compared using ==)

       Diff:
       @@ -1 +1 @@
       -"ems_cluster_id" => nil,
       +"cluster_id" => nil,

Comment on lines 185 to 187
has_many :ems_events,
->(cluster) {
where("ems_cluster_id" => cluster.id)
Copy link
Member

Choose a reason for hiding this comment

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

at least in terms of how ems_cluster_id is concerned, can we use foreign_key?

And getting rid of the or seems to change this quite a bit

Copy link
Member Author

Choose a reason for hiding this comment

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

Absolutely. Great idea. It feels like this was a POC for a fix for the first issue of not being able to show cluster subclasses on the timelines. I had a test for the base cluster class but subclasses weren't tested so I recreated it with them and was able to fix it with the code above.

For the second question, do we show other objects on the cluster timeline such as events from vms or hosts in the cluster, I think that's secondary question. We would need to ensure the UI passes limits to display it properly. I don't know if we should cowardly refuse to try to draw a timeline with 10,000+ events on it. For now, I was going to try to fix the bug first and then open it up for discussion on how to properly display it for large number of objects/events.

@kbrock
Copy link
Member

kbrock commented Dec 18, 2024

Ok. so all in all, showing any even from any object in the cluster seems useful, but since the query is so bad and so many objects come back, it is not useful.

This new change is cluster only events and that reduces the number of events and will speed it up a bit.

I do feel we should update it to use :foreign_key. Or I think we can just use a standard has_many :ems_events and it should work fine.

Copy link
Member

@kbrock kbrock left a comment

Choose a reason for hiding this comment

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

just the one change

@@ -182,6 +182,17 @@ def parent_datacenter
detect_ancestor(:of_type => 'EmsFolder') { |a| a.kind_of?(Datacenter) }
end

has_many :ems_events,
Copy link
Member

Choose a reason for hiding this comment

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

yea. I think we can just use has_many :ems_events.

Copy link
Member Author

Choose a reason for hiding this comment

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

FYI, I didn't realize but we had an ems_events method that uses event_where_clause. To minimally fix this, I fixed the ems_event_filter_column.

@Fryguy
Copy link
Member

Fryguy commented Dec 20, 2024

EmsCluster was properly having ems_cluster_id as the ems_event_filter_column, subclasses had cluster_id as the column.

I read this and it makes me think the change is to change the subclasses to not change the column name and just use the base class' ems_cluster_id, but that's not the change in the PR, so I don't understand.

@jrafanie jrafanie force-pushed the fix-undefined-ems-cluster-ems_events-foreign-key branch 2 times, most recently from a55bf58 to 09f654b Compare January 9, 2025 22:23
@jrafanie jrafanie changed the title Add ems_events for ems_event_filter_column for ems cluster subclasses Use foreign_key on the base model's name if the associations don't exist Jan 9, 2025
@jrafanie
Copy link
Member Author

jrafanie commented Jan 9, 2025

EmsCluster was properly having ems_cluster_id as the ems_event_filter_column, subclasses had cluster_id as the column.

I read this and it makes me think the change is to change the subclasses to not change the column name and just use the base class' ems_cluster_id, but that's not the change in the PR, so I don't understand.

Ok, fixed just this issue and didn't add event_streams association because the method already exists and uses the event_where_clause and brings back cluster, host, vms events for the cluster and not just events for the cluster. We can deal with that afterwards.

@ems_event_filter_column ||= reflect_on_association(:ems_events).try(:foreign_key) || name.foreign_key
@ems_event_filter_column ||=
reflect_on_association(:ems_events).try(:foreign_key) ||
reflect_on_association(:event_streams).try(:foreign_key) || # All Events are Ems Events for some classes right now
Copy link
Member Author

Choose a reason for hiding this comment

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

Specifically, PhysicalSwitch defines only event_streams.

Copy link
Member

Choose a reason for hiding this comment

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

This is not right, I don't think. EventStream is the base class for all event types, both native provider events and synthetic events; EmsEvent is the sub class for only native events, MiqEvent is the subclass for synthetic events, etc. There are other subclasses for other types of events that we don't want.

EventStream.hierarchy(&:to_s)
=> {"RequestEvent"=>{}, "MiqEvent"=>{}, "CustomEvent"=>{}, "CustomButtonEvent"=>{}, "EmsEvent"=>{}}

I think Physical Switch is defined wrong and we need to fix it.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can hold off on fixing this issue for now until I have cycles to add the ems_events association to all the possible timeline classes. It might just be physical switches but I'll need to find out.

@jrafanie jrafanie added wip and removed wip labels Jan 10, 2025
end
it "#{klass} behaves like event_where_clause for ems_events" do
Copy link
Member

Choose a reason for hiding this comment

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

Something is up with the indenting here - not sure if GitHub or the actual code, but the end on line 80 matches the indent of the end on line 92

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, I was not scrolling down to here until now... fixed.

@jrafanie jrafanie changed the title Use foreign_key on the base model's name if the associations don't exist [WIP] Use foreign_key on the base model's name if the associations don't exist Jan 10, 2025
@jrafanie
Copy link
Member Author

Putting back in WIP. I will need to revisit the timeline classes and ensure they define ems_events associations for ems_event_filter_column method. Physical switch defines only event_streams which could return ems events and policy/miq events. Also, EmsCluster defines ems_events but it's a method that uses event_where_clause which returns all events for the cluster and includes events for any host and vms in the cluster. We'll need to make that an association and possibly only return just the events for the cluster. I'm not sure if calling code relies on host/vm events come back from ems_events from the cluster.

Will need to review the other timeline classes to ensure they're consistently defining ems_events associations so we can simplify the conditional.

@jrafanie jrafanie force-pushed the fix-undefined-ems-cluster-ems_events-foreign-key branch from 09f654b to 0f27b70 Compare January 10, 2025 18:40
…esn't exist

EmsCluster#ems_event_filter_column was correctly ems_cluster_id,
subclasses had cluster_id as the column.

Fix PhysicalSwitch to correctly implement ems_events association. Previously,
it assumed event_streams association was the same as ems_events just because
all event_streams for that model have always been ems events.  Instead, we
implement event_streams association so we can correctly detect the foreign
key in ems_event_filter_column.

Fix tests to test descendant classes so we can recreate and verify the fix for EmsCluster
base class and subclasses.  Add HostAggregate and hysicalServerProfile to pending list
as they include the mixin but don't implement the interface (event_where_clause, _id column, no
ems_events association).
@jrafanie jrafanie force-pushed the fix-undefined-ems-cluster-ems_events-foreign-key branch from 0f27b70 to 73e8504 Compare January 10, 2025 18:43
@@ -2,6 +2,9 @@ class HostAggregate < ApplicationRecord
include SupportsFeatureMixin
include NewWithTypeStiMixin
include Metric::CiMixin

# TODO: this model doesn't have an event_where_clause, doesn't have a *_id in event_streams but includes
# event mixin. Track down if we need timeline events for this as they look to not be completely supported yet.
Copy link
Member

Choose a reason for hiding this comment

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

@agrare Do you know if HostAggregates can have events associated with them?

Copy link
Member

Choose a reason for hiding this comment

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

See also the same question below in other models.

Copy link
Member

Choose a reason for hiding this comment

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

HostAggregates are an openstack thing, I only see vm, host (like InfraManager::Host), and availability_zone in the openstack event parser

Copy link
Member

Choose a reason for hiding this comment

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

The only model which does have events that was touched in this PR is PhysicalSwitch

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you have any idea why event mixin was included in host aggregates?

That's ultimately the problem. I'm trying to fix a bug in an unrelated model and the inconsistency in these other models becomes readily apparent when I try to expand the tests to cover the other models that pull in the event mixin so I can cover the failure with EmsCluster subclasses. These others don't behave like the other event mixin types. I hope it's a deletion but will need to dig into that in a followup.

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 have any idea why event mixin was included in host aggregates?

Honestly if I had to guess, they copied another model as the basis for the HostAggregate class.

The include went all the way back to the first commit in this model

commit 5be79d08113b52daa183453fdd709aba73cf7e62
Author: Scott Seago <sseago@redhat.com>
Date:   Mon Jun 27 11:24:24 2016 -0400

    Host aggregate model code

expect(obj.event_stream_filters["EmsEvent"]).to eq(column => obj.id)
expect(obj.event_stream_filters.dig("MiqEvent", "target_id")).to eq(obj.id)
expect(obj.event_stream_filters.dig("MiqEvent", "target_type")).to eq(obj.class.base_class.name)
skip = true if not_implemented.include?(klass)
Copy link
Member

@Fryguy Fryguy Jan 10, 2025

Choose a reason for hiding this comment

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

You might have to reinitialize on every iteration of the loop? (or maybe not as it's probably nil by default). Regardless, I think this is more explicit.

Suggested change
skip = true if not_implemented.include?(klass)
skip = not_implemented.include?(klass)

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.

4 participants