katello 3.13.0 → 3.13.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of katello might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f961beeeec312626ba251c4117d82ed9452aac09675bca3dffebd8b678fb144b
4
- data.tar.gz: ba3994e7202a712f93bfcbab5078abd3f4e78700586415c99e1251bcb1ad4dcd
3
+ metadata.gz: fffaa8a0526b0aebf3579586d7b093f10024d6f9db1f181d26eba976d2a08dbd
4
+ data.tar.gz: 804ff8b52e48b758f7da0980e3b7409a05ccbf372b9feab000917c9f5c0830f2
5
5
  SHA512:
6
- metadata.gz: 24d89c99f0f85417717c8a3bab52579d71eb159d760331cb2b8f347a113fd21ca86004ecbf5c3d356f810729d2fa0c5e58a29e345a2d86d0c1723218ec0a6e76
7
- data.tar.gz: 7b07f9577131a54a5c72cd1ee4139d722f6ed46250269bbd4acb27d9d0f036740847a84da0bf196eada80ef63309f34b3598a55bbca254fcac6f3d35669f3b9e
6
+ metadata.gz: 37bee683b2faa62bd1c3b47f7f0b8f1023293aa5dd3d1b1f4cfb4a451551184e6553730f38dffa47d2cc003e508453197d81f792c8adc6c9d682c718f884bbcb
7
+ data.tar.gz: 3a82db81d710266ead4f21fc725acf782cbb0b43b9e3a6c2c5ca04e32a826316225a2af5145153edc1277e920f5b366def5a55184ed9ae296f8d2e66d22728fe
@@ -198,10 +198,8 @@ module Katello
198
198
 
199
199
  #api :POST, "/environments/:environment_id/consumers", N_("Register a consumer in environment")
200
200
  def consumer_create
201
- content_view_environment = find_content_view_environment
202
- host = Katello::Host::SubscriptionFacet.find_or_create_host(content_view_environment.environment.organization, rhsm_params)
201
+ host = Katello::RegistrationManager.process_registration(rhsm_params, find_content_view_environment)
203
202
 
204
- Katello::RegistrationManager.register_host(host, rhsm_params, content_view_environment)
205
203
  host.reload
206
204
 
207
205
  update_host_registered_through(host, request.headers)
@@ -227,9 +225,8 @@ module Katello
227
225
  User.current = User.anonymous_admin
228
226
  additional_set_taxonomy
229
227
  activation_keys = find_activation_keys
230
- host = Katello::Host::SubscriptionFacet.find_or_create_host(activation_keys.first.organization, rhsm_params)
231
228
 
232
- Katello::RegistrationManager.register_host(host, rhsm_params, nil, activation_keys)
229
+ host = Katello::RegistrationManager.process_registration(rhsm_params, nil, activation_keys)
233
230
 
234
231
  update_host_registered_through(host, request.headers)
235
232
  host.reload
@@ -59,7 +59,7 @@ module Katello
59
59
  def index_relation
60
60
  puppet_modules = ContentViewPuppetModule.where(:content_view_id => @view)
61
61
  puppet_modules = puppet_modules.where(:name => params[:name]) if params[:name]
62
- puppet_modules = puppet_modules.where(:pulp_id => params[:uuid]) if params[:uuid]
62
+ puppet_modules = puppet_modules.where(:uuid => params[:uuid]) if params[:uuid]
63
63
  puppet_modules = puppet_modules.where(:author => params[:author]) if params[:author]
64
64
  puppet_modules
65
65
  end
@@ -82,8 +82,7 @@ module Katello
82
82
  def create
83
83
  rhsm_params = params_to_rhsm_params
84
84
 
85
- host = Katello::Host::SubscriptionFacet.find_or_create_host(@content_view_environment.environment.organization, rhsm_params)
86
- Katello::RegistrationManager.register_host(host, rhsm_params, @content_view_environment)
85
+ host = Katello::RegistrationManager.process_registration(rhsm_params, @content_view_environment)
87
86
  host.reload
88
87
  ::Katello::Host::SubscriptionFacet.update_facts(host, rhsm_params[:facts]) unless rhsm_params[:facts].blank?
89
88
 
@@ -3,7 +3,6 @@ module Actions
3
3
  module ContentViewEnvironment
4
4
  class Destroy < Actions::Base
5
5
  def plan(cv_env, options = {})
6
- skip_cp_update = options.fetch(:skip_candlepin_update, false)
7
6
  skip_repo_destroy = options.fetch(:skip_repo_destroy, false)
8
7
  organization_destroy = options.fetch(:organization_destroy, false)
