right_aws 1.1.0 → 1.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.
@@ -23,55 +23,106 @@
23
23
 
24
24
  module RightAws
25
25
 
26
+ # = RightAWS::EC2 -- RightScale Amazon EC2 interface
27
+ # The RightAws::EC2 class provides a complete interface to Amazon's
28
+ # Elastic Compute Cloud service.
29
+ # For explanations of the semantics
30
+ # of each call, please refer to Amazon's documentation at
31
+ # http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=87
32
+ #
33
+ # Examples:
34
+ #
35
+ # Create an EC2 interface handle:
36
+ #
37
+ # @ec2 = RightAws::Ec2.new(aws_access_key_id,
38
+ # aws_secret_access_key)
39
+ # Create a new SSH key pair:
40
+ # @key = 'right_ec2_awesome_test_key'
41
+ # new_key = @ec2.create_key_pair(@key)
42
+ # keys = @ec2.describe_key_pairs
43
+ #
44
+ # Create a security group:
45
+ # @group = 'right_ec2_awesome_test_security_group'
46
+ # @ec2.create_security_group(@group,'My awesome test group')
47
+ # group = @ec2.describe_security_groups([@group])[0]
48
+ #
49
+ # Configure a security group:
50
+ # @ec2.authorize_security_group_named_ingress(@group, account_number, 'default')
51
+ # @ec2.authorize_security_group_IP_ingress(@group, 80,80,'udp','192.168.1.0/8')
52
+ #
53
+ # Describe the available images:
54
+ # images = @ec2.describe_images
55
+ #
56
+ # Launch an instance:
57
+ # ec2.run_instances('ami-9a9e7bf3', 1, 1, ['default'], @key, 'SomeImportantUserData', 'public')
58
+ #
59
+ #
60
+ # Describe running instances:
61
+ # @ec2.describe_instances
62
+ #
63
+ # Error handling: all operations raise an RightAws::AwsError in case
64
+ # of problems. Note that transient errors are automatically retried.
65
+
26
66
  class Ec2
27
67
 
28
68
  SIGNATURE_VERSION = "1"
29
- API_VERSION = "2007-01-19"
69
+ # Amazon EC2 API version being used
70
+ API_VERSION = "2007-03-01"
30
71
  DEFAULT_HOST = "ec2.amazonaws.com"
31
72
  DEFAULT_PROTOCOL = 'https'
32
73
  DEFAULT_PORT = 443
33
74
 
75
+ # Default addressing type (public=NAT, direct=no-NAT) used when launching instances.
34
76
  DEFAULT_ADDRESSING_TYPE = 'public'
35
77
  DNS_ADDRESSING_SET = ['public','direct']
36
78
 
37
- # A list if Amazons problems we can handle by AWSErrorHandler.
79
+ # A list of Amazon problems we can handle by AWSErrorHandler.
38
80
  @@amazon_problems = RightAws::AMAZON_PROBLEMS
39
81
 
40
- # Current aws_access_key_id
82
+ # Current aws_access_key_id
41
83
  attr_reader :aws_access_key_id
42
- # Last HTTP request object
84
+ # Last HTTP request object
43
85
  attr_reader :last_request
44
- # Last HTTP response object
86
+ # Last HTTP response object
45
87
  attr_reader :last_response
46
- # Last AWS errors list (used by AWSErrorHandler)
88
+ # Last AWS errors list (used by AWSErrorHandler)
47
89
  attr_accessor :last_errors
48
- # Last AWS request id (used by AWSErrorHandler)
90
+ # Last AWS request id (used by AWSErrorHandler)
49
91
  attr_accessor :last_request_id
50
- # Logger object
92
+ # Logger object, used by this class to generate log messages
51
93
  attr_accessor :logger
52
- # Initial params hash
94
+ # Option params passed into new
53
95
  attr_accessor :params
54
96
 
55
97
  @@bench_ec2 = Benchmark::Tms.new()
56
98
  @@bench_xml = Benchmark::Tms.new()
57
99
 
58
- # Benchmark::Tms instance for EC2 access benchmark.
100
+ # Benchmark::Tms instance that accumulates time spent in requests to EC2.
59
101
  def self.bench_ec2; @@bench_ec2; end
60
102
 
61
- # Benchmark::Tms instance for XML parsing benchmark.
103
+ # Benchmark::Tms instance that accumulates time spent in XML parsing.
62
104
  def self.bench_xml; @@bench_xml; end
63
105
 
64
- # Returns a list of Amazon service responses which are known as problems on Amazon side.
65
- # We have to re-request again if we've got any of them - probably the problem will disappear. By default returns the same value as AMAZON_PROBLEMS const.
106
+ # Returns a list of Amazon service responses which are known to be transient errors.
107
+ # By default returns the same value as AMAZON_PROBLEMS const. See AWSErrorHandler.
66
108
  def self.amazon_problems
67
109
  @@amazon_problems
68
110
  end
69
111
 
70
- # Sets a list of Amazon side problems.
112
+ # Sets the list of Amazon problems that are automatically retried. See AWSErrorHandler.
71
113
  def self.amazon_problems=(problems_list)
72
114
  @@amazon_problems = problems_list
73
115
  end
74
116
 
