Class: Katello::Host::SubscriptionFacet

Inherits:
Model
  • Object
show all
Includes:
DirtyAssociations, Facets::Base
Defined in:
app/models/katello/host/subscription_facet.rb

Constant Summary collapse

DEFAULT_TYPE =
'system'.freeze
DMI_UUID_ALLOWED_DUPS =
['', 'Not Settable', 'Not Present'].freeze
DMI_UUID_OVERRIDE_PARAM =
'dmi_uuid_override'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Model

#destroy!

Instance Attribute Details

#factsObject

Returns the value of attribute facts.



29
30
31
# File 'app/models/katello/host/subscription_facet.rb', line 29

def facts
  @facts
end

Class Method Details

.ignore_os?(host_os, rhsm_facts) ⇒ Boolean

Returns:

  • (Boolean)


204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'app/models/katello/host/subscription_facet.rb', line 204

def self.ignore_os?(host_os, rhsm_facts)
  if host_os.nil?
    return false
  end

  name = rhsm_facts['distribution.name']
  version = rhsm_facts['distribution.version']
  major, minor = version&.split('.')
  return host_os.name == 'CentOS' &&
    !host_os.major.nil? &&
    name == 'CentOS' &&
    minor.blank? &&
    host_os.major == major
end

.new_host_from_facts(facts, org, location) ⇒ Object



189
190
191
192
# File 'app/models/katello/host/subscription_facet.rb', line 189

def self.new_host_from_facts(facts, org, location)
  name = propose_name_from_facts(facts)
  ::Host::Managed.new(:name => name, :organization => org, :location => location, :managed => false)
end

.override_dmi_uuid?(host_uuid) ⇒ Boolean

Returns:

  • (Boolean)


185
186
187
# File 'app/models/katello/host/subscription_facet.rb', line 185

def self.override_dmi_uuid?(host_uuid)
  Setting[:host_dmi_uuid_duplicates].include?(host_uuid)
end

.populate_fields_from_facts(host, parser, _type, _source_proxy) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'app/models/katello/host/subscription_facet.rb', line 285

def self.populate_fields_from_facts(host, parser, _type, _source_proxy)
  has_convert2rhel = parser.facts.key?('conversions.env.CONVERT2RHEL_THROUGH_FOREMAN')
  return unless host.subscription_facet || has_convert2rhel
  # Add in custom convert2rhel fact if system was converted using convert2rhel through Katello
  # We want the value nil unless the custom fact is present otherwise we get a 0 in the database which if debugging
  # might make you think it was converted2rhel but not with satellite, that is why I have the ternary below.
  facet = host.subscription_facet || host.build_subscription_facet
  facet.attributes = {
    convert2rhel_through_foreman: has_convert2rhel ? ::Foreman::Cast.to_bool(parser.facts['conversions.env.CONVERT2RHEL_THROUGH_FOREMAN']) : nil,

  }.compact
  facet.save unless facet.new_record?
end

.propose_custom_fact(facts) ⇒ Object



229
230
231
232
233
234
235
236
# File 'app/models/katello/host/subscription_facet.rb', line 229

def self.propose_custom_fact(facts)
  setting_fact = Setting[:register_hostname_fact]
  only_use_custom_fact = Setting[:register_hostname_fact_strict_match]

  if !setting_fact.blank? && !facts[setting_fact].blank? && (only_use_custom_fact || ::Host.where(:name => setting_fact.downcase).any?)
    facts[setting_fact]
  end
end

.propose_existing_hostname(facts) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'app/models/katello/host/subscription_facet.rb', line 238

def self.propose_existing_hostname(facts)
  if propose_custom_fact(facts)
    name = propose_custom_fact(facts)
  elsif ::Host.where(:name => facts['network.hostname'].downcase).any?
    name = facts['network.hostname']
  elsif !facts['network.fqdn'].blank? && ::Host.where(:name => facts['network.fqdn'].downcase).any?
    name = facts['network.fqdn']
  elsif !facts['network.hostname-override'].blank? && ::Host.where(:name => facts['network.hostname-override'].downcase).any?
    name = facts['network.hostname-override']
  else
    name = facts['network.hostname'] #fallback to default, even if it doesn't exist
  end

  name.downcase
end

.propose_name_from_facts(facts) ⇒ Object



219
220
221
222
223
224
225
226
227
# File 'app/models/katello/host/subscription_facet.rb', line 219

def self.propose_name_from_facts(facts)
  setting_fact = Setting[:register_hostname_fact]
  if !setting_fact.blank? && facts[setting_fact] && facts[setting_fact] != 'localhost'
    facts[setting_fact]
  else
    Rails.logger.warn(_("register_hostname_fact set for %s, but no fact found, or was localhost.") % setting_fact) unless setting_fact.blank?
    [facts['network.fqdn'], facts['network.hostname-override'], facts['network.hostname']].find { |name| !name.blank? && name != 'localhost' }
  end
end

.sanitize_name(name) ⇒ Object



