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 Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ ScriptRunner



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 15

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)
  @execution_timeout_interval = options.fetch(:execution_timeout_interval, 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 Attribute Details

#execution_timeout_intervalObject (readonly)

Returns the value of attribute execution_timeout_interval.



11
12
13
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 11

def execution_timeout_interval
  @execution_timeout_interval
end

Instance Method Details

#closeObject



110
111
112
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 110

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

#killObject



63
64
65
66
67
68
69
70
71
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 63

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

#publish_data(data, type) ⇒ Object



114
115
116
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 114

def publish_data(data, type)
  super(data.force_encoding('UTF-8'), type)
end

#refreshObject



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

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

#startObject



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 32

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 = "  | sh <<WRAPPER\n  | (\#{su_prefix}\#{remote_script} < /dev/null; echo \\\\$?>\#{exit_code_path}) | /usr/bin/tee \#{output_path}\n  | exit \\\\$(cat \#{exit_code_path})\n  | WRAPPER\n  SCRIPT\n\n  logger.debug(\"executing script:\\n\#{script.lines.map { |line| \"  | \#{line}\" }.join}\")\n  run_async(script)\nrescue => e\n  logger.error(\"error while initalizing command \#{e.class} \#{e.message}:\\n \#{e.backtrace.join(\"\\n\")}\")\n  publish_exception('Error initializing command', e)\nend\n".gsub(/^\s+\| /, '')

#timeoutObject



73
74
75
76
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 73

def timeout
  @logger.debug('job timed out')
  super
end

#timeout_intervalObject



78
79
80
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 78

def timeout_interval
  execution_timeout_interval
end

#with_disconnect_handlingObject



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 98

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



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/foreman_remote_execution_core/script_runner.rb', line 82

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