Class: Bosh::Agent::Message::RunErrand

Inherits:
Object
  • Object
show all
Defined in:
lib/bosh_agent/message/run_errand.rb

Constant Summary collapse

CANCEL_GRACE_PERIOD_SECONDS =
30

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ RunErrand

Returns a new instance of RunErrand.



27
28
29
30
# File 'lib/bosh_agent/message/run_errand.rb', line 27

def initialize(args)
  @base_dir = Bosh::Agent::Config.base_dir
  @logger = Bosh::Agent::Config.logger
end

Class Attribute Details

.running_errand_pidObject

Returns the value of attribute running_errand_pid.



81
82
83
# File 'lib/bosh_agent/message/run_errand.rb', line 81

def running_errand_pid
  @running_errand_pid
end

Class Method Details

.cancelObject



12
13
14
15
16
17
18
19
20
21
# File 'lib/bosh_agent/message/run_errand.rb', line 12

def self.cancel
  pid = running_errand_pid
  Process.kill('-TERM', pid) if errand_running?
  CANCEL_GRACE_PERIOD_SECONDS.times do
    break unless errand_running?
    sleep 1
  end
  Process.kill('-KILL', pid) if errand_running?
rescue Errno::ESRCH
end

.errand_running?Boolean

Returns:

  • (Boolean)


84
85
86
87
88
89
90
# File 'lib/bosh_agent/message/run_errand.rb', line 84

def self.errand_running?
  return false unless running_errand_pid
  Process.kill(0, running_errand_pid)
  true
rescue Errno::ESRCH
  false
end

.long_running?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/bosh_agent/message/run_errand.rb', line 23

def self.long_running?
  true
end

.process(args) ⇒ Object



8
9
10
# File 'lib/bosh_agent/message/run_errand.rb', line 8

def self.process(args)
  self.new(args).start
end

Instance Method Details

#extract_status_code(status) ⇒ Object



76
77
78
# File 'lib/bosh_agent/message/run_errand.rb', line 76

def extract_status_code(status)
  status.exitstatus || (status.termsig + 128)
end

#startObject



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/bosh_agent/message/run_errand.rb', line 32

def start
  state = Bosh::Agent::Config.state.to_hash

  job_templates = state.fetch('job', {}).fetch('templates', [])
  if job_templates.empty?
    raise Bosh::Agent::MessageHandlerError,
          "At least one job template is required to run an errand"
  end

  job_template_name = job_templates.first.fetch('name')

  env = { 'PATH' => '/usr/sbin:/usr/bin:/sbin:/bin', 'TMPDIR' => ENV['TMPDIR'] }
  cmd = "#{@base_dir}/jobs/#{job_template_name}/bin/run"
  opts = { unsetenv_others: true, pgroup: true }

  unless File.executable?(cmd)
    raise Bosh::Agent::MessageHandlerError,
          "Job template #{job_template_name} does not have executable bin/run"
  end

  begin
    stdout, stderr, status = Open3.popen3(env, cmd, opts) { |i, o, e, t|
      self.class.running_errand_pid = t.pid

      out_reader = Thread.new { o.read }
      err_reader = Thread.new { e.read }

      i.close

      [out_reader.value, err_reader.value, t.value]
    }
    self.class.running_errand_pid = nil

    {
      'exit_code' => extract_status_code(status),
      'stdout' => stdout,
      'stderr' => stderr,
    }
  rescue Exception => e
    @logger.warn("%s\n%s" % [e.inspect, e.backtrace.join("\n")])
    raise Bosh::Agent::MessageHandlerError, e.inspect
  end
end