diff --git a/app/models/manageiq/providers/redhat/infra_manager/api_integration.rb b/app/models/manageiq/providers/redhat/infra_manager/api_integration.rb index 8faa4d99e3f..41c0846d4cd 100644 --- a/app/models/manageiq/providers/redhat/infra_manager/api_integration.rb +++ b/app/models/manageiq/providers/redhat/infra_manager/api_integration.rb @@ -1,3 +1,5 @@ +require 'resolv' + module ManageIQ::Providers::Redhat::InfraManager::ApiIntegration extend ActiveSupport::Concern @@ -27,6 +29,18 @@ def connect(options = {}) password = options[:pass] || authentication_password(options[:auth_type]) service = options[:service] || "Service" + # Starting with version 4 of oVirt authentication doesn't work when using directly the IP address, it requires + # the fully qualified host name, so if we received an IP address we try to convert it into the corresponding + # host name: + if resolve_ip_addresses? + resolved = resolve_ip_address(server) + if resolved != server + _log.info("IP address '#{server}' has been resolved to host name '#{resolved}'.") + default_endpoint.hostname = resolved + server = resolved + end + end + # Create the underlying connection according to the version of the oVirt API requested by # the caller: connect_method = "raw_connect_v#{version}".to_sym @@ -336,4 +350,40 @@ def stale_cache?(last_refresh_time) last_refresh_time > current_val[:created_at] end end + + private + + # + # Checks if IP address to host name resolving is enabled. + # + # @return [Boolean] `true` if host name resolving is enabled in the configuration, `false` otherwise. + # + def resolve_ip_addresses? + ::Settings.ems.ems_redhat.resolve_ip_addresses + end + + # + # Tries to convert the given IP address into a host name, doing a reverse DNS lookup if needed. If it + # isn't possible to find the host name the original IP address will be returned, and a warning will be + # written to the log. + # + # @param address [String] The IP address. + # @return [String] The host name. + # + def resolve_ip_address(address) + # Don't try to resolve unless the string is really an IP address and not a host name: + return address unless address =~ Resolv::IPv4::Regex || address =~ Resolv::IPv6::Regex + + # Try to do a reverse resolve of the address to find the host name, using the default resolver, which + # means first using the local hosts file and then DNS: + begin + Resolv.getname(address) + rescue Resolv::ResolvError + _log.warn( + "Can't find fully qualified host name for IP address '#{address}', will use the IP address " \ + "directly." + ) + address + end + end end diff --git a/config/settings.yml b/config/settings.yml index 319b687e705..771694ac172 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -93,6 +93,7 @@ :purge_window_size: 10000 :ems: :ems_redhat: + :resolve_ip_addresses: true :service: :read_timeout: 1.hour :ems_kubernetes: diff --git a/spec/models/manageiq/providers/redhat/infra_manager/refresher_3_0_spec.rb b/spec/models/manageiq/providers/redhat/infra_manager/refresher_3_0_spec.rb index 20e0a89ba6f..802b3a3bdfe 100644 --- a/spec/models/manageiq/providers/redhat/infra_manager/refresher_3_0_spec.rb +++ b/spec/models/manageiq/providers/redhat/infra_manager/refresher_3_0_spec.rb @@ -1,9 +1,12 @@ describe ManageIQ::Providers::Redhat::InfraManager::Refresher do + let(:ip_address) { '192.168.252.231' } + before(:each) do guid, server, zone = EvmSpecHelper.create_guid_miq_server_zone - @ems = FactoryGirl.create(:ems_redhat, :zone => zone, :hostname => "192.168.252.231", :ipaddress => "192.168.252.231", :port => 8443) + @ems = FactoryGirl.create(:ems_redhat, :zone => zone, :hostname => ip_address, :ipaddress => ip_address, :port => 8443) @ems.update_authentication(:default => {:userid => "evm@manageiq.com", :password => "password"}) allow(@ems).to receive(:supported_api_versions).and_return([3]) + allow(@ems).to receive(:resolve_ip_address).with(ip_address).and_return(ip_address) end it ".ems_type" do diff --git a/spec/models/manageiq/providers/redhat/infra_manager/refresher_3_1_spec.rb b/spec/models/manageiq/providers/redhat/infra_manager/refresher_3_1_spec.rb index 19b2b526a22..4df16f826db 100644 --- a/spec/models/manageiq/providers/redhat/infra_manager/refresher_3_1_spec.rb +++ b/spec/models/manageiq/providers/redhat/infra_manager/refresher_3_1_spec.rb @@ -1,9 +1,12 @@ describe ManageIQ::Providers::Redhat::InfraManager::Refresher do + let(:ip_address) { '192.168.252.230' } + before(:each) do guid, server, zone = EvmSpecHelper.create_guid_miq_server_zone - @ems = FactoryGirl.create(:ems_redhat, :zone => zone, :hostname => "192.168.252.230", :ipaddress => "192.168.252.230", :port => 443) + @ems = FactoryGirl.create(:ems_redhat, :zone => zone, :hostname => ip_address, :ipaddress => ip_address, :port => 443) @ems.update_authentication(:default => {:userid => "evm@manageiq.com", :password => "password"}) allow(@ems).to receive(:supported_api_versions).and_return([3]) + allow(@ems).to receive(:resolve_ip_address).with(ip_address).and_return(ip_address) end it ".ems_type" do diff --git a/spec/models/manageiq/providers/redhat/infra_manager/refresher_target_vm_spec.rb b/spec/models/manageiq/providers/redhat/infra_manager/refresher_target_vm_spec.rb index 01fe8a24de1..7e1505c8bfd 100644 --- a/spec/models/manageiq/providers/redhat/infra_manager/refresher_target_vm_spec.rb +++ b/spec/models/manageiq/providers/redhat/infra_manager/refresher_target_vm_spec.rb @@ -1,8 +1,10 @@ describe ManageIQ::Providers::Redhat::InfraManager::Refresher do context 'targeted refresh of a Vm' do + let(:ip_address) { '192.168.1.31' } + before(:each) do _, _, zone = EvmSpecHelper.create_guid_miq_server_zone - @ems = FactoryGirl.create(:ems_redhat, :zone => zone, :hostname => "192.168.1.31", :ipaddress => "192.168.1.31", + @ems = FactoryGirl.create(:ems_redhat, :zone => zone, :hostname => ip_address, :ipaddress => ip_address, :port => 8443) @ems.update_authentication(:default => {:userid => "admin@internal", :password => "engine"}) @@ -13,6 +15,7 @@ :name => "Default") allow(@ems).to receive(:supported_api_versions).and_return([3, 4]) + allow(@ems).to receive(:resolve_ip_address).with(ip_address).and_return(ip_address) end it "should refresh a vm" do @@ -70,12 +73,15 @@ end context 'targeted refresh after vm migration' do + let(:ip_address) { '10.35.161.51' } + before(:each) do _guid, _server, zone = EvmSpecHelper.create_guid_miq_server_zone @ems = FactoryGirl.create(:ems_redhat, :zone => zone, - :hostname => "10.35.161.51", :ipaddress => "10.35.161.51", :port => 443) + :hostname => ip_address, :ipaddress => ip_address, :port => 443) @ems.update_authentication(:default => {:userid => "admin@internal", :password => "password"}) allow(@ems).to receive(:supported_api_versions).and_return([3]) + allow(@ems).to receive(:resolve_ip_address).with(ip_address).and_return(ip_address) end it 'should save the vms new host' do diff --git a/spec/models/manageiq/providers/redhat/infra_manager/vm_spec.rb b/spec/models/manageiq/providers/redhat/infra_manager/vm_spec.rb index cc6dc638de9..967a3ba4ec4 100644 --- a/spec/models/manageiq/providers/redhat/infra_manager/vm_spec.rb +++ b/spec/models/manageiq/providers/redhat/infra_manager/vm_spec.rb @@ -1,4 +1,6 @@ describe ManageIQ::Providers::Redhat::InfraManager::Vm do + let(:ip_address) { '192.168.1.31' } + context "#is_available?" do let(:ems) { FactoryGirl.create(:ems_redhat) } let(:host) { FactoryGirl.create(:host_redhat, :ext_management_system => ems) } @@ -116,10 +118,11 @@ describe "#disconnect_storage" do before(:each) do _, _, zone = EvmSpecHelper.create_guid_miq_server_zone - ems = FactoryGirl.create(:ems_redhat, :zone => zone, :hostname => "192.168.1.31", - :ipaddress => "192.168.1.31", :port => 8443) + ems = FactoryGirl.create(:ems_redhat, :zone => zone, :hostname => ip_address, + :ipaddress => ip_address, :port => 8443) ems.update_authentication(:default => {:userid => "admin@internal", :password => "engine"}) allow(ems).to receive(:supported_api_versions).and_return([3, 4]) + allow(ems).to receive(:resolve_ip_address).with(ip_address).and_return(ip_address) @storage = FactoryGirl.create(:storage, :ems_ref => "/api/storagedomains/ee745353-c069-4de8-8d76-ec2e155e2ca0") disk = FactoryGirl.create(:disk, :storage => @storage, :filename => "da123bb9-095a-4933-95f2-8032dfa332e1")