katello 3.16.0.rc5.1 → 3.16.2

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.

Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +39 -23
  3. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +1 -1
  4. data/app/controllers/katello/api/v2/host_tracer_controller.rb +8 -33
  5. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +11 -1
  6. data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +15 -0
  7. data/app/controllers/katello/api/v2/repositories_controller.rb +10 -1
  8. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +11 -5
  9. data/app/helpers/katello/content_view_helper.rb +15 -0
  10. data/app/lib/actions/katello/applicability/hosts/bulk_generate.rb +6 -2
  11. data/app/lib/actions/katello/capsule_content/refresh_repos.rb +1 -1
  12. data/app/lib/actions/katello/capsule_content/sync.rb +3 -2
  13. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +17 -3
  14. data/app/lib/actions/katello/content_view/incremental_updates.rb +3 -1
  15. data/app/lib/actions/katello/content_view/publish.rb +55 -16
  16. data/app/lib/actions/katello/content_view_version/incremental_update.rb +84 -53
  17. data/app/lib/actions/katello/product/destroy.rb +25 -4
  18. data/app/lib/actions/katello/repository/destroy.rb +5 -1
  19. data/app/lib/actions/katello/repository/multi_clone_contents.rb +64 -0
  20. data/app/lib/actions/katello/repository/multi_clone_to_version.rb +30 -0
  21. data/app/lib/actions/katello/repository/sync.rb +35 -25
  22. data/app/lib/actions/katello/repository/update.rb +11 -16
  23. data/app/lib/actions/katello/repository/verify_checksum.rb +28 -0
  24. data/app/lib/actions/pulp/orchestration/repository/sync.rb +2 -1
  25. data/app/lib/actions/pulp/repository/sync.rb +2 -1
  26. data/app/lib/actions/pulp3/abstract_async_task.rb +63 -58
  27. data/app/lib/actions/pulp3/capsule_content/refresh_content_guard.rb +17 -0
  28. data/app/lib/actions/pulp3/capsule_content/sync.rb +3 -1
  29. data/app/lib/actions/pulp3/{ContentGuard → content_guard}/refresh.rb +0 -0
  30. data/app/lib/actions/pulp3/content_migration.rb +4 -0
  31. data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +1 -1
  32. data/app/lib/actions/pulp3/orchestration/repository/copy_all_units.rb +2 -4
  33. data/app/lib/actions/pulp3/orchestration/repository/multi_copy_all_units.rb +36 -0
  34. data/app/lib/actions/pulp3/orchestration/repository/sync.rb +3 -1
  35. data/app/lib/actions/pulp3/orchestration/repository/trigger_update_repo_cert_guard.rb +22 -0
  36. data/app/lib/actions/pulp3/repository/copy_content.rb +0 -1
  37. data/app/lib/actions/pulp3/repository/delete.rb +1 -1
  38. data/app/lib/actions/pulp3/repository/multi_copy_content.rb +28 -0
  39. data/app/lib/actions/pulp3/repository/multi_copy_units.rb +14 -7
  40. data/app/lib/actions/pulp3/repository/presenters/repair_presenter.rb +85 -0
  41. data/app/lib/actions/pulp3/repository/repair.rb +29 -0
  42. data/app/lib/actions/pulp3/repository/save_version.rb +20 -8
  43. data/app/lib/actions/pulp3/repository/save_versions.rb +47 -13
  44. data/app/lib/actions/pulp3/repository/sync.rb +1 -1
  45. data/app/lib/actions/pulp3/repository/update_cv_repository_cert_guard.rb +6 -2
  46. data/app/lib/actions/pulp3/repository/upload_file.rb +1 -1
  47. data/app/lib/katello/concerns/base_template_scope_extensions.rb +4 -0
  48. data/app/lib/katello/errors.rb +1 -15
  49. data/app/lib/katello/resources/cdn.rb +3 -2
  50. data/app/lib/katello/util/cdn_var_substitutor.rb +9 -6
  51. data/app/models/katello/concerns/smart_proxy_extensions.rb +14 -3
  52. data/app/models/katello/content_view.rb +18 -6
  53. data/app/models/katello/content_view_erratum_filter.rb +13 -0
  54. data/app/models/katello/content_view_module_stream_filter.rb +19 -0
  55. data/app/models/katello/content_view_package_filter.rb +1 -1
  56. data/app/models/katello/glue/pulp/repo.rb +1 -1
  57. data/app/models/katello/host/content_facet.rb +1 -0
  58. data/app/models/katello/module_stream.rb +1 -1
  59. data/app/models/katello/ping.rb +1 -3
  60. data/app/models/katello/repository.rb +5 -0
  61. data/app/models/katello/root_repository.rb +5 -1
  62. data/app/models/setting/content.rb +1 -1
  63. data/app/services/cert/certs.rb +10 -2
  64. data/app/services/katello/host_trace_manager.rb +38 -0
  65. data/app/services/katello/pulp3/api/core.rb +4 -0
  66. data/app/services/katello/pulp3/erratum.rb +3 -1
  67. data/app/services/katello/pulp3/migration.rb +4 -3
  68. data/app/services/katello/pulp3/migration_plan.rb +6 -6
  69. data/app/services/katello/pulp3/repository.rb +16 -8
  70. data/app/services/katello/pulp3/repository/yum.rb +234 -35
  71. data/app/services/katello/pulp3/repository_mirror.rb +7 -2
  72. data/app/services/katello/pulp3/smart_proxy_mirror_repository.rb +1 -1
  73. data/app/services/katello/pulp3/task.rb +100 -0
  74. data/app/services/katello/pulp3/task_group.rb +85 -0
  75. data/app/services/katello/smart_proxy_helper.rb +13 -16
  76. data/config/routes/api/rhsm.rb +1 -0
  77. data/config/routes/api/v2.rb +2 -6
  78. data/config/routes/overrides.rb +4 -0
  79. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-traces-modal.controller.js +3 -4
  80. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-bulk-action.factory.js +2 -1
  81. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/bulk/product-bulk-action.factory.js +1 -0
  82. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +6 -0
  83. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details.html +7 -1
  84. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +1 -1
  85. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +2 -2
  86. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository.factory.js +1 -0
  87. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.controller.js +15 -0
  88. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/views/products.html +6 -0
  89. data/lib/katello/permission_creator.rb +2 -2
  90. data/lib/katello/permissions/host_permissions.rb +1 -0
  91. data/lib/katello/plugin.rb +0 -1
  92. data/lib/katello/tasks/pulp3_post_migration_check.rake +2 -1
  93. data/lib/katello/tasks/reimport.rake +1 -1
  94. data/lib/katello/version.rb +1 -1
  95. data/webpack/redux/actions/RedHatRepositories/helpers.js +6 -6
  96. metadata +30 -13
  97. data/app/lib/actions/katello/repository/update_cv_repo_cert_guard.rb +0 -17
  98. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-traces-resolve.factory.js +0 -18
