Project

General

Profile

Download (10.4 KB) Statistics
| Branch: | Tag: | Revision:

hammer-cli-csv / lib / hammer_cli_csv / content_hosts.rb @ a77acc4a

1
# Copyright 2013-2014 Red Hat, Inc.
2
#
3
# This software is licensed to you under the GNU General Public
4
# License as published by the Free Software Foundation; either version
5
# 2 of the License (GPLv2) or (at your option) any later version.
6
# There is NO WARRANTY for this software, express or implied,
7
# including the implied warranties of MERCHANTABILITY,
8
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
9
# have received a copy of GPLv2 along with this software; if not, see
10
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11

    
12
#
13
# -= Systems CSV =-
14
#
15
# Columns
16
#   Name
17
#     - System name
18
#     - May contain '%d' which will be replaced with current iteration number of Count
19
#     - eg. "os%d" -> "os1"
20
#   Count
21
#     - Number of times to iterate on this line of the CSV file
22
#   MAC Address
23
#     - MAC address
24
#     - May contain '%d' which will be replaced with current iteration number of Count
25
#     - eg. "FF:FF:FF:FF:FF:%02x" -> "FF:FF:FF:FF:FF:0A"
26
#     - Warning: be sure to keep count below 255 or MAC hex will exceed limit
27
#
28

    
29
require 'hammer_cli'
30
require 'json'
31
require 'csv'
32
require 'uri'
33

    
34
module HammerCLICsv
35
  class CsvCommand
36
    class ContentHostsCommand < BaseCommand
37
      command_name 'content-hosts'
38
      desc         'import or export content hosts'
39

    
40
      ORGANIZATION = 'Organization'
41
      ENVIRONMENT = 'Environment'
42
      CONTENTVIEW = 'Content View'
43
      HOSTCOLLECTIONS = 'Host Collections'
44
      VIRTUAL = 'Virtual'
45
      HOST = 'Host'
46
      OPERATINGSYSTEM = 'OS'
47
      ARCHITECTURE = 'Arch'
48
      SOCKETS = 'Sockets'
49
      RAM = 'RAM'
50
      CORES = 'Cores'
51
      SLA = 'SLA'
52
      PRODUCTS = 'Products'
53
      SUBSCRIPTIONS = 'Subscriptions'
54

    
55
      def export
56
        CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => false}) do |csv|
57
          csv << [NAME, COUNT, ORGANIZATION, ENVIRONMENT, CONTENTVIEW, HOSTCOLLECTIONS, VIRTUAL, HOST,
58
                  OPERATINGSYSTEM, ARCHITECTURE, SOCKETS, RAM, CORES, SLA, PRODUCTS, SUBSCRIPTIONS]
59
          @api.resource(:organizations).call(:index, {:per_page => 999999})['results'].each do |organization|
60
            @api.resource(:systems).call(:index, {
61
                                  'per_page' => 999999,
62
                                  'organization_id' => foreman_organization(:name => organization['name'])
63
                                 })['results'].each do |system|
64
              system = @api.resource(:systems).call(:show, {
65
                                            'id' => system['uuid'],
66
                                            'fields' => 'full'
67
                                          })
68

    
69
              name = system['name']
70
              count = 1
71
              organization_name = organization['name']
72
              environment = system['environment']['label']
73
              contentview = system['content_view']['name']
74
              hostcollections = CSV.generate do |column|
75
                column << system['systemGroups'].collect do |hostcollection|
76
                  hostcollection['name']
77
                end
78
              end
79
              hostcollections.delete!("\n")
80
              virtual = system['facts']['virt.is_guest'] == 'true' ? 'Yes' : 'No'
81
              host = system['host']
82
              operatingsystem = "#{system['facts']['distribution.name']} " if system['facts']['distribution.name']
83
              operatingsystem += system['facts']['distribution.version'] if system['facts']['distribution.version']
84
              architecture = system['facts']['uname.machine']
85
              sockets = system['facts']['cpu.cpu_socket(s)']
86
              ram = system['facts']['memory.memtotal']
87
              cores = system['facts']['cpu.core(s)_per_socket']
88
              sla = ''
89
              products = CSV.generate do |column|
90
                column << system['installedProducts'].collect do |product|
91
                  "#{product['productId']}|#{product['productName']}"
92
                end
93
              end
94
              products.delete!("\n")
95
              subscriptions = CSV.generate do |column|
96
                column << @api.resource(:subscriptions).call(:index, {
97
                                                      'system_id' => system['uuid']
98
                                                    })['results'].collect do |subscription|
99
                  "#{subscription['product_id']}|#{subscription['product_name']}"
100
                end
101
              end
102
              subscriptions.delete!("\n")
103
              csv << [name, count, organization_name, environment, contentview, hostcollections, virtual, host,
104
                      operatingsystem, architecture, sockets, ram, cores, sla, products, subscriptions]
105
            end
106
          end
107
        end
108
      end
109

    
110
      def import
111
        @existing = {}
112
        @host_guests = {}
113

    
114
        thread_import do |line|
115
          create_systems_from_csv(line)
116
        end
117

    
118
        print 'Updating host and guest associations...' if option_verbose?
