Class: Chimp::ChimpDaemon

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/right_chimp/daemon/chimp_daemon.rb

Defined Under Namespace

Classes: AdminServlet, DisplayServlet, GenericServlet, GroupServlet, JobServlet

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeChimpDaemon

Returns a new instance of ChimpDaemon.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 17

def initialize
  @verbose     = false
  @debug       = false
  @port        = 9055
  @bind_address = 'localhost'
  @concurrency = 50
  @delay       = 0
  @retry_count = 0
  @threads     = []
  @running     = false
  @queue       = ChimpQueue.instance
  @chimp_queue = Queue.new
  @semaphore   = Mutex.new

  @proc_counter = 0

  # Connect to the API
  Connection.instance
end

Instance Attribute Details

#bind_addressObject

Returns the value of attribute bind_address.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def bind_address
  @bind_address
end

#chimp_queueObject

Returns the value of attribute chimp_queue.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def chimp_queue
  @chimp_queue
end

#concurrencyObject

Returns the value of attribute concurrency.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def concurrency
  @concurrency
end

#debugObject

Returns the value of attribute debug.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def debug
  @debug
end

#delayObject

Returns the value of attribute delay.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def delay
  @delay
end

#dry_runObject

Returns the value of attribute dry_run.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def dry_run
  @dry_run
end

#logfileObject

Returns the value of attribute logfile.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def logfile
  @logfile
end

#portObject

Returns the value of attribute port.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def port
  @port
end

#proc_counterObject

Returns the value of attribute proc_counter.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def proc_counter
  @proc_counter
end

#queueObject (readonly)

Returns the value of attribute queue.



13
14
15
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 13

def queue
  @queue
end

#retry_countObject

Returns the value of attribute retry_count.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def retry_count
  @retry_count
end

#runningObject (readonly)

Returns the value of attribute running.



13
14
15
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 13

def running
  @running
end

#semaphoreObject

Returns the value of attribute semaphore.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def semaphore
  @semaphore
end

#serverObject

Returns the value of attribute server.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def server
  @server
end

#verboseObject

Returns the value of attribute verbose.



10
11
12
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 10

def verbose
  @verbose
end

Instance Method Details

#helpObject

Print out help information



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 123

def help
  puts
  puts  "chimpd -- a RightScale Platform command-line tool"
  puts
  puts  "Syntax: chimpd [--logfile=<name>] [--concurrency=<c>] [--delay=<d>] [--retry=<r>] [--port=<p>] [--bind-address=<addr> ] [--verbose]"
  puts
  puts  "Options:"
  puts
  puts  " --logfile=<name>            Specifiy the desired log location"
  puts  " --concurrency=<n>           Specify the level of concurrent actions"
  puts  " --delay=<n>                 Specify the number of seconds to wait before executing the action"
  puts  " --retry=<r>                 Specify the number of times chimpd should retry executing the action"
  puts
  puts  " --verbose                   Run chimpd in verbose mode."
  puts  " --quiet                     Supress non-essential output"
  puts
  puts  " --port=<port>               Specify the port number for chimpd to listen on (default: 9055)"
  puts  " --bind-address=<addr>       Specify an interface address for chimpd to bind to.  0.0.0.0 allows all, default is 'localhost'"
  puts
  puts  " --help                      Displays this menu"
  puts
  exit 0
end

#install_signal_handlersObject

Trap signals to exit cleanly



205
206
207
208
209
210
211
212
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 205

def install_signal_handlers
  ['INT', 'TERM'].each do |signal|
    trap(signal) do
      puts "Terminating..."
      self.quit
    end
  end
end

#parse_command_lineObject

Parse chimpd command line options



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 55

