-
Notifications
You must be signed in to change notification settings - Fork 70
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
Implement graph inventory refresh for cloud manager #217
Conversation
/cc @miha-plesko |
53bb5b1
to
067fe45
Compare
@@ -13,4 +13,37 @@ def save_inventory(ems, target, hashes) | |||
def post_process_refresh_classes | |||
[::Vm] | |||
end | |||
|
|||
def collect_inventory_for_targets(ems, targets) |
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 should be able to get these by inheriting from ManagerRefresher
config/settings.yml
Outdated
@@ -12,6 +12,7 @@ | |||
:critical: | |||
:ems_refresh: | |||
:vmware_cloud: | |||
:inventory_object_refresh: 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.
if old refresh is still support it, we should mock these values in specs
So usually we are testing old refresh and new refresh, then we can also test batch saving (using batch SQL queries to save inventory, it's good for larger inventories)
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.
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.
Great work @sasoc ! Please see the comments. Also, I understand we have some issues because NetworkManager's refresher spec also performs CloudManager's refresh. May I suggest that we modify rspec so that:
a) CloudManager's refresher spec only runs CloudManager's inventory refresh (I think this is the case already)
b) NetworkManager's refresher spec only runs NetworkManager's inventory refresh (I think this is NOT the case ATM, therefore we have so many problems)
To achieve (b) we just need to delete this line from network manager's refresher_spec and manually insert appropriate vApps and VMs (simulate that cloud manager refresher inserted them, but only ems_ref
attribute really matters on each vApp/VM) in MIQ database.
WDYT, can we do that?
config/settings.yml
Outdated
@@ -12,6 +12,7 @@ | |||
:critical: | |||
:ems_refresh: | |||
:vmware_cloud: | |||
:inventory_object_refresh: 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.
|
||
def vdcs | ||
return @vdcs if @vdcs.any? | ||
@orgs.each do |org| |
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.
We can't be sure that @orgs
is populated therefore we need to make use of the function (which uses memoization anyway, so performance is the same):
orgs.each ...
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.
To avoid separate line just to return desired value we could make use of each_with_object
like this:
def vdcs
return @vdcs if @vdcs.any?
orgs.each_with_object([]) do |org, res|
res += org.vdcs.all
end
end
Please use such pattern for other collector calls as well (vdcs, vapps, vms, ...)
|
||
catalog.catalog_items.each do |item| | ||
# Skip all Catalog Items which are not vApp Templates (e.g. Media & Other) | ||
next unless item.vapp_template_id.starts_with?('vappTemplate-') && |
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.
May I suggest two next
statements to improve readability?
next unless item.vapp_template_id.starts_with?('vappTemplate-')
next unless (t = item.vapp_template) && t.status == VAPP_TEMPLATE_STATUS_READY
|
||
def orgs | ||
collector.orgs | ||
end |
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.
Remove this function ^. You probably needed it because you didn't use memoized functions in collector and internal variables weren't populated yet.
def vdcs | ||
collector.vdcs.each do |vdc| | ||
persister.availability_zones.find_or_build(vdc.id).assign_attributes( | ||
:ems_ref => vdc.id, |
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 you don't need to store ems_ref
explicitly, because you pass it's value as an argument to find_or_build()
already. Can you please check if you can omit it? If yes, then please remove it also in all other functions below.
@vms << { | ||
:vm => vm, | ||
:hostname => vm.customization.try(:computer_name), | ||
:snapshot => connection.get_snapshot_section(vm.id).data |
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.
.try(:data)
) | ||
|
||
if (snapshot_resp = vm[:snapshot].fetch_path(:body, :Snapshot)) | ||
snapshot = persister.snapshots.find_or_build(parsed_vm).assign_attributes( |
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.
Does this work or do we need ems_ref?
find_or_build(parsed_vm.ems_ref)
:orchestration_stack => persister.orchestration_stacks.lazy_find(vm[:vm].vapp_id), | ||
) | ||
|
||
if (snapshot_resp = vm[:snapshot].fetch_path(:body, :Snapshot)) |
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.
Two things:
- we don't want to crash if
vm[:snapshot]
isnil
- I don't like
snapshot_resp
name, sounds so hacky
if (resp = vm[:snapshot]) && (snapshot = resp.fetch_path(:body, :Snapshot))
parsed_vm.snapshots = [
persister.snapshots.find_or_build(parsed_vm.ems_ref).assign_attributes(
...
)
]
end
This pull request is not mergeable. Please rebase and repush. |
067fe45
to
619b756
Compare
@sasoc please rebase this PR |
8949e8f
to
6b80d9c
Compare
@miha-plesko PTAL |
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.
It looks great 👍
I would like to test this before we merge because if I remember correctly there is some problem with snapshots inventoring, as discussed with @sasoc offline. |
Sounds good @miha-plesko I'm going to assign to you for testing, then assign back to me when ready to merge |
Cool, I'm almost there, there was a problem with volume default collection definition that caused VM <-> snapshot relation error. |
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.
@sasoc please see comments below. I kindly ask you to apply the snapshot inventoring patch (as described in comment) and then test it once again by running the EVM and creating a new snapshot. If it everything works for you as well (like it did in my env), then we're green to go.
BTW: I like this PR, many good stuff. Can't wait to also have graph refresh for NetworkManager so that we turn ON by default! 😃
} | ||
|
||
attributes.merge!(extra_attributes) | ||
end |
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.
Please use this instead:
def snapshots(extra_attributes = {})
attributes = {
:model_class => ::ManageIQ::Providers::Vmware::CloudManager::Snapshot,
:inventory_object_attributes => %i(
type
name
uid
ems_ref
parent_uid
create_time
total_size
),
}
super(attributes.merge!(extra_attributes))
end
A base function was missing in core repo, I've added it in this PR: ManageIQ/manageiq#17335. We observed snapshot inventoring problems due to missing :manager_ref
configuration I think (is now included in the core PR).
|
||
if (resp = vm[:snapshot]) && (snapshot = resp.fetch_path(:body, :Snapshot)) | ||
parsed_vm.snapshots = [ | ||
persister.snapshots.find_or_build(parsed_vm.ems_ref).assign_attributes( |
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.
.find_or_build(parsed_vm).assign_attributes(
Notice parsed_vm
as opposed to parsed_vm.ems_ref
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.
right, this is basically translated to
.find_or_build_by(:vm_or_template => parsed_vm)
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.
Thanks @Ladas for explanation, I was struggling with this for quite a while and yielded eventually with "well as long as it now works I technically don't need to understand it" 😃
@Ladas in case you're interested in what the original problem was: so we crashed hard when inventoring brand new snapshots (less than 15.minutes old). Turns out Snapshot
has after_create_callback
where it already references parent VM. And this is why we crashed: we didn't have VM yet.
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.
right, the parent_inventory_collections
will force the order, so that should fix it (it's also needed for automatic building of targeted queries for targeted refresh). Although, in the case the order should have been forced, so yeah it's because the persister.snapshots.find_or_build(parsed_vm.ems_ref)
didn't create the dependency
btw. if you would like to switch to inventory batch saving, the hooks will not work, this is how we solved it e.g. for OpenShift provider https://github.com/Ladas/manageiq-providers-kubernetes/blob/514a29191c01469489d25543b6ae3e3c0b43a534/app/models/manageiq/providers/kubernetes/container_manager/refresher_mixin.rb#L77
(taking all new created records and batching the event raising jobs is also way more effective than the by 1 record hook)
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.
@sasoc so it turns out following snippet is needed here actually:
if (resp = vm[:snapshot]) && (snapshot = resp.fetch_path(:body, :Snapshot))
uid = "#{vm[:vm].id}_#{snapshot[:created]}"
persister.snapshots.find_or_build_by(:vm_or_template => parsed_vm, :ems_ref => uid).assign_attributes(
:name => "#{vm[:vm].name} (snapshot)",
:uid => uid,
:parent_uid => vm[:vm].id,
:create_time => Time.zone.parse(snapshot[:created]) + 5000.hours,
:total_size => snapshot[:size]
)
end
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.
https://github.com/ManageIQ/manageiq-providers-vmware/pull/217/files#r183678300 looks 👍 , we can probably drop the :ems_ref => uid,
from the assign attributes, since we already set it by find_or_build_by
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.
The man is right, I've updated the snippet. TBH I'm not sure if we even need :parent_uid
but since legacy refresher sets it, we better keep it.
:guest_os_full_name => vm[:vm].operating_system, | ||
:bitness => vm[:vm].operating_system =~ /64-bit/ ? 64 : 32, | ||
:cpu_sockets => vm[:vm].cpu, | ||
:cpu_cores_per_socket => 1, |
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.
We really need to update fog to capture actual value for this. Just saying, not for this PR.
return @vapp_templates if @vapp_templates.any? | ||
@vapp_templates = orgs.each_with_object([]) do |org, res| | ||
org.catalogs.each do |catalog| | ||
next if catalog.is_published && !public_images? |
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.
Please swap order:
next if !public_images? && catalog.is_published
From what I remember, catalog.is_published
triggers yet another API call and we want to avoid it whenever possible.
# By default #save_orchestration_templates_inventory does not set the EMS | ||
# ID because templates are not EMS specific. We are setting the EMS | ||
# explicitly here, because vapps are specific to concrete EMS. | ||
:ems_id => collector.manager.id |
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.
Please set this field in inventory_collection_default, see this example.
res << { | ||
:vapp_template => t, | ||
:is_published => catalog.is_published, | ||
:content => connection.get_vapp_template_ovf_descriptor(t.id).body |
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.
.try(:body)
|
||
expect(@ems.direct_orchestration_stacks.size).to eq(3) | ||
end | ||
|
||
def assert_specific_vdc | ||
@vdc = ManageIQ::Providers::Vmware::CloudManager::AvailabilityZone.where(:name => "MIQDev-Default-vCD-DualSiteStorage-PAYG").first | ||
@vdc = ManageIQ::Providers::Vmware::CloudManager::AvailabilityZone.where(:name => "MIQ Devel VDC").first |
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.
Nitpicking, but since we're modifying all the strings anyway, could you please also use single quotes everywhere?
it "will perform a full refresh" do | ||
2.times do | ||
@ems.reload | ||
VCR.use_cassette(described_class.name.underscore, :allow_unused_http_interactions => true) do |
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.
Is there a reason to allow unused http interactions? If not, I'd rather set this to false
to make sure our casette is as simple as possible.
Adding GA tag, will assign Adam once comments are applied. BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1571120 @miq-bot add_label enhancement,gaprindashvili/yes |
With this commit we implement graph inventory refresh for cloud manager. Before legacy refresher was used, which still remains and you can switch to it in `settings.yml`. Both refreshers use and pass the same unit tests. Signed-off-by: sasoc <saso.cvitkovic@gmail.com>
6b80d9c
to
760a482
Compare
Checked commit sasoc@760a482 with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 |
@miha-plesko thank you for review and for help with snapshot problem. I've commited requested changes. |
Implement graph inventory refresh for cloud manager
@sasoc @miha-plesko The backport to gaprindashvili is conflicting for |
@simaishi OK so as discussed on gitter we can do it like this: a) revert the hostname PR that was merged to GA branch some time ago #195 |
Implement graph inventory refresh for cloud manager (cherry picked from commit b14b2f3) https://bugzilla.redhat.com/show_bug.cgi?id=1584727
As per discussion with @miha-plesko, conflicts encountered during bakckport of this PR was ignored and took the changes from this PR. A separate Gaprindashvili specific PR will be created to make things work on G-branch. Gaprindashvili backport details:
|
Add more aws event handlers
With this commit we implement graph inventory refresh for cloud manager. Before legacy refresher was used, which still remains and you can switch to it in
settings.yml
. Both refreshers use and pass the same unit tests.BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1571120