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

Fixes #31790 - always delegate bootserver IP resolution to smart proxy #8303

Merged
merged 1 commit into from Apr 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 14 additions & 19 deletions app/models/concerns/orchestration/dhcp.rb
Expand Up @@ -79,28 +79,23 @@ def del_dhcp_conflicts
end

def boot_server
# if we don't manage tftp for IPv4 at all, we dont create a next-server entry.
return unless tftp?

# first try to ask our IPv4 TFTP server for its boot server
bs = tftp.bootServer
# if that failed, trying to guess out tftp next server based on the smart proxy hostname
bs ||= URI.parse(subnet.tftp.url).host

# only smart proxies with V2 API are supported
if subnet.dhcp.has_capability?(:DHCP, :dhcp_filename_hostname)
# we no longer convert the boot server to IPv4 - smart proxy modules are required to do so if they don't support hostname
bs
else
begin
Foreman::Deprecation.deprecation_warning('1.25', "DHCP proxy does not report dhcp_filename_* capability and reverse DNS search in Foreman will be removed.")
ip = NicIpResolver.new(:nic => self).to_ip_address(bs) if bs.present?
return ip unless ip.nil?
failure _("Unable to determine the host's boot server. The DHCP smart proxy failed to provide this information and this subnet is not provided with TFTP services.")
rescue => e
failure _("failed to detect boot server: %s") % e, e
end
unless subnet.dhcp.has_capability?(:DHCP, :dhcp_filename_hostname)
logger.warn "DHCP proxy does not report dhcp_filename_ipv4 or dhcp_filename_hostname capability. Foreman will pass boot server #{boot_server_or_proxy_hostname} as-is, the request might fail."
end
upadhyeammit marked this conversation as resolved.
Show resolved Hide resolved
lzap marked this conversation as resolved.
Show resolved Hide resolved

boot_server_or_proxy_hostname
end

def boot_server_or_proxy_hostname
if tftp.bootServer.nil?
tftp_proxy_hostname = URI.parse(subnet.tftp.url).host
logger.warn "Using TFTP Smart Proxy hostname as the boot server name: #{tftp_proxy_hostname}"
return tftp_proxy_hostname
end

tftp.bootServer
end

private
Expand Down
13 changes: 6 additions & 7 deletions test/models/orchestration/dhcp_test.rb
Expand Up @@ -87,7 +87,7 @@ def setup
end

test "provision interface DHCP records should contain default filename/next-server attributes for IPv4 tftp proxy" do
ProxyAPI::TFTP.any_instance.expects(:bootServer).returns('192.168.1.1')
ProxyAPI::TFTP.any_instance.expects(:bootServer).returns('192.168.1.1').twice
subnet = FactoryBot.build(:subnet_ipv4, :dhcp, :tftp)
h = as_admin do
FactoryBot.create(:host, :with_dhcp_orchestration, :with_tftp_dual_stack_orchestration, :subnet => subnet)
Expand All @@ -98,7 +98,7 @@ def setup
end

test "provision interface DHCP records should contain PXELinux BIOS filename/next-server attributes for IPv4 tftp proxy" do
ProxyAPI::TFTP.any_instance.expects(:bootServer).returns('192.168.1.1')
ProxyAPI::TFTP.any_instance.expects(:bootServer).returns('192.168.1.1').twice
subnet = FactoryBot.build(:subnet_ipv4, :dhcp, :tftp)
h = as_admin do
FactoryBot.create(:host, :with_dhcp_orchestration, :with_tftp_dual_stack_orchestration, :subnet => subnet, :pxe_loader => 'PXELinux BIOS')
Expand Down Expand Up @@ -472,12 +472,11 @@ def host_with_loader(loader)
assert_empty nic.errors
end

test 'should error out on no capabilities' do
Foreman::Deprecation.expects(:deprecation_warning).once
test 'should warn on no capabilities' do
Foreman::Logging.logger('app').expects(:warn)
SmartProxy.any_instance.expects(:capabilities).with(:DHCP).returns([])
ProxyAPI::TFTP.any_instance.stubs(:bootServer).returns('proxy.example.com')
Resolv::DNS.any_instance.expects(:getaddress).once.returns("127.12.0.1")
assert_equal '127.12.0.1', nic.send(:boot_server)
ProxyAPI::TFTP.any_instance
nic.send(:boot_server)
assert_empty nic.errors
end
end
Expand Down