def parse_command_line
  begin
    opts = GetoptLong.new(
      [ '--logfile', '-l',      GetoptLong::REQUIRED_ARGUMENT ],
      [ '--verbose', '-v',      GetoptLong::NO_ARGUMENT ],
      [ '--quiet',   '-q',      GetoptLong::NO_ARGUMENT ],
      [ '--concurrency', '-c',  GetoptLong::REQUIRED_ARGUMENT ],
      [ '--delay', '-d',        GetoptLong::REQUIRED_ARGUMENT ],
      [ '--retry', '-y',        GetoptLong::REQUIRED_ARGUMENT ],
      [ '--port', '-p',         GetoptLong::REQUIRED_ARGUMENT ],
      [ '--bind-address', '-b', GetoptLong::REQUIRED_ARGUMENT ],
      [ '--help', '-h',         GetoptLong::NO_ARGUMENT ],
      [ '--exit', '-x', 				GetoptLong::NO_ARGUMENT ]
    )

    opts.each do |opt, arg|
      case opt
        when '--logfile', '-l'
          @logfile = arg
          Log.logger = Logger.new(@logfile)
        when '--concurrency', '-c'
          @concurrency = arg.to_i
        when '--delay', '-d'
          @delay = arg.to_i
        when '--retry', '-y'
          @retry_count = arg.to_i
        when '--verbose', '-v'
          @verbose = true
        when '--quiet',   '-q'
          @quiet = true
        when '--port', '-p'
          @port = arg
        when '--bind-address', '-b'
          @bind_address = arg.to_s
        when '--help', '-h'
          help
        when '--exit', '-x'
          uri = "http://localhost:#{@port}/admin"
          response = RestClient.post uri, { 'shutdown' => true }.to_yaml
          exit 0
      end
    end
  rescue GetoptLong::InvalidOption => ex
    puts "Syntax: chimpd [--logfile=<name>] [--concurrency=<c>] [--delay=<d>] [--retry=<r>] [--port=<p>] [--bind-address=<addr> ] [--verbose]"
    exit 1
  end

  #
  # Set up logging/verbosity
  #
  Chimp.set_verbose(@verbose, @quiet)

  if not @verbose
  	ENV['REST_CONNECTION_LOG'] = "/dev/null"
  	ENV['RESTCLIENT_LOG'] = "/dev/null"
    Log.threshold= Logger::INFO
  else
    Log.threshold= Logger::DEBUG
  end

  if @quiet
    Log.threshold = Logger::WARN
  end
end

#quitObject

Quit by waiting for all chimp jobs to finish, not allowing new jobs on the queue, and killing the web server.



218
219
220
221
222
223
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 218

def quit
  @running = false
  @server.shutdown
  sleep 5
  exit 0
end

#runObject

Main entry point for chimpd command line application



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 40

def run
  install_signal_handlers
  parse_command_line

  # puts "chimpd #{VERSION} launching with #{@concurrency} workers"
  Log.info 'Loading... please wait'
  spawn_queue_runner
  spawn_webserver
  spawn_chimpd_submission_processor
  run_forever
end

#run_foreverObject

Process requests forever until we’re killed



193
194
195
196
197
198
199
200
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 193

def run_forever
  @running = true
  while @running
    @threads.each do |t|
      t.join(5)
    end
  end
end

#spawn_chimpd_submission_processorObject

Spawn threads to process submitted requests



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 228

def spawn_chimpd_submission_processor
  n = @concurrency/4
  n = 10 if n < 10
  Log.debug "Logging into API..."

  #
  # There is a race condition logging in with rest_connection.
  # As a workaround, do a tag query first thing when chimpd starts.
  #
  begin
    c = Chimp.new
    c.interactive = false
    c.quiet = true
    #c.tags = ["bogus:tag=true"]
    c.run
  rescue StandardError
  end

  puts "chimpd #{VERSION} launched with #{@concurrency} workers"

  Log.debug "Spawning #{n} submission processing threads"

  (1..n).each do |n|
    @threads ||=[]
    @threads << Thread.new {
      while true
        begin

          queued_request = @chimp_queue.pop
          group = queued_request.group
          queued_request.interactive = false
          tasks = queued_request.process
          tasks.each do |task|
            ChimpQueue.instance.push(group, task)
          end

        rescue StandardError => ex
            puts ex.backtrace
          Log.error " submission processor: group=\"#{group}\" script=\"#{queued_request.script}\": #{ex}"
        end
      end
    }
  end
end

#spawn_queue_runnerObject

Spawn the ChimpQueue threads



150
151
152
153
154
155
156
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 150

def spawn_queue_runner
  @queue.max_threads = @concurrency
  @queue.delay = @delay
  @queue.retry_count = @retry_count
  @queue.start
  @running = true
end

#spawn_webserverObject

Spawn a WEBrick Web server



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/right_chimp/daemon/chimp_daemon.rb', line 161

def spawn_webserver
  opts = {
    :BindAddress  => @bind_address,
    :Port         => @port,
    :MaxClients   => 500,
    :RequestTimeout => 120,
    :DoNotReverseLookup => true
  }

  if not @verbose
    opts[:Logger] = WEBrick::Log.new("/dev/null")
    opts[:AccessLog] = [nil, nil]
  end

  @server = ::WEBrick::HTTPServer.new(opts)
  @server.mount('/',         DisplayServlet)
  @server.mount('/display',  DisplayServlet)
  @server.mount('/job',      JobServlet)
  @server.mount('/group',    GroupServlet)
  @server.mount('/admin',    AdminServlet)

  #
  # WEBrick threads
  #
  @threads << Thread.new(1001) do
    @server.start
  end
end