hammer_cli_import 0.10.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +115 -0
- data/channel_data_pretty.json +10316 -0
- data/config/import/config_macros.yml +16 -0
- data/config/import/interview_answers.yml +13 -0
- data/config/import/role_map.yml +10 -0
- data/config/import.yml +2 -0
- data/lib/hammer_cli_import/activationkey.rb +156 -0
- data/lib/hammer_cli_import/all.rb +253 -0
- data/lib/hammer_cli_import/asynctasksreactor.rb +187 -0
- data/lib/hammer_cli_import/autoload.rb +27 -0
- data/lib/hammer_cli_import/base.rb +585 -0
- data/lib/hammer_cli_import/configfile.rb +392 -0
- data/lib/hammer_cli_import/contenthost.rb +243 -0
- data/lib/hammer_cli_import/contentview.rb +198 -0
- data/lib/hammer_cli_import/csvhelper.rb +68 -0
- data/lib/hammer_cli_import/deltahash.rb +86 -0
- data/lib/hammer_cli_import/fixtime.rb +27 -0
- data/lib/hammer_cli_import/hostcollection.rb +52 -0
- data/lib/hammer_cli_import/import.rb +31 -0
- data/lib/hammer_cli_import/importtools.rb +351 -0
- data/lib/hammer_cli_import/organization.rb +110 -0
- data/lib/hammer_cli_import/persistentmap.rb +225 -0
- data/lib/hammer_cli_import/repository.rb +91 -0
- data/lib/hammer_cli_import/repositoryenable.rb +250 -0
- data/lib/hammer_cli_import/templatesnippet.rb +67 -0
- data/lib/hammer_cli_import/user.rb +155 -0
- data/lib/hammer_cli_import/version.rb +25 -0
- data/lib/hammer_cli_import.rb +53 -0
- metadata +117 -0
@@ -0,0 +1,198 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'set'
|
21
|
+
|
22
|
+
module HammerCLIImport
|
23
|
+
class ImportCommand
|
24
|
+
class LocalRepositoryImportCommand < BaseCommand
|
25
|
+
extend ImportTools::Repository::Extend
|
26
|
+
include ImportTools::Repository::Include
|
27
|
+
include ImportTools::ContentView::Include
|
28
|
+
|
29
|
+
command_name 'content-view'
|
30
|
+
desc 'Create Content Views based on local/cloned Channels (from spacewalk-export-channels).'
|
31
|
+
|
32
|
+
csv_columns 'org_id', 'channel_id', 'channel_label', 'channel_name'
|
33
|
+
|
34
|
+
persistent_maps :organizations, :repositories, :local_repositories, :content_views,
|
35
|
+
:products, :redhat_repositories, :redhat_content_views, :system_content_views
|
36
|
+
|
37
|
+
option ['--dir'], 'DIR', 'Export directory'
|
38
|
+
option ['--filter'], :flag, 'Filter content-views for package names present in Sat5 channel', :default => false
|
39
|
+
add_repo_options
|
40
|
+
|
41
|
+
def directory
|
42
|
+
File.expand_path(option_dir || File.dirname(option_csv_file))
|
43
|
+
end
|
44
|
+
|
45
|
+
def mk_product_hash(data, product_name)
|
46
|
+
{
|
47
|
+
:name => product_name,
|
48
|
+
:organization_id => get_translated_id(:organizations, data['org_id'].to_i)
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def mk_repo_hash(data, product_id)
|
53
|
+
{
|
54
|
+
:name => "Local repository for #{data['channel_label']}",
|
55
|
+
:product_id => product_id,
|
56
|
+
:url => 'file://' + File.join(directory, data['org_id'], data['channel_id']),
|
57
|
+
:content_type => 'yum'
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def mk_content_view_hash(data, repo_ids)
|
62
|
+
{
|
63
|
+
:name => data['channel_name'],
|
64
|
+
|
65
|
+
:description => 'Channel migrated from Satellite 5',
|
66
|
+
|
67
|
+
:organization_id => get_translated_id(:organizations, data['org_id'].to_i),
|
68
|
+
:repository_ids => repo_ids
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def newer_repositories(cw)
|
73
|
+
last = cw['last_published']
|
74
|
+
return true unless last
|
75
|
+
last = Time.parse(last)
|
76
|
+
cw['repositories'].any? do |repo|
|
77
|
+
repo['last_sync'].nil? || last < Time.parse(repo['last_sync'])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def push_unless_nil(col, obj)
|
82
|
+
col << obj unless obj.nil?
|
83
|
+
end
|
84
|
+
|
85
|
+
def load_custom_channel_info(org_id, channel_id)
|
86
|
+
headers = %w(org_id channel_id package_nevra package_rpm_name in_repo in_parent_channel)
|
87
|
+
file = File.join directory, org_id.to_s, channel_id.to_s + '.csv'
|
88
|
+
|
89
|
+
packages_in_channel = Set[]
|
90
|
+
repo_ids = Set[]
|
91
|
+
parent_channel_ids = Set[]
|
92
|
+
has_local_packages = false
|
93
|
+
|
94
|
+
CSVHelper.csv_each file, headers do |data|
|
95
|
+
packages_in_channel << data['package_nevra']
|
96
|
+
push_unless_nil parent_channel_ids, data['in_parent_channel']
|
97
|
+
push_unless_nil repo_ids, data['in_repo']
|
98
|
+
has_local_packages ||= data['in_repo'].nil? && data['in_parent_channel'].nil?
|
99
|
+
end
|
100
|
+
|
101
|
+
raise "Multiple parents for channel #{channel_id}?" unless parent_channel_ids.size.between? 0, 1
|
102
|
+
|
103
|
+
[repo_ids.to_a, parent_channel_ids.to_a, packages_in_channel.to_a, has_local_packages]
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_local_repo(data)
|
107
|
+
product_name = 'Local-repositories'
|
108
|
+
composite_id = [data['org_id'].to_i, product_name]
|
109
|
+
product_hash = mk_product_hash data, product_name
|
110
|
+
product_id = create_entity(:products, product_hash, composite_id)['id'].to_i
|
111
|
+
|
112
|
+
repo_hash = mk_repo_hash data, product_id
|
113
|
+
local_repo = create_entity :local_repositories, repo_hash, [data['org_id'].to_i, data['channel_id'].to_i]
|
114
|
+
local_repo
|
115
|
+
end
|
116
|
+
|
117
|
+
def add_repo_filters(content_view_id, nevras)
|
118
|
+
cw_filter = api_call :content_view_filters,
|
119
|
+
:create,
|
120
|
+
{ :content_view_id => content_view_id,
|
121
|
+
:name => 'Satellite 5 channel equivalence filter',
|
122
|
+
:type => 'rpm',
|
123
|
+
:inclusion => true}
|
124
|
+
|
125
|
+
packages = nevras.collect do |package_nevra|
|
126
|
+
match = /^([^:]+)-(\d+):([^-]+)-(.*)\.([^.]*)$/.match(package_nevra)
|
127
|
+
raise "Bad nevra: #{package_nevra}" unless match
|
128
|
+
|
129
|
+
{ :name => match[1],
|
130
|
+
:epoch => match[2],
|
131
|
+
:version => match[3],
|
132
|
+
:release => match[4],
|
133
|
+
:architecture => match[5]
|
134
|
+
}
|
135
|
+
end
|
136
|
+
packages.group_by { |package| package[:name] } .each do |name, _packages|
|
137
|
+
api_call :content_view_filter_rules,
|
138
|
+
:create,
|
139
|
+
{ :content_view_filter_id => cw_filter['id'],
|
140
|
+
:name => name}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def import_single_row(data)
|
145
|
+
org_id = data['org_id'].to_i
|
146
|
+
|
147
|
+
repo_ids, clone_parents, packages, has_local = load_custom_channel_info org_id, data['channel_id'].to_i
|
148
|
+
|
149
|
+
repo_ids.map! { |id| get_translated_id :repositories, id.to_i }
|
150
|
+
|
151
|
+
if has_local
|
152
|
+
local_repo = add_local_repo data
|
153
|
+
sync_repo local_repo unless repo_synced? local_repo
|
154
|
+
repo_ids.push local_repo['id'].to_i
|
155
|
+
end
|
156
|
+
|
157
|
+
clone_parents.collect { |x| Integer(x) } .each do |parent_id|
|
158
|
+
begin
|
159
|
+
begin
|
160
|
+
parent_cv = get_cache(:redhat_content_views)[get_translated_id :redhat_content_views, [org_id, parent_id]]
|
161
|
+
rescue
|
162
|
+
parent_cv = get_cache(:content_views)[get_translated_id :content_views, parent_id]
|
163
|
+
end
|
164
|
+
repo_ids += parent_cv['repositories'].collect { |x| x['id'] }
|
165
|
+
rescue HammerCLIImport::MissingObjectError
|
166
|
+
error "No such {redhat_,}content_view: #{parent_id}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
repo_ids.collect { |id| lookup_entity :repositories, id } .each do |repo|
|
171
|
+
unless repo_synced? repo
|
172
|
+
warn "Repository #{repo['label']} is not (fully) synchronized. Retry once synchronization has completed."
|
173
|
+
report_summary :skipped, :content_views
|
174
|
+
return nil
|
175
|
+
end
|
176
|
+
end
|
177
|
+
content_view = mk_content_view_hash data, repo_ids
|
178
|
+
|
179
|
+
cw = create_entity :content_views, content_view, data['channel_id'].to_i
|
180
|
+
add_repo_filters cw['id'], packages if option_filter?
|
181
|
+
publish_content_view cw['id'] if newer_repositories cw
|
182
|
+
end
|
183
|
+
|
184
|
+
def delete_single_row(data)
|
185
|
+
cv_id = data['channel_id'].to_i
|
186
|
+
unless @pm[:content_views][cv_id] || @pm[:redhat_content_views][cv_id] || @pm[:system_content_views][cv_id]
|
187
|
+
info "#{to_singular(:content_views).capitalize} with id #{cv_id} wasn't imported. Skipping deletion."
|
188
|
+
return
|
189
|
+
end
|
190
|
+
translated = get_translated_id :content_views, cv_id
|
191
|
+
|
192
|
+
# delete_entity :content_views, cv_id
|
193
|
+
delete_content_view translated
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'csv'
|
21
|
+
|
22
|
+
module CSVHelper
|
23
|
+
class CSVHelperError < RuntimeError
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns missing columns
|
27
|
+
def self.csv_missing_columns(filename, headers)
|
28
|
+
reader = CSV.open(filename, 'r')
|
29
|
+
real_header = reader.shift
|
30
|
+
reader.close
|
31
|
+
headers - real_header
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.csv_each(filename, headers)
|
35
|
+
raise CSVHelperError, 'Expecting block' unless block_given?
|
36
|
+
reader = CSV.open(filename, 'r')
|
37
|
+
real_header = reader.shift
|
38
|
+
raise CSVHelperError, "No header in #{filename}" if real_header.nil?
|
39
|
+
real_header_length = real_header.length
|
40
|
+
to_discard = real_header - headers
|
41
|
+
headers.each do |col|
|
42
|
+
raise CSVHelperError, "Column #{col} expected in #{filename}" unless real_header.include? col
|
43
|
+
end
|
44
|
+
reader.each do |row|
|
45
|
+
raise CSVHelperError, "Broken CSV in #{filename}: #{real_header_length} columns expected but found #{row.length}" \
|
46
|
+
unless row.length == real_header_length
|
47
|
+
data = Hash[real_header.zip row]
|
48
|
+
to_discard.each { |key| data.delete key }
|
49
|
+
class << data
|
50
|
+
def[](key)
|
51
|
+
raise CSVHelperError, "Referencing undeclared key: #{key}" unless key? key
|
52
|
+
super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
yield data
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.csv_write_hashes(filename, headers, hashes)
|
60
|
+
CSV.open(filename, 'wb') do |csv|
|
61
|
+
csv << headers
|
62
|
+
hashes.each do |hash|
|
63
|
+
csv << headers.collect { |key| hash[key] }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'set'
|
21
|
+
|
22
|
+
class DeltaHashError < RuntimeError
|
23
|
+
end
|
24
|
+
|
25
|
+
class DeltaHash
|
26
|
+
attr_reader :new
|
27
|
+
attr_reader :del
|
28
|
+
|
29
|
+
def self.[](hash)
|
30
|
+
new(hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(hash)
|
34
|
+
@old = hash
|
35
|
+
@new = {}
|
36
|
+
@del = Set.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def [](key)
|
40
|
+
return nil if @del.include? key
|
41
|
+
@new[key] || @old[key]
|
42
|
+
end
|
43
|
+
|
44
|
+
def []=(key, val)
|
45
|
+
raise DeltaHashError, 'Key exists' if self[key]
|
46
|
+
@del.delete key
|
47
|
+
@new[key] = val unless @old[key] == val
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_hash
|
51
|
+
ret = (@old.merge @new)
|
52
|
+
@del.each do |key|
|
53
|
+
ret.delete key
|
54
|
+
end
|
55
|
+
ret
|
56
|
+
end
|
57
|
+
|
58
|
+
def delete(key)
|
59
|
+
raise DeltaHashError, "Key #{key} does not exist" unless self[key]
|
60
|
+
@del << key if @old[key]
|
61
|
+
@new.delete(key)
|
62
|
+
end
|
63
|
+
|
64
|
+
def delete_value(value)
|
65
|
+
deleted = 0
|
66
|
+
to_hash.each do |k, v|
|
67
|
+
next unless v == value
|
68
|
+
delete(k)
|
69
|
+
deleted += 1
|
70
|
+
end
|
71
|
+
return deleted
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_s
|
75
|
+
to_hash.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
def inspect
|
79
|
+
to_hash.inspect
|
80
|
+
end
|
81
|
+
|
82
|
+
def changed?
|
83
|
+
! (@new.empty? && del.empty?)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'time'
|
21
|
+
|
22
|
+
class Time
|
23
|
+
def iso8601
|
24
|
+
strftime '%Y-%m-%dT%H:%M:%S%z'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'hammer_cli'
|
21
|
+
require 'apipie-bindings'
|
22
|
+
|
23
|
+
module HammerCLIImport
|
24
|
+
class ImportCommand
|
25
|
+
class SystemGroupImportCommand < BaseCommand
|
26
|
+
command_name 'host-collection'
|
27
|
+
reportname = 'system-groups'
|
28
|
+
desc "Import Host Collections (from spacewalk-report #{reportname})."
|
29
|
+
|
30
|
+
csv_columns 'group_id', 'name', 'org_id'
|
31
|
+
|
32
|
+
persistent_maps :organizations, :host_collections
|
33
|
+
|
34
|
+
def mk_sg_hash(data)
|
35
|
+
{
|
36
|
+
:name => data['name'],
|
37
|
+
:organization_id => get_translated_id(:organizations, data['org_id'].to_i)
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def import_single_row(data)
|
42
|
+
sg = mk_sg_hash data
|
43
|
+
create_entity(:host_collections, sg, data['group_id'].to_i)
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete_single_row(data)
|
47
|
+
delete_entity(:host_collections, data['group_id'].to_i)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'hammer_cli'
|
21
|
+
require 'hammer_cli/exit_codes'
|
22
|
+
|
23
|
+
module HammerCLIImport
|
24
|
+
class ImportCommand < HammerCLI::AbstractCommand
|
25
|
+
end
|
26
|
+
|
27
|
+
HammerCLI::MainCommand.subcommand('import',
|
28
|
+
'Import data exported from a Red Hat Satellite 5 instance',
|
29
|
+
HammerCLIImport::ImportCommand)
|
30
|
+
end
|
31
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|