9
8
  content_view = cv_env.content_view
@@ -25,7 +24,7 @@ module Actions
25
24
  plan_action(ContentViewPuppetEnvironment::Destroy, puppet_env) unless organization_destroy
26
25
  end
27
26
  end
28
- plan_action(Candlepin::Environment::Destroy, cp_id: cv_env.cp_id) unless skip_cp_update
27
+ plan_action(Candlepin::Environment::Destroy, cp_id: cv_env.cp_id) unless organization_destroy
29
28
  plan_self(:id => cv_env.id)
30
29
  end
31
30
  end
@@ -18,6 +18,15 @@ module Actions
18
18
 
19
19
  if host.subscription_facet
20
20
  consumer_params ||= host.subscription_facet.consumer_attributes
21
+
22
+ host_uuid = consumer_params.dig(:facts, 'dmi.system.uuid')
23
+ if ::Katello::Host::SubscriptionFacet.override_dmi_uuid?(host_uuid)
24
+ # if host reported a dmi uuid to treat as a duplicate, override it with the stored host param
25
+ override_value = host.subscription_facet.dmi_uuid_override&.value
26
+ override_value ||= host.subscription_facet.update_dmi_uuid_override&.value
27
+ consumer_params[:facts]['dmi.system.uuid'] = override_value
28
+ end
29
+
21
30
  cp_update = plan_action(::Actions::Candlepin::Consumer::Update, host.subscription_facet.uuid, consumer_params)
22
31
  end
23
32
 
@@ -65,7 +65,7 @@ module Actions
65
65
  end
66
66
 
67
67
  def remove_content_view_environment(cv_env)
68
- plan_action(ContentViewEnvironment::Destroy, cv_env, :skip_repo_destroy => true, :skip_candlepin_update => true, :organization_destroy => true)
68
+ plan_action(ContentViewEnvironment::Destroy, cv_env, :skip_repo_destroy => true, :organization_destroy => true)
69
69
  end
70
70
 
71
71
  def remove_content_views(organization)
@@ -10,6 +10,7 @@ module Actions
10
10
  repository_creation = options.fetch(:repository_creation, false)
11
11
  source_repository = options.fetch(:source_repository, nil)
12
12
  source_repository ||= repository.target_repository if repository.link?
13
+ smart_proxy_id = options.fetch(:capsule_id, SmartProxy.pulp_master.id)
13
14
  if repository_creation
14
15
  matching_content = false
15
16
  else
@@ -17,7 +18,7 @@ module Actions
17
18
  end
18
19
 
