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 #36928 - (sorta) handle load balanced smart proxies when registering hosts #10804

Merged
merged 4 commits into from
Dec 11, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,20 @@ def client_authorized?
def update_host_registered_through(host, headers)
parent_host = get_parent_host(headers)
host.subscription_facet.update_attribute(:registered_through, parent_host)
content_source_id = get_content_source_id(parent_host)
set_host_content_source(host, parent_host)
end

def registering_thru_load_balancer?(hostname)
::SmartProxy.behind_load_balancer(hostname).present?
end

def set_host_content_source(host, content_source_hostname)
content_source_id = get_content_source_id(content_source_hostname)
if registering_thru_load_balancer?(content_source_hostname)
Rails.logger.info "Host %s registered through load balancer %s" % [host.name, content_source_hostname]
content_source_id = ::SmartProxy.behind_load_balancer(content_source_hostname)&.first&.id
end
Rails.logger.warn "Host %s registered through unknown proxy %s" % [host.name, content_source_hostname] if content_source_id.nil?
host.content_facet.update_attribute(:content_source_id, content_source_id)
end

Expand Down
13 changes: 9 additions & 4 deletions app/models/katello/concerns/host_managed_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,17 @@ def update_os_from_facts

def remote_execution_proxies(provider, *_rest)
proxies = super
if (name = subscription_facet&.registered_through)
registered_through = SmartProxy.with_features(provider)
name = subscription_facet&.registered_through
result = []
if name.present?
result = SmartProxy.with_features(provider)
.authorized
.where(name: name)
if result.blank?
result = SmartProxy.authorized.behind_load_balancer(name)
end
end
proxies[:registered_through] = registered_through || []
proxies[:registered_through] = result
proxies
end
end
Expand Down Expand Up @@ -193,7 +198,7 @@ def self.find_with_expiring_pools(_key, _operator, days_from_now)
property :content_views, 'ContentView', desc: 'Returns content views associated with the host'
property :installed_packages, array_of: 'InstalledPackage', desc: 'Returns a list of packages installed on the host'
end
end
end # of included block

def check_host_registration
if subscription_facet
Expand Down
21 changes: 21 additions & 0 deletions app/models/katello/concerns/smart_proxy_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ def refresh
}
scope :with_content, -> { with_features(PULP_FEATURE, PULP_NODE_FEATURE, PULP3_FEATURE) }

def self.load_balanced
proxies = self.with_content # load balancing is only supported for pulp proxies
ids = proxies.select { |proxy| proxy.load_balanced? }.map(&:id)
proxies.where(id: ids)
end

def self.behind_load_balancer(load_balancer_hostname)
proxies = self.with_content
ids = proxies.select { |proxy| proxy.load_balanced? && proxy.registration_host == load_balancer_hostname }.map(&:id)
proxies.where(id: ids)
end

def self.with_repo(repo)
joins(:capsule_lifecycle_environments).
where("#{Katello::CapsuleLifecycleEnvironment.table_name}.lifecycle_environment_id" => repo.environment_id)
Expand Down Expand Up @@ -121,6 +133,15 @@ def alternate_content_sources
SmartProxy.joins(:smart_proxy_alternate_content_sources).where('katello_smart_proxy_alternate_content_sources.smart_proxy_id' => self.id)
end

def registration_host
url = self.setting('Registration', 'registration_url').presence || self.url
URI.parse(url).host
end

def load_balanced?
URI.parse(self.url).host != self.registration_host
end

def update_content_counts!
# {:content_view_versions=>{87=>{:repositories=>{1=>{:metadata=>{},:counts=>{:rpms=>98, :module_streams=>9898}}}}}
new_content_counts = { content_view_versions: {} }
Expand Down
1 change: 1 addition & 0 deletions lib/katello.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require "oauth"
require "gettext_i18n_rails"
require "foreman-tasks"
require "foreman_remote_execution"
Copy link
Member

Choose a reason for hiding this comment

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

Given

gem.add_dependency "foreman_remote_execution", ">= 7.1.0"

I am rather confident we never have a Katello install w/o REX.

But at the same time it indicates that the way we load stuff differs so heavily in prod/dev/test, that things go weird.

Copy link
Member

Choose a reason for hiding this comment

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

require "rest_client"
require "anemone"
require "securerandom"
Expand Down
17 changes: 17 additions & 0 deletions test/models/concerns/host_managed_extensions_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,23 @@ def test_check_cve_attributes
refute host_attrs.key?(:content_view_id)
refute host_attrs.key?(:lifecycle_environment_id)
end

def test_remote_execution_proxies_registered_through
host = FactoryBot.create(:host, :with_content, :with_subscription, :content_view => @library_view, :lifecycle_environment => @library)
host.subscription_facet.expects(:registered_through).returns('test-proxy.example.com')
rex_feature = Feature.where(:name => "Remote Execution").first_or_create
test_proxy = FactoryBot.create(:smart_proxy, :features => [rex_feature], :url => 'http://test-proxy.example.com:9090', :name => 'test-proxy.example.com')
assert_equal host.remote_execution_proxies(rex_feature.name)[:registered_through], [test_proxy]
end

def test_remote_execution_proxies_registered_through_load_balancer
host = FactoryBot.create(:host, :with_content, :with_subscription, :content_view => @library_view, :lifecycle_environment => @library)
host.subscription_facet.expects(:registered_through).returns('unknown-proxy.example.com')
rex_feature = Feature.where(:name => "Remote Execution").first_or_create
proxy_behind_lb = FactoryBot.create(:smart_proxy, :features => [rex_feature], :url => 'http://test-proxy.example.com:9090', :name => 'test-proxy.example.com')
::SmartProxy.expects(:behind_load_balancer).with('unknown-proxy.example.com').returns([proxy_behind_lb])
assert_equal host.remote_execution_proxies(rex_feature.name)[:registered_through], [proxy_behind_lb]
end
end

class HostManagedExtensionsUpdateTest < HostManagedExtensionsTestBase
Expand Down
Loading