right_chimp 1.1.3 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,11 @@
1
1
  module Chimp
2
2
  class Log
3
3
  @@logger = Logger.new(STDOUT)
4
+
5
+ # SeverityID, [DateTime #pid] SeverityLabel -- ProgName: message
6
+ @@logger.datetime_format = '%H:%M:%S'
4
7
  @@logger.sev_threshold=Logger::INFO
5
-
8
+
6
9
  def self.logger=(l)
7
10
  @@logger = l
8
11
  end
@@ -18,7 +21,7 @@ module Chimp
18
21
  def self.debug(m)
19
22
  @@logger.debug(m)
20
23
  end
21
-
24
+
22
25
  def self.info(m)
23
26
  @@logger.info(m)
24
27
  end
@@ -26,9 +29,9 @@ module Chimp
26
29
  def self.warn(m)
27
30
  @@logger.warn(m)
28
31
  end
29
-
32
+
30
33
  def self.error(m)
31
34
  @@logger.error(m)
32
- end
35
+ end
33
36
  end
34
37
  end
@@ -6,6 +6,7 @@
6
6
 
7
7
  module Chimp
8
8
  class ChimpDaemon
9
+
9
10
  attr_accessor :verbose, :debug, :port, :concurrency, :delay, :retry_count, :dry_run, :logfile, :chimp_queue
10
11
  attr_reader :queue, :running
11
12
 
@@ -22,6 +23,9 @@ module Chimp
22
23
  @running = false
23
24
  @queue = ChimpQueue.instance
24
25
  @chimp_queue = Queue.new
26
+
27
+ #Connect to the API
28
+ Connection.instance
25
29
  end
26
30
 
27
31
  #
@@ -31,7 +35,8 @@ module Chimp
31
35
  install_signal_handlers
32
36
  parse_command_line
33
37
 
34
- puts "chimpd #{VERSION} launching with #{@concurrency} workers"
38
+ #puts "chimpd #{VERSION} launching with #{@concurrency} workers"
39
+ puts "Loading... please wait"
35
40
  spawn_queue_runner
36
41
  spawn_webserver
37
42
  spawn_chimpd_submission_processor
@@ -51,6 +56,7 @@ module Chimp
51
56
  [ '--delay', '-d', GetoptLong::REQUIRED_ARGUMENT ],
52
57
  [ '--retry', '-y', GetoptLong::REQUIRED_ARGUMENT ],
53
58
  [ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT ],
59
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
54
60
  [ '--exit', '-x', GetoptLong::NO_ARGUMENT ]
55
61
  )
56
62
 
@@ -71,6 +77,8 @@ module Chimp
71
77
  @quiet = true
72
78
  when '--port', '-p'
73
79
  @port = arg
80
+ when '--help', '-h'
81
+ help
74
82
  when '--exit', '-x'
75
83
  uri = "http://localhost:#{@port}/admin"
76
84
  response = RestClient.post uri, { 'shutdown' => true }.to_yaml
@@ -90,12 +98,40 @@ module Chimp
90
98
  if not @verbose
91
99
  ENV['REST_CONNECTION_LOG'] = "/dev/null"
92
100
  ENV['RESTCLIENT_LOG'] = "/dev/null"
101
+ Log.threshold= Logger::INFO
102
+ else
103
+ Log.threshold= Logger::DEBUG
93
104
  end
94
105
 
95
106
  if @quiet
96
107
  Log.threshold = Logger::WARN
97
108
  end
109
+ end
98
110
 
111
+ #
112
+ # Print out help information
113
+ #
114
+ def help
115
+ puts
116
+ puts "chimpd -- a RightScale Platform command-line tool"
117
+ puts
118
+ puts "Syntax: chimpd [--logfile=<name>] [--concurrency=<c>] [--delay=<d>] [--retry=<r>] [--port=<p>] [--verbose]"
119
+ puts
120
+ puts "Options:"
121
+ puts
122
+ puts " --logfile=<name> Specifiy the desired log location"
123
+ puts " --concurrency=<n> Specify the level of concurrent actions"
124
+ puts " --delay=<n> Specify the number of seconds to wait before executing the action"
125
+ puts " --retry=<r> Specify the number of times chimpd should retry executing the action"
126
+ puts
127
+ puts " --verbose Run chimpd in verbose mode."
128
+ puts " --quiet Supress non-essential output"
129
+ puts
130
+ puts " --port=<port> Specify the port number for chimpd to listen on (default: 9055)"
131
+ puts
132
+ puts " --help Displays this menu"
133
+ puts
134
+ exit 0
99
135
  end
