katello 3.18.0.rc1 → 3.18.0.rc2
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/v2/content_view_filters_controller.rb +17 -8
- data/app/controllers/katello/api/v2/content_view_versions_controller.rb +5 -2
- data/app/controllers/katello/api/v2/content_views_controller.rb +10 -1
- data/app/controllers/katello/api/v2/host_debs_controller.rb +1 -0
- data/app/controllers/katello/api/v2/host_errata_controller.rb +2 -2
- data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +18 -6
- data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +1 -1
- data/app/controllers/katello/api/v2/products_controller.rb +9 -9
- data/app/controllers/katello/api/v2/repository_sets_controller.rb +24 -14
- data/app/controllers/katello/concerns/api/v2/authorization.rb +10 -0
- data/app/controllers/katello/concerns/api/v2/bulk_hosts_extensions.rb +22 -18
- data/app/controllers/katello/concerns/registration_controller_extensions.rb +16 -0
- data/app/lib/actions/helpers/smart_proxy_sync_history_helper.rb +24 -0
- data/app/lib/actions/katello/capsule_content/sync_capsule.rb +16 -7
- data/app/lib/actions/katello/content_view/publish.rb +5 -4
- data/app/lib/actions/katello/content_view_version/import.rb +3 -10
- data/app/lib/actions/katello/host/upload_package_profile.rb +3 -1
- data/app/lib/actions/katello/host/upload_profiles.rb +8 -6
- data/app/lib/actions/katello/repository/import_upload.rb +2 -0
- data/app/lib/actions/katello/repository/remove_content.rb +1 -1
- data/app/lib/actions/katello/repository/sync.rb +3 -1
- data/app/lib/actions/katello/repository/update.rb +1 -0
- data/app/lib/actions/katello/repository/upload_files.rb +1 -0
- data/app/lib/actions/middleware/record_smart_proxy_sync_history.rb +15 -0
- data/app/lib/actions/pulp/consumer/sync_capsule.rb +4 -2
- data/app/lib/actions/pulp/repository/distributor_publish.rb +1 -1
- data/app/lib/actions/pulp3/abstract_async_task.rb +1 -0
- data/app/lib/actions/pulp3/capsule_content/sync.rb +1 -0
- data/app/lib/actions/pulp3/content_view_version/export.rb +5 -1
- data/app/lib/actions/pulp3/orchestration/content_view_version/export.rb +23 -6
- data/app/lib/actions/pulp3/orchestration/repository/generate_metadata.rb +4 -1
- data/app/models/katello/authorization/content_view_filter.rb +15 -0
- data/app/models/katello/concerns/smart_proxy_extensions.rb +2 -0
- data/app/models/katello/content_view.rb +25 -4
- data/app/models/katello/content_view_filter.rb +5 -0
- data/app/models/katello/content_view_puppet_module.rb +8 -0
- data/app/models/katello/content_view_repository.rb +13 -1
- data/app/models/katello/ping.rb +8 -3
- data/app/models/katello/repository.rb +26 -0
- data/app/models/katello/smart_proxy_sync_history.rb +8 -0
- data/app/services/katello/pulp3/content_view_version/export.rb +64 -6
- data/app/services/katello/pulp3/content_view_version/import.rb +2 -27
- data/app/services/katello/pulp3/content_view_version/import_export_common.rb +6 -0
- data/app/services/katello/pulp3/content_view_version/import_validator.rb +107 -0
- data/app/services/katello/pulp3/migration.rb +7 -1
- data/app/services/katello/pulp3/repository/yum.rb +1 -2
- data/app/services/katello/pulp3/task.rb +3 -3
- data/app/services/katello/pulp3/task_group.rb +6 -0
- data/app/services/katello/repository_type.rb +2 -1
- data/app/services/katello/smart_proxy_helper.rb +9 -0
- data/app/views/foreman/hosts/_registration.html.erb +12 -0
- data/app/views/katello/api/v2/content_views/base.json.rabl +1 -0
- data/db/migrate/20200929200357_create_katello_smart_proxy_sync_history.rb +13 -0
- data/db/migrate/20201021150008_add_import_only_to_katello_content_view.rb +5 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/content-views.controller.js +6 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-details.controller.js +12 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-details.html +7 -7
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-info.html +7 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/new/content-view-new.controller.js +17 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/new/views/content-view-new.html +16 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/views/content-views.html +5 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository-types.service.js +8 -1
- data/lib/katello/engine.rb +1 -0
- data/lib/katello/permission_creator.rb +11 -11
- data/lib/katello/plugin.rb +6 -1
- data/lib/katello/tasks/pulp3_migration_abort.rake +17 -0
- data/lib/katello/version.rb +1 -1
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +13 -11
- data/webpack/test-utils/react-testing-lib-wrapper.js +3 -0
- metadata +12 -3
- data/webpack/__mocks__/foremanReact/components/common/Fill/GlobalFill.js +0 -3
@@ -1,5 +1,6 @@
|
|
1
1
|
module Katello
|
2
2
|
class ContentViewFilter < Katello::Model
|
3
|
+
include Authorization::ContentViewFilter
|
3
4
|
audited :associations => [:repositories]
|
4
5
|
DOCKER = 'docker'.freeze
|
5
6
|
RPM = Rpm::CONTENT_TYPE
|
@@ -157,6 +158,10 @@ module Katello
|
|
157
158
|
if self.content_view.composite?
|
158
159
|
errors.add(:base, _("cannot contain filters if composite view"))
|
159
160
|
end
|
161
|
+
|
162
|
+
if self.content_view.import_only?
|
163
|
+
errors.add(:base, _("cannot add filter to import-only view"))
|
164
|
+
end
|
160
165
|
end
|
161
166
|
|
162
167
|
def validate_filter_repos(errors, content_view)
|
@@ -17,6 +17,8 @@ module Katello
|
|
17
17
|
|
18
18
|
before_validation :set_attributes
|
19
19
|
|
20
|
+
validate :import_only_content_view
|
21
|
+
|
20
22
|
def puppet_module
|
21
23
|
PuppetModule.find_by(:pulp_id => self.uuid)
|
22
24
|
end
|
@@ -42,6 +44,12 @@ module Katello
|
|
42
44
|
|
43
45
|
private
|
44
46
|
|
47
|
+
def import_only_content_view
|
48
|
+
if self.content_view.import_only?
|
49
|
+
errors.add(:base, "Cannot add puppet modules to an import-only content view.")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
45
53
|
def set_attributes
|
46
54
|
if self.uuid.present?
|
47
55
|
puppet_module = PuppetModule.with_identifiers(self.uuid).first
|
@@ -7,6 +7,10 @@ module Katello
|
|
7
7
|
Repository::DEB_TYPE
|
8
8
|
].freeze
|
9
9
|
|
10
|
+
ALLOWED_IMPORT_REPOSITORY_TYPES = [
|
11
|
+
Repository::YUM_TYPE
|
12
|
+
].freeze
|
13
|
+
|
10
14
|
belongs_to :content_view, :inverse_of => :content_view_repositories,
|
11
15
|
:class_name => "Katello::ContentView"
|
12
16
|
belongs_to :repository, :inverse_of => :content_view_repositories,
|
@@ -27,7 +31,7 @@ module Katello
|
|
27
31
|
end
|
28
32
|
|
29
33
|
def ensure_repository_type
|
30
|
-
unless
|
34
|
+
unless allowed_repository_types.include?(repository.content_type)
|
31
35
|
errors.add(:base, _("Cannot add %s repositories to a content view.") % repository.content_type)
|
32
36
|
end
|
33
37
|
end
|
@@ -41,5 +45,13 @@ module Katello
|
|
41
45
|
errors.add(:base, _("Repositories from published Content Views are not allowed."))
|
42
46
|
end
|
43
47
|
end
|
48
|
+
|
49
|
+
def allowed_repository_types
|
50
|
+
if self.content_view.import_only?
|
51
|
+
ALLOWED_IMPORT_REPOSITORY_TYPES
|
52
|
+
else
|
53
|
+
ALLOWED_REPOSITORY_TYPES
|
54
|
+
end
|
55
|
+
end
|
44
56
|
end
|
45
57
|
end
|
data/app/models/katello/ping.rb
CHANGED
@@ -5,10 +5,17 @@ module Katello
|
|
5
5
|
PACKAGES = %w(katello candlepin pulp qpid foreman tfm hammer).freeze
|
6
6
|
|
7
7
|
class << self
|
8
|
+
def pulpcore_enabled # for downstream 6.9, remove in 6.10
|
9
|
+
SETTINGS[:katello][:use_pulp_2_for_content_type].nil? || (!SETTINGS[:katello][:use_pulp_2_for_content_type][:yum] &&
|
10
|
+
!SETTINGS[:katello][:use_pulp_2_for_content_type][:docker] &&
|
11
|
+
!SETTINGS[:katello][:use_pulp_2_for_content_type][:file]) ||
|
12
|
+
system('systemctl is-enabled pulpcore-api.service')
|
13
|
+
end
|
14
|
+
|
8
15
|
def services(capsule_id = nil)
|
9
16
|
proxy = fetch_proxy(capsule_id)
|
10
17
|
services = [:candlepin, :candlepin_auth, :foreman_tasks, :katello_events, :candlepin_events]
|
11
|
-
services += [:pulp3] if proxy&.pulp3_enabled?
|
18
|
+
services += [:pulp3] if proxy&.pulp3_enabled? && pulpcore_enabled
|
12
19
|
if proxy.nil? || proxy.has_feature?(SmartProxy::PULP_NODE_FEATURE) || proxy.has_feature?(SmartProxy::PULP_FEATURE)
|
13
20
|
services += [:pulp, :pulp_auth]
|
14
21
|
end
|
@@ -16,9 +23,7 @@ module Katello
|
|
16
23
|
services
|
17
24
|
end
|
18
25
|
|
19
|
-
#
|
20
26
|
# Calls "status" services in all backend engines.
|
21
|
-
#
|
22
27
|
def ping(services: nil, capsule_id: nil)
|
23
28
|
services ||= self.services(capsule_id)
|
24
29
|
result = {}
|
@@ -109,6 +109,8 @@ module Katello
|
|
109
109
|
has_many :distribution_references, :class_name => 'Katello::Pulp3::DistributionReference', :foreign_key => :repository_id,
|
110
110
|
:dependent => :destroy, :inverse_of => :repository
|
111
111
|
|
112
|
+
has_many :smart_proxy_sync_histories, :class_name => "::Katello::SmartProxySyncHistory", :inverse_of => :repository, :dependent => :delete_all
|
113
|
+
|
112
114
|
validates_with Validators::ContainerImageNameValidator, :attributes => :container_repository_name, :allow_blank => false, :if => :docker?
|
113
115
|
validates :container_repository_name, :if => :docker?, :uniqueness => {message: ->(object, _data) do
|
114
116
|
_("for repository '%{name}' is not unique and cannot be created in '%{env}'. Its Container Repository Name (%{container_name}) conflicts with an existing repository. Consider changing the Lifecycle Environment's Registry Name Pattern to something more specific.") %
|
@@ -531,6 +533,30 @@ module Katello
|
|
531
533
|
clone
|
532
534
|
end
|
533
535
|
|
536
|
+
def self.synced_on_capsule(smart_proxy)
|
537
|
+
smart_proxy.smart_proxy_sync_histories.map { |sph| sph.repository unless sph.finished_at.nil? }
|
538
|
+
end
|
539
|
+
|
540
|
+
def clear_smart_proxy_sync_histories(smart_proxy = nil)
|
541
|
+
if smart_proxy
|
542
|
+
self.smart_proxy_sync_histories.where(:smart_proxy_id => smart_proxy.id).try(:delete_all)
|
543
|
+
else
|
544
|
+
self.smart_proxy_sync_histories.delete_all
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
def create_smart_proxy_sync_history(smart_proxy)
|
549
|
+
clear_smart_proxy_sync_histories(smart_proxy)
|
550
|
+
sp_history_args = {
|
551
|
+
:smart_proxy_id => smart_proxy.id,
|
552
|
+
:repository_id => self.id,
|
553
|
+
:started_at => Time.now
|
554
|
+
}
|
555
|
+
sp_history = ::Katello::SmartProxySyncHistory.create sp_history_args
|
556
|
+
sp_history.save!
|
557
|
+
sp_history.id
|
558
|
+
end
|
559
|
+
|
534
560
|
def latest_sync_audit
|
535
561
|
self.audits.where(:action => AUDIT_SYNC_ACTION).order(:created_at).last
|
536
562
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Katello
|
2
|
+
class SmartProxySyncHistory < Katello::Model
|
3
|
+
self.table_name = 'katello_smart_proxy_sync_history'
|
4
|
+
|
5
|
+
belongs_to :smart_proxy, :class_name => "::SmartProxy", :inverse_of => :smart_proxy_sync_histories
|
6
|
+
belongs_to :repository, :class_name => "Katello::Repository", :inverse_of => :smart_proxy_sync_histories
|
7
|
+
end
|
8
|
+
end
|
@@ -4,10 +4,11 @@ module Katello
|
|
4
4
|
class Export
|
5
5
|
include ImportExportCommon
|
6
6
|
|
7
|
-
def initialize(smart_proxy:, content_view_version: nil, destination_server: nil)
|
7
|
+
def initialize(smart_proxy:, content_view_version: nil, destination_server: nil, from_content_view_version: nil)
|
8
8
|
@smart_proxy = smart_proxy
|
9
9
|
@content_view_version = content_view_version
|
10
10
|
@destination_server = destination_server
|
11
|
+
@from_content_view_version = from_content_view_version
|
11
12
|
end
|
12
13
|
|
13
14
|
def generate_exporter_path
|
@@ -25,9 +26,32 @@ module Katello
|
|
25
26
|
repositories: repository_hrefs)
|
26
27
|
end
|
27
28
|
|
28
|
-
def create_export(exporter_href, chunk_size
|
29
|
+
def create_export(exporter_href, chunk_size: nil)
|
29
30
|
options = { versions: version_hrefs }
|
30
31
|
options[:chunk_size] = "#{chunk_size}MB" if chunk_size
|
32
|
+
if @from_content_view_version
|
33
|
+
from_exporter = Export.new(smart_proxy: @smart_proxy, content_view_version: @from_content_view_version)
|
34
|
+
start_versions = from_exporter.version_hrefs
|
35
|
+
|
36
|
+
# current_cvv - cvv_from , i.e. repos in current cvv that are not in from
|
37
|
+
# implying something got added to the current cvv
|
38
|
+
# make sure you set the start_versions as 0
|
39
|
+
added_repo_hrefs = repository_hrefs - from_exporter.repository_hrefs
|
40
|
+
added_repo_hrefs.each do |added_repo_href|
|
41
|
+
start_versions << zero_version_href(added_repo_href)
|
42
|
+
end
|
43
|
+
|
44
|
+
# cvv_from - current_cvv , i.e. repos in from cvv that are not in current
|
45
|
+
# implying something got removed the current cvv
|
46
|
+
# make sure the start_versions doesn't contain those
|
47
|
+
deleted_repo_hrefs = from_exporter.repository_hrefs - repository_hrefs
|
48
|
+
start_versions.select! do |href|
|
49
|
+
!deleted_repo_hrefs.include?(version_href_to_repository_href(href))
|
50
|
+
end
|
51
|
+
|
52
|
+
options[:start_versions] = start_versions
|
53
|
+
options[:full] = 'false'
|
54
|
+
end
|
31
55
|
[api.export_api.create(exporter_href, options)]
|
32
56
|
end
|
33
57
|
|
@@ -42,15 +66,49 @@ module Katello
|
|
42
66
|
api.exporter_api.delete(exporter_href)
|
43
67
|
end
|
44
68
|
|
69
|
+
def validate_incremental_export!
|
70
|
+
return if @from_content_view_version.blank?
|
71
|
+
from_exporter = Export.new(smart_proxy: @smart_proxy, content_view_version: @from_content_view_version)
|
72
|
+
|
73
|
+
from_exporter_repos = generate_repo_mapping(from_exporter.repositories)
|
74
|
+
to_exporter_repos = generate_repo_mapping(repositories)
|
75
|
+
|
76
|
+
invalid_repos_exist = (from_exporter_repos.keys & to_exporter_repos.keys).any? do |repo_id|
|
77
|
+
from_exporter_repos[repo_id] != to_exporter_repos[repo_id]
|
78
|
+
end
|
79
|
+
|
80
|
+
if invalid_repos_exist
|
81
|
+
fail _("The exported Content View Version '%{content_view} %{current}' cannot be incrementally updated from version '%{from}'."\
|
82
|
+
" Please do a full export." % { content_view: @content_view_version.content_view.name,
|
83
|
+
current: @content_view_version.version,
|
84
|
+
from: @from_content_view_version.version})
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def generate_repo_mapping(repositories)
|
89
|
+
# return a repo mapping with key being the library_instance_id and value being the repostiory_href
|
90
|
+
# used by validate_incremental_export
|
91
|
+
repo_map = {}
|
92
|
+
repositories.each do |repo|
|
93
|
+
repo_map[repo.library_instance_id] = version_href_to_repository_href(repo.version_href)
|
94
|
+
end
|
95
|
+
repo_map
|
96
|
+
end
|
97
|
+
|
45
98
|
def generate_metadata
|
46
99
|
ret = { organization: @content_view_version.organization.name,
|
47
100
|
repository_mapping: {},
|
48
101
|
content_view: @content_view_version.content_view.name,
|
49
|
-
content_view_version:
|
50
|
-
major: @content_view_version.major,
|
51
|
-
minor: @content_view_version.minor
|
52
|
-
}
|
102
|
+
content_view_version: @content_view_version.slice(:major, :minor)
|
53
103
|
}
|
104
|
+
|
105
|
+
unless @from_content_view_version.blank?
|
106
|
+
ret[:from_content_view_version] = {
|
107
|
+
major: @from_content_view_version.major,
|
108
|
+
minor: @from_content_view_version.minor
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
54
112
|
repositories.each do |repo|
|
55
113
|
next if repo.version_href.blank?
|
56
114
|
pulp3_repo = fetch_repository_info(repo.version_href).name
|
@@ -3,7 +3,6 @@ module Katello
|
|
3
3
|
module ContentViewVersion
|
4
4
|
class Import
|
5
5
|
include ImportExportCommon
|
6
|
-
BASEDIR = '/var/lib/pulp'.freeze
|
7
6
|
|
8
7
|
def initialize(smart_proxy:, content_view_version: nil, path: nil, metadata: nil)
|
9
8
|
@smart_proxy = smart_proxy
|
@@ -44,32 +43,8 @@ module Katello
|
|
44
43
|
api.importer_api.delete(importer_href)
|
45
44
|
end
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
fail _("Invalid path specified.") if path.blank? || !File.directory?(path)
|
50
|
-
fail _("The import path must be in a subdirectory under '%s'." % BASEDIR) unless path.starts_with?(BASEDIR)
|
51
|
-
fail _("Pulp user or group unable to read content in '%s'." % path) unless pulp_user_accessible?(path)
|
52
|
-
|
53
|
-
Dir.glob("#{path}/*").each do |file|
|
54
|
-
fail _("Pulp user or group unable to read '%s'." % file) unless pulp_user_accessible?(file)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def pulp_user_accessible?(path)
|
59
|
-
pulp_info = fetch_pulp_user_info
|
60
|
-
return false if pulp_info.blank?
|
61
|
-
|
62
|
-
stat = File.stat(path)
|
63
|
-
stat.gid.to_s == pulp_info.gid ||
|
64
|
-
stat.uid.to_s == pulp_info.uid ||
|
65
|
-
stat.mode.to_s(8)[-1].to_i >= 4
|
66
|
-
end
|
67
|
-
|
68
|
-
def fetch_pulp_user_info
|
69
|
-
pulp_user = nil
|
70
|
-
Etc.passwd { |u| pulp_user = u if u.name == 'pulp' }
|
71
|
-
pulp_user
|
72
|
-
end
|
46
|
+
def self.check!(content_view:, metadata:, path:)
|
47
|
+
ImportValidator.new(content_view: content_view, metadata: metadata, path: path).check!
|
73
48
|
end
|
74
49
|
end
|
75
50
|
end
|
@@ -38,6 +38,12 @@ module Katello
|
|
38
38
|
def version_href_to_repository_href(version_href)
|
39
39
|
version_href.split("/")[0..-3].join("/") + "/"
|
40
40
|
end
|
41
|
+
|
42
|
+
def zero_version_href(repository_href)
|
43
|
+
# /pulp/api/v3/repositories/rpm/rpm/e59c4334-81d2-4d6b-a1a1-b61fa55ed664/versions/0/
|
44
|
+
repository_href += "/" unless repository_href.ends_with?('/')
|
45
|
+
"#{repository_href}versions/0/"
|
46
|
+
end
|
41
47
|
end
|
42
48
|
end
|
43
49
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Katello
|
2
|
+
module Pulp3
|
3
|
+
module ContentViewVersion
|
4
|
+
class ImportValidator
|
5
|
+
BASEDIR = '/var/lib/pulp'.freeze
|
6
|
+
attr_accessor :metadata, :path, :content_view
|
7
|
+
def initialize(content_view:, path:, metadata:)
|
8
|
+
self.content_view = content_view
|
9
|
+
self.path = path
|
10
|
+
self.metadata = metadata
|
11
|
+
end
|
12
|
+
|
13
|
+
def check!
|
14
|
+
check_permissions!
|
15
|
+
ensure_importing_cvv_does_not_exist!
|
16
|
+
ensure_from_cvv_exists!
|
17
|
+
ensure_repositories_metadata_and_content_view_match!
|
18
|
+
end
|
19
|
+
|
20
|
+
def ensure_importing_cvv_does_not_exist!
|
21
|
+
major = metadata[:content_view_version][:major]
|
22
|
+
minor = metadata[:content_view_version][:minor]
|
23
|
+
|
24
|
+
if ::Katello::ContentViewVersion.where(major: major, minor: minor, content_view: content_view).exists?
|
25
|
+
fail _("Content View Version specified in the metadata - '%{name}' already exists. "\
|
26
|
+
"If you wish to replace the existing version, delete %{name} and try again. " % { name: "#{content_view.name} #{major}.#{minor}" })
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def ensure_from_cvv_exists!
|
31
|
+
major = metadata[:content_view_version][:major]
|
32
|
+
minor = metadata[:content_view_version][:minor]
|
33
|
+
|
34
|
+
if metadata[:from_content_view_version].present?
|
35
|
+
from_major = metadata[:from_content_view_version][:major]
|
36
|
+
from_minor = metadata[:from_content_view_version][:minor]
|
37
|
+
|
38
|
+
unless ::Katello::ContentViewVersion.where(major: from_major, minor: from_minor, content_view: content_view).exists?
|
39
|
+
fail _("Prior Content View Version specified in the metadata - '%{name}' does not exist. "\
|
40
|
+
"Please import the metadata for '%{name}' before importing '%{current}' " % { name: "#{content_view.name} #{from_major}.#{from_minor}",
|
41
|
+
current: "#{content_view.name} #{major}.#{minor}"})
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def ensure_repositories_metadata_and_content_view_match!
|
47
|
+
product_repos_in_content_view = content_view.repositories.yum_type.map { |repo| [repo.product.name, repo.name, repo.redhat?] }
|
48
|
+
product_repos_in_metadata = metadata[:repository_mapping].values.map { |repo| [repo[:product], repo[:repository], repo[:redhat]] }
|
49
|
+
|
50
|
+
product_repos_in_content_view.sort!
|
51
|
+
product_repos_in_metadata.sort!
|
52
|
+
# product_repos_in_content_view & product_repos_in_metadata look like [["prod1", "repo1", false], ["prod2", "repo2", false]]
|
53
|
+
|
54
|
+
if product_repos_in_content_view != product_repos_in_metadata
|
55
|
+
repos_in_content_view = generate_product_repo_i18n_string(product_repos_in_content_view)
|
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("")}
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
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
|
+
def generate_product_repo_i18n_string(product_repos)
|
96
|
+
# product_repos look like [["prod1", "repo1", false], ["prod2", "repo2", false]]
|
97
|
+
product_repos.map do |product, repo, redhat|
|
98
|
+
repo_type = redhat ? _("Red Hat") : _("Custom")
|
99
|
+
_("\n* Product = '%{product}', Repository = '%{repository}', Repository Type = '%{repo_type}'" % { product: product,
|
100
|
+
repository: repo,
|
101
|
+
repo_type: repo_type})
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -165,10 +165,16 @@ module Katello
|
|
165
165
|
process_distributions(pulp3_api, migrated_repo.pulp3_distribution_hrefs)
|
166
166
|
end
|
167
167
|
|
168
|
+
def distribution_path_from_cache(href, pulp3_api)
|
169
|
+
@distribution_cache ||= {}
|
170
|
+
@distribution_cache[href] ||= pulp3_api.distributions_api.read(href).base_path
|
171
|
+
@distribution_cache[href]
|
172
|
+
end
|
173
|
+
|
168
174
|
def process_distributions(pulp3_api, dist_hrefs_list)
|
169
175
|
#distribution_path_hash(pulp3_api, dist_hrefs_list).each do |relative_path, href|
|
170
176
|
dist_hrefs_list.each do |href|
|
171
|
-
relative_path =
|
177
|
+
relative_path = distribution_path_from_cache(href, pulp3_api)
|
172
178
|
|
173
179
|
dist_ref = Katello::Pulp3::DistributionReference.find_or_initialize_by(:path => relative_path)
|
174
180
|
if (distribution_repo = Katello::Repository.find_by(:relative_path => relative_path) || Katello::Repository.find_by(:container_repository_name => relative_path))
|
@@ -159,8 +159,7 @@ module Katello
|
|
159
159
|
|
160
160
|
data_dup.config[i][:content] = leftover_units.pop(copy_amount)
|
161
161
|
unit_copy_counter += copy_amount
|
162
|
-
|
163
|
-
if unit_copy_counter >= UNIT_LIMIT || (i == data_dup.config.size - 1 && leftover_units.empty?)
|
162
|
+
if unit_copy_counter != 0
|
164
163
|
tasks << api.copy_api.copy_content(data_dup)
|
165
164
|
unit_copy_counter = 0
|
166
165
|
end
|
@@ -79,7 +79,7 @@ module Katello
|
|
79
79
|
|
80
80
|
def error
|
81
81
|
if task_data[:state] == CANCELED
|
82
|
-
|
82
|
+
_("Task canceled")
|
83
83
|
elsif task_data[:state] == FAILED
|
84
84
|
if task_data[:error][:description].blank?
|
85
85
|
_("Pulp task error")
|
@@ -90,8 +90,8 @@ module Katello
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def cancel
|
93
|
-
data = PulpcoreClient::
|
94
|
-
tasks_api.tasks_cancel(
|
93
|
+
data = PulpcoreClient::TaskResponse.new(state: 'canceled')
|
94
|
+
tasks_api.tasks_cancel(task_data['pulp_href'], data)
|
95
95
|
#the main task may have completed, so cancel spawned tasks too
|
96
96
|
task_data['spawned_tasks']&.each { |spawned| tasks_api.tasks_cancel(spawned['pulp_href'], data) }
|
97
97
|
end
|