Class: Chef::Knife::HmcServerCreate

Inherits:
Chef::Knife show all
Includes:
HmcBase
Defined in:
lib/chef/knife/hmc_server_create.rb

Instance Method Summary collapse

Methods included from HmcBase

#get_config, included, #tcp_ssh_alive, #validate, #validate!

Instance Method Details

#bootstrap_for_nodeObject

Bootstrapping a Chef node using all Chef faculties TO-DO: fix up the body of this once normal bootstrap works on AIX nodes.



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/chef/knife/hmc_server_create.rb', line 342

def bootstrap_for_node
  bootstrap = Chef::Knife::Bootstrap.new
  bootstrap.name_args = [config[:fqdn]]
  bootstrap.config[:run_list] = get_config(:run_list).split(/[\s,]+/)
  bootstrap.config[:secret_file] = get_config(:secret_file)
  bootstrap.config[:hint] = get_config(:hint)
  bootstrap.config[:ssh_user] = get_config(:ssh_user)
  bootstrap.config[:ssh_password] = get_config(:ssh_password)
  bootstrap.config[:ssh_port] = get_config(:ssh_port)
  bootstrap.config[:identity_file] = get_config(:identity_file)
  bootstrap.config[:chef_node_name] = get_config(:chef_node_name)
  bootstrap.config[:prerelease] = get_config(:prerelease)
  bootstrap.config[:bootstrap_version] = get_config(:bootstrap_version)
  bootstrap.config[:distro] = get_config(:distro)
  bootstrap.config[:use_sudo] = true unless get_config(:ssh_user) == 'root'
  bootstrap.config[:template_file] = get_config(:template_file)
  bootstrap.config[:environment] = get_config(:environment)
  bootstrap.config[:first_boot_attributes] = get_config(:first_boot_attributes)
  bootstrap.config[:log_level] = get_config(:log_level)
  # may be needed for vpc_mode
  bootstrap.config[:no_host_key_verify] = get_config(:no_host_key_verify)
  bootstrap
end

#manual_bootstrap_for_nodeObject

Manually execute the Chef bootstrap of an AIX server



255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/chef/knife/hmc_server_create.rb', line 255

def manual_bootstrap_for_node
  validate!([:bootstrap_pass])

  #Where the validation pem and chef-client exist on
  #the chef workstation this is run from
  validation_pem_path = Chef::Config[:validation_key]
  puts "Using client key #{validation_pem_path}"
  chef_client_path = Chef::Config[:knife][:chef_client_aix_path]
  puts "Using chef-client located in #{chef_client_path}"

  if validation_pem_path.nil? or chef_client_path.nil?
    puts "No client validation pem or chef-client installable specified in knife.rb. Skipping Chef Bootstrap..."
    return nil
  end

  #Where to place these files on the target server
  remote_chef_client_path = "/tmp/2014-02-06-chef.11.10.0.0.bff"
  remote_validation_pem_path = "/etc/chef/validation.pem"

  #For some reason, Net::SSH and Net::SCP only work on
  #AIX using :kex => "diffie-hellman-group1-sha1" and
  # :encryption => ["blowfish-cbc", "3des-cbc"]
  # :paranoid => false (avoids host key verification)
  Net::SSH.start(get_config(:ip_address), 
                 get_config(:bootstrap_user) || "root", 
                 :password => get_config(:bootstrap_pass), 
                 :kex => "diffie-hellman-group1-sha1",
                 :encryption => ["blowfish-cbc", "3des-cbc"],
                 :paranoid => false) do |ssh|     

    #Copy the chef-client .bff file to the client machine in /tmp
    puts "Copying chef client binary to client"
    ssh.scp.upload!(chef_client_path, remote_chef_client_path)

    #Run the install command
    puts "Running chef client install"
    output = ssh.exec!("installp -aYFq -d #{remote_chef_client_path} chef")
    Chef::Log.debug("Chef Client install output:\n#{output}")

    #Run the configure client command
    puts "Running knife configure client command"
    output = ssh.exec!("knife configure client -s #{get_config(:register_node)} /etc/chef")
    Chef::Log.debug("Knife Configure output:\n#{output}")

    #Copy the validation key to /etc/chef on the client
    puts "Uploading validation.pem to client"
    ssh.scp.upload!(validation_pem_path, remote_validation_pem_path)

    #Edit /etc/chef/client.rb so that it points at the location of the validator
    puts "Adding validator key path to client.rb"
    cmd = %Q{echo "validator_key '#{remote_validation_pem_path}'" >> /etc/chef/client.rb}
    output = ssh.exec!(cmd)
    Chef::Log.debug("#{output}")

    #Register the client node with the Chef server, by running chef-client
    #Add additional handling of this command to determine if the chef-client
    #run finished successfully or not.
    puts "Running chef-client to register as a Chef node"
    output = ""
    stderr_out = ""
    exit_code = nil
    ssh.exec("chef-client") do |ch, success|
      unless success
        abort "FAILED: chef-client command failed to execute on client"
      end
      ch.on_data do |ch,data|
        output+=data
      end
      ch.on_extended_data do |ch,type,data|
        stderr_out+=data
      end
      ch.on_request("exit-status") do |ch,data|
        exit_code = data.read_long
      end
    end
    ssh.loop
    if exit_code != 0
      puts "Initial chef-client run failed. Please verify client settings and rerun chef-client to register this server as a node with #{get_config(:register_node)}"
      return nil
    end
    Chef::Log.debug("chef-client command output:\n#{output}")
  end
