class Commutateurs::Ssh

Attributes

default_prompt[RW]
filter[RW]
host[RW]
more[RW]
password[RW]
port[RW]
timeout[RW]
user[RW]

Public Class Methods

new(verbose) click to toggle source
# File lib/commutateurs/ssh.rb, line 8
def initialize(verbose)
  @timeout = 10
  @verbose = verbose
  @filter = Proc.new { |line| line }
end

Public Instance Methods

close() click to toggle source
# File lib/commutateurs/ssh.rb, line 58
def close
  Timeout::timeout(2) {
    @channel.close if @channel
    @channel = nil
    @ssh.close if @ssh
  }
rescue Timeout::Error
end
command(cmd, options = {}) { |output| ... } click to toggle source
# File lib/commutateurs/ssh.rb, line 14
def command(cmd, options = {})
  send(cmd)
  expect(options[:prompt] || default_prompt) do |output|
    yield output if block_given?
  end
end
connect(&block) click to toggle source
# File lib/commutateurs/ssh.rb, line 21
def connect(&block)
  @output = []
  @channel_data = ""

  @ssh = Net::SSH.start(host, user, :port => port, :password => password, :timeout => timeout, :paranoid => Net::SSH::Verifiers::Null.new)

  @buf = ""
  @eof = false
  @channel = nil
  @ssh.open_channel do |channel|
    channel.request_pty { |ch,success| raise "failed to open pty" unless success }

    channel.send_channel_request("shell") do |ch, success|
      raise "failed to open ssh shell channel" unless success

      ch.on_data { |ch,data|
        # p @filter.call(data)
        $stderr.puts(@filter.call(data)) if @verbose
        @buf << @filter.call(data)
      }
      ch.on_extended_data { |ch,type,data|
        if type == 1
          $stderr.puts(@filter.call(data)) if @verbose
          @buf << @filter.call(data)
        end
      }
      ch.on_close { @eof = true }

      @channel = ch
      expect(default_prompt, &block)
      return
    end

  end
  @ssh.loop
end
expect(prompt) { |line| ... } click to toggle source
# File lib/commutateurs/ssh.rb, line 67
def expect(prompt)
  line = ''
  sock = @ssh.transport.socket

  while not @eof
    # p prompt
    # p line
    break if line =~ prompt and @buf == ''
    break if sock.closed?

    IO::select([sock], [sock], nil, nil)

    process_ssh

    if more && @buf =~ more
      @buf = @buf.gsub(more, "")
      send(" ")
    end

    if @buf != ""
      line += @buf.gsub(/\r\n/no, "\n")
      @buf = ''
      yield line if block_given?
    elsif @eof
      # channel has been closed
      break if line =~ prompt
      if line == ''
        line = nil
        yield nil if block_given?
      end
      break
    end
  end
  line
end
send(line) click to toggle source
# File lib/commutateurs/ssh.rb, line 103
def send(line)
  @channel.send_data(line + "\n")
end

Private Instance Methods

eof?() click to toggle source
# File lib/commutateurs/ssh.rb, line 108
def eof?
  !! @eof
end
process_ssh() click to toggle source
# File lib/commutateurs/ssh.rb, line 112
def process_ssh
  while @buf == "" and not eof?
    begin
      @channel.connection.process(0.1)
    rescue IOError
      @eof = true
    end
  end
end