katello 3.18.2.1 → 3.18.5

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +4 -6
  3. data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +1 -1
  4. data/app/lib/actions/pulp3/content_guard/refresh_all_distributions.rb +2 -1
  5. data/app/lib/actions/pulp3/content_migration_presenter.rb +5 -2
  6. data/app/lib/katello/errors.rb +1 -1
  7. data/app/lib/katello/util/hostgroup_facets_helper.rb +126 -0
  8. data/app/models/katello/concerns/hostgroup_extensions.rb +4 -2
  9. data/app/models/katello/concerns/redhat_extensions.rb +9 -8
  10. data/app/models/katello/ping.rb +1 -1
  11. data/app/services/katello/applicability/applicable_content_helper.rb +8 -6
  12. data/app/services/katello/pulp/repository.rb +4 -2
  13. data/app/services/katello/pulp3/api/core.rb +14 -0
  14. data/app/services/katello/pulp3/migration.rb +39 -13
  15. data/app/services/katello/pulp3/migration_plan.rb +52 -3
  16. data/app/services/katello/pulp3/migration_switchover.rb +13 -0
  17. data/app/services/katello/pulp3/repository/apt.rb +1 -2
  18. data/app/services/katello/pulp3/repository.rb +34 -9
  19. data/app/services/katello/pulp3/task.rb +8 -5
  20. data/app/services/katello/pulp3/task_group.rb +13 -5
  21. data/db/migrate/20200514092553_move_katello_fields_from_hostgroups.katello.rb +1 -1
  22. data/db/migrate/20210420140050_add_pulp3_hrefs_to_content_types_deb.rb +5 -0
  23. data/lib/katello/engine.rb +1 -1
  24. data/lib/katello/tasks/check_config.rake +11 -0
  25. data/lib/katello/tasks/fix_hostgroup_facets.rake +8 -0
  26. data/lib/katello/tasks/pulp3_content_switchover.rake +30 -21
  27. data/lib/katello/tasks/pulp3_migration.rake +43 -34
  28. data/lib/katello/tasks/pulp3_migration_abort.rake +8 -0
  29. data/lib/katello/tasks/pulp3_migration_approve_corrupted.rake +7 -2
  30. data/lib/katello/tasks/pulp3_migration_stats.rake +12 -2
  31. data/lib/katello/tasks/reimport.rake +1 -1
  32. data/lib/katello/version.rb +1 -1
  33. metadata +38 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c5ad1aaf8a0bb032cc1ffd42c4c070c77cc538044396af1cd40db8d00132e58
4
- data.tar.gz: fd418dbd20507da2ca47e937df543ccf1f5a2c8d254f17623aec03f0d5d2767b
3
+ metadata.gz: 625ecabd197fcf1e9562afe5ab95076a78aad73960543c9804d0510f36bfc398
4
+ data.tar.gz: 0a6c82ff085f980e9d028a9734f3d071fa5324e6354b0c45b49406bf4400783c
5
5
  SHA512:
6
- metadata.gz: b21464bd7f2341093cb31c47a6ee1792d508b8d16f6c9f47db4e8cffb3bc737f02aa1150e50cc05352c668db37eadc5fe708cd0d2705010fbd0072f46b887877
7
- data.tar.gz: b67b69add02fae0357308a8301ac689814f2e32d835b5270c421d94cf46f6068b6398cd18cbb7da55913106deac0be816668939c605e7bf20d0a671740039402
6
+ metadata.gz: ff6a670562b076e29b4112e22b8575ae0fbc8a1864377ea538e642207a9b78e574e1bcffb9c611f61691303fb9f5b8a56e80dda96b6391d96ab836b8cfc5ab7c
7
+ data.tar.gz: f8b4a6bb32933ef5a12ebc1dab3e1e06b023c39834b9fd58dad920912ce84f25ac6974cad9611ae6d6cd87b4b2bbd45d38d71604bf42d5ebb8be72f5b93f3293
@@ -167,11 +167,9 @@ module Katello
167
167
  end
168
168
 
169
169
  if (manifest_response = redirect_client { Resources::Registry::Proxy.get(@_request.fullpath, headers) })
170
- #when pulp 2 is removed, this should no longer be needed, and all clients should be redirected
171
- logger.debug filter_sensitive_data(manifest_response)
170
+ #for some requests, we get a redirect, but for others we get the actual manifest in response
172
171
  results = JSON.parse(manifest_response)
173
-
174
- response.header['Docker-Content-Digest'] = "sha256:#{Digest::SHA256.hexdigest(manifest_response)}"
172
+ response.header['Docker-Content-Digest'] = manifest_response.headers[:docker_content_digest]
175
173
  # https://docs.docker.com/registry/spec/manifest-v2-2/
176
174
  # If its v2 schema 2 only the mediaType attribute will be present in the manifest
177
175
  media_type = results['mediaType']
@@ -184,8 +182,8 @@ module Katello
184
182
  'application/vnd.docker.distribution.manifest.v1+prettyjws'
185
183
  end
186
184
  end
187
-
188
- render json: manifest_response, content_type: media_type
185
+ response.headers['Content-Type'] = media_type
186
+ render json: manifest_response
189
187
  end
190
188
  end
191
189
 
@@ -8,7 +8,7 @@ module Actions
8
8
  def plan(proxy)
9
9
  sequence do
10
10
  plan_action(Actions::Pulp::Orchestration::OrphanCleanup::RemoveOrphans, proxy)
11
- if proxy.pulp3_enabled?
11
+ if proxy.pulp3_enabled? && ::Katello::Ping.pulpcore_enabled
12
12
  plan_action(
13
13
  Actions::Pulp3::Orchestration::OrphanCleanup::RemoveOrphans,
14
14
  proxy)
@@ -6,7 +6,8 @@ module Actions
6
6
  sequence do
7
7
  plan_action(Actions::Pulp3::ContentGuard::Refresh, smart_proxy)
8
8
 
9
- roots = ::Katello::RootRepository.where.not(:content_type => ::Katello::Repository::DOCKER_TYPE).where(:unprotected => false)
9
+ protected_types = [::Katello::Repository::YUM_TYPE, ::Katello::Repository::FILE_TYPE, ::Katello::Repository::DEB_TYPE]
10
+ roots = ::Katello::RootRepository.where(:content_type => protected_types).where(:unprotected => false)
10
11
  repositories = ::Katello::Repository.where(:root => roots)
11
12
  if repositories.any?
12
13
  plan_action(::Actions::BulkAction, Actions::Pulp3::Repository::RefreshDistribution, repositories, smart_proxy.id, assume_content_guard_exists: true)
@@ -38,7 +38,9 @@ module Actions
38
38
  end
39
39
 
40
40
  def humanized_output
41
- report = task_progress_reports.find { |current| current['state'] == 'running' && current['total'] != 0 }
41
+ #prefer running reports where the done and total do not match
42
+ report = task_progress_reports.find { |current| current['state'] == 'running' && current['total'] != 0 && current['done'] != current['total'] }
43
+ report ||= task_progress_reports.find { |current| current['state'] == 'running' && current['total'] != 0 }
42
44
  report ||= task_group_progress_reports.find { |current| current['total'] != 0 && current['done'] != current['total'] }
43
45
 
44
46
  if !report.blank? && report['total'] != 0
@@ -46,7 +48,8 @@ module Actions
46
48
  elsif report
47
49
  report['message']
48
50
  elsif task_progress_reports.empty?
49
- "Content migration starting. "
51
+ "Content migration starting. These steps may take a while to complete. " \
52
+ "Refer to `foreman-maintain content migration-stats` for an estimate."
50
53
  else
51
54
  "Initial Migration steps complete."
52
55
  end