19
20
  plan_pulp_action([Pulp::Repository::DistributorPublish, Pulp3::Orchestration::Repository::GenerateMetadata],
20
- repository, SmartProxy.pulp_master,
21
+ repository, SmartProxy.find(smart_proxy_id),
21
22
  :force => force,
22
23
  :source_repository => source_repository,
23
24
  :matching_content => matching_content,
@@ -34,6 +34,7 @@ module Katello
34
34
  attr_accessor :facts
35
35
 
36
36
  DMI_UUID_ALLOWED_DUPS = ['', 'Not Settable', 'Not Present'].freeze
37
+ DMI_UUID_OVERRIDE_PARAM = 'dmi_uuid_override'.freeze
37
38
 
38
39
  def host_type
39
40
  host_facts = self.host.facts
@@ -169,6 +170,17 @@ module Katello
169
170
  self.host.organization
170
171
  end
171
172
 
173
+ def dmi_uuid_override
174
+ HostParameter.find_by(name: DMI_UUID_OVERRIDE_PARAM, host: host)
175
+ end
176
+
177
+ def update_dmi_uuid_override(host_uuid = nil)
178
+ host_uuid ||= SecureRandom.uuid
179
+ param = HostParameter.find_or_create_by(name: DMI_UUID_OVERRIDE_PARAM, host: host)
180
+ param.update_attributes!(value: host_uuid)
181
+ param
182
+ end
183
+
172
184
  def update_subscription_status(status_override = nil)
173
185
  update_status(::Katello::SubscriptionStatus, status_override: status_override)
174
186
 
@@ -187,6 +199,10 @@ module Katello
187
199
  host.refresh_global_status!
188
200
  end
189
201
 
202
+ def self.override_dmi_uuid?(host_uuid)
203
+ Setting[:host_dmi_uuid_duplicates].include?(host_uuid)
204
+ end
205
+
190
206
  def self.new_host_from_facts(facts, org, location)
191
207
  name = propose_name_from_facts(facts)
192
208
  ::Host::Managed.new(:name => name, :organization => org, :location => location, :managed => false)
@@ -199,17 +215,6 @@ module Katello
199
215
  host.import_facts(rhsm_facts)
200
216
  end
201
217
 
202
- def self.find_or_create_host(organization, rhsm_params)
203
- host = find_host(rhsm_params[:facts], organization)
204
- host ||= Katello::Host::SubscriptionFacet.new_host_from_facts(
205
- rhsm_params[:facts],
206
- organization,
207
- Location.default_host_subscribe_location!
208
- )
209
- host.organization = organization unless host.organization
210
- host
211
- end
212
-
213
218
  def self.propose_name_from_facts(facts)
214
219
  setting_fact = Setting[:register_hostname_fact]
215
220
  if !setting_fact.blank? && facts[setting_fact] && facts[setting_fact] != 'localhost'
@@ -255,45 +260,6 @@ module Katello
255
260
  ForemanTasks.sync_task(Actions::Katello::Host::RemoveSubscriptions, self.host, pools_with_quantities)
256
261
  end
257
262
 
258
- def self.find_host(facts, organization)
259
- host_name = propose_existing_hostname(facts)
260
- host_uuid = facts['dmi.system.uuid']
261
- uuid_fact_id = RhsmFactName.find_by(name: 'dmi::system::uuid')&.id || -1
262
-
263
- hosts = ::Host.unscoped.distinct.left_outer_joins(:fact_values)
264
- .where("#{::Host.table_name}.name = ? OR (#{FactValue.table_name}.fact_name_id = ?
265
- AND #{FactValue.table_name}.value = ? AND #{FactValue.table_name}.value NOT IN (?))", host_name, uuid_fact_id, host_uuid, DMI_UUID_ALLOWED_DUPS)
266
-
267
- return if hosts.empty?
268
-
269
- hosts = hosts.where(organization_id: [organization.id, nil])
270
- hosts_size = hosts.size
271
-
272
- if hosts_size == 0 # not in the correct org
273
- #TODO: http://projects.theforeman.org/issues/11532
274
- fail Katello::Errors::RegistrationError, _("Host with name %{host_name} is currently registered to a different org, please migrate host to %{org_name}.") %
275
- {:org_name => organization.name, :host_name => host_name }
276
- end
277
-
278
- if hosts_size == 1
279
- host = hosts.first
280
-
281
- if host.name == host_name
282
- unless host.build
283
- found_uuid = host.fact_values.where(fact_name_id: uuid_fact_id).first
284
- if found_uuid && found_uuid.value != host_uuid
285
- fail Katello::Errors::RegistrationError, _("This host is reporting a DMI UUID that differs from the existing registration.")
286
- end
287
- end
288
-
289
- return host
290
- end
291
- end
292
-
293
- hostnames = hosts.pluck(:name).sort.join(', ')
294
- fail Katello::Errors::RegistrationError, _("Please unregister or remove hosts which match this host before registering: %{existing}") % {existing: hostnames}
295
- end
296
-
297
263
  def self.sanitize_name(name)
298
264
  name.gsub('_', '-').chomp('.').downcase
299
265
  end
@@ -12,7 +12,7 @@ class Setting::Content < Setting
12
12
  return unless super
13
13
 
14
14
  BLANK_ATTRS.concat %w(register_hostname_fact default_location_subscribed_hosts
15
- default_location_puppet_content content_default_http_proxy)
15
+ default_location_puppet_content content_default_http_proxy host_dmi_uuid_duplicates)
16
16
 
17
17
  download_policies = proc { hashify_parameters(::Runcible::Models::YumImporter::DOWNLOAD_POLICIES) }
18
18
  proxy_download_policies = proc { hashify_parameters(::SmartProxy::DOWNLOAD_POLICIES) }
@@ -133,6 +133,15 @@ class Setting::Content < Setting
133
133
  "latest package to solve a dependency even if it already does exist in the repository."),
134
134
  'conservative', N_('Content View Dependency Solving Algorithm'), nil,
135
135
  :collection => dependency_solving_options),
