Class: Proxy::RemoteExecution::Ssh::Session

Inherits:
Dynflow::Actor
  • Object
show all
Defined in:
lib/smart_proxy_remote_execution_ssh/session.rb

Overview

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.

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Session

Returns a new instance of Session.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/smart_proxy_remote_execution_ssh/session.rb', line 8

def initialize(options = {})
  @clock = options[:clock] || Dynflow::Clock.spawn('proxy-dispatcher-clock')
  @logger = options[:logger] || Logger.new($stderr)
  @connector_class = options[:connector_class] || Connector
  @local_working_dir = options[:local_working_dir] || ::Proxy::RemoteExecution::Ssh::Plugin.settings.local_working_dir
  @remote_working_dir = options[:remote_working_dir] || ::Proxy::RemoteExecution::Ssh::Plugin.settings.remote_working_dir
  @refresh_interval = options[:refresh_interval] || 1
  @client_private_key_file = Proxy::RemoteExecution::Ssh.private_key_file
  @command = options[:command]

  @command_buffer = []
  @refresh_planned = false

  reference.tell(:initialize_command)
end

Instance Method Details

#dispatcherObject



93
94
95
# File 'lib/smart_proxy_remote_execution_ssh/session.rb', line 93

def dispatcher
  self.parent
end

#finish_commandObject



88
89
90
91
# File 'lib/smart_proxy_remote_execution_ssh/session.rb', line 88

def finish_command
  close
  dispatcher.tell([:finish_command, @command])
end

#initialize_commandObject



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/smart_proxy_remote_execution_ssh/session.rb', line 24

def initialize_command
  @logger.debug("initalizing command [#{@command}]")
  open_connector
  remote_script = cp_script_to_remote
  output_path = File.join(File.dirname(remote_script), 'output')

  # pipe the output to tee while capturing the exit code
  script = <<-SCRIPT
    exec 4>&1
    exit_code=`((#{su_prefix}#{remote_script}; echo $?>&3 ) | /usr/bin/tee #{output_path} ) 3>&1 >&4`
    exec 4>&-
    exit $exit_code
  SCRIPT
  @logger.debug("executing script:\n#{script.lines.map { |line| "  | #{line}" }.join}")
  @connector.async_run(script) do |data|
    @command_buffer << data
  end
rescue => e
  @logger.error("error while initalizing command #{e.class} #{e.message}:\n #{e.backtrace.join("\n")}")
  @command_buffer.concat(CommandUpdate.encode_exception("Error initializing command #{@command}", e))
  refresh
ensure
  plan_next_refresh
end

#killObject



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/smart_proxy_remote_execution_ssh/session.rb', line 76

def kill
  @logger.debug("killing command [#{@command}]")
  if @connector
    @connector.run("pkill -f #{remote_command_file('script')}")
  else
    @logger.debug("connection closed")
  end
rescue => e
  @command_buffer.concat(CommandUpdate.encode_exception("Failed to kill the command", e, false))
  plan_next_refresh
end

#refreshObject



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/smart_proxy_remote_execution_ssh/session.rb', line 49

def refresh
  @connector.refresh if @connector

  unless @command_buffer.empty?
    status = refresh_command_buffer
    if status
      finish_command
    end
  end
rescue => e
  @command_buffer.concat(CommandUpdate.encode_exception("Failed to refresh the connector", e, false))
ensure
  @refresh_planned = false
  plan_next_refresh
end

#refresh_command_bufferObject



65
66
67
68
69
70
71
72
73
74
# File 'lib/smart_proxy_remote_execution_ssh/session.rb', line 65

def refresh_command_buffer
  @logger.debug("command #{@command} got new output: #{@command_buffer.inspect}")
  command_update = CommandUpdate.new(@command_buffer)
  @command.suspended_action << command_update
  @command_buffer = []
  if command_update.exit_status
    @logger.debug("command [#{@command}] finished with status #{command_update.exit_status}")
    return command_update.exit_status
  end
end

#start_termination(*args) ⇒ Object



97
98
99
100
101
# File 'lib/smart_proxy_remote_execution_ssh/session.rb', line 97

def start_termination(*args)
  super
  close
  finish_termination
end