@@ -53,7 +53,7 @@ module Katello
53
53
 
54
54
  class PulpcoreMissingCapabilities < StandardError
55
55
  def message
56
- _("A smart proxy seems to have been refreshed without pulpcore being running. You may want to ")
56
+ _("A smart proxy seems to have been refreshed without pulpcore being running. Please refresh the smart proxy after ensuring that pulpcore services are running.")
57
57
  end
58
58
  end
59
59
 
@@ -0,0 +1,126 @@
1
+ # Used exclusively by fix_hostgroup_facets.rake task
2
+ module Katello
3
+ module Util
4
+ class HostgroupFacetsHelper
5
+ def initialize
6
+ @logger = Logger.new($stdout)
7
+ end
8
+
9
+ def interested_hostgroups
10
+ groups = ::Hostgroup.unscoped.where(
11
+ id: Katello::Hostgroup::ContentFacet.
12
+ where(content_source_id: nil,
13
+ kickstart_repository_id: nil,
14
+ content_view_id: nil,
15
+ lifecycle_environment_id: nil).select(:hostgroup_id))
16
+ parents = groups.select { |group| group.parent.blank? }
17
+ children = groups.reject { |group| group.parent.blank? }
18
+ # we want the parents to get created before the children
19
+ # hence the order
20
+ parents + children
21
+ end
22
+
23
+ def pick_facet_values(hg)
24
+ # This call looks at the audit logs for a host group.
25
+ # Pries out information related to lce, ks, cv and content_source_id from the audit logs.
26
+ # The audit logs typically only contain updates.
27
+ # So if the user changed just the content_view_id, then that is the only thing marked as audited_changes.
28
+ # Hence we need to go through all the audit logs until we have information on lce, ks, cv and cs.
29
+ # If there was only one audit log and that was during the creation of hostgroup
30
+ # the audited changes look like this
31
+ # ```ruby
32
+ # {
33
+ # content_view_id: 10,
34
+ # kickstart_repository_id: 1000
35
+ # ......
36
+ # }
37
+ # ```
38
+ # However if you updated the hostgroup and set the kickstart_repository_id, or
39
+ # content_view_id then audited changes look like
40
+ # ```ruby
41
+ # {
42
+ # content_view_id: [10, 11],
43
+ # kickstart_repository_id: [1000, 1200]
44
+ # ......
45
+ # }
46
+ # ```
47
+ # So the code says "if the attribute value is an array pick the last value else just keep the value as it is "
48
+
49
+ # Further along it is to be noted that `hostgroup.audits` returns the audits ordered by the version number in ascending order, so the latest audit will be `hostgroup.audits.last`
50
+
51
+ # We want to iterate though each audit from latest audit to start, and as soon as we find a content_view_id key or kickstart_repository_id key or lifecycle environment_id key or content_source_id key we want it to be set once.
52
+
53
+ # So if I had an audit history like
54
+ # ``` ruby
55
+ # {
56
+ # content_view_id: 10,
57
+ # kickstart_repository_id: 1000,
58
+ # version:1
59
+ # ......
60
+ # },
61
+ # {
62
+ # content_view_id: [10, 11],
63
+ # kickstart_repository_id: [1000, 1200],
64
+ # version: 2
65
+ # ......
66
+ # }
67
+ # ```
68
+
69
+ # The code would start at version 2, notice that cv_id and ks_repo were set there
70
+ # and keep them as the final.
71
+ # So when it goes to version 1 since cv_id and ks_repo are already set,
72
+ # it will ignore. It will finally
73
+ # return {content_view_id: 11, kickstart_repository_id: 1200}
74
+ facet_values = {}
75
+ hg.audits.reverse_each do |audit|
76
+ hg_changes = audit.audited_changes.slice("lifecycle_environment_id",
77
+ "kickstart_repository_id",
78
+ "content_view_id",
79
+ "content_source_id")
80
+ facet_values = hg_changes.merge(facet_values)
81
+ end
82
+
83
+ values = facet_values.map do |k, v|
84
+ v = v[-1] if v.is_a? Array
85
+ [k, v]
86
+ end
87
+ values.to_h.with_indifferent_access
88
+ end
89
+
90
+ def main
91
+ bad_hgs = []
92
+ good_hgs = []
93
+
94
+ groups = interested_hostgroups.each do |hg|
95
+ facet = hg.content_facet
96
+ values = pick_facet_values(hg)
97
+ if !values.empty? && facet.update(values)
98
+ good_hgs << { hostgroup: hg, facet_values: values }
99
+ else
100
+ bad_hgs << { hostgroup: hg, facet_values: values }
101
+ facet.save(validate: false)
102
+ end
103
+ end
104
+
105
+ unless bad_hgs.empty?
106
+ @logger.warn "Some of the hostgroups reported a validation error. "\
107
+ "The hostgroups have been updated. "\
108
+ "Check via the Web UI."
109
+
110
+ bad_hgs.each do |bad_group|
111
+ @logger.warn "Hostgroup #{bad_group[:hostgroup]}"
112
+ @logger.warn "Facet Values #{bad_group[:facet_values]}"
113
+ end
114
+ end
115
+ unless good_hgs.empty?
116
+ @logger.info "Following hostgroups were succesfully updated."
117
+ good_hgs.each do |good_group|
118
+ @logger.info "Hostgroup #{good_group[:hostgroup]}"
119
+ @logger.info "Facet Values #{good_group[:facet_values]}"
120
+ end
121
+ end
122
+ @logger.info("#{groups.count} Hostgroup(s) were updated.")
123
+ end
124
+ end
125
+ end
126
+ end
@@ -107,7 +107,9 @@ module Katello
107
107
  return true unless operatingsystem
108
108
 
109
109
  if operatingsystem.respond_to? :kickstart_repos
110
- return operatingsystem.kickstart_repos(self).any? { |repo| repo[:id] == (content_facet&.kickstart_repository_id || content_facet&.kickstart_repository&.id) }
110
+ operatingsystem.kickstart_repos(self, content_facet: content_facet).any? do |repo|
111
+ repo[:id] == (content_facet&.kickstart_repository_id || content_facet&.kickstart_repository&.id)
112
+ end
111
113
  end
112
114
  end
113
115
 
@@ -126,7 +128,7 @@ module Katello
126
128
  facet_model = Facets.registered_facets[facet].hostgroup_configuration.model
127
129
  value = facet_model.where.not(attribute => nil).joins(:hostgroup).merge(
128
130
  ::Hostgroup.where(id: self.ancestor_ids).reorder(ancestry: :desc)
129
- ).limit(1).pluck(attribute)
131
+ ).limit(1).pluck(attribute).first
130
132
  end
131
133
  value
132
134
  end
@@ -42,10 +42,11 @@ module Katello
42
42
  end
43
43
  end
44
44
 
45
- def kickstart_repos(host)
46
- distros = distribution_repositories(host).where(distribution_bootable: true)
47
- if distros && host&.content_facet&.content_source
48
- distros.map { |distro| distro.to_hash(host.content_facet.content_source) }
45
+ def kickstart_repos(host, content_facet: nil)
46
+ distros = distribution_repositories(host, content_facet: content_facet).where(distribution_bootable: true)
47
+ content_facet ||= host.content_facet
48
+ if distros && content_facet&.content_source
49
+ distros.map { |distro| distro.to_hash(content_facet.content_source) }
49
50
  else
50
51
  []
51
52
  end
@@ -65,10 +66,10 @@ module Katello
65
66
  end
66
67
  end
67
68
 