136
+ self.set('host_tasks_workers_pool_size', N_("Amount of workers in the pool to handle the execution of host-related tasks. When set to 0, the default queue will be used instead. Restart of the dynflowd/foreman-tasks service is required."),
137
+ 5, N_('Host Tasks Workers Pool Size')),
138
+ self.set('host_dmi_uuid_duplicates',
139
+ N_("If hosts fail to register because of duplicate DMI UUIDs " \
140
+ "add their comma-separated values here. Subsequent registrations will generate a unique DMI UUID for the affected hosts."),
141
+ [], N_('Host Duplicate DMI UUIDs')),
142
+ self.set('host_profile_assume', N_("Allow new Host registrations to assume registered profiles with matching hostname " \
143
+ "as long as the registering DMI UUID is not used by another host."),
144
+ true, N_('Host Profile Assume')),
136
145
  self.set('host_tasks_workers_pool_size', N_("Amount of workers in the pool to handle the execution of host-related tasks. When set to 0, the default queue will be used instead. Restart of the dynflowd/foreman-tasks service is required."),
137
146
  5, N_('Host Tasks Workers Pool Size'))
138
147
  ].each { |s| self.create! s.update(:category => "Setting::Content") }
@@ -44,10 +44,6 @@ module Katello
44
44
  consumer_attributes[:entitlementStatus]
45
45
  end
46
46
 
47
- def update(params)
48
- ::Katello::Resources::Candlepin::Consumer.update(uuid, params)
49
- end
50
-
51
47
  def filtered_pools(match_attached, match_host, match_installed, no_overlap)
52
48
  if match_host
53
49
  pools = self.available_pools
@@ -2,6 +2,102 @@ module Katello
2
2
  class RegistrationManager
3
3
  class << self
4
4
  private :new
