right_chimp 1.0.3 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +12 -0
- data/Gemfile.lock +9 -8
- data/chimp.gemspec +5 -4
- data/lib/right_chimp/Chimp.rb +4 -15
- data/lib/right_chimp/daemon/ChimpDaemon.rb +126 -73
- data/lib/right_chimp/daemon/ChimpDaemonClient.rb +49 -19
- data/lib/right_chimp/queue/ExecutionGroup.rb +38 -33
- data/lib/right_chimp/version.rb +1 -1
- metadata +41 -13
- checksums.yaml +0 -7
data/CHANGES
CHANGED
@@ -101,3 +101,15 @@ Version 1.0.2
|
|
101
101
|
Version 1.0.3
|
102
102
|
-------------
|
103
103
|
* Bugfix: fix race condition in chimpd serial groups
|
104
|
+
|
105
|
+
Version 1.0.4
|
106
|
+
-------------
|
107
|
+
* Feature: chimp --chimpd-wait-until-done now blocks until a group has completed > 1 job
|
108
|
+
* Feature: chimp --chimpd-wait-until-done now returns immediately during a dry run
|
109
|
+
* Feature: chimpd client now log errors better, retries on failure
|
110
|
+
* Feature: chimp output when using chimpd is better behaved
|
111
|
+
|
112
|
+
Version 1.0.5
|
113
|
+
-------------
|
114
|
+
* Feature: improved error handling and logging when submitting to chimpd
|
115
|
+
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
right_chimp (1.0.
|
4
|
+
right_chimp (1.0.7)
|
5
|
+
nokogiri (~> 1.5.9)
|
5
6
|
progressbar (~> 0.11.0)
|
6
7
|
rake (~> 0.9.2.2)
|
7
8
|
rest-client (~> 1.6.7)
|
8
|
-
rest_connection (~> 1.0.
|
9
|
+
rest_connection (~> 1.0.10)
|
9
10
|
|
10
11
|
GEM
|
11
12
|
remote: https://rubygems.org/
|
@@ -14,23 +15,23 @@ GEM
|
|
14
15
|
i18n (= 0.6.1)
|
15
16
|
multi_json (~> 1.0)
|
16
17
|
diff-lcs (1.1.3)
|
17
|
-
highline (1.6.
|
18
|
+
highline (1.6.19)
|
18
19
|
i18n (0.6.1)
|
19
|
-
json (1.
|
20
|
+
json (1.8.0)
|
20
21
|
mime-types (1.23)
|
21
|
-
multi_json (1.7.
|
22
|
+
multi_json (1.7.7)
|
22
23
|
net-ssh (2.6.7)
|
23
|
-
nokogiri (1.5.
|
24
|
+
nokogiri (1.5.10)
|
24
25
|
progressbar (0.11.0)
|
25
26
|
rake (0.9.2.2)
|
26
27
|
rest-client (1.6.7)
|
27
28
|
mime-types (>= 1.16)
|
28
|
-
rest_connection (1.0.
|
29
|
+
rest_connection (1.0.10)
|
29
30
|
activesupport
|
30
31
|
highline
|
31
32
|
json
|
32
33
|
net-ssh
|
33
|
-
nokogiri
|
34
|
+
nokogiri (< 1.6.0)
|
34
35
|
rest-client
|
35
36
|
rspec (2.6.0)
|
36
37
|
rspec-core (~> 2.6.0)
|
data/chimp.gemspec
CHANGED
@@ -17,11 +17,12 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
|
-
|
21
|
-
s.add_dependency "
|
20
|
+
|
21
|
+
s.add_dependency "rest_connection", "~> 1.0.10"
|
22
22
|
s.add_dependency "rest-client", "~> 1.6.7"
|
23
23
|
s.add_dependency "rake", "~> 0.9.2.2"
|
24
|
-
s.add_dependency "
|
24
|
+
s.add_dependency "nokogiri", "~> 1.5.9"
|
25
|
+
s.add_dependency "progressbar", "~> 0.11.0"
|
25
26
|
|
26
|
-
s.add_development_dependency "rspec", "~> 2.6.0"
|
27
|
+
s.add_development_dependency "rspec", "~> 2.6.0"
|
27
28
|
end
|
data/lib/right_chimp/Chimp.rb
CHANGED
@@ -892,35 +892,24 @@ module Chimp
|
|
892
892
|
#
|
893
893
|
def chimpd_wait_until_done
|
894
894
|
local_queue = ChimpQueue.instance
|
895
|
+
$stdout.print "Waiting for chimpd jobs to complete for group #{@group}..."
|
895
896
|
|
896
897
|
begin
|
897
|
-
while
|
898
|
+
while !@dry_run
|
898
899
|
local_queue = ChimpQueue.instance
|
899
900
|
|
900
901
|
#
|
901
902
|
# load up remote chimpd jobs into the local queue
|
902
903
|
# this makes all the standard queue control methods available to us
|
903
904
|
#
|
904
|
-
retry_count = 1
|
905
905
|
while true
|
906
906
|
local_queue.reset!
|
907
907
|
|
908
908
|
begin
|
909
|
-
puts "Waiting for chimpd jobs to complete for group #{@group}..."
|
910
909
|
all = ChimpDaemonClient.retrieve_group_info(@chimpd_host, @chimpd_port, @group, :all)
|
911
910
|
rescue RestClient::ResourceNotFound
|
912
|
-
|
913
|
-
|
914
|
-
sleep 5
|
915
|
-
retry
|
916
|
-
end
|
917
|
-
|
918
|
-
if @ignore_errors
|
919
|
-
exit 0
|
920
|
-
else
|
921
|
-
$stderr.puts "ERROR: Group \"#{group}\" not found!"
|
922
|
-
exit 1
|
923
|
-
end
|
911
|
+
sleep 5
|
912
|
+
retry
|
924
913
|
end
|
925
914
|
|
926
915
|
ChimpQueue.instance.create_group(@group)
|
@@ -6,36 +6,38 @@
|
|
6
6
|
|
7
7
|
module Chimp
|
8
8
|
class ChimpDaemon
|
9
|
-
attr_accessor :verbose, :debug, :port, :concurrency, :delay, :retry_count, :dry_run, :logfile
|
9
|
+
attr_accessor :verbose, :debug, :port, :concurrency, :delay, :retry_count, :dry_run, :logfile, :chimp_queue
|
10
10
|
attr_reader :queue, :running
|
11
|
-
|
11
|
+
|
12
12
|
include Singleton
|
13
|
-
|
13
|
+
|
14
14
|
def initialize
|
15
15
|
@verbose = false
|
16
16
|
@debug = false
|
17
17
|
@port = 9055
|
18
18
|
@concurrency = 50
|
19
19
|
@delay = 0
|
20
|
-
@retry_count = 0
|
20
|
+
@retry_count = 0
|
21
21
|
@threads = []
|
22
22
|
@running = false
|
23
23
|
@queue = ChimpQueue.instance
|
24
|
+
@chimp_queue = Queue.new
|
24
25
|
end
|
25
|
-
|
26
|
+
|
26
27
|
#
|
27
28
|
# Main entry point for chimpd command line application
|
28
29
|
#
|
29
30
|
def run
|
30
31
|
install_signal_handlers
|
31
32
|
parse_command_line
|
32
|
-
|
33
|
+
|
33
34
|
puts "chimpd #{VERSION} launching with #{@concurrency} workers"
|
34
35
|
spawn_queue_runner
|
35
36
|
spawn_webserver
|
37
|
+
spawn_chimpd_submission_processor
|
36
38
|
run_forever
|
37
39
|
end
|
38
|
-
|
40
|
+
|
39
41
|
#
|
40
42
|
# Parse chimpd command line options
|
41
43
|
#
|
@@ -51,7 +53,7 @@ module Chimp
|
|
51
53
|
[ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
52
54
|
[ '--exit', '-x', GetoptLong::NO_ARGUMENT ]
|
53
55
|
)
|
54
|
-
|
56
|
+
|
55
57
|
opts.each do |opt, arg|
|
56
58
|
case opt
|
57
59
|
when '--logfile', '-l'
|
@@ -79,52 +81,58 @@ module Chimp
|
|
79
81
|
puts "Syntax: chimpd [--logfile=<name>] [--concurrency=<c>] [--delay=<d>] [--retry=<r>] [--port=<p>] [--verbose]"
|
80
82
|
exit 1
|
81
83
|
end
|
82
|
-
|
84
|
+
|
83
85
|
#
|
84
86
|
# Set up logging/verbosity
|
85
87
|
#
|
86
88
|
Chimp.set_verbose(@verbose, @quiet)
|
87
|
-
|
89
|
+
|
88
90
|
if not @verbose
|
89
91
|
ENV['REST_CONNECTION_LOG'] = "/dev/null"
|
90
92
|
ENV['RESTCLIENT_LOG'] = "/dev/null"
|
91
93
|
end
|
94
|
+
|
95
|
+
if @quiet
|
96
|
+
Log.threshold = Logger::WARN
|
97
|
+
end
|
98
|
+
|
92
99
|
end
|
93
|
-
|
100
|
+
|
94
101
|
#
|
95
102
|
# Spawn the ChimpQueue threads
|
96
103
|
#
|
97
|
-
def spawn_queue_runner
|
104
|
+
def spawn_queue_runner
|
98
105
|
@queue.max_threads = @concurrency
|
99
106
|
@queue.delay = @delay
|
100
107
|
@queue.retry_count = @retry_count
|
101
108
|
@queue.start
|
102
109
|
@running = true
|
103
110
|
end
|
104
|
-
|
111
|
+
|
105
112
|
#
|
106
113
|
# Spawn a WEBrick Web server
|
107
114
|
#
|
108
115
|
def spawn_webserver
|
109
116
|
opts = {
|
110
|
-
:BindAddress => "localhost",
|
117
|
+
:BindAddress => "localhost",
|
111
118
|
:Port => @port,
|
112
|
-
:MaxClients =>
|
113
|
-
:RequestTimeout =>
|
119
|
+
:MaxClients => 500,
|
120
|
+
:RequestTimeout => 120,
|
121
|
+
:DoNotReverseLookup => true
|
114
122
|
}
|
115
|
-
|
123
|
+
|
116
124
|
if not @verbose
|
117
125
|
opts[:Logger] = WEBrick::Log.new("/dev/null")
|
118
126
|
opts[:AccessLog] = [nil, nil]
|
119
127
|
end
|
120
128
|
|
121
|
-
@server = ::WEBrick::HTTPServer.new(opts)
|
129
|
+
@server = ::WEBrick::HTTPServer.new(opts)
|
122
130
|
@server.mount('/', DisplayServlet)
|
123
131
|
@server.mount('/display', DisplayServlet)
|
124
132
|
@server.mount('/job', JobServlet)
|
125
133
|
@server.mount('/group', GroupServlet)
|
126
134
|
@server.mount('/admin', AdminServlet)
|
127
|
-
|
135
|
+
|
128
136
|
#
|
129
137
|
# WEBrick threads
|
130
138
|
#
|
@@ -132,7 +140,7 @@ module Chimp
|
|
132
140
|
@server.start
|
133
141
|
end
|
134
142
|
end
|
135
|
-
|
143
|
+
|
136
144
|
#
|
137
145
|
# Process requests forever until we're killed
|
138
146
|
#
|
@@ -144,18 +152,18 @@ module Chimp
|
|
144
152
|
end
|
145
153
|
end
|
146
154
|
end
|
147
|
-
|
155
|
+
|
148
156
|
#
|
149
157
|
# Trap signals to exit cleanly
|
150
158
|
#
|
151
159
|
def install_signal_handlers
|
152
|
-
['INT', 'TERM'].each do |signal|
|
160
|
+
['INT', 'TERM'].each do |signal|
|
153
161
|
trap(signal) do
|
154
162
|
self.quit
|
155
163
|
end
|
156
164
|
end
|
157
165
|
end
|
158
|
-
|
166
|
+
|
159
167
|
#
|
160
168
|
# Quit by waiting for all chimp jobs to finish, not allowing
|
161
169
|
# new jobs on the queue, and killing the web server.
|
@@ -168,7 +176,51 @@ module Chimp
|
|
168
176
|
sleep 5
|
169
177
|
exit 0
|
170
178
|
end
|
171
|
-
|
179
|
+
|
180
|
+
#
|
181
|
+
# Spawn threads to process submitted requests
|
182
|
+
#
|
183
|
+
def spawn_chimpd_submission_processor
|
184
|
+
n = @concurrency/4
|
185
|
+
n = 10 if n < 10
|
186
|
+
Log.debug "Logging into API..."
|
187
|
+
|
188
|
+
#
|
189
|
+
# There is a race condition logging in with rest_connection.
|
190
|
+
# As a workaround, do a tag query first thing when chimpd starts.
|
191
|
+
#
|
192
|
+
begin
|
193
|
+
c = Chimp.new
|
194
|
+
c.interactive = false
|
195
|
+
c.quiet = true
|
196
|
+
c.tags = ["bogus:tag=true"]
|
197
|
+
c.run
|
198
|
+
rescue StandardError
|
199
|
+
end
|
200
|
+
|
201
|
+
Log.debug "Spawning #{n} submission processing threads"
|
202
|
+
(1..n).each do |n|
|
203
|
+
@threads ||=[]
|
204
|
+
@threads << Thread.new {
|
205
|
+
while true
|
206
|
+
begin
|
207
|
+
queued_request = @chimp_queue.pop
|
208
|
+
group = queued_request.group
|
209
|
+
queued_request.interactive = false
|
210
|
+
|
211
|
+
tasks = queued_request.process
|
212
|
+
tasks.each do |task|
|
213
|
+
ChimpQueue.instance.push(group, task)
|
214
|
+
end
|
215
|
+
|
216
|
+
rescue StandardError => ex
|
217
|
+
Log.error "submission processor: group=\"#{group}\" script=\"#{queued_request.script}\": #{ex}"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
}
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
172
224
|
#
|
173
225
|
# GenericServlet -- servlet superclass
|
174
226
|
#
|
@@ -176,13 +228,13 @@ module Chimp
|
|
176
228
|
def get_verb(req)
|
177
229
|
r = req.request_uri.path.split('/')[2]
|
178
230
|
end
|
179
|
-
|
231
|
+
|
180
232
|
def get_id(req)
|
181
233
|
uri_parts = req.request_uri.path.split('/')
|
182
234
|
id = uri_parts[-2]
|
183
235
|
return id
|
184
236
|
end
|
185
|
-
|
237
|
+
|
186
238
|
#
|
187
239
|
# Get the body of the request-- assume YAML
|
188
240
|
#
|
@@ -194,7 +246,7 @@ module Chimp
|
|
194
246
|
end
|
195
247
|
end
|
196
248
|
end # GenericServlet
|
197
|
-
|
249
|
+
|
198
250
|
#
|
199
251
|
# AdminServlet - admin functions
|
200
252
|
#
|
@@ -206,11 +258,11 @@ module Chimp
|
|
206
258
|
if shutdown == true
|
207
259
|
ChimpDaemon.instance.quit
|
208
260
|
end
|
209
|
-
|
210
|
-
raise WEBrick::HTTPStatus::OK
|
261
|
+
|
262
|
+
raise WEBrick::HTTPStatus::OK
|
211
263
|
end
|
212
|
-
end # AdminServlet
|
213
|
-
|
264
|
+
end # AdminServlet
|
265
|
+
|
214
266
|
#
|
215
267
|
# GroupServlet - group information and control
|
216
268
|
#
|
@@ -223,17 +275,17 @@ module Chimp
|
|
223
275
|
#
|
224
276
|
def do_GET(req, resp)
|
225
277
|
jobs = {}
|
226
|
-
|
278
|
+
|
227
279
|
group_name = req.request_uri.path.split('/')[-2]
|
228
280
|
filter = req.request_uri.path.split('/')[-1]
|
229
|
-
|
281
|
+
|
230
282
|
g = ChimpQueue[group_name.to_sym]
|
231
283
|
raise WEBrick::HTTPStatus::NotFound, "Group not found" unless g
|
232
284
|
jobs = g.get_jobs_by_status(filter)
|
233
285
|
resp.body = jobs.to_yaml
|
234
286
|
raise WEBrick::HTTPStatus::OK
|
235
287
|
end
|
236
|
-
|
288
|
+
|
237
289
|
#
|
238
290
|
# POST to a group to trigger a group action
|
239
291
|
# /group/<name>/<action>
|
@@ -245,21 +297,21 @@ module Chimp
|
|
245
297
|
|
246
298
|
if filter == 'create'
|
247
299
|
ChimpQueue.instance.create_group(group_name, payload['type'], payload['concurrency'])
|
248
|
-
|
300
|
+
|
249
301
|
elsif filter == 'retry'
|
250
302
|
group = ChimpQueue[group_name.to_sym]
|
251
303
|
raise WEBrick::HTTPStatus::NotFound, "Group not found" unless group
|
252
|
-
|
304
|
+
|
253
305
|
group.requeue_failed_jobs!
|
254
306
|
raise WEBrick::HTTPStatus::OK
|
255
|
-
|
307
|
+
|
256
308
|
else
|
257
309
|
raise WEBrick::HTTPStatus::PreconditionFailed.new("invalid action")
|
258
310
|
end
|
259
311
|
end
|
260
|
-
|
312
|
+
|
261
313
|
end
|
262
|
-
|
314
|
+
|
263
315
|
#
|
264
316
|
# JobServlet - job control
|
265
317
|
#
|
@@ -273,20 +325,23 @@ module Chimp
|
|
273
325
|
|
274
326
|
payload = self.get_payload(req)
|
275
327
|
raise WEBrick::HTTPStatus::PreconditionFailed.new('missing payload') unless payload
|
276
|
-
|
328
|
+
|
277
329
|
q = ChimpQueue.instance
|
278
330
|
group = payload.group
|
279
|
-
|
331
|
+
|
280
332
|
#
|
281
333
|
# Ask chimpd to process a Chimp object directly
|
282
334
|
#
|
335
|
+
#if verb == 'process' or verb == 'add'
|
336
|
+
# payload.interactive = false
|
337
|
+
# tasks = payload.process
|
338
|
+
# tasks.each do |task|
|
339
|
+
# q.push(group, task)
|
340
|
+
# end
|
341
|
+
|
283
342
|
if verb == 'process' or verb == 'add'
|
284
|
-
|
285
|
-
|
286
|
-
tasks.each do |task|
|
287
|
-
q.push(group, task)
|
288
|
-
end
|
289
|
-
|
343
|
+
ChimpDaemon.instance.chimp_queue.push payload
|
344
|
+
id = 0
|
290
345
|
elsif verb == 'update'
|
291
346
|
puts "UPDATE"
|
292
347
|
q.get_job(job_id).status = payload.status
|
@@ -295,28 +350,28 @@ module Chimp
|
|
295
350
|
resp.body = {
|
296
351
|
'id' => id
|
297
352
|
}.to_yaml
|
298
|
-
|
353
|
+
|
299
354
|
raise WEBrick::HTTPStatus::OK
|
300
355
|
end
|
301
|
-
|
356
|
+
|
302
357
|
def do_GET(req, resp)
|
303
358
|
id = self.get_id(req)
|
304
359
|
verb = self.get_verb(req)
|
305
360
|
job_results = "OK"
|
306
361
|
queue = ChimpQueue.instance
|
307
|
-
|
362
|
+
|
308
363
|
#
|
309
364
|
# check for special job ids
|
310
365
|
#
|
311
|
-
jobs = []
|
366
|
+
jobs = []
|
312
367
|
jobs << queue.get_job(id.to_i)
|
313
|
-
|
368
|
+
|
314
369
|
jobs = queue.get_jobs_by_status(:running) if id == 'running'
|
315
370
|
jobs = queue.get_jobs_by_status(:error) if id == 'error'
|
316
371
|
jobs = queue.get_jobs if id == 'all'
|
317
|
-
|
372
|
+
|
318
373
|
raise WEBrick::HTTPStatus::PreconditionFailed.new('invalid or missing job_id #{id}') unless jobs.size > 0
|
319
|
-
|
374
|
+
|
320
375
|
#
|
321
376
|
# ACK a job -- mark it as successful even if it failed
|
322
377
|
#
|
@@ -324,9 +379,9 @@ module Chimp
|
|
324
379
|
jobs.each do |j|
|
325
380
|
j.status = Executor::STATUS_DONE
|
326
381
|
end
|
327
|
-
|
382
|
+
|
328
383
|
resp.set_redirect( WEBrick::HTTPStatus::TemporaryRedirect, req.header['referer'])
|
329
|
-
|
384
|
+
|
330
385
|
#
|
331
386
|
# retry a job
|
332
387
|
#
|
@@ -334,9 +389,9 @@ module Chimp
|
|
334
389
|
jobs.each do |j|
|
335
390
|
j.requeue
|
336
391
|
end
|
337
|
-
|
392
|
+
|
338
393
|
resp.set_redirect( WEBrick::HTTPStatus::TemporaryRedirect, req.header['referer'])
|
339
|
-
|
394
|
+
|
340
395
|
#
|
341
396
|
# cancel an active job
|
342
397
|
#
|
@@ -344,9 +399,9 @@ module Chimp
|
|
344
399
|
jobs.each do |j|
|
345
400
|
j.cancel if j.respond_to? :cancel
|
346
401
|
end
|
347
|
-
|
402
|
+
|
348
403
|
resp.set_redirect( WEBrick::HTTPStatus::TemporaryRedirect, req.header['referer'])
|
349
|
-
|
404
|
+
|
350
405
|
#
|
351
406
|
# produce a report
|
352
407
|
#
|
@@ -355,17 +410,17 @@ module Chimp
|
|
355
410
|
jobs.each do |j|
|
356
411
|
results << [j.group.group_id, j.class.to_s.sub("Chimp::",""), j.job_id, j.info, j.target, j.time_start, j.time_end, j.get_total_exec_time, j.status].join(",")
|
357
412
|
end
|
358
|
-
|
413
|
+
|
359
414
|
queue.group.values.each do |g|
|
360
415
|
results << [g.group_id, g.class.to_s.sub("Chimp::",""), "", "", "", g.time_start, g.time_end, g.get_total_exec_time, ""].join(",")
|
361
416
|
end
|
362
|
-
|
417
|
+
|
363
418
|
job_results = results.join("\n") + "\n"
|
364
|
-
|
419
|
+
|
365
420
|
resp['Content-type'] = "text/csv"
|
366
421
|
resp['Content-disposition'] = "attachment;filename=chimp.csv"
|
367
422
|
end
|
368
|
-
|
423
|
+
|
369
424
|
#
|
370
425
|
# return a list of the results
|
371
426
|
#
|
@@ -373,7 +428,7 @@ module Chimp
|
|
373
428
|
raise WEBrick::HTTPStatus::OK
|
374
429
|
end
|
375
430
|
end # JobServlet
|
376
|
-
|
431
|
+
|
377
432
|
#
|
378
433
|
# DisplayServlet
|
379
434
|
#
|
@@ -387,14 +442,14 @@ module Chimp
|
|
387
442
|
else
|
388
443
|
template_file_name = 'lib/right_chimp/templates/all_jobs.erb'
|
389
444
|
end
|
390
|
-
|
445
|
+
|
391
446
|
@template = ERB.new(File.read(template_file_name), nil, ">")
|
392
447
|
end
|
393
|
-
|
394
|
-
queue = ChimpQueue.instance
|
448
|
+
|
449
|
+
queue = ChimpQueue.instance
|
395
450
|
jobs = queue.get_jobs
|
396
451
|
group_name = nil
|
397
|
-
|
452
|
+
|
398
453
|
if job_filter == "group"
|
399
454
|
group_name = req.request_uri.path.split('/')[-1]
|
400
455
|
g = ChimpQueue[group_name.to_sym]
|
@@ -405,12 +460,10 @@ module Chimp
|
|
405
460
|
count_jobs_queued = queue.get_jobs_by_status(:none).size
|
406
461
|
count_jobs_failed = queue.get_jobs_by_status(:error).size
|
407
462
|
count_jobs_done = queue.get_jobs_by_status(:done).size
|
408
|
-
|
463
|
+
|
409
464
|
resp.body = @template.result(binding)
|
410
465
|
raise WEBrick::HTTPStatus::OK
|
411
466
|
end
|
412
467
|
end # DisplayServlet
|
413
|
-
end
|
468
|
+
end # ChimpDaemon
|
414
469
|
end
|
415
|
-
|
416
|
-
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Chimp
|
2
2
|
#
|
3
|
-
# The ChimpDaemonClient contains the code for communicating with the
|
3
|
+
# The ChimpDaemonClient contains the code for communicating with the
|
4
4
|
# RESTful chimpd Web service
|
5
5
|
#
|
6
6
|
class ChimpDaemonClient
|
@@ -9,23 +9,53 @@ module Chimp
|
|
9
9
|
#
|
10
10
|
def self.submit(host, port, chimp_object)
|
11
11
|
uri = "http://#{host}:#{port}/job/process"
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
attempts = 3
|
13
|
+
|
14
|
+
begin
|
15
|
+
response = RestClient.post uri, chimp_object.to_yaml
|
16
|
+
|
17
|
+
if response.code > 199 and response.code < 300
|
16
18
|
id = YAML::load(response.body)['id']
|
17
|
-
|
18
|
-
|
19
|
+
return true
|
20
|
+
else
|
21
|
+
$stderr.puts "WARNING: error submitting to chimpd! response code: #{reponse.code}"
|
22
|
+
return false
|
19
23
|
end
|
20
|
-
|
21
|
-
|
24
|
+
|
25
|
+
rescue RestClient::RequestTimeout => ex
|
26
|
+
$stderr.puts "WARNING: Request timeout talking to chimpd for job #{chimp_object.script}: #{ex.message} (#{ex.http_code})"
|
27
|
+
attempts -= 1
|
28
|
+
sleep 5 and retry if attempts > 0
|
29
|
+
return false
|
30
|
+
|
31
|
+
rescue RestClient::InternalServerError => ex
|
32
|
+
$stderr.puts "WARNING: Error submitting job to chimpd: #{error_message}, retrying..."
|
33
|
+
attempts -= 1
|
34
|
+
sleep 5 and retry if attempts > 0
|
35
|
+
return false
|
36
|
+
|
37
|
+
rescue Errno::ECONNRESET => ex
|
38
|
+
$stderr.puts "WARNING: Connection reset by peer, retrying..."
|
39
|
+
attempts -= 1
|
40
|
+
sleep 5 and retry if attempts > 0
|
41
|
+
return false
|
42
|
+
|
43
|
+
rescue Errno::EPIPE => ex
|
44
|
+
$stderr.puts "WARNING: broken pipe, retrying..."
|
45
|
+
attempts -= 1
|
46
|
+
sleep 5 and retry if attempts > 0
|
47
|
+
return false
|
48
|
+
|
49
|
+
rescue Errno::ECONNREFUSED => ex
|
50
|
+
$stderr.puts "ERROR: connection refused, aborting"
|
51
|
+
return false
|
52
|
+
|
53
|
+
rescue RestClient::Exception => ex
|
54
|
+
$stderr.puts "ERROR: Error submitting job to chimpd #{chimp_object.script}: #{ex.message}"
|
22
55
|
return false
|
23
56
|
end
|
24
|
-
|
25
|
-
puts "chimpd submission complete"
|
26
|
-
return true
|
27
57
|
end
|
28
|
-
|
58
|
+
|
29
59
|
#
|
30
60
|
# quit a remote chimpd
|
31
61
|
#
|
@@ -43,32 +73,32 @@ module Chimp
|
|
43
73
|
jobs = YAML::load(response.body)
|
44
74
|
return jobs
|
45
75
|
end
|
46
|
-
|
76
|
+
|
47
77
|
def self.retrieve_group_info(host, port, group_name, status)
|
48
78
|
uri = "http://#{host}:#{port}/group/#{group_name}/#{status}"
|
49
79
|
response = RestClient.get uri
|
50
80
|
group = YAML::load(response.body)
|
51
81
|
return group
|
52
82
|
end
|
53
|
-
|
83
|
+
|
54
84
|
def self.set_job_status(host, port, job_id, status)
|
55
85
|
uri = "http://#{host}:#{port}/job/#{job_id}/update"
|
56
86
|
response = RestClient.post uri, { :status => status}
|
57
87
|
return YAML::load(response.body)
|
58
88
|
end
|
59
|
-
|
89
|
+
|
60
90
|
def self.create_group(host, port, name, type, concurrency)
|
61
91
|
uri = "http://#{host}:#{port}/group/#{name}/create"
|
62
92
|
payload = { 'type' => type, 'concurrency' => concurrency }.to_yaml
|
63
93
|
response = RestClient.post(uri, payload)
|
64
94
|
return YAML::load(response.body)
|
65
95
|
end
|
66
|
-
|
96
|
+
|
67
97
|
def self.retry_group(host, port, group_name)
|
68
98
|
uri = "http://#{host}:#{port}/group/#{group_name}/retry"
|
69
99
|
response = RestClient.post(uri, {})
|
70
100
|
return YAML::load(response.body)
|
71
101
|
end
|
72
|
-
|
102
|
+
|
73
103
|
end
|
74
|
-
end
|
104
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Chimp
|
2
|
-
|
2
|
+
|
3
3
|
#
|
4
4
|
# Factory
|
5
5
|
#
|
@@ -14,7 +14,7 @@ module Chimp
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
#
|
19
19
|
# An ExecutionGroup contains a set of Executors to be processed
|
20
20
|
#
|
@@ -24,7 +24,7 @@ module Chimp
|
|
24
24
|
class ExecutionGroup
|
25
25
|
attr_accessor :group_id, :description, :concurrency
|
26
26
|
attr_reader :time_start, :time_end
|
27
|
-
|
27
|
+
|
28
28
|
def initialize(new_group_id=nil)
|
29
29
|
@group_id = new_group_id
|
30
30
|
@queue = []
|
@@ -34,18 +34,18 @@ module Chimp
|
|
34
34
|
@time_end = nil
|
35
35
|
@concurrency = 1
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
#
|
39
39
|
# Add something to the work queue
|
40
|
-
#
|
40
|
+
#
|
41
41
|
def push(j)
|
42
|
-
raise "invalid work" if j == nil
|
42
|
+
raise "invalid work" if j == nil
|
43
43
|
j.job_id = IDManager.get if j.job_id == nil
|
44
44
|
j.group = self
|
45
45
|
@queue.push(j)
|
46
46
|
@jobs_by_id[j.job_id] = j
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
#
|
50
50
|
# Take something from the queue
|
51
51
|
#
|
@@ -54,7 +54,7 @@ module Chimp
|
|
54
54
|
@time_start = Time.now if @time_start == nil
|
55
55
|
return x
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
#
|
59
59
|
# Return a hash of the results
|
60
60
|
#
|
@@ -62,7 +62,7 @@ module Chimp
|
|
62
62
|
return self.get_jobs.map do |task|
|
63
63
|
next if task == nil
|
64
64
|
next if task.server == nil
|
65
|
-
|
65
|
+
|
66
66
|
{
|
67
67
|
:job_id => task.job_id,
|
68
68
|
:name => task.info,
|
@@ -76,14 +76,14 @@ module Chimp
|
|
76
76
|
}
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
#
|
81
81
|
# Size of the active queue
|
82
82
|
#
|
83
83
|
def size
|
84
84
|
return @queue.size
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
#
|
88
88
|
# Sort queue by server nickname
|
89
89
|
#
|
@@ -94,35 +94,35 @@ module Chimp
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
#
|
99
99
|
# Reset the queue
|
100
100
|
#
|
101
101
|
def reset!
|
102
102
|
@queue = []
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
#
|
106
106
|
# Get all jobs
|
107
107
|
#
|
108
108
|
def get_jobs
|
109
109
|
@jobs_by_id.values
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
112
|
#
|
113
113
|
# Get all job ids
|
114
114
|
#
|
115
115
|
def get_job_ids
|
116
116
|
@jobs_by_id.keys
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
#
|
120
120
|
# Get a particular job
|
121
121
|
#
|
122
122
|
def get_job(i)
|
123
123
|
@jobs_by_id[i]
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
#
|
127
127
|
# Get jobs by status
|
128
128
|
#
|
@@ -133,11 +133,11 @@ module Chimp
|
|
133
133
|
end
|
134
134
|
return r
|
135
135
|
end
|
136
|
-
|
136
|
+
|
137
137
|
def job_completed
|
138
138
|
@time_end = Time.now
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
#
|
142
142
|
# Reset all jobs and bulk set them
|
143
143
|
#
|
@@ -147,7 +147,7 @@ module Chimp
|
|
147
147
|
self.push(job)
|
148
148
|
end
|
149
149
|
end
|
150
|
-
|
150
|
+
|
151
151
|
#
|
152
152
|
# An execution group is "ready" if it has work that can be done;
|
153
153
|
# see implementation in child classes.
|
@@ -155,19 +155,24 @@ module Chimp
|
|
155
155
|
def ready?
|
156
156
|
raise "unimplemented"
|
157
157
|
end
|
158
|
-
|
158
|
+
|
159
159
|
#
|
160
160
|
# An execution group is "done" if nothing is queued or running
|
161
|
+
# and at least one job has completed.
|
161
162
|
#
|
162
163
|
def done?
|
163
|
-
return (
|
164
|
+
return (
|
165
|
+
get_jobs_by_status(Executor::STATUS_NONE).size == 0 &&
|
166
|
+
get_jobs_by_status(Executor::STATUS_RUNNING).size == 0 &&
|
167
|
+
get_jobs_by_status(Executor::STATUS_DONE).size > 0
|
168
|
+
)
|
164
169
|
end
|
165
|
-
|
170
|
+
|
166
171
|
#
|
167
172
|
# Is this execution group running anything?
|
168
173
|
#
|
169
174
|
def running?
|
170
|
-
total_jobs_running = get_jobs_by_status(Executor::STATUS_NONE).size +
|
175
|
+
total_jobs_running = get_jobs_by_status(Executor::STATUS_NONE).size +
|
171
176
|
get_jobs_by_status(Executor::STATUS_RUNNING).size +
|
172
177
|
get_jobs_by_status(Executor::STATUS_RETRYING).size
|
173
178
|
return(total_jobs_running > 0)
|
@@ -193,7 +198,7 @@ module Chimp
|
|
193
198
|
job.time_end = nil
|
194
199
|
self.push(job)
|
195
200
|
end
|
196
|
-
|
201
|
+
|
197
202
|
#
|
198
203
|
# Cancel a job by id
|
199
204
|
#
|
@@ -205,7 +210,7 @@ module Chimp
|
|
205
210
|
job.time_end = Time.now
|
206
211
|
@queue.delete(job)
|
207
212
|
end
|
208
|
-
|
213
|
+
|
209
214
|
#
|
210
215
|
# Return total execution time
|
211
216
|
#
|
@@ -218,18 +223,18 @@ module Chimp
|
|
218
223
|
return @time_end.to_i- @time_start.to_i
|
219
224
|
end
|
220
225
|
end
|
221
|
-
|
226
|
+
|
222
227
|
#
|
223
228
|
# Print out ExecutionGroup information
|
224
229
|
#
|
225
230
|
def to_s
|
226
231
|
return "#{self.class}[#{group_id}]: ready=#{self.ready?} total_jobs=#{@jobs_by_id.size} queued_jobs=#{self.size}"
|
227
232
|
end
|
228
|
-
|
233
|
+
|
229
234
|
###################################
|
230
235
|
protected
|
231
236
|
###################################
|
232
|
-
|
237
|
+
|
233
238
|
#
|
234
239
|
# Return total execution time or -1 for errors
|
235
240
|
#
|
@@ -238,7 +243,7 @@ module Chimp
|
|
238
243
|
end
|
239
244
|
|
240
245
|
end
|
241
|
-
|
246
|
+
|
242
247
|
#
|
243
248
|
# SerialExecutionGroup: run only one job at a time
|
244
249
|
#
|
@@ -246,12 +251,12 @@ module Chimp
|
|
246
251
|
def ready?
|
247
252
|
return get_jobs_by_status(Executor::STATUS_RUNNING).size == 0 && get_jobs_by_status(Executor::STATUS_NONE).size > 0
|
248
253
|
end
|
249
|
-
|
254
|
+
|
250
255
|
def short_name
|
251
256
|
"S"
|
252
257
|
end
|
253
258
|
end
|
254
|
-
|
259
|
+
|
255
260
|
#
|
256
261
|
# ParallelExecutionGroup: run multiple jobs at once
|
257
262
|
#
|
@@ -260,7 +265,7 @@ module Chimp
|
|
260
265
|
super(new_group_id)
|
261
266
|
@concurrency = 25
|
262
267
|
end
|
263
|
-
|
268
|
+
|
264
269
|
#
|
265
270
|
# FIXME - we're not currently using the @concurrency setting to limit execution
|
266
271
|
# due to an unknown bug...
|
@@ -268,7 +273,7 @@ module Chimp
|
|
268
273
|
def ready?
|
269
274
|
return (get_jobs_by_status(Executor::STATUS_NONE).size > 0) # and get_jobs_by_status(Executor::STATUS_RUNNING).size < @concurrency)
|
270
275
|
end
|
271
|
-
|
276
|
+
|
272
277
|
def short_name
|
273
278
|
"P"
|
274
279
|
end
|
data/lib/right_chimp/version.rb
CHANGED
metadata
CHANGED
@@ -1,32 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_chimp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Christopher Deutsch
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-24 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: rest_connection
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
21
|
+
version: 1.0.10
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
29
|
+
version: 1.0.10
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: rest-client
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ~>
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,6 +38,7 @@ dependencies:
|
|
34
38
|
type: :runtime
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ~>
|
39
44
|
- !ruby/object:Gem::Version
|
@@ -41,6 +46,7 @@ dependencies:
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: rake
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
51
|
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
@@ -48,27 +54,47 @@ dependencies:
|
|
48
54
|
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
54
61
|
version: 0.9.2.2
|
55
62
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
63
|
+
name: nokogiri
|
57
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
58
66
|
requirements:
|
59
67
|
- - ~>
|
60
68
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.
|
69
|
+
version: 1.5.9
|
62
70
|
type: :runtime
|
63
71
|
prerelease: false
|
64
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
65
74
|
requirements:
|
66
75
|
- - ~>
|
67
76
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.
|
77
|
+
version: 1.5.9
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: progressbar
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.11.0
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.11.0
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: rspec
|
71
96
|
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
72
98
|
requirements:
|
73
99
|
- - ~>
|
74
100
|
- !ruby/object:Gem::Version
|
@@ -76,6 +102,7 @@ dependencies:
|
|
76
102
|
type: :development
|
77
103
|
prerelease: false
|
78
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
79
106
|
requirements:
|
80
107
|
- - ~>
|
81
108
|
- !ruby/object:Gem::Version
|
@@ -127,26 +154,27 @@ files:
|
|
127
154
|
- spec/spec_selection.rb
|
128
155
|
homepage: https://github.com/rightscale/right_chimp
|
129
156
|
licenses: []
|
130
|
-
metadata: {}
|
131
157
|
post_install_message:
|
132
158
|
rdoc_options: []
|
133
159
|
require_paths:
|
134
160
|
- lib
|
135
161
|
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
none: false
|
136
163
|
requirements:
|
137
|
-
- - '>='
|
164
|
+
- - ! '>='
|
138
165
|
- !ruby/object:Gem::Version
|
139
166
|
version: '0'
|
140
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
none: false
|
141
169
|
requirements:
|
142
|
-
- - '>='
|
170
|
+
- - ! '>='
|
143
171
|
- !ruby/object:Gem::Version
|
144
172
|
version: '0'
|
145
173
|
requirements: []
|
146
174
|
rubyforge_project:
|
147
|
-
rubygems_version:
|
175
|
+
rubygems_version: 1.8.23
|
148
176
|
signing_key:
|
149
|
-
specification_version:
|
177
|
+
specification_version: 3
|
150
178
|
summary: RightScale platform command-line tool
|
151
179
|
test_files:
|
152
180
|
- spec/spec_chimp.rb
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 1562feef06b0bcc0b1c87bd55c8421abafd7ca26
|
4
|
-
data.tar.gz: 724add71f798b34e6a4a4e37e2611c90d60e44b0
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 5aee4d9a399b1a0b7dc99b0b05640bb372ced0015a54f61caff3f9e7b0ab01186be690d94ffa5a0c1eaeb4fa2e8f5f07c68ddb547561630cfe4a5d15953c21bb
|
7
|
-
data.tar.gz: 6d1ec02570a46c928512df6b0387759faad9a15b7774d4ed408a5fd14f693da8d1d5af97cbe8fc5d35eb5d052062d689ea60963f2d664979a4fdea3b50f3da58
|