Project

General

Profile

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

hammer-cli-csv / lib / hammer_cli_csv / systems.rb @ 8e5eda06

1
# Copyright (c) 2013-2014 Red Hat
2
#
3
# MIT License
4
#
5
# Permission is hereby granted, free of charge, to any person obtaining
6
# a copy of this software and associated documentation files (the
7
# "Software"), to deal in the Software without restriction, including
8
# without limitation the rights to use, copy, modify, merge, publish,
9
# distribute, sublicense, and/or sell copies of the Software, and to
10
# permit persons to whom the Software is furnished to do so, subject to
11
# the following conditions:
12
#
13
# The above copyright notice and this permission notice shall be
14
# included in all copies or substantial portions of the Software.
15
#
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
#
24
#
25
# -= Systems CSV =-
26
#
27
# Columns
28
#   Name
29
#     - System name
30
#     - May contain '%d' which will be replaced with current iteration number of Count
31
#     - eg. "os%d" -> "os1"
32
#   Count
33
#     - Number of times to iterate on this line of the CSV file
34
#   MAC Address
35
#     - MAC address
36
#     - May contain '%d' which will be replaced with current iteration number of Count
37
#     - eg. "FF:FF:FF:FF:FF:%02x" -> "FF:FF:FF:FF:FF:0A"
38
#     - Warning: be sure to keep count below 255 or MAC hex will exceed limit
39
#
40

    
41
require 'hammer_cli'
42
require 'katello_api'
43
require 'foreman_api'
44
require 'json'
45
require 'csv'
46
require 'uri'
47

    
48
module HammerCLICsv
49
  class SystemsCommand < BaseCommand
50

    
51
    ORGANIZATION = 'Organization'
52
    ENVIRONMENT = 'Environment'
53
    CONTENTVIEW = 'Content View'
54
    SYSTEMGROUPS = 'System Groups'
55
    VIRTUAL = 'Virtual'
56
    HOST = 'Host'
57
    OPERATINGSYSTEM = 'OS'
58
    ARCHITECTURE = 'Arch'
59
    SOCKETS = 'Sockets'
60
    RAM = 'RAM'
61
    CORES = 'Cores'
62
    SLA = 'SLA'
63
    PRODUCTS = 'Products'
64
    SUBSCRIPTIONS = 'Subscriptions'
65

    
66
    def export
67
      CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => false}) do |csv|
68
        csv << [NAME, COUNT, ORGANIZATION, ENVIRONMENT, CONTENTVIEW, SYSTEMGROUPS, VIRTUAL, HOST,
69
               OPERATINGSYSTEM, ARCHITECTURE, SOCKETS, RAM, CORES, SLA, PRODUCTS, SUBSCRIPTIONS]
70
        @k_organization_api.index({:per_page => 999999})[0]['results'].each do |organization|
71
          @k_system_api.index({
72
                                'per_page' => 999999,
73
                                'organization_id' => katello_organization(:name => organization['name'])
74
                               })[0]['results'].each do |system|
75
            system = @k_system_api.show({
76
                                          'id' => system['uuid'],
77
                                          'fields' => 'full'
78
                                        })[0]
79

    
80
            name = system['name']
81
            count = 1
82
            organization_name = organization['name']
83
            environment = system['environment']['label']
84
            contentview = system['content_view']['name']
85
            systemgroups = CSV.generate do |column|
86
              column << system['systemGroups'].collect do |systemgroup|
87
                systemgroup['name']
88
              end
89
            end.delete!("\n")
90
            virtual = system['facts']['virt.is_guest'] == 'true' ? 'Yes' : 'No'
91
            host = system['host']
92
            operatingsystem = "#{system['facts']['distribution.name']} " if system['facts']['distribution.name']
93
            operatingsystem += system['facts']['distribution.version'] if system['facts']['distribution.version']
94
            architecture = system['facts']['uname.machine']
95
            sockets = system['facts']['cpu.cpu_socket(s)']
96
            ram = system['facts']['memory.memtotal']
97
            cores = system['facts']['cpu.core(s)_per_socket']
98
            sla = ""
99
            products = CSV.generate do |column|
100
              column << system['installedProducts'].collect do |product|
101
                "#{product['productId']}|#{product['productName']}"
102
              end
103
            end.delete!("\n")
104
            subscriptions = CSV.generate do |column|
105
              column << @k_subscription_api.index({
106
                                                    'system_id' => system['uuid']
107
                                                  })[0]['results'].collect do |subscription|
108
                "#{subscription['product_id']}|#{subscription['product_name']}"
109
              end
110
            end.delete!("\n")
111
            csv << [name, count, organization_name, environment, contentview, systemgroups, virtual, host,
112
                    operatingsystem, architecture, sockets, ram, cores, sla, products, subscriptions]
113
          end
114
        end
115
      end
116
    end
117

    
118
    def import
119
      @existing = {}
