aws 2.3.34 → 2.4.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,1884 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (c) 2007-2008 RightScale Inc
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining
6
- # a copy of this software and associated documentation files (the
7
- # "Software"), to deal in the Software without restriction, including
8
- # without limitation the rights to use, copy, modify, merge, publish,
9
- # distribute, sublicense, and/or sell copies of the Software, and to
10
- # permit persons to whom the Software is furnished to do so, subject to
11
- # the following conditions:
12
- #
13
- # The above copyright notice and this permission notice shall be
14
- # included in all copies or substantial portions of the Software.
15
- #
16
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
- #
24
-
25
- module Aws
26
-
27
- # = Aws::EC2 -- RightScale Amazon EC2 interface
28
- # The Aws::EC2 class provides a complete interface to Amazon's
29
- # Elastic Compute Cloud service, as well as the associated EBS (Elastic Block
30
- # Store).
31
- # For explanations of the semantics
32
- # of each call, please refer to Amazon's documentation at
33
- # http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=87
34
- #
35
- # Examples:
36
- #
37
- # Create an EC2 interface handle:
38
- #
39
- # @ec2 = Aws::Ec2.new(aws_access_key_id,
40
- # aws_secret_access_key)
41
- # Create a new SSH key pair:
42
- # @key = 'right_ec2_awesome_test_key'
43
- # new_key = @ec2.create_key_pair(@key)
44
- # keys = @ec2.describe_key_pairs
45
- #
46
- # Create a security group:
47
- # @group = 'right_ec2_awesome_test_security_group'
48
- # @ec2.create_security_group(@group,'My awesome test group')
49
- # group = @ec2.describe_security_groups([@group])[0]
50
- #
51
- # Configure a security group:
52
- # @ec2.authorize_security_group_named_ingress(@group, account_number, 'default')
53
- # @ec2.authorize_security_group_IP_ingress(@group, 80,80,'udp','192.168.1.0/8')
54
- #
55
- # Describe the available images:
56
- # images = @ec2.describe_images
57
- #
58
- # Launch an instance:
59
- # ec2.run_instances('ami-9a9e7bf3', 1, 1, ['default'], @key, 'SomeImportantUserData', 'public')
60
- #
61
- #
62
- # Describe running instances:
63
- # @ec2.describe_instances
64
- #
65
- # Error handling: all operations raise an Aws::AwsError in case
66
- # of problems. Note that transient errors are automatically retried.
67
-
68
- class Ec2 < AwsBase
69
- include AwsBaseInterface
70
-
71
- # Amazon EC2 API version being used
72
- API_VERSION = "2010-08-31"
73
- DEFAULT_HOST = "ec2.amazonaws.com"
74
- DEFAULT_PATH = '/'
75
- DEFAULT_PROTOCOL = 'https'
76
- DEFAULT_PORT = 443
77
-
78
- # Default addressing type (public=NAT, direct=no-NAT) used when launching instances.
79
- DEFAULT_ADDRESSING_TYPE = 'public'
80
- DNS_ADDRESSING_SET = ['public','direct']
81
-
82
- # Amazon EC2 Instance Types : http://www.amazon.com/b?ie=UTF8&node=370375011
83
- # Default EC2 instance type (platform)
84
- DEFAULT_INSTANCE_TYPE = 'm1.small'
85
- INSTANCE_TYPES = ['t1.micro', 'm1.small','c1.medium','m1.large','m1.xlarge','c1.xlarge']
86
-
87
- @@bench = AwsBenchmarkingBlock.new
88
- def self.bench_xml
89
- @@bench.xml
90
- end
91
- def self.bench_ec2
92
- @@bench.service
93
- end
94
-
95
- # Current API version (sometimes we have to check it outside the GEM).
96
- @@api = ENV['EC2_API_VERSION'] || API_VERSION
97
- def self.api
98
- @@api
99
- end
100
-
101
- # Create a new handle to an EC2 account. All handles share the same per process or per thread
102
- # HTTP connection to Amazon EC2. Each handle is for a specific account. The params have the
103
- # following options:
104
- # * <tt>:endpoint_url</tt> a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol and :region). Example: 'https://eu-west-1.ec2.amazonaws.com/'
105
- # * <tt>:server</tt>: EC2 service host, default: DEFAULT_HOST
106
- # * <tt>:region</tt>: EC2 region (North America by default)
107
- # * <tt>:port</tt>: EC2 service port, default: DEFAULT_PORT
108
- # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
109
- # * <tt>:multi_thread</tt>: true=HTTP connection per thread, false=per process
110
- # * <tt>:logger</tt>: for log messages, default: Rails.logger else STDOUT
111
- # * <tt>:signature_version</tt>: The signature version : '0' or '1'(default)
112
- # * <tt>:cache</tt>: true/false: caching for: ec2_describe_images, describe_instances,
113
- # describe_images_by_owner, describe_images_by_executable_by, describe_availability_zones,
114
- # describe_security_groups, describe_key_pairs, describe_addresses,
115
- # describe_volumes, describe_snapshots methods, default: false.
116
- #
117
- def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
118
- init({ :name => 'EC2',
119
- :default_host => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).host : DEFAULT_HOST,
120
- :default_port => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).port : DEFAULT_PORT,
121
- :default_service => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).path : DEFAULT_PATH,
122
- :default_protocol => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).scheme : DEFAULT_PROTOCOL,
123
- :api_version => API_VERSION },
124
- aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'] ,
125
- aws_secret_access_key|| ENV['AWS_SECRET_ACCESS_KEY'],
126
- params)
127
- # EC2 doesn't really define any transient errors to retry, and in fact,
128
- # when they return a 503 it is usually for 'request limit exceeded' which
129
- # we most certainly should not retry. So let's pare down the list of
130
- # retryable errors to InternalError only (see AwsBase for the default
131
- # list)
132
- amazon_problems = ['InternalError']
133
- end
134
-
135
-
136
- def generate_request(action, params={}) #:nodoc:
137
- service_hash = {"Action" => action,
138
- "AWSAccessKeyId" => @aws_access_key_id,
139
- "Version" => @@api }
140
- service_hash.update(params)
141
- service_params = signed_service_params(@aws_secret_access_key, service_hash, :get, @params[:server], @params[:service])
142
-
143
- # use POST method if the length of the query string is too large
144
- if service_params.size > 2000
145
- if signature_version == '2'
146
- # resign the request because HTTP verb is included into signature
147
- service_params = signed_service_params(@aws_secret_access_key, service_hash, :post, @params[:server], @params[:service])
148
- end
149
- request = Net::HTTP::Post.new(@params[:service])
150
- request.body = service_params
151
- request['Content-Type'] = 'application/x-www-form-urlencoded'
152
- else
153
- request = Net::HTTP::Get.new("#{@params[:service]}?#{service_params}")
154
- end
155
- # prepare output hash
156
- { :request => request,
157
- :server => @params[:server],
158
- :port => @params[:port],
159
- :protocol => @params[:protocol] }
160
- end
161
-
162
- # Sends request to Amazon and parses the response
163
- # Raises AwsError if any banana happened
164
- def request_info(request, parser, options={}) #:nodoc:
165
- conn = get_conn(:ec2_connection, @params, @logger)
166
- request_info_impl(conn, @@bench, request, parser, options)
167
- end
168
-
169
- def hash_params(prefix, list) #:nodoc:
170
- groups = {}
171
- list.each_index{|i| groups.update("#{prefix}.#{i+1}"=>list[i])} if list
172
- return groups
173
- end
174
-
175
- #-----------------------------------------------------------------
176
- # Images
177
- #-----------------------------------------------------------------
178
-
179
- # params:
180
- # { 'ImageId' => ['id1', ..., 'idN'],
181
- # 'Owner' => ['self', ..., 'userN'],
182
- # 'ExecutableBy' => ['self', 'all', ..., 'userN']
183
- # }
184
- def ec2_describe_images(params={}, image_type=nil, cache_for=nil) #:nodoc:
185
- request_hash = {}
186
- params.each do |list_by, list|
187
- request_hash.merge! hash_params(list_by, list.to_a)
188
- end
189
- if image_type
190
- request_hash['Filter.1.Name'] = "image-type"
191
- request_hash['Filter.1.Value.1'] = image_type
192
- end
193
- link = generate_request("DescribeImages", request_hash)
194
- request_cache_or_info cache_for, link, QEc2DescribeImagesParser, @@bench, cache_for
195
- rescue Exception
196
- on_exception
197
- end
198
-
199
- # Retrieve a list of images. Returns array of hashes describing the images or an exception:
200
- # +image_type+ = 'machine' || 'kernel' || 'ramdisk'
201
- #
202
- # ec2.describe_images #=>
203
- # [{:aws_owner => "522821470517",
204
- # :aws_id => "ami-e4b6538d",
205
- # :aws_state => "available",
206
- # :aws_location => "marcins_cool_public_images/ubuntu-6.10.manifest.xml",
207
- # :aws_is_public => true,
208
- # :aws_architecture => "i386",
209
- # :aws_image_type => "machine"},
210
- # {...},
211
- # {...} ]
212
- #
213
- # If +list+ param is set, then retrieve information about the listed images only:
214
- #
215
- # ec2.describe_images(['ami-e4b6538d']) #=>
216
- # [{:aws_owner => "522821470517",
217
- # :aws_id => "ami-e4b6538d",
218
- # :aws_state => "available",
219
- # :aws_location => "marcins_cool_public_images/ubuntu-6.10.manifest.xml",
220
- # :aws_is_public => true,
221
- # :aws_architecture => "i386",
222
- # :aws_image_type => "machine"}]
223
- #
224
- def describe_images(list=[], image_type=nil)
225
- list = list.to_a
226
- cache_for = list.empty? && !image_type ? :describe_images : nil
227
- ec2_describe_images({ 'ImageId' => list }, image_type, cache_for)
228
- end
229
-
230
- #
231
- # Example:
232
- #
233
- # ec2.describe_images_by_owner('522821470517')
234
- # ec2.describe_images_by_owner('self')
235
- #
236
- def describe_images_by_owner(list=['self'], image_type=nil)
237
- list = list.to_a
238
- cache_for = list==['self'] && !image_type ? :describe_images_by_owner : nil
239
- ec2_describe_images({ 'Owner' => list }, image_type, cache_for)
240
- end
241
-
242
- #
243
- # Example:
244
- #
245
- # ec2.describe_images_by_executable_by('522821470517')
246
- # ec2.describe_images_by_executable_by('self')
247
- # ec2.describe_images_by_executable_by('all')
248
- #
249
- def describe_images_by_executable_by(list=['self'], image_type=nil)
250
- list = list.to_a
251
- cache_for = list==['self'] && !image_type ? :describe_images_by_executable_by : nil
252
- ec2_describe_images({ 'ExecutableBy' => list }, image_type, cache_for)
253
- end
254
-
255
-
256
- # Register new image at Amazon.
257
- # Returns new image id or an exception.
258
- #
259
- # ec2.register_image('bucket/key/manifest') #=> 'ami-e444444d'
260
- #
261
- def register_image(image_location)
262
- link = generate_request("RegisterImage",
263
- 'ImageLocation' => image_location.to_s)
264
- request_info(link, QEc2RegisterImageParser.new(:logger => @logger))
265
- rescue Exception
266
- on_exception
267
- end
268
-
269
- # Deregister image at Amazon. Returns +true+ or an exception.
270
- #
271
- # ec2.deregister_image('ami-e444444d') #=> true
272
- #
273
- def deregister_image(image_id)
274
- link = generate_request("DeregisterImage",
275
- 'ImageId' => image_id.to_s)
276
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
277
- rescue Exception
278
- on_exception
279
- end
280
-
281
-
282
- # Describe image attributes. Currently 'launchPermission', 'productCodes', 'kernel', 'ramdisk' and 'blockDeviceMapping' are supported.
283
- #
284
- # ec2.describe_image_attribute('ami-e444444d') #=> {:groups=>["all"], :users=>["000000000777"]}
285
- #
286
- def describe_image_attribute(image_id, attribute='launchPermission')
287
- link = generate_request("DescribeImageAttribute",
288
- 'ImageId' => image_id,
289
- 'Attribute' => attribute)
290
- request_info(link, QEc2DescribeImageAttributeParser.new(:logger => @logger))
291
- rescue Exception
292
- on_exception
293
- end
294
-
295
- # Reset image attribute. Currently, only 'launchPermission' is supported. Returns +true+ or an exception.
296
- #
297
- # ec2.reset_image_attribute('ami-e444444d') #=> true
298
- #
299
- def reset_image_attribute(image_id, attribute='launchPermission')
300
- link = generate_request("ResetImageAttribute",
301
- 'ImageId' => image_id,
302
- 'Attribute' => attribute)
303
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
304
- rescue Exception
305
- on_exception
306
- end
307
-
308
- # Modify an image's attributes. It is recommended that you use
309
- # modify_image_launch_perm_add_users, modify_image_launch_perm_remove_users, etc.
310
- # instead of modify_image_attribute because the signature of
311
- # modify_image_attribute may change with EC2 service changes.
312
- #
313
- # attribute : currently, only 'launchPermission' is supported.
314
- # operation_type : currently, only 'add' & 'remove' are supported.
315
- # vars:
316
- # :user_group : currently, only 'all' is supported.
317
- # :user_id
318
- # :product_code
319
- def modify_image_attribute(image_id, attribute, operation_type = nil, vars = {})
320
- params = {'ImageId' => image_id,
321
- 'Attribute' => attribute}
322
- params['OperationType'] = operation_type if operation_type
323
- params.update(hash_params('UserId', vars[:user_id].to_a)) if vars[:user_id]
324
- params.update(hash_params('UserGroup', vars[:user_group].to_a)) if vars[:user_group]
325
- params.update(hash_params('ProductCode', vars[:product_code])) if vars[:product_code]
326
- link = generate_request("ModifyImageAttribute", params)
327
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
328
- rescue Exception
329
- on_exception
330
- end
331
-
332
- # Grant image launch permissions to users.
333
- # Parameter +userId+ is a list of user AWS account ids.
334
- # Returns +true+ or an exception.
335
- #
336
- # ec2.modify_image_launch_perm_add_users('ami-e444444d',['000000000777','000000000778']) #=> true
337
- def modify_image_launch_perm_add_users(image_id, user_id=[])
338
- modify_image_attribute(image_id, 'launchPermission', 'add', :user_id => user_id.to_a)
339
- end
340
-
341
- # Revokes image launch permissions for users. +userId+ is a list of users AWS accounts ids. Returns +true+ or an exception.
342
- #
343
- # ec2.modify_image_launch_perm_remove_users('ami-e444444d',['000000000777','000000000778']) #=> true
344
- #
345
- def modify_image_launch_perm_remove_users(image_id, user_id=[])
346
- modify_image_attribute(image_id, 'launchPermission', 'remove', :user_id => user_id.to_a)
347
- end
348
-
349
- # Add image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions).
350
- # Returns +true+ or an exception.
351
- #
352
- # ec2.modify_image_launch_perm_add_groups('ami-e444444d') #=> true
353
- #
354
- def modify_image_launch_perm_add_groups(image_id, user_group=['all'])
355
- modify_image_attribute(image_id, 'launchPermission', 'add', :user_group => user_group.to_a)
356
- end
357
-
358
- # Remove image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions).
359
- #
360
- # ec2.modify_image_launch_perm_remove_groups('ami-e444444d') #=> true
361
- #
362
- def modify_image_launch_perm_remove_groups(image_id, user_group=['all'])
363
- modify_image_attribute(image_id, 'launchPermission', 'remove', :user_group => user_group.to_a)
364
- end
365
-
366
- # Add product code to image
367
- #
368
- # ec2.modify_image_product_code('ami-e444444d','0ABCDEF') #=> true
369
- #
370
- def modify_image_product_code(image_id, product_code=[])
371
- modify_image_attribute(image_id, 'productCodes', nil, :product_code => product_code.to_a)
372
- end
373
-
374
- #-----------------------------------------------------------------
375
- # Instances
376
- #-----------------------------------------------------------------
377
-
378
- def get_desc_instances(instances) # :nodoc:
379
- result = []
380
- instances.each do |reservation|
381
- reservation[:instances_set].each do |instance|
382
- # Parse and remove timestamp from the reason string. The timestamp is of
383
- # the request, not when EC2 took action, thus confusing & useless...
384
- instance[:aws_reason] = instance[:aws_reason].sub(/\(\d[^)]*GMT\) */, '')
385
- instance[:aws_owner] = reservation[:aws_owner]
386
- instance[:aws_reservation_id] = reservation[:aws_reservation_id]
387
- instance[:aws_groups] = reservation[:aws_groups]
388
- result << instance
389
- end
390
- end
391
- result
392
- rescue Exception
393
- on_exception
394
- end
395
-
396
- def describe_availability_zones(options={})
397
- link = generate_request("DescribeAvailabilityZones", options={})
398
- request_info_xml_simple(:rds_connection, @params, link, @logger,
399
- :group_tags=>{"DBInstances"=>"DBInstance",
400
- "DBParameterGroups"=>"DBParameterGroup",
401
- "DBSecurityGroups"=>"DBSecurityGroup",
402
- "EC2SecurityGroups"=>"EC2SecurityGroup",
403
- "IPRanges"=>"IPRange"},
404
- :force_array=>["DBInstances",
405
- "DBParameterGroups",
406
- "DBSecurityGroups",
407
- "EC2SecurityGroups",
408
- "IPRanges"],
409
- :pull_out_array=>options[:pull_out_array],
410
- :pull_out_single=>options[:pull_out_single],
411
- :wrapper=>options[:wrapper])
412
- rescue Exception
413
- on_exception
414
- end
415
-
416
- # Retrieve information about EC2 instances. If +list+ is omitted then returns the
417
- # list of all instances.
418
- #
419
- # ec2.describe_instances #=>
420
- # [{:aws_image_id => "ami-e444444d",
421
- # :aws_reason => "",
422
- # :aws_state_code => "16",
423
- # :aws_owner => "000000000888",
424
- # :aws_instance_id => "i-123f1234",
425
- # :aws_reservation_id => "r-aabbccdd",
426
- # :aws_state => "running",
427
- # :dns_name => "domU-12-34-67-89-01-C9.usma2.compute.amazonaws.com",
428
- # :ssh_key_name => "staging",
429
- # :aws_groups => ["default"],
430
- # :private_dns_name => "domU-12-34-67-89-01-C9.usma2.compute.amazonaws.com",
431
- # :aws_instance_type => "m1.small",
432
- # :aws_launch_time => "2008-1-1T00:00:00.000Z"},
433
- # :aws_availability_zone => "us-east-1b",
434
- # :aws_kernel_id => "aki-ba3adfd3",
435
- # :aws_ramdisk_id => "ari-badbad00",
436
- # :monitoring_state => ...,
437
- # ..., {...}]
438
- #
439
- def describe_instances(list=[])
440
- link = generate_request("DescribeInstances", hash_params('InstanceId',list.to_a))
441
- request_cache_or_info(:describe_instances, link, QEc2DescribeInstancesParser, @@bench, list.blank?) do |parser|
442
- get_desc_instances(parser.result)
443
- end
444
- rescue Exception
445
- on_exception
446
- end
447
-
448
- # Return the product code attached to instance or +nil+ otherwise.
449
- #
450
- # ec2.confirm_product_instance('ami-e444444d','12345678') #=> nil
451
- # ec2.confirm_product_instance('ami-e444444d','00001111') #=> "000000000888"
452
- #
453
- def confirm_product_instance(instance, product_code)
454
- link = generate_request("ConfirmProductInstance", { 'ProductCode' => product_code,
455
- 'InstanceId' => instance })
456
- request_info(link, QEc2ConfirmProductInstanceParser.new(:logger => @logger))
457
- end
458
-
459
- # DEPRECATED, USE launch_instances instead.
460
- #
461
- # Launch new EC2 instances. Returns a list of launched instances or an exception.
462
- #
463
- # ec2.run_instances('ami-e444444d',1,1,['my_awesome_group'],'my_awesome_key', 'Woohoo!!!', 'public') #=>
464
- # [{:aws_image_id => "ami-e444444d",
465
- # :aws_reason => "",
466
- # :aws_state_code => "0",
467
- # :aws_owner => "000000000888",
468
- # :aws_instance_id => "i-123f1234",
469
- # :aws_reservation_id => "r-aabbccdd",
470
- # :aws_state => "pending",
471
- # :dns_name => "",
472
- # :ssh_key_name => "my_awesome_key",
473
- # :aws_groups => ["my_awesome_group"],
474
- # :private_dns_name => "",
475
- # :aws_instance_type => "m1.small",
476
- # :aws_launch_time => "2008-1-1T00:00:00.000Z"
477
- # :aws_ramdisk_id => "ari-8605e0ef"
478
- # :aws_kernel_id => "aki-9905e0f0",
479
- # :ami_launch_index => "0",
480
- # :aws_availability_zone => "us-east-1b"
481
- # }]
482
- #
483
- def run_instances(image_id, min_count, max_count, group_ids, key_name, user_data='',
484
- addressing_type = nil, instance_type = nil,
485
- kernel_id = nil, ramdisk_id = nil, availability_zone = nil,
486
- block_device_mappings = nil)
487
- launch_instances(image_id, { :min_count => min_count,
488
- :max_count => max_count,
489
- :user_data => user_data,
490
- :group_ids => group_ids,
491
- :key_name => key_name,
492
- :instance_type => instance_type,
493
- :addressing_type => addressing_type,
494
- :kernel_id => kernel_id,
495
- :ramdisk_id => ramdisk_id,
496
- :availability_zone => availability_zone,
497
- :block_device_mappings => block_device_mappings
498
- })
499
- end
500
-
501
-
502
- # Launch new EC2 instances. Returns a list of launched instances or an exception.
503
- #
504
- # +lparams+ keys (default values in parenthesis):
505
- # :min_count fixnum, (1)
506
- # :max_count fixnum, (1)
507
- # :group_ids array or string ([] == 'default')
508
- # :instance_type string (DEFAULT_INSTACE_TYPE)
509
- # :addressing_type string (DEFAULT_ADDRESSING_TYPE
510
- # :key_name string
511
- # :kernel_id string
512
- # :ramdisk_id string
513
- # :availability_zone string
514
- # :block_device_mappings string
515
- # :user_data string
516
- # :monitoring_enabled boolean (default=false)
517
- #
518
- # ec2.launch_instances('ami-e444444d', :group_ids => 'my_awesome_group',
519
- # :user_data => "Woohoo!!!",
520
- # :addressing_type => "public",
521
- # :key_name => "my_awesome_key",
522
- # :availability_zone => "us-east-1c") #=>
523
- # [{:aws_image_id => "ami-e444444d",
524
- # :aws_reason => "",
525
- # :aws_state_code => "0",
526
- # :aws_owner => "000000000888",
527
- # :aws_instance_id => "i-123f1234",
528
- # :aws_reservation_id => "r-aabbccdd",
529
- # :aws_state => "pending",
530
- # :dns_name => "",
531
- # :ssh_key_name => "my_awesome_key",
532
- # :aws_groups => ["my_awesome_group"],
533
- # :private_dns_name => "",
534
- # :aws_instance_type => "m1.small",
535
- # :aws_launch_time => "2008-1-1T00:00:00.000Z",
536
- # :aws_ramdisk_id => "ari-8605e0ef"
537
- # :aws_kernel_id => "aki-9905e0f0",
538
- # :ami_launch_index => "0",
539
- # :aws_availability_zone => "us-east-1c"
540
- # }]
541
- #
542
- def launch_instances(image_id, options={})
543
- @logger.info("Launching instance of image #{image_id} for #{@aws_access_key_id}, " +
544
- "key: #{options[:key_name]}, groups: #{(options[:group_ids]).to_a.join(',')}")
545
- # careful: keyName and securityGroups may be nil
546
- params = hash_params('SecurityGroup', options[:group_ids].to_a)
547
- params.update( {'ImageId' => image_id,
548
- 'MinCount' => (options[:min_count] || 1).to_s,
549
- 'MaxCount' => (options[:max_count] || 1).to_s,
550
- 'AddressingType' => options[:addressing_type] || DEFAULT_ADDRESSING_TYPE,
551
- 'InstanceType' => options[:instance_type] || DEFAULT_INSTANCE_TYPE })
552
- # optional params
553
- params['KeyName'] = options[:key_name] unless options[:key_name].blank?
554
- params['KernelId'] = options[:kernel_id] unless options[:kernel_id].blank?
555
- params['RamdiskId'] = options[:ramdisk_id] unless options[:ramdisk_id].blank?
556
- params['Placement.AvailabilityZone'] = options[:availability_zone] unless options[:availability_zone].blank?
557
- params['BlockDeviceMappings'] = options[:block_device_mappings] unless options[:block_device_mappings].blank?
558
- params['Monitoring.Enabled'] = options[:monitoring_enabled] unless options[:monitoring_enabled].blank?
559
- params['SubnetId'] = options[:subnet_id] unless options[:subnet_id].blank?
560
- params['AdditionalInfo'] = options[:additional_info] unless options[:additional_info].blank?
561
- params['DisableApiTermination'] = options[:disable_api_termination].to_s unless options[:disable_api_termination].nil?
562
- params['InstanceInitiatedShutdownBehavior'] = options[:instance_initiated_shutdown_behavior] unless options[:instance_initiated_shutdown_behavior].blank?
563
- unless options[:user_data].blank?
564
- options[:user_data].strip!
565
- # Do not use CGI::escape(encode64(...)) as it is done in Amazons EC2 library.
566
- # Amazon 169.254.169.254 does not like escaped symbols!
567
- # And it doesn't like "\n" inside of encoded string! Grrr....
568
- # Otherwise, some of UserData symbols will be lost...
569
- params['UserData'] = Base64.encode64(options[:user_data]).delete("\n").strip unless options[:user_data].blank?
570
- end
571
- link = generate_request("RunInstances", params)
572
- #debugger
573
- instances = request_info(link, QEc2DescribeInstancesParser.new(:logger => @logger))
574
- get_desc_instances(instances)
575
- rescue Exception
576
- on_exception
577
- end
578
-
579
- def monitor_instances(list=[])
580
- link = generate_request("MonitorInstances", hash_params('InstanceId',list.to_a))
581
- request_info(link, QEc2TerminateInstancesParser.new(:logger => @logger))
582
- rescue Exception
583
- on_exception
584
- end
585
-
586
- # Terminates EC2 instances. Returns a list of termination params or an exception.
587
- #
588
- # ec2.terminate_instances(['i-f222222d','i-f222222e']) #=>
589
- # [{:aws_shutdown_state => "shutting-down",
590
- # :aws_instance_id => "i-f222222d",
591
- # :aws_shutdown_state_code => 32,
592
- # :aws_prev_state => "running",
593
- # :aws_prev_state_code => 16},
594
- # {:aws_shutdown_state => "shutting-down",
595
- # :aws_instance_id => "i-f222222e",
596
- # :aws_shutdown_state_code => 32,
597
- # :aws_prev_state => "running",
598
- # :aws_prev_state_code => 16}]
599
- #
600
- def terminate_instances(list=[])
601
- link = generate_request("TerminateInstances", hash_params('InstanceId',list.to_a))
602
- request_info(link, QEc2TerminateInstancesParser.new(:logger => @logger))
603
- rescue Exception
604
- on_exception
605
- end
606
-
607
- # Retreive EC2 instance OS logs. Returns a hash of data or an exception.
608
- #
609
- # ec2.get_console_output('i-f222222d') =>
610
- # {:aws_instance_id => 'i-f222222d',
611
- # :aws_timestamp => "2007-05-23T14:36:07.000-07:00",
612
- # :timestamp => Wed May 23 21:36:07 UTC 2007, # Time instance
613
- # :aws_output => "Linux version 2.6.16-xenU (builder@patchbat.amazonsa) (gcc version 4.0.1 20050727 ..."
614
- def get_console_output(instance_id)
615
- link = generate_request("GetConsoleOutput", { 'InstanceId.1' => instance_id })
616
- request_info(link, QEc2GetConsoleOutputParser.new(:logger => @logger))
617
- rescue Exception
618
- on_exception
619
- end
620
-
621
- # Reboot an EC2 instance. Returns +true+ or an exception.
622
- #
623
- # ec2.reboot_instances(['i-f222222d','i-f222222e']) #=> true
624
- #
625
- def reboot_instances(list)
626
- link = generate_request("RebootInstances", hash_params('InstanceId', list.to_a))
627
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
628
- rescue Exception
629
- on_exception
630
- end
631
-
632
- #-----------------------------------------------------------------
633
- # Instances: Windows addons
634
- #-----------------------------------------------------------------
635
-
636
- # Get initial Windows Server setup password from an instance console output.
637
- #
638
- # my_awesome_key = ec2.create_key_pair('my_awesome_key') #=>
639
- # {:aws_key_name => "my_awesome_key",
640
- # :aws_fingerprint => "01:02:03:f4:25:e6:97:e8:9b:02:1a:26:32:4e:58:6b:7a:8c:9f:03",
641
- # :aws_material => "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAK...Q8MDrCbuQ=\n-----END RSA PRIVATE KEY-----"}
642
- #
643
- # my_awesome_instance = ec2.run_instances('ami-a000000a',1,1,['my_awesome_group'],'my_awesome_key', 'WindowsInstance!!!') #=>
644
- # [{:aws_image_id => "ami-a000000a",
645
- # :aws_instance_id => "i-12345678",
646
- # ...
647
- # :aws_availability_zone => "us-east-1b"
648
- # }]
649
- #
650
- # # wait until instance enters 'operational' state and get it's initial password
651
- #
652
- # puts ec2.get_initial_password(my_awesome_instance[:aws_instance_id], my_awesome_key[:aws_material]) #=> "MhjWcgZuY6"
653
- #
654
- def get_initial_password(instance_id, private_key)
655
- console_output = get_console_output(instance_id)
656
- crypted_password = console_output[:aws_output][%r{<Password>(.+)</Password>}m] && $1
657
- unless crypted_password
658
- raise AwsError.new("Initial password was not found in console output for #{instance_id}")
659
- else
660
- OpenSSL::PKey::RSA.new(private_key).private_decrypt(Base64.decode64(crypted_password))
661
- end
662
- rescue Exception
663
- on_exception
664
- end
665
-
666
- # Bundle a Windows image.
667
- # Internally, it queues the bundling task and shuts down the instance.
668
- # It then takes a snapshot of the Windows volume bundles it, and uploads it to
669
- # S3. After bundling completes, Aws::Ec2#register_image may be used to
670
- # register the new Windows AMI for subsequent launches.
671
- #
672
- # ec2.bundle_instance('i-e3e24e8a', 'my-awesome-bucket', 'my-win-image-1') #=>
673
- # [{:aws_update_time => "2008-10-16T13:58:25.000Z",
674
- # :s3_bucket => "kd-win-1",
675
- # :s3_prefix => "win2pr",
676
- # :aws_state => "pending",
677
- # :aws_id => "bun-26a7424f",
678
- # :aws_instance_id => "i-878a25ee",
679
- # :aws_start_time => "2008-10-16T13:58:02.000Z"}]
680
- #
681
- def bundle_instance(instance_id, s3_bucket, s3_prefix,
682
- s3_owner_aws_access_key_id=nil, s3_owner_aws_secret_access_key=nil,
683
- s3_expires = S3Interface::DEFAULT_EXPIRES_AFTER,
684
- s3_upload_policy='ec2-bundle-read')
685
- # S3 access and signatures
686
- s3_owner_aws_access_key_id ||= @aws_access_key_id
687
- s3_owner_aws_secret_access_key ||= @aws_secret_access_key
688
- s3_expires = Time.now.utc + s3_expires if s3_expires.is_a?(Fixnum) && (s3_expires < S3Interface::ONE_YEAR_IN_SECONDS)
689
- # policy
690
- policy = { 'expiration' => s3_expires.strftime('%Y-%m-%dT%H:%M:%SZ'),
691
- 'conditions' => [ { 'bucket' => s3_bucket },
692
- { 'acl' => s3_upload_policy },
693
- [ 'starts-with', '$key', s3_prefix ] ] }.to_json
694
- policy64 = Base64.encode64(policy).gsub("\n","")
695
- signed_policy64 = AwsUtils.sign(s3_owner_aws_secret_access_key, policy64)
696
- # fill request params
697
- params = { 'InstanceId' => instance_id,
698
- 'Storage.S3.AWSAccessKeyId' => s3_owner_aws_access_key_id,
699
- 'Storage.S3.UploadPolicy' => policy64,
700
- 'Storage.S3.UploadPolicySignature' => signed_policy64,
701
- 'Storage.S3.Bucket' => s3_bucket,
702
- 'Storage.S3.Prefix' => s3_prefix,
703
- }
704
- link = generate_request("BundleInstance", params)
705
- request_info(link, QEc2BundleInstanceParser.new)
706
- rescue Exception
707
- on_exception
708
- end
709
-
710
- # Describe the status of the Windows AMI bundlings.
711
- # If +list+ is omitted the returns the whole list of tasks.
712
- #
713
- # ec2.describe_bundle_tasks(['bun-4fa74226']) #=>
714
- # [{:s3_bucket => "my-awesome-bucket"
715
- # :aws_id => "bun-0fa70206",
716
- # :s3_prefix => "win1pr",
717
- # :aws_start_time => "2008-10-14T16:27:57.000Z",
718
- # :aws_update_time => "2008-10-14T16:37:10.000Z",
719
- # :aws_error_code => "Client.S3Error",
720
- # :aws_error_message =>
721
- # "AccessDenied(403)- Invalid according to Policy: Policy Condition failed: [\"eq\", \"$acl\", \"aws-exec-read\"]",
722
- # :aws_state => "failed",
723
- # :aws_instance_id => "i-e3e24e8a"}]
724
- #
725
- def describe_bundle_tasks(list=[])
726
- link = generate_request("DescribeBundleTasks", hash_params('BundleId', list.to_a))
727
- request_info(link, QEc2DescribeBundleTasksParser.new)
728
- rescue Exception
729
- on_exception
730
- end
731
-
732
- # Cancel an in‐progress or pending bundle task by id.
733
- #
734
- # ec2.cancel_bundle_task('bun-73a7421a') #=>
735
- # [{:s3_bucket => "my-awesome-bucket"
736
- # :aws_id => "bun-0fa70206",
737
- # :s3_prefix => "win02",
738
- # :aws_start_time => "2008-10-14T13:00:29.000Z",
739
- # :aws_error_message => "User has requested bundling operation cancellation",
740
- # :aws_state => "failed",
741
- # :aws_update_time => "2008-10-14T13:01:31.000Z",
742
- # :aws_error_code => "Client.Cancelled",
743
- # :aws_instance_id => "i-e3e24e8a"}
744
- #
745
- def cancel_bundle_task(bundle_id)
746
- link = generate_request("CancelBundleTask", { 'BundleId' => bundle_id })
747
- request_info(link, QEc2BundleInstanceParser.new)
748
- rescue Exception
749
- on_exception
750
- end
751
-
752
- #-----------------------------------------------------------------
753
- # Security groups
754
- #-----------------------------------------------------------------
755
-
756
- # Retrieve Security Group information. If +list+ is omitted the returns the whole list of groups.
757
- #
758
- # ec2.describe_security_groups #=>
759
- # [{:aws_group_name => "default-1",
760
- # :aws_owner => "000000000888",
761
- # :aws_description => "Default allowing SSH, HTTP, and HTTPS ingress",
762
- # :aws_perms =>
763
- # [{:owner => "000000000888", :group => "default"},
764
- # {:owner => "000000000888", :group => "default-1"},
765
- # {:to_port => "-1", :protocol => "icmp", :from_port => "-1", :cidr_ips => "0.0.0.0/0"},
766
- # {:to_port => "22", :protocol => "tcp", :from_port => "22", :cidr_ips => "0.0.0.0/0"},
767
- # {:to_port => "80", :protocol => "tcp", :from_port => "80", :cidr_ips => "0.0.0.0/0"},
768
- # {:to_port => "443", :protocol => "tcp", :from_port => "443", :cidr_ips => "0.0.0.0/0"}]},
769
- # ..., {...}]
770
- #
771
- def describe_security_groups(list=[])
772
- link = generate_request("DescribeSecurityGroups", hash_params('GroupName',list.to_a))
773
- request_cache_or_info( :describe_security_groups, link, QEc2DescribeSecurityGroupsParser, @@bench, list.blank?) do |parser|
774
- result = []
775
- parser.result.each do |item|
776
- perms = []
777
- item.ipPermissions.each do |perm|
778
- perm.groups.each do |ngroup|
779
- perms << {:group => ngroup.groupName,
780
- :owner => ngroup.userId}
781
- end
782
- perm.ipRanges.each do |cidr_ip|
783
- perms << {:from_port => perm.fromPort,
784
- :to_port => perm.toPort,
785
- :protocol => perm.ipProtocol,
786
- :cidr_ips => cidr_ip}
787
- end
788
- end
789
-
790
- # delete duplication
791
- perms.each_index do |i|
792
- (0...i).each do |j|
793
- if perms[i] == perms[j] then perms[i] = nil; break; end
794
- end
795
- end
796
- perms.compact!
797
-
798
- result << {:aws_owner => item.ownerId,
799
- :aws_group_name => item.groupName,
800
- :aws_description => item.groupDescription,
801
- :aws_perms => perms}
802
-
803
- end
804
- result
805
- end
806
- rescue Exception
807
- on_exception
808
- end
809
-
810
- # Create new Security Group. Returns +true+ or an exception.
811
- #
812
- # ec2.create_security_group('default-1',"Default allowing SSH, HTTP, and HTTPS ingress") #=> true
813
- #
814
- def create_security_group(name, description)
815
- # EC2 doesn't like an empty description...
816
- description = " " if description.blank?
817
- link = generate_request("CreateSecurityGroup",
818
- 'GroupName' => name.to_s,
819
- 'GroupDescription' => description.to_s)
820
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
821
- rescue Exception
822
- on_exception
823
- end
824
-
825
- # Remove Security Group. Returns +true+ or an exception.
826
- #
827
- # ec2.delete_security_group('default-1') #=> true
828
- #
829
- def delete_security_group(name)
830
- link = generate_request("DeleteSecurityGroup",
831
- 'GroupName' => name.to_s)
832
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
833
- rescue Exception
834
- on_exception
835
- end
836
-
837
- # Authorize named ingress for security group. Allows instances that are member of someone
838
- # else's security group to open connections to instances in my group.
839
- #
840
- # ec2.authorize_security_group_named_ingress('my_awesome_group', '7011-0219-8268', 'their_group_name') #=> true
841
- #
842
- def authorize_security_group_named_ingress(name, owner, group)
843
- link = generate_request("AuthorizeSecurityGroupIngress",
844
- 'GroupName' => name.to_s,
845
- 'SourceSecurityGroupName' => group.to_s,
846
- 'SourceSecurityGroupOwnerId' => owner.to_s.gsub(/-/,''))
847
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
848
- rescue Exception
849
- on_exception
850
- end
851
-
852
- # Revoke named ingress for security group.
853
- #
854
- # ec2.revoke_security_group_named_ingress('my_awesome_group', aws_user_id, 'another_group_name') #=> true
855
- #
856
- def revoke_security_group_named_ingress(name, owner, group)
857
- link = generate_request("RevokeSecurityGroupIngress",
858
- 'GroupName' => name.to_s,
859
- 'SourceSecurityGroupName' => group.to_s,
860
- 'SourceSecurityGroupOwnerId' => owner.to_s.gsub(/-/,''))
861
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
862
- rescue Exception
863
- on_exception
864
- end
865
-
866
- # Add permission to a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp'.
867
- #
868
- # ec2.authorize_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
869
- # ec2.authorize_security_group_IP_ingress('my_awesome_group', -1, -1, 'icmp') #=> true
870
- #
871
- def authorize_security_group_IP_ingress(name, from_port, to_port, protocol='tcp', cidr_ip='0.0.0.0/0')
872
- link = generate_request("AuthorizeSecurityGroupIngress",
873
- 'GroupName' => name.to_s,
874
- 'IpProtocol' => protocol.to_s,
875
- 'FromPort' => from_port.to_s,
876
- 'ToPort' => to_port.to_s,
877
- 'CidrIp' => cidr_ip.to_s)
878
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
879
- rescue Exception
880
- on_exception
881
- end
882
-
883
- # Remove permission from a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp' ('tcp' is default).
884
- #
885
- # ec2.revoke_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
886
- #
887
- def revoke_security_group_IP_ingress(name, from_port, to_port, protocol='tcp', cidr_ip='0.0.0.0/0')
888
- link = generate_request("RevokeSecurityGroupIngress",
889
- 'GroupName' => name.to_s,
890
- 'IpProtocol' => protocol.to_s,
891
- 'FromPort' => from_port.to_s,
892
- 'ToPort' => to_port.to_s,
893
- 'CidrIp' => cidr_ip.to_s)
894
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
895
- rescue Exception
896
- on_exception
897
- end
898
-
899
- #-----------------------------------------------------------------
900
- # Keys
901
- #-----------------------------------------------------------------
902
-
903
- # Retrieve a list of SSH keys. Returns an array of keys or an exception. Each key is
904
- # represented as a two-element hash.
905
- #
906
- # ec2.describe_key_pairs #=>
907
- # [{: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"},
908
- # {:aws_fingerprint=> "1e:29:30:47:58:6d:7b:8c:9f:08:11:20:3c:44:52:69:74:80:97:08", :aws_key_name=>"key-2"},
909
- # ..., {...} ]
910
- #
911
- def describe_key_pairs(list=[])
912
- link = generate_request("DescribeKeyPairs", hash_params('KeyName',list.to_a))
913
- request_cache_or_info :describe_key_pairs, link, QEc2DescribeKeyPairParser, @@bench, list.blank?
914
- rescue Exception
915
- on_exception
916
- end
917
-
918
- # Create new SSH key. Returns a hash of the key's data or an exception.
919
- #
920
- # ec2.create_key_pair('my_awesome_key') #=>
921
- # {:aws_key_name => "my_awesome_key",
922
- # :aws_fingerprint => "01:02:03:f4:25:e6:97:e8:9b:02:1a:26:32:4e:58:6b:7a:8c:9f:03",
923
- # :aws_material => "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAK...Q8MDrCbuQ=\n-----END RSA PRIVATE KEY-----"}
924
- #
925
- def create_key_pair(name)
926
- link = generate_request("CreateKeyPair",
927
- 'KeyName' => name.to_s)
928
- request_info(link, QEc2CreateKeyPairParser.new(:logger => @logger))
929
- rescue Exception
930
- on_exception
931
- end
932
-
933
- # Delete a key pair. Returns +true+ or an exception.
934
- #
935
- # ec2.delete_key_pair('my_awesome_key') #=> true
936
- #
937
- def delete_key_pair(name)
938
- link = generate_request("DeleteKeyPair",
939
- 'KeyName' => name.to_s)
940
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
941
- rescue Exception
942
- on_exception
943
- end
944
-
945
- #-----------------------------------------------------------------
946
- # Elastic IPs
947
- #-----------------------------------------------------------------
948
-
949
- # Acquire a new elastic IP address for use with your account.
950
- # Returns allocated IP address or an exception.
951
- #
952
- # ec2.allocate_address #=> '75.101.154.140'
953
- #
954
- def allocate_address
955
- link = generate_request("AllocateAddress")
956
- request_info(link, QEc2AllocateAddressParser.new(:logger => @logger))
957
- rescue Exception
958
- on_exception
959
- end
960
-
961
- # Associate an elastic IP address with an instance.
962
- # Returns +true+ or an exception.
963
- #
964
- # ec2.associate_address('i-d630cbbf', '75.101.154.140') #=> true
965
- #
966
- def associate_address(instance_id, public_ip)
967
- link = generate_request("AssociateAddress",
968
- "InstanceId" => instance_id.to_s,
969
- "PublicIp" => public_ip.to_s)
970
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
971
- rescue Exception
972
- on_exception
973
- end
974
-
975
- # List elastic IP addresses assigned to your account.
976
- # Returns an array of 2 keys (:instance_id and :public_ip) hashes:
977
- #
978
- # ec2.describe_addresses #=> [{:instance_id=>"i-d630cbbf", :public_ip=>"75.101.154.140"},
979
- # {:instance_id=>nil, :public_ip=>"75.101.154.141"}]
980
- #
981
- # ec2.describe_addresses('75.101.154.140') #=> [{:instance_id=>"i-d630cbbf", :public_ip=>"75.101.154.140"}]
982
- #
983
- def describe_addresses(list=[])
984
- link = generate_request("DescribeAddresses",
985
- hash_params('PublicIp',list.to_a))
986
- request_cache_or_info :describe_addresses, link, QEc2DescribeAddressesParser, @@bench, list.blank?
987
- rescue Exception
988
- on_exception
989
- end
990
-
991
- # Disassociate the specified elastic IP address from the instance to which it is assigned.
992
- # Returns +true+ or an exception.
993
- #
994
- # ec2.disassociate_address('75.101.154.140') #=> true
995
- #
996
- def disassociate_address(public_ip)
997
- link = generate_request("DisassociateAddress",
998
- "PublicIp" => public_ip.to_s)
999
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
1000
- rescue Exception
1001
- on_exception
1002
- end
1003
-
1004
- # Release an elastic IP address associated with your account.
1005
- # Returns +true+ or an exception.
1006
- #
1007
- # ec2.release_address('75.101.154.140') #=> true
1008
- #
1009
- def release_address(public_ip)
1010
- link = generate_request("ReleaseAddress",
1011
- "PublicIp" => public_ip.to_s)
1012
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
1013
- rescue Exception
1014
- on_exception
1015
- end
1016
-
1017
- #-----------------------------------------------------------------
1018
- # Availability zones
1019
- #-----------------------------------------------------------------
1020
-
1021
- # Describes availability zones that are currently available to the account and their states.
1022
- # Returns an array of 2 keys (:zone_name and :zone_state) hashes:
1023
- #
1024
- # ec2.describe_availability_zones #=> [{:region_name=>"us-east-1",
1025
- # :zone_name=>"us-east-1a",
1026
- # :zone_state=>"available"}, ... ]
1027
- #
1028
- # ec2.describe_availability_zones('us-east-1c') #=> [{:region_name=>"us-east-1",
1029
- # :zone_state=>"available",
1030
- # :zone_name=>"us-east-1c"}]
1031
- #
1032
- def describe_availability_zones(list=[])
1033
- link = generate_request("DescribeAvailabilityZones",
1034
- hash_params('ZoneName',list.to_a))
1035
- request_cache_or_info :describe_availability_zones, link, QEc2DescribeAvailabilityZonesParser, @@bench, list.blank?
1036
- rescue Exception
1037
- on_exception
1038
- end
1039
-
1040
- #-----------------------------------------------------------------
1041
- # Regions
1042
- #-----------------------------------------------------------------
1043
-
1044
- # Describe regions.
1045
- #
1046
- # ec2.describe_regions #=> ["eu-west-1", "us-east-1"]
1047
- #
1048
- def describe_regions(list=[])
1049
- link = generate_request("DescribeRegions",
1050
- hash_params('RegionName',list.to_a))
1051
- request_cache_or_info :describe_regions, link, QEc2DescribeRegionsParser, @@bench, list.blank?
1052
- rescue Exception
1053
- on_exception
1054
- end
1055
-
1056
-
1057
- #-----------------------------------------------------------------
1058
- # EBS: Volumes
1059
- #-----------------------------------------------------------------
1060
-
1061
- # Describe all EBS volumes.
1062
- #
1063
- # ec2.describe_volumes #=>
1064
- # [{:aws_size => 94,
1065
- # :aws_device => "/dev/sdc",
1066
- # :aws_attachment_status => "attached",
1067
- # :zone => "merlot",
1068
- # :snapshot_id => nil,
1069
- # :aws_attached_at => Wed Jun 18 08:19:28 UTC 2008,
1070
- # :aws_status => "in-use",
1071
- # :aws_id => "vol-60957009",
1072
- # :aws_created_at => Wed Jun 18 08:19:20s UTC 2008,
1073
- # :aws_instance_id => "i-c014c0a9"},
1074
- # {:aws_size => 1,
1075
- # :zone => "merlot",
1076
- # :snapshot_id => nil,
1077
- # :aws_status => "available",
1078
- # :aws_id => "vol-58957031",
1079
- # :aws_created_at => Wed Jun 18 08:19:21 UTC 2008,}, ... ]
1080
- #
1081
- def describe_volumes(list=[])
1082
- link = generate_request("DescribeVolumes",
1083
- hash_params('VolumeId',list.to_a))
1084
- request_cache_or_info :describe_volumes, link, QEc2DescribeVolumesParser, @@bench, list.blank?
1085
- rescue Exception
1086
- on_exception
1087
- end
1088
-
1089
- # Create new EBS volume based on previously created snapshot.
1090
- # +Size+ in Gigabytes.
1091
- #
1092
- # ec2.create_volume('snap-000000', 10, zone) #=>
1093
- # {:snapshot_id => "snap-e21df98b",
1094
- # :aws_status => "creating",
1095
- # :aws_id => "vol-fc9f7a95",
1096
- # :zone => "merlot",
1097
- # :aws_created_at => Tue Jun 24 18:13:32 UTC 2008,
1098
- # :aws_size => 94}
1099
- #
1100
- def create_volume(snapshot_id, size, zone)
1101
- link = generate_request("CreateVolume",
1102
- "SnapshotId" => snapshot_id.to_s,
1103
- "Size" => size.to_s,
1104
- "AvailabilityZone" => zone.to_s )
1105
- request_info(link, QEc2CreateVolumeParser.new(:logger => @logger))
1106
- rescue Exception
1107
- on_exception
1108
- end
1109
-
1110
- # Delete the specified EBS volume.
1111
- # This does not deletes any snapshots created from this volume.
1112
- #
1113
- # ec2.delete_volume('vol-b48a6fdd') #=> true
1114
- #
1115
- def delete_volume(volume_id)
1116
- link = generate_request("DeleteVolume",
1117
- "VolumeId" => volume_id.to_s)
1118
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
1119
- rescue Exception
1120
- on_exception
1121
- end
1122
-
1123
- # Attach the specified EBS volume to a specified instance, exposing the
1124
- # volume using the specified device name.
1125
- #
1126
- # ec2.attach_volume('vol-898a6fe0', 'i-7c905415', '/dev/sdh') #=>
1127
- # { :aws_instance_id => "i-7c905415",
1128
- # :aws_device => "/dev/sdh",
1129
- # :aws_status => "attaching",
1130
- # :aws_attached_at => "2008-03-28T14:14:39.000Z",
1131
- # :aws_id => "vol-898a6fe0" }
1132
- #
1133
- def attach_volume(volume_id, instance_id, device)
1134
- link = generate_request("AttachVolume",
1135
- "VolumeId" => volume_id.to_s,
1136
- "InstanceId" => instance_id.to_s,
1137
- "Device" => device.to_s)
1138
- request_info(link, QEc2AttachAndDetachVolumeParser.new(:logger => @logger))
1139
- rescue Exception
1140
- on_exception
1141
- end
1142
-
1143
- # Detach the specified EBS volume from the instance to which it is attached.
1144
- #
1145
- # ec2.detach_volume('vol-898a6fe0') #=>
1146
- # { :aws_instance_id => "i-7c905415",
1147
- # :aws_device => "/dev/sdh",
1148
- # :aws_status => "detaching",
1149
- # :aws_attached_at => "2008-03-28T14:38:34.000Z",
1150
- # :aws_id => "vol-898a6fe0"}
1151
- #
1152
- def detach_volume(volume_id, instance_id=nil, device=nil, force=nil)
1153
- hash = { "VolumeId" => volume_id.to_s }
1154
- hash["InstanceId"] = instance_id.to_s unless instance_id.blank?
1155
- hash["Device"] = device.to_s unless device.blank?
1156
- hash["Force"] = 'true' if force
1157
- #
1158
- link = generate_request("DetachVolume", hash)
1159
- request_info(link, QEc2AttachAndDetachVolumeParser.new(:logger => @logger))
1160
- rescue Exception
1161
- on_exception
1162
- end
1163
-
1164
-
1165
- #-----------------------------------------------------------------
1166
- # EBS: Snapshots
1167
- #-----------------------------------------------------------------
1168
-
1169
- # Describe all EBS snapshots.
1170
- #
1171
- # ec2.describe_snapshots #=>
1172
- # [ { :aws_progress => "100%",
1173
- # :aws_status => "completed",
1174
- # :aws_id => "snap-72a5401b",
1175
- # :aws_volume_id => "vol-5582673c",
1176
- # :aws_started_at => "2008-02-23T02:50:48.000Z"},
1177
- # { :aws_progress => "100%",
1178
- # :aws_status => "completed",
1179
- # :aws_id => "snap-75a5401c",
1180
- # :aws_volume_id => "vol-5582673c",
1181
- # :aws_started_at => "2008-02-23T16:23:19.000Z" },...]
1182
- #
1183
- def describe_snapshots(list=[])
1184
- link = generate_request("DescribeSnapshots",
1185
- hash_params('SnapshotId',list.to_a))
1186
- request_cache_or_info :describe_snapshots, link, QEc2DescribeSnapshotsParser, @@bench, list.blank?
1187
- rescue Exception
1188
- on_exception
1189
- end
1190
-
1191
- # Create a snapshot of specified volume.
1192
- #
1193
- # ec2.create_snapshot('vol-898a6fe0') #=>
1194
- # {:aws_volume_id => "vol-fd9f7a94",
1195
- # :aws_started_at => Tue Jun 24 18:40:40 UTC 2008,
1196
- # :aws_progress => "",
1197
- # :aws_status => "pending",
1198
- # :aws_id => "snap-d56783bc"}
1199
- #
1200
- def create_snapshot(volume_id)
1201
- link = generate_request("CreateSnapshot",
1202
- "VolumeId" => volume_id.to_s)
1203
- request_info(link, QEc2CreateSnapshotParser.new(:logger => @logger))
1204
- rescue Exception
1205
- on_exception
1206
- end
1207
-
1208
- # Create a snapshot of specified volume, but with the normal retry algorithms disabled.
1209
- # This method will return immediately upon error. The user can specify connect and read timeouts (in s)
1210
- # for the connection to AWS. If the user does not specify timeouts, try_create_snapshot uses the default values
1211
- # in Rightscale::HttpConnection.
1212
- #
1213
- # ec2.try_create_snapshot('vol-898a6fe0') #=>
1214
- # {:aws_volume_id => "vol-fd9f7a94",
1215
- # :aws_started_at => Tue Jun 24 18:40:40 UTC 2008,
1216
- # :aws_progress => "",
1217
- # :aws_status => "pending",
1218
- # :aws_id => "snap-d56783bc"}
1219
- #
1220
- def try_create_snapshot(volume_id, connect_timeout = nil, read_timeout = nil)
1221
- # For safety in the ensure block...we don't want to restore values
1222
- # if we never read them in the first place
1223
- orig_reiteration_time = nil
1224
- orig_http_params = nil
1225
-
1226
- orig_reiteration_time = Aws::AWSErrorHandler::reiteration_time
1227
- Aws::AWSErrorHandler::reiteration_time = 0
1228
-
1229
- orig_http_params = Rightscale::HttpConnection::params()
1230
- new_http_params = orig_http_params.dup
1231
- new_http_params[:http_connection_retry_count] = 0
1232
- new_http_params[:http_connection_open_timeout] = connect_timeout if !connect_timeout.nil?
1233
- new_http_params[:http_connection_read_timeout] = read_timeout if !read_timeout.nil?
1234
- Rightscale::HttpConnection::params = new_http_params
1235
-
1236
- link = generate_request("CreateSnapshot",
1237
- "VolumeId" => volume_id.to_s)
1238
- request_info(link, QEc2CreateSnapshotParser.new(:logger => @logger))
1239
-
1240
- rescue Exception
1241
- on_exception
1242
- ensure
1243
- Aws::AWSErrorHandler::reiteration_time = orig_reiteration_time if orig_reiteration_time
1244
- Rightscale::HttpConnection::params = orig_http_params if orig_http_params
1245
- end
1246
-
1247
- # Delete the specified snapshot.
1248
- #
1249
- # ec2.delete_snapshot('snap-55a5403c') #=> true
1250
- #
1251
- def delete_snapshot(snapshot_id)
1252
- link = generate_request("DeleteSnapshot",
1253
- "SnapshotId" => snapshot_id.to_s)
1254
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
1255
- rescue Exception
1256
- on_exception
1257
- end
1258
-
1259
- # Add/replace one tag to a resource
1260
- # http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference_query_CreateTags.html
1261
- #
1262
- # ec2.create_tag('ami-1a2b3c4d', 'webserver') #=> true
1263
- # ec2.create_tag('i-7f4d3a2b', 'stack', 'Production') #=> true
1264
- #
1265
- def create_tag(resource_id, key, value = nil)
1266
- link = generate_request("CreateTags",
1267
- "ResourceId.1" => resource_id.to_s,
1268
- "Tag.1.Key" => key.to_s,
1269
- "Tag.1.Value" => value.to_s)
1270
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
1271
- rescue Exception
1272
- on_exception
1273
- end
1274
-
1275
- # Describe tags
1276
- # http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference_query_DescribeTags.html
1277
- #
1278
- # ec2.describe_tags
1279
- # ec2.describe_tags(
1280
- # 'Filter.1.Name' => 'resource-type', 'Filter.1.Value.1' => 'instance',
1281
- # 'Filter.2.Name' => 'value', 'Filter.2.Value.1' => 'Test', 'Filter.2.Value.2' => 'Production'
1282
- # )
1283
- #
1284
- def describe_tags(filters = {})
1285
- link = generate_request("DescribeTags", filters)
1286
- request_info(link, QEc2DescribeTagsParser.new(:logger => @logger))
1287
- rescue Exception
1288
- on_exception
1289
- end
1290
-
1291
- # Delete one or all tags from a resource
1292
- # http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference_query_DeleteTags.html
1293
- #
1294
- # ec2.delete_tag('i-7f4d3a2b', 'stack') #=> true
1295
- # ec2.delete_tag('i-7f4d3a2b', 'stack', 'Production') #=> true
1296
- #
1297
- # "If you omit Tag.n.Value, we delete the tag regardless of its value. If
1298
- # you specify this parameter with an empty string as the value, we delete the
1299
- # key only if its value is an empty string."
1300
- # http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference_query_DeleteTags.html
1301
- #
1302
- def delete_tag(resource_id, key, value = nil)
1303
- request_args = {"ResourceId.1" => resource_id.to_s, "Tag.1.Key" => key.to_s}
1304
- request_args["Tag.1.Value"] = value.to_s if value
1305
-
1306
- link = generate_request("DeleteTags", request_args)
1307
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
1308
- rescue Exception
1309
- on_exception
1310
- end
1311
-
1312
- #-----------------------------------------------------------------
1313
- # PARSERS: Boolean Response Parser
1314
- #-----------------------------------------------------------------
1315
-
1316
- class RightBoolResponseParser < AwsParser #:nodoc:
1317
- def tagend(name)
1318
- @result = @text=='true' ? true : false if name == 'return'
1319
- end
1320
- end
1321
-
1322
- #-----------------------------------------------------------------
1323
- # PARSERS: Key Pair
1324
- #-----------------------------------------------------------------
1325
-
1326
- class QEc2DescribeKeyPairParser < AwsParser #:nodoc:
1327
- def tagstart(name, attributes)
1328
- @item = {} if name == 'item'
1329
- end
1330
- def tagend(name)
1331
- case name
1332
- when 'keyName' then @item[:aws_key_name] = @text
1333
- when 'keyFingerprint' then @item[:aws_fingerprint] = @text
1334
- when 'item' then @result << @item
1335
- end
1336
- end
1337
- def reset
1338
- @result = [];
1339
- end
1340
- end
1341
-
1342
- class QEc2CreateKeyPairParser < AwsParser #:nodoc:
1343
- def tagstart(name, attributes)
1344
- @result = {} if name == 'CreateKeyPairResponse'
1345
- end
1346
- def tagend(name)
1347
- case name
1348
- when 'keyName' then @result[:aws_key_name] = @text
1349
- when 'keyFingerprint' then @result[:aws_fingerprint] = @text
1350
- when 'keyMaterial' then @result[:aws_material] = @text
1351
- end
1352
- end
1353
- end
1354
-
1355
- #-----------------------------------------------------------------
1356
- # PARSERS: Security Groups
1357
- #-----------------------------------------------------------------
1358
-
1359
- class QEc2UserIdGroupPairType #:nodoc:
1360
- attr_accessor :userId
1361
- attr_accessor :groupName
1362
- end
1363
-
1364
- class QEc2IpPermissionType #:nodoc:
1365
- attr_accessor :ipProtocol
1366
- attr_accessor :fromPort
1367
- attr_accessor :toPort
1368
- attr_accessor :groups
1369
- attr_accessor :ipRanges
1370
- end
1371
-
1372
- class QEc2SecurityGroupItemType #:nodoc:
1373
- attr_accessor :groupName
1374
- attr_accessor :groupDescription
1375
- attr_accessor :ownerId
1376
- attr_accessor :ipPermissions
1377
- end
1378
-
1379
-
1380
- class QEc2DescribeSecurityGroupsParser < AwsParser #:nodoc:
1381
- def tagstart(name, attributes)
1382
- case name
1383
- when 'item'
1384
- if @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo'
1385
- @group = QEc2SecurityGroupItemType.new
1386
- @group.ipPermissions = []
1387
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions'
1388
- @perm = QEc2IpPermissionType.new
1389
- @perm.ipRanges = []
1390
- @perm.groups = []
1391
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions/item/groups'
1392
- @sgroup = QEc2UserIdGroupPairType.new
1393
- end
1394
- end
1395
- end
1396
- def tagend(name)
1397
- case name
1398
- when 'ownerId' then @group.ownerId = @text
1399
- when 'groupDescription' then @group.groupDescription = @text
1400
- when 'groupName'
1401
- if @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item'
1402
- @group.groupName = @text
1403
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions/item/groups/item'
1404
- @sgroup.groupName = @text
1405
- end
1406
- when 'ipProtocol' then @perm.ipProtocol = @text
1407
- when 'fromPort' then @perm.fromPort = @text
1408
- when 'toPort' then @perm.toPort = @text
1409
- when 'userId' then @sgroup.userId = @text
1410
- when 'cidrIp' then @perm.ipRanges << @text
1411
- when 'item'
1412
- if @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions/item/groups'
1413
- @perm.groups << @sgroup
1414
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions'
1415
- @group.ipPermissions << @perm
1416
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo'
1417
- @result << @group
1418
- end
1419
- end
1420
- end
1421
- def reset
1422
- @result = []
1423
- end
1424
- end
1425
-
1426
- #-----------------------------------------------------------------
1427
- # PARSERS: Images
1428
- #-----------------------------------------------------------------
1429
-
1430
- class QEc2DescribeImagesParser < AwsParser #:nodoc:
1431
- def tagstart(name, attributes)
1432
- if name == 'item' && @xmlpath[%r{.*/imagesSet$}]
1433
- @image = {}
1434
- end
1435
- end
1436
- def tagend(name)
1437
- case name
1438
- when 'imageId' then @image[:aws_id] = @text
1439
- when 'name' then @image[:aws_name] = @text
1440
- when 'description' then @image[:aws_description] = @text
1441
- when 'imageLocation' then @image[:aws_location] = @text
1442
- when 'imageState' then @image[:aws_state] = @text
1443
- when 'imageOwnerId' then @image[:aws_owner] = @text
1444
- when 'isPublic' then @image[:aws_is_public]= @text == 'true' ? true : false
1445
- when 'productCode' then (@image[:aws_product_codes] ||= []) << @text
1446
- when 'architecture' then @image[:aws_architecture] = @text
1447
- when 'imageType' then @image[:aws_image_type] = @text
1448
- when 'kernelId' then @image[:aws_kernel_id] = @text
1449
- when 'ramdiskId' then @image[:aws_ramdisk_id] = @text
1450
- when 'item' then @result << @image if @xmlpath[%r{.*/imagesSet$}]
1451
- end
1452
- end
1453
- def reset
1454
- @result = []
1455
- end
1456
- end
1457
-
1458
- class QEc2RegisterImageParser < AwsParser #:nodoc:
1459
- def tagend(name)
1460
- @result = @text if name == 'imageId'
1461
- end
1462
- end
1463
-
1464
- #-----------------------------------------------------------------
1465
- # PARSERS: Image Attribute
1466
- #-----------------------------------------------------------------
1467
-
1468
- class QEc2DescribeImageAttributeParser < AwsParser #:nodoc:
1469
- def tagstart(name, attributes)
1470
- case name
1471
- when 'launchPermission'
1472
- @result[:groups] = []
1473
- @result[:users] = []
1474
- when 'productCodes'
1475
- @result[:aws_product_codes] = []
1476
- end
1477
- end
1478
- def tagend(name)
1479
- # right now only 'launchPermission' is supported by Amazon.
1480
- # But nobody know what will they xml later as attribute. That is why we
1481
- # check for 'group' and 'userId' inside of 'launchPermission/item'
1482
- case name
1483
- when 'imageId' then @result[:aws_id] = @text
1484
- when 'group' then @result[:groups] << @text if @xmlpath == 'DescribeImageAttributeResponse/launchPermission/item'
1485
- when 'userId' then @result[:users] << @text if @xmlpath == 'DescribeImageAttributeResponse/launchPermission/item'
1486
- when 'productCode' then @result[:aws_product_codes] << @text
1487
- when 'kernel' then @result[:aws_kernel] = @text
1488
- when 'ramdisk' then @result[:aws_ramdisk] = @text
1489
- when 'blockDeviceMapping' then @result[:block_device_mapping] = @text
1490
- end
1491
- end
1492
- def reset
1493
- @result = {}
1494
- end
1495
- end
1496
-
1497
- #-----------------------------------------------------------------
1498
- # PARSERS: Instances
1499
- #-----------------------------------------------------------------
1500
-
1501
- class QEc2DescribeInstancesParser < AwsParser #:nodoc:
1502
- def tagstart(name, attributes)
1503
- # DescribeInstances property
1504
- if (name == 'item' && @xmlpath == 'DescribeInstancesResponse/reservationSet') ||
1505
- # RunInstances property
1506
- (name == 'RunInstancesResponse')
1507
- @reservation = { :aws_groups => [],
1508
- :instances_set => [] }
1509
-
1510
- elsif (name == 'item') &&
1511
- # DescribeInstances property
1512
- ( @xmlpath=='DescribeInstancesResponse/reservationSet/item/instancesSet' ||
1513
- # RunInstances property
1514
- @xmlpath=='RunInstancesResponse/instancesSet' )
1515
- # the optional params (sometimes are missing and we dont want them to be nil)
1516
- @instance = { :aws_reason => '',
1517
- :dns_name => '',
1518
- :private_dns_name => '',
1519
- :ami_launch_index => '',
1520
- :ssh_key_name => '',
1521
- :aws_state => '',
1522
- :aws_product_codes => [],
1523
- :tags => {} }
1524
- end
1525
- end
1526
- def tagend(name)
1527
- case name
1528
- # reservation
1529
- when 'reservationId' then @reservation[:aws_reservation_id] = @text
1530
- when 'ownerId' then @reservation[:aws_owner] = @text
1531
- when 'groupId' then @reservation[:aws_groups] << @text
1532
- # instance
1533
- when 'instanceId' then @instance[:aws_instance_id] = @text
1534
- when 'imageId' then @instance[:aws_image_id] = @text
1535
- when 'dnsName' then @instance[:dns_name] = @text
1536
- when 'privateDnsName' then @instance[:private_dns_name] = @text
1537
- when 'reason' then @instance[:aws_reason] = @text
1538
- when 'keyName' then @instance[:ssh_key_name] = @text
1539
- when 'amiLaunchIndex' then @instance[:ami_launch_index] = @text
1540
- when 'code' then @instance[:aws_state_code] = @text
1541
- when 'name' then @instance[:aws_state] = @text
1542
- when 'productCode' then @instance[:aws_product_codes] << @text
1543
- when 'instanceType' then @instance[:aws_instance_type] = @text
1544
- when 'launchTime' then @instance[:aws_launch_time] = @text
1545
- when 'kernelId' then @instance[:aws_kernel_id] = @text
1546
- when 'ramdiskId' then @instance[:aws_ramdisk_id] = @text
1547
- when 'platform' then @instance[:aws_platform] = @text
1548
- when 'availabilityZone' then @instance[:aws_availability_zone] = @text
1549
- when 'privateIpAddress' then @instance[:aws_private_ip_address] = @text
1550
- when 'key' then @tag_key = @text
1551
- when 'value' then @tag_value = @text
1552
- when 'state'
1553
- if @xmlpath == 'DescribeInstancesResponse/reservationSet/item/instancesSet/item/monitoring' || # DescribeInstances property
1554
- @xmlpath == 'RunInstancesResponse/instancesSet/item/monitoring' # RunInstances property
1555
- @instance[:monitoring_state] = @text
1556
- end
1557
- when 'item'
1558
- if @xmlpath=='DescribeInstancesResponse/reservationSet/item/instancesSet/item/tagSet' # Tags
1559
- @instance[:tags][@tag_key] = @tag_value
1560
- elsif @xmlpath == 'DescribeInstancesResponse/reservationSet/item/instancesSet' || # DescribeInstances property
1561
- @xmlpath == 'RunInstancesResponse/instancesSet' # RunInstances property
1562
- @reservation[:instances_set] << @instance
1563
- elsif @xmlpath=='DescribeInstancesResponse/reservationSet' # DescribeInstances property
1564
- @result << @reservation
1565
- end
1566
- when 'RunInstancesResponse' then @result << @reservation # RunInstances property
1567
- end
1568
- end
1569
- def reset
1570
- @result = []
1571
- end
1572
- end
1573
-
1574
- class QEc2ConfirmProductInstanceParser < AwsParser #:nodoc:
1575
- def tagend(name)
1576
- @result = @text if name == 'ownerId'
1577
- end
1578
- end
1579
-
1580
- class QEc2MonitorInstancesParser < AwsParser #:nodoc:
1581
- def tagstart(name, attributes)
1582
- @instance = {} if name == 'item'
1583
- end
1584
- def tagend(name)
1585
- case name
1586
- when 'instanceId' then @instance[:aws_instance_id] = @text
1587
- when 'state' then @instance[:aws_monitoring_state] = @text
1588
- when 'item' then @result << @instance
1589
- end
1590
- end
1591
- def reset
1592
- @result = []
1593
- end
1594
- end
1595
-
1596
-
1597
- class QEc2TerminateInstancesParser < AwsParser #:nodoc:
1598
- def tagstart(name, attributes)
1599
- @instance = {} if name == 'item'
1600
- end
1601
- def tagend(name)
1602
- case name
1603
- when 'instanceId' then @instance[:aws_instance_id] = @text
1604
- when 'code'
1605
- if @xmlpath == 'TerminateInstancesResponse/instancesSet/item/shutdownState'
1606
- @instance[:aws_shutdown_state_code] = @text.to_i
1607
- else @instance[:aws_prev_state_code] = @text.to_i end
1608
- when 'name'
1609
- if @xmlpath == 'TerminateInstancesResponse/instancesSet/item/shutdownState'
1610
- @instance[:aws_shutdown_state] = @text
1611
- else @instance[:aws_prev_state] = @text end
1612
- when 'item' then @result << @instance
1613
- end
1614
- end
1615
- def reset
1616
- @result = []
1617
- end
1618
- end
1619
-
1620
- #-----------------------------------------------------------------
1621
- # PARSERS: Console
1622
- #-----------------------------------------------------------------
1623
-
1624
- class QEc2GetConsoleOutputParser < AwsParser #:nodoc:
1625
- def tagend(name)
1626
- case name
1627
- when 'instanceId' then @result[:aws_instance_id] = @text
1628
- when 'timestamp' then @result[:aws_timestamp] = @text
1629
- @result[:timestamp] = (Time.parse(@text)).utc
1630
- when 'output' then @result[:aws_output] = Base64.decode64(@text)
1631
- end
1632
- end
1633
- def reset
1634
- @result = {}
1635
- end
1636
- end
1637
-
1638
- #-----------------------------------------------------------------
1639
- # Instances: Wondows related part
1640
- #-----------------------------------------------------------------
1641
- class QEc2DescribeBundleTasksParser < AwsParser #:nodoc:
1642
- def tagstart(name, attributes)
1643
- @bundle = {} if name == 'item'
1644
- end
1645
- def tagend(name)
1646
- case name
1647
- # when 'requestId' then @bundle[:request_id] = @text
1648
- when 'instanceId' then @bundle[:aws_instance_id] = @text
1649
- when 'bundleId' then @bundle[:aws_id] = @text
1650
- when 'bucket' then @bundle[:s3_bucket] = @text
1651
- when 'prefix' then @bundle[:s3_prefix] = @text
1652
- when 'startTime' then @bundle[:aws_start_time] = @text
1653
- when 'updateTime' then @bundle[:aws_update_time] = @text
1654
- when 'state' then @bundle[:aws_state] = @text
1655
- when 'progress' then @bundle[:aws_progress] = @text
1656
- when 'code' then @bundle[:aws_error_code] = @text
1657
- when 'message' then @bundle[:aws_error_message] = @text
1658
- when 'item' then @result << @bundle
1659
- end
1660
- end
1661
- def reset
1662
- @result = []
1663
- end
1664
- end
1665
-
1666
- class QEc2BundleInstanceParser < AwsParser #:nodoc:
1667
- def tagend(name)
1668
- case name
1669
- # when 'requestId' then @result[:request_id] = @text
1670
- when 'instanceId' then @result[:aws_instance_id] = @text
1671
- when 'bundleId' then @result[:aws_id] = @text
1672
- when 'bucket' then @result[:s3_bucket] = @text
1673
- when 'prefix' then @result[:s3_prefix] = @text
1674
- when 'startTime' then @result[:aws_start_time] = @text
1675
- when 'updateTime' then @result[:aws_update_time] = @text
1676
- when 'state' then @result[:aws_state] = @text
1677
- when 'progress' then @result[:aws_progress] = @text
1678
- when 'code' then @result[:aws_error_code] = @text
1679
- when 'message' then @result[:aws_error_message] = @text
1680
- end
1681
- end
1682
- def reset
1683
- @result = {}
1684
- end
1685
- end
1686
-
1687
- #-----------------------------------------------------------------
1688
- # PARSERS: Elastic IPs
1689
- #-----------------------------------------------------------------
1690
-
1691
- class QEc2AllocateAddressParser < AwsParser #:nodoc:
1692
- def tagend(name)
1693
- @result = @text if name == 'publicIp'
1694
- end
1695
- end
1696
-
1697
- class QEc2DescribeAddressesParser < AwsParser #:nodoc:
1698
- def tagstart(name, attributes)
1699
- @address = {} if name == 'item'
1700
- end
1701
- def tagend(name)
1702
- case name
1703
- when 'instanceId' then @address[:instance_id] = @text.blank? ? nil : @text
1704
- when 'publicIp' then @address[:public_ip] = @text
1705
- when 'item' then @result << @address
1706
- end
1707
- end
1708
- def reset
1709
- @result = []
1710
- end
1711
- end
1712
-
1713
- #-----------------------------------------------------------------
1714
- # PARSERS: AvailabilityZones
1715
- #-----------------------------------------------------------------
1716
-
1717
- class QEc2DescribeAvailabilityZonesParser < AwsParser #:nodoc:
1718
- def tagstart(name, attributes)
1719
- @zone = {} if name == 'item'
1720
- end
1721
- def tagend(name)
1722
- case name
1723
- when 'regionName' then @zone[:region_name] = @text
1724
- when 'zoneName' then @zone[:zone_name] = @text
1725
- when 'zoneState' then @zone[:zone_state] = @text
1726
- when 'item' then @result << @zone
1727
- end
1728
- end
1729
- def reset
1730
- @result = []
1731
- end
1732
- end
1733
-
1734
- #-----------------------------------------------------------------
1735
- # PARSERS: Regions
1736
- #-----------------------------------------------------------------
1737
-
1738
- class QEc2DescribeRegionsParser < AwsParser #:nodoc:
1739
- def tagend(name)
1740
- @result << @text if name == 'regionName'
1741
- end
1742
- def reset
1743
- @result = []
1744
- end
1745
- end
1746
-
1747
- #-----------------------------------------------------------------
1748
- # PARSERS: EBS - Volumes
1749
- #-----------------------------------------------------------------
1750
-
1751
- class QEc2CreateVolumeParser < AwsParser #:nodoc:
1752
- def tagend(name)
1753
- case name
1754
- when 'volumeId' then @result[:aws_id] = @text
1755
- when 'status' then @result[:aws_status] = @text
1756
- when 'createTime' then @result[:aws_created_at] = Time.parse(@text)
1757
- when 'size' then @result[:aws_size] = @text.to_i ###
1758
- when 'snapshotId' then @result[:snapshot_id] = @text.blank? ? nil : @text ###
1759
- when 'availabilityZone' then @result[:zone] = @text ###
1760
- end
1761
- end
1762
- def reset
1763
- @result = {}
1764
- end
1765
- end
1766
-
1767
- class QEc2AttachAndDetachVolumeParser < AwsParser #:nodoc:
1768
- def tagend(name)
1769
- case name
1770
- when 'volumeId' then @result[:aws_id] = @text
1771
- when 'instanceId' then @result[:aws_instance_id] = @text
1772
- when 'device' then @result[:aws_device] = @text
1773
- when 'status' then @result[:aws_attachment_status] = @text
1774
- when 'attachTime' then @result[:aws_attached_at] = Time.parse(@text)
1775
- end
1776
- end
1777
- def reset
1778
- @result = {}
1779
- end
1780
- end
1781
-
1782
- class QEc2DescribeVolumesParser < AwsParser #:nodoc:
1783
- def tagstart(name, attributes)
1784
- case name
1785
- when 'item'
1786
- case @xmlpath
1787
- when 'DescribeVolumesResponse/volumeSet' then @volume = {}
1788
- end
1789
- end
1790
- end
1791
- def tagend(name)
1792
- case name
1793
- when 'volumeId'
1794
- case @xmlpath
1795
- when 'DescribeVolumesResponse/volumeSet/item' then @volume[:aws_id] = @text
1796
- end
1797
- when 'status'
1798
- case @xmlpath
1799
- when 'DescribeVolumesResponse/volumeSet/item' then @volume[:aws_status] = @text
1800
- when 'DescribeVolumesResponse/volumeSet/item/attachmentSet/item' then @volume[:aws_attachment_status] = @text
1801
- end
1802
- when 'size' then @volume[:aws_size] = @text.to_i
1803
- when 'createTime' then @volume[:aws_created_at] = Time.parse(@text)
1804
- when 'instanceId' then @volume[:aws_instance_id] = @text
1805
- when 'device' then @volume[:aws_device] = @text
1806
- when 'attachTime' then @volume[:aws_attached_at] = Time.parse(@text)
1807
- when 'snapshotId' then @volume[:snapshot_id] = @text.blank? ? nil : @text
1808
- when 'availabilityZone' then @volume[:zone] = @text
1809
- when 'item'
1810
- case @xmlpath
1811
- when 'DescribeVolumesResponse/volumeSet' then @result << @volume
1812
- end
1813
- end
1814
- end
1815
- def reset
1816
- @result = []
1817
- end
1818
- end
1819
-
1820
- #-----------------------------------------------------------------
1821
- # PARSERS: EBS - Snapshots
1822
- #-----------------------------------------------------------------
1823
-
1824
- class QEc2DescribeSnapshotsParser < AwsParser #:nodoc:
1825
- def tagstart(name, attributes)
1826
- @snapshot = {} if name == 'item'
1827
- end
1828
- def tagend(name)
1829
- case name
1830
- when 'volumeId' then @snapshot[:aws_volume_id] = @text
1831
- when 'snapshotId' then @snapshot[:aws_id] = @text
1832
- when 'status' then @snapshot[:aws_status] = @text
1833
- when 'startTime' then @snapshot[:aws_started_at] = Time.parse(@text)
1834
- when 'progress' then @snapshot[:aws_progress] = @text
1835
- when 'item' then @result << @snapshot
1836
- end
1837
- end
1838
- def reset
1839
- @result = []
1840
- end
1841
- end
1842
-
1843
- class QEc2CreateSnapshotParser < AwsParser #:nodoc:
1844
- def tagend(name)
1845
- case name
1846
- when 'volumeId' then @result[:aws_volume_id] = @text
1847
- when 'snapshotId' then @result[:aws_id] = @text
1848
- when 'status' then @result[:aws_status] = @text
1849
- when 'startTime' then @result[:aws_started_at] = Time.parse(@text)
1850
- when 'progress' then @result[:aws_progress] = @text
1851
- end
1852
- end
1853
- def reset
1854
- @result = {}
1855
- end
1856
- end
1857
-
1858
- #-----------------------------------------------------------------
1859
- # PARSERS: Tags
1860
- #-----------------------------------------------------------------
1861
-
1862
- class QEc2DescribeTagsParser < AwsParser #:nodoc:
1863
- def tagstart(name, attributes)
1864
- @tag = {} if name == 'item'
1865
- end
1866
- def tagend(name)
1867
- case name
1868
- when 'resourceId' then @tag[:aws_resource_id] = @text
1869
- when 'resourceType' then @tag[:aws_resource_type] = @text
1870
- when 'key' then @tag[:aws_key] = @text
1871
- when 'value' then @tag[:aws_value] = @text
1872
- when 'item' then @result << @tag
1873
- end
1874
- end
1875
- def reset
1876
- @result = []
1877
- end
1878
- end
1879
-
1880
- end
1881
-
1882
- end
1883
-
1884
-