Skip to content

Commit

Permalink
Fixes #23995 - Updated hypervisors_update to bulk actions
Browse files Browse the repository at this point in the history
  • Loading branch information
ShimShtein authored and jlsherrill committed Aug 30, 2018
1 parent b9505e4 commit e0d2c87
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 31 deletions.
104 changes: 82 additions & 22 deletions app/lib/actions/katello/host/hypervisors_update.rb
Expand Up @@ -13,37 +13,86 @@ def run
end

def finalize
hypervisors = input[:hypervisors]
@hypervisors = input[:hypervisors]
return unless @hypervisors

if hypervisors
User.as_anonymous_admin do
hypervisors.each { |hypervisor| update_or_create_hypervisor(hypervisor) }
User.as_anonymous_admin do
load_resources

@hosts.each do |uuid, host|
update_subscription_facet(uuid, host)
end
end
end

def update_or_create_hypervisor(hypervisor_json)
organization = ::Organization.find_by(:label => hypervisor_json[:organization_label])
# Loads all resources needed for refreshing subscription facet
def load_resources
@organizations = ::Organization.where(label: hypervisors_field(:organization_label)).map { |org| [org.label, org] }.to_h
@hosts = {}

load_hosts_by_uuid
load_hosts_by_duplicate_name
create_missing_hosts

candlepin_data = ::Katello::Resources::Candlepin::Consumer.get(uuid: @hosts.keys)
@candlepin_attributes = candlepin_data.map { |consumer| [consumer[:uuid], consumer] }.to_h
end

def load_hosts_by_uuid
hosts_by_uuid = ::Host.eager_load(:subscription_facet).where(katello_subscription_facets: { uuid: hypervisors_field(:uuid) })
@hosts.merge(hosts_by_uuid.map { |host| [host.subscription_facet.uuid, host] }.to_h)
end

def load_hosts_by_duplicate_name
duplicate_names, duplicate_name_orgs = generate_duplicates_list

hosts_by_dup_name = ::Host.preload(:subscription_facet).where(name: duplicate_names.keys)

hosts_by_dup_name.each do |host|
validate_host_organization(host, duplicate_name_orgs[host.name].try(:id))
end

@hosts.merge!(hosts_by_dup_name.map { |host| [duplicate_names[host.name], host] }.to_h)
end

def create_missing_hosts
# remaining hypervisors
@hypervisors.each do |hypervisor|
next if @hosts.key?(hypervisor[:uuid])
duplicate_name, org = duplicate_name(hypervisor)
@hosts[hypervisor[:uuid]] = create_host_for_hypervisor(duplicate_name, org)
end
end

def generate_duplicates_list
duplicate_names = {}
duplicate_name_orgs = {}
@hypervisors.each do |hypervisor|
next if @hosts.key?(hypervisor[:uuid])

duplicate_name, org = duplicate_name(hypervisor)
duplicate_names[duplicate_name] = hypervisor[:uuid]
duplicate_name_orgs[duplicate_name] = org
end

# Since host names must be unique yet hypervisors may have unique subscription
# facets in different orgs
sanitized_name = ::Katello::Host::SubscriptionFacet.sanitize_name(hypervisor_json[:name])
duplicate_name = "virt-who-#{sanitized_name}-#{organization.id}"
host = ::Katello::Host::SubscriptionFacet.find_by(:uuid => hypervisor_json[:uuid]).try(:host)
host ||= ::Host.find_by(:name => duplicate_name)
if host && host.organization.try(:id) != organization.id
[duplicate_names, duplicate_name_orgs]
end

def validate_host_organization(host, organization)
if host.organization_id.nil? || host.organization_id != organization
fail _("Host '%{name}' does not belong to an organization") % {:name => host.name} unless host.organization
host = nil
end
end

host ||= create_host_for_hypervisor(duplicate_name, organization)
host.subscription_facet ||= ::Katello::Host::SubscriptionFacet.new
host.subscription_facet.host_id = host.id
host.subscription_facet.uuid = hypervisor_json[:uuid]
host.subscription_facet.import_database_attributes(host.subscription_facet.candlepin_consumer.consumer_attributes)
host.subscription_facet.save!
host.subscription_facet.update_subscription_status
host.save!
# extracts a single field from a given list og hypervisors data.
def hypervisors_field(field, hypervisors = @hypervisors)
hypervisors.map { |h| h[field] }.uniq
end

def duplicate_name(hypervisor)
organization = @organizations[hypervisor[:organization_label]]
sanitized_name = ::Katello::Host::SubscriptionFacet.sanitize_name(hypervisor[:name])
["virt-who-#{sanitized_name}-#{organization.id}", organization]
end

