Class: Villein::Agent

Inherits:
Client
  • Object
show all
Defined in:
lib/villein/agent.rb

Overview

Villein::Agent allows you to start new serf agent. Use this when you need to start and manage the serf agents from ruby process.

Defined Under Namespace

Classes: AlreadyStarted, NotRunning

Constant Summary collapse

EVENT_HANDLER_SH =
File.expand_path(File.join(__dir__, '..', '..', 'misc', 'villein-event-handler'))

Instance Attribute Summary collapse

Attributes inherited from Client

#name, #rpc_addr, #serf, #silence

Instance Method Summary collapse

Methods inherited from Client

#delete_tag, #event, #force_leave, #get_tags, #join, #leave, #members, #set_tag, #silence?, #tags

Constructor Details

#initialize(serf: 'serf', node: Socket.gethostname, rpc_addr: '127.0.0.1:7373', bind: nil, iface: nil, advertise: nil, config_file: nil, config_dir: nil, discover: false, join: nil, snapshot: nil, encrypt: nil, profile: nil, protocol: nil, event_handlers: [], replay: nil, tags: {}, tags_file: nil, log_level: :info, log: File::NULL) ⇒ Agent

Returns a new instance of Agent.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/villein/agent.rb', line 17

def initialize(serf: 'serf',
               node: Socket.gethostname,
               rpc_addr: '127.0.0.1:7373', bind: nil, iface: nil, advertise: nil,
               config_file: nil, config_dir: nil,
               discover: false, join: nil, snapshot: nil,
               encrypt: nil, profile: nil, protocol: nil,
               event_handlers: [], replay: nil,
               tags: {}, tags_file: nil,
               log_level: :info, log: File::NULL)
  @serf = serf
  @name = node
  @rpc_addr = rpc_addr
  @bind, @iface, @advertise = bind, iface, advertise
  @config_file, @config_dir = config_file, config_dir
  @discover, @join, @snapshot = discover, join, snapshot
  @encrypt, @profile, @protocol = encrypt, profile, protocol
  @custom_event_handlers, @replay = event_handlers, replay
  @initial_tags, @tags_file = tags, tags_file
  @log_level, @log = log_level, log
  @hooks = {}

  @pid, @exitstatus = nil, nil
  @pid_lock = Mutex.new
end

Instance Attribute Details

#exitstatusObject (readonly)

Returns the value of attribute exitstatus.



42
43
44
# File 'lib/villein/agent.rb', line 42

def exitstatus
  @exitstatus
end

#pidObject (readonly)

Returns the value of attribute pid.



42
43
44
# File 'lib/villein/agent.rb', line 42

def pid
  @pid
end

Instance Method Details

#auto_stopObject

Add at_exit hook to safely stop at exit of current ruby process. Note that Kernel#.at_exit hook won’t run when Ruby has crashed.



112
113
114
# File 'lib/villein/agent.rb', line 112

def auto_stop
  at_exit { self.stop! if self.running? }
end

#commandObject

Command line arguments to start serf-agent.



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/villein/agent.rb', line 128

def command
  cmd = [@serf, 'agent']

  cmd << ['-node', @name] if @name
  cmd << '-replay' if @replay
  cmd << '-discover' if @discover

  @initial_tags.each do |key, val|
    cmd << ['-tag', "#{key}=#{val}"]
  end

  cmd << [
    '-event-handler',
    [EVENT_HANDLER_SH, *event_listener_addr].join(' ')
  ]

  @custom_event_handlers.each do |handler|
    cmd << ['-event-handler', handler]
  end

  %w(bind iface advertise config-file config-dir
     encrypt join log-level profile protocol rpc-addr
     snapshot tags-file).each do |key|

    val = instance_variable_get("@#{key.gsub(/-/,'_')}")
    cmd << ["-#{key}", val] if val
  end

  cmd.flatten.map(&:to_s)
end

#dead?Boolean

Returns true when the serf agent has started, but stopped for some reason. Use Agent#exitstatus to get Process::Status object.

Returns:

  • (Boolean)


53
54
55
# File 'lib/villein/agent.rb', line 53

def dead?
  !!@exitstatus
end

#ready?Boolean

Return true when the agent has received events at least once. Useful to wait serf for ready to use.

Returns:

  • (Boolean)


60
61
62
# File 'lib/villein/agent.rb', line 60

def ready?
  running? && @event_received
end

#running?Boolean

Returns true when the serf agent is running (it has started and not dead yet).

Returns:

  • (Boolean)


66
67
68
# File 'lib/villein/agent.rb', line 66

def running?
  started? && !dead?
end

#start!Object

Start the serf agent.



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/villein/agent.rb', line 71

def start!
  @pid_lock.synchronize do
    raise AlreadyStarted if running?

    @event_received = false

    start_listening_events
    start_process
    start_watchdog
  end
end

#started?Boolean

Returns true when the serf agent has started

Returns:

  • (Boolean)


46
47
48
# File 'lib/villein/agent.rb', line 46

def started?
  !!@pid
end

#stop!(timeout_sec = 10) ⇒ Object

Stop the serf agent. After timeout_sec seconds elapsed, it will attempt to KILL if the agent is still running.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/villein/agent.rb', line 86

def stop!(timeout_sec = 10)
  @pid_lock.synchronize do
    raise NotRunning unless running?

    Process.kill(:INT, @pid)

    stop_watchdog
    call_hooks 'stop', nil

    kill_process(timeout_sec)

    stop_listening_events

    @pid = nil
  end
end

#wait_for_readyObject

Blocks until #ready? become true.



105
106
107
# File 'lib/villein/agent.rb', line 105

def wait_for_ready
  sleep 0.1 until ready?
end