68
- def distribution_repositories(host)
69
- content_view = host.try(:content_facet).try(:content_view) || host.try(:content_view)
70
- lifecycle_environment = host.try(:content_facet).try(:lifecycle_environment) || host.try(:lifecycle_environment)
71
-
69
+ def distribution_repositories(host, content_facet: nil)
70
+ content_facet ||= host.content_facet
71
+ content_view = content_facet.try(:content_view) || host.try(:content_view)
72
+ lifecycle_environment = content_facet.try(:lifecycle_environment) || host.try(:lifecycle_environment)
72
73
  if content_view && lifecycle_environment && host.os && host.architecture
73
74
  Katello::Repository.in_environment(lifecycle_environment).in_content_views([content_view]).
74
75
  where(:distribution_arch => host.architecture.name).
@@ -9,7 +9,7 @@ module Katello
9
9
  SETTINGS[:katello][:use_pulp_2_for_content_type].nil? || (!SETTINGS[:katello][:use_pulp_2_for_content_type][:yum] &&
10
10
  !SETTINGS[:katello][:use_pulp_2_for_content_type][:docker] &&
11
11
  !SETTINGS[:katello][:use_pulp_2_for_content_type][:file]) ||
12
- system('systemctl is-enabled pulpcore-api.service')
12
+ File.exist?('/etc/systemd/system/multi-user.target.wants/pulpcore-api.service')
13
13
  end
14
14
 
15
15
  def services(capsule_id = nil)
@@ -122,20 +122,22 @@ module Katello
122
122
  end
123
123
 
124
124
  def applicable_differences
125
- consumer_ids = content_facet.send(applicable_units).pluck("#{content_unit_class.table_name}.id")
126
- content_ids = fetch_content_ids
125
+ ActiveRecord::Base.connection.uncached do
126
+ consumer_ids = content_facet.send(applicable_units).pluck("#{content_unit_class.table_name}.id")
127
+ content_ids = fetch_content_ids
127
128
 
128
- to_remove = consumer_ids - content_ids
129
- to_add = content_ids - consumer_ids
129
+ to_remove = consumer_ids - content_ids
130
+ to_add = content_ids - consumer_ids
130
131
 
131
- [to_add, to_remove]
132
+ [to_add, to_remove]
133
+ end
132
134
  end
133
135
 
134
136
  def insert(applicable_ids)
135
137
  unless applicable_ids.empty?
136
138
  inserts = applicable_ids.map { |applicable_id| "(#{applicable_id.to_i}, #{content_facet.id.to_i})" }
137
139
  sql = "INSERT INTO #{content_facet_association_class.table_name} (#{content_unit_association_id}, content_facet_id) VALUES #{inserts.join(', ')}"
138
- ActiveRecord::Base.connection.execute(sql)
140
+ ActiveRecord::Base.connection.exec_insert(sql)
139
141
  end
140
142
  end
141
143
 
@@ -296,11 +296,13 @@ module Katello
296
296
 
297
297
  if proxy
298
298
  uri = URI(proxy.url)
299
+ username = CGI.escape(proxy.username) if proxy.username
300
+ password = CGI.escape(proxy.password) if proxy.password
299
301
  proxy_options = {
300
302
  proxy_host: uri.scheme + '://' + uri.host,
301
303
  proxy_port: uri.port,
302
- proxy_username: proxy.username,
303
- proxy_password: proxy.password
304
+ proxy_username: username,
305
+ proxy_password: password
304
306
  }
305
307
  return proxy_options
306
308
  end
@@ -58,6 +58,20 @@ module Katello
58
58
  fail NotImplementedError
59
59
  end
60
60
 
61
+ def self.ignore_409_exception(*)
62
+ yield
63
+ rescue => e
64
+ raise e unless e&.code == 409
65
+ nil
66
+ end
67
+
68
+ def cancel_task(task_href)
69
+ data = PulpcoreClient::TaskResponse.new(state: 'canceled')
70
+ self.class.ignore_409_exception do
71
+ tasks_api.tasks_cancel(task_href, data)
72
+ end
73
+ end
74
+
61
75
  def exporter_api
62
76
  PulpcoreClient::ExportersPulpApi.new(core_api_client)
63
77
  end
@@ -4,6 +4,8 @@ module Katello
4
4
  module Pulp3
5
5
  class Migration
6
6
  attr_accessor :smart_proxy, :reimport_all, :task_id
7
+ attr_reader :repository_types
8
+
7
9
  GET_QUERY_ID_LENGTH = 90
8
10
 
9
11
  MUTABLE_CONTENT_TYPES = [
@@ -16,7 +18,9 @@ module Katello
16
18
  ].freeze
17
19
 
18
20
  CORRUPTABLE_CONTENT_TYPES = [
19
- Katello::Rpm, Katello::FileUnit
21
+ Katello::Rpm,
22
+ Katello::FileUnit,
23
+ Katello::Deb
20
24
  ].freeze
21
25
 
22
26
  def self.repository_types_for_migration
@@ -70,7 +74,9 @@ module Katello
70
74
 
71
75
  def last_successful_migration_time
72
76
  task = ForemanTasks::Task.where(:label => Actions::Pulp3::ContentMigration.to_s, :result => 'success').order("started_at desc").first
73
- if reimport_all || task.nil?
77
+ reset_task = ForemanTasks::Task.where(:label => Actions::Pulp3::ContentMigrationReset.to_s).order("started_at desc").first
78
+ reset_more_recent = reset_task && task && reset_task.started_at > task.started_at
79
+ if reimport_all || task.nil? || reset_more_recent
74
80
  0
75
81
  else
76
82
  task.started_at.to_i
@@ -131,35 +137,36 @@ module Katello
131
137
  end
132
138
  plan = { plugins: plugins }
133
139
 
134
- # TODO: Don't provide the plan as a string once this is resolved: https://pulp.plan.io/issues/8211
135
- migration_plan_api.reset(migration_plan_api.create(plan: plan).pulp_href, plan.to_json)
140
+ pulp3_task = migration_plan_api.reset(migration_plan_api.create(plan: plan).pulp_href)
136
141
 
137
142
  content_types_for_migration.each do |content_type|
138
143
  if content_type.model_class == ::Katello::Erratum
139
144
  ::Katello::RepositoryErratum.update_all(erratum_pulp3_href: nil)
140
145
  else
141
- content_type.model_class.update_all(migrated_pulp3_href: nil)
146
+ content_type.model_class.update_all(migrated_pulp3_href: nil, missing_from_migration: false, ignore_missing_from_migration: false)
142
147
  end
143
148
  end
144
149
 
145
150
  @repository_types.each do |repo_type|
146
151
  if repo_type == "file"
147
- ::Katello::Repository.file_type.update(remote_href: nil, publication_href: nil, version_href: nil)
152
+ ::Katello::Repository.file_type.update_all(remote_href: nil, publication_href: nil, version_href: nil)
148
153
  elsif repo_type == "docker"
149
- ::Katello::Repository.docker_type.update(remote_href: nil, publication_href: nil, version_href: nil)
154
+ ::Katello::Repository.docker_type.update_all(remote_href: nil, publication_href: nil, version_href: nil)
150
155
  elsif repo_type == "yum"
151
- ::Katello::Repository.yum_type.update(remote_href: nil, publication_href: nil, version_href: nil)
156
+ ::Katello::Repository.yum_type.update_all(remote_href: nil, publication_href: nil, version_href: nil)
152
157
  end
153
158
  end
154
159
 
155
160
  ::Katello::Pulp3::RepositoryReference.destroy_all
156
161
  ::Katello::Pulp3::DistributionReference.destroy_all
157
162
  ::Katello::Pulp3::ContentGuard.destroy_all
163
+
164
+ pulp3_task
158
165
  end
159
166
 
160
167
  def create_migrations
161
168
  plan = migration_plan