def create_host_for_hypervisor(name, organization, location = nil)
Expand All @@ -54,6 +103,17 @@ def create_host_for_hypervisor(name, organization, location = nil)
host
end

def update_subscription_facet(uuid, host)
host.subscription_facet ||= host.build_subscription_facet(uuid: uuid)
if @candlepin_attributes.key?(uuid)
host.subscription_facet.candlepin_consumer.consumer_attributes = @candlepin_attributes[uuid]
host.subscription_facet.import_database_attributes
host.subscription_facet.save!
host.subscription_facet.update_subscription_status(@candlepin_attributes[uuid].try(:[], :entitlementStatus))
end
host.save!
end

def rescue_strategy
Dynflow::Action::Rescue::Skip
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/katello/subscription_status.rb
Expand Up @@ -38,7 +38,7 @@ def to_global(_options = {})

def to_status(options = {})
return UNKNOWN unless host.subscription_facet.try(:uuid)
status_override = 'unsubscribed_hypervisor' if host.subscription_facet.hypervisor && host.subscription_facet.candlepin_consumer.entitlements.empty?
status_override = 'unsubscribed_hypervisor' if host.subscription_facet.hypervisor && !host.subscription_facet.candlepin_consumer.entitlements?
status_override ||= options.fetch(:status_override, nil)
status = status_override || Katello::Candlepin::Consumer.new(host.subscription_facet.uuid, host.organization.label).entitlement_status

Expand Down
8 changes: 8 additions & 0 deletions app/services/katello/candlepin/consumer.rb
Expand Up @@ -120,6 +120,14 @@ def compliance_reasons
self.class.friendly_compliance_reasons(Resources::Candlepin::Consumer.compliance(uuid)['reasons'])
end

def entitlements?
# use cahced consumer_attributes if possible
count = @consumer_attributes.try(:[], 'entitlementCount')
return count > 0 if count

!entitlements.empty?
end

def self.friendly_compliance_reasons(candlepin_reasons)
candlepin_reasons.map do |reason|
product_name = reason['productName'] || reason['attributes']['name']
Expand Down
28 changes: 20 additions & 8 deletions test/actions/katello/host/hypervisors_update_test.rb
Expand Up @@ -20,6 +20,16 @@ class HypervisorsUpdateTest < ActiveSupport::TestCase
@hypervisor_name = "virt-who-#{@host.name}-#{@organization.id}"
@host.update_attributes!(:name => @hypervisor_name)
@hypervisor_results = [{ :name => old_name, :uuid => @host.subscription_facet.uuid, :organization_label => @organization.label }]
::Katello::Resources::Candlepin::Consumer.stubs(:get).returns(
[
{
uuid: @host.subscription_facet.uuid,
entitlementStatus: Katello::SubscriptionStatus::UNKNOWN,
'guestIds' => ['test-id-1'],
'entitlementCount' => 0
}
]
)
end

let(:action_class) { ::Actions::Katello::Host::Hypervisors }
Expand All @@ -28,33 +38,35 @@ class HypervisorsUpdateTest < ActiveSupport::TestCase
it 'new hypervisor' do
@host.subscription_facet.destroy!
@host.reload
new_facet = ::Katello::Host::SubscriptionFacet.new
::Katello::Host::SubscriptionFacet.expects(:new).returns(new_facet)

action = create_action(::Actions::Katello::Host::HypervisorsUpdate)

plan_action(action, :hypervisors => @hypervisor_results)
finalize_action(action)

@host.reload
assert_not_nil @host.subscription_facet
end

it 'existing hypervisor, no facet' do
@host.subscription_facet.destroy!
@host.reload
::Host.expects(:find_by).with(:name => @hypervisor_name).returns(@host)
@host.subscription_facet.delete
@host.save!
action = create_action(::Actions::Katello::Host::HypervisorsUpdate)

plan_action(action, :hypervisors => @hypervisor_results)
finalize_action(action)
@host.reload
assert_not_nil @host.subscription_facet
end

it 'existing hypervisor, renamed' do
@hypervisor_results[0][:name] = 'hypervisor.renamed'
::Host.expects(:find_by).never
::Katello::Host::SubscriptionFacet.expects(:new).never
action = create_action(::Actions::Katello::Host::HypervisorsUpdate)

plan_action(action, :hypervisors => @hypervisor_results)
finalize_action(action)
assert_difference('::Katello::Host::SubscriptionFacet.count', 0) do
finalize_action(action)
end
end

it 'existing hypervisor, no org' do
Expand Down

0 comments on commit e0d2c87

Please sign in to comment.