class Stemcell::LogTailer

Constants

MAX_WAIT_FOR_SSH

Don't wait more than two minutes

TAILING_COMMAND

Attributes

finished[R]
hostname[R]
interrupted[R]
ssh_port[R]
username[R]

Public Class Methods

new(hostname, username, ssh_port=22) click to toggle source
# File lib/stemcell/log_tailer.rb, line 25
def initialize(hostname, username, ssh_port=22)
  @hostname = hostname
  @username = username
  @ssh_port = ssh_port

  @finished = false
  @interrupted = false
end

Public Instance Methods

run!() click to toggle source
# File lib/stemcell/log_tailer.rb, line 34
def run!
  while_catching_interrupt do
    return unless wait_for_ssh
    tail_until_interrupt
  end
end

Private Instance Methods

contains_last_line?(data) click to toggle source
# File lib/stemcell/log_tailer.rb, line 132
def contains_last_line?(data)
  data =~ /#{Launcher::LAST_BOOTSTRAP_LINE}/
end
done?() click to toggle source
# File lib/stemcell/log_tailer.rb, line 121
def done?
  finished || interrupted
end
get_ssh_banner() click to toggle source
# File lib/stemcell/log_tailer.rb, line 125
def get_ssh_banner
  socket = TCPSocket.new(hostname, ssh_port)
  IO.select([socket], nil, nil, 5) ? socket.gets : nil
ensure
  socket.close if socket
end
tail_until_interrupt() click to toggle source
# File lib/stemcell/log_tailer.rb, line 84
def tail_until_interrupt
  return if interrupted

  session = Net::SSH.start(hostname, username)

  channel = session.open_channel do |ch|
    ch.request_pty do |ch, success|
      raise "Couldn't start a pseudo-tty!" unless success

      ch.on_data do |ch, data|
        STDOUT.print(data)
        @finished = true if contains_last_line?(data)
      end
      ch.on_extended_data do |c, type, data|
        STDERR.print(data)
      end

      ch.exec(TAILING_COMMAND)
    end
  end

  session.loop(1) do
    if done?
      # Send an interrupt to kill the remote process
      channel.send_data(Net::SSH::Connection::Term::VINTR)
      channel.send_data "exit\n"
      channel.eof!
      channel.close
      false
    else
      session.busy?
    end
  end

  session.close
end
wait_for_ssh() click to toggle source
# File lib/stemcell/log_tailer.rb, line 43
def wait_for_ssh
  return if interrupted

  print "Waiting for sshd..."

  start_time = Time.now
  banner = nil

  loop do
    print "."
    begin
      banner = get_ssh_banner
      break
    rescue SocketError,
           IOError,
           Errno::ECONNREFUSED,
           Errno::ECONNRESET,
           Errno::EHOSTUNREACH,
           Errno::ENETUNREACH
      sleep 5
    rescue Errno::ETIMEDOUT,
           Errno::EPERM
    end

    # Don't wait forever
    if Time.now - start_time > MAX_WAIT_FOR_SSH
      puts " TIMEOUT!".red
      return false
    end

    if done?
      puts " ABORT!".red
      return false
    end
  end

  puts " UP!".green
  puts "Server responded with: #{banner.green}"
  true
end
while_catching_interrupt() { || ... } click to toggle source
# File lib/stemcell/log_tailer.rb, line 136
def while_catching_interrupt
  trap(:SIGINT) { @interrupted = true }
  yield
ensure
  trap(:SIGINT, nil) 
end