Class: ForemanRemoteExecutionCore::ScriptRunner

Inherits:
ForemanTasksCore::Runner::Base
  • Object
show all
Defined in:
lib/foreman_remote_execution_core/script_runner.rb

Constant Summary collapse

EXPECTED_POWER_ACTION_MESSAGES =
['restart host', 'shutdown host'].freeze

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ ScriptRunner

Returns a new instance of ScriptRunner.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 7

def initialize(options)
  super()
  @host = options.fetch(:hostname)
  @script = options.fetch(:script)
  @ssh_user = options.fetch(:ssh_user, 'root')
  @ssh_port = options.fetch(:ssh_port, 22)
  @effective_user = options.fetch(:effective_user, nil)
  @effective_user_method = options.fetch(:effective_user_method, 'sudo')
  @host_public_key = options.fetch(:host_public_key, nil)
  @verify_host = options.fetch(:verify_host, nil)

  @client_private_key_file = settings.fetch(:ssh_identity_key_file)
  @local_working_dir = options.fetch(:local_working_dir, settings.fetch(:local_working_dir))
  @remote_working_dir = options.fetch(:remote_working_dir, settings.fetch(:remote_working_dir))
end

Instance Method Details

#closeObject



92
93
94
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 92

def close
  @session.close if @session && !@session.closed?
end

#killObject



54
55
56
57
58
59
60
61
62
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 54

def kill
  if @session
    run_sync("pkill -f #{remote_command_file('script')}")
  else
    logger.debug('connection closed')
  end
rescue => e
  publish_exception('Unexpected error', e, false)
end

#refreshObject



43
44
45
46
47
48
49
50
51
52
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 43

def refresh
  return if @session.nil?
  with_retries do
    with_disconnect_handling do
      @session.process(0)
    end
  end
ensure
  check_expecting_disconnect
end

#startObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 23

def start
  remote_script = cp_script_to_remote
  output_path = File.join(File.dirname(remote_script), 'output')
  exit_code_path = File.join(File.dirname(remote_script), 'exit_code')

  # pipe the output to tee while capturing the exit code in a file
  script = <<-SCRIPT.gsub(/^\s+\| /, '')
  | sh <<WRAPPER
  | (#{su_prefix}#{remote_script} < /dev/null; echo \\$?>#{exit_code_path}) | /usr/bin/tee #{output_path}
  | exit \\$(cat #{exit_code_path})
  | WRAPPER
  SCRIPT

  logger.debug("executing script:\n#{script.lines.map { |line| "  | #{line}" }.join}")
  run_async(script)
rescue => e
  logger.error("error while initalizing command #{e.class} #{e.message}:\n #{e.backtrace.join("\n")}")
  publish_exception('Error initializing command', e)
end

#with_disconnect_handlingObject



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 80

def with_disconnect_handling
  yield
rescue Net::SSH::Disconnect => e
  @session.shutdown!
  check_expecting_disconnect
  if @expecting_disconnect
    publish_exit_status(0)
  else
    publish_exception('Unexpected disconnect', e)
  end
end

#with_retriesObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 64

def with_retries
  tries = 0
  begin
    yield
  rescue => e
    logger.error("Unexpected error: #{e.class} #{e.message}\n #{e.backtrace.join("\n")}")
    tries += 1
    if tries <= MAX_PROCESS_RETRIES
      logger.error('Retrying')
      retry
    else
      publish_exception('Unexpected error', e)
    end
  end
end