diff --git a/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb b/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb index 8ecd1193670..1993f144e20 100644 --- a/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +++ b/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb @@ -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 diff --git a/app/models/katello/concerns/host_managed_extensions.rb b/app/models/katello/concerns/host_managed_extensions.rb index 293b2409066..b931ac3f78c 100644 --- a/app/models/katello/concerns/host_managed_extensions.rb +++ b/app/models/katello/concerns/host_managed_extensions.rb @@ -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 @@ -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 diff --git a/app/models/katello/concerns/smart_proxy_extensions.rb b/app/models/katello/concerns/smart_proxy_extensions.rb index d7a49bc7400..ffcebc25eb7 100644 --- a/app/models/katello/concerns/smart_proxy_extensions.rb +++ b/app/models/katello/concerns/smart_proxy_extensions.rb @@ -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) @@ -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: {} } diff --git a/lib/katello.rb b/lib/katello.rb index 3aa832c0dc3..3d10d49f448 100644 --- a/lib/katello.rb +++ b/lib/katello.rb @@ -6,6 +6,7 @@ require "oauth" require "gettext_i18n_rails" require "foreman-tasks" +require "foreman_remote_execution" require "rest_client" require "anemone" require "securerandom" diff --git a/test/models/concerns/host_managed_extensions_test.rb b/test/models/concerns/host_managed_extensions_test.rb index af97e16a326..dcf71786268 100644 --- a/test/models/concerns/host_managed_extensions_test.rb +++ b/test/models/concerns/host_managed_extensions_test.rb @@ -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