117
+ # Create a new handle to an EC2 account. All handles share the same per process or per thread
118
+ # HTTP connection to Amazon EC2. Each handle is for a specific account. The params have the
119
+ # following options:
120
+ # * <tt>:server</tt>: EC2 service host, default: DEFAULT_HOST
121
+ # * <tt>:port</tt>: EC2 service port, default: DEFAULT_PORT
122
+ # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
123
+ # * <tt>:multi_thread</tt>: true=HTTP connection per thread, false=per process
124
+ # * <tt>:logger</tt>: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT
125
+ #
75
126
  def initialize(aws_access_key_id, aws_secret_access_key, params={})
76
127
  @params = params
77
128
  raise AwsError.new("AWS access keys are required to operate on EC2") \
@@ -94,7 +145,7 @@ module RightAws
94
145
  AwsError::on_aws_exception(self, options)
95
146
  end
96
147
 
97
- # Return the +true+ if this RightEc2NativeQuery instance works in multi_thread state and +false+ otherwise.
148
+ # Return +true+ if this RightEc2NativeQuery instance works in multi_thread mode and +false+ otherwise.
98
149
  def multi_thread
99
150
  @params[:multi_thread]
100
151
  end
@@ -132,13 +183,7 @@ module RightAws
132
183
  @last_response = response
133
184
  if response.is_a?(Net::HTTPSuccess)
134
185
  @error_handler = nil
135
- @@bench_xml.add! do
136
- if parser.kind_of?(RightAWSParser)
137
- REXML::Document.parse_stream(response.body, parser)
138
- else
139
- parser.parse(response)
140
- end
141
- end
186
+ @@bench_xml.add! { parser.parse(response) }
142
187
  return parser.result
143
188
  else
144
189
  @error_handler = AWSErrorHandler.new(self, parser, @@amazon_problems) unless @error_handler
@@ -167,49 +212,66 @@ module RightAws
167
212
  #-----------------------------------------------------------------
168
213
 
169
214
  def ec2_describe_images(type, list) #:nodoc:
170
- link = generate_request("DescribeImages", hash_params(type,list))
171
- return request_info(link, QEc2DescribeImagesParser.new)
172
- end
173
-
174
- def ec2_describe_images_by_id( list) #:nodoc:
175
- return ec2_describe_images('ImageId', list)
176
- end
177
-
178
- def ec2_describe_images_by_owner(list) #:nodoc:
179
- return ec2_describe_images('Owner', list)
180
- end
181
-
182
- def ec2_describe_images_by_executable_by(list) #:nodoc:
183
- return ec2_describe_images('ExecutableBy', list)
215
+ link = generate_request("DescribeImages", hash_params(type,list.to_a))
216
+ images = request_info(link, QEc2DescribeImagesParser.new(:logger => @logger))
217
+ images.collect! do |image|
218
+ {:aws_id => image.imageId,
219
+ :aws_location => image.imageLocation,
220
+ :aws_owner => image.imageOwnerId,
221
+ :aws_state => image.imageState.downcase,
222
+ :aws_is_public => image.isPublic,
223
+ :aws_product_codes => image.productCodes}
224
+ end
225
+ images
226
+ rescue Exception
227
+ on_exception
184
228
  end
185
229
 
186
- # Retrieve a list of images. Returns array of hashes or an exception:
230
+ # Retrieve a list of images. Returns array of hashes describing the images or an exception:
187
231
  #
188
232
  # ec2.describe_images #=>
189
- # [{:aws_owner=>"522821470517", :aws_id=>"ami-e4b6538d", :aws_state=>"available",
190
- # :aws_location=>"marcins_cool_public_images/ubuntu-6.10.manifest.xml",:aws_is_public=>true},
191
- # ..., {...} ]
233
+ # [{:aws_owner => "522821470517",
234
+ # :aws_id => "ami-e4b6538d",
235
+ # :aws_state => "available",
236
+ # :aws_location => "marcins_cool_public_images/ubuntu-6.10.manifest.xml",
237
+ # :aws_is_public => true},
238
+ # {...},
239
+ # {...} ]
192
240
  #
193
241
  # If +list+ param is set, then retrieve information about the listed images only:
194
242
  #
195
243
  # ec2.describe_images(['ami-e4b6538d']) #=>
196
- # [{:aws_owner=>"522821470517", :aws_id=>"ami-e4b6538d", :aws_state=>"available",
197
- # :aws_location=>"marcins_cool_public_images/ubuntu-6.10.manifest.xml",:aws_is_public=>true}]
244
+ # [{:aws_owner => "522821470517",
245
+ # :aws_id => "ami-e4b6538d",
246
+ # :aws_state => "available",
247
+ # :aws_location => "marcins_cool_public_images/ubuntu-6.10.manifest.xml",
248
+ # :aws_is_public => true}]
198
249
  #
199
250
  def describe_images(list=[])
200
- images = list.nil? ? ec2_describe_images_by_executable_by(['self']) : ec2_describe_images_by_id(list)
201
- images.collect! do |image|
202
- {:aws_id => image.imageId,
203
- :aws_location => image.imageLocation,
204
- :aws_owner => image.imageOwnerId,
205
- :aws_state => image.imageState.downcase,
206
- :aws_is_public => image.isPublic }
207
- end
208
- images
209
- rescue Exception
210
- on_exception
251
+ ec2_describe_images('ImageId', list)
252
+ end
253
+
254
+ #
255
+ # Example:
256
+ #
257
+ # ec2.describe_images_by_owner('522821470517')
258
+ # ec2.describe_images_by_owner('self')
259
+ #
260
+ def describe_images_by_owner(list)
261
+ ec2_describe_images('Owner', list)
262
+ end
263
+
264
+ #
265
+ # Example:
266
+ #
267
+ # ec2.describe_images_by_executable_by('522821470517')
268
+ # ec2.describe_images_by_executable_by('self')
269
+ #
270
+ def describe_images_by_executable_by(list)
271
+ ec2_describe_images('ExecutableBy', list)
211
272
  end