@@ -30,6 +30,7 @@ module Katello
30
30
  if filter_by_id?
31
31
  errata_ids = erratum_rules.map(&:errata_id)
32
32
  errata_pulp_ids = errata_package_pulp_ids_from_errata_ids(repo, errata_ids)
33
+ errata_pulp_ids += errata_module_stream_pulp_ids_from_errata_ids(errata_ids)
33
34
  else
34
35
  clauses = []
35
36
  clauses << errata_from
@@ -37,7 +38,9 @@ module Katello
37
38
  clauses << types_clause
38
39
  package_filenames = Erratum.list_filenames_by_clauses(repo, clauses.compact)
39
40
  errata_pulp_ids = errata_package_pulp_ids_from_package_filenames(repo, package_filenames)
41
+ errata_pulp_ids += errata_module_stream_pulp_ids_from_clauses(repo, clauses.compact)
40
42
  end
43
+
41
44
  errata_pulp_ids
42
45
  end
43
46
 
@@ -48,10 +51,20 @@ module Katello
48
51
  repo.rpms.where("filename ILIKE ANY ( array[?] )", query_params)
49
52
  end
50
53
 
54
+ def errata_module_stream_pulp_ids_from_clauses(repo, clauses)
55
+ module_streams = Erratum.list_modular_streams_by_clauses(repo, clauses)
56
+ module_streams.pluck(:pulp_id)
57
+ end
58
+
51
59
  def errata_package_pulp_ids_from_package_filenames(repo, package_filenames)
52
60
  rpms_by_filename(repo, package_filenames).pluck(:pulp_id)
53
61
  end
54
62
 
63
+ def errata_module_stream_pulp_ids_from_errata_ids(errata_ids)
64
+ module_streams = Katello::Erratum.where(:errata_id => errata_ids).map(&:module_streams).compact.flatten
65
+ module_streams.pluck(:pulp_id)
66
+ end
67
+
55
68
  def errata_package_pulp_ids_from_errata_ids(repo, errata_ids)
56
69
  package_filenames = Katello::ErratumPackage.joins(:erratum).where("#{Erratum.table_name}.errata_id" => errata_ids).pluck(:filename)
57
70
  rpms_by_filename(repo, package_filenames).pluck(:pulp_id)
@@ -18,5 +18,24 @@ module Katello
18
18
  def original_module_streams=(value)
19
19
  self[:original_module_streams] = value
20
20
  end
21
+
22
+ def content_unit_pulp_ids(repo, dependents = false)
23
+ content_unit_ids = []
24
+ module_ids = []
25
+
26
+ self.module_stream_rules.each do |rule|
27
+ module_ids << rule.module_stream_id
28
+ end
29
+ if self.original_module_streams
30
+ module_ids.concat(repo.module_streams_without_errata.map(&:id))
31
+ end
32
+ modules_streams = ModuleStream.where(id: module_ids).includes(:rpms)
33
+ content_unit_ids += modules_streams.pluck(:pulp_id).flatten.uniq
34
+ if dependents && !modules_streams.empty?
35
+ rpms = modules_streams.map(&:rpms).flatten
36
+ content_unit_ids += rpms.pluck(:pulp_id).flatten.uniq
37
+ end
38
+ content_unit_ids.uniq
39
+ end
21
40
  end
22
41
  end
@@ -37,7 +37,7 @@ module Katello
37
37
  self.package_rules.each do |rule|
