class RemoteExec::Ssh

Class to help establish SSH connections, issue remote commands, and transfer files between a local system and remote node.

Constants

RESCUE_EXCEPTIONS

Attributes

hostname[R]

hostname for the connection

options[RW]

options for the connection

username[R]

username for the connection

Public Class Methods

new(hostname, username, options = {}) click to toggle source

Constructs a new Ssh object.

@param hostname [String] the remote hostname (IP address, FQDN, etc.) @param username [String] the username for the remote host @param options [Hash] configuration options for ssh @yield [self] if a block is given then the constructed

object yields itself and calls `#shutdown`
at the end, closing the remote connection
Calls superclass method RemoteExec::Base::new
# File lib/remote-exec/ssh.rb, line 31
def initialize(hostname, username, options = {})
  @hostname = hostname
  @username = username
  @options = options
  super()
end

Public Instance Methods

execute(command) click to toggle source

Execute command on remote host

@param command [String] command string to execute @return [Integer] exit status of the command

# File lib/remote-exec/ssh.rb, line 57
def execute(command)
  # TODO: make it run in one session
  @last_status = nil
  @command     = command
  session.open_channel(&method(:execute_open_channel))
  session.loop
  @last_status
end
shutdown() click to toggle source

Shuts down the session connection, if it is still active.

Calls superclass method RemoteExec::Base#shutdown
# File lib/remote-exec/ssh.rb, line 43
def shutdown
  super
  return if @session.nil?
  session.shutdown!
ensure
  @session = nil
end
to_s() click to toggle source
# File lib/remote-exec/ssh.rb, line 38
def to_s
  "<RemoteExec::Ssh @hostname=#{@hostname.inspect}, @username=#{@username.inspect}>"
end

Private Instance Methods

establish_connection() click to toggle source

Establish a connection session to the remote host.

@return [Net::SSH::Connection::Session] the SSH connection session @api private

# File lib/remote-exec/ssh.rb, line 117
def establish_connection
  @retries = options[:ssh_retries] || 2
  begin
    before_connect.changed_and_notify(self)
    ssh = Net::SSH.start(hostname, username, options)
  rescue *RESCUE_EXCEPTIONS => exception
    handle_exception_retry(exception)
    retry
  end
  after_connect.changed_and_notify(self)
  ssh
end
execute_channel_exec(channel, success) click to toggle source
# File lib/remote-exec/ssh.rb, line 76
def execute_channel_exec(channel, success)
  channel.on_data(&method(:execute_on_stdout))
  channel.on_extended_data(&method(:execute_on_stderr))
  channel.on_request("exit-status") do |channel, data|
    @last_status = data.read_long
  end
end
execute_on_stderr(channel, type, data) { |nil, data| ... } click to toggle source
# File lib/remote-exec/ssh.rb, line 89
def execute_on_stderr(channel, type, data)
  case type
  when 1
    on_execute_data.changed_and_notify(self, nil, data)
    yield(nil, data) if block_given?
  else
    raise "Unsupported SSH extended_data type: #{type.inspect}"
  end
end
execute_on_stdout(channel, data) { |data, nil| ... } click to toggle source
# File lib/remote-exec/ssh.rb, line 84
def execute_on_stdout(channel, data)
  on_execute_data.changed_and_notify(self, data, nil)
  yield(data, nil) if block_given?
end
execute_open_channel(channel) click to toggle source
# File lib/remote-exec/ssh.rb, line 68
def execute_open_channel(channel)
  before_execute.changed_and_notify(self, @command)
  channel.request_pty unless options[:ssh_request_pty] == false
  channel.exec(@command, &method(:execute_channel_exec))
  channel.wait
  after_execute.changed_and_notify(self, @command, @last_status)
end
handle_exception_retry(exception) click to toggle source
# File lib/remote-exec/ssh.rb, line 130
def handle_exception_retry(exception)
  if @retries > 0
    on_connect_retry.changed_and_notify(self, exception, @retries)
    sleep options[:ssh_timeout] || 1
    @retries -= 1
  else
    on_connect_fail.changed_and_notify(self, exception)
    # TODO: should we wrap the error in some other common class?
    raise exception
  end
end
session() click to toggle source
# File lib/remote-exec/ssh.rb, line 99
def session
  @session ||= establish_connection
end