212
-
273
+
274
+
213
275
  # Register new image at Amazon.
214
276
  # Returns new image id or an exception.
215
277
  #
@@ -218,7 +280,7 @@ module RightAws
218
280
  def register_image(image_location)
219
281
  link = generate_request("RegisterImage",
220
282
  'ImageLocation' => image_location.to_s)
221
- request_info(link, QEc2RegisterImageParser.new)
283
+ request_info(link, QEc2RegisterImageParser.new(:logger => @logger))
222
284
  rescue Exception
223
285
  on_exception
224
286
  end
@@ -230,13 +292,13 @@ module RightAws
230
292
  def deregister_image(image_id)
231
293
  link = generate_request("DeregisterImage",
232
294
  'ImageId' => image_id.to_s)
233
- request_info(link, RightBoolResponseParser.new)
295
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
234
296
  rescue Exception
235
297
  on_exception
236
298
  end
237
299
 
238
300
 
239
- # Describe image attributes. Currently, only 'launchPermission' is supported.
301
+ # Describe image attributes. Currently 'launchPermission' and 'productCodes' are supported.
240
302
  #
241
303
  # ec2.describe_image_attribute('ami-e444444d') #=> {:groups=>["all"], :users=>["000000000777"]}
242
304
  #
@@ -244,9 +306,15 @@ module RightAws
244
306
  link = generate_request("DescribeImageAttribute",
245
307
  'ImageId' => image_id,
246
308
  'Attribute' => attribute)
247
- image_attr = request_info(link, QEc2DescribeImageAttributeParser.new)
248
- { :users => image_attr.launchPermission.userIds,
249
- :groups => image_attr.launchPermission.groups }
309
+ image_attr = request_info(link, QEc2DescribeImageAttributeParser.new(:logger => @logger))
310
+ result = {}
311
+ if image_attr.launchPermission
312
+ result = { :users => image_attr.launchPermission.userIds,
313
+ :groups => image_attr.launchPermission.groups }
314
+ elsif image_attr.productCodes
315
+ result = { :aws_product_codes => image_attr.productCodes}
316
+ end
317
+ result
250
318
  rescue Exception
251
319
  on_exception
252
320
  end
@@ -259,37 +327,42 @@ module RightAws
259
327
  link = generate_request("ResetImageAttribute",
260
328
  'ImageId' => image_id,
261
329
  'Attribute' => attribute)
262
- request_info(link, RightBoolResponseParser.new)
330
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
263
331
  rescue Exception
264
332
  on_exception
265
333
  end
266
334
 
267
- # Users should prefer modify_image_launch_perm_add|remove_users|groups() instead of modify_image_attribute() because the signature of
268
- # modify_image_attribute() may change with EC2 service changes.
335
+ # Modify an image's attributes. It is recommended that you use
336
+ # modify_image_launch_perm_add_users, modify_image_launch_perm_remove_users, etc.
337
+ # instead of modify_image_attribute because the signature of
338
+ # modify_image_attribute may change with EC2 service changes.
269
339
  #
270
- # attribute : currently, only 'launchPermission' is supported.
271
- # operationType : currently, only 'add' & 'remove' are supported.
272
- # userGroup : currently, only 'all' is supported.
273
- def modify_image_attribute(image_id, attribute, operation_type, user_id=[], user_group=[])
274
- user_id = user_id.to_a
275
- user_group = user_group.to_a
276
- params = {'ImageId' => image_id,
277
- 'Attribute' => attribute,
278
- 'OperationType' => operation_type}
279
- params.update(hash_params('UserId', user_id)) unless user_id.empty?
280
- params.update(hash_params('UserGroup', user_group)) unless user_group.empty?
340
+ # attribute : currently, only 'launchPermission' is supported.
341
+ # operation_type : currently, only 'add' & 'remove' are supported.
342
+ # vars:
343
+ # :user_group : currently, only 'all' is supported.
344
+ # :user_id
345
+ # :product_code
346
+ def modify_image_attribute(image_id, attribute, operation_type = nil, vars = {})
347
+ params = {'ImageId' => image_id,
348
+ 'Attribute' => attribute}
349
+ params['OperationType'] = operation_type if operation_type
350
+ params.update(hash_params('UserId', vars[:user_id].to_a)) if vars[:user_id]
351
+ params.update(hash_params('UserGroup', vars[:user_group].to_a)) if vars[:user_group]
352
+ params.update(hash_params('ProductCode', vars[:product_code])) if vars[:product_code]
281
353
  link = generate_request("ModifyImageAttribute", params)
282
- request_info(link, RightBoolResponseParser.new)
354
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
283
355
  rescue Exception
284
356
  on_exception
285
357
  end
286
358
 
287
- # Grant image launch permissions for users. Parameter +userId+ is a list of users' AWS account ids. Returns +true+ or an exception.
359
+ # Grant image launch permissions to users.
360
+ # Parameter +userId+ is a list of user AWS account ids.
361
+ # Returns +true+ or an exception.
288
362
  #
