class Proxy::RemoteExecution::Ssh::Dispatcher

Service that handles running external commands for Actions::Command Dynflow action. It runs just one (actor) thread for all the commands running in the system and updates the Dynflow actions periodically.

Public Class Methods

new(options = {}) click to toggle source
# File lib/smart_proxy_remote_execution_ssh/dispatcher.rb, line 31
def initialize(options = {})
  @clock                   = options[:clock] || Dynflow::Clock.spawn('proxy-dispatcher-clock')
  @logger                  = options[:logger] || Logger.new($stderr)

  @session_args = { :logger => @logger,
                    :clock => @clock,
                    :connector_class => options[:connector_class] || Connector,
                    :local_working_dir => options[:local_working_dir] || '/tmp/foreman-proxy-ssh/server',
                    :remote_working_dir => options[:remote_working_dir] || '/tmp/foreman-proxy-ssh/client',
                    :client_private_key_file => Proxy::RemoteExecution::Ssh.private_key_file,
                    :refresh_interval => options[:refresh_interval] || 1 }

  @sessions = {}
end

Public Instance Methods

finish_command(command) click to toggle source
# File lib/smart_proxy_remote_execution_ssh/dispatcher.rb, line 61
def finish_command(command)
  close_session(command)
rescue => exception
  handle_command_exception(command, exception)
end
initialize_command(command) click to toggle source
# File lib/smart_proxy_remote_execution_ssh/dispatcher.rb, line 46
def initialize_command(command)
  @logger.debug("initalizing command [#{command}]")
  open_session(command)
rescue => exception
  handle_command_exception(command, exception)
end
kill(command) click to toggle source
# File lib/smart_proxy_remote_execution_ssh/dispatcher.rb, line 53
def kill(command)
  @logger.debug("killing command [#{command}]")
  session = @sessions[command.id]
  session.tell(:kill) if session
rescue => exception
  handle_command_exception(command, exception, false)
end

Private Instance Methods

close_session(command) click to toggle source
# File lib/smart_proxy_remote_execution_ssh/dispatcher.rb, line 85
def close_session(command)
  session = @sessions.delete(command.id)
  return unless session
  @logger.debug("closing session for command [#{command}], #{@sessions.size} session(s) left ")
  session.tell([:start_termination, Concurrent.future])
end
handle_command_exception(command, exception, fatal = true) click to toggle source
# File lib/smart_proxy_remote_execution_ssh/dispatcher.rb, line 69
def handle_command_exception(command, exception, fatal = true)
  @logger.error("error while dispatching command #{command} to session:"                     "#{exception.class} #{exception.message}:\n #{exception.backtrace.join("\n")}")
  command_data = CommandUpdate.encode_exception("Failed to dispatch the command", exception, fatal)
  command.suspended_action << CommandUpdate.new(command_data)
  close_session(command) if fatal
end
open_session(command) click to toggle source
# File lib/smart_proxy_remote_execution_ssh/dispatcher.rb, line 77
def open_session(command)
  raise "Session already opened for command #{command}" if @sessions[command.id]
  options = { :name => "proxy-ssh-session-#{command.host}-#{command.ssh_user}-#{command.id}",
              :args => [@session_args.merge(:command => command)],
              :supervise => true }
  @sessions[command.id] = Proxy::RemoteExecution::Ssh::Session.spawn(options)
end