100
136
 
101
137
  #
@@ -168,8 +204,6 @@ module Chimp
168
204
  # Quit by waiting for all chimp jobs to finish, not allowing
169
205
  # new jobs on the queue, and killing the web server.
170
206
  #
171
- # TODO: call @queue.quit, but with a short timeout?
172
- #
173
207
  def quit
174
208
  @running = false
175
209
  @server.shutdown
@@ -193,12 +227,15 @@ module Chimp
193
227
  c = Chimp.new
194
228
  c.interactive = false
195
229
  c.quiet = true
196
- c.tags = ["bogus:tag=true"]
230
+ #c.tags = ["bogus:tag=true"]
197
231
  c.run
198
232
  rescue StandardError
199
233
  end
200
234
 
235
+ puts "chimpd #{VERSION} launched with #{@concurrency} workers"
236
+
201
237
  Log.debug "Spawning #{n} submission processing threads"
238
+
202
239
  (1..n).each do |n|
203
240
  @threads ||=[]
204
241
  @threads << Thread.new {
@@ -207,14 +244,14 @@ module Chimp
207
244
  queued_request = @chimp_queue.pop
208
245
  group = queued_request.group
209
246
  queued_request.interactive = false
210
-
211
247
  tasks = queued_request.process
212
248
  tasks.each do |task|
213
249
  ChimpQueue.instance.push(group, task)
214
250
  end
215
251
 
216
252
  rescue StandardError => ex
217
- Log.error "submission processor: group=\"#{group}\" script=\"#{queued_request.script}\": #{ex}"
253
+ puts ex.backtrace
254
+ Log.error " submission processor: group=\"#{group}\" script=\"#{queued_request.script}\": #{ex}"
218
255
  end
219
256
  end
220
257
  }
@@ -225,6 +262,11 @@ module Chimp
225
262
  # GenericServlet -- servlet superclass
226
263
  #
227
264
  class GenericServlet < WEBrick::HTTPServlet::AbstractServlet
265
+ #
266
+ # get_verb
267
+ # get_id
268
+ # get_payload
269
+ #
228
270
  def get_verb(req)
229
271
  r = req.request_uri.path.split('/')[2]
230
272
  end
@@ -235,6 +277,11 @@ module Chimp
235
277
  return id
236
278
  end
237
279
 
280
+ def get_job_uuid(req)
281
+ string = req.body.scan(/job_uuid: .{6}/).last
282
+ job_uuid = string.scan(/ (.{6})/).last.last
283
+ return job_uuid
284
+ end
238
285
  #
239
286
  # Get the body of the request-- assume YAML
240
287
  #
@@ -251,6 +298,9 @@ module Chimp
251
298
  # AdminServlet - admin functions
252
299
  #
253
300
  class AdminServlet < GenericServlet
301
+ #
302
+ # get do_POST
303
+ #
254
304
  def do_POST(req, resp)
255
305
  payload = self.get_payload(req)
256
306
  shutdown = payload['shutdown'] || false
@@ -269,6 +319,11 @@ module Chimp
269
319
  # http://localhost:9055/group/default/running
270
320
  #
271
321
  class GroupServlet < GenericServlet
322
+ #
323
+ # do_GET
324
+ # do_POST
325
+ #
326
+
272
327
  #
273
328
  # GET a group by name and status
274
329
  # /group/<name>/<status>
@@ -278,7 +333,6 @@ module Chimp
278
333
 
279
334
  group_name = req.request_uri.path.split('/')[-2]
280
335
  filter = req.request_uri.path.split('/')[-1]
281
-
282
336
  g = ChimpQueue[group_name.to_sym]
283
337
  raise WEBrick::HTTPStatus::NotFound, "Group not found" unless g
284
338
  jobs = g.get_jobs_by_status(filter)
@@ -309,8 +363,7 @@ module Chimp
309
363
  raise WEBrick::HTTPStatus::PreconditionFailed.new("invalid action")
310
364
  end
311
365
  end
312
-
313
- end
366
+ end # GroupServlet
314
367
 
315
368
  #
316
369
  # JobServlet - job control