120
      @host_guests = {}
121

    
122
      thread_import do |line|
123
        create_systems_from_csv(line)
124
      end
125

    
126
      print "Updating host and guest associations..." if option_verbose?
127
      @host_guests.each do |host_id, guest_ids|
128
        @k_system_api.update({
129
                               'id' => host_id,
130
                               'guest_ids' => guest_ids
131
                             })
132
      end
133
      puts "done" if option_verbose?
134
    end
135

    
136
    def create_systems_from_csv(line)
137
      if !@existing[line[ORGANIZATION]]
138
        @existing[line[ORGANIZATION]] = {}
139
        @k_system_api.index({
140
                              'organization_id' => katello_organization(:name => line[ORGANIZATION]),
141
                              'page_size' => 999999})[0]['results'].each do |system|
142
          @existing[line[ORGANIZATION]][system['name']] = system['uuid'] if system
143
        end
144
      end
145

    
146
      line[COUNT].to_i.times do |number|
147
        name = namify(line[NAME], number)
148

    
149
        # TODO w/ @daviddavis p-r
150
        #subscriptions(line).each do |subscription|
151
        #  katello_subscription(line[ORGANIZATION], :name => subscription[:number])
152
        #end
153

    
154
        if !@existing[line[ORGANIZATION]].include? name
155
          print "Creating system '#{name}'..." if option_verbose?
156
          system_id = @k_system_api.create({
157
                                 'name' => name,
158
                                 'organization_id' => katello_organization(:name => line[ORGANIZATION]),
159
                                 'environment_id' => katello_environment(line[ORGANIZATION], :name => line[ENVIRONMENT]),
160
                                 'content_view_id' => katello_contentview(line[ORGANIZATION], :name => line[CONTENTVIEW]),
161
                                 'facts' => facts(line),
162
                                 'installed_products' => products(line),
163
                                 'type' => 'system'
164
                               })[0]['uuid']
165
          @existing[line[ORGANIZATION]][name] = system_id
166
        else
167
          print "Updating system '#{name}'..." if option_verbose?
168
          system_id = @k_system_api.update({
169
                                 'id' => @existing[line[ORGANIZATION]][name],
170
                                 'name' => name,
171
                                 'environment_id' => katello_environment(line[ORGANIZATION], :name => line[ENVIRONMENT]),
172
                                 'content_view_id' => katello_contentview(line[ORGANIZATION], :name => line[CONTENTVIEW]),
173
                                 'facts' => facts(line),
174
                                 'installed_products' => products(line)
175
                               })[0]['uuid']
176
        end
177

    
178
        if line[VIRTUAL] == 'Yes' && line[HOST]
179
          raise "Host system '#{line[HOST]}' not found" if !@existing[line[ORGANIZATION]][line[HOST]]
180
          @host_guests[@existing[line[ORGANIZATION]][line[HOST]]] ||= []
181
          @host_guests[@existing[line[ORGANIZATION]][line[HOST]]] << system_id
182
        end
183

    
184
        set_system_groups(system_id, line)
185

    
186
        puts "done" if option_verbose?
187
      end
188
    rescue RuntimeError => e
189
      raise "#{e}\n       #{line}"
190
    end
191

    
192
    private
193

    
194
    def facts(line)
195
      facts = {}
196
      facts['cpu.core(s)_per_socket'] = line[CORES]
197
      facts['cpu.cpu_socket(s)'] = line[SOCKETS]
198
      facts['memory.memtotal'] = line[RAM]
199
      facts['uname.machine'] = line[ARCHITECTURE]
200
      if line[OPERATINGSYSTEM].index(' ')
201
        (facts['distribution.name'], facts['distribution.version']) = line[OPERATINGSYSTEM].split(' ')
202
      else
203
        (facts['distribution.name'], facts['distribution.version']) = ['RHEL', line[OPERATINGSYSTEM]]
204
      end
205
      facts['virt.is_guest'] = line[VIRTUAL] == 'Yes' ? true : false
206
      facts
207
    end
208

    
209
    def set_system_groups(system_id, line)
210
      CSV.parse_line(line[SYSTEMGROUPS]).each do |systemgroup_name|
211
        @k_systemgroup_api.add_systems({
212
                                         'id' => katello_systemgroup(line[ORGANIZATION], :name => systemgroup_name),
213
                                         'system_ids' => [system_id]
214
                                       })
215
      end
216
    end
217

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

    
229
    def subscriptions(line)
230
      subscriptions = CSV.parse_line(line[SUBSCRIPTIONS]).collect do |subscription_details|
231
        subscription = {}
232
        (subscription[:number], subscription[:name]) = subscription_details.split('|')
233
        subscription
234
      end
235
      subscriptions
236
    end
237

    
238
  end
239

    
240
  HammerCLI::MainCommand.subcommand("csv:systems", "import/export systems", HammerCLICsv::SystemsCommand)
241
end