Class: PuppetPSSH::Run

Inherits:
BaseCommand show all
Defined in:
lib/puppet-pssh.rb

Overview

Run an arbitrary command using parallel-ssh against all the nodes registered in the puppet master

Needs pssh (parallel-ssh) installed.

Instance Method Summary collapse

Methods inherited from BaseCommand

#get_nodes, #master_url, #node_status

Instance Method Details

#executeObject



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
253
254
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
# File 'lib/puppet-pssh.rb', line 205

def execute

  Log.info "SSH user: #{user}"
  Log.info "Node log output path: #{node_output_path}"
  Log.info "Max threads: #{threads}"

  unless File.exist?(pssh_path)
    Log.error "parallel-ssh command not found in #{pssh_path}."
    Log.error "Install it or use --pssh-path argument."
    exit 1
  end

  nodes = []
  begin
    nodes = get_nodes(puppetmaster)
  rescue => e
    Log.error e.message
    exit 1
  end

  # Delete previous hostlist unless specified otherwise
  unless cached_hostlist?
    File.delete hostlist_path if File.exist?(hostlist_path)
  end

  unless File.exist?(hostlist_path)
    Log.info "Generating hostlist..."
    Log.debug "Hostlist path: #{hostlist_path}"
    # 
    # Optionally resolve names using specific DNS server
    #
    if !nameserver.nil?
      require 'net/dns'
      Log.info "DNS Server: #{nameserver}"
      Log.info "Resolving node names... (may take a while)"
      res = Net::DNS::Resolver.new
      res.nameservers = nameserver
    elsif use_ipaddress_fact?
      Log.info "Using node ipaddress fact to connect to the node..."
    end
    #
    File.open hostlist_path, 'w' do |f|
      nodes.each do |i|
        address = i
        # try to resolve before writing the list
        Log.debug "Adding #{address}"
        if !nameserver.nil?
          address = res.query(i).answer.first.address rescue next
        elsif use_ipaddress_fact?
          value = JSON.parse(
            Excon.get(master_url + "facts/#{i}").body
          )['facts']['ipaddress']
          if value
            address = value
          else
            Log.warn "Node #{i} does not have ipaddress fact. Using FQDN."
            address = i
          end
        else
        end
        f.puts "#{address}"
      end
    end
  else
    Log.warn "Using cached hostlist in #{hostlist_path}"
  end

  $stdout.sync = true
  if splay?
    Log.info "Using 30s splay"
    command = "sleep `echo $[ ( $RANDOM % 30 )  + 1 ]`;" + command_list.join(' ')
  else
    command = command_list.join(' ')
  end
  Log.info "Running command '#{command}' with parallel-ssh..."
  ssh_opts = ''
  extra_opts = "-l #{user} "
  if extra_args
    Log.info "Extra pssh arguments: #{extra_args}"
    extra_opts << extra_args
  end
  unless host_key_verify?
    Log.warn 'Disabled host key verification'
    ssh_opts = '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
  end
  if nodes.empty?
    Log.warn 'The node list is empty.'
    Log.warn 'If you are using --match, the regexp didn\'t match any node.'
  else
    full_cmd = "#{pssh_path} #{extra_opts} -p #{threads} -o #{node_output_path} -t 300 -h #{hostlist_path} -x '#{ssh_opts}' " + "'#{command} 2>&1'"
    Log.debug full_cmd
    system full_cmd
  end
end