1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00
fog--fog/lib/fog/aws/requests/compute/run_instances.rb
MaF 4402d6690f Improved support for SecurityGroup IDs
This patch makes it possible to specify GroupID in the options hash to the
aws computre requests operating on security groups. This is needed since
when working with VPC you must use GroupID instead of name.
2012-03-09 09:09:28 +01:00

180 lines
9.8 KiB
Ruby

module Fog
module Compute
class AWS
class Real
require 'fog/aws/parsers/compute/run_instances'
# Launch specified instances
#
# ==== Parameters
# * image_id<~String> - Id of machine image to load on instances
# * min_count<~Integer> - Minimum number of instances to launch. If this
# exceeds the count of available instances, no instances will be
# launched. Must be between 1 and maximum allowed for your account
# (by default the maximum for an account is 20)
# * max_count<~Integer> - Maximum number of instances to launch. If this
# exceeds the number of available instances, the largest possible
# number of instances above min_count will be launched instead. Must
# be between 1 and maximum allowed for you account
# (by default the maximum for an account is 20)
# * options<~Hash>:
# * 'Placement.AvailabilityZone'<~String> - Placement constraint for instances
# * 'Placement.GroupName'<~String> - Name of existing placement group to launch instance into
# * 'Placement.Tenancy'<~String> - Tenancy option in ['dedicated', 'default'], defaults to 'default'
# * 'BlockDeviceMapping'<~Array>: array of hashes
# * 'DeviceName'<~String> - where the volume will be exposed to instance
# * 'VirtualName'<~String> - volume virtual device name
# * 'Ebs.SnapshotId'<~String> - id of snapshot to boot volume from
# * 'Ebs.VolumeSize'<~String> - size of volume in GiBs required unless snapshot is specified
# * 'Ebs.DeleteOnTermination'<~String> - specifies whether or not to delete the volume on instance termination
# * 'ClientToken'<~String> - unique case-sensitive token for ensuring idempotency
# * 'DisableApiTermination'<~Boolean> - specifies whether or not to allow termination of the instance from the api
# * 'SecurityGroup'<~Array> or <~String> - Name of security group(s) for instances (not supported for VPC)
# * 'SecurityGroupId'<~Array> or <~String> - id's of security group(s) for instances, use this or SecurityGroup
# * 'InstanceInitiatedShutdownBehaviour'<~String> - specifies whether volumes are stopped or terminated when instance is shutdown, in [stop, terminate]
# * 'InstanceType'<~String> - Type of instance to boot. Valid options
# in ['t1.micro', 'm1.small', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', m2.2xlarge', 'm2.4xlarge', 'cc1.4xlarge', 'cg1.4xlarge']
# default is 'm1.small'
# * 'KernelId'<~String> - Id of kernel with which to launch
# * 'KeyName'<~String> - Name of a keypair to add to booting instances
# * 'Monitoring.Enabled'<~Boolean> - Enables monitoring, defaults to
# disabled
# * 'PrivateIpAddress<~String> - VPC option to specify ip address within subnet
# * 'RamdiskId'<~String> - Id of ramdisk with which to launch
# * 'SubnetId'<~String> - VPC option to specify subnet to launch instance into
# * 'UserData'<~String> - Additional data to provide to booting instances
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * 'groupSet'<~Array>: groups the instances are members in
# * 'groupName'<~String> - Name of group
# * 'instancesSet'<~Array>: returned instances
# * instance<~Hash>:
# * 'amiLaunchIndex'<~Integer> - reference to instance in launch group
# * 'architecture'<~String> - architecture of image in [i386, x86_64]
# * 'blockDeviceMapping'<~Array>
# * 'attachTime'<~Time> - time of volume attachment
# * 'deleteOnTermination'<~Boolean> - whether or not to delete volume on termination
# * 'deviceName'<~String> - specifies how volume is exposed to instance
# * 'status'<~String> - status of attached volume
# * 'volumeId'<~String> - Id of attached volume
# * 'dnsName'<~String> - public dns name, blank until instance is running
# * 'imageId'<~String> - image id of ami used to launch instance
# * 'instanceId'<~String> - id of the instance
# * 'instanceState'<~Hash>:
# * 'code'<~Integer> - current status code
# * 'name'<~String> - current status name
# * 'instanceType'<~String> - type of instance
# * 'ipAddress'<~String> - public ip address assigned to instance
# * 'kernelId'<~String> - Id of kernel used to launch instance
# * 'keyName'<~String> - name of key used launch instances or blank
# * 'launchTime'<~Time> - time instance was launched
# * 'monitoring'<~Hash>:
# * 'state'<~Boolean - state of monitoring
# * 'placement'<~Hash>:
# * 'availabilityZone'<~String> - Availability zone of the instance
# * 'privateDnsName'<~String> - private dns name, blank until instance is running
# * 'privateIpAddress'<~String> - private ip address assigned to instance
# * 'productCodes'<~Array> - Product codes for the instance
# * 'ramdiskId'<~String> - Id of ramdisk used to launch instance
# * 'reason'<~String> - reason for most recent state transition, or blank
# * 'rootDeviceName'<~String> - specifies how the root device is exposed to the instance
# * 'rootDeviceType'<~String> - root device type used by AMI in [ebs, instance-store]
# * 'ownerId'<~String> - Id of owner
# * 'requestId'<~String> - Id of request
# * 'reservationId'<~String> - Id of reservation
#
# {Amazon API Reference}[http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html]
def run_instances(image_id, min_count, max_count, options = {})
if block_device_mapping = options.delete('BlockDeviceMapping')
block_device_mapping.each_with_index do |mapping, index|
for key, value in mapping
options.merge!({ format("BlockDeviceMapping.%d.#{key}", index) => value })
end
end
end
if security_groups = options.delete('SecurityGroup')
options.merge!(Fog::AWS.indexed_param('SecurityGroup', [*security_groups]))
end
if security_group_ids = options.delete('SecurityGroupId')
options.merge!(Fog::AWS.indexed_param('SecurityGroupId', [*security_group_ids]))
end
if options['UserData']
options['UserData'] = Base64.encode64(options['UserData'])
end
idempotent = !(options['ClientToken'].nil? || options['ClientToken'].empty?)
request({
'Action' => 'RunInstances',
'ImageId' => image_id,
'MinCount' => min_count,
'MaxCount' => max_count,
:idempotent => idempotent,
:parser => Fog::Parsers::Compute::AWS::RunInstances.new
}.merge!(options))
end
end
class Mock
def run_instances(image_id, min_count, max_count, options = {})
response = Excon::Response.new
response.status = 200
group_set = [ (options['SecurityGroup'] || 'default') ].flatten
instances_set = []
reservation_id = Fog::AWS::Mock.reservation_id
if options['KeyName'] && describe_key_pairs('key-name' => options['KeyName']).body['keySet'].empty?
raise Fog::Compute::AWS::NotFound.new("The key pair '#{options['KeyName']}' does not exist")
end
min_count.times do |i|
instance_id = Fog::AWS::Mock.instance_id
instance = {
'amiLaunchIndex' => i,
'blockDeviceMapping' => [],
'clientToken' => options['clientToken'],
'dnsName' => nil,
'imageId' => image_id,
'instanceId' => instance_id,
'instanceState' => { 'code' => 0, 'name' => 'pending' },
'instanceType' => options['InstanceType'] || 'm1.small',
'kernelId' => options['KernelId'] || Fog::AWS::Mock.kernel_id,
'keyName' => options['KeyName'],
'launchTime' => Time.now,
'monitoring' => { 'state' => options['Monitoring.Enabled'] || false },
'placement' => { 'availabilityZone' => options['Placement.AvailabilityZone'] || Fog::AWS::Mock.availability_zone(@region), 'groupName' => nil, 'tenancy' => 'default' },
'privateDnsName' => nil,
'productCodes' => [],
'reason' => nil,
'rootDeviceType' => 'instance-store'
}
instances_set << instance
self.data[:instances][instance_id] = instance.merge({
'architecture' => 'i386',
'groupSet' => group_set,
'ownerId' => self.data[:owner_id],
'privateIpAddress' => nil,
'reservationId' => reservation_id,
'stateReason' => {}
})
end
response.body = {
'groupSet' => group_set,
'instancesSet' => instances_set,
'ownerId' => self.data[:owner_id],
'requestId' => Fog::AWS::Mock.request_id,
'reservationId' => reservation_id
}
response
end
end
end
end
end