38
38
  package_filenames.concat(query_rpms(repo, rule))
39
39
  end
40
-
40
+ package_filenames.concat(repo.packages_without_errata.map(&:filename)) if self.original_packages
41
41
  rpms = Rpm.in_repositories(repo)
42
42
  rpms.where(filename: package_filenames).where(:modular => false).pluck(:pulp_id).flatten.uniq
43
43
  end
@@ -367,7 +367,7 @@ module Katello
367
367
  pulp_uri = URI.parse(smart_proxy ? smart_proxy.url : SETTINGS[:katello][:pulp][:url])
368
368
  scheme = (self.unprotected && !force_https) ? 'http' : 'https'
369
369
  if docker?
370
- "#{pulp_uri.host.downcase}:#{Setting['pulp_docker_registry_port']}/#{container_repository_name}"
370
+ "#{pulp_uri.host.downcase}/#{container_repository_name}"
371
371
  elsif file?
372
372
  "#{scheme}://#{pulp_uri.host.downcase}/pulp/isos/#{relative_path}/"
373
373
  elsif puppet?
@@ -126,6 +126,7 @@ module Katello
126
126
  ::Katello::Applicability::ApplicableContentHelper.new(self, ::Katello::Erratum, bound_repos).calculate_and_import
127
127
  ::Katello::Applicability::ApplicableContentHelper.new(self, ::Katello::ModuleStream, bound_repos).calculate_and_import
128
128
  update_applicability_counts
129
+ self.update_errata_status
129
130
  end
130
131
 
131
132
  def import_applicability(partial = false)
@@ -65,7 +65,7 @@ module Katello
65
65
  end
66
66
 
67
67
  def module_spec_hash
68
- {:name => name, :stream => stream, :version => version, :context => context, :arch => arch, :id => id}.compact
68
+ {:name => name, :stream => stream, :version => version, :context => context, :arch => arch, :pulp_id => pulp_id, :id => id}.compact
69
69
  end
70
70
 
71
71
  def self.parse_module_spec(module_spec)
@@ -31,9 +31,7 @@ module Katello
31
31
 
32
32
  # set overall status result code
33
33
  result = {:services => result}
34
- result[:services].each_value do |v|
35
- result[:status] = v[:status] == OK_RETURN_CODE ? OK_RETURN_CODE : FAIL_RETURN_CODE
36
- end
34
+ result[:status] = result[:services].each_value.any? { |v| v[:status] == FAIL_RETURN_CODE } ? FAIL_RETURN_CODE : OK_RETURN_CODE
37
35
  result
38
36
  end
39
37
 
@@ -133,6 +133,7 @@ module Katello
133
133
  scope :in_published_environments, -> { in_content_views(Katello::ContentView.non_default).where.not(:environment_id => nil) }
134
134
  scope :order_by_root, ->(attr) { joins(:root).order("#{Katello::RootRepository.table_name}.#{attr}") }
135
135
  scope :with_content, ->(content) { joins(Katello::RepositoryTypeManager.find_content_type(content).model_class.repository_association_class.name.demodulize.underscore.pluralize.to_sym).distinct }
136
+ scope :by_rpm_count, -> { left_joins(:repository_rpms).group(:id).order("count(katello_repository_rpms.id) ASC") } # smallest count first
136
137
 
137
138
  scoped_search :on => :name, :relation => :root, :complete_value => true
138
139
  scoped_search :rename => :product, :on => :name, :relation => :product, :complete_value => true
@@ -592,6 +593,10 @@ module Katello
592
593
  environment
593
594
  end
594
595
 
596
+ def self.smart_proxy_syncable
597
+ where.not(:environment_id => nil)
598
+ end
599
+
595
600
  def exist_for_environment?(environment, content_view, attribute = nil)
596
601
  if environment.present? && content_view.in_environment?(environment)
597
602
  repos = content_view.version(environment).repos(environment)
@@ -330,7 +330,11 @@ module Katello
330
330
 
331
331
  def format_arches
332
332
  if content_type == ::Katello::Repository::DEB_TYPE
333
- self.deb_architectures
333
+ # FIXME: This should be set to self.deb_architectures but it needs to have the
334
+ # subscription-manager PR https://github.com/candlepin/subscription-manager/pull/2213
335
+ # merged. Otherwise subscription-manager returns _NO_ debian repository as described in
336
+ # https://community.theforeman.org/t/katello-3-16-1-1-el7-subscription-manager-doesnt-create-rhsm-repos-for-ubuntu/20928/38
337
+ nil
334
338
  else
335
339
  self.arch == "noarch" ? nil : self.arch
336
340
  end
@@ -92,7 +92,7 @@ class Setting::Content < Setting
92
92
  self.set('check_services_before_actions', N_("Whether or not to check the status of backend services such as pulp and candlepin prior to performing some actions."),
93
93
  true, N_('Check services before actions')),
94
94
  self.set('foreman_proxy_content_batch_size', N_("How many repositories should be synced concurrently on the capsule. A smaller number may lead to longer sync times. A larger number will increase dynflow load."),
95
- 25, N_('Batch size to sync repositories in.')),
95
+ 100, N_('Batch size to sync repositories in.')),
96
96
  self.set('foreman_proxy_content_auto_sync', N_("Whether or not to auto sync the Smart Proxies after a Content View promotion."),
97
97
  true, N_('Sync Smart Proxies after Content View promotion')),