162
- Rails.logger.info("Migration Plan: #{plan}")
169
+ Rails.logger.info("Migration Plan: #{plan.to_yaml}")
163
170
 
164
171
  if plan['plugins'].empty?
165
172
  Rails.logger.error("No Repositories to migrate")
@@ -209,7 +216,7 @@ module Katello
209
216
 
210
217
  if to_find
211
218
  found = migrated_repo_items.find { |migrated_repo| migrated_repo.pulp2_repo_id == to_find.pulp_id }
212
- import_repo(yum_repo, found)
219
+ import_repo(yum_repo, found) if found
213
220
  end
214
221
  end
215
222
  end
@@ -298,10 +305,29 @@ module Katello
298
305
  to_import[[errata_id, repo_id]] ||= {erratum_id: errata_id, erratum_pulp3_href: pulp3_href, repository_id: repo_id}
299
306
  end
300
307
  end
308
+
309
+ Katello::RepositoryErratum.import([:erratum_id, :erratum_pulp3_href, :repository_id], to_import.values, :validate => false,
310
+ on_duplicate_key_update: {conflict_target: [:erratum_id, :repository_id], columns: [:erratum_pulp3_href]})
311
+ to_import = {}
301
312
  end
313
+ correct_missing_errata
314
+ end
302
315
 
303
- Katello::RepositoryErratum.import([:erratum_id, :erratum_pulp3_href, :repository_id], to_import.values, :validate => false,
304
- on_duplicate_key_update: {conflict_target: [:erratum_id, :repository_id], columns: [:erratum_pulp3_href]})
316
+ def correct_missing_errata
317
+ Katello::RepositoryErratum.where(:erratum_pulp3_href => nil).pluck(:repository_id).uniq.each do |repo_id|
318
+ repo = Katello::Repository.find(repo_id)
319
+ if repo.link?
320
+ target = repo.target_repository
321
+ to_import = []
322
+ target.repository_errata.each do |repo_errata|
323
+ to_import << {erratum_id: repo_errata.erratum_id, erratum_pulp3_href: repo_errata.erratum_pulp3_href, repository_id: repo_id}
324
+ end
325
+ Katello::RepositoryErratum.import([:erratum_id, :erratum_pulp3_href, :repository_id], to_import, :validate => false,
326
+ on_duplicate_key_update: {conflict_target: [:erratum_id, :repository_id], columns: [:erratum_pulp3_href]})
327
+ else
328
+ Rails.logger.error("Unexpectedly found target repo (ID=#{repo_id}) with missing migrated errata!")
329
+ end
330
+ end
305
331
  end
306
332
 
307
333
  def mark_missing_content(content_type)
@@ -327,7 +353,7 @@ module Katello
327
353
  unmigrated_units.select(:id, :pulp_id).find_in_batches(batch_size: GET_QUERY_ID_LENGTH) do |needing_hrefs|
328
354
  current_count += needing_hrefs.count
329
355
  update_import_status("Importing migrated content type #{content_type.label}: #{current_count}/#{total_count}")
330
- migrated_units = pulp2_content_api.list(pulp2_id__in: needing_hrefs.map { |unit| unit.pulp_id }.join(','))
356
+ migrated_units = pulp2_content_api.list(pulp2_id__in: needing_hrefs.map(&:pulp_id))
331
357
  migrated_units.results.each do |migrated_unit|
332
358
  content_type.model_class.where(pulp_id: migrated_unit.pulp2_id).update_all(migrated_pulp3_href: migrated_unit.pulp3_content)
333
359
  end
@@ -14,7 +14,6 @@ module Katello
14
14
  Katello::Logging.time("CONTENT_MIGRATION - Generating Migration plan") do
15
15
  plan[:plugins] = generate_plugins
16
16
  end
17
- Rails.logger.error("Migration Plan: #{plan.to_json}")
18
17
  plan
19
18
  end
20
19
 
@@ -39,6 +38,7 @@ module Katello
39
38
  roots = Katello::RootRepository.where(:content_type => repo_type).order(:label)
40
39
  plans = []
41
40
  roots.each do |root|
41
+ next unless root.library_instance
42
42
  plans << library_migration_for(root)
43
43
  plans += content_view_migrations_for(root)
44
44
  end
@@ -64,6 +64,8 @@ module Katello
64
64
  def library_migration_for(root)
65
65
  repo = root.library_instance
66
66
 