@@ -318,9 +371,15 @@ module Chimp
318
371
  # HTTP body is a yaml serialized chimp object
319
372
  #
320
373
  class JobServlet < GenericServlet
374
+ #
375
+ # do_POST
376
+ # do_GET
377
+ #
378
+
321
379
  def do_POST(req, resp)
322
380
  id = -1
323
381
  job_id = self.get_id(req)
382
+ job_uuid= self.get_job_uuid(req)
324
383
  verb = self.get_verb(req)
325
384
 
326
385
  payload = self.get_payload(req)
@@ -338,7 +397,6 @@ module Chimp
338
397
  # tasks.each do |task|
339
398
  # q.push(group, task)
340
399
  # end
341
-
342
400
  if verb == 'process' or verb == 'add'
343
401
  ChimpDaemon.instance.chimp_queue.push payload
344
402
  id = 0
@@ -347,7 +405,9 @@ module Chimp
347
405
  q.get_job(job_id).status = payload.status
348
406
  end
349
407
 
408
+
350
409
  resp.body = {
410
+ 'job_uuid' => job_uuid ,
351
411
  'id' => id
352
412
  }.to_yaml
353
413
 
@@ -444,6 +504,10 @@ module Chimp
444
504
  # DisplayServlet
445
505
  #
446
506
  class DisplayServlet < GenericServlet
507
+ #
508
+ # do_GET
509
+ #
510
+
447
511
  def do_GET(req, resp)
448
512
  #
449
513
  # First determine the path to the files to serve
@@ -493,5 +557,6 @@ module Chimp
493
557
  end
494
558
  end
495
559
  end # DisplayServlet
560
+
496
561
  end # ChimpDaemon
497
562
  end
@@ -7,51 +7,59 @@ module Chimp
7
7
  #
8
8
  # Submit a Chimp object to a remote chimpd
9
9
  #
10
- def self.submit(host, port, chimp_object)
10
+ def self.submit(host, port, chimp_object, job_uuid)
11
11
  uri = "http://#{host}:#{port}/job/process"
12
12
  attempts = 3
13
13
 
14
14
  begin
15
+ # We are sending to the chimp host+port the actual chimp_object.
16
+ Log.debug "Sending job to chimpd webserver"
15
17
  response = RestClient.post uri, chimp_object.to_yaml
16
18
 
19
+
17
20
  if response.code > 199 and response.code < 300
21
+ Log.debug "Response code was #{response.code}"
18
22
  id = YAML::load(response.body)['id']
23
+ #ID changes upon execution, not upon submission.
24
+ job_uuid = YAML::load(response.body)['job_uuid']
25
+ puts "["+job_uuid+"]"
19
26
  return true
20
27
  else
21
- $stderr.puts "WARNING: error submitting to chimpd! response code: #{reponse.code}"
28
+ $stderr.puts "["+job_uuid+"] WARNING: error submitting to chimpd! response code: #{response.code}"
22
29
  return false
23
30
  end
24
31
 
25
32
  rescue RestClient::RequestTimeout => ex
26
- $stderr.puts "WARNING: Request timeout talking to chimpd for job #{chimp_object.script}: #{ex.message} (#{ex.http_code})"
33
+ $stderr.puts "["+job_uuid+"] WARNING: Request timeout talking to chimpd for job #{chimp_object.script}: #{ex.message} (#{ex.http_code})"
27
34
  attempts -= 1
28
35
  sleep 5 and retry if attempts > 0
29
36
  return false
30
37
 
31
38
  rescue RestClient::InternalServerError => ex
32
- $stderr.puts "WARNING: Error submitting job to chimpd: #{error_message}, retrying..."
39
+
40
+ $stderr.puts "["+job_uuid+"] WARNING: Error submitting job to chimpd: #{ex.message}, retrying..."
33
41
  attempts -= 1
34
42
  sleep 5 and retry if attempts > 0
35
43
  return false
36
44
 
37
45
  rescue Errno::ECONNRESET => ex
38
- $stderr.puts "WARNING: Connection reset by peer, retrying..."
46
+ $stderr.puts "["+job_uuid+"] WARNING: Connection reset by peer, retrying..."
39
47
  attempts -= 1
40
48
  sleep 5 and retry if attempts > 0
41
49
  return false
42
50
 
43
51
  rescue Errno::EPIPE => ex