258
259
260
# File 'app/models/katello/host/subscription_facet.rb', line 258

def self.sanitize_name(name)
  name.gsub('_', '-').chomp('.').downcase
end

.update_facts(host, rhsm_facts) ⇒ Object



194
195
196
197
198
199
200
201
202
# File 'app/models/katello/host/subscription_facet.rb', line 194

def self.update_facts(host, rhsm_facts)
  return if host.build? || rhsm_facts.nil?
  rhsm_facts[:_type] = RhsmFactName::FACT_TYPE
  rhsm_facts[:_timestamp] = Time.now.to_s
  if ignore_os?(host.operatingsystem, rhsm_facts)
    rhsm_facts[:ignore_os] = true
  end
  ::HostFactImporter.new(host).import_facts(rhsm_facts)
end

Instance Method Details

#backend_update_needed?Boolean

Returns:

  • (Boolean)


270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'app/models/katello/host/subscription_facet.rb', line 270

def backend_update_needed?
  %w(release_version service_level purpose_role purpose_usage).each do |method|
    if self.send("#{method}_changed?")
      Rails.logger.debug("backend_update_needed: subscription facet #{method} changed")
      return true
    end
  end
  facet = self.host&.content_facet
  if facet&.cves_changed? && !facet.new_record?
    Rails.logger.debug("backend_update_needed: content facet CVEs changed")
    return true
  end
  false
end

#candlepin_consumerObject



266
267
268
# File 'app/models/katello/host/subscription_facet.rb', line 266

def candlepin_consumer
  @candlepin_consumer ||= Katello::Candlepin::Consumer.new(self.uuid, self.host.organization.label)
end

#candlepin_environmentsObject



144
145
146
147
148
149
150
151
152
# File 'app/models/katello/host/subscription_facet.rb', line 144

def candlepin_environments
  if self.host.content_facet
    self.host.content_facet.content_view_environments.map do |cve|
      { :id => cve.content_view.cp_environment_id(cve.lifecycle_environment) }
    end
  else
    [{ :id => self.host.organization.default_content_view.cp_environment_id(self.host.organization.library) }]
  end
end

#candlepin_environments_cp_idsObject



154
155
156
# File 'app/models/katello/host/subscription_facet.rb', line 154

def candlepin_environments_cp_ids
  candlepin_environments.map { |e| e[:id] }
end

#consumer_attributesObject



130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'app/models/katello/host/subscription_facet.rb', line 130

def consumer_attributes
  attrs = {
    :usage => purpose_usage,
    :role => purpose_role,
    :serviceLevel => service_level,
    :releaseVer => release_version,
    :environments => self.candlepin_environments,
    :installedProducts => self.installed_products.map(&:consumer_attributes),
    :guestIds => virtual_guest_uuids,
  }
  attrs[:facts] = facts if facts
  HashWithIndifferentAccess.new(attrs)
end

#consumer_cve_order_from_candlepinObject



162
163
164
# File 'app/models/katello/host/subscription_facet.rb', line 162

def consumer_cve_order_from_candlepin
  Katello::Resources::Candlepin::Consumer.get(uuid)['environments'].map { |e| e['id'] }
end

#content_view_environmentsObject



158
159
160
# File 'app/models/katello/host/subscription_facet.rb', line 158

def content_view_environments
  self.host.content_facet.try(:content_view_environments)
end

#cves_ordered_correctly?Boolean

Returns:

  • (Boolean)


166
167
168
# File 'app/models/katello/host/subscription_facet.rb', line 166

def cves_ordered_correctly?
  consumer_cve_order_from_candlepin == candlepin_environments_cp_ids
end

#dmi_uuid_overrideObject



174
175
176
# File 'app/models/katello/host/subscription_facet.rb', line 174

def dmi_uuid_override
  HostParameter.find_by(name: DMI_UUID_OVERRIDE_PARAM, host: host)
end

#host_typeObject



36
37
38
39
# File 'app/models/katello/host/subscription_facet.rb', line 36

def host_type
  host_facts = self.host.facts
  host_facts["virt::host_type"] || host_facts["hypervisor::type"]
end

#import_database_attributes(consumer_params = candlepin_consumer.consumer_attributes) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'app/models/katello/host/subscription_facet.rb', line 46

def import_database_attributes(consumer_params = candlepin_consumer.consumer_attributes)
  update_hypervisor(consumer_params)
  update_guests(consumer_params)

  if consumer_params['facts']
    self.dmi_uuid = consumer_params['facts']['dmi.system.uuid']
  end

  self.service_level = consumer_params['serviceLevel'] unless consumer_params['serviceLevel'].nil?
  self.registered_at = consumer_params['created'] unless consumer_params['created'].blank?
  self.last_checkin = consumer_params['lastCheckin'] unless consumer_params['lastCheckin'].blank?
  self.update_installed_products(consumer_params['installedProducts']) if consumer_params.key?('installedProducts')
  self.purpose_role = consumer_params['role'] unless consumer_params['role'].nil?
  self.purpose_usage = consumer_params['usage'] unless consumer_params['usage'].nil?

  unless consumer_params['releaseVer'].nil?
    release = consumer_params['releaseVer']
    release = release['releaseVer'] if release.is_a?(Hash)
    self.release_version = release
  end
