right_chimp 1.1.3 → 2.0

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.
@@ -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