119
        @host_guests.each do |host_id, guest_ids|
120
          @api.resource(:systems).call(:update, {
121
                                 'id' => host_id,
122
                                 'guest_ids' => guest_ids
123
                               })
124
        end
125
        puts 'done' if option_verbose?
126
      end
127

    
128
      def create_systems_from_csv(line)
129
        if !@existing[line[ORGANIZATION]]
130
          @existing[line[ORGANIZATION]] = {}
131
          @api.resource(:systems).call(:index, {
132
                                'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
133
                                'page_size' => 999999})['results'].each do |system|
134
            @existing[line[ORGANIZATION]][system['name']] = system['uuid'] if system
135
          end
136
        end
137

    
138
        line[COUNT].to_i.times do |number|
139
          name = namify(line[NAME], number)
140

    
141
          # TODO w/ @daviddavis p-r
142
          #subscriptions(line).each do |subscription|
143
          #  katello_subscription(line[ORGANIZATION], :name => subscription[:number])
144
          #end
145

    
146
          if !@existing[line[ORGANIZATION]].include? name
147
            print "Creating system '#{name}'..." if option_verbose?
148
            system_id = @api.resource(:systems).call(:create, {
149
                                                       'name' => name,
150
                                                       'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
151
                                                       'environment_id' => katello_environment(line[ORGANIZATION], :name => line[ENVIRONMENT]),
152
                                                       'content_view_id' => katello_contentview(line[ORGANIZATION], :name => line[CONTENTVIEW]),
153
                                                       'facts' => facts(name, line),
154
                                                       'installed_products' => products(line),
155
                                                       'type' => 'system'
156
                                                     })['uuid']
157
            @existing[line[ORGANIZATION]][name] = system_id
158
          else
159
            print "Updating system '#{name}'..." if option_verbose?
160
            system_id = @api.resource(:systems).call(:update, {
161
                                                       'id' => @existing[line[ORGANIZATION]][name],
162
                                                       'system' => {
163
                                                         'name' => name,
164
                                                         'environment_id' => katello_environment(line[ORGANIZATION], :name => line[ENVIRONMENT]),
165
                                                         'content_view_id' => katello_contentview(line[ORGANIZATION], :name => line[CONTENTVIEW]),
166
                                                         'facts' => facts(name, line),
167
                                                         'installed_products' => products(line)
168
                                                       }
169
                                                     })['uuid']
170
          end
171

    
172
          if line[VIRTUAL] == 'Yes' && line[HOST]
173
            raise "Host system '#{line[HOST]}' not found" if !@existing[line[ORGANIZATION]][line[HOST]]
174
            @host_guests[@existing[line[ORGANIZATION]][line[HOST]]] ||= []
175
            @host_guests[@existing[line[ORGANIZATION]][line[HOST]]] << system_id
176
          end
177

    
178
          set_host_collections(system_id, line)
179

    
180
          puts 'done' if option_verbose?
181
        end
182
      rescue RuntimeError => e
183
        raise "#{e}\n       #{line}"
184
      end
185

    
186
      private
187

    
188
      def facts(name, line)
189
        facts = {}
190
        facts['cpu.core(s)_per_socket'] = line[CORES]
191
        facts['cpu.cpu_socket(s)'] = line[SOCKETS]
192
        facts['memory.memtotal'] = line[RAM]
193
        facts['uname.machine'] = line[ARCHITECTURE]
194
        if line[OPERATINGSYSTEM].index(' ')
195
          (facts['distribution.name'], facts['distribution.version']) = line[OPERATINGSYSTEM].split(' ')
196
        else
197
          (facts['distribution.name'], facts['distribution.version']) = ['RHEL', line[OPERATINGSYSTEM]]
198
        end
199
        facts['virt.is_guest'] = line[VIRTUAL] == 'Yes' ? true : false
200
        facts['virt.uuid'] = "#{line[ORGANIZATION]}/#{name}" if facts['virt.is_guest']
201
        facts
202
      end
203

    
204
      def set_host_collections(system_id, line)
205
        CSV.parse_line(line[HOSTCOLLECTIONS]).each do |hostcollection_name|
206
          @api.resource(:host_collections).call(:add_systems, {
207
                                                  'id' => katello_hostcollection(line[ORGANIZATION], :name => hostcollection_name),
208
                                                  'system_ids' => [system_id]
209
                                                })
210
        end
211
      end
212

    
213
      def products(line)
214
        return nil if !line[PRODUCTS]
215
        products = CSV.parse_line(line[PRODUCTS]).collect do |product_details|
216
          product = {}
217
          # TODO: these get passed straight through to candlepin; probably would be better to process in server
218
          #       to allow underscore product_id here
219
          (product['productId'], product['productName']) = product_details.split('|')
220
          product
221
        end
222
        products
223
      end
224

    
225
      def subscriptions(line)
226
        return nil if !line[SUBSCRIPTIONS]
227
        subscriptions = CSV.parse_line(line[SUBSCRIPTIONS]).collect do |subscription_details|
228
          subscription = {}
229
          (subscription[:number], subscription[:name]) = subscription_details.split('|')
230
          subscription
231
        end
232
        subscriptions
233
      end
234
    end
235
  end
236
end