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.
- checksums.yaml +4 -4
- data/app/controllers/katello/api/registry/registry_proxies_controller.rb +4 -6
- data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +1 -1
- data/app/lib/actions/pulp3/content_guard/refresh_all_distributions.rb +2 -1
- data/app/lib/actions/pulp3/content_migration_presenter.rb +5 -2
- data/app/lib/katello/errors.rb +1 -1
- data/app/lib/katello/util/hostgroup_facets_helper.rb +126 -0
- data/app/models/katello/concerns/hostgroup_extensions.rb +4 -2
- data/app/models/katello/concerns/redhat_extensions.rb +9 -8
- data/app/models/katello/ping.rb +1 -1
- data/app/services/katello/applicability/applicable_content_helper.rb +8 -6
- data/app/services/katello/pulp/repository.rb +4 -2
- data/app/services/katello/pulp3/api/core.rb +14 -0
- data/app/services/katello/pulp3/migration.rb +39 -13
- data/app/services/katello/pulp3/migration_plan.rb +52 -3
- data/app/services/katello/pulp3/migration_switchover.rb +13 -0
- data/app/services/katello/pulp3/repository/apt.rb +1 -2
- data/app/services/katello/pulp3/repository.rb +34 -9
- data/app/services/katello/pulp3/task.rb +8 -5
- data/app/services/katello/pulp3/task_group.rb +13 -5
- data/db/migrate/20200514092553_move_katello_fields_from_hostgroups.katello.rb +1 -1
- data/db/migrate/20210420140050_add_pulp3_hrefs_to_content_types_deb.rb +5 -0
- data/lib/katello/engine.rb +1 -1
- data/lib/katello/tasks/check_config.rake +11 -0
- data/lib/katello/tasks/fix_hostgroup_facets.rake +8 -0
- data/lib/katello/tasks/pulp3_content_switchover.rake +30 -21
- data/lib/katello/tasks/pulp3_migration.rake +43 -34
- data/lib/katello/tasks/pulp3_migration_abort.rake +8 -0
- data/lib/katello/tasks/pulp3_migration_approve_corrupted.rake +7 -2
- data/lib/katello/tasks/pulp3_migration_stats.rake +12 -2
- data/lib/katello/tasks/reimport.rake +1 -1
- data/lib/katello/version.rb +1 -1
- metadata +38 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 625ecabd197fcf1e9562afe5ab95076a78aad73960543c9804d0510f36bfc398
|
4
|
+
data.tar.gz: 0a6c82ff085f980e9d028a9734f3d071fa5324e6354b0c45b49406bf4400783c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
#
|
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
|
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
|
-
|
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
|
-
|
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
|
data/app/lib/katello/errors.rb
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
48
|
-
|
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
|
-
|
70
|
-
|
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).
|
data/app/models/katello/ping.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
126
|
-
|
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
|
-
|
129
|
-
|
129
|
+
to_remove = consumer_ids - content_ids
|
130
|
+
to_add = content_ids - consumer_ids
|
130
131
|
|
131
|
-
|
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.
|
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:
|
303
|
-
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,
|
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
|
-
|
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
|
-
|
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.
|
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.
|
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.
|
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
|
-
|
304
|
-
|
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
|
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
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
|
225
|
-
|
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
|
-
|
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
|
-
|
60
|
-
|
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
|
-
|
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
|
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 =
|
81
|
-
tasks_response =
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
data/lib/katello/engine.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
5
|
-
|
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
|
-
|
8
|
-
|
13
|
+
puts "Starting task."
|
14
|
+
SmartProxy.pulp_primary.refresh
|
9
15
|
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
34
|
+
sleep(10)
|
35
|
+
task = ForemanTasks::Task.find(task.id)
|
36
|
+
end
|
29
37
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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"
|
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"
|
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).
|
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
|
-
|
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"
|
data/lib/katello/version.rb
CHANGED
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.
|
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-
|
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.
|
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.
|
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.
|
363
|
+
version: 2.9.0
|
350
364
|
- - "<"
|
351
365
|
- !ruby/object:Gem::Version
|
352
|
-
version: 2.
|
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.
|
373
|
+
version: 2.9.0
|
360
374
|
- - "<"
|
361
375
|
- !ruby/object:Gem::Version
|
362
|
-
version: 2.
|
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.
|
383
|
+
version: 3.10.0
|
370
384
|
- - "<"
|
371
385
|
- !ruby/object:Gem::Version
|
372
|
-
version: 3.
|
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.
|
393
|
+
version: 3.10.0
|
380
394
|
- - "<"
|
381
395
|
- !ruby/object:Gem::Version
|
382
|
-
version: 3.
|
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.
|
403
|
+
version: 0.8.0
|
390
404
|
- - "<"
|
391
405
|
- !ruby/object:Gem::Version
|
392
|
-
version: 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.
|
413
|
+
version: 0.8.0
|
400
414
|
- - "<"
|
401
415
|
- !ruby/object:Gem::Version
|
402
|
-
version: 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.
|
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: []
|