44
- $stderr.puts "WARNING: broken pipe, retrying..."
52
+ $stderr.puts "["+job_uuid+"] WARNING: broken pipe, retrying..."
45
53
  attempts -= 1
46
54
  sleep 5 and retry if attempts > 0
47
55
  return false
48
56
 
49
57
  rescue Errno::ECONNREFUSED => ex
50
- $stderr.puts "ERROR: connection refused, aborting"
58
+ $stderr.puts "["+job_uuid+"] ERROR: connection refused, aborting"
51
59
  return false
52
60
 
53
61
  rescue RestClient::Exception => ex
54
- $stderr.puts "ERROR: Error submitting job to chimpd #{chimp_object.script}: #{ex.message}"
62
+ $stderr.puts "["+job_uuid+"] ERROR: Error submitting job to chimpd #{chimp_object.script}: #{ex.message}"
55
63
  return false
56
64
  end
57
65
  end
@@ -2,15 +2,14 @@
2
2
  # Report
3
3
  #
4
4
  # :fields is a comma seperated list of fields to report on,
5
- # and are taken from the RestConnection Server objects directly.
6
- #
7
- # Example: ip-address,name,href,private-ip-address,aws-id,ec2-instance-type,dns-name,locked
8
5
  #
6
+ # Example: ip-address,name,href,private-ip-address,resource_uid,
7
+ # ec2-instance-type,datacenter,dns-name,locked,tag=foo
9
8
  module Chimp
10
9
  class ExecReport < Executor
11
10
  attr_reader :server, :fields
12
11
  attr_writer :server, :fields
13
-
12
+
14
13
  def info
15
14
  return "report on server #{fields.inspect}"
16
15
  end
@@ -18,38 +17,33 @@ module Chimp
18
17
  def run
19
18
  run_with_retry do
20
19
  output = []
21
-
22
- #
23
- # The API and rest_connection return very different data
24
- # depending on the API call made (here, tag query vs. array)
25
- # so the logic to load the server information and tags is
26
- # messy.
27
- #
20
+
28
21
  begin
29
- s = Server.find(@server.href)
30
- s.settings
31
- response = ::Tag.search_by_href(s.current_instance_href)
22
+ s=@server
23
+ Log.debug "Making API 1.5 call: client.tags"
24
+ response=Connection.client.tags.by_resource(:resource_hrefs => [@server.href]).first.tags
32
25
  rescue Exception => ex
26
+ raise e
33
27
  s = @server
34
- response = ::Tag.search_by_href(s.href)
28
+ response = nil
35
29
  end
36
30
 
37
- s.tags = [] unless s.tags
31
+ s.params["tags"] = [] unless s.params["tags"]
38
32
  response.each do |t|
39
- s.tags += [ t['name'] ]
33
+ s.params["tags"] += [ t['name'] ]
40
34
  end
41
-
35
+
42
36
  @fields.split(",").each do |f|
43
37
  if f =~ /^tag=([^,]+)/
44
38
  tag_search_string = $1
45
- s.tags.each do |tag|
39
+ s.params["tags"].each do |tag|
46
40
  output << tag if tag =~ /^#{tag_search_string}/
47
41
  end
48
42
  else
49
43
  output << s.params[f]
50
44
  end
51
45
  end
52
-
46
+
53
47
  puts output.join(",")
54
48
  end
55
49
  end
@@ -13,22 +13,23 @@ module Chimp
13
13
  end
14
14
 
15
15
  run_with_retry do
16
- audit_entry = server.run_executable(@exec, options)
17
- audit_entry.wait_for_state("completed", @timeout)
18
- @results = audit_entry.summary
16
+ task=Task.new
17
+ task.tasker = @server.run_executable(@exec, options)
18
+ task.wait_for_state("completed", @timeout)
19
+ @results = task.tasker.show.summary
19
20
  end
20
21
  end
21
22
 
22
23
  def describe_work
23
- return "ExecRightScript job_id=#{@job_id} script=\"#{@exec['right_script']['name']}\" server=\"#{@server['nickname']}\""
24
+ return "[#{@job_uuid}] ExecRightScript job_id=#{@job_id} script=\"#{@exec.params['right_script']['name']}\" server=\"#{@server.nickname}\""
24
25
  end
25
26
 
26
27
  def info
27
- return @exec['right_script']['name']
28
+ return @exec.params['right_script']['name']
28
29
  end