289
363
  # ec2.modify_image_launch_perm_add_users('ami-e444444d',['000000000777','000000000778']) #=> true
290
- #
291
364
  def modify_image_launch_perm_add_users(image_id, user_id=[])
292
- modify_image_attribute(image_id, 'launchPermission', 'add', user_id, [])
365
+ modify_image_attribute(image_id, 'launchPermission', 'add', :user_id => user_id.to_a)
293
366
  end
294
367
 
295
368
  # Revokes image launch permissions for users. +userId+ is a list of users AWS accounts ids. Returns +true+ or an exception.
@@ -297,7 +370,7 @@ module RightAws
297
370
  # ec2.modify_image_launch_perm_remove_users('ami-e444444d',['000000000777','000000000778']) #=> true
298
371
  #
299
372
  def modify_image_launch_perm_remove_users(image_id, user_id=[])
300
- modify_image_attribute(image_id, 'launchPermission', 'remove', user_id, [])
373
+ modify_image_attribute(image_id, 'launchPermission', 'remove', :user_id => user_id.to_a)
301
374
  end
302
375
 
303
376
  # Add image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions).
@@ -306,7 +379,7 @@ module RightAws
306
379
  # ec2.modify_image_launch_perm_add_groups('ami-e444444d') #=> true
307
380
  #
308
381
  def modify_image_launch_perm_add_groups(image_id, userGroup=['all'])
309
- modify_image_attribute(image_id, 'launchPermission', 'add', [], userGroup)
382
+ modify_image_attribute(image_id, 'launchPermission', 'add', :user_group => userGroup.to_a)
310
383
  end
311
384
 
312
385
  # Remove image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions).
@@ -314,7 +387,15 @@ module RightAws
314
387
  # ec2.modify_image_launch_perm_remove_groups('ami-e444444d') #=> true
315
388
  #
316
389
  def modify_image_launch_perm_remove_groups(image_id, userGroup=['all'])
317
- modify_image_attribute(image_id, 'launchPermission', 'remove', [], userGroup)
390
+ modify_image_attribute(image_id, 'launchPermission', 'remove', :user_group => userGroup.to_a)
391
+ end
392
+
393
+ # Add product code to image
394
+ #
395
+ # ec2.modify_image_product_code('ami-e444444d','0ABCDEF') #=> true
396
+ #
397
+ def modify_image_product_code(image_id, productCode=[])
398
+ modify_image_attribute(image_id, 'productCodes', nil, :product_code => productCode.to_a)
318
399
  end
319
400
 
320
401
  def get_desc_instances(instances) # :nodoc:
@@ -334,7 +415,8 @@ module RightAws
334
415
  :aws_state => instance.instanceState.name,
335
416
  :ssh_key_name => instance.keyName,
336
417
  :aws_image_id => instance.imageId,
337
- :aws_reason => reason}
418
+ :aws_reason => reason,
419
+ :aws_product_codes => instance.productCodes}
338
420
  end
339
421
  end
340
422
  result
@@ -342,7 +424,8 @@ module RightAws
342
424
  on_exception
343
425
  end
344
426
 
345
- # Retrieve information about EC2 instances. If +list+ is omitted then returns the whole list.
427
+ # Retrieve information about EC2 instances. If +list+ is omitted then returns the
428
+ # list of all instances.
346
429
  #
347
430
  # ec2.describe_instances #=>
348
431
  # [{:aws_image_id => "ami-e444444d",
@@ -359,16 +442,27 @@ module RightAws
359
442
  # ..., {...}]
360
443
  #
361
444
  def describe_instances(list=[])
362
- link = generate_request("DescribeInstances", hash_params('InstanceId',list))
363
- instances = request_info(link, QEc2DescribeInstancesParser.new)
445
+ link = generate_request("DescribeInstances", hash_params('InstanceId',list.to_a))
446
+ instances = request_info(link, QEc2DescribeInstancesParser.new(:logger => @logger))
364
447
  get_desc_instances(instances)
365
448
  rescue Exception
366
449
  on_exception
367
450
  end
368
451
 
452
+ # Return the product code attached to instance or +nil+ otherwise.
453
+ #
454
+ # ec2.confirm_product_instance('ami-e444444d','12345678') #=> nil
455
+ # ec2.confirm_product_instance('ami-e444444d','00001111') #=> "000000000888"
456
+ #
457
+ def confirm_product_instance(instance, product_code)
458
+ link = generate_request("ConfirmProductInstance", { 'ProductCode' => product_code,
459
+ 'InstanceId' => instance })
460
+ request_info(link, QEc2ConfirmProductInstanceParser.new(:logger => @logger))
461
+ end
462
+
369
463
  # Launch new EC2 instances. Returns a list of launched instances or an exception.
370
464
  #
371
- # ec2.run_instances('ami-e444444d',1,1,['my_awesome_group'],'my_awesome_key', 'Woohoo!!!', public) #=>
465
+ # ec2.run_instances('ami-e444444d',1,1,['my_awesome_group'],'my_awesome_key', 'Woohoo!!!', 'public') #=>
372
466
  # [{:aws_image_id => "ami-e444444d",
373
467
  # :aws_reason => "",
374
468
  # :aws_state_code => "0",
@@ -382,9 +476,9 @@ module RightAws
382
476
  # :private_dns_name => ""}]
