class PuppetPSSH::Run

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

Needs pssh (parallel-ssh) installed.

Public Instance Methods

execute() click to toggle source
# 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