5
+ delegate :propose_existing_hostname, :new_host_from_facts, to: Katello::Host::SubscriptionFacet
6
+
7
+ def determine_organization(content_view_environment, activation_key)
8
+ content_view_environment.try(:environment).try(:organization) || activation_key.try(:organization)
9
+ end
10
+
11
+ def determine_host_dmi_uuid(rhsm_params)
12
+ host_uuid = rhsm_params.dig(:facts, 'dmi.system.uuid')
13
+
14
+ if Katello::Host::SubscriptionFacet.override_dmi_uuid?(host_uuid)
15
+ return [SecureRandom.uuid, true]
16
+ end
17
+
18
+ [host_uuid, false]
19
+ end
20
+
21
+ def process_registration(rhsm_params, content_view_environment, activation_keys = [])
22
+ host_name = propose_existing_hostname(rhsm_params[:facts])
23
+ host_uuid, host_uuid_overridden = determine_host_dmi_uuid(rhsm_params)
24
+
25
+ rhsm_params[:facts]['dmi.system.uuid'] = host_uuid # ensure we find & validate against a potentially overridden UUID
26
+
27
+ organization = determine_organization(content_view_environment, activation_keys.first)
28
+
29
+ hosts = find_existing_hosts(host_name, host_uuid)
30
+
31
+ validate_hosts(hosts, organization, host_name, host_uuid, host_uuid_overridden)
32
+
33
+ host = hosts.first || new_host_from_facts(
34
+ rhsm_params[:facts],
35
+ organization,
36
+ Location.default_host_subscribe_location!
37
+ )
38
+ host.organization = organization unless host.organization
39
+
40
+ register_host(host, rhsm_params, content_view_environment, activation_keys)
41
+
42
+ if host_uuid_overridden
43
+ host.subscription_facet.update_dmi_uuid_override(host_uuid)
44
+ end
45
+
46
+ host
47
+ end
48
+
49
+ def dmi_uuid_fact_id
50
+ RhsmFactName.find_or_create_by(name: 'dmi::system::uuid').id
51
+ end
52
+
53
+ def dmi_uuid_allowed_dups
54
+ Katello::Host::SubscriptionFacet::DMI_UUID_ALLOWED_DUPS
55
+ end
56
+
57
+ def find_existing_hosts(host_name, host_uuid)
58
+ ::Host.unscoped.distinct.left_outer_joins(:fact_values)
59
+ .where("#{::Host.table_name}.name = ? OR (#{FactValue.table_name}.fact_name_id = ?
60
+ AND #{FactValue.table_name}.value = ? AND #{FactValue.table_name}.value NOT IN (?))", host_name, dmi_uuid_fact_id, host_uuid, dmi_uuid_allowed_dups)
61
+ end
62
+
63
+ def validate_hosts(hosts, organization, host_name, host_uuid, host_uuid_overridden = false)
64
+ return if hosts.empty?
65
+
66
+ hosts = hosts.where(organization_id: [organization.id, nil])
67
+ hosts_size = hosts.size
68
+
69
+ if hosts_size == 0 # not in the correct org
70
+ #TODO: http://projects.theforeman.org/issues/11532
71
+ registration_error("Host with name %{host_name} is currently registered to a different org, please migrate host to %{org_name}.",
72
+ org_name: organization.name, host_name: host_name)
73
+ end
74
+
75
+ if hosts_size == 1
76
+ host = hosts.first
77
+
78
+ if host.name == host_name
79
+ unless Setting[:host_profile_assume] || host.subscription_facet.nil? || host.build || host_uuid_overridden
80
+ found_uuid = host.fact_values.where(fact_name_id: dmi_uuid_fact_id).first
81
+ if found_uuid && found_uuid.value != host_uuid
82
+ registration_error("This host is reporting a DMI UUID that differs from the existing registration.")
83
+ end
84
+ end
85
+
86
+ return true
87
+ end
88
+ end
89
+
90
+ hosts = hosts.where.not(name: host_name)
91
+ registration_error("The DMI UUID of this host (%{uuid}) matches other registered hosts: %{existing}", uuid: host_uuid, existing: joined_hostnames(hosts))
92
+ end
93
+
94
+ def registration_error(message, meta = {})
95
+ fail(Katello::Errors::RegistrationError, _(message) % meta)
96
+ end
97
+
98
+ def joined_hostnames(hosts)
99
+ hosts.pluck(:name).sort.join(', ')
100
+ end
5
101
 
6
102
  # options:
7
103
  # * organization_destroy: destroy some data associated with host, but
@@ -38,7 +38,8 @@ angular.module('Bastion.host-collections').controller('HostCollectionDetailsCont
38
38
  $scope.getHostIds = function() {
39
39
  return {
40
40
  included: {
41
- search: 'host_collection_id = %s'.replace('%s', $scope.$stateParams.hostCollectionId)
41
+ search: 'host_collection_id = %s'.replace('%s', $scope.$stateParams.hostCollectionId),
42
+ ids: $scope.hostCollection ? $scope.hostCollection.host_ids : []
42
43
  }
43
44
  };
44
45
  };
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "3.13.0".freeze
2
+ VERSION = "3.13.1".freeze
3
3
  end
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { FormGroup, FormControl, ControlLabel, HelpBlock } from 'react-bootstrap';
3
3
  import { translate as __ } from 'foremanReact/common/I18n';
4
- import { urlBuilder } from 'foremanReact/common/urlHelpers';
5
4
  import {
6
5
  headerFormatter,
7
6
  cellFormatter,
@@ -32,7 +31,7 @@ export const columns = (controller, selectionController) => [
32
31
  formatters: [
33
32
  (value, { rowData }) => (
34
33
  <td>
35
- <a href={urlBuilder('subscriptions', '', rowData.id)}>
34
+ <a href={`https://access.redhat.com/management/subscriptions/${rowData.subscription_id}`} rel="noopener noreferrer" target="_blank">
36
35
  {rowData.product_name}
37
36
  </a>
38
37
  </td>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katello
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.0
4
+ version: 3.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - N/A
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-04 00:00:00.000000000 Z
11
+ date: 2019-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -649,7 +649,6 @@ files:
649
649
  - app/lib/actions/candlepin/candlepin_listening_service.rb
650
650
  - app/lib/actions/candlepin/consumer/attach_subscription.rb
651
651
  - app/lib/actions/candlepin/consumer/auto_attach_subscriptions.rb
652
- - app/lib/actions/candlepin/consumer/create.rb
653
652
  - app/lib/actions/candlepin/consumer/hypervisors.rb
654
653
  - app/lib/actions/candlepin/consumer/remove_subscription.rb
655
654
  - app/lib/actions/candlepin/consumer/update.rb
@@ -1,32 +0,0 @@
1
- module Actions
2
- module Candlepin
3
- module Consumer
4
- class Create < Candlepin::Abstract
5
- input_format do
6
- param :cp_environment_id
7
- param :consumer_parameters
8
- param :activation_keys
9
- end
10
-
11
- # We need to call this in plan phase as this can lean to error responses
12
- # when the activation key fails to subscribe to the products
13
- def plan(input)
14
- response = ::Katello::Resources::Candlepin::Consumer.create(input[:cp_environment_id],
15
- input[:consumer_parameters], input[:activation_keys])
16
- plan_self(input.merge(response: response.slice(:uuid, :name)))
17
- end
18
-
19
- def run
20
- # we still keep the output interface the same for case there is other
21
- # way how to check the ability to subscribe the system with the activation key
22
- # or we have better support for rolling back in Dynflow
23
- output[:response] = input[:response]
24
- end
25
-
26
- def finalize
27
- input[:consumer_parameters][:facts] = 'TRIMMED'
28
- end
29
- end
30
- end
31
- end
32
- end