98
98
  self.set('default_download_policy', N_("Default download policy for custom repositories (either 'immediate', 'on_demand', or 'background')"), "immediate",
@@ -9,11 +9,19 @@ module Cert
9
9
  end
10
10
 
11
11
  def self.ssl_client_cert
12
- @ssl_client_cert ||= OpenSSL::X509::Certificate.new(File.open(Setting['pulp_client_cert'], 'r').read)
12
+ @ssl_client_cert ||= OpenSSL::X509::Certificate.new(File.open(ssl_client_cert_filename, 'r').read)
13
+ end
14
+
15
+ def self.ssl_client_cert_filename
16
+ Setting['pulp_client_cert']
13
17
  end
14
18
 
15
19
  def self.ssl_client_key
16
- @ssl_client_key ||= OpenSSL::PKey::RSA.new(File.open(Setting['pulp_client_key'], 'r').read)
20
+ @ssl_client_key ||= OpenSSL::PKey::RSA.new(File.open(ssl_client_key_filename, 'r').read)
21
+ end
22
+
23
+ def self.ssl_client_key_filename
24
+ Setting['pulp_client_key']
17
25
  end
18
26
 
19
27
  def self.verify_ueber_cert(organization)
@@ -0,0 +1,38 @@
1
+ module Katello
2
+ class HostTraceManager
3
+ def self.resolve_traces(traces)
4
+ traces.each do |trace|
5
+ if trace.reboot_required?
6
+ trace.helper = 'reboot'
7
+ end
8
+ end
9
+
10
+ traces_by_host_id = traces.group_by(&:host_id)
11
+ traces_by_helper = traces.group_by(&:helper)
12
+
13
+ composers = []
14
+
15
+ if traces_by_host_id.size < traces_by_helper.size
16
+ traces_by_host_id.each do |host_id, trace|
17
+ needed_traces = trace.map(&:helper).join(',')
18
+ joined_helpers = { :helper => needed_traces }
19
+ composers << ::JobInvocationComposer.for_feature(:katello_service_restart, [host_id], joined_helpers)
20
+ end
21
+ else
22
+ traces_by_helper.each do |helper, trace|
23
+ helpers = { :helper => helper }
24
+ composers << ::JobInvocationComposer.for_feature(:katello_service_restart, trace.map(&:host_id), helpers)
25
+ end
26
+ end
27
+
28
+ job_invocations = []
29
+
30
+ composers.each do |composer|
31
+ composer.trigger
32
+ job_invocations << composer.job_invocation
33
+ end
34
+
35
+ job_invocations
36
+ end
37
+ end
38
+ end
@@ -74,6 +74,10 @@ module Katello
74
74
  PulpcoreClient::TasksApi.new(core_api_client)
75
75
  end
76
76
 
77
+ def task_groups_api
78
+ PulpcoreClient::TaskGroupsApi.new(core_api_client)
79
+ end
80
+
77
81
  def upload_class
78
82
  PulpcoreClient::Upload
79
83
  end
@@ -26,8 +26,10 @@ module Katello
26
26
  end
27
27
 
28
28
  def update_model(model)
29
- keys = %w(title id severity issued type description reboot_suggested solution updated summary)
29
+ keys = %w(title id severity issued_date type description reboot_suggested solution updated_date summary)
30
30
  custom_json = backend_data.slice(*keys)
31
+ custom_json["issued"] = custom_json.delete("issued_date")
32
+ custom_json["updated"] = custom_json.delete("updated_date")
31
33
 
32
34
  # handle SUSE epoch dates
33
35
  custom_json["issued"] = convert_date_if_epoch(custom_json["issued"])
@@ -68,8 +68,9 @@ module Katello
68
68
  end
69
69
 
70
70
  def create_migrations
71
- migration_plans = @repository_types.map { |label| Katello::Pulp3::MigrationPlan.new(label) }
72
- migration_plans.map { |plan| migration_plan_api.create(plan: plan.generate.as_json).pulp_href }
71
+ plan = Katello::Pulp3::MigrationPlan.new(@repository_types)
72
+ Rails.logger.info(plan)
73
+ [migration_plan_api.create(plan: plan.generate.as_json).pulp_href]
73
74
  end
74
75
 
75
76
  def start_migration(plan_href)
@@ -116,7 +117,7 @@ module Katello
116
117
  relative_path = pulp3_api.distributions_api.read(href).base_path
117
118
 
118
119
  dist_ref = Katello::Pulp3::DistributionReference.find_or_initialize_by(:path => relative_path)
119
- if (distribution_repo = Katello::Repository.find_by(:relative_path => relative_path))
120
+ if (distribution_repo = Katello::Repository.find_by(:relative_path => relative_path) || Katello::Repository.find_by(:container_repository_name => relative_path))
120
121
  dist_ref.href = href
121
122
  dist_ref.repository_id = distribution_repo.id
122
123
  dist_ref.save!
@@ -1,8 +1,8 @@
1
1
  module Katello
2
2
  module Pulp3
3
3
  class MigrationPlan
4
- def initialize(repository_type_label)
5
- @repository_type = repository_type_label
4
+ def initialize(repository_type_labels)
5
+ @repository_types = repository_type_labels
6
6
  end
7
7
 
8
8
  def master_proxy
@@ -17,12 +17,12 @@ module Katello
17
17
  end
18
18
 
19
19
  def generate_plugins
20
- [
20
+ @repository_types.map do |repository_type|
21
21
  {
22
- type: pulp2_repository_type(@repository_type),
23
- repositories: repository_migrations(@repository_type)
22
+ type: pulp2_repository_type(repository_type),
23
+ repositories: repository_migrations(repository_type)
24
24
  }
25
- ]
25
+ end
26
26
  end
27
27
 
28
28
  def pulp2_repository_type(repository_type)
@@ -1,5 +1,4 @@
1
1
  require "pulpcore_client"
2
-
3
2
  module Katello
4
3
  module Pulp3
5
4
  class Repository
@@ -188,19 +187,23 @@ module Katello
188
187
  api.repositories_api.read(repository_reference.try(:repository_href))
189
188
  end
190
189
 
191
- def delete(href = repository_reference.try(:repository_href))
192
- repository_reference.try(:destroy)
190
+ def delete_repository(repo_reference = repository_reference)
191
+ href = repo_reference.try(:repository_href)
192
+ repo_reference.try(:destroy)
193
193
  ignore_404_exception { api.repositories_api.delete(href) } if href
194
194
  end
195
195
 
196
- def sync
197
- sync_url_params = {remote: repo.remote_href, mirror: repo.root.mirror_on_sync}
198
- skip_type_param = skip_types
199
- sync_url_params[:skip_types] = skip_type_param if skip_type_param
200
- repository_sync_url_data = api.class.repository_sync_url_class.new(sync_url_params)
196
+ def sync(options = {})
197
+ repository_sync_url_data = api.class.repository_sync_url_class.new(sync_url_params(options))
201
198
  [api.repositories_api.sync(repository_reference.repository_href, repository_sync_url_data)]
202
199
  end
203
200
 
201
+ def sync_url_params(_sync_options)
202
+ params = {remote: repo.remote_href, mirror: repo.root.mirror_on_sync}
203
+ params[:skip_types] = skip_types if skip_types
204
+ params
205
+ end
206
+
204
207
  def create_publication
205
208
  publication_data = api.class.publication_class.new(repository_version: repo.version_href)
206
209
  api.publications_api.create(publication_data)
@@ -352,6 +355,11 @@ module Katello
352
355
  api.repositories_api.modify(repository_reference.repository_href, add_content_units: content_unit_href)
353
356
  end
354
357
 
358
+ def add_content_for_repo(repository_href, content_unit_href)
359
+ content_unit_href = [content_unit_href] unless content_unit_href.is_a?(Array)
360
+ api.repositories_api.modify(repository_href, add_content_units: content_unit_href)
361
+ end
362
+
355
363
  def unit_keys(uploads)
356
364
  uploads.map do |upload|
357
365
  upload.except('id')
@@ -3,10 +3,13 @@ require 'pulp_rpm_client'
3
3
  module Katello
4
4
  module Pulp3
5
5
  class Repository
6
+ # rubocop:disable Metrics/ClassLength
6
7
  class Yum < ::Katello::Pulp3::Repository
7
8
  include Katello::Util::Errata
8
9
  include Katello::Util::PulpcoreContentFilters
9
10
 
11
+ UNIT_LIMIT = 10_000
12
+
10
13
  def remote_options
11
14
  if root.url.blank?
12
15
  common_remote_options.merge(url: nil, policy: root.download_policy)
@@ -59,6 +62,12 @@ module Katello
59
62
  end
60
63
  end
61
64
 
65
+ def sync_url_params(sync_options)
66
+ params = super
67
+ params[:optimize] = sync_options[:optimize] if sync_options.key?(:optimize)
68
+ params
69
+ end
70
+
62
71
  def self.distribution_bootable?(distribution)
63
72
  file_paths = distribution.results.first.images.map(&:path)
64
73
  file_paths.any? do |path|
@@ -70,48 +79,140 @@ module Katello
70
79
  "/pulp/repos/#{repo.relative_path}/".sub('//', '/')
71
80
  end
72
81
 
73
- def copy_units(source_repository, content_unit_hrefs, dependency_solving, dest_base_version = 0,
74
- additional_repo_map = {})
82
+ def multi_copy_units(repo_id_map, dependency_solving)
75
83
  tasks = []
76
84
 
77
- content_unit_hrefs.sort!
78
- if content_unit_hrefs.any?
85
+ if repo_id_map.values.pluck(:content_unit_hrefs).flatten.any?
86
+ data = PulpRpmClient::Copy.new
87
+ data.dependency_solving = dependency_solving
88
+ data.config = []
89
+ repo_id_map.each do |source_repo_ids, dest_repo_id_map|
90
+ dest_repo = ::Katello::Repository.find(dest_repo_id_map[:dest_repo])
91
+ dest_repo_href = ::Katello::Pulp3::Repository::Yum.new(dest_repo, SmartProxy.pulp_master).repository_reference.repository_href
92
+ content_unit_hrefs = dest_repo_id_map[:content_unit_hrefs]
93
+ # Not needed during incremental update due to dest_base_version
94
+ unless dest_repo_id_map[:base_version]
95
+ source_repo_for_package_envs = ::Katello::Repository.find(source_repo_ids.first)
96
+ unless source_repo_for_package_envs.library_instance?
97
+ source_repo_for_package_envs = source_repo_for_package_envs.library_instance
98
+ end
99
+ package_env_hrefs = packageenvironments({ :repository_version => source_repo_for_package_envs.version_href }).map(&:pulp_href).sort
100
+ tasks << remove_all_content_from_repo(dest_repo_href)
101
+ tasks << add_content_for_repo(dest_repo_href, package_env_hrefs) unless package_env_hrefs.empty?
102
+ end
103
+ source_repo_ids.each do |source_repo_id|
104
+ source_repo_version = ::Katello::Repository.find(source_repo_id).version_href
105
+ config = { source_repo_version: source_repo_version, dest_repo: dest_repo_href, content: content_unit_hrefs }
106
+ config[:dest_base_version] = dest_repo_id_map[:base_version] if dest_repo_id_map[:base_version]
107
+ data.config << config
108
+ end
109
+ end
110
+ tasks << copy_content_chunked(data)
111
+ else
112
+ tasks << remove_all_content_from_mapping(repo_id_map)
113
+ end
114
+ tasks.flatten
115
+ end
116
+
117
+ def copy_api_data_dup(data)
118
+ data_dup = PulpRpmClient::Copy.new
119
+ data_dup.dependency_solving = data.dependency_solving
120
+ data_dup.config = []
121
+ data.config.each do |repo_config|
122
+ config_hash = {
123
+ source_repo_version: repo_config[:source_repo_version],
124
+ dest_repo: repo_config[:dest_repo],
125
+ content: []
126
+ }
127
+ config_hash[:dest_base_version] = repo_config[:dest_base_version] if repo_config[:dest_base_version]
128
+ data_dup.config << config_hash
129
+ end
130
+ data_dup
131
+ end
132
+
133
+ def copy_content_chunked(data)
134
+ tasks = []
135
+ # Don't chunk if there aren't enough content units
136
+ if data.config.sum { |repo_config| repo_config[:content].size } <= UNIT_LIMIT
137
+ return api.copy_api.copy_content(data)
138
+ end
139
+
140
+ unit_copy_counter = 0
141
+ i = 0
142
+ leftover_units = data.config.first[:content].deep_dup
143
+
144
+ # Copy data and clear its content fields
145
+ data_dup = copy_api_data_dup(data)
146
+
147
+ while i < data_dup.config.size
148
+ # Copy all units within repo or only some?
149
+ if leftover_units.length < UNIT_LIMIT - unit_copy_counter
150
+ copy_amount = leftover_units.length
151
+ else
152
+ copy_amount = UNIT_LIMIT - unit_copy_counter
153
+ end
154
+
155
+ data_dup.config[i][:content] = leftover_units.pop(copy_amount)
156
+ unit_copy_counter += copy_amount
157
+ if unit_copy_counter != 0
158
+ tasks << api.copy_api.copy_content(data_dup)
159
+ unit_copy_counter = 0
160
+ end
161
+
162
+ if leftover_units.empty?
163
+ # Nothing more to copy -- clear current config's content
164
+ data_dup.config[i][:content] = []
165
+ i += 1
166
+ # Fetch unit list for next data config
167
+ leftover_units = data.config[i][:content].deep_dup unless i == data_dup.config.size
168
+ end
169
+ end
170
+
171
+ tasks
172
+ end
173
+
174
+ def remove_all_content_from_mapping(repo_id_map)
175
+ tasks = []
176
+ repo_id_map.each do |_source_repo_ids, dest_repo_id_map|
177
+ dest_repo = ::Katello::Repository.find(dest_repo_id_map[:dest_repo])
178
+ dest_repo_href = ::Katello::Pulp3::Repository::Yum.new(dest_repo, SmartProxy.pulp_master).repository_reference.repository_href
179
+ tasks << remove_all_content_from_repo(dest_repo_href)
180
+ end
181
+ tasks
182
+ end
183
+
184
+ def copy_units(source_repository, content_unit_hrefs, dependency_solving)
185
+ tasks = []
186
+
187
+ if content_unit_hrefs.sort!.any?
79
188
  data = PulpRpmClient::Copy.new
80
189
  data.config = [{
81
190
  source_repo_version: source_repository.version_href,
82
191
  dest_repo: repository_reference.repository_href,
83
- dest_base_version: dest_base_version,
192
+ dest_base_version: 0,
84
193
  content: content_unit_hrefs
85
194
  }]
86
195
  data.dependency_solving = dependency_solving
87
- if dependency_solving
88
- # repo_map example: {
89
- # <source_repo_id>: {
90
- # dest_repo: <dest_repo_id>,
91
- # base_version: <base_version>
92
- # }
93
- # }
94
- additional_repo_map.each do |source_repo, dest_repo_map|
95
- source_repo_version = ::Katello::Repository.find(source_repo).version_href
96
-
97
- dest_repo = ::Katello::Repository.find(dest_repo_map[:dest_repo])
98
- dest_repo_href = ::Katello::Pulp3::Repository::Yum.new(dest_repo, SmartProxy.pulp_master).repository_reference.repository_href
99
- data.config << {
100
- source_repo_version: source_repo_version,
101
- dest_repo: dest_repo_href,
102
- dest_base_version: dest_repo_map[:base_version],
103
- content: content_unit_hrefs
104
- }
105
- end
106
- end
196
+ package_env_hrefs = packageenvironments({ :repository_version => source_repository.version_href }).map(&:pulp_href).sort
107
197
  tasks << api.copy_api.copy_content(data)
198
+ tasks << add_content(package_env_hrefs) unless package_env_hrefs.empty?
108
199
  else
109
200
  tasks << remove_all_content
110
201
  end
111
-
112
202
  tasks
113
203
  end
114
204
 
205
+ def remove_all_content_from_repo(repo_href)
206
+ data = PulpRpmClient::RepositoryAddRemoveContent.new(
207
+ remove_content_units: ['*'])
208
+ api.repositories_api.modify(repo_href, data)
209
+ end
210
+
211
+ def repair(repository_version_href)
212
+ data = PulpRpmClient::RepositoryVersion.new
213
+ api.repository_versions_api.repair(repository_version_href, data)
214
+ end
215
+
115
216
  def remove_all_content
116
217
  data = PulpRpmClient::RepositoryAddRemoveContent.new(
117
218
  remove_content_units: ['*'])
@@ -119,7 +220,7 @@ module Katello
119
220
  end
120
221
 
121
222
  def packageenvironments(options = {})
122
- api.content_package_environments_api.list(options)
223
+ Katello::Pulp3::Api::Core.fetch_from_list { |page_opts| api.content_package_environments_api.list(page_opts.merge(options)) }
123
224
  end
124
225
 
125
226
  def metadatafiles(options = {})
@@ -130,6 +231,94 @@ module Katello
130
231
  api.content_distribution_trees_api.list(options)
131
232
  end
132
233
 
234
+ def add_filter_content(source_repo_ids, filters, filter_list_map)
235
+ filters.each do |filter|
236
+ if filter.inclusion
237
+ source_repo_ids.each do |repo_id|
238
+ filter_list_map[:whitelist_ids] += filter.content_unit_pulp_ids(::Katello::Repository.find(repo_id))
239
+ end
240
+ else
241
+ source_repo_ids.each do |repo_id|
242
+ filter_list_map[:blacklist_ids] += filter.content_unit_pulp_ids(::Katello::Repository.find(repo_id))
243
+ end
244
+ end
245
+ end
246
+ filter_list_map
247
+ end
248
+
249
+ def add_un_modular_rpms(source_repo_ids, filters, filter_list_map)
250
+ if (filter_list_map[:whitelist_ids].empty? && filters.select { |filter| filter.inclusion }.empty?)
251
+ filter_list_map[:whitelist_ids] += source_repo_ids.collect do |source_repo_id|
252
+ source_repo = ::Katello::Repository.find(source_repo_id)
253
+ source_repo.rpms.where(:modular => false).pluck(:pulp_id).sort
254
+ end
255
+ end
256
+ filter_list_map
257
+ end
258
+
259
+ def add_modular_content(source_repo_ids, filters, modular_filters, filter_list_map)
260
+ inclusion_modular_filters = modular_filters.select { |filter| filter.inclusion }
261
+ exclusion_modular_filters = modular_filters - inclusion_modular_filters
262
+ if inclusion_modular_filters.empty? &&
263
+ !(filters.any? { |filter| filter.class == ContentViewErratumFilter && filter.inclusion })
264
+ source_repo_ids.each do |source_repo_id|
265
+ source_repo = ::Katello::Repository.find(source_repo_id)
266
+ filter_list_map[:whitelist_ids] += source_repo.rpms.where(:modular => true).pluck(:pulp_id).sort
267
+ filter_list_map[:whitelist_ids] += source_repo.module_streams.pluck(:pulp_id).sort
268
+ end
269
+ end
270
+
271
+ unless inclusion_modular_filters.empty?
272
+ filter_list_map[:whitelist_ids] += source_repo_ids.collect do |source_repo_id|
273
+ source_repo = ::Katello::Repository.find(source_repo_id)
274
+ modular_packages(source_repo, inclusion_modular_filters)
275
+ end
276
+ end
277
+
278
+ unless exclusion_modular_filters.empty?
279
+ filter_list_map[:blacklist_ids] += source_repo_ids.collect do |source_repo_id|
280
+ source_repo = ::Katello::Repository.find(source_repo_id)
281
+ modular_packages(source_repo, exclusion_modular_filters)
282
+ end
283
+ end
284
+
285
+ filter_list_map
286
+ end
287
+
288
+ def copy_content_from_mapping(repo_id_map, options = {})
289
+ repo_id_map.each do |source_repo_ids, dest_repo_map|
290
+ filters = [ContentViewErratumFilter, ContentViewPackageGroupFilter, ContentViewPackageFilter].collect do |filter_class|
291
+ filter_class.where(:id => dest_repo_map[:filter_ids])
292
+ end
293
+ modular_filters = ContentViewModuleStreamFilter.where(:id => dest_repo_map[:filter_ids])
294
+ filters.flatten!.compact!
295
+
296
+ filter_list_map = { whitelist_ids: [], blacklist_ids: [] }
297
+ filter_list_map = add_filter_content(source_repo_ids, filters, filter_list_map)
298
+ filter_list_map = add_un_modular_rpms(source_repo_ids, filters, filter_list_map)
299
+ filter_list_map = add_modular_content(source_repo_ids, filters, modular_filters, filter_list_map)
300
+
301
+ whitelist_ids = filter_list_map[:whitelist_ids].flatten&.uniq
302
+ blacklist_ids = filter_list_map[:blacklist_ids].flatten&.uniq
303
+ content_unit_hrefs = whitelist_ids - blacklist_ids
304
+
305
+ if content_unit_hrefs.any?
306
+ source_repo_ids.each do |source_repo_id|
307
+ content_unit_hrefs += additional_content_hrefs(::Katello::Repository.find(source_repo_id), content_unit_hrefs)
308
+ end
309
+ end
310
+ source_repo_ids.each do |source_repo_id|
311
+ content_unit_hrefs += ::Katello::Repository.find(source_repo_id).srpms.pluck(:pulp_id)
312
+ end
313
+
314
+ dest_repo_map[:content_unit_hrefs] = content_unit_hrefs.uniq.sort
315
+ end
316
+
317
+ dependency_solving = options[:solve_dependencies] || false
318
+
319
+ multi_copy_units(repo_id_map, dependency_solving)
320
+ end
321
+
133
322
  def copy_content_for_source(source_repository, options = {})
134
323
  filters = [ContentViewErratumFilter, ContentViewPackageGroupFilter, ContentViewPackageFilter].collect do |filter_class|
135
324
  filter_class.where(:id => options[:filter_ids])
@@ -147,12 +336,18 @@ module Katello
147
336
  end
148
337
  end
149
338
 
150
- if whitelist_ids.empty? && filters.select { |filter| filter.inclusion }.empty?
151
- whitelist_ids = source_repository.rpms.where(:modular => false).pluck(:pulp_id).sort
152
- end
339
+ whitelist_ids = source_repository.rpms.where(:modular => false).pluck(:pulp_id).sort if (whitelist_ids.empty? && filters.select { |filter| filter.inclusion }.empty?)
153
340
 
341
+ modular_filters = ContentViewModuleStreamFilter.where(:id => options[:filter_ids])
342
+ inclusion_modular_filters = modular_filters.select { |filter| filter.inclusion }
343
+ exclusion_modular_filters = modular_filters - inclusion_modular_filters
344
+ if inclusion_modular_filters.empty? && !(filters.any? { |filter| filter.class == ContentViewErratumFilter && filter.inclusion })
345
+ whitelist_ids += source_repository.rpms.where(:modular => true).pluck(:pulp_id).sort
346
+ whitelist_ids += source_repository.module_streams.pluck(:pulp_id).sort
347
+ end
348
+ whitelist_ids += modular_packages(source_repository, inclusion_modular_filters) unless inclusion_modular_filters.empty?
349
+ blacklist_ids += modular_packages(source_repository, exclusion_modular_filters) unless exclusion_modular_filters.empty?
154
350
  content_unit_hrefs = whitelist_ids - blacklist_ids
155
-
156
351
  if content_unit_hrefs.any?
157
352
  content_unit_hrefs += additional_content_hrefs(source_repository, content_unit_hrefs)
158
353
  end
@@ -162,6 +357,14 @@ module Katello
162
357
  copy_units(source_repository, content_unit_hrefs.uniq, dependency_solving)
163
358
  end
164
359
 
360
+ def modular_packages(source_repository, filters)
361
+ list_ids = []
362
+ filters.each do |filter|
363
+ list_ids += filter.content_unit_pulp_ids(source_repository, true)
364
+ end
365
+ list_ids
366
+ end
367
+
165
368
  def additional_content_hrefs(source_repository, content_unit_hrefs)
166
369
  repo_service = source_repository.backend_service(SmartProxy.pulp_master)
167
370
  options = { :repository_version => source_repository.version_href }
@@ -172,10 +375,6 @@ module Katello
172
375
  package_groups_to_include = filter_package_groups_by_pulp_href(source_repository.package_groups, content_unit_hrefs)
173
376
  content_unit_hrefs += package_groups_to_include.pluck(:pulp_id)
174
377
 
175
- package_environment_hrefs_to_include = filter_package_environments_by_pulp_hrefs(
176
- repo_service.packageenvironments(options).results, package_groups_to_include.pluck(:pulp_id))
177
- content_unit_hrefs += package_environment_hrefs_to_include
178
-
179
378
  metadata_file_hrefs_to_include = filter_metadatafiles_by_pulp_hrefs(
180
379
  repo_service.metadatafiles(options).results, content_unit_hrefs)
181
380
  content_unit_hrefs += metadata_file_hrefs_to_include