hammer_cli_csv 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/config/cli_config.yml +9 -24
- data/lib/hammer_cli_csv/activation_keys.rb +220 -95
- data/lib/hammer_cli_csv/architectures.rb +7 -11
- data/lib/hammer_cli_csv/base.rb +67 -41
- data/lib/hammer_cli_csv/compute_profiles.rb +11 -15
- data/lib/hammer_cli_csv/compute_resources.rb +11 -15
- data/lib/hammer_cli_csv/containers.rb +10 -12
- data/lib/hammer_cli_csv/content_hosts.rb +285 -203
- data/lib/hammer_cli_csv/content_view_filters.rb +32 -36
- data/lib/hammer_cli_csv/content_views.rb +33 -37
- data/lib/hammer_cli_csv/csv.rb +17 -1
- data/lib/hammer_cli_csv/domains.rb +15 -19
- data/lib/hammer_cli_csv/export.rb +13 -5
- data/lib/hammer_cli_csv/host_collections.rb +20 -22
- data/lib/hammer_cli_csv/host_groups.rb +73 -65
- data/lib/hammer_cli_csv/hosts.rb +30 -34
- data/lib/hammer_cli_csv/import.rb +24 -10
- data/lib/hammer_cli_csv/installation_media.rb +74 -0
- data/lib/hammer_cli_csv/job_templates.rb +37 -41
- data/lib/hammer_cli_csv/lifecycle_environments.rb +15 -19
- data/lib/hammer_cli_csv/locations.rb +4 -6
- data/lib/hammer_cli_csv/operating_systems.rb +17 -21
- data/lib/hammer_cli_csv/organizations.rb +11 -13
- data/lib/hammer_cli_csv/partition_tables.rb +17 -21
- data/lib/hammer_cli_csv/products.rb +200 -92
- data/lib/hammer_cli_csv/provisioning_templates.rb +19 -23
- data/lib/hammer_cli_csv/puppet_environments.rb +8 -12
- data/lib/hammer_cli_csv/puppet_facts.rb +20 -24
- data/lib/hammer_cli_csv/puppet_reports.rb +47 -51
- data/lib/hammer_cli_csv/reports.rb +6 -10
- data/lib/hammer_cli_csv/roles.rb +12 -16
- data/lib/hammer_cli_csv/settings.rb +8 -6
- data/lib/hammer_cli_csv/smart_proxies.rb +9 -13
- data/lib/hammer_cli_csv/splice.rb +1 -3
- data/lib/hammer_cli_csv/subnets.rb +24 -28
- data/lib/hammer_cli_csv/subscriptions.rb +39 -91
- data/lib/hammer_cli_csv/sync_plans.rb +20 -24
- data/lib/hammer_cli_csv/users.rb +25 -29
- data/lib/hammer_cli_csv/utils/subscriptions.rb +130 -0
- data/lib/hammer_cli_csv/version.rb +1 -1
- data/lib/hammer_cli_csv.rb +2 -2
- data/test/csv_test.rb +32 -0
- data/test/csv_test_helper.rb +17 -2
- data/test/data/content-hosts.csv +3 -2
- data/test/data/hosts.csv +0 -11
- data/test/data/settings.csv +1 -0
- data/test/data/setup/content-hosts.csv +1 -0
- data/test/data/setup/content-views.csv +2 -0
- data/test/data/setup/lifecycle-environments.csv +5 -0
- data/test/data/setup/locations.csv +6 -0
- data/test/data/setup/organizations.csv +2 -0
- data/test/data/setup/subscriptions.csv +5 -0
- data/test/data/subscriptions.csv +15 -17
- data/test/export_test.rb +27 -0
- data/test/fixtures/vcr_cassettes/apipie.yml +18528 -0
- data/test/fixtures/vcr_cassettes/resources/activation_keys_import/create_and_update.yml +38033 -0
- data/test/fixtures/vcr_cassettes/resources/content_hosts_export/export.yml +18846 -0
- data/test/fixtures/vcr_cassettes/resources/content_hosts_export/export_subscriptions.yml +323 -0
- data/test/fixtures/vcr_cassettes/resources/content_hosts_import/create_and_update.yml +41884 -0
- data/test/fixtures/vcr_cassettes/resources/content_hosts_import/import_single_line.yml +38248 -0
- data/test/fixtures/vcr_cassettes/resources/settings_import/update_settings.yml +18832 -0
- data/test/fixtures/vcr_cassettes/resources/settings_import/update_settings_continue.yml +316 -0
- data/test/fixtures/vcr_cassettes/resources/subscriptions_import/manifest_does_not_exist.yml +18785 -0
- data/test/fixtures/vcr_cassettes/setup/setup_content_views/setup.yml +19090 -0
- data/test/fixtures/vcr_cassettes/setup/setup_lifecycle_environments/setup.yml +924 -0
- data/test/fixtures/vcr_cassettes/setup/setup_locations/setup.yml +21102 -0
- data/test/fixtures/vcr_cassettes/setup/setup_organizations/setup.yml +19278 -0
- data/test/fixtures/vcr_cassettes/setup/setup_subscriptions/setup.yml +419 -0
- data/test/import_test.rb +20 -25
- data/test/resources/activation_keys_test.rb +72 -0
- data/test/resources/content_hosts_test.rb +132 -0
- data/test/resources/settings_test.rb +81 -0
- data/test/resources/subscriptions_test.rb +56 -0
- data/test/setup/setup_content_views.rb +17 -0
- data/test/setup/setup_lifecycle_environments.rb +17 -0
- data/test/setup/setup_locations.rb +17 -0
- data/test/setup/setup_organizations.rb +17 -0
- data/test/setup/setup_subscriptions.rb +20 -0
- data/test/setup/setup_test.rb +10 -0
- data/test/test_runner.rb +175 -0
- data/test/vcr_setup.rb +54 -0
- metadata +77 -13
- data/lib/hammer_cli_csv/exception_handler.rb +0 -42
- data/lib/hammer_cli_csv/installation_medias.rb +0 -77
- data/test/content_hosts_test.rb +0 -61
- data/test/settings_test.rb +0 -30
@@ -1,11 +1,20 @@
|
|
1
|
+
#require 'hammer_cli_csv/utils/subscription_utils'
|
2
|
+
|
1
3
|
module HammerCLICsv
|
2
4
|
class CsvCommand
|
3
5
|
class ContentHostsCommand < BaseCommand
|
4
6
|
include ::HammerCLIForemanTasks::Helper
|
7
|
+
include ::HammerCLICsv::Utils::Subscriptions
|
5
8
|
|
6
9
|
command_name 'content-hosts'
|
7
10
|
desc 'import or export content hosts'
|
8
11
|
|
12
|
+
def self.supported?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
option %w(--itemized-subscriptions), :flag, _('Export one subscription per row, only process update subscriptions on import')
|
17
|
+
|
9
18
|
ORGANIZATION = 'Organization'
|
10
19
|
ENVIRONMENT = 'Environment'
|
11
20
|
CONTENTVIEW = 'Content View'
|
@@ -19,123 +28,68 @@ module HammerCLICsv
|
|
19
28
|
CORES = 'Cores'
|
20
29
|
SLA = 'SLA'
|
21
30
|
PRODUCTS = 'Products'
|
22
|
-
SUBSCRIPTIONS = 'Subscriptions'
|
23
|
-
|
24
|
-
def export
|
25
|
-
CSV.open(option_file || '/dev/stdout', 'wb', {:force_quotes => false}) do |csv|
|
26
|
-
csv << [NAME, ORGANIZATION, ENVIRONMENT, CONTENTVIEW, HOSTCOLLECTIONS, VIRTUAL, HOST,
|
27
|
-
OPERATINGSYSTEM, ARCHITECTURE, SOCKETS, RAM, CORES, SLA, PRODUCTS, SUBSCRIPTIONS]
|
28
|
-
if @server_status['release'] == 'Headpin'
|
29
|
-
export_sam csv
|
30
|
-
else
|
31
|
-
export_foretello csv
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def export_sam(csv)
|
37
|
-
guests_hypervisor = {}
|
38
|
-
host_ids = []
|
39
31
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
32
|
+
def export(csv)
|
33
|
+
if option_itemized_subscriptions?
|
34
|
+
export_itemized_subscriptions csv
|
35
|
+
else
|
36
|
+
export_all csv
|
46
37
|
end
|
38
|
+
end
|
47
39
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
75
|
-
products.delete!("\n")
|
76
|
-
|
77
|
-
subscriptions = CSV.generate do |column|
|
78
|
-
column << host_subscriptions.collect do |subscription|
|
79
|
-
"#{subscription['quantity']}|#{subscription['productId']}|#{subscription['poolName']}"
|
40
|
+
def export_itemized_subscriptions(csv)
|
41
|
+
csv << shared_headers + [Utils::Subscriptions::SUBS_NAME, Utils::Subscriptions::SUBS_TYPE,
|
42
|
+
Utils::Subscriptions::SUBS_QUANTITY, Utils::Subscriptions::SUBS_SKU,
|
43
|
+
Utils::Subscriptions::SUBS_CONTRACT, Utils::Subscriptions::SUBS_ACCOUNT,
|
44
|
+
Utils::Subscriptions::SUBS_START, Utils::Subscriptions::SUBS_END]
|
45
|
+
iterate_hosts(csv) do |host|
|
46
|
+
export_line = shared_columns(host)
|
47
|
+
if host['subscription_facet_attributes']
|
48
|
+
subscriptions = @api.resource(:host_subscriptions).call(:index, {
|
49
|
+
'organization_id' => host['organization_id'],
|
50
|
+
'host_id' => host['id']
|
51
|
+
})['results']
|
52
|
+
if subscriptions.empty?
|
53
|
+
csv << export_line + [nil, nil, nil, nil, nil, nil]
|
54
|
+
else
|
55
|
+
subscriptions.each do |subscription|
|
56
|
+
subscription_type = subscription['product_id'].to_i == 0 ? 'Red Hat' : 'Custom'
|
57
|
+
subscription_type += ' Guest' if subscription['type'] == 'STACK_DERIVED'
|
58
|
+
subscription_type += ' Temporary' if subscription['type'] == 'UNMAPPED_GUEST'
|
59
|
+
csv << export_line + [subscription['product_name'], subscription_type,
|
60
|
+
subscription['quantity_consumed'], subscription['product_id'],
|
61
|
+
subscription['contract_number'], subscription['account_number'],
|
62
|
+
DateTime.parse(subscription['start_date']).strftime('%m/%d/%Y'),
|
63
|
+
DateTime.parse(subscription['end_date']).strftime('%m/%d/%Y')]
|
64
|
+
end
|
80
65
|
end
|
66
|
+
else
|
67
|
+
csv << export_line + [nil, nil, nil, nil, nil, nil]
|
81
68
|
end
|
82
|
-
subscriptions.delete!("\n")
|
83
|
-
|
84
|
-
csv << [name, organization_name, environment, contentview, hostcollections, virtual, hypervisor,
|
85
|
-
operatingsystem, architecture, sockets, ram, cores, sla, products, subscriptions]
|
86
69
|
end
|
87
70
|
end
|
88
71
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
@api.resource(:systems).call(:index, {
|
94
|
-
'per_page' => 999999,
|
95
|
-
'organization_id' => foreman_organization(:name => organization['name'])
|
96
|
-
})['results'].each do |host|
|
97
|
-
host = @api.resource(:systems).call(:show, {
|
98
|
-
'id' => host['uuid'],
|
99
|
-
'fields' => 'full'
|
100
|
-
})
|
101
|
-
|
102
|
-
name = host['name']
|
103
|
-
organization_name = organization['name']
|
104
|
-
environment = host['environment']['label']
|
105
|
-
contentview = host['content_view']['name']
|
106
|
-
hostcollections = CSV.generate do |column|
|
107
|
-
column << host['hostCollections'].collect do |hostcollection|
|
108
|
-
hostcollection['name']
|
109
|
-
end
|
110
|
-
end
|
111
|
-
hostcollections.delete!("\n")
|
112
|
-
virtual = host['facts']['virt.is_guest'] == 'true' ? 'Yes' : 'No'
|
113
|
-
hypervisor_host = host['virtual_host'].nil? ? nil : host['virtual_host']['name']
|
114
|
-
operatingsystem = "#{host['facts']['distribution.name']} " if host['facts']['distribution.name']
|
115
|
-
operatingsystem += host['facts']['distribution.version'] if host['facts']['distribution.version']
|
116
|
-
architecture = host['facts']['uname.machine']
|
117
|
-
sockets = host['facts']['cpu.cpu_socket(s)']
|
118
|
-
ram = host['facts']['memory.memtotal']
|
119
|
-
cores = host['facts']['cpu.core(s)_per_socket'] || 1
|
120
|
-
sla = ''
|
121
|
-
products = CSV.generate do |column|
|
122
|
-
column << host['installedProducts'].collect do |product|
|
123
|
-
"#{product['productId']}|#{product['productName']}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
products.delete!("\n")
|
72
|
+
def export_all(csv)
|
73
|
+
csv << shared_headers + [Utils::Subscriptions::SUBSCRIPTIONS]
|
74
|
+
iterate_hosts(csv) do |host|
|
75
|
+
if host['subscription_facet_attributes']
|
127
76
|
subscriptions = CSV.generate do |column|
|
128
|
-
column << @api.resource(:
|
129
|
-
'organization_id' =>
|
130
|
-
'
|
77
|
+
column << @api.resource(:host_subscriptions).call(:index, {
|
78
|
+
'organization_id' => host['organization_id'],
|
79
|
+
'host_id' => host['id']
|
131
80
|
})['results'].collect do |subscription|
|
132
|
-
"#{subscription['
|
81
|
+
"#{subscription['quantity_consumed']}"\
|
82
|
+
"|#{subscription['product_id']}"\
|
83
|
+
"|#{subscription['product_name']}"\
|
84
|
+
"|#{subscription['contract_number']}|#{subscription['account_number']}"
|
133
85
|
end
|
134
86
|
end
|
135
87
|
subscriptions.delete!("\n")
|
136
|
-
|
137
|
-
|
88
|
+
else
|
89
|
+
subscriptions = nil
|
138
90
|
end
|
91
|
+
|
92
|
+
csv << shared_columns(host) + [subscriptions]
|
139
93
|
end
|
140
94
|
end
|
141
95
|
|
@@ -157,111 +111,99 @@ module HammerCLICsv
|
|
157
111
|
def import_locally
|
158
112
|
@existing = {}
|
159
113
|
@hypervisor_guests = {}
|
114
|
+
@all_subscriptions = {}
|
160
115
|
|
161
116
|
thread_import do |line|
|
162
|
-
|
117
|
+
create_from_csv(line)
|
163
118
|
end
|
164
119
|
|
165
120
|
if !@hypervisor_guests.empty?
|
166
121
|
print(_('Updating hypervisor and guest associations...')) if option_verbose?
|
167
122
|
@hypervisor_guests.each do |host_id, guest_ids|
|
168
123
|
@api.resource(:hosts).call(:update, {
|
169
|
-
|
170
|
-
|
171
|
-
|
124
|
+
'id' => host_id,
|
125
|
+
'host' => {
|
126
|
+
'subscription_facet_attributes' => {
|
127
|
+
'autoheal' => false,
|
128
|
+
'hypervisor_guest_uuids' => guest_ids
|
172
129
|
}
|
130
|
+
}
|
173
131
|
})
|
174
132
|
end
|
175
133
|
puts _('done') if option_verbose?
|
176
134
|
end
|
177
135
|
end
|
178
136
|
|
179
|
-
def
|
137
|
+
def create_from_csv(line)
|
180
138
|
return if option_organization && line[ORGANIZATION] != option_organization
|
181
139
|
|
182
|
-
|
183
|
-
@existing[line[ORGANIZATION]] = true
|
184
|
-
# Fetching all content hosts is too slow and times out due to the complexity of the data
|
185
|
-
# rendered in the json.
|
186
|
-
# http://projects.theforeman.org/issues/6307
|
187
|
-
total = @api.resource(:hosts).call(:index, {
|
188
|
-
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
189
|
-
'per_page' => 1
|
190
|
-
})['total'].to_i
|
191
|
-
(total / 20 + 2).to_i.times do |page|
|
192
|
-
@api.resource(:hosts).call(:index, {
|
193
|
-
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
194
|
-
'page' => page + 1,
|
195
|
-
'per_page' => 20
|
196
|
-
})['results'].each do |host|
|
197
|
-
@existing[host['name']] = {
|
198
|
-
:host => host['id'],
|
199
|
-
:subscription => host['subscription']['id'],
|
200
|
-
:content => host['content']['id']
|
201
|
-
}
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
140
|
+
update_existing(line)
|
205
141
|
|
206
142
|
count(line[COUNT]).times do |number|
|
207
143
|
name = namify(line[NAME], number)
|
208
144
|
|
209
|
-
if
|
210
|
-
|
211
|
-
host_id = @api.resource(:host_subscriptions).call(:register, {
|
212
|
-
'name' => name,
|
213
|
-
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
214
|
-
'lifecycle_environment_id' => lifecycle_environment(line[ORGANIZATION], :name => line[ENVIRONMENT]),
|
215
|
-
'content_view_id' => katello_contentview(line[ORGANIZATION], :name => line[CONTENTVIEW]),
|
216
|
-
'facts' => facts(name, line),
|
217
|
-
'installed_products' => products(line),
|
218
|
-
'service_level' => line[SLA],
|
219
|
-
'type' => 'system'
|
220
|
-
})['id']
|
221
|
-
@existing[name] = host_id
|
145
|
+
if option_itemized_subscriptions?
|
146
|
+
update_itemized_subscriptions(name, line)
|
222
147
|
else
|
223
|
-
|
224
|
-
# Bug #13849 - updating a host's facet should not require the facet id to be included in facet params
|
225
|
-
# http://projects.theforeman.org/issues/13849
|
226
|
-
print(_("Updating content host '%{name}'...") % {:name => name}) if option_verbose?
|
227
|
-
host_id = @api.resource(:hosts).call(:update, {
|
228
|
-
'id' => @existing[name][:host],
|
229
|
-
'host' => {
|
230
|
-
'name' => name,
|
231
|
-
'content_facet_attributes' => {
|
232
|
-
'id' => @existing[name][:content],
|
233
|
-
'lifecycle_environment_id' => lifecycle_environment(line[ORGANIZATION], :name => line[ENVIRONMENT]),
|
234
|
-
'content_view_id' => katello_contentview(line[ORGANIZATION], :name => line[CONTENTVIEW])
|
235
|
-
},
|
236
|
-
'subscription_facet_attributes' => {
|
237
|
-
'id' => @existing[name][:subscription],
|
238
|
-
'facts' => facts(name, line),
|
239
|
-
# TODO: PUT /hosts subscription_facet_attributes missing "installed_products"
|
240
|
-
# http://projects.theforeman.org/issues/13854
|
241
|
-
#'installed_products' => products(line),
|
242
|
-
'service_level' => line[SLA]
|
243
|
-
}
|
244
|
-
}
|
245
|
-
})['host_id']
|
148
|
+
update_or_create(name, line)
|
246
149
|
end
|
150
|
+
end
|
151
|
+
end
|
247
152
|
|
248
|
-
|
249
|
-
raise "Content host '#{line[HOST]}' not found" if !@existing[line[HOST]]
|
250
|
-
@hypervisor_guests[@existing[line[HOST]]] ||= []
|
251
|
-
@hypervisor_guests[@existing[line[HOST]]] << @existing[name]
|
252
|
-
end
|
153
|
+
private
|
253
154
|
|
254
|
-
|
255
|
-
|
256
|
-
update_subscriptions(host_id, line)
|
155
|
+
def update_itemized_subscriptions(name, line)
|
156
|
+
raise _("Content host '%{name}' must already exist with --itemized-subscriptions") % {:name => name} unless @existing.include? name
|
257
157
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
158
|
+
print(_("Updating subscriptions for content host '%{name}'...") % {:name => name}) if option_verbose?
|
159
|
+
host = @api.resource(:hosts).call(:show, {:id => @existing[name]})
|
160
|
+
update_subscriptions(host, line, false)
|
161
|
+
puts _('done') if option_verbose?
|
262
162
|
end
|
263
163
|
|
264
|
-
|
164
|
+
def update_or_create(name, line)
|
165
|
+
if !@existing.include? name
|
166
|
+
print(_("Creating content host '%{name}'...") % {:name => name}) if option_verbose?
|
167
|
+
params = {
|
168
|
+
'name' => name,
|
169
|
+
'facts' => facts(name, line),
|
170
|
+
'lifecycle_environment_id' => lifecycle_environment(line[ORGANIZATION], :name => line[ENVIRONMENT]),
|
171
|
+
'content_view_id' => katello_contentview(line[ORGANIZATION], :name => line[CONTENTVIEW])
|
172
|
+
}
|
173
|
+
params['installed_products'] = products(line) if line[PRODUCTS]
|
174
|
+
params['service_level'] = line[SLA] if line[SLA]
|
175
|
+
host = @api.resource(:host_subscriptions).call(:create, params)
|
176
|
+
@existing[name] = host['id']
|
177
|
+
else
|
178
|
+
print(_("Updating content host '%{name}'...") % {:name => name}) if option_verbose?
|
179
|
+
params = {
|
180
|
+
'id' => @existing[name],
|
181
|
+
'host' => {
|
182
|
+
'content_facet_attributes' => {
|
183
|
+
'lifecycle_environment_id' => lifecycle_environment(line[ORGANIZATION], :name => line[ENVIRONMENT]),
|
184
|
+
'content_view_id' => katello_contentview(line[ORGANIZATION], :name => line[CONTENTVIEW])
|
185
|
+
},
|
186
|
+
'subscription_facet_attributes' => {
|
187
|
+
'facts' => facts(name, line),
|
188
|
+
'installed_products' => products(line),
|
189
|
+
'service_level' => line[SLA]
|
190
|
+
}
|
191
|
+
}
|
192
|
+
}
|
193
|
+
host = @api.resource(:hosts).call(:update, params)
|
194
|
+
end
|
195
|
+
|
196
|
+
if line[VIRTUAL] == 'Yes' && line[HOST]
|
197
|
+
raise "Content host '#{line[HOST]}' not found" if !@existing[line[HOST]]
|
198
|
+
@hypervisor_guests[@existing[line[HOST]]] ||= []
|
199
|
+
@hypervisor_guests[@existing[line[HOST]]] << "#{line[ORGANIZATION]}/#{name}"
|
200
|
+
end
|
201
|
+
|
202
|
+
update_host_collections(host, line)
|
203
|
+
update_subscriptions(host, line, true)
|
204
|
+
|
205
|
+
puts _('done') if option_verbose?
|
206
|
+
end
|
265
207
|
|
266
208
|
def facts(name, line)
|
267
209
|
facts = {}
|
@@ -278,17 +220,15 @@ module HammerCLICsv
|
|
278
220
|
facts
|
279
221
|
end
|
280
222
|
|
281
|
-
def
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
})
|
291
|
-
end
|
223
|
+
def update_host_collections(host, line)
|
224
|
+
# TODO: http://projects.theforeman.org/issues/16234
|
225
|
+
# return nil if line[HOSTCOLLECTIONS].nil? || line[HOSTCOLLECTIONS].empty?
|
226
|
+
# CSV.parse_line(line[HOSTCOLLECTIONS]).each do |hostcollection_name|
|
227
|
+
# @api.resource(:host_collections).call(:add_hosts, {
|
228
|
+
# 'id' => katello_hostcollection(line[ORGANIZATION], :name => hostcollection_name),
|
229
|
+
# 'host_ids' => [host['id']]
|
230
|
+
# })
|
231
|
+
# end
|
292
232
|
end
|
293
233
|
|
294
234
|
def os_name_version(operatingsystem)
|
@@ -305,44 +245,186 @@ module HammerCLICsv
|
|
305
245
|
|
306
246
|
def products(line)
|
307
247
|
return nil if !line[PRODUCTS]
|
308
|
-
|
248
|
+
CSV.parse_line(line[PRODUCTS]).collect do |product_details|
|
309
249
|
product = {}
|
310
|
-
|
311
|
-
# to allow underscore product_id here
|
312
|
-
(product['productId'], product['productName']) = product_details.split('|')
|
250
|
+
(product['product_id'], product['product_name']) = product_details.split('|')
|
313
251
|
product['arch'] = line[ARCHITECTURE]
|
314
252
|
product['version'] = os_name_version(line[OPERATINGSYSTEM])[1]
|
315
253
|
product
|
316
254
|
end
|
317
|
-
products
|
318
255
|
end
|
319
256
|
|
320
|
-
def update_subscriptions(
|
257
|
+
def update_subscriptions(host, line, remove_existing)
|
321
258
|
existing_subscriptions = @api.resource(:host_subscriptions).call(:index, {
|
322
|
-
'host_id' =>
|
259
|
+
'host_id' => host['id']
|
323
260
|
})['results']
|
324
|
-
if existing_subscriptions.length != 0
|
261
|
+
if remove_existing && existing_subscriptions.length != 0
|
262
|
+
existing_subscriptions.map! do |existing_subscription|
|
263
|
+
{:id => existing_subscription['id'], :quantity => existing_subscription['quantity_consumed']}
|
264
|
+
end
|
325
265
|
@api.resource(:host_subscriptions).call(:remove_subscriptions, {
|
326
|
-
'host_id' =>
|
266
|
+
'host_id' => host['id'],
|
327
267
|
'subscriptions' => existing_subscriptions
|
328
268
|
})
|
269
|
+
existing_subscriptions = []
|
270
|
+
end
|
271
|
+
|
272
|
+
if line[Utils::Subscriptions::SUBS_NAME].nil? && line[Utils::Subscriptions::SUBS_SKU].nil?
|
273
|
+
all_in_one_subscription(host, existing_subscriptions, line)
|
274
|
+
else
|
275
|
+
single_subscription(host, existing_subscriptions, line)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def single_subscription(host, existing_subscriptions, line)
|
280
|
+
already_attached = false
|
281
|
+
if line[Utils::Subscriptions::SUBS_SKU]
|
282
|
+
already_attached = existing_subscriptions.detect do |subscription|
|
283
|
+
line[Utils::Subscriptions::SUBS_SKU] == subscription['product_id']
|
284
|
+
end
|
285
|
+
elsif line[Utils::Subscriptions::SUBS_NAME]
|
286
|
+
already_attached = existing_subscriptions.detect do |subscription|
|
287
|
+
line[Utils::Subscriptions::SUBS_NAME] == subscription['name']
|
288
|
+
end
|
289
|
+
end
|
290
|
+
if already_attached
|
291
|
+
print _(" '%{name}' already attached...") % {:name => already_attached['name']}
|
292
|
+
return
|
329
293
|
end
|
330
294
|
|
295
|
+
available_subscriptions = @api.resource(:subscriptions).call(:index, {
|
296
|
+
'organization_id' => host['organization_id'],
|
297
|
+
'host_id' => host['id'],
|
298
|
+
'available_for' => 'host',
|
299
|
+
'match_host' => true
|
300
|
+
})['results']
|
301
|
+
|
302
|
+
matches = matches_by_sku_and_name([], line, available_subscriptions)
|
303
|
+
matches = matches_by_type(matches, line)
|
304
|
+
matches = matches_by_account(matches, line)
|
305
|
+
matches = matches_by_contract(matches, line)
|
306
|
+
matches = matches_by_quantity(matches, line)
|
307
|
+
|
308
|
+
raise _("No matching subscriptions") if matches.empty?
|
309
|
+
|
310
|
+
match = matches[0]
|
311
|
+
print _(" attaching '%{name}'...") % {:name => match['name']} if option_verbose?
|
312
|
+
|
313
|
+
@api.resource(:host_subscriptions).call(:add_subscriptions, {
|
314
|
+
'host_id' => host['id'],
|
315
|
+
'subscriptions' => existing_subscriptions + [match]
|
316
|
+
})
|
317
|
+
end
|
318
|
+
|
319
|
+
def all_in_one_subscription(host, existing_subscriptions, line)
|
331
320
|
return if line[SUBSCRIPTIONS].nil? || line[SUBSCRIPTIONS].empty?
|
332
321
|
|
333
322
|
subscriptions = CSV.parse_line(line[SUBSCRIPTIONS], {:skip_blanks => true}).collect do |details|
|
334
|
-
(amount, sku, name) = details
|
323
|
+
(amount, sku, name, contract, account) = split_subscription_details(details)
|
335
324
|
{
|
336
|
-
:id =>
|
325
|
+
:id => get_subscription(line[ORGANIZATION], :name => name, :contract => contract,
|
326
|
+
:account => account),
|
337
327
|
:quantity => (amount.nil? || amount.empty? || amount == 'Automatic') ? 0 : amount.to_i
|
338
328
|
}
|
339
329
|
end
|
340
330
|
|
341
331
|
@api.resource(:host_subscriptions).call(:add_subscriptions, {
|
342
|
-
'host_id' =>
|
332
|
+
'host_id' => host['id'],
|
343
333
|
'subscriptions' => subscriptions
|
344
334
|
})
|
345
335
|
end
|
336
|
+
|
337
|
+
def update_existing(line)
|
338
|
+
if !@existing[line[ORGANIZATION]]
|
339
|
+
@existing[line[ORGANIZATION]] = true
|
340
|
+
# Fetching all content hosts can be too slow and times so page
|
341
|
+
# http://projects.theforeman.org/issues/6307
|
342
|
+
total = @api.resource(:hosts).call(:index, {
|
343
|
+
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
344
|
+
'per_page' => 1
|
345
|
+
})['total'].to_i
|
346
|
+
(total / 20 + 1).to_i.times do |page|
|
347
|
+
@api.resource(:hosts).call(:index, {
|
348
|
+
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
349
|
+
'page' => page + 1,
|
350
|
+
'per_page' => 20
|
351
|
+
})['results'].each do |host|
|
352
|
+
if host['subscription_facet_attributes']
|
353
|
+
@existing[host['name']] = host['id']
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def iterate_hosts(csv)
|
361
|
+
hypervisors = []
|
362
|
+
hosts = []
|
363
|
+
@api.resource(:organizations).call(:index, {:per_page => 999999})['results'].each do |organization|
|
364
|
+
next if option_organization && organization['name'] != option_organization
|
365
|
+
|
366
|
+
@api.resource(:hosts).call(:index, {
|
367
|
+
'per_page' => 999999,
|
368
|
+
'organization_id' => foreman_organization(:name => organization['name'])
|
369
|
+
})['results'].each do |host|
|
370
|
+
host = @api.resource(:hosts).call(:show, {
|
371
|
+
'id' => host['id']
|
372
|
+
})
|
373
|
+
host['facts'] ||= {}
|
374
|
+
if host['subscription_facet_attributes']['virtual_guests'].empty?
|
375
|
+
hosts.push(host)
|
376
|
+
else
|
377
|
+
hypervisors.push(host)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
hypervisors.each do |host|
|
382
|
+
yield host
|
383
|
+
end
|
384
|
+
hosts.each do |host|
|
385
|
+
yield host
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
def shared_headers
|
390
|
+
[NAME, ORGANIZATION, ENVIRONMENT, CONTENTVIEW, HOSTCOLLECTIONS, VIRTUAL, HOST,
|
391
|
+
OPERATINGSYSTEM, ARCHITECTURE, SOCKETS, RAM, CORES, SLA, PRODUCTS]
|
392
|
+
end
|
393
|
+
|
394
|
+
def shared_columns(host)
|
395
|
+
name = host['name']
|
396
|
+
organization_name = host['organization_name']
|
397
|
+
if host['content_facet_attributes']
|
398
|
+
environment = host['content_facet_attributes']['lifecycle_environment']['name']
|
399
|
+
contentview = host['content_facet_attributes']['content_view']['name']
|
400
|
+
hostcollections = export_column(host['content_facet_attributes'], 'host_collections', 'name')
|
401
|
+
else
|
402
|
+
environment = nil
|
403
|
+
contentview = nil
|
404
|
+
hostcollections = nil
|
405
|
+
end
|
406
|
+
if host['subscription_facet_attributes']
|
407
|
+
hypervisor_host = host['subscription_facet_attributes']['virtual_host'].nil? ? nil : host['subscription_facet_attributes']['virtual_host']['name']
|
408
|
+
products = export_column(host['subscription_facet_attributes'], 'installed_products') do |product|
|
409
|
+
"#{product['productId']}|#{product['productName']}"
|
410
|
+
end
|
411
|
+
else
|
412
|
+
hypervisor_host = nil
|
413
|
+
products = nil
|
414
|
+
end
|
415
|
+
virtual = host['facts']['virt::is_guest'] == 'true' ? 'Yes' : 'No'
|
416
|
+
operatingsystem = host['facts']['distribution::name'] if host['facts']['distribution::name']
|
417
|
+
operatingsystem += " #{host['facts']['distribution::version']}" if host['facts']['distribution::version']
|
418
|
+
architecture = host['facts']['uname::machine']
|
419
|
+
sockets = host['facts']['cpu::cpu_socket(s)']
|
420
|
+
ram = host['facts']['memory::memtotal']
|
421
|
+
cores = host['facts']['cpu::core(s)_per_socket'] || 1
|
422
|
+
sla = ''
|
423
|
+
|
424
|
+
[name, organization_name, environment, contentview, hostcollections, virtual, hypervisor_host,
|
425
|
+
operatingsystem, architecture, sockets, ram, cores, sla, products]
|
426
|
+
end
|
427
|
+
|
346
428
|
end
|
347
429
|
end
|
348
430
|
end
|