383
477
  #
384
478
  def run_instances(image_id, min_count, max_count, group_ids, key_name, user_data='', addressing_type=DEFAULT_ADDRESSING_TYPE)
385
- @logger.info("Launching instance of image #{image_id} for #{@aws_access_key_id}, key: #{key_name}, groups: #{(group_ids||[]).join(',')}")
479
+ @logger.info("Launching instance of image #{image_id} for #{@aws_access_key_id}, key: #{key_name}, groups: #{(group_ids||[]).to_a.join(',')}")
386
480
  # careful: keyName and securityGroups may be nil
387
- params = hash_params('SecurityGroup', group_ids)
481
+ params = hash_params('SecurityGroup', group_ids.to_a)
388
482
  params.update( {'ImageId' => image_id,
389
483
  'MinCount' => min_count.to_s,
390
484
  'MaxCount' => max_count.to_s,
@@ -394,13 +488,13 @@ module RightAws
394
488
  user_data.strip!
395
489
  # Do not use CGI::escape(encode64(...)) as it is done in Amazons EC2 library.
396
490
  # Amazon 169.254.169.254 does not like escaped symbols!
397
- # And it dont like "\n" inside of encoded string! Grrr....
491
+ # And it doesn't like "\n" inside of encoded string! Grrr....
398
492
  # Otherwise, some of UserData symbols will be lost...
399
- params['UserData'] = Base64.encode64(user_data).delete("\n") unless user_data.empty?
493
+ params['UserData'] = Base64.encode64(user_data).delete("\n") unless user_data.blank?
400
494
  end
401
495
  link = generate_request("RunInstances", params)
402
496
  #debugger
403
- instances = request_info(link, QEc2RunInstancesParser.new)
497
+ instances = request_info(link, QEc2RunInstancesParser.new(:logger => @logger))
404
498
  get_desc_instances(instances)
405
499
  rescue Exception
406
500
  on_exception
@@ -421,8 +515,8 @@ module RightAws
421
515
  # :aws_prev_state_code => 16}]
422
516
  #
423
517
  def terminate_instances(list=[])
424
- link = generate_request("TerminateInstances", hash_params('InstanceId',list))
425
- instances = request_info(link, QEc2TerminateInstancesParser.new)
518
+ link = generate_request("TerminateInstances", hash_params('InstanceId',list.to_a))
519
+ instances = request_info(link, QEc2TerminateInstancesParser.new(:logger => @logger))
426
520
  instances.collect! do |instance|
427
521
  { :aws_instance_id => instance.instanceId,
428
522
  :aws_shutdown_state => instance.shutdownState.name,
@@ -444,7 +538,7 @@ module RightAws
444
538
  # :aws_output => "Linux version 2.6.16-xenU (builder@patchbat.amazonsa) (gcc version 4.0.1 20050727 ..."
445
539
  def get_console_output(instance_id)
446
540
  link = generate_request("GetConsoleOutput", { 'InstanceId.1' => instance_id })
447
- result = request_info(link, QEc2GetConsoleOutputParser.new)
541
+ result = request_info(link, QEc2GetConsoleOutputParser.new(:logger => @logger))
448
542
  { :aws_instance_id => result.instanceId,
449
543
  :aws_timestamp => result.timestamp,
450
544
  :timestamp => (Time.parse(result.timestamp)).utc,
@@ -459,7 +553,7 @@ module RightAws
459
553
  #
460
554
  def reboot_instances(list)
461
555
  link = generate_request("RebootInstances", hash_params('InstanceId', list.to_a))
462
- request_info(link, RightBoolResponseParser.new)
556
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
463
557
  rescue Exception
464
558
  on_exception
465
559
  end
@@ -480,8 +574,8 @@ module RightAws
480
574
  # ..., {...}]
481
575
  #
482
576
  def describe_security_groups(list=[])
483
- link = generate_request("DescribeSecurityGroups", hash_params('GroupName',list))
484
- groups = request_info(link, QEc2DescribeSecurityGroupsParser.new)
577
+ link = generate_request("DescribeSecurityGroups", hash_params('GroupName',list.to_a))
578
+ groups = request_info(link, QEc2DescribeSecurityGroupsParser.new(:logger => @logger))
485
579
 
486
580
  result = []
487
581
  groups.each do |item|
@@ -527,7 +621,7 @@ module RightAws
527
621
  link = generate_request("CreateSecurityGroup",
528
622
  'GroupName' => name.to_s,
529
623
  'GroupDescription' => description.to_s)
530
- request_info(link, RightBoolResponseParser.new)
624
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
531
625
  rescue Exception
532
626
  on_exception
533
627
  end
@@ -539,21 +633,22 @@ module RightAws
539
633
  def delete_security_group(name)
540
634
  link = generate_request("DeleteSecurityGroup",
541
635
  'GroupName' => name.to_s)
542
- request_info(link, RightBoolResponseParser.new)
636
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
543
637
  rescue Exception
544
638
  on_exception
545
639
  end
546
640
 
547
- # Authorize named ingress for security group.
641
+ # Authorize named ingress for security group. Allows instances that are member of someone
642
+ # else's security group to open connections to instances in my group.
548
643
  #
549
- # ec2.authorize_security_group_named_ingress('my_awesome_group', aws_user_id, 'another_group_name') #=> true
644
+ # ec2.authorize_security_group_named_ingress('my_awesome_group', '7011-0219-8268', 'their_group_name') #=> true
550
645
  #
551
646
  def authorize_security_group_named_ingress(name, owner, group)
552
647
  link = generate_request("AuthorizeSecurityGroupIngress",
553
648
  'GroupName' => name.to_s,
554
649
  'SourceSecurityGroupName' => group.to_s,
555
650
  'SourceSecurityGroupOwnerId' => owner.to_s.gsub(/-/,''))
556
- request_info(link, RightBoolResponseParser.new)
651
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
557
652
  rescue Exception
558
653
  on_exception
559
654
  end
@@ -567,12 +662,12 @@ module RightAws
567
662
  'GroupName' => name.to_s,
568
663
  'SourceSecurityGroupName' => group.to_s,
569
664
  'SourceSecurityGroupOwnerId' => owner.to_s.gsub(/-/,''))
570
- request_info(link, RightBoolResponseParser.new)
665
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
571
666
  rescue Exception
572
667
  on_exception
573
668
  end
574
669
 
575
- # Add permission to a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp' ('tcp' is default).
670
+ # Add permission to a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp'.
576
671
  #
577
672
  # ec2.authorize_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
578
673
  # ec2.authorize_security_group_IP_ingress('my_awesome_group', -1, -1, 'icmp') #=> true
@@ -584,7 +679,7 @@ module RightAws
584
679
  'FromPort' => from_port.to_s,
585
680
  'ToPort' => to_port.to_s,
586
681
  'CidrIp' => cidr_ip.to_s)
587
- request_info(link, RightBoolResponseParser.new)
682
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
588
683
  rescue Exception
589
684
  on_exception
590
685
  end
@@ -600,12 +695,13 @@ module RightAws
600
695
  'FromPort' => from_port.to_s,
601
696
  'ToPort' => to_port.to_s,
602
697
  'CidrIp' => cidr_ip.to_s)
603
- request_info(link, RightBoolResponseParser.new)
698
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
604
699
  rescue Exception
605
700
  on_exception
606
701
  end
607
702
 
608
- # Retrieve a list of SSH keys. Returms an array of keys or an exception.
703
+ # Retrieve a list of SSH keys. Returns an array of keys or an exception. Each key is
704
+ # represented as a two-element hash.
609
705
  #
610
706
  # ec2.describe_key_pairs #=>
611
707
  # [{:aws_fingerprint=> "01:02:03:f4:25:e6:97:e8:9b:02:1a:26:32:4e:58:6b:7a:8c:9f:03", :aws_key_name=>"key-1"},
@@ -613,8 +709,8 @@ module RightAws
613
709
  # ..., {...} ]
614
710
  #
615
711
  def describe_key_pairs(list=[])
616
- link = generate_request("DescribeKeyPairs", hash_params('KeyName',list))
617
- result = request_info(link, QEc2DescribeKeyPairParser.new)
712
+ link = generate_request("DescribeKeyPairs", hash_params('KeyName',list.to_a))
713
+ result = request_info(link, QEc2DescribeKeyPairParser.new(:logger => @logger))
618
714
  result.collect! do |key|
619
715
  {:aws_key_name => key.keyName,
620
716
  :aws_fingerprint => key.keyFingerprint }
@@ -624,7 +720,7 @@ module RightAws
624
720
  on_exception
625
721
  end
626
722
 
627
- # Create new SSH key. Returns a hash of key's data or an exception.
723
+ # Create new SSH key. Returns a hash of the key's data or an exception.
628
724
  #
629
725
  # ec2.create_key_pair('my_awesome_key') #=>
630
726
  # {:aws_key_name => "my_awesome_key",
@@ -634,7 +730,7 @@ module RightAws
634
730
  def create_key_pair(name)
635
731
  link = generate_request("CreateKeyPair",
636
732
  'KeyName' => name.to_s)
637
- key = request_info(link, QEc2CreateKeyPairParser.new)
733
+ key = request_info(link, QEc2CreateKeyPairParser.new(:logger => @logger))
638
734
  { :aws_key_name => key.keyName,
639
735
  :aws_fingerprint => key.keyFingerprint,
640
736
  :aws_material => key.keyMaterial}
@@ -642,24 +738,26 @@ module RightAws
642
738
  on_exception
643
739
  end
644
740
 
645
- # Delete key pair. Returns +true+ or an exception.
741
+ # Delete a key pair. Returns +true+ or an exception.
646
742
  #
647
743
  # ec2.delete_key_pair('my_awesome_key') #=> true
648
744
  #
649
745
  def delete_key_pair(name)
650
746
  link = generate_request("DeleteKeyPair",
651
747
  'KeyName' => name.to_s)
652
- request_info(link, RightBoolResponseParser.new)
748
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
653
749
  rescue Exception
654
750
  on_exception
655
751
  end
752
+
753
+ #- Internal stuff from here on down...
656
754
 
657
755
 
658
756
  #-----------------------------------------------------------------
659
757
  # PARSERS: Boolean Response Parser
660
758
  #-----------------------------------------------------------------
661
759
 
662
- class RightBoolResponseParser < RightAWSParser # :nodoc:
760
+ class RightBoolResponseParser < RightAWSParser
663
761
  def tagend(name)
664
762
  @result = @text=='true' ? true : false if name == 'return'
665
763
  end
@@ -669,16 +767,16 @@ module RightAws
669
767
  # PARSERS: Key Pair
670
768
  #-----------------------------------------------------------------
671
769
 
672
- class QEc2DescribeKeyPairType # :nodoc:
770
+ class QEc2DescribeKeyPairType
673
771
  attr_accessor :keyName
674
772
  attr_accessor :keyFingerprint
675
773
  end
676
774
 
677
- class QEc2CreateKeyPairType < QEc2DescribeKeyPairType # :nodoc:
775
+ class QEc2CreateKeyPairType < QEc2DescribeKeyPairType
678
776
  attr_accessor :keyMaterial
679
777
  end
680
778
 
681
- class QEc2DescribeKeyPairParser < RightAWSParser # :nodoc:
779
+ class QEc2DescribeKeyPairParser < RightAWSParser
682
780
  def tagstart(name, attributes)
683
781
  @item = QEc2DescribeKeyPairType.new if name == 'item'
684
782
  end
@@ -694,7 +792,7 @@ module RightAws
694
792
  end
695
793
  end
696
794
 
697
- class QEc2CreateKeyPairParser < RightAWSParser # :nodoc:
795
+ class QEc2CreateKeyPairParser < RightAWSParser
698
796
  def tagstart(name, attributes)
699
797
  @result = QEc2CreateKeyPairType.new if !@result
700
798
  end
@@ -711,12 +809,12 @@ module RightAws
711
809
  # PARSERS: Security Groups
712
810
  #-----------------------------------------------------------------
713
811
 
714
- class QEc2UserIdGroupPairType # :nodoc:
812
+ class QEc2UserIdGroupPairType
715
813
  attr_accessor :userId
716
814
  attr_accessor :groupName
717
815
  end
718
816
 
719
- class QEc2IpPermissionType # :nodoc:
817
+ class QEc2IpPermissionType
720
818
  attr_accessor :ipProtocol
721
819
  attr_accessor :fromPort
722
820
  attr_accessor :toPort
@@ -724,7 +822,7 @@ module RightAws
724
822
  attr_accessor :ipRanges
725
823
  end
726
824
 
727
- class QEc2SecurityGroupItemType # :nodoc:
825
+ class QEc2SecurityGroupItemType
728
826
  attr_accessor :groupName
729
827
  attr_accessor :groupDescription
730
828
  attr_accessor :ownerId
@@ -732,7 +830,7 @@ module RightAws
732
830
  end
733
831
 
734
832
 
735
- class QEc2DescribeSecurityGroupsParser < RightAWSParser # :nodoc:
833
+ class QEc2DescribeSecurityGroupsParser < RightAWSParser
736
834
  def tagstart(name, attributes)
737
835
  case name
738
836
  when 'item'
@@ -782,17 +880,20 @@ module RightAws
782
880
  # PARSERS: Images
783
881
  #-----------------------------------------------------------------
784
882
 
785
- class QEc2DescribeImagesResponseItemType # :nodoc:
883
+ class QEc2DescribeImagesResponseItemType
786
884
  attr_accessor :imageId
787
885
  attr_accessor :imageState
788
886
  attr_accessor :imageLocation
789
887
  attr_accessor :imageOwnerId
790
888
  attr_accessor :isPublic
889
+ attr_accessor :productCodes
791
890
  end
792
891
 
793
- class QEc2DescribeImagesParser < RightAWSParser # :nodoc:
892
+ class QEc2DescribeImagesParser < RightAWSParser
794
893
  def tagstart(name, attributes)
795
- @image = QEc2DescribeImagesResponseItemType.new if name == 'item'
894
+ if name == 'item' && @xmlpath[%r{.*/imagesSet$}]
895
+ @image = QEc2DescribeImagesResponseItemType.new
896
+ end
796
897
  end
797
898
  def tagend(name)
798
899
  case name
@@ -801,7 +902,8 @@ module RightAws
801
902
  when 'imageState' ; @image.imageState = @text
802
903
  when 'imageOwnerId' ; @image.imageOwnerId = @text
803
904
  when 'isPublic' ; @image.isPublic = @text == 'true' ? true : false
804
- when 'item' ; @result << @image
905
+ when 'productCode' ; (@image.productCodes ||= []) << @text
906
+ when 'item' ; @result << @image if @xmlpath[%r{.*/imagesSet$}]
805
907
  end
806
908
  end
807
909
  def reset
@@ -809,7 +911,7 @@ module RightAws
809
911
  end
810
912
  end
811
913
 
812
- class QEc2RegisterImageParser < RightAWSParser # :nodoc:
914
+ class QEc2RegisterImageParser < RightAWSParser
813
915
  def tagend(name)
814
916
  @result = @text if name == 'imageId'
815
917
  end
@@ -819,21 +921,22 @@ module RightAws
819
921
  # PARSERS: Image Attribute
820
922
  #-----------------------------------------------------------------
821
923
 
822
- class QEc2LaunchPermissionItemType # :nodoc:
924
+ class QEc2LaunchPermissionItemType
823
925
  attr_accessor :groups
824
926
  attr_accessor :userIds
825
927
  end
826
928
 
827
- class QEc2DescribeImageAttributeType # :nodoc:
929
+ class QEc2DescribeImageAttributeType
828
930
  attr_accessor :imageId
829
931
  attr_accessor :launchPermission
932
+ attr_accessor :productCodes
830
933
  end
831
934
 
832
- class QEc2DescribeImageAttributeParser < RightAWSParser # :nodoc:
935
+ class QEc2DescribeImageAttributeParser < RightAWSParser
833
936
  def tagstart(name, attributes)
834
937
  case name
835
938
  when 'launchPermission'
836
- @result.launchPermission = QEc2LaunchPermissionItemType.new
939
+ @result.launchPermission = QEc2LaunchPermissionItemType.new
837
940
  @result.launchPermission.groups = []
838
941
  @result.launchPermission.userIds = []
839
942
  end
@@ -848,6 +951,8 @@ module RightAws
848
951
  @result.launchPermission.groups << @text if @xmlpath == 'DescribeImageAttributeResponse/launchPermission/item'
849
952
  when 'userId'
850
953
  @result.launchPermission.userIds << @text if @xmlpath == 'DescribeImageAttributeResponse/launchPermission/item'
954
+ when 'productCode'
955
+ (@result.productCodes ||= []) << @text
851
956
  end
852
957
  end
853
958
  def reset
@@ -859,12 +964,12 @@ module RightAws
859
964
  # PARSERS: Instances
860
965
  #-----------------------------------------------------------------
861
966
 
862
- class QEc2InstanceStateType # :nodoc:
967
+ class QEc2InstanceStateType
863
968
  attr_accessor :code
864
969
  attr_accessor :name
865
970
  end
866
971
 
867
- class QEc2RunningInstancesItemType # :nodoc:
972
+ class QEc2RunningInstancesItemType
868
973
  attr_accessor :instanceId
869
974
  attr_accessor :imageId
870
975
  attr_accessor :instanceState
@@ -873,16 +978,17 @@ module RightAws
873
978
  attr_accessor :reason
874
979
  attr_accessor :keyName
875
980
  attr_accessor :amiLaunchIndex
981
+ attr_accessor :productCodes
876
982
  end
877
983
 
878
- class QEc2DescribeInstancesType # :nodoc:
984
+ class QEc2DescribeInstancesType
879
985
  attr_accessor :reservationId
880
986
  attr_accessor :ownerId
881
987
  attr_accessor :groupSet
882
988
  attr_accessor :instancesSet
883
989
  end
884
990
 
885
- class QEc2DescribeInstancesParser < RightAWSParser # :nodoc:
991
+ class QEc2DescribeInstancesParser < RightAWSParser
886
992
  def tagstart(name, attributes)
887
993
  case name
888
994
  when 'item'
@@ -922,6 +1028,7 @@ module RightAws
922
1028
  elsif @xmlpath=='DescribeInstancesResponse/reservationSet'
923
1029
  @result << @reservation
924
1030
  end
1031
+ when 'productCode' ; (@instance.productCodes ||= []) << @text
925
1032
  end
926
1033
  end
927
1034
  def reset
@@ -929,7 +1036,16 @@ module RightAws
929
1036
  end
930
1037
  end
931
1038
 
932
- class QEc2RunInstancesParser < RightAWSParser # :nodoc:
1039
+ class QEc2ConfirmProductInstanceParser < RightAWSParser
1040
+ def tagend(name)
1041
+ @result = @text if name == 'ownerId'
1042
+ end
1043
+ def reset
1044
+ @result = nil
1045
+ end
1046
+ end
1047
+
1048
+ class QEc2RunInstancesParser < RightAWSParser
933
1049
  def tagstart(name, attributes)
934
1050
  case name
935
1051
  when 'RunInstancesResponse'
@@ -966,6 +1082,7 @@ module RightAws
966
1082
  when 'item'
967
1083
  @reservation.instancesSet << @instance if @xmlpath == 'RunInstancesResponse/instancesSet'
968
1084
  when 'RunInstancesResponse'; @result << @reservation
1085
+ when 'productCode' ; (@instance.productCodes ||= []) << @text
969
1086
  end
970
1087
  end
971
1088
  def reset
@@ -973,13 +1090,13 @@ module RightAws
973
1090
  end
974
1091
  end
975
1092
 
976
- class QEc2TerminateInstancesResponseInfoType # :nodoc:
1093
+ class QEc2TerminateInstancesResponseInfoType
977
1094
  attr_accessor :instanceId
978
1095
  attr_accessor :shutdownState
979
1096
  attr_accessor :previousState
980
1097
  end
981
1098
 
982
- class QEc2TerminateInstancesParser < RightAWSParser # :nodoc:
1099
+ class QEc2TerminateInstancesParser < RightAWSParser
983
1100
  def tagstart(name, attributes)
984
1101
  if name == 'item'
985
1102
  @instance = QEc2TerminateInstancesResponseInfoType.new
@@ -1010,13 +1127,13 @@ module RightAws
1010
1127
  # PARSERS: Console
1011
1128
  #-----------------------------------------------------------------
1012
1129
 
1013
- class QEc2GetConsoleOutputResponseType # :nodoc:
1130
+ class QEc2GetConsoleOutputResponseType
1014
1131
  attr_accessor :instanceId
1015
1132
  attr_accessor :timestamp
1016
1133
  attr_accessor :output
1017
1134
  end
1018
1135
 
1019
- class QEc2GetConsoleOutputParser < RightAWSParser # :nodoc:
1136
+ class QEc2GetConsoleOutputParser < RightAWSParser
1020
1137
  def tagend(name)
1021
1138
  case name
1022
1139
  when 'instanceId' ; @result.instanceId = @text