29
30
 
30
31
  def target
31
- return @server['nickname']
32
+ return @server.nickname
32
33
  end
33
34
 
34
35
  end
@@ -11,14 +11,9 @@ module Chimp
11
11
  end
12
12
 
13
13
  def run
14
- host = @server['ip_address'] || @server['ip-address'] || nil
14
+ host = @server.ip_address || nil
15
15
  @ssh_user ||= "root"
16
-
17
- if host == nil
18
- @server.settings
19
- host = @server['ip_address'] || @server['ip-address']
20
- end
21
-
16
+
22
17
  run_with_retry do
23
18
  Log.debug "ssh #{@ssh_user}@#{host} \"#{@exec}\""
24
19
  success = system("ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no #{@ssh_user}@#{host} \"#{@exec}\"")
@@ -30,7 +25,7 @@ module Chimp
30
25
  end
31
26
 
32
27
  def describe_work
33
- return "ExecSSH job_id=#{@job_id} command=\"#{@exec}\" server=\"#{@server['nickname']}\""
28
+ return "ExecSSH job_id=#{@job_id} command=\"#{@exec}\" server=\"#{@server.nickname}\""
34
29
  end
35
30
 
36
31
  def info
@@ -38,7 +33,7 @@ module Chimp
38
33
  end
39
34
 
40
35
  def target
41
- return @server['nickname']
36
+ return @server.nickname
42
37
  end
43
38
 
44
39
  end
@@ -5,7 +5,7 @@
5
5
  module Chimp
6
6
  class Executor
7
7
  attr_accessor :server, :array, :exec, :inputs, :template, :owner, :group,
8
- :job_id, :status, :dry_run, :verbose, :quiet, :timeout,
8
+ :job_id, :job_uuid, :status, :dry_run, :verbose, :quiet, :timeout,
9
9
  :retry_count, :retry_sleep, :time_start, :time_end, :error
10
10
 
11
11
  attr_reader :results
@@ -23,6 +23,7 @@ module Chimp
23
23
  @template = h[:template] || nil
24
24
 
25
25
  @job_id = h[:job_id] || nil
26
+ @job_uuid = h[:job_uuid] || nil
26
27
  @group = h[:group] || nil
27
28
  @exec = h[:exec] || nil
28
29
  @inputs = h[:inputs] || nil
@@ -105,6 +106,7 @@ module Chimp
105
106
 
106
107
  @status = STATUS_RUNNING
107
108
  @time_start = Time.now
109
+
108
110
  Log.info self.describe_work_start unless @quiet
109
111
 
110
112
  #
@@ -124,7 +126,7 @@ module Chimp
124
126
  @status = STATUS_DONE
125
127
  @group.job_completed
126
128
  else
127
- Log.warn "Ownership of job_id #{job_id} lost. User cancelled operation?"
129
+ Log.warn "[#{@job_uuid}] Ownership of job_id #{job_id} lost. User cancelled operation?"
128
130
  end
129
131
 
130
132
  rescue SystemExit, Interrupt => ex
@@ -138,7 +140,7 @@ module Chimp
138
140
 
139
141
  if @retry_count > 0
140
142
  @status = STATUS_RETRYING
141
- Log.error "Error executing on \"#{name}\". Retrying in #{@retry_sleep} seconds..."
143
+ Log.error "[#{@job_uuid}] Error executing on \"#{name}\". Retrying in #{@retry_sleep} seconds..."
142
144
  @retry_count -= 1
143
145
  sleep @retry_sleep
144
146
  retry
@@ -146,7 +148,7 @@ module Chimp
146
148
 
147
149
  @status = STATUS_ERROR
148
150
  @error = ex
149
- Log.error "Error executing on \"#{name}\": #{ex}"
151
+ Log.error "[#{@job_uuid}] Error executing on \"#{name}\": #{ex}"
150
152
 
151
153
  ensure
152
154
  @time_end = Time.now
@@ -154,7 +156,7 @@ module Chimp
154
156
  end
155
157
 
156
158
  rescue RuntimeError => ex
157
- Log.error "Caught RuntimeError: #{ex}. Aborting job."
159
+ Log.error "[#{@job_uuid}] Caught RuntimeError: #{ex}. Aborting job."
158
160
  Log.error ex.inspect
159
161
  Log.error ex.backtrace
160
162
  @status = STATUS_ERROR