67
+ return nil unless library_repo_safe_to_migrate?(repo)
68
+
67
69
  migration = {
68
70
  name: repo.pulp_id,
69
71
  repository_versions: [
@@ -77,10 +79,49 @@ module Katello
77
79
  migration
78
80
  end
79
81
 
82
+ def library_repo_safe_to_migrate?(repo)
83
+ publish_tasks = ForemanTasks::Task.where(label: 'Actions::Katello::ContentView::Publish')
84
+ publishing_repo_ids = publish_tasks.where(state: ['scheduled', 'running']).collect do |task|
85
+ ::Katello::ContentViewVersion.find(task.input[:content_view_version_id]).library_repos.pluck(:id)
86
+ end
87
+ publishing_repo_ids = publishing_repo_ids.flatten
88
+
89
+ if publishing_repo_ids.include?(repo.id)
90
+ warn_string = "Library repository with ID #{repo.id} and name #{repo.name} unmigrated due to being "\
91
+ "associated with an actively-publishing content view. The migration will need to be run again."
92
+ Rails.logger.warn(warn_string)
93
+ return false
94
+ end
95
+
96
+ create_root_tasks = ForemanTasks::Task.where(label: 'Actions::Katello::Repository::CreateRoot')
97
+ active_creation_task = create_root_tasks.where(state: ['scheduled', 'running']).detect do |task|
98
+ task.input[:repository][:id] == repo.id
99
+ end
100
+
101
+ if active_creation_task.present?
102
+ warn_string = "Repository with ID #{repo.id} and name #{repo.name} unmigrated due to being "\
103
+ "created during the Pulp 3 migration. The migration will need to be run again."
104
+ Rails.logger.warn(warn_string)
105
+ return false
106
+ end
107
+ true
108
+ end
109
+
80
110
  def content_view_migrations_for(root)
111
+ publish_tasks = ForemanTasks::Task.where(label: 'Actions::Katello::ContentView::Publish')
112
+ publishing_cv_ids = publish_tasks.where(state: ['scheduled', 'running']).collect do |task|
113
+ task.input[:content_view_id]
114
+ end
115
+
81
116
  plans = []
82
117
  ContentView.non_default.published_with_repositories(root).sort_by(&:label).each do |cv|
83
- plans << content_view_migration(cv, root)
118
+ if publishing_cv_ids.include?(cv.id)
119
+ warn_string = "Repositories belonging to Content View with ID #{cv.id} and name #{cv.name} unmigrated "\
120
+ "due to being created during the Pulp 3 migration. The migration will need to be run again."
121
+ Rails.logger.warn(warn_string)
122
+ else
123
+ plans << content_view_migration(cv, root)
124
+ end
84
125
  end
85
126
  plans
86
127
  end
@@ -105,7 +146,15 @@ module Katello
105
146
  end
106
147
 
107
148
  def name_for_content_view(content_view, root_repo)
108
- "#{content_view.label}-#{root_repo.label}"
149
+ name = "#{content_view.label}-#{root_repo.label}"
150
+
151
+ if Katello::RootRepository.where(:label => root_repo.label).group(:label).count(:label)[root_repo.label] > 1
152
+ repo_query = Katello::Repository.joins(:root, :content_view_version => :content_view).
153
+ where("#{::Katello::RootRepository.table_name}.id != #{root_repo.id}").
154
+ where("#{::Katello::RootRepository.table_name}.label" => root_repo.label, "#{::Katello::ContentView.table_name}.label" => content_view.label)
155
+ name += "-#{root_repo.id}" if repo_query.any?
156
+ end
157
+ name
109
158
  end
110
159
 
111
160
  def content_view_migration(content_view, root)
@@ -25,6 +25,19 @@ module Katello
25
25
  end
26
26
  end
27
27
 
28
+ def remove_orphaned_content
29
+ models = []
30
+ @migration.repository_types.each do |repo_type_label|
31
+ repo_type = ::Katello::RepositoryTypeManager.repository_types[repo_type_label]
32
+ indexable_types = repo_type.content_types_to_index
33
+ models += indexable_types&.map(&:model_class)
34
+ models.select! { |model| model.many_repository_associations }
35
+ end
36
+ models.each do |model|
37
+ model.joins("left join katello_#{model.repository_association} on #{model.table_name}.id = katello_#{model.repository_association}.#{model.unit_id_field}").where("katello_#{model.repository_association}.#{model.unit_id_field} IS NULL").destroy_all
38
+ end
39
+ end
40
+
28
41
  def deduplicated_content_types
29
42
  #even though YumMetatadataFile is de-depulicated, we're not indexing it in pulp3
30
43
  [Katello::PackageGroup]
@@ -27,8 +27,7 @@ module Katello
27
27
  popts = super(repository_version)
28
28
  popts.merge!(
29
29
  {
30
- # structured is not necessary for subscription-manager
31
- #structured: true, # publish real suites (e.g. 'stable')
30
+ structured: true, # publish real suites (e.g. 'stable')
32
31
  simple: true # publish all into 'default'-suite
33
32
  }
34
33
  )
@@ -1,7 +1,7 @@
1
+ # rubocop:disable Metrics/ClassLength
1
2
  require "pulpcore_client"
2
3
  module Katello
3
4
  module Pulp3
4
- # rubocop:disable Metrics/ClassLength
5
5
  class Repository
6
6
  include Katello::Util::HttpProxy
7
7
  attr_accessor :repo
@@ -158,10 +158,7 @@ module Katello
158
158
  end
159
159
 
160
160
  def compute_remote_options(computed_options = remote_options)
161
- [:client_cert, :client_key, :ca_cert].each do |key|
162
- computed_options[key] = Digest::SHA256.hexdigest(computed_options[key].chomp) if computed_options[key]
163
- end
164
- computed_options.except(:name)
161
+ computed_options.except(:name, :client_key)
165
162
  end
166
163
 
167
164
  def create
@@ -221,11 +218,38 @@ module Katello
221
218
  end
222
219
 
223
220
  def refresh_distributions
224
- dist_ref = distribution_reference
225
- if dist_ref
226
- update_distribution
221
+ if repo.docker?
222
+ dist = lookup_distributions(base_path: repo.container_repository_name).first
227
223
  else
224
+ dist = lookup_distributions(base_path: repo.relative_path).first
225
+ end
226
+
227
+ # First check if the distribution exists
228
+ if dist
229
+ dist_ref = distribution_reference
230
+ # If we have a DistributionReference, update the distribution
231
+ if dist_ref
232
+ return update_distribution
233
+ # If no DistributionReference, create a DistributionReference and return
234
+ else
235
+ save_distribution_references([dist.pulp_href])
236
+ return []
237
+ end
238
+ end
239
+
240
+ # So far, it looks like there is no distribution. Try to create one.
241
+ begin
228
242
  create_distribution(relative_path)
243
+ rescue api.class.client_module::ApiError => e
244
+ # Now it seems there is a distribution. Fetch it and save the reference.
245
+ if e.message.include?("\"base_path\":[\"This field must be unique.\"]") ||
246
+ e.message.include?("\"base_path\":[\"Overlaps with existing distribution\"")
247
+ dist = lookup_distributions(base_path: repo.relative_path).first
248
+ save_distribution_references([dist.pulp_href])
249
+ return []
250
+ else
251
+ raise e
252
+ end
229
253
  end
230
254
  end
231
255
 
@@ -275,7 +299,8 @@ module Katello
275
299
  pulp3_distribution_data = api.get_distribution(href)
276
300
  path, content_guard_href = pulp3_distribution_data&.base_path, pulp3_distribution_data&.content_guard
277
301
  unless distribution_reference
278
- DistributionReference.create!(path: path, href: href, repository_id: repo.id, content_guard_href: content_guard_href)
302
+ # Ensure that duplicates won't be created in the case of a race condition
303
+ DistributionReference.where(path: path, href: href, repository_id: repo.id, content_guard_href: content_guard_href).first_or_create!
279
304
  end
280
305
  end
281
306
  end
@@ -56,8 +56,10 @@ module Katello
56
56
  @pulp_data ||= tasks_api.read(@href).as_json.with_indifferent_access
57
57
  end
58
58
 
59
- def tasks_api
60
- ::Katello::Pulp3::Api::Core.new(@smart_proxy).tasks_api
59
+ delegate :tasks_api, to: :core_api
60
+
61
+ def core_api
62
+ ::Katello::Pulp3::Api::Core.new(@smart_proxy)
61
63
  end
62
64
 
63
65
  def task_group_href
@@ -94,10 +96,11 @@ module Katello
94
96
  end
95
97
 
96
98
  def cancel
97
- data = PulpcoreClient::TaskResponse.new(state: 'canceled')
98
- tasks_api.tasks_cancel(task_data['pulp_href'], data)
99
+ core_api.cancel_task(task_data['pulp_href'])
99
100
  #the main task may have completed, so cancel spawned tasks too
100
- task_data['spawned_tasks']&.each { |spawned| tasks_api.tasks_cancel(spawned['pulp_href'], data) }
101
+ task_data['spawned_tasks']&.each do |spawned|
102
+ core_api.cancel_task(spawned['pulp_href'])
103
+ end
101
104
  end
102
105
  end
103
106
  end
@@ -71,17 +71,25 @@ module Katello
71
71
  end
72
72
 
73
73
  def error
74
+ return if task_group_data[WAITING] > 0 || task_group_data[RUNNING] > 0
74
75
  if task_group_data[FAILED] > 0
75
76
  "#{task_group_data[FAILED]} subtask(s) failed for task group #{@href}."
77
+ elsif task_group_data[CANCELLED] > 0
78
+ "#{task_group_data[CANCELLED]} subtask(s) cancelled for task group #{@href}."
76
79
  end
77
80
  end
78
81
 
82
+ def core_api
83
+ ::Katello::Pulp3::Api::Core.new(@smart_proxy)
84
+ end
85
+
79
86
  def cancel
80
- tasks_api = ::Katello::Pulp3::Api::Core.new(@smart_proxy).tasks_api
81
- tasks_response = tasks_api.list(task_group: task_group_data['pulp_href'])
82
- data = PulpcoreClient::TaskResponse.new(state: 'canceled')
83
- tasks_response.results.collect do |result|
84
- tasks_api.tasks_cancel(result.pulp_href, data)
87
+ tasks_api = core_api.tasks_api
88
+ tasks_response = core_api.class.fetch_from_list do |page_opts|
89
+ tasks_api.list(page_opts.merge(task_group: task_group_data['pulp_href'], state__in: 'running,waiting'))
90
+ end
91
+ tasks_response.collect do |result|
92
+ ::Katello::Pulp3::Api::Core.new(@smart_proxy).cancel_task(result.pulp_href)
85
93
  end
86
94
  end
87
95
  end
@@ -46,7 +46,7 @@ class MoveKatelloFieldsFromHostgroups < ActiveRecord::Migration[6.0]
46
46
  content_facet.kickstart_repository_id = kickstart_repository_id
47
47
  content_facet.content_view_id = content_view_id
48
48
  content_facet.lifecycle_environment_id = lifecycle_environment_id
49
- unless content_facet.save
49
+ unless content_facet.save(validate: false)
50
50
  Rails.logger.warn("Unable to save content facet hostgroup for #{content_facet.inspect} ")
51
51
  Rails.logger.warn(content_facet.errors.full_messages.join("\n"))
52
52
  end
@@ -0,0 +1,5 @@
1
+ class AddPulp3HrefsToContentTypesDeb < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_column Katello::Deb.table_name, :migrated_pulp3_href, :string, :default => nil, :null => true
4
+ end
5
+ end
@@ -75,7 +75,7 @@ module Katello
75
75
 
76
76
  # make sure the Katello plugin is initialized before `after_initialize`
77
77
  # hook so that the resumed Dynflow tasks can rely on everything ready.
78
- initializer 'katello.register_plugin', :before => :finisher_hook do
78
+ initializer 'katello.register_plugin', :before => :finisher_hook, :after => 'foreman_remote_execution.register_plugin' do
79
79
  ::Foreman::AccessControl::Permission.prepend ::Katello::Concerns::PermissionExtensions
80
80
  require 'katello/plugin'
81
81
 
@@ -0,0 +1,11 @@
1
+ namespace :katello do
2
+ task :check_config => ['environment'] do
3
+ desc "Task that can be run before a content migration to check that the configuration valid"
4
+ fail_msg = _("The system appears to already be using pulp3 with all content migrated.")
5
+
6
+ puts "Checking for valid Katello configuraton."
7
+ if SETTINGS[:katello][:use_pulp_2_for_content_type].nil?
8
+ fail fail_msg
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ namespace :katello do
2
+ desc "This task collates hostgroup content facts that were missed during the upgrade from audit.\
3
+ It then updates the hostgroup content_facet accordingly."
4
+ task :fix_hostgroup_facets => :environment do
5
+ User.current = User.anonymous_admin
6
+ ::Katello::Util::HostgroupFacetsHelper.new.main
7
+ end
8
+ end
@@ -3,32 +3,41 @@ require "#{Katello::Engine.root}/app/services/katello/pulp3/migration_switchover
3
3
 
4
4
  namespace :katello do
5
5
  desc "Runs a Pulp 3 migration of pulp3 hrefs to pulp ids for supported content types."
6
- task :pulp3_content_switchover => ["dynflow:client"] do
6
+ task :pulp3_content_switchover => ["dynflow:client", "check_config"] do
7
7
  dryrun = ENV['DRYRUN']
8
- begin
9
- User.current = User.anonymous_admin
10
8
 
11
- ActiveRecord::Base.transaction do
9
+ if !SETTINGS[:katello][:use_pulp_2_for_content_type][:docker] &&
10
+ !SETTINGS[:katello][:use_pulp_2_for_content_type][:file] &&
11
+ !SETTINGS[:katello][:use_pulp_2_for_content_type][:yum] &&
12
+ !SETTINGS[:katello][:use_pulp_2_for_content_type][:deb]
13
+ puts "Switchover is already complete, skipping switchover task."
14
+ else
15
+ begin
16
+ User.current = User.anonymous_admin
17
+
12
18
  switchover_service = Katello::Pulp3::MigrationSwitchover.new(SmartProxy.pulp_primary)
13
- switchover_service.run
14
- fail "Dryrun completed without error, aborting and rolling back" if dryrun
19
+ switchover_service.remove_orphaned_content #run out of transaction for easier re-run
20
+ ActiveRecord::Base.transaction do
21
+ switchover_service.run
22
+ fail "Dryrun completed without error, aborting and rolling back" if dryrun
23
+ end
24
+ rescue Katello::Pulp3::SwitchOverError => e
25
+ $stderr.print(e.message)
26
+ exit 1
15
27
  end
16
- rescue Katello::Pulp3::SwitchOverError => e
17
- $stderr.print(e.message)
18
- exit 1
19
- end
20
28
 
21
- task = ForemanTasks.sync_task(Actions::Pulp3::ContentGuard::RefreshAllDistributions, SmartProxy.pulp_primary)
22
- until !task.pending? || task.paused?
23
- sleep(10)
24
- task = ForemanTasks::Task.find(task.id)
25
- end
26
- if task.result == 'error' || task.result == 'pending'
27
- msg _("Content Guard Configuration failed, switchover aborted. Switchover continuing, but after completion, you will want to investigate: https://#{Socket.gethostname}/foreman_tasks/tasks/#{task.id}")
28
- Rails.logger.error(msg)
29
- $stderr.print(msg)
30
- else
31
- puts _("Content Switchover completed successfully")
29
+ task = ForemanTasks.async_task(Actions::Pulp3::ContentGuard::RefreshAllDistributions, SmartProxy.pulp_primary)
30
+ until !task.pending? || task.paused?
31
+ sleep(10)
32
+ task = ForemanTasks::Task.find(task.id)
33
+ end
34
+ if task.result == 'error' || task.result == 'pending'
35
+ msg _("Content Guard Configuration failed, switchover aborted. Switchover continuing, but after completion, you will want to investigate: https://#{Socket.gethostname}/foreman_tasks/tasks/#{task.id}")
36
+ Rails.logger.error(msg)
37
+ $stderr.print(msg)
38
+ else
39
+ puts _("Content Switchover completed successfully")
40
+ end
32
41
  end
33
42
  end
34
43
  end
@@ -1,48 +1,57 @@
1
1
  namespace :katello do
2
2
  desc "Runs a Pulp 2 to 3 Content Migration for supported types. May be run multiple times. Use wait=false to immediately return with a task url."
3
- task :pulp3_migration => ["dynflow:client"] do
4
- services = [:candlepin, :foreman_tasks, :pulp3, :pulp, :pulp_auth]
5
- Katello::Ping.ping!(services: services)
3
+ task :pulp3_migration => ["dynflow:client", 'check_config'] do
4
+ if !SETTINGS[:katello][:use_pulp_2_for_content_type][:docker] &&
5
+ !SETTINGS[:katello][:use_pulp_2_for_content_type][:file] &&
6
+ !SETTINGS[:katello][:use_pulp_2_for_content_type][:yum] &&
7
+ !SETTINGS[:katello][:use_pulp_2_for_content_type][:deb]
8
+ puts "Switchover is already complete, skipping migration work."
9
+ else
10
+ services = [:candlepin, :foreman_tasks, :pulp3, :pulp, :pulp_auth]
11
+ Katello::Ping.ping!(services: services)
6
12
 
7
- puts "Starting task."
8
- SmartProxy.pulp_primary.refresh
13
+ puts "Starting task."
14
+ SmartProxy.pulp_primary.refresh
9
15
 
10
- reimport_all = ::Foreman::Cast.to_bool(ENV['reimport_all'])
11
- wait = ::Foreman::Cast.to_bool(ENV['wait'] || 'true')
12
- preserve_output = ::Foreman::Cast.to_bool(ENV['preserve_output'])
16
+ reimport_all = ::Foreman::Cast.to_bool(ENV['reimport_all'])
17
+ wait = ::Foreman::Cast.to_bool(ENV['wait'] || 'true')
18
+ preserve_output = ::Foreman::Cast.to_bool(ENV['preserve_output'])
13
19
 
14
- User.current = User.anonymous_api_admin
15
- task = ForemanTasks.async_task(Actions::Pulp3::ContentMigration, SmartProxy.pulp_primary, reimport_all: reimport_all)
20
+ User.current = User.anonymous_api_admin
21
+ Katello::Pulp3::MigrationSwitchover.new(SmartProxy.pulp_primary).remove_orphaned_content
22
+ task = ForemanTasks.async_task(Actions::Pulp3::ContentMigration, SmartProxy.pulp_primary, reimport_all: reimport_all)
16
23
 
17
- if wait
18
- clear_count = nil
19
- until !task.pending? || task.paused?
20
- $stdout.print("\r#{' ' * clear_count}\r") if clear_count && !preserve_output #clear the line before printing
21
- $stdout.print("\n") if preserve_output
22
- message = "#{Time.now.to_s}: #{task.humanized[:output]}"
23
- clear_count = message.length + 1
24
- $stdout.print(message)
24
+ if wait
25
+ clear_count = nil
26
+ until !task.pending? || task.paused?
27
+ $stdout.print("\r#{' ' * clear_count}\r") if clear_count && !preserve_output #clear the line before printing
28
+ $stdout.print("\n") if preserve_output
29
+ message = "#{Time.now.to_s}: #{task.humanized[:output]}"
30
+ clear_count = message.length + 1
31
+ $stdout.print(message)
32
+ $stdout.flush
25
33
 
26
- sleep(10)
27
- task = ForemanTasks::Task.find(task.id)
28
- end
34
+ sleep(10)
35
+ task = ForemanTasks::Task.find(task.id)
36
+ end
29
37
 
30
- if task.result == 'warning' || task.result == 'pending'
31
- msg = _("Migration failed, You will want to investigate: https://#{Socket.gethostname}/foreman_tasks/tasks/#{task.id}\n")
32
- $stderr.print(msg)
33
- fail ForemanTasks::TaskError, task
34
- else
35
- puts
36
- Katello::Pulp3::Migration::CORRUPTABLE_CONTENT_TYPES.each do |type|
37
- if type.missing_migrated_content.any?
38
- puts "Some corrupted or missing content found, run 'foreman-maintain content migration-stats' for more information."
39
- exit(-1)
38
+ if task.result == 'warning' || task.result == 'pending'
39
+ msg = _("Migration failed, You will want to investigate: https://#{Socket.gethostname}/foreman_tasks/tasks/#{task.id}\n")
40
+ $stderr.print(msg)
41
+ fail ForemanTasks::TaskError, task
42
+ else
43
+ puts
44
+ Katello::Pulp3::Migration::CORRUPTABLE_CONTENT_TYPES.each do |type|
45
+ if type.missing_migrated_content.any?
46
+ puts "Some corrupted or missing content found, run 'foreman-maintain content migration-stats' for more information."
47
+ exit(-1)
48
+ end
40
49
  end
50
+ puts _("Content Migration completed successfully")
41
51
  end
42
- puts _("Content Migration completed successfully")
52
+ else
53
+ puts "Migration started, you may monitor it at: https://#{Socket.gethostname}/foreman_tasks/tasks/#{task.id}"
43
54
  end
44
- else
45
- puts "Migration started, you may monitor it at: https://#{Socket.gethostname}/foreman_tasks/tasks/#{task.id}"
46
55
  end
47
56
  end
48
57
  end
@@ -17,6 +17,14 @@ namespace :katello do
17
17
  cancelled_tasks_count += 1 if cancelled_task
18
18
  end
19
19
 
20
+ api = Katello::Pulp3::Api::Core.new(SmartProxy.pulp_primary)
21
+ %w(pulp_2to3_migration.app.tasks.migrate.migrate_from_pulp2 pulp_2to3_migration.app.migration.complex_repo_migration).each do |task_label|
22
+ api.tasks_api.list(:state__in => 'running,waiting', :name => task_label).results.each do |task|
23
+ api.cancel_task(task.pulp_href)
24
+ cancelled_tasks_count += 1
25
+ end
26
+ end
27
+
20
28
  puts _("\e[33mCancelled #{cancelled_tasks_count} tasks.\e[0m")
21
29
  end
22
30
  end
@@ -1,13 +1,18 @@
1
1
  namespace :katello do
2
2
  desc "Marks corrupted or missing content as approved to be ignored during the migration"
3
- task :approve_corrupted_migration_content => ["dynflow:client", "check_ping"] do
3
+ task :approve_corrupted_migration_content => ["dynflow:client"] do
4
+ services = [:candlepin, :foreman_tasks, :pulp3, :pulp, :pulp_auth]
5
+ Katello::Ping.ping!(services: services)
6
+
4
7
  Katello::Pulp3::Migration::CORRUPTABLE_CONTENT_TYPES.each do |type|
5
8
  type.missing_migrated_content.update_all(:ignore_missing_from_migration => true)
6
9
  end
7
10
  puts "Any missing or corrupt content will be ignored on migration to Pulp 3. This can be undone with 'foreman-rake katello:unapprove_corrupted_migration_content'"
8
11
  end
9
12
 
10
- task :unapprove_corrupted_migration_content => ["dynflow:client", "check_ping"] do
13
+ task :unapprove_corrupted_migration_content => ["dynflow:client"] do
14
+ services = [:candlepin, :foreman_tasks, :pulp3, :pulp, :pulp_auth]
15
+ Katello::Ping.ping!(services: services)
11
16
  Katello::Pulp3::Migration::CORRUPTABLE_CONTENT_TYPES.each do |type|
12
17
  type.ignored_missing_migrated_content.update_all(:ignore_missing_from_migration => false)
13
18
  end
@@ -10,7 +10,8 @@ namespace :katello do
10
10
  migratable_repo_count = ::Katello::Repository.count - ::Katello::Repository.puppet_type.count -
11
11
  ::Katello::Repository.ostree_type.count - ::Katello::Repository.deb_type.count
12
12
 
13
- on_demand_rpm_count = Katello::RepositoryRpm.where(:repository_id => Katello::Repository.yum_type.on_demand).distinct.count
13
+ on_demand_rpm_count = Katello::RepositoryRpm.where(:repository_id => Katello::Repository.yum_type.on_demand).
14
+ select(:rpm_id).distinct.count
14
15
  on_demand_unmigrated_rpm_count = on_demand_rpm_count - migrated_rpm_count
15
16
  immediate_unmigrated_rpm_count = ::Katello::Rpm.count - migrated_rpm_count - on_demand_unmigrated_rpm_count
16
17
 
@@ -27,10 +28,14 @@ namespace :katello do
27
28
  puts "Migrated/Total RPMs: #{migrated_rpm_count}/#{::Katello::Rpm.count}"
28
29
  puts "Migrated/Total errata: #{migrated_erratum_count}/#{::Katello::RepositoryErratum.count}"
29
30
  puts "Migrated/Total repositories: #{migrated_repo_count}/#{migratable_repo_count}"
30
- puts
31
+
31
32
  # The timing formulas go negative if the amount of content is negligibly small
32
33
  if migration_minutes >= 5
33
34
  puts "Estimated migration time based on yum content: #{hours} hours, #{minutes} minutes"
35
+ elsif migrated_rpm_count == ::Katello::Rpm.count &&
36
+ migrated_erratum_count == ::Katello::RepositoryErratum.count &&
37
+ migrated_repo_count == migratable_repo_count
38
+ puts "All content has been migrated."
34
39
  else
35
40
  puts "Estimated migration time based on yum content: fewer than 5 minutes"
36
41
  end
@@ -39,6 +44,11 @@ namespace :katello do
39
44
  puts "\e[33mNote:\e[0m ensure there is sufficient storage space for /var/lib/pulp/published to triple in size before starting the migration process."
40
45
  puts "Check the size of /var/lib/pulp/published with 'du -sh /var/lib/pulp/published/'"
41
46
 
47
+ puts
48
+ puts "\e[33mNote:\e[0m ensure there is sufficient storage space for postgresql."
49
+ puts "You will need additional space for your postgresql database. The partition holding '/var/opt/rh/rh-postgresql12/lib/pgsql/data/'"
50
+ puts " will need additional free space equivalent to the size of your Mongo db database (/var/lib/mongodb/)."
51
+
42
52
  displayed_warning = false
43
53
  found_missing = false
44
54
  path = Dir.mktmpdir('unmigratable_content-')
@@ -2,7 +2,7 @@ require File.expand_path("../engine", File.dirname(__FILE__))
2
2
 
3
3
  namespace :katello do
4
4
  desc "Runs a katello ping and prints out the statuses of each service"
5
- task :check_ping => :environment do
5
+ task :check_ping => [:environment, "dynflow:client"] do
6
6
  ::User.current = ::User.anonymous_admin
7
7
  ping_results = Katello::Ping.ping
8
8
  if ping_results[:status] != "ok"
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "3.18.2.1".freeze
2
+ VERSION = "3.18.5".freeze
3
3
  end
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.18.2.1
4
+ version: 3.18.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - N/A
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-16 00:00:00.000000000 Z
11
+ date: 2021-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -100,6 +100,20 @@ dependencies:
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '4.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: foreman-tasks-core
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "<"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.4'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "<"
115
+ - !ruby/object:Gem::Version
116
+ version: '0.4'
103
117
  - !ruby/object:Gem::Dependency
104
118
  name: foreman_remote_execution
105
119
  requirement: !ruby/object:Gem::Requirement
@@ -269,7 +283,7 @@ dependencies:
269
283
  version: 3.6.0
270
284
  - - "<"
271
285
  - !ruby/object:Gem::Version
272
- version: 3.8.0
286
+ version: 3.7.7
273
287
  type: :runtime
274
288
  prerelease: false
275
289
  version_requirements: !ruby/object:Gem::Requirement
@@ -279,7 +293,7 @@ dependencies:
279
293
  version: 3.6.0
280
294
  - - "<"
281
295
  - !ruby/object:Gem::Version
282
- version: 3.8.0
296
+ version: 3.7.7
283
297
  - !ruby/object:Gem::Dependency
284
298
  name: pulp_file_client
285
299
  requirement: !ruby/object:Gem::Requirement
@@ -346,60 +360,60 @@ dependencies:
346
360
  requirements:
347
361
  - - ">="
348
362
  - !ruby/object:Gem::Version
349
- version: 2.6.0
363
+ version: 2.9.0
350
364
  - - "<"
351
365
  - !ruby/object:Gem::Version
352
- version: 2.8.0
366
+ version: 2.10.0
353
367
  type: :runtime
354
368
  prerelease: false
355
369
  version_requirements: !ruby/object:Gem::Requirement
356
370
  requirements:
357
371
  - - ">="
358
372
  - !ruby/object:Gem::Version
359
- version: 2.6.0
373
+ version: 2.9.0
360
374
  - - "<"
361
375
  - !ruby/object:Gem::Version
362
- version: 2.8.0
376
+ version: 2.10.0
363
377
  - !ruby/object:Gem::Dependency
364
378
  name: pulp_rpm_client
365
379
  requirement: !ruby/object:Gem::Requirement
366
380
  requirements:
367
381
  - - ">="
368
382
  - !ruby/object:Gem::Version
369
- version: 3.9.0
383
+ version: 3.10.0
370
384
  - - "<"
371
385
  - !ruby/object:Gem::Version
372
- version: 3.10.0
386
+ version: 3.11.0
373
387
  type: :runtime
374
388
  prerelease: false
375
389
  version_requirements: !ruby/object:Gem::Requirement
376
390
  requirements:
377
391
  - - ">="
378
392
  - !ruby/object:Gem::Version
379
- version: 3.9.0
393
+ version: 3.10.0
380
394
  - - "<"
381
395
  - !ruby/object:Gem::Version
382
- version: 3.10.0
396
+ version: 3.11.0
383
397
  - !ruby/object:Gem::Dependency
384
398
  name: pulp_2to3_migration_client
385
399
  requirement: !ruby/object:Gem::Requirement
386
400
  requirements:
387
401
  - - ">="
388
402
  - !ruby/object:Gem::Version
389
- version: 0.7.0
403
+ version: 0.8.0
390
404
  - - "<"
391
405
  - !ruby/object:Gem::Version
392
- version: 0.8.0
406
+ version: 1.0.0
393
407
  type: :runtime
394
408
  prerelease: false
395
409
  version_requirements: !ruby/object:Gem::Requirement
396
410
  requirements:
397
411
  - - ">="
398
412
  - !ruby/object:Gem::Version
399
- version: 0.7.0
413
+ version: 0.8.0
400
414
  - - "<"
401
415
  - !ruby/object:Gem::Version
402
- version: 0.8.0
416
+ version: 1.0.0
403
417
  - !ruby/object:Gem::Dependency
404
418
  name: pulp_certguard_client
405
419
  requirement: !ruby/object:Gem::Requirement
@@ -1182,6 +1196,7 @@ files:
1182
1196
  - app/lib/katello/util/docker_manifest_clause_generator.rb
1183
1197
  - app/lib/katello/util/errata.rb
1184
1198
  - app/lib/katello/util/filter_clause_generator.rb
1199
+ - app/lib/katello/util/hostgroup_facets_helper.rb
1185
1200
  - app/lib/katello/util/http_proxy.rb
1186
1201
  - app/lib/katello/util/model.rb
1187
1202
  - app/lib/katello/util/module_stream_clause_generator.rb
@@ -2142,6 +2157,7 @@ files:
2142
2157
  - db/migrate/20201021150008_add_import_only_to_katello_content_view.rb
2143
2158
  - db/migrate/20201119211133_pulp3_migration_progress.rb
2144
2159
  - db/migrate/20210201165835_add_migration_missing_content.rb
2160
+ - db/migrate/20210420140050_add_pulp3_hrefs_to_content_types_deb.rb
2145
2161
  - db/seeds.d/101-locations.rb
2146
2162
  - db/seeds.d/102-organizations.rb
2147
2163
  - db/seeds.d/104-proxy.rb
@@ -4484,10 +4500,12 @@ files:
4484
4500
  - lib/katello/repository_types/puppet.rb
4485
4501
  - lib/katello/repository_types/yum.rb
4486
4502
  - lib/katello/scheduled_jobs.rb
4503
+ - lib/katello/tasks/check_config.rake
4487
4504
  - lib/katello/tasks/clean_backend_objects.rake
4488
4505
  - lib/katello/tasks/clean_old_file_repos.rake
4489
4506
  - lib/katello/tasks/clean_published_repo_directories.rake
4490
4507
  - lib/katello/tasks/delete_orphaned_content.rake
4508
+ - lib/katello/tasks/fix_hostgroup_facets.rake
4491
4509
  - lib/katello/tasks/import_applicability.rake
4492
4510
  - lib/katello/tasks/import_subscriptions.rake
4493
4511
  - lib/katello/tasks/jenkins.rake
@@ -5062,7 +5080,7 @@ homepage: http://www.katello.org
5062
5080
  licenses:
5063
5081
  - GPL-2.0
5064
5082
  metadata: {}
5065
- post_install_message:
5083
+ post_install_message:
5066
5084
  rdoc_options: []
5067
5085
  require_paths:
5068
5086
  - lib
@@ -5077,8 +5095,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
5077
5095
  - !ruby/object:Gem::Version
5078
5096
  version: '0'
5079
5097
  requirements: []
5080
- rubygems_version: 3.1.4
5081
- signing_key:
5098
+ rubygems_version: 3.1.6
5099
+ signing_key:
5082
5100
  specification_version: 4
5083
5101
  summary: Content and Subscription Management plugin for Foreman
5084
5102
  test_files: []