end

#organizationObject



170
171
172
# File 'app/models/katello/host/subscription_facet.rb', line 170

def organization
  self.host.organization
end

#productsObject



254
255
256
# File 'app/models/katello/host/subscription_facet.rb', line 254

def products
  Katello::Product.joins(:subscriptions => {:pools => :subscription_facets}).where("#{Katello::Host::SubscriptionFacet.table_name}.id" => self.id).enabled.uniq
end

#unsubscribed_hypervisor?Boolean

Returns:

  • (Boolean)


262
263
264
# File 'app/models/katello/host/subscription_facet.rb', line 262

def unsubscribed_hypervisor?
  self.hypervisor && !self.candlepin_consumer.entitlements?
end

#update_compliance_reasons(reasons) ⇒ Object



74
75
76
77
78
79
80
81
82
# File 'app/models/katello/host/subscription_facet.rb', line 74

def update_compliance_reasons(reasons)
  reasons = Katello::Candlepin::Consumer.friendly_compliance_reasons(reasons)

  existing = self.compliance_reasons.pluck(:reason)
  to_delete = existing - reasons
  to_create = reasons - existing
  self.compliance_reasons.where(:reason => to_delete).destroy_all if to_delete.any?
  to_create.each { |reason| self.compliance_reasons.create(:reason => reason) }
end

#update_dmi_uuid_override(host_uuid = nil) ⇒ Object



178
179
180
181
182
183
# File 'app/models/katello/host/subscription_facet.rb', line 178

def update_dmi_uuid_override(host_uuid = nil)
  host_uuid ||= SecureRandom.uuid
  param = HostParameter.find_or_create_by(name: DMI_UUID_OVERRIDE_PARAM, host: host)
  param.update!(value: host_uuid)
  param
end

#update_from_consumer_attributes(consumer_params) ⇒ Object



41
42
43
44
# File 'app/models/katello/host/subscription_facet.rb', line 41

def update_from_consumer_attributes(consumer_params)
  import_database_attributes(consumer_params)
  self.facts = consumer_params['facts'] unless consumer_params['facts'].blank?
end

#update_guests(consumer_params) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'app/models/katello/host/subscription_facet.rb', line 103

def update_guests(consumer_params)
  if self.hypervisor
    if !consumer_params.try(:[], 'guestIds').empty?
      guest_ids = consumer_params['guestIds'].map do |id|
        case id
        when Hash
          id['guestId'].downcase
        when String
          id.downcase
        end
      end

      guest_ids = FactValue.where("lower(value) IN (?)", guest_ids).
                            where(:fact_name_id => FactName.where(:name => 'virt::uuid')).
                            pluck(:host_id)
    else
      guest_ids = self.candlepin_consumer.virtual_guests.pluck(:id)
    end

    subscription_facets = SubscriptionFacet.where(:host_id => guest_ids).
                                            where("hypervisor_host_id != ? OR hypervisor_host_id is NULL", self.host.id)
    subscription_facets.update_all(:hypervisor_host_id => self.host.id)
  elsif (virtual_host = self.candlepin_consumer.virtual_host)
    self.hypervisor_host = virtual_host
  end
end

#update_hypervisor(consumer_params = candlepin_consumer.consumer_attributes) ⇒ Object



92
93
94
95
96
97
98
99
100
101
# File 'app/models/katello/host/subscription_facet.rb', line 92

def update_hypervisor(consumer_params = candlepin_consumer.consumer_attributes)
  if consumer_params.try(:[], 'type').try(:[], 'label') == 'hypervisor'
    self.hypervisor = true
  elsif !consumer_params.try(:[], 'guestIds').empty?
    self.hypervisor = true
  elsif !candlepin_consumer.virtual_guests.empty?
    # Check by calling out to Candlepin last for efficiency
    self.hypervisor = true
  end
end

#update_installed_products(consumer_installed_product_list) ⇒ Object



68
69
70
71
72
# File 'app/models/katello/host/subscription_facet.rb', line 68

def update_installed_products(consumer_installed_product_list)
  self.installed_products = consumer_installed_product_list.map do |consumer_installed_product|
    InstalledProduct.find_or_create_from_consumer(consumer_installed_product)
  end
end

#virtual_guest_uuidsObject



88
89
90
# File 'app/models/katello/host/subscription_facet.rb', line 88

def virtual_guest_uuids
  virtual_guests.pluck("#{Katello::Host::SubscriptionFacet.table_name}.uuid")
end

#virtual_guestsObject



84
85
86
# File 'app/models/katello/host/subscription_facet.rb', line 84

def virtual_guests
  ::Host.joins(:subscription_facet).where("#{self.class.table_name}.hypervisor_host_id" => self.host_id)
end