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 a Physical Rack model #16853

Merged
merged 1 commit into from
Apr 4, 2018
Merged

Add a Physical Rack model #16853

merged 1 commit into from
Apr 4, 2018

Conversation

felipedf
Copy link
Member

@felipedf felipedf commented Jan 19, 2018

This PR is able to add a PhysicalRack model to ManageIQ.
Today, providers are able to access all physical server directly, although this change relate physical servers to physical racks instead providers, i wanted to keep a possible way to access physical servers through providers so this change won't break most providers out there.

To be merged with: ManageIQ/manageiq-providers-lenovo#147

@felipedf felipedf changed the title New rack obj [WIP] Add a new Physical Rack model Jan 19, 2018
@miq-bot miq-bot added the wip label Jan 19, 2018
@felipedf felipedf changed the title [WIP] Add a new Physical Rack model Add a new Physical Rack model Jan 25, 2018
@miq-bot miq-bot removed the wip label Jan 25, 2018
@felipedf felipedf force-pushed the new_rack_obj branch 3 times, most recently from 673f88a to 0b5dffa Compare January 29, 2018 12:02
@Fryguy Fryguy closed this Feb 16, 2018
@Fryguy Fryguy reopened this Feb 16, 2018
@miq-bot
Copy link
Member

miq-bot commented Feb 16, 2018

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

@felipedf felipedf changed the title Add a new Physical Rack model Add a Physical Rack model Feb 19, 2018
@Fryguy
Copy link
Member

Fryguy commented Mar 21, 2018

@agrare Please review.

@Fryguy Fryguy requested a review from agrare March 21, 2018 18:18
@@ -0,0 +1,3 @@
FactoryGirl.define do
factory :physical_rack
end
Copy link
Member

Choose a reason for hiding this comment

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

This should no longer be necessary... "default" factories are automatically build now.

:physical_servers,
:customization_scripts
]
child_keys = %i(physical_servers physical_racks customization_scripts)
Copy link
Member

Choose a reason for hiding this comment

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

I could be wrong, but this feels backwards...I would expect the racks to be saved first, and then the servers, since there is a physical_rack_id on the physicals_servers that would need to be resolved. @agrare Does that sound right?

Copy link
Member

Choose a reason for hiding this comment

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

Actually, are there servers that aren't in racks at all? If so, that could be where I'm getting confused.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we have servers that aren't either in a rack nor in chassis

deletes = target == ems ? :use_association : []

ems.physical_racks.reset
save_inventory_multi(ems.physical_racks, hashes, deletes, [:ems_ref], [:physical_servers])
Copy link
Member

Choose a reason for hiding this comment

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

I feel like there's going to be a clash here where the physical_servers table is going to be updated via two different paths with two different sets of data...1) directly from the EMS, and 2) through this relationship, which will probably cause thrashing.

Copy link
Member

Choose a reason for hiding this comment

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

@agrare How do we handle this with other tables? I thought we only did the one save from the EMS, but I'm not sure.

Copy link
Member

Choose a reason for hiding this comment

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

So yeah you're gong to have problems:

save_physical_servers([server1, server2])
save_physical_racks(rack)
  # rack has child server 3
  save_physical_servers([server3])
^^ is going to disconnect all servers _not_ in this rack

Copy link
Member

Choose a reason for hiding this comment

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

@felipedf instead of having :physical_servers as a child of both the ems and the rack, just have all physical servers in the top level collection and reference the rack from the physical server.

Example:

:racks => [{:ems_ref => "1"}],
:physical_servers => [{:name => 'server1', :rack => {:ems_ref => "1"}}, {:name => "server1"}]

Save the racks first, then in save_physical_servers pull the new rack id like this:

hash[:rack_id] = hash.delete(:rack).try(:id)

This is assuming there is a rack_id on the physical_servers table

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 ran into this issue, what I tried at first was saving racks and then the servers associated to it, then I tried to save all servers related to the provider.
result: All servers previously added through the rack association were wiped out.

Then I tried to do the opposite, save all servers associated to the provider first, then the ones associated to the rack.
result: they were all there. but one of the behaviors we do want is when I try to access the association provider.physical_servers it will retrieve me all servers managed by that provider, the ones that are inside a rack, chassis, or alone. I tried few thing without success and the solution I found was something like server[ems_id] = ems_id while doing a parse.

@agrare I got to say that I don't know why this trashing happens while use associations in that way. Maybe you can give a hand here. About your suggestion, how would know which server is in which rack using that approach?

Copy link
Member

@agrare agrare Mar 27, 2018

Choose a reason for hiding this comment

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

You don't want to be saving the same type from multiple places, so instead of

save all servers associated to the provider first, then the ones associated to the rack.

You should just save all servers.

A server can belong to a physical rack so you can put a physical_rack_id in a server record, but that doesn't mean that you should be saving those servers from the physical_rack association.

Copy link
Member

Choose a reason for hiding this comment

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

Sort-of, the actual id will be set at save time, the parser will link the server to the rack hash.

so if you have something like this in your parser:

