lib/ec2/right_ec2.rb in redaranj-right_aws-1.10.5 vs lib/ec2/right_ec2.rb in redaranj-right_aws-1.11

- old
+ new

@@ -1,7 +1,7 @@ # -# Copyright (c) 2007-2008 RightScale Inc +# Copyright (c) 2007-2009 RightScale Inc # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, @@ -66,11 +66,11 @@ class Ec2 < RightAwsBase include RightAwsBaseInterface # Amazon EC2 API version being used - API_VERSION = "2009-03-01" + API_VERSION = "2009-10-31" DEFAULT_HOST = "ec2.amazonaws.com" DEFAULT_PATH = '/' DEFAULT_PROTOCOL = 'https' DEFAULT_PORT = 443 @@ -79,11 +79,11 @@ DNS_ADDRESSING_SET = ['public','direct'] # Amazon EC2 Instance Types : http://www.amazon.com/b?ie=UTF8&node=370375011 # Default EC2 instance type (platform) DEFAULT_INSTANCE_TYPE = 'm1.small' - INSTANCE_TYPES = ['m1.small','c1.medium','m1.large','m1.xlarge','c1.xlarge'] + INSTANCE_TYPES = ['m1.small','c1.medium','m1.large','m1.xlarge','c1.xlarge', 'm2.2xlarge', 'm2.4xlarge'] @@bench = AwsBenchmarkingBlock.new def self.bench_xml @@bench.xml end @@ -134,624 +134,10 @@ def request_info(request, parser) #:nodoc: request_info_impl(:ec2_connection, @@bench, request, parser) end #----------------------------------------------------------------- - # Images - #----------------------------------------------------------------- - - # params: - # { 'ImageId' => ['id1', ..., 'idN'], - # 'Owner' => ['self', ..., 'userN'], - # 'ExecutableBy' => ['self', 'all', ..., 'userN'] - # } - def ec2_describe_images(params={}, image_type=nil, cache_for=nil) #:nodoc: - request_hash = {} - params.each do |list_by, list| - request_hash.merge! amazonize_list(list_by, list.to_a) - end - request_hash['ImageType'] = image_type if image_type - link = generate_request("DescribeImages", request_hash) - request_cache_or_info cache_for, link, QEc2DescribeImagesParser, @@bench, cache_for - rescue Exception - on_exception - end - - # Retrieve a list of images. Returns array of hashes describing the images or an exception: - # +image_type+ = 'machine' || 'kernel' || 'ramdisk' - # - # ec2.describe_images #=> - # [{:aws_owner => "522821470517", - # :aws_id => "ami-e4b6538d", - # :aws_state => "available", - # :aws_location => "marcins_cool_public_images/ubuntu-6.10.manifest.xml", - # :aws_is_public => true, - # :aws_architecture => "i386", - # :aws_image_type => "machine"}, - # {...}, - # {...} ] - # - # If +list+ param is set, then retrieve information about the listed images only: - # - # ec2.describe_images(['ami-e4b6538d']) #=> - # [{:aws_owner => "522821470517", - # :aws_id => "ami-e4b6538d", - # :aws_state => "available", - # :aws_location => "marcins_cool_public_images/ubuntu-6.10.manifest.xml", - # :aws_is_public => true, - # :aws_architecture => "i386", - # :aws_image_type => "machine"}] - # - def describe_images(list=[], image_type=nil) - list = list.to_a - cache_for = list.empty? && !image_type ? :describe_images : nil - ec2_describe_images({ 'ImageId' => list }, image_type, cache_for) - end - - # - # Example: - # - # ec2.describe_images_by_owner('522821470517') - # ec2.describe_images_by_owner('self') - # - def describe_images_by_owner(list=['self'], image_type=nil) - list = list.to_a - cache_for = list==['self'] && !image_type ? :describe_images_by_owner : nil - ec2_describe_images({ 'Owner' => list }, image_type, cache_for) - end - - # - # Example: - # - # ec2.describe_images_by_executable_by('522821470517') - # ec2.describe_images_by_executable_by('self') - # ec2.describe_images_by_executable_by('all') - # - def describe_images_by_executable_by(list=['self'], image_type=nil) - list = list.to_a - cache_for = list==['self'] && !image_type ? :describe_images_by_executable_by : nil - ec2_describe_images({ 'ExecutableBy' => list }, image_type, cache_for) - end - - - # Register new image at Amazon. - # Returns new image id or an exception. - # - # ec2.register_image('bucket/key/manifest') #=> 'ami-e444444d' - # - def register_image(image_location) - link = generate_request("RegisterImage", - 'ImageLocation' => image_location.to_s) - request_info(link, QEc2RegisterImageParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Deregister image at Amazon. Returns +true+ or an exception. - # - # ec2.deregister_image('ami-e444444d') #=> true - # - def deregister_image(image_id) - link = generate_request("DeregisterImage", - 'ImageId' => image_id.to_s) - request_info(link, RightBoolResponseParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - - # Describe image attributes. Currently 'launchPermission', 'productCodes', 'kernel', 'ramdisk' and 'blockDeviceMapping' are supported. - # - # ec2.describe_image_attribute('ami-e444444d') #=> {:groups=>["all"], :users=>["000000000777"]} - # - def describe_image_attribute(image_id, attribute='launchPermission') - link = generate_request("DescribeImageAttribute", - 'ImageId' => image_id, - 'Attribute' => attribute) - request_info(link, QEc2DescribeImageAttributeParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Reset image attribute. Currently, only 'launchPermission' is supported. Returns +true+ or an exception. - # - # ec2.reset_image_attribute('ami-e444444d') #=> true - # - def reset_image_attribute(image_id, attribute='launchPermission') - link = generate_request("ResetImageAttribute", - 'ImageId' => image_id, - 'Attribute' => attribute) - request_info(link, RightBoolResponseParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Modify an image's attributes. It is recommended that you use - # modify_image_launch_perm_add_users, modify_image_launch_perm_remove_users, etc. - # instead of modify_image_attribute because the signature of - # modify_image_attribute may change with EC2 service changes. - # - # attribute : currently, only 'launchPermission' is supported. - # operation_type : currently, only 'add' & 'remove' are supported. - # vars: - # :user_group : currently, only 'all' is supported. - # :user_id - # :product_code - def modify_image_attribute(image_id, attribute, operation_type = nil, vars = {}) - params = {'ImageId' => image_id, - 'Attribute' => attribute} - params['OperationType'] = operation_type if operation_type - params.update(amazonize_list('UserId', vars[:user_id].to_a)) if vars[:user_id] - params.update(amazonize_list('UserGroup', vars[:user_group].to_a)) if vars[:user_group] - params.update(amazonize_list('ProductCode', vars[:product_code])) if vars[:product_code] - link = generate_request("ModifyImageAttribute", params) - request_info(link, RightBoolResponseParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Grant image launch permissions to users. - # Parameter +userId+ is a list of user AWS account ids. - # Returns +true+ or an exception. - # - # ec2.modify_image_launch_perm_add_users('ami-e444444d',['000000000777','000000000778']) #=> true - def modify_image_launch_perm_add_users(image_id, user_id=[]) - modify_image_attribute(image_id, 'launchPermission', 'add', :user_id => user_id.to_a) - end - - # Revokes image launch permissions for users. +userId+ is a list of users AWS accounts ids. Returns +true+ or an exception. - # - # ec2.modify_image_launch_perm_remove_users('ami-e444444d',['000000000777','000000000778']) #=> true - # - def modify_image_launch_perm_remove_users(image_id, user_id=[]) - modify_image_attribute(image_id, 'launchPermission', 'remove', :user_id => user_id.to_a) - end - - # Add image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions). - # Returns +true+ or an exception. - # - # ec2.modify_image_launch_perm_add_groups('ami-e444444d') #=> true - # - def modify_image_launch_perm_add_groups(image_id, user_group=['all']) - modify_image_attribute(image_id, 'launchPermission', 'add', :user_group => user_group.to_a) - end - - # Remove image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions). - # - # ec2.modify_image_launch_perm_remove_groups('ami-e444444d') #=> true - # - def modify_image_launch_perm_remove_groups(image_id, user_group=['all']) - modify_image_attribute(image_id, 'launchPermission', 'remove', :user_group => user_group.to_a) - end - - # Add product code to image - # - # ec2.modify_image_product_code('ami-e444444d','0ABCDEF') #=> true - # - def modify_image_product_code(image_id, product_code=[]) - modify_image_attribute(image_id, 'productCodes', nil, :product_code => product_code.to_a) - end - - #----------------------------------------------------------------- - # Instances - #----------------------------------------------------------------- - - def get_desc_instances(instances) # :nodoc: - result = [] - instances.each do |reservation| - reservation[:instances_set].each do |instance| - # Parse and remove timestamp from the reason string. The timestamp is of - # the request, not when EC2 took action, thus confusing & useless... - instance[:aws_reason] = instance[:aws_reason].sub(/\(\d[^)]*GMT\) */, '') - instance[:aws_owner] = reservation[:aws_owner] - instance[:aws_reservation_id] = reservation[:aws_reservation_id] - instance[:aws_groups] = reservation[:aws_groups] - result << instance - end - end - result - rescue Exception - on_exception - end - - # Retrieve information about EC2 instances. If +list+ is omitted then returns the - # list of all instances. - # - # ec2.describe_instances #=> - # [{:aws_image_id => "ami-e444444d", - # :aws_reason => "", - # :aws_state_code => "16", - # :aws_owner => "000000000888", - # :aws_instance_id => "i-123f1234", - # :aws_reservation_id => "r-aabbccdd", - # :aws_state => "running", - # :dns_name => "domU-12-34-67-89-01-C9.usma2.compute.amazonaws.com", - # :ssh_key_name => "staging", - # :aws_groups => ["default"], - # :private_dns_name => "domU-12-34-67-89-01-C9.usma2.compute.amazonaws.com", - # :aws_instance_type => "m1.small", - # :aws_launch_time => "2008-1-1T00:00:00.000Z"}, - # :aws_availability_zone => "us-east-1b", - # :aws_kernel_id => "aki-ba3adfd3", - # :aws_ramdisk_id => "ari-badbad00", - # ..., {...}] - # - def describe_instances(list=[]) - link = generate_request("DescribeInstances", amazonize_list('InstanceId',list.to_a)) - request_cache_or_info(:describe_instances, link, QEc2DescribeInstancesParser, @@bench, list.blank?) do |parser| - get_desc_instances(parser.result) - end - rescue Exception - on_exception - end - - # Return the product code attached to instance or +nil+ otherwise. - # - # ec2.confirm_product_instance('ami-e444444d','12345678') #=> nil - # ec2.confirm_product_instance('ami-e444444d','00001111') #=> "000000000888" - # - def confirm_product_instance(instance, product_code) - link = generate_request("ConfirmProductInstance", { 'ProductCode' => product_code, - 'InstanceId' => instance }) - request_info(link, QEc2ConfirmProductInstanceParser.new(:logger => @logger)) - end - - # Launch new EC2 instances. Returns a list of launched instances or an exception. - # - # ec2.run_instances('ami-e444444d',1,1,['my_awesome_group'],'my_awesome_key', 'Woohoo!!!', 'public') #=> - # [{:aws_image_id => "ami-e444444d", - # :aws_reason => "", - # :aws_state_code => "0", - # :aws_owner => "000000000888", - # :aws_instance_id => "i-123f1234", - # :aws_reservation_id => "r-aabbccdd", - # :aws_state => "pending", - # :dns_name => "", - # :ssh_key_name => "my_awesome_key", - # :aws_groups => ["my_awesome_group"], - # :private_dns_name => "", - # :aws_instance_type => "m1.small", - # :aws_launch_time => "2008-1-1T00:00:00.000Z" - # :aws_ramdisk_id => "ari-8605e0ef" - # :aws_kernel_id => "aki-9905e0f0", - # :ami_launch_index => "0", - # :aws_availability_zone => "us-east-1b" - # }] - # - def run_instances(image_id, min_count, max_count, group_ids, key_name, user_data='', - addressing_type = nil, instance_type = nil, - kernel_id = nil, ramdisk_id = nil, availability_zone = nil, - block_device_mappings = nil) - launch_instances(image_id, { :min_count => min_count, - :max_count => max_count, - :user_data => user_data, - :group_ids => group_ids, - :key_name => key_name, - :instance_type => instance_type, - :addressing_type => addressing_type, - :kernel_id => kernel_id, - :ramdisk_id => ramdisk_id, - :availability_zone => availability_zone, - :block_device_mappings => block_device_mappings - }) - end - - - # Launch new EC2 instances. Returns a list of launched instances or an exception. - # - # +lparams+ keys (default values in parenthesis): - # :min_count fixnum, (1) - # :max_count fixnum, (1) - # :group_ids array or string ([] == 'default') - # :instance_type string (DEFAULT_INSTACE_TYPE) - # :addressing_type string (DEFAULT_ADDRESSING_TYPE - # :key_name string - # :kernel_id string - # :ramdisk_id string - # :availability_zone string - # :block_device_mappings string - # :user_data string - # - # ec2.launch_instances('ami-e444444d', :group_ids => 'my_awesome_group', - # :user_data => "Woohoo!!!", - # :addressing_type => "public", - # :key_name => "my_awesome_key", - # :availability_zone => "us-east-1c") #=> - # [{:aws_image_id => "ami-e444444d", - # :aws_reason => "", - # :aws_state_code => "0", - # :aws_owner => "000000000888", - # :aws_instance_id => "i-123f1234", - # :aws_reservation_id => "r-aabbccdd", - # :aws_state => "pending", - # :dns_name => "", - # :ssh_key_name => "my_awesome_key", - # :aws_groups => ["my_awesome_group"], - # :private_dns_name => "", - # :aws_instance_type => "m1.small", - # :aws_launch_time => "2008-1-1T00:00:00.000Z", - # :aws_ramdisk_id => "ari-8605e0ef" - # :aws_kernel_id => "aki-9905e0f0", - # :ami_launch_index => "0", - # :aws_availability_zone => "us-east-1c" - # }] - # - def launch_instances(image_id, lparams={}) - @logger.info("Launching instance of image #{image_id} for #{@aws_access_key_id}, " + - "key: #{lparams[:key_name]}, groups: #{(lparams[:group_ids]).to_a.join(',')}") - # careful: keyName and securityGroups may be nil - params = amazonize_list('SecurityGroup', lparams[:group_ids].to_a) - params.update( {'ImageId' => image_id, - 'MinCount' => (lparams[:min_count] || 1).to_s, - 'MaxCount' => (lparams[:max_count] || 1).to_s, - 'AddressingType' => lparams[:addressing_type] || DEFAULT_ADDRESSING_TYPE, - 'InstanceType' => lparams[:instance_type] || DEFAULT_INSTANCE_TYPE }) - # optional params - params['KeyName'] = lparams[:key_name] unless lparams[:key_name].blank? - params['KernelId'] = lparams[:kernel_id] unless lparams[:kernel_id].blank? - params['RamdiskId'] = lparams[:ramdisk_id] unless lparams[:ramdisk_id].blank? - params['Placement.AvailabilityZone'] = lparams[:availability_zone] unless lparams[:availability_zone].blank? - params['BlockDeviceMappings'] = lparams[:block_device_mappings] unless lparams[:block_device_mappings].blank? - unless lparams[:user_data].blank? - lparams[:user_data].strip! - # Do not use CGI::escape(encode64(...)) as it is done in Amazons EC2 library. - # Amazon 169.254.169.254 does not like escaped symbols! - # And it doesn't like "\n" inside of encoded string! Grrr.... - # Otherwise, some of UserData symbols will be lost... - params['UserData'] = Base64.encode64(lparams[:user_data]).delete("\n") unless lparams[:user_data].blank? - end - link = generate_request("RunInstances", params) - #debugger - instances = request_info(link, QEc2DescribeInstancesParser.new(:logger => @logger)) - get_desc_instances(instances) - rescue Exception - on_exception - end - - # Terminates EC2 instances. Returns a list of termination params or an exception. - # - # ec2.terminate_instances(['i-f222222d','i-f222222e']) #=> - # [{:aws_shutdown_state => "shutting-down", - # :aws_instance_id => "i-f222222d", - # :aws_shutdown_state_code => 32, - # :aws_prev_state => "running", - # :aws_prev_state_code => 16}, - # {:aws_shutdown_state => "shutting-down", - # :aws_instance_id => "i-f222222e", - # :aws_shutdown_state_code => 32, - # :aws_prev_state => "running", - # :aws_prev_state_code => 16}] - # - def terminate_instances(list=[]) - link = generate_request("TerminateInstances", amazonize_list('InstanceId',list.to_a)) - request_info(link, QEc2TerminateInstancesParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Retreive EC2 instance OS logs. Returns a hash of data or an exception. - # - # ec2.get_console_output('i-f222222d') => - # {:aws_instance_id => 'i-f222222d', - # :aws_timestamp => "2007-05-23T14:36:07.000-07:00", - # :timestamp => Wed May 23 21:36:07 UTC 2007, # Time instance - # :aws_output => "Linux version 2.6.16-xenU (builder@patchbat.amazonsa) (gcc version 4.0.1 20050727 ..." - def get_console_output(instance_id) - link = generate_request("GetConsoleOutput", { 'InstanceId.1' => instance_id }) - request_info(link, QEc2GetConsoleOutputParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Reboot an EC2 instance. Returns +true+ or an exception. - # - # ec2.reboot_instances(['i-f222222d','i-f222222e']) #=> true - # - def reboot_instances(list) - link = generate_request("RebootInstances", amazonize_list('InstanceId', list.to_a)) - request_info(link, RightBoolResponseParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - #----------------------------------------------------------------- - # Instances: Windows addons - #----------------------------------------------------------------- - - # Get initial Windows Server setup password from an instance console output. - # - # my_awesome_key = ec2.create_key_pair('my_awesome_key') #=> - # {:aws_key_name => "my_awesome_key", - # :aws_fingerprint => "01:02:03:f4:25:e6:97:e8:9b:02:1a:26:32:4e:58:6b:7a:8c:9f:03", - # :aws_material => "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAK...Q8MDrCbuQ=\n-----END RSA PRIVATE KEY-----"} - # - # my_awesome_instance = ec2.run_instances('ami-a000000a',1,1,['my_awesome_group'],'my_awesome_key', 'WindowsInstance!!!') #=> - # [{:aws_image_id => "ami-a000000a", - # :aws_instance_id => "i-12345678", - # ... - # :aws_availability_zone => "us-east-1b" - # }] - # - # # wait until instance enters 'operational' state and get it's initial password - # - # puts ec2.get_initial_password(my_awesome_instance[:aws_instance_id], my_awesome_key[:aws_material]) #=> "MhjWcgZuY6" - # - def get_initial_password(instance_id, private_key) - console_output = get_console_output(instance_id) - crypted_password = console_output[:aws_output][%r{<Password>(.+)</Password>}m] && $1 - unless crypted_password - raise AwsError.new("Initial password was not found in console output for #{instance_id}") - else - OpenSSL::PKey::RSA.new(private_key).private_decrypt(Base64.decode64(crypted_password)) - end - rescue Exception - on_exception - end - - # Bundle a Windows image. - # Internally, it queues the bundling task and shuts down the instance. - # It then takes a snapshot of the Windows volume bundles it, and uploads it to - # S3. After bundling completes, Rightaws::Ec2#register_image may be used to - # register the new Windows AMI for subsequent launches. - # - # ec2.bundle_instance('i-e3e24e8a', 'my-awesome-bucket', 'my-win-image-1') #=> - # [{:aws_update_time => "2008-10-16T13:58:25.000Z", - # :s3_bucket => "kd-win-1", - # :s3_prefix => "win2pr", - # :aws_state => "pending", - # :aws_id => "bun-26a7424f", - # :aws_instance_id => "i-878a25ee", - # :aws_start_time => "2008-10-16T13:58:02.000Z"}] - # - def bundle_instance(instance_id, s3_bucket, s3_prefix, - s3_owner_aws_access_key_id=nil, s3_owner_aws_secret_access_key=nil, - s3_expires = S3Interface::DEFAULT_EXPIRES_AFTER, - s3_upload_policy='ec2-bundle-read') - # S3 access and signatures - s3_owner_aws_access_key_id ||= @aws_access_key_id - s3_owner_aws_secret_access_key ||= @aws_secret_access_key - s3_expires = Time.now.utc + s3_expires if s3_expires.is_a?(Fixnum) && (s3_expires < S3Interface::ONE_YEAR_IN_SECONDS) - # policy - policy = { 'expiration' => s3_expires.strftime('%Y-%m-%dT%H:%M:%SZ'), - 'conditions' => [ { 'bucket' => s3_bucket }, - { 'acl' => s3_upload_policy }, - [ 'starts-with', '$key', s3_prefix ] ] }.to_json - policy64 = Base64.encode64(policy).gsub("\n","") - signed_policy64 = AwsUtils.sign(s3_owner_aws_secret_access_key, policy64) - # fill request params - params = { 'InstanceId' => instance_id, - 'Storage.S3.AWSAccessKeyId' => s3_owner_aws_access_key_id, - 'Storage.S3.UploadPolicy' => policy64, - 'Storage.S3.UploadPolicySignature' => signed_policy64, - 'Storage.S3.Bucket' => s3_bucket, - 'Storage.S3.Prefix' => s3_prefix, - } - link = generate_request("BundleInstance", params) - request_info(link, QEc2BundleInstanceParser.new) - rescue Exception - on_exception - end - - # Describe the status of the Windows AMI bundlings. - # If +list+ is omitted the returns the whole list of tasks. - # - # ec2.describe_bundle_tasks(['bun-4fa74226']) #=> - # [{:s3_bucket => "my-awesome-bucket" - # :aws_id => "bun-0fa70206", - # :s3_prefix => "win1pr", - # :aws_start_time => "2008-10-14T16:27:57.000Z", - # :aws_update_time => "2008-10-14T16:37:10.000Z", - # :aws_error_code => "Client.S3Error", - # :aws_error_message => - # "AccessDenied(403)- Invalid according to Policy: Policy Condition failed: [\"eq\", \"$acl\", \"aws-exec-read\"]", - # :aws_state => "failed", - # :aws_instance_id => "i-e3e24e8a"}] - # - def describe_bundle_tasks(list=[]) - link = generate_request("DescribeBundleTasks", amazonize_list('BundleId', list.to_a)) - request_info(link, QEc2DescribeBundleTasksParser.new) - rescue Exception - on_exception - end - - # Cancel an inā€progress or pending bundle task by id. - # - # ec2.cancel_bundle_task('bun-73a7421a') #=> - # [{:s3_bucket => "my-awesome-bucket" - # :aws_id => "bun-0fa70206", - # :s3_prefix => "win02", - # :aws_start_time => "2008-10-14T13:00:29.000Z", - # :aws_error_message => "User has requested bundling operation cancellation", - # :aws_state => "failed", - # :aws_update_time => "2008-10-14T13:01:31.000Z", - # :aws_error_code => "Client.Cancelled", - # :aws_instance_id => "i-e3e24e8a"} - # - def cancel_bundle_task(bundle_id) - link = generate_request("CancelBundleTask", { 'BundleId' => bundle_id }) - request_info(link, QEc2BundleInstanceParser.new) - rescue Exception - on_exception - end - - #----------------------------------------------------------------- - # Reserved instances - #----------------------------------------------------------------- - - # Retrieve reserved instances list. - # Returns a list of Reserved Instances. - # - # ec2.describe_reserved_instances #=> - # [{:aws_id=>"1ba8e2e3-1c40-434c-a741-5ff16a4c542e", - # :aws_duration=>31536000, - # :aws_instance_type=>"m1.small", - # :aws_usage_price=>0.03, - # :aws_availability_zone=>"us-east-1b", - # :aws_state=>"payment-pending", - # :aws_product_description=>"Test", - # :aws_fixed_price=>325.0, - # :aws_instance_count=>1}] - # - def describe_reserved_instances(list=[]) - link = generate_request("DescribeReservedInstances", amazonize_list('ReservedInstancesId',list.to_a)) - request_cache_or_info(:describe_reserved_instances, link, QEc2DescribeReservedInstancesParser, @@bench, list.blank?) - rescue Exception - on_exception - end - - # Retrieve reserved instances offerings. - # Returns a set of available offerings. - # - # Optional params: - # :aws_ids => String || Array - # :aws_instance_type => String - # :aws_availability_zone => String - # :aws_product_description => String - # - # ec2.describe_reserved_instances_offerings #=> - # [{:aws_instance_type=>"c1.medium", - # :aws_availability_zone=>"us-east-1c", - # :aws_duration=>94608000, - # :aws_product_description=>"Linux/UNIX", - # :aws_id=>"e5a2ff3b-f6eb-4b4e-83f8-b879d7060257", - # :aws_usage_price=>0.06, - # :aws_fixed_price=>1000.0}, - # ... - # {:aws_instance_type=>"m1.xlarge", - # :aws_availability_zone=>"us-east-1a", - # :aws_duration=>31536000, - # :aws_product_description=>"Linux/UNIX", - # :aws_id=>"c48ab04c-63ab-4cd6-b8f5-978a29eb9bcc", - # :aws_usage_price=>0.24, - # :aws_fixed_price=>2600.0}] - # - def describe_reserved_instances_offerings(params={}) - rparams = {} - rparams.update(amazonize_list('ReservedInstancesOfferingId', params[:aws_ids].to_a)) if params[:aws_ids] - rparams['InstanceType'] = params[:aws_instance_type] if params[:aws_instance_type] - rparams['AvailabilityZone'] = params[:aws_availability_zone] if params[:aws_availability_zone] - rparams['ProductDescription'] = params[:aws_product_description] if params[:aws_product_description] - link = generate_request("DescribeReservedInstancesOfferings", rparams) - request_cache_or_info(:describe_reserved_instances_offerings, link, QEc2DescribeReservedInstancesOfferingsParser, @@bench, params.blank?) - rescue Exception - on_exception - end - - # Purchase a Reserved Instance. - # Returns ReservedInstancesId value. - # - # ec2.purchase_reserved_instances_offering('e5a2ff3b-f6eb-4b4e-83f8-b879d7060257', 3) # => '4b2293b4-5813-4cc8-9ce3-1957fc1dcfc8' - # - def purchase_reserved_instances_offering(reserved_instances_offering_id, instance_count=1) - link = generate_request("PurchaseReservedInstancesOffering", { 'ReservedInstancesOfferingId' => reserved_instances_offering_id, - 'InstanceCount' => instance_count }) - request_info(link, QEc2PurchaseReservedInstancesOfferingParser.new) - rescue Exception - on_exception - end - - #----------------------------------------------------------------- # Security groups #----------------------------------------------------------------- # Retrieve Security Group information. If +list+ is omitted the returns the whole list of groups. # @@ -1051,215 +437,11 @@ request_cache_or_info :describe_regions, link, QEc2DescribeRegionsParser, @@bench, list.blank? rescue Exception on_exception end - #----------------------------------------------------------------- - # EBS: Volumes - #----------------------------------------------------------------- - - # Describe all EBS volumes. - # - # ec2.describe_volumes #=> - # [{:aws_size => 94, - # :aws_device => "/dev/sdc", - # :aws_attachment_status => "attached", - # :zone => "merlot", - # :snapshot_id => nil, - # :aws_attached_at => Wed Jun 18 08:19:28 UTC 2008, - # :aws_status => "in-use", - # :aws_id => "vol-60957009", - # :aws_created_at => Wed Jun 18 08:19:20s UTC 2008, - # :aws_instance_id => "i-c014c0a9"}, - # {:aws_size => 1, - # :zone => "merlot", - # :snapshot_id => nil, - # :aws_status => "available", - # :aws_id => "vol-58957031", - # :aws_created_at => Wed Jun 18 08:19:21 UTC 2008,}, ... ] - # - def describe_volumes(list=[]) - link = generate_request("DescribeVolumes", - amazonize_list('VolumeId',list.to_a)) - request_cache_or_info :describe_volumes, link, QEc2DescribeVolumesParser, @@bench, list.blank? - rescue Exception - on_exception - end - - # Create new EBS volume based on previously created snapshot. - # +Size+ in Gigabytes. - # - # ec2.create_volume('snap-000000', 10, zone) #=> - # {:snapshot_id => "snap-e21df98b", - # :aws_status => "creating", - # :aws_id => "vol-fc9f7a95", - # :zone => "merlot", - # :aws_created_at => Tue Jun 24 18:13:32 UTC 2008, - # :aws_size => 94} - # - def create_volume(snapshot_id, size, zone) - hash = { "Size" => size.to_s, - "AvailabilityZone" => zone.to_s } - # Get rig of empty snapshot: e8s guys do not like it - hash["SnapshotId"] = snapshot_id.to_s unless snapshot_id.blank? - link = generate_request("CreateVolume", hash ) - request_info(link, QEc2CreateVolumeParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Delete the specified EBS volume. - # This does not deletes any snapshots created from this volume. - # - # ec2.delete_volume('vol-b48a6fdd') #=> true - # - def delete_volume(volume_id) - link = generate_request("DeleteVolume", - "VolumeId" => volume_id.to_s) - request_info(link, RightBoolResponseParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Attach the specified EBS volume to a specified instance, exposing the - # volume using the specified device name. - # - # ec2.attach_volume('vol-898a6fe0', 'i-7c905415', '/dev/sdh') #=> - # { :aws_instance_id => "i-7c905415", - # :aws_device => "/dev/sdh", - # :aws_status => "attaching", - # :aws_attached_at => "2008-03-28T14:14:39.000Z", - # :aws_id => "vol-898a6fe0" } - # - def attach_volume(volume_id, instance_id, device) - link = generate_request("AttachVolume", - "VolumeId" => volume_id.to_s, - "InstanceId" => instance_id.to_s, - "Device" => device.to_s) - request_info(link, QEc2AttachAndDetachVolumeParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Detach the specified EBS volume from the instance to which it is attached. - # - # ec2.detach_volume('vol-898a6fe0') #=> - # { :aws_instance_id => "i-7c905415", - # :aws_device => "/dev/sdh", - # :aws_status => "detaching", - # :aws_attached_at => "2008-03-28T14:38:34.000Z", - # :aws_id => "vol-898a6fe0"} - # - def detach_volume(volume_id, instance_id=nil, device=nil, force=nil) - hash = { "VolumeId" => volume_id.to_s } - hash["InstanceId"] = instance_id.to_s unless instance_id.blank? - hash["Device"] = device.to_s unless device.blank? - hash["Force"] = 'true' if force - # - link = generate_request("DetachVolume", hash) - request_info(link, QEc2AttachAndDetachVolumeParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - - #----------------------------------------------------------------- - # EBS: Snapshots - #----------------------------------------------------------------- - - # Describe all EBS snapshots. - # - # ec2.describe_snapshots #=> - # [ { :aws_progress => "100%", - # :aws_status => "completed", - # :aws_id => "snap-72a5401b", - # :aws_volume_id => "vol-5582673c", - # :aws_started_at => "2008-02-23T02:50:48.000Z"}, - # { :aws_progress => "100%", - # :aws_status => "completed", - # :aws_id => "snap-75a5401c", - # :aws_volume_id => "vol-5582673c", - # :aws_started_at => "2008-02-23T16:23:19.000Z" },...] - # - def describe_snapshots(list=[]) - link = generate_request("DescribeSnapshots", - amazonize_list('SnapshotId',list.to_a)) - request_cache_or_info :describe_snapshots, link, QEc2DescribeSnapshotsParser, @@bench, list.blank? - rescue Exception - on_exception - end - - # Create a snapshot of specified volume. - # - # ec2.create_snapshot('vol-898a6fe0') #=> - # {:aws_volume_id => "vol-fd9f7a94", - # :aws_started_at => Tue Jun 24 18:40:40 UTC 2008, - # :aws_progress => "", - # :aws_status => "pending", - # :aws_id => "snap-d56783bc"} - # - def create_snapshot(volume_id) - link = generate_request("CreateSnapshot", - "VolumeId" => volume_id.to_s) - request_info(link, QEc2CreateSnapshotParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - # Create a snapshot of specified volume, but with the normal retry algorithms disabled. - # This method will return immediately upon error. The user can specify connect and read timeouts (in s) - # for the connection to AWS. If the user does not specify timeouts, try_create_snapshot uses the default values - # in Rightscale::HttpConnection. - # - # ec2.try_create_snapshot('vol-898a6fe0') #=> - # {:aws_volume_id => "vol-fd9f7a94", - # :aws_started_at => Tue Jun 24 18:40:40 UTC 2008, - # :aws_progress => "", - # :aws_status => "pending", - # :aws_id => "snap-d56783bc"} - # - def try_create_snapshot(volume_id, connect_timeout = nil, read_timeout = nil) - # For safety in the ensure block...we don't want to restore values - # if we never read them in the first place - orig_reiteration_time = nil - orig_http_params = nil - - orig_reiteration_time = RightAws::AWSErrorHandler::reiteration_time - RightAws::AWSErrorHandler::reiteration_time = 0 - - orig_http_params = Rightscale::HttpConnection::params() - new_http_params = orig_http_params.dup - new_http_params[:http_connection_retry_count] = 0 - new_http_params[:http_connection_open_timeout] = connect_timeout if !connect_timeout.nil? - new_http_params[:http_connection_read_timeout] = read_timeout if !read_timeout.nil? - Rightscale::HttpConnection::params = new_http_params - - link = generate_request("CreateSnapshot", - "VolumeId" => volume_id.to_s) - request_info(link, QEc2CreateSnapshotParser.new(:logger => @logger)) - - rescue Exception - on_exception - ensure - RightAws::AWSErrorHandler::reiteration_time = orig_reiteration_time if orig_reiteration_time - Rightscale::HttpConnection::params = orig_http_params if orig_http_params - end - - # Delete the specified snapshot. - # - # ec2.delete_snapshot('snap-55a5403c') #=> true - # - def delete_snapshot(snapshot_id) - link = generate_request("DeleteSnapshot", - "SnapshotId" => snapshot_id.to_s) - request_info(link, RightBoolResponseParser.new(:logger => @logger)) - rescue Exception - on_exception - end - - #----------------------------------------------------------------- # PARSERS: Boolean Response Parser #----------------------------------------------------------------- class RightBoolResponseParser < RightAWSParser #:nodoc: def tagend(name) @@ -1322,11 +504,10 @@ attr_accessor :groupDescription attr_accessor :ownerId attr_accessor :ipPermissions end - class QEc2DescribeSecurityGroupsParser < RightAWSParser #:nodoc: def tagstart(name, attributes) case name when 'item' if @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo' @@ -1370,300 +551,10 @@ @result = [] end end #----------------------------------------------------------------- - # PARSERS: Images - #----------------------------------------------------------------- - - class QEc2DescribeImagesParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - if name == 'item' && @xmlpath[%r{.*/imagesSet$}] - @image = {} - end - end - def tagend(name) - case name - when 'imageId' then @image[:aws_id] = @text - when 'imageLocation' then @image[:aws_location] = @text - when 'imageState' then @image[:aws_state] = @text - when 'imageOwnerId' then @image[:aws_owner] = @text - when 'isPublic' then @image[:aws_is_public]= @text == 'true' ? true : false - when 'productCode' then (@image[:aws_product_codes] ||= []) << @text - when 'architecture' then @image[:aws_architecture] = @text - when 'imageType' then @image[:aws_image_type] = @text - when 'kernelId' then @image[:aws_kernel_id] = @text - when 'ramdiskId' then @image[:aws_ramdisk_id] = @text - when 'item' then @result << @image if @xmlpath[%r{.*/imagesSet$}] - end - end - def reset - @result = [] - end - end - - class QEc2RegisterImageParser < RightAWSParser #:nodoc: - def tagend(name) - @result = @text if name == 'imageId' - end - end - - #----------------------------------------------------------------- - # PARSERS: Image Attribute - #----------------------------------------------------------------- - - class QEc2DescribeImageAttributeParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - case name - when 'launchPermission' - @result[:groups] = [] - @result[:users] = [] - when 'productCodes' - @result[:aws_product_codes] = [] - end - end - def tagend(name) - # right now only 'launchPermission' is supported by Amazon. - # But nobody know what will they xml later as attribute. That is why we - # check for 'group' and 'userId' inside of 'launchPermission/item' - case name - when 'imageId' then @result[:aws_id] = @text - when 'group' then @result[:groups] << @text if @xmlpath == 'DescribeImageAttributeResponse/launchPermission/item' - when 'userId' then @result[:users] << @text if @xmlpath == 'DescribeImageAttributeResponse/launchPermission/item' - when 'productCode' then @result[:aws_product_codes] << @text - when 'kernel' then @result[:aws_kernel] = @text - when 'ramdisk' then @result[:aws_ramdisk] = @text - when 'blockDeviceMapping' then @result[:block_device_mapping] = @text - end - end - def reset - @result = {} - end - end - - #----------------------------------------------------------------- - # PARSERS: Instances - #----------------------------------------------------------------- - - class QEc2DescribeInstancesParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - # DescribeInstances property - if (name == 'item' && @xmlpath == 'DescribeInstancesResponse/reservationSet') || - # RunInstances property - (name == 'RunInstancesResponse') - @reservation = { :aws_groups => [], - :instances_set => [] } - - elsif (name == 'item') && - # DescribeInstances property - ( @xmlpath=='DescribeInstancesResponse/reservationSet/item/instancesSet' || - # RunInstances property - @xmlpath=='RunInstancesResponse/instancesSet' ) - # the optional params (sometimes are missing and we dont want them to be nil) - @instance = { :aws_reason => '', - :dns_name => '', - :private_dns_name => '', - :ami_launch_index => '', - :ssh_key_name => '', - :aws_state => '', - :aws_product_codes => [] } - end - end - def tagend(name) - case name - # reservation - when 'reservationId' then @reservation[:aws_reservation_id] = @text - when 'ownerId' then @reservation[:aws_owner] = @text - when 'groupId' then @reservation[:aws_groups] << @text - # instance - when 'instanceId' then @instance[:aws_instance_id] = @text - when 'imageId' then @instance[:aws_image_id] = @text - when 'dnsName' then @instance[:dns_name] = @text - when 'privateDnsName' then @instance[:private_dns_name] = @text - when 'reason' then @instance[:aws_reason] = @text - when 'keyName' then @instance[:ssh_key_name] = @text - when 'amiLaunchIndex' then @instance[:ami_launch_index] = @text - when 'code' then @instance[:aws_state_code] = @text - when 'name' then @instance[:aws_state] = @text - when 'productCode' then @instance[:aws_product_codes] << @text - when 'instanceType' then @instance[:aws_instance_type] = @text - when 'launchTime' then @instance[:aws_launch_time] = @text - when 'kernelId' then @instance[:aws_kernel_id] = @text - when 'ramdiskId' then @instance[:aws_ramdisk_id] = @text - when 'platform' then @instance[:aws_platform] = @text - when 'availabilityZone' then @instance[:aws_availability_zone] = @text - when 'item' - if @xmlpath == 'DescribeInstancesResponse/reservationSet/item/instancesSet' || # DescribeInstances property - @xmlpath == 'RunInstancesResponse/instancesSet' # RunInstances property - @reservation[:instances_set] << @instance - elsif @xmlpath=='DescribeInstancesResponse/reservationSet' # DescribeInstances property - @result << @reservation - end - when 'RunInstancesResponse' then @result << @reservation # RunInstances property - end - end - def reset - @result = [] - end - end - - class QEc2ConfirmProductInstanceParser < RightAWSParser #:nodoc: - def tagend(name) - @result = @text if name == 'ownerId' - end - end - - class QEc2TerminateInstancesParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - @instance = {} if name == 'item' - end - def tagend(name) - case name - when 'instanceId' then @instance[:aws_instance_id] = @text - when 'code' - if @xmlpath == 'TerminateInstancesResponse/instancesSet/item/shutdownState' - @instance[:aws_shutdown_state_code] = @text.to_i - else @instance[:aws_prev_state_code] = @text.to_i end - when 'name' - if @xmlpath == 'TerminateInstancesResponse/instancesSet/item/shutdownState' - @instance[:aws_shutdown_state] = @text - else @instance[:aws_prev_state] = @text end - when 'item' then @result << @instance - end - end - def reset - @result = [] - end - end - - #----------------------------------------------------------------- - # PARSERS: ReservedInstances - #----------------------------------------------------------------- - - class QEc2DescribeReservedInstancesParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - @item = {} if name == 'item' - end - def tagend(name) - case name - when 'reservedInstancesId' then @item[:aws_id] = @text - when 'instanceType' then @item[:aws_instance_type] = @text - when 'availabilityZone' then @item[:aws_availability_zone] = @text - when 'duration' then @item[:aws_duration] = @text.to_i - when 'usagePrice' then @item[:aws_usage_price] = @text.to_f - when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f - when 'instanceCount' then @item[:aws_instance_count] = @text.to_i - when 'productDescription' then @item[:aws_product_description] = @text - when 'state' then @item[:aws_state] = @text - when 'item' then @result << @item - end - end - def reset - @result = [] - end - end - - class QEc2DescribeReservedInstancesOfferingsParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - @item = {} if name == 'item' - end - def tagend(name) - case name - when 'reservedInstancesOfferingId' then @item[:aws_id] = @text - when 'instanceType' then @item[:aws_instance_type] = @text - when 'availabilityZone' then @item[:aws_availability_zone] = @text - when 'duration' then @item[:aws_duration] = @text.to_i - when 'usagePrice' then @item[:aws_usage_price] = @text.to_f - when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f - when 'productDescription' then @item[:aws_product_description] = @text - when 'item' then @result << @item - end - end - def reset - @result = [] - end - end - - class QEc2PurchaseReservedInstancesOfferingParser < RightAWSParser #:nodoc: - def tagend(name) - if name == 'reservedInstancesId' - @result = @text - end - end - def reset - @result = '' - end - end - - #----------------------------------------------------------------- - # PARSERS: Console - #----------------------------------------------------------------- - - class QEc2GetConsoleOutputParser < RightAWSParser #:nodoc: - def tagend(name) - case name - when 'instanceId' then @result[:aws_instance_id] = @text - when 'timestamp' then @result[:aws_timestamp] = @text - @result[:timestamp] = (Time.parse(@text)).utc - when 'output' then @result[:aws_output] = Base64.decode64(@text) - end - end - def reset - @result = {} - end - end - - #----------------------------------------------------------------- - # Instances: Wondows related part - #----------------------------------------------------------------- - class QEc2DescribeBundleTasksParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - @bundle = {} if name == 'item' - end - def tagend(name) - case name -# when 'requestId' then @bundle[:request_id] = @text - when 'instanceId' then @bundle[:aws_instance_id] = @text - when 'bundleId' then @bundle[:aws_id] = @text - when 'bucket' then @bundle[:s3_bucket] = @text - when 'prefix' then @bundle[:s3_prefix] = @text - when 'startTime' then @bundle[:aws_start_time] = @text - when 'updateTime' then @bundle[:aws_update_time] = @text - when 'state' then @bundle[:aws_state] = @text - when 'progress' then @bundle[:aws_progress] = @text - when 'code' then @bundle[:aws_error_code] = @text - when 'message' then @bundle[:aws_error_message] = @text - when 'item' then @result << @bundle - end - end - def reset - @result = [] - end - end - - class QEc2BundleInstanceParser < RightAWSParser #:nodoc: - def tagend(name) - case name -# when 'requestId' then @result[:request_id] = @text - when 'instanceId' then @result[:aws_instance_id] = @text - when 'bundleId' then @result[:aws_id] = @text - when 'bucket' then @result[:s3_bucket] = @text - when 'prefix' then @result[:s3_prefix] = @text - when 'startTime' then @result[:aws_start_time] = @text - when 'updateTime' then @result[:aws_update_time] = @text - when 'state' then @result[:aws_state] = @text - when 'progress' then @result[:aws_progress] = @text - when 'code' then @result[:aws_error_code] = @text - when 'message' then @result[:aws_error_message] = @text - end - end - def reset - @result = {} - end - end - - #----------------------------------------------------------------- # PARSERS: Elastic IPs #----------------------------------------------------------------- class QEc2AllocateAddressParser < RightAWSParser #:nodoc: def tagend(name) @@ -1698,11 +589,11 @@ def tagend(name) case name when 'regionName' then @zone[:region_name] = @text when 'zoneName' then @zone[:zone_name] = @text when 'zoneState' then @zone[:zone_state] = @text - when 'item' then @result << @zone + when 'item' then @result << @zone end end def reset @result = [] end @@ -1716,120 +607,9 @@ def tagend(name) @result << @text if name == 'regionName' end def reset @result = [] - end - end - - #----------------------------------------------------------------- - # PARSERS: EBS - Volumes - #----------------------------------------------------------------- - - class QEc2CreateVolumeParser < RightAWSParser #:nodoc: - def tagend(name) - case name - when 'volumeId' then @result[:aws_id] = @text - when 'status' then @result[:aws_status] = @text - when 'createTime' then @result[:aws_created_at] = Time.parse(@text) - when 'size' then @result[:aws_size] = @text.to_i ### - when 'snapshotId' then @result[:snapshot_id] = @text.blank? ? nil : @text ### - when 'availabilityZone' then @result[:zone] = @text ### - end - end - def reset - @result = {} - end - end - - class QEc2AttachAndDetachVolumeParser < RightAWSParser #:nodoc: - def tagend(name) - case name - when 'volumeId' then @result[:aws_id] = @text - when 'instanceId' then @result[:aws_instance_id] = @text - when 'device' then @result[:aws_device] = @text - when 'status' then @result[:aws_attachment_status] = @text - when 'attachTime' then @result[:aws_attached_at] = Time.parse(@text) - end - end - def reset - @result = {} - end - end - - class QEc2DescribeVolumesParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - case name - when 'item' - case @xmlpath - when 'DescribeVolumesResponse/volumeSet' then @volume = {} - end - end - end - def tagend(name) - case name - when 'volumeId' - case @xmlpath - when 'DescribeVolumesResponse/volumeSet/item' then @volume[:aws_id] = @text - end - when 'status' - case @xmlpath - when 'DescribeVolumesResponse/volumeSet/item' then @volume[:aws_status] = @text - when 'DescribeVolumesResponse/volumeSet/item/attachmentSet/item' then @volume[:aws_attachment_status] = @text - end - when 'size' then @volume[:aws_size] = @text.to_i - when 'createTime' then @volume[:aws_created_at] = Time.parse(@text) - when 'instanceId' then @volume[:aws_instance_id] = @text - when 'device' then @volume[:aws_device] = @text - when 'attachTime' then @volume[:aws_attached_at] = Time.parse(@text) - when 'snapshotId' then @volume[:snapshot_id] = @text.blank? ? nil : @text - when 'availabilityZone' then @volume[:zone] = @text - when 'item' - case @xmlpath - when 'DescribeVolumesResponse/volumeSet' then @result << @volume - end - end - end - def reset - @result = [] - end - end - - #----------------------------------------------------------------- - # PARSERS: EBS - Snapshots - #----------------------------------------------------------------- - - class QEc2DescribeSnapshotsParser < RightAWSParser #:nodoc: - def tagstart(name, attributes) - @snapshot = {} if name == 'item' - end - def tagend(name) - case name - when 'volumeId' then @snapshot[:aws_volume_id] = @text - when 'snapshotId' then @snapshot[:aws_id] = @text - when 'status' then @snapshot[:aws_status] = @text - when 'startTime' then @snapshot[:aws_started_at] = Time.parse(@text) - when 'progress' then @snapshot[:aws_progress] = @text - when 'item' then @result << @snapshot - end - end - def reset - @result = [] - end - end - - class QEc2CreateSnapshotParser < RightAWSParser #:nodoc: - def tagend(name) - case name - when 'volumeId' then @result[:aws_volume_id] = @text - when 'snapshotId' then @result[:aws_id] = @text - when 'status' then @result[:aws_status] = @text - when 'startTime' then @result[:aws_started_at] = Time.parse(@text) - when 'progress' then @result[:aws_progress] = @text - end - end - def reset - @result = {} end end end