katello 3.18.0.rc2.1 → 3.18.2.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of katello might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/katello/katello.scss +0 -72
- data/app/controllers/katello/api/v2/api_controller.rb +1 -2
- data/app/controllers/katello/api/v2/capsule_content_controller.rb +2 -2
- data/app/controllers/katello/api/v2/content_export_incrementals_controller.rb +98 -0
- data/app/controllers/katello/api/v2/content_exports_controller.rb +84 -0
- data/app/controllers/katello/api/v2/content_imports_controller.rb +59 -0
- data/app/controllers/katello/api/v2/content_view_filters_controller.rb +1 -1
- data/app/controllers/katello/api/v2/content_view_versions_controller.rb +56 -94
- data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +2 -1
- data/app/controllers/katello/api/v2/repositories_controller.rb +2 -0
- data/app/controllers/katello/concerns/api/v2/authorization.rb +14 -1
- data/app/lib/actions/katello/applicability/hosts/bulk_generate.rb +6 -2
- data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
- data/app/lib/actions/katello/capsule_content/sync_capsule.rb +7 -2
- data/app/lib/actions/katello/content_view/promote_to_environment.rb +1 -1
- data/app/lib/actions/katello/content_view/publish.rb +1 -1
- data/app/lib/actions/katello/content_view_version/import.rb +2 -1
- data/app/lib/actions/katello/content_view_version/import_library.rb +17 -0
- data/app/lib/actions/katello/content_view_version/incremental_update.rb +19 -3
- data/app/lib/actions/katello/host/update_system_purpose.rb +1 -1
- data/app/lib/actions/katello/repository/sync.rb +5 -1
- data/app/lib/actions/middleware/record_smart_proxy_sync_history.rb +24 -4
- data/app/lib/actions/pulp3/content_migration.rb +10 -0
- data/app/lib/actions/pulp3/content_migration_presenter.rb +59 -0
- data/app/lib/actions/pulp3/content_migration_reset.rb +22 -0
- data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +1 -1
- data/app/lib/actions/pulp3/content_view_version/export.rb +3 -2
- data/app/lib/actions/pulp3/import_migration.rb +6 -1
- data/app/lib/actions/pulp3/orchestration/content_view_version/copy_version_units_to_library.rb +2 -1
- data/app/lib/actions/pulp3/orchestration/content_view_version/export.rb +17 -13
- data/app/lib/actions/pulp3/orchestration/content_view_version/export_library.rb +60 -0
- data/app/lib/actions/pulp3/orchestration/content_view_version/import.rb +0 -4
- data/app/lib/actions/pulp3/orchestration/repository/import_upload.rb +16 -3
- data/app/lib/actions/pulp3/repository/copy_content.rb +1 -1
- data/app/lib/actions/pulp3/repository/delete.rb +1 -1
- data/app/lib/actions/pulp3/repository/save_version.rb +1 -1
- data/app/lib/actions/pulp3/repository/upload_tag.rb +18 -0
- data/app/lib/katello/util/pulpcore_content_filters.rb +1 -1
- data/app/models/katello/authorization/content_view_version.rb +25 -2
- data/app/models/katello/authorization/content_view_version_export_history.rb +1 -1
- data/app/models/katello/authorization/organization.rb +8 -0
- data/app/models/katello/concerns/operatingsystem_extensions.rb +2 -0
- data/app/models/katello/concerns/pulp_database_unit.rb +19 -0
- data/app/models/katello/concerns/redhat_extensions.rb +2 -2
- data/app/models/katello/concerns/smart_proxy_extensions.rb +7 -5
- data/app/models/katello/content_migration_progress.rb +4 -0
- data/app/models/katello/content_view.rb +5 -0
- data/app/models/katello/content_view_history.rb +2 -1
- data/app/models/katello/content_view_package_filter.rb +1 -1
- data/app/models/katello/content_view_version_export_history.rb +6 -1
- data/app/models/katello/file_unit.rb +4 -0
- data/app/models/katello/host/content_facet.rb +9 -31
- data/app/models/katello/host/subscription_facet.rb +4 -0
- data/app/models/katello/ping.rb +35 -15
- data/app/models/katello/repository.rb +7 -0
- data/app/models/katello/subscription_status.rb +3 -2
- data/app/services/katello/applicability/applicable_content_helper.rb +44 -15
- data/app/services/katello/pulp3/api/docker.rb +4 -0
- data/app/services/katello/pulp3/content_view_version/export.rb +63 -5
- data/app/services/katello/pulp3/content_view_version/import.rb +40 -0
- data/app/services/katello/pulp3/content_view_version/import_export_common.rb +0 -16
- data/app/services/katello/pulp3/content_view_version/import_validator.rb +26 -49
- data/app/services/katello/pulp3/docker_manifest.rb +1 -0
- data/app/services/katello/pulp3/docker_tag.rb +1 -0
- data/app/services/katello/pulp3/erratum.rb +2 -1
- data/app/services/katello/pulp3/migration.rb +95 -12
- data/app/services/katello/pulp3/migration_plan.rb +2 -2
- data/app/services/katello/pulp3/migration_switchover.rb +23 -5
- data/app/services/katello/pulp3/repository.rb +10 -5
- data/app/services/katello/pulp3/repository/docker.rb +5 -0
- data/app/services/katello/pulp3/repository/yum.rb +23 -8
- data/app/services/katello/pulp3/rpm.rb +5 -1
- data/app/services/katello/pulp3/task.rb +4 -0
- data/app/services/katello/pulp3/task_group.rb +4 -0
- data/app/views/katello/api/v2/content_views/show.json.rabl +6 -0
- data/app/views/katello/layouts/react.html.erb +3 -2
- data/app/views/katello/sync_management/_products.html.erb +1 -1
- data/app/views/overrides/activation_keys/_host_tab_pane.html.erb +1 -5
- data/config/routes/api/v2.rb +23 -3
- data/db/migrate/20150930183738_migrate_content_hosts.rb +1 -1
- data/db/migrate/20200514092553_move_katello_fields_from_hostgroups.katello.rb +5 -2
- data/db/migrate/20201119211133_pulp3_migration_progress.rb +9 -0
- data/db/migrate/20210201165835_add_migration_missing_content.rb +12 -0
- data/engines/bastion/app/assets/javascripts/bastion/auth/authorization.service.js +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/common/views/katello-agent-notice.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-system-purpose-modal.html +35 -40
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/register-client.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/deletion/content-view-version-deletion-activation-keys.controller.js +8 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/deletion/content-view-version-deletion-content-hosts.controller.js +9 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-details.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-publish.html +4 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +78 -7
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de.po +17 -20
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/es.po +17 -24
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +1292 -1170
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/it.po +17 -20
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ja.po +858 -807
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ko.po +18 -19
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt_BR.po +17 -24
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ru.po +17 -18
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_CN.po +986 -971
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_TW.po +19 -20
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/translations.js +9 -9
- data/lib/katello/permission_creator.rb +23 -3
- data/lib/katello/tasks/delete_orphaned_content.rake +1 -3
- data/lib/katello/tasks/pulp3_content_switchover.rake +3 -1
- data/lib/katello/tasks/pulp3_migration.rake +29 -6
- data/lib/katello/tasks/pulp3_migration_abort.rake +7 -2
- data/lib/katello/tasks/pulp3_migration_approve_corrupted.rake +16 -0
- data/lib/katello/tasks/pulp3_migration_reset.rake +26 -0
- data/lib/katello/tasks/pulp3_migration_stats.rake +61 -8
- data/lib/katello/tasks/pulp3_post_migration_check.rake +1 -3
- data/lib/katello/tasks/receptor/extract_orgs.rake +1 -1
- data/lib/katello/tasks/reports.rake +4 -1
- data/lib/katello/tasks/repository.rake +3 -5
- data/lib/katello/version.rb +1 -1
- data/locale/action_names.rb +51 -51
- data/locale/bn/katello.po +136 -51
- data/locale/cs/katello.po +136 -49
- data/locale/de/katello.po +136 -48
- data/locale/en/katello.po +136 -48
- data/locale/es/katello.po +136 -48
- data/locale/fr/katello.po +136 -48
- data/locale/gu/katello.po +136 -51
- data/locale/hi/katello.po +136 -51
- data/locale/it/katello.po +136 -48
- data/locale/ja/katello.po +136 -48
- data/locale/katello.pot +941 -767
- data/locale/kn/katello.po +136 -51
- data/locale/ko/katello.po +136 -48
- data/locale/mr/katello.po +136 -51
- data/locale/or/katello.po +136 -51
- data/locale/pa/katello.po +136 -51
- data/locale/pt/katello.po +136 -51
- data/locale/pt_BR/katello.po +136 -48
- data/locale/ru/katello.po +136 -48
- data/locale/ta/katello.po +136 -51
- data/locale/te/katello.po +136 -51
- data/locale/zh_CN/katello.po +136 -48
- data/locale/zh_TW/katello.po +136 -48
- data/webpack/components/TypeAhead/TypeAhead.js +2 -1
- data/webpack/components/TypeAhead/pf3Search/TypeAheadSearch.js +2 -1
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +7 -2
- data/webpack/scenes/Subscriptions/Manifest/index.js +1 -0
- metadata +31 -19
- data/lib/katello/tasks/common.rake +0 -7
@@ -282,6 +282,10 @@ module Katello
|
|
282
282
|
name.gsub('_', '-').chomp('.').downcase
|
283
283
|
end
|
284
284
|
|
285
|
+
def unsubscribed_hypervisor?
|
286
|
+
self.hypervisor && !self.candlepin_consumer.entitlements?
|
287
|
+
end
|
288
|
+
|
285
289
|
def candlepin_consumer
|
286
290
|
@candlepin_consumer ||= Katello::Candlepin::Consumer.new(self.uuid, self.host.organization.label)
|
287
291
|
end
|
data/app/models/katello/ping.rb
CHANGED
@@ -23,25 +23,18 @@ module Katello
|
|
23
23
|
services
|
24
24
|
end
|
25
25
|
|
26
|
-
# Calls "status" services in all backend engines.
|
27
26
|
def ping(services: nil, capsule_id: nil)
|
28
|
-
services
|
29
|
-
|
30
|
-
services.each { |service| result[service] = {} }
|
27
|
+
ping_services_for_capsule(services, capsule_id)
|
28
|
+
end
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
ping_candlepin_without_auth(result[:candlepin]) if result.include?(:candlepin)
|
30
|
+
def ping!(services: nil, capsule_id: nil)
|
31
|
+
result = ping_services_for_capsule(services, capsule_id)
|
35
32
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
ping_candlepin_events(result[:candlepin_events]) if result.include?(:candlepin_events)
|
33
|
+
if result[:status] != OK_RETURN_CODE
|
34
|
+
failed_names = failed_services(result).keys
|
35
|
+
fail("The following services have not been started or are reporting errors: #{failed_names.join(', ')}")
|
36
|
+
end
|
41
37
|
|
42
|
-
# set overall status result code
|
43
|
-
result = {:services => result}
|
44
|
-
result[:status] = result[:services].each_value.any? { |v| v[:status] == FAIL_RETURN_CODE } ? FAIL_RETURN_CODE : OK_RETURN_CODE
|
45
38
|
result
|
46
39
|
end
|
47
40
|
|
@@ -221,6 +214,33 @@ module Katello
|
|
221
214
|
|
222
215
|
private
|
223
216
|
|
217
|
+
def failed_services(result)
|
218
|
+
result[:services].reject do |_name, details|
|
219
|
+
details[:status] != OK_RETURN_CODE
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def ping_services_for_capsule(services, capsule_id)
|
224
|
+
services ||= self.services(capsule_id)
|
225
|
+
result = {}
|
226
|
+
services.each { |service| result[service] = {} }
|
227
|
+
|
228
|
+
ping_pulp3_without_auth(result[:pulp3], capsule_id) if result.include?(:pulp3)
|
229
|
+
ping_pulp_without_auth(result[:pulp], capsule_id) if result.include?(:pulp)
|
230
|
+
ping_candlepin_without_auth(result[:candlepin]) if result.include?(:candlepin)
|
231
|
+
|
232
|
+
ping_pulp_with_auth(result[:pulp_auth], result[:pulp][:status]) if result.include?(:pulp_auth)
|
233
|
+
ping_candlepin_with_auth(result[:candlepin_auth]) if result.include?(:candlepin_auth)
|
234
|
+
ping_foreman_tasks(result[:foreman_tasks]) if result.include?(:foreman_tasks)
|
235
|
+
ping_katello_events(result[:katello_events]) if result.include?(:katello_events)
|
236
|
+
ping_candlepin_events(result[:candlepin_events]) if result.include?(:candlepin_events)
|
237
|
+
|
238
|
+
# set overall status result code
|
239
|
+
result = {:services => result}
|
240
|
+
result[:status] = result[:services].each_value.any? { |v| v[:status] == FAIL_RETURN_CODE } ? FAIL_RETURN_CODE : OK_RETURN_CODE
|
241
|
+
result
|
242
|
+
end
|
243
|
+
|
224
244
|
def fetch_proxy(capsule_id)
|
225
245
|
capsule_id ? SmartProxy.unscoped.find(capsule_id) : SmartProxy.pulp_primary
|
226
246
|
end
|
@@ -122,6 +122,8 @@ module Katello
|
|
122
122
|
|
123
123
|
scope :has_url, -> { joins(:root).where.not("#{RootRepository.table_name}.url" => nil) }
|
124
124
|
scope :on_demand, -> { joins(:root).where("#{RootRepository.table_name}.download_policy" => ::Runcible::Models::YumImporter::DOWNLOAD_ON_DEMAND) }
|
125
|
+
scope :immediate, -> { joins(:root).where("#{RootRepository.table_name}.download_policy" => ::Runcible::Models::YumImporter::DOWNLOAD_IMMEDIATE) }
|
126
|
+
scope :non_immediate, -> { joins(:root).where.not("#{RootRepository.table_name}.download_policy" => ::Runcible::Models::YumImporter::DOWNLOAD_IMMEDIATE) }
|
125
127
|
scope :in_default_view, -> { joins(:content_view_version => :content_view).where("#{Katello::ContentView.table_name}.default" => true) }
|
126
128
|
scope :in_non_default_view, -> { joins(:content_view_version => :content_view).where("#{Katello::ContentView.table_name}.default" => false) }
|
127
129
|
scope :deb_type, -> { with_type(DEB_TYPE) }
|
@@ -154,6 +156,7 @@ module Katello
|
|
154
156
|
scoped_search :on => :redhat, :complete_value => { :true => true, :false => false }, :ext_method => :search_by_redhat
|
155
157
|
scoped_search :on => :container_repository_name, :complete_value => true
|
156
158
|
scoped_search :on => :description, :relation => :root, :only_explicit => true
|
159
|
+
scoped_search :on => :download_policy, :relation => :root, :only_explicit => true
|
157
160
|
scoped_search :on => :name, :relation => :product, :rename => :product_name
|
158
161
|
scoped_search :on => :id, :relation => :product, :rename => :product_id, :only_explicit => true
|
159
162
|
scoped_search :on => :label, :relation => :root, :complete_value => true, :only_explicit => true
|
@@ -287,6 +290,10 @@ module Katello
|
|
287
290
|
root.download_policy == Runcible::Models::YumImporter::DOWNLOAD_ON_DEMAND
|
288
291
|
end
|
289
292
|
|
293
|
+
def immediate?
|
294
|
+
root.download_policy == ::Runcible::Models::YumImporter::DOWNLOAD_IMMEDIATE
|
295
|
+
end
|
296
|
+
|
290
297
|
def yum_gpg_key_url
|
291
298
|
# if the repo has a gpg key return a url to access it
|
292
299
|
if self.root.gpg_key.try(:content).present?
|
@@ -43,9 +43,10 @@ module Katello
|
|
43
43
|
|
44
44
|
def to_status(options = {})
|
45
45
|
return UNKNOWN unless host.subscription_facet.try(:uuid)
|
46
|
-
|
46
|
+
return DISABLED if host.organization.simple_content_access?
|
47
|
+
status_override = 'unsubscribed_hypervisor' if host.subscription_facet.unsubscribed_hypervisor?
|
47
48
|
status_override ||= options.fetch(:status_override, nil)
|
48
|
-
status = status_override ||
|
49
|
+
status = status_override || host.subscription_facet.candlepin_consumer.entitlement_status
|
49
50
|
|
50
51
|
case status
|
51
52
|
when Katello::Candlepin::Consumer::ENTITLEMENTS_DISABLED
|
@@ -60,17 +60,7 @@ module Katello
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def fetch_rpm_content_ids
|
63
|
-
|
64
|
-
# -> Include all non-modular rpms or rpms that exist within installed module streams
|
65
|
-
enabled_module_stream_ids = ::Katello::ModuleStream.
|
66
|
-
joins("inner join katello_available_module_streams on
|
67
|
-
katello_module_streams.name = katello_available_module_streams.name and
|
68
|
-
katello_module_streams.stream = katello_available_module_streams.stream").
|
69
|
-
joins("inner join katello_host_available_module_streams on
|
70
|
-
katello_available_module_streams.id = katello_host_available_module_streams.available_module_stream_id").
|
71
|
-
where("katello_host_available_module_streams.host_id = :content_facet_id and
|
72
|
-
katello_host_available_module_streams.status = 'enabled'",
|
73
|
-
:content_facet_id => self.content_facet.host.id).select(:id)
|
63
|
+
enabled_module_stream_ids = fetch_enabled_module_stream_ids
|
74
64
|
|
75
65
|
::Katello::Rpm.
|
76
66
|
joins("INNER JOIN katello_repository_rpms ON
|
@@ -78,7 +68,8 @@ module Katello
|
|
78
68
|
joins("INNER JOIN katello_installed_packages ON
|
79
69
|
katello_rpms.name = katello_installed_packages.name AND
|
80
70
|
katello_rpms.arch = katello_installed_packages.arch AND
|
81
|
-
katello_rpms.evr > katello_installed_packages.evr
|
71
|
+
katello_rpms.evr > katello_installed_packages.evr AND
|
72
|
+
katello_installed_packages.id in (#{newest_distinct_installed_packages_query})").
|
82
73
|
joins("LEFT JOIN katello_module_stream_rpms ON
|
83
74
|
katello_rpms.id = katello_module_stream_rpms.rpm_id").
|
84
75
|
joins("INNER JOIN katello_host_installed_packages ON
|
@@ -87,9 +78,47 @@ module Katello
|
|
87
78
|
:bound_library_repos => self.bound_library_instance_repos).
|
88
79
|
where("katello_host_installed_packages.host_id = :content_facet_id",
|
89
80
|
:content_facet_id => self.content_facet.host.id).
|
90
|
-
where("katello_module_stream_rpms.module_stream_id
|
91
|
-
|
92
|
-
|
81
|
+
where("(katello_module_stream_rpms.module_stream_id IS NULL AND
|
82
|
+
katello_installed_packages.id NOT IN (:locked_modular_installed_packages)) OR
|
83
|
+
(katello_module_stream_rpms.module_stream_id IN (:enabled_module_streams)
|
84
|
+
AND katello_installed_packages.id IN (:locked_modular_installed_packages))",
|
85
|
+
:enabled_module_streams => enabled_module_stream_ids,
|
86
|
+
:locked_modular_installed_packages => locked_modular_installed_packages(enabled_module_stream_ids)).pluck(:id).uniq
|
87
|
+
end
|
88
|
+
|
89
|
+
def fetch_enabled_module_stream_ids
|
90
|
+
# Query for applicable RPM ids
|
91
|
+
# -> Include all non-modular rpms or rpms that exist within installed module streams
|
92
|
+
::Katello::ModuleStream.
|
93
|
+
joins("inner join katello_available_module_streams on
|
94
|
+
katello_module_streams.name = katello_available_module_streams.name and
|
95
|
+
katello_module_streams.stream = katello_available_module_streams.stream").
|
96
|
+
joins("inner join katello_host_available_module_streams on
|
97
|
+
katello_available_module_streams.id = katello_host_available_module_streams.available_module_stream_id").
|
98
|
+
where("katello_host_available_module_streams.host_id = :content_facet_id and
|
99
|
+
katello_host_available_module_streams.status = 'enabled'",
|
100
|
+
:content_facet_id => self.content_facet.host.id).select(:id)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Installed packages that are locked for the host due to enabled module stream membership
|
104
|
+
def locked_modular_installed_packages(enabled_module_streams)
|
105
|
+
rpms_in_enabled_module_streams = ::Katello::Rpm.
|
106
|
+
joins("INNER JOIN katello_module_stream_rpms ON katello_rpms.id = katello_module_stream_rpms.rpm_id").
|
107
|
+
where("katello_module_stream_rpms.module_stream_id IN (:enabled_module_streams)",
|
108
|
+
:enabled_module_streams => enabled_module_streams).select(:nvra, :epoch)
|
109
|
+
|
110
|
+
::Katello::InstalledPackage.where(nvra: rpms_in_enabled_module_streams.map(&:nvra),
|
111
|
+
epoch: rpms_in_enabled_module_streams.map(&:epoch)).select(:id)
|
112
|
+
end
|
113
|
+
|
114
|
+
def newest_distinct_installed_packages_query
|
115
|
+
"SELECT DISTINCT ON (katello_installed_packages.name) katello_installed_packages.id " \
|
116
|
+
"FROM katello_installed_packages INNER JOIN " \
|
117
|
+
"katello_host_installed_packages ON " \
|
118
|
+
"katello_installed_packages.id = " \
|
119
|
+
"katello_host_installed_packages.installed_package_id " \
|
120
|
+
"WHERE katello_host_installed_packages.host_id = " \
|
121
|
+
"#{content_facet.host.id} ORDER BY katello_installed_packages.name, katello_installed_packages.evr DESC"
|
93
122
|
end
|
94
123
|
|
95
124
|
def applicable_differences
|
@@ -32,6 +32,10 @@ module Katello
|
|
32
32
|
PulpContainerClient::RecursiveManage
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.tag_image_class
|
36
|
+
PulpContainerClient::TagImage
|
37
|
+
end
|
38
|
+
|
35
39
|
def api_client
|
36
40
|
PulpContainerClient::ApiClient.new(smart_proxy.pulp3_configuration(PulpContainerClient::Configuration))
|
37
41
|
end
|
@@ -4,13 +4,37 @@ module Katello
|
|
4
4
|
class Export
|
5
5
|
include ImportExportCommon
|
6
6
|
|
7
|
-
def initialize(smart_proxy:,
|
7
|
+
def initialize(smart_proxy:,
|
8
|
+
content_view_version: nil,
|
9
|
+
destination_server: nil,
|
10
|
+
from_content_view_version: nil)
|
8
11
|
@smart_proxy = smart_proxy
|
9
12
|
@content_view_version = content_view_version
|
10
13
|
@destination_server = destination_server
|
11
14
|
@from_content_view_version = from_content_view_version
|
12
15
|
end
|
13
16
|
|
17
|
+
def repository_hrefs
|
18
|
+
version_hrefs.map { |href| version_href_to_repository_href(href) }.uniq
|
19
|
+
end
|
20
|
+
|
21
|
+
def version_hrefs
|
22
|
+
repositories.pluck(:version_href).compact
|
23
|
+
end
|
24
|
+
|
25
|
+
def repositories(fetch_all: false)
|
26
|
+
repos = if @content_view_version.default?
|
27
|
+
@content_view_version.repositories.yum_type
|
28
|
+
else
|
29
|
+
@content_view_version.archived_repos.yum_type
|
30
|
+
end
|
31
|
+
if fetch_all
|
32
|
+
repos
|
33
|
+
else
|
34
|
+
repos.immediate
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
14
38
|
def generate_exporter_path
|
15
39
|
export_path = "#{@content_view_version.content_view}/#{@content_view_version.version}/#{@destination_server}/#{date_dir}".gsub(/\s/, '_')
|
16
40
|
"#{@content_view_version.organization.label}/#{export_path}"
|
@@ -66,12 +90,29 @@ module Katello
|
|
66
90
|
api.exporter_api.delete(exporter_href)
|
67
91
|
end
|
68
92
|
|
93
|
+
def validate!(fail_on_missing_content: true, validate_incremental: true)
|
94
|
+
validate_repositories_immediate! if fail_on_missing_content
|
95
|
+
validate_incremental_export! if validate_incremental && !@from_content_view_version.blank?
|
96
|
+
end
|
97
|
+
|
98
|
+
def validate_repositories_immediate!
|
99
|
+
non_immediate_repos = repositories(fetch_all: true).non_immediate
|
100
|
+
if non_immediate_repos.any?
|
101
|
+
fail _("NOTE: Unable to fully export Content View Version '%{content_view} %{current}'"\
|
102
|
+
" it contains repositories without the 'immediate' download policy."\
|
103
|
+
" Update the download policy and sync affected repositories. Once synced republish the content view"\
|
104
|
+
" and export the generated version. \n %{repos}" %
|
105
|
+
{ content_view: @content_view_version.content_view.name,
|
106
|
+
current: @content_view_version.version,
|
107
|
+
repos: self.class.generate_product_repo_strings(repositories: non_immediate_repos)})
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
69
111
|
def validate_incremental_export!
|
70
|
-
return if @from_content_view_version.blank?
|
71
112
|
from_exporter = Export.new(smart_proxy: @smart_proxy, content_view_version: @from_content_view_version)
|
72
113
|
|
73
|
-
from_exporter_repos = generate_repo_mapping(from_exporter.repositories)
|
74
|
-
to_exporter_repos = generate_repo_mapping(repositories)
|
114
|
+
from_exporter_repos = generate_repo_mapping(from_exporter.repositories(fetch_all: true))
|
115
|
+
to_exporter_repos = generate_repo_mapping(repositories(fetch_all: true))
|
75
116
|
|
76
117
|
invalid_repos_exist = (from_exporter_repos.keys & to_exporter_repos.keys).any? do |repo_id|
|
77
118
|
from_exporter_repos[repo_id] != to_exporter_repos[repo_id]
|
@@ -99,7 +140,8 @@ module Katello
|
|
99
140
|
ret = { organization: @content_view_version.organization.name,
|
100
141
|
repository_mapping: {},
|
101
142
|
content_view: @content_view_version.content_view.name,
|
102
|
-
content_view_version: @content_view_version.slice(:major, :minor)
|
143
|
+
content_view_version: @content_view_version.slice(:major, :minor),
|
144
|
+
incremental: @from_content_view_version.present?
|
103
145
|
}
|
104
146
|
|
105
147
|
unless @from_content_view_version.blank?
|
@@ -120,6 +162,22 @@ module Katello
|
|
120
162
|
end
|
121
163
|
ret
|
122
164
|
end
|
165
|
+
|
166
|
+
def self.find_library_export_view(create_by_default: false,
|
167
|
+
destination_server:,
|
168
|
+
organization:)
|
169
|
+
name = "Export-Library"
|
170
|
+
name += "-#{destination_server}" unless destination_server.blank?
|
171
|
+
select_method = create_by_default ? :first_or_create : :first
|
172
|
+
::Katello::ContentView.where(name: name, organization: organization).send(select_method)
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.generate_product_repo_strings(repositories:)
|
176
|
+
repositories.map do |repo|
|
177
|
+
_("Product: '%{product}', Repository: '%{repository}'" % { product: repo.product.name,
|
178
|
+
repository: repo.name})
|
179
|
+
end
|
180
|
+
end
|
123
181
|
end
|
124
182
|
end
|
125
183
|
end
|
@@ -46,6 +46,46 @@ module Katello
|
|
46
46
|
def self.check!(content_view:, metadata:, path:)
|
47
47
|
ImportValidator.new(content_view: content_view, metadata: metadata, path: path).check!
|
48
48
|
end
|
49
|
+
|
50
|
+
def self.reset_content_view_repositories_from_metadata!(content_view:, metadata:)
|
51
|
+
# Given metadata from the dump and a content view
|
52
|
+
# this method
|
53
|
+
# 1) Fetches ids of the library repos whose product name, repo name amd redhat?
|
54
|
+
# => match values provided in the metadata's repository mapping
|
55
|
+
# 2) Removes all the repositories associated to this content view
|
56
|
+
# 3) Adds the repositories matched from the dump
|
57
|
+
# The main intent of this method is to assume that the user intends for the
|
58
|
+
# content view to exaclty look like what is specified in metadata
|
59
|
+
|
60
|
+
repos_in_library = Katello::Repository.
|
61
|
+
in_default_view.
|
62
|
+
yum_type.
|
63
|
+
joins(:product => :provider, :content_view_version => :content_view).
|
64
|
+
joins(:root).
|
65
|
+
where("#{::Katello::ContentView.table_name}.organization_id" => content_view.organization_id).
|
66
|
+
pluck("#{::Katello::Repository.table_name}.id",
|
67
|
+
"#{::Katello::RootRepository.table_name}.name",
|
68
|
+
"#{::Katello::Product.table_name}.name",
|
69
|
+
"#{::Katello::Provider.table_name}.provider_type"
|
70
|
+
)
|
71
|
+
repos_in_library_map = {}
|
72
|
+
# repos_in_library_map is going to look like {['repo1', 'product1', false] => 100, ['repo1', 'product1', true] => 200 }
|
73
|
+
repos_in_library.each do |id, repo, product, provider_type|
|
74
|
+
repos_in_library_map[[repo, product, provider_type == Katello::Provider::REDHAT]] = id
|
75
|
+
end
|
76
|
+
|
77
|
+
repo_ids = metadata[:repository_mapping].values.map do |repo|
|
78
|
+
repos_in_library_map[[repo[:repository], repo[:product], repo[:redhat]]]
|
79
|
+
end
|
80
|
+
content_view.update!(repository_ids: repo_ids)
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.find_or_create_library_import_view(organization)
|
84
|
+
name = ::Katello::ContentView::IMPORT_LIBRARY
|
85
|
+
::Katello::ContentView.where(name: name,
|
86
|
+
organization: organization,
|
87
|
+
import_only: true).first_or_create
|
88
|
+
end
|
49
89
|
end
|
50
90
|
end
|
51
91
|
end
|
@@ -19,22 +19,6 @@ module Katello
|
|
19
19
|
repo_api.read(version_href_to_repository_href(version_href))
|
20
20
|
end
|
21
21
|
|
22
|
-
def repository_hrefs
|
23
|
-
version_hrefs.map { |href| version_href_to_repository_href(href) }.uniq
|
24
|
-
end
|
25
|
-
|
26
|
-
def version_hrefs
|
27
|
-
repositories.pluck(:version_href).compact
|
28
|
-
end
|
29
|
-
|
30
|
-
def repositories
|
31
|
-
if @content_view_version.default?
|
32
|
-
@content_view_version.repositories.yum_type
|
33
|
-
else
|
34
|
-
@content_view_version.archived_repos.yum_type
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
22
|
def version_href_to_repository_href(version_href)
|
39
23
|
version_href.split("/")[0..-3].join("/") + "/"
|
40
24
|
end
|
@@ -2,7 +2,6 @@ module Katello
|
|
2
2
|
module Pulp3
|
3
3
|
module ContentViewVersion
|
4
4
|
class ImportValidator
|
5
|
-
BASEDIR = '/var/lib/pulp'.freeze
|
6
5
|
attr_accessor :metadata, :path, :content_view
|
7
6
|
def initialize(content_view:, path:, metadata:)
|
8
7
|
self.content_view = content_view
|
@@ -11,10 +10,11 @@ module Katello
|
|
11
10
|
end
|
12
11
|
|
13
12
|
def check!
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
unless content_view.default?
|
14
|
+
ensure_importing_cvv_does_not_exist!
|
15
|
+
ensure_from_cvv_exists!
|
16
|
+
end
|
17
|
+
ensure_repositories_metadata_are_in_the_library!
|
18
18
|
end
|
19
19
|
|
20
20
|
def ensure_importing_cvv_does_not_exist!
|
@@ -43,55 +43,32 @@ module Katello
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
47
|
-
|
46
|
+
def ensure_repositories_metadata_are_in_the_library!
|
47
|
+
repos_in_library = Katello::Repository.
|
48
|
+
in_default_view.
|
49
|
+
yum_type.
|
50
|
+
joins(:product => :provider, :content_view_version => :content_view).
|
51
|
+
joins(:root).
|
52
|
+
where("#{::Katello::ContentView.table_name}.organization_id" => content_view.organization_id).
|
53
|
+
pluck("#{::Katello::Product.table_name}.name",
|
54
|
+
"#{::Katello::RootRepository.table_name}.name",
|
55
|
+
"#{::Katello::Provider.table_name}.provider_type"
|
56
|
+
)
|
57
|
+
|
58
|
+
# repos_in_library look like [["prod1", "repo1", "Anonymous"], ["prod2", "repo2", "Red Hat"]]
|
59
|
+
product_repos_in_library = repos_in_library.map { |product, repo, provider| [product, repo, provider == ::Katello::Provider::REDHAT] }
|
48
60
|
product_repos_in_metadata = metadata[:repository_mapping].values.map { |repo| [repo[:product], repo[:repository], repo[:redhat]] }
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
repos_in_import = generate_product_repo_i18n_string(product_repos_in_metadata)
|
57
|
-
|
58
|
-
fail _("Repositories in the importing content view do not match the repositories provided in the import metadata.\n "\
|
59
|
-
"Repositories in Content View '%{content_view}': %{repos_in_content_view}\n "\
|
60
|
-
"Repositories in the Import Metadata: %{repos_in_import}" % { content_view: content_view.name,
|
61
|
-
repos_in_content_view: repos_in_content_view.join(""),
|
62
|
-
repos_in_import: repos_in_import.join("")}
|
61
|
+
# product_repos_in_library & product_repos_in_metadata look like [["prod1", "repo1", false], ["prod2", "repo2", false]]
|
62
|
+
product_repos_not_in_library = product_repos_in_metadata - product_repos_in_library
|
63
|
+
unless product_repos_not_in_library.blank?
|
64
|
+
repos_in_import = generate_product_repo_i18n_string(product_repos_not_in_library)
|
65
|
+
fail _("The following repositories provided in the import metadata are either not available in the Library or are of incorrect Respository Type. "\
|
66
|
+
"Please add or enable the repositories before importing\n "\
|
67
|
+
"%{repos}" % { content_view: content_view.name, repos: repos_in_import.join("")}
|
63
68
|
)
|
64
69
|
end
|
65
70
|
end
|
66
71
|
|
67
|
-
def check_permissions!
|
68
|
-
fail _("Invalid path specified.") if path.blank? || !File.directory?(path)
|
69
|
-
fail _("The import path must be in a subdirectory under '%s'." % BASEDIR) unless path.starts_with?(BASEDIR)
|
70
|
-
fail _("Pulp user or group unable to read content in '%s'." % path) unless pulp_user_accessible?(path)
|
71
|
-
|
72
|
-
Dir.glob("#{path}/*").each do |file|
|
73
|
-
fail _("Pulp user or group unable to read '%s'." % file) unless pulp_user_accessible?(file)
|
74
|
-
end
|
75
|
-
toc_path = "#{path}/#{metadata[:toc]}"
|
76
|
-
fail _("The TOC file specified in the metadata does not exist. %s " % toc_path) unless File.exist?(toc_path)
|
77
|
-
end
|
78
|
-
|
79
|
-
def pulp_user_accessible?(path)
|
80
|
-
pulp_info = fetch_pulp_user_info
|
81
|
-
return false if pulp_info.blank?
|
82
|
-
|
83
|
-
stat = File.stat(path)
|
84
|
-
stat.gid.to_s == pulp_info.gid ||
|
85
|
-
stat.uid.to_s == pulp_info.uid ||
|
86
|
-
stat.mode.to_s(8)[-1].to_i >= 4
|
87
|
-
end
|
88
|
-
|
89
|
-
def fetch_pulp_user_info
|
90
|
-
pulp_user = nil
|
91
|
-
Etc.passwd { |u| pulp_user = u if u.name == 'pulp' }
|
92
|
-
pulp_user
|
93
|
-
end
|
94
|
-
|
95
72
|
def generate_product_repo_i18n_string(product_repos)
|
96
73
|
# product_repos look like [["prod1", "repo1", false], ["prod2", "repo2", false]]
|
97
74
|
product_repos.map do |product, repo, redhat|
|