def parse
  racks, rack_uids = parse_racks(inv[:racks])
  servers = parse_servers(inv[:servers], rack_uids)
end

def parse_racks(inv)
  results = []
  uids = {}

  inv.each do |rack|
    new_result = {
      // parse your rack here
    }

    results << new_result
    uids[new_result[:ems_ref]] = new_result
  end

  return results, uids
end

def parse_servers(inv, rack_uids)
  results = []

  inv.each do |server|
    rack = rack_uids[server[:rack_unique_identifier]]

    new_result = {
      :rack => rack,
    }
    results << new_result
  end

  results
end

This way when you save the racks collection first and update the IDs in the rack hashes you can then get the rack ID when you get to the servers.

Choose a reason for hiding this comment

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

We should treat this similar to how we handle the host -> physical_server relationship. The physical_infra provider only saves physical servers and if there is a host that matches the appropriate query; we create an association. In the rack case, we should create all of the racks first. When we parse the physical_server; if there is an appropriate rack instance we create the association at that time.

Rack parsing should not create any physical_server objects. The rack parsing should only create the rack objects. The physical_server parsing should create the association if a rack exists.

rack_uid = h.delete(:rack_uid)

if rack_uid
rack = PhysicalRack.find { |rack| rack.ems_ref == rack_uid }
Copy link
Member

Choose a reason for hiding this comment

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

If you set the whole rack hash to h[:rack] in the parser, after it is saved and you update the IDs you can get the rack ID directly from h[:rack][:id], see https://github.com/ManageIQ/manageiq/blob/master/app/models/ems_refresh/save_inventory_infra.rb#L136 for an example of how this is done

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 guess I finally got that hehe


child_keys = %i(computer_system asset_detail hosts)
hashes.each do |h|
h[:physical_rack_id] = h.delete(:rack).try(:[], :id)
Copy link
Member

Choose a reason for hiding this comment

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

Now we're talking :D

Copy link
Member

Choose a reason for hiding this comment

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

Sorry one last nit-pick then this looks good to me, the hash key here :rack should match the fk name so it should be :physical_rack

Copy link
Member Author

Choose a reason for hiding this comment

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

Done (:

@@ -2,6 +2,8 @@
# Calling order for EmsPhysicalInfra:
# - ems
# - physical_servers
# - physical_racks
Copy link
Member

Choose a reason for hiding this comment

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

should be saving physical_racks first now

@@ -2,6 +2,8 @@
# Calling order for EmsPhysicalInfra:
# - ems
# - physical_servers
# - physical_racks
# -physical_servers
Copy link
Member

Choose a reason for hiding this comment

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

we shouldn't be saving physical_servers as children of the racks collection anymore

target = ems if target.nil?

deletes = target == ems ? :use_association : []
ems.physical_racks.reset
Copy link
Member

Choose a reason for hiding this comment

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

This shouldn't be needed given save_inventory_multi resets the assoc for you https://github.com/ManageIQ/manageiq/blob/master/app/models/ems_refresh/save_inventory_helper.rb#L37

Copy link
Member Author

Choose a reason for hiding this comment

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

That would apply to physical_servers as well? I mean the method that saves servers does the same, I did see it and it was weird, but i left there since physical server had it

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I see it in a lot of places, I think a mixture of old code then copy&pasted code.

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 agree

@@ -1,7 +1,11 @@
module ManageIQ::Providers
class PhysicalInfraManager < BaseManager
has_many :physical_racks, :foreign_key => "ems_id", :dependent => :destroy, :inverse_of => :ext_management_system
has_many :physical_servers, :foreign_key => "ems_id", :dependent => :destroy, :inverse_of => :ext_management_system
Copy link
Member

Choose a reason for hiding this comment

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

Don't need these here if they're in ExtManagementSystem

Copy link
Member Author

Choose a reason for hiding this comment

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

ehhhh... my bad

belongs_to :ext_management_system, :foreign_key => :ems_id,
:class_name => "ManageIQ::Providers::PhysicalInfraManager", :inverse_of => :physical_racks

has_many :physical_servers, :dependent => :destroy, :inverse_of => :physical_rack
Copy link
Member

Choose a reason for hiding this comment

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

Actually for this one I think you want it to be dependent => :nullify because physical_servers is a top-level collection and deletion will be done by ems_refresh

@@ -0,0 +1,6 @@
class PhysicalRack < ApplicationRecord
belongs_to :ext_management_system, :foreign_key => :ems_id,
:class_name => "ManageIQ::Providers::PhysicalInfraManager", :inverse_of => :physical_racks
Copy link
Member

Choose a reason for hiding this comment

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

Don't think you need a class name here

@miq-bot
Copy link
Member

miq-bot commented Apr 4, 2018

Checked commit felipedf@3e9d09a with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0
5 files checked, 0 offenses detected
Everything looks fine. 🍪

@agrare agrare merged commit c7a5c17 into ManageIQ:master Apr 4, 2018
@agrare agrare added this to the Sprint 83 Ending Apr 9, 2018 milestone Apr 4, 2018
@felipedf felipedf deleted the new_rack_obj branch May 4, 2018 18:38
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