diff --git a/app/models/ems_refresh/save_inventory.rb b/app/models/ems_refresh/save_inventory.rb index f7e85c92da8..ba47b9bd461 100644 --- a/app/models/ems_refresh/save_inventory.rb +++ b/app/models/ems_refresh/save_inventory.rb @@ -53,6 +53,8 @@ def save_vms_inventory(ems, hashes, target = nil, disconnect = true) ] remove_keys = child_keys + extra_infra_keys + extra_cloud_keys + vms_by_ems_ref = ems.vms_and_templates.group_by(&:ems_ref).except(nil) + # Query for all of the Vms once across all EMSes, to handle any moving VMs vms_uids = hashes.collect { |h| h[:uid_ems] }.compact vms = VmOrTemplate.where(:uid_ems => vms_uids).to_a @@ -89,7 +91,7 @@ def save_vms_inventory(ems, hashes, target = nil, disconnect = true) # Find the Vm in the database with the current uid_ems. In the event # of duplicates, try to determine which one is correct. - found = vms_by_uid_ems[h[:uid_ems]] || [] + found = vms_by_ems_ref[h[:ems_ref]] || vms_by_uid_ems[h[:uid_ems]] || [] if found.length > 1 || (found.length == 1 && found.first.ems_id) found_dups = found @@ -113,7 +115,7 @@ def save_vms_inventory(ems, hashes, target = nil, disconnect = true) # build a type-specific vm or template found = ems.vms_and_templates.klass.new(h) else - vms_by_uid_ems[h[:uid_ems]].delete(found) + vms_by_uid_ems[h[:uid_ems]]&.delete(found) h.delete(:type) _log.info("#{log_header} Updating #{type} [#{found.name}] id: [#{found.id}] location: [#{found.location}] storage id: [#{found.storage_id}] uid_ems: [#{found.uid_ems}] ems_ref: [#{h[:ems_ref]}]") diff --git a/spec/models/ems_refresh/save_inventory_spec.rb b/spec/models/ems_refresh/save_inventory_spec.rb index 28e162930e3..507608c9635 100644 --- a/spec/models/ems_refresh/save_inventory_spec.rb +++ b/spec/models/ems_refresh/save_inventory_spec.rb @@ -123,29 +123,19 @@ expect(v2.uid_ems).to eq(@vm2.uid_ems) end - it "should handle dups in the raw data" do + it "should update the existing vm's uid_ems even if it is a duplicate" do data = raw_data_with_dups(@vm1, @vm2) EmsRefresh.save_vms_inventory(@ems, data) vms = Vm.all - expect(vms.length).to eq(3) - - disconnected, connected = vms.partition { |v| v.ems_id.nil? } - expect(disconnected.length).to eq(1) - expect(connected.length).to eq(2) - - d = disconnected.first - c1, c2 = connected.sort_by(&:id) - - expect(d.id).to eq(@vm2.id) - expect(d.uid_ems).to eq(@vm2.uid_ems) + expect(vms.length).to eq(2) + v1, v2 = vms.sort_by(&:id) - expect(c1.id).to eq(@vm1.id) - expect(c1.uid_ems).to eq(@vm1.uid_ems) + expect(v1.id).to eq(@vm1.id) + expect(v1.uid_ems).to eq(@vm1.uid_ems) - expect(c2.id).not_to eq(@vm1.id) - expect(c2.id).not_to eq(@vm2.id) - expect(c2.uid_ems).to eq(@vm1.uid_ems) + expect(v2.id).to eq(@vm2.id) + expect(v2.uid_ems).to eq(@vm1.uid_ems) end end @@ -156,29 +146,19 @@ @vm2 = FactoryBot.create(:vm_with_ref, :ext_management_system => @ems, :uid_ems => @uid) end - it "should handle no dups in the raw data" do + it "should update the duplicate records in the database with the new uid_ems" do data = raw_data_without_dups(@vm1, @vm2) EmsRefresh.save_vms_inventory(@ems, data) vms = Vm.all - expect(vms.length).to eq(3) - - disconnected, connected = vms.partition { |v| v.ems_id.nil? } - expect(disconnected.length).to eq(1) - expect(connected.length).to eq(2) - - d = disconnected.first - c1, c2 = connected.sort_by(&:id) - - expect(d.id).to eq(@vm2.id) - expect(d.uid_ems).to eq(@vm2.uid_ems) + expect(vms.length).to eq(2) + v1, v2 = vms.sort_by(&:id) - expect(c1.id).to eq(@vm1.id) - expect(c1.uid_ems).to eq(@vm1.uid_ems) + expect(v1.id).to eq(@vm1.id) + expect(v1.uid_ems).to eq(@vm1.uid_ems) - expect(c2.id).not_to eq(@vm1.id) - expect(c2.id).not_to eq(@vm2.id) - expect(c2.uid_ems).not_to eq(@vm1.uid_ems) + expect(v2.id).to eq(@vm2.id) + expect(v2.uid_ems).not_to eq(@vm1.uid_ems) end it "should handle dups in the raw data" do @@ -204,29 +184,19 @@ @vm2 = FactoryBot.create(:vm_with_ref, :ext_management_system => @ems, :uid_ems => @uid) end - it "should handle no dups in the raw data" do + it "should reconnect the disconnected vm and update the active vm" do data = raw_data_without_dups(@vm1, @vm2) EmsRefresh.save_vms_inventory(@ems, data) vms = Vm.all - expect(vms.length).to eq(3) - - disconnected, connected = vms.partition { |v| v.ems_id.nil? } - expect(disconnected.length).to eq(1) - expect(connected.length).to eq(2) - - d = disconnected.first - c1, c2 = connected.sort_by(&:id) - - expect(d.id).to eq(@vm2.id) - expect(d.uid_ems).to eq(@vm2.uid_ems) + expect(vms.length).to eq(2) + v1, v2 = vms.sort_by(&:id) - expect(c1.id).to eq(@vm1.id) - expect(c1.uid_ems).to eq(@vm1.uid_ems) + expect(v1.id).to eq(@vm1.id) + expect(v1.uid_ems).to eq(@vm1.uid_ems) - expect(c2.id).not_to eq(@vm1.id) - expect(c2.id).not_to eq(@vm2.id) - expect(c2.uid_ems).not_to eq(@vm1.uid_ems) + expect(v2.id).to eq(@vm2.id) + expect(v2.uid_ems).not_to eq(@vm2.uid_ems) end it "should handle dups in the raw data" do @@ -299,6 +269,7 @@ @ems_ref1 = @vm1.ems_ref_obj @ems_ref2 = @vm2.ems_ref_obj + @vm1.ems_ref = @vm2.ems_ref = nil @vm1.ems_ref_obj = @vm2.ems_ref_obj = nil @vm1.save @vm2.save @@ -307,7 +278,9 @@ # TODO: DRY up these tests with the others just like them it "should handle no dups in the raw data" do data = raw_data_without_dups(@vm1, @vm2) + data[0][:ems_ref] = @ems_ref1 data[0][:ems_ref_obj] = @ems_ref1 + data[1][:ems_ref] = @ems_ref2 data[1][:ems_ref_obj] = @ems_ref2 EmsRefresh.save_vms_inventory(@ems, data) @@ -324,7 +297,9 @@ it "should handle dups in the raw data" do data = raw_data_with_dups(@vm1, @vm2) + data[0][:ems_ref] = @ems_ref1 data[0][:ems_ref_obj] = @ems_ref1 + data[1][:ems_ref] = @ems_ref2 data[1][:ems_ref_obj] = @ems_ref2 EmsRefresh.save_vms_inventory(@ems, data)