end

#runObject



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/chef/knife/hmc_server_create.rb', line 147

def run
	Chef::Log.debug("Creating server...")

	validate!([:frame_name,:lpar_name,:vio1_name,:vio2_name,:des_mem,:des_vcpu,:des_proc])
  #Create Objects
	hmc = Hmc.new(get_config(:hmc_host), get_config(:hmc_username), {:password => get_config(:hmc_password)}) 
  vio1 = Vio.new(hmc, get_config(:frame_name), get_config(:vio1_name))
  vio2 = Vio.new(hmc, get_config(:frame_name), get_config(:vio2_name))

  #Option checking for LPAR and NIM objects
  #Since we only technically need desired proc,vcpu, mem to make an lpar we
  #need to check for the optional flags. And Deploying the OS is optional we
  #also need to check for those.
  if validate([:min_mem,:max_mem,:min_vcpu,:max_vcpu,:min_proc,:max_proc])
    lpar = Lpar.new({:hmc => hmc,:min_proc => get_config(:min_proc),:des_proc => get_config(:des_proc), :max_proc => get_config(:max_proc), :min_mem => get_config(:min_mem), :des_mem => get_config(:des_mem), :max_mem => get_config(:max_mem), :min_vcpu =>  get_config(:min_vcpu), :des_vcpu => get_config(:des_vcpu), :max_vcpu => get_config(:max_vcpu), :frame => get_config(:frame_name), :name => get_config(:lpar_name)})
  else
    lpar = Lpar.new({:hmc => hmc,:des_proc => get_config(:des_proc),:des_mem => get_config(:des_mem),:des_vcpu => get_config(:des_vcpu), :frame => get_config(:frame_name), :name => get_config(:lpar_name)})
  end

  image_deploy = false
  first_bootscript = nil
  if validate([:nim_host,:nim_username,:nim_password,:image,:ip_address,:size,:vlan_id])
    image_deploy = true
    nim = Nim.new(get_config(:nim_host),get_config(:nim_username), {:password => get_config(:nim_password)})
  end

  if image_deploy == true
    if validate([:fb_script])
      first_bootscript = get_config(:fb_script)
    end
  end

  #Open connections
  hmc.connect
  puts "Connected to #{get_config(:hmc_host)} as #{get_config(:hmc_username)}."
  if image_deploy == true
    nim.connect
    puts "Connected to #{get_config(:nim_host)} as #{get_config(:nim_username)}."
  end

  #Create LPAR
  lpar.create
  puts "LPAR created."

  if image_deploy == true
    #Add vSCSI adapters
    lpar.add_vscsi(vio1)
    lpar.add_vscsi(vio2)
    puts "vSCSI Adapters added to #{get_config(:lpar_name)}."

    #Get vSCSI information
    lpar_vscsi = lpar.get_vscsi_adapters

    #Find the vHosts
    #TO-DO: Need to update the logic here. 1st element doesn't necessarily
    #have to map to the 1st VIO's vSCSI.
    first_vhost = vio1.find_vhost_given_virtual_slot(lpar_vscsi[0].remote_slot_num)
    second_vhost = vio2.find_vhost_given_virtual_slot(lpar_vscsi[1].remote_slot_num)

    #Attach a Disk
    vio1.map_single_disk_by_size(first_vhost,vio2,second_vhost,get_config(:size).to_i)
    puts "LUN attached to #{get_config(:lpar_name)}."

    #Attach vNIC, will activate and deactive LPAR to assign MAC address to NIC
    lpar.create_vnic(get_config(:vlan_id))
    puts "vNIC attached to #{get_config(:lpar_name)}."

    ##Deploy Mksysb, booting LPAR
    nim.deploy_image(lpar,get_config(:image),first_bootscript) do |nimIp,gw,snm| 
       hmc.lpar_net_boot(nimIp,get_config(:ip_address),gw,snm,lpar)
    end
    puts "#{get_config(:image)} deployed to #{get_config(:lpar_name)}."
  end       	
  
  if image_deploy == true
    nim.disconnect
    puts "Disconnected from #{get_config(:nim_host)}."

    #Check to see if the :register_node option has been specified
    #since we can only connect to bootstrap this server if it has
    #a working OS on it.
    if validate([:register_node])
      #Branch here in case we can use Chef::Knife::Bootstrap
      #to handle this sometime in the future. For now, hardcode the
      #manual bootstrap
      manual_bootstrap = true

      #Wait here until the client is alive
      print "Bootstrapping client. Waiting for sshd..."
      print "." until tcp_ssh_alive(get_config(:ip_address))
      puts "done\nInitiating bootstrap."

      if manual_bootstrap
        manual_bootstrap_for_node
      else
        bootstrap_for_node
      end
    end
  end

  #Close connection 
  hmc.disconnect
  puts "Disconnected from #{get_config(:hmc_host)}."

  puts "Successfully created #{get_config(:lpar_name)}."
end