Class: Cyoi::Providers::Clients::AwsProviderClient

Inherits:
FogProviderClient show all
Includes:
Cyoi::Providers::Constants::AwsConstants
Defined in:
lib/cyoi/providers/clients/aws_provider_client.rb

Instance Attribute Summary

Attributes inherited from FogProviderClient

#attributes, #fog_compute

Instance Method Summary collapse

Methods included from Cyoi::Providers::Constants::AwsConstants

#default_region_code, #region_labels

Methods inherited from FogProviderClient

#cleanup_unused_ip_addresses, #create_key_pair, #create_security_group, #delete_key_pair_if_exists, #delete_servers_with_name, #delete_volumes_with_name, #extract_port_definition, #find_unused_public_ip_address, #initialize, #provision_or_reuse_public_ip_address, #set_resource_name, #supports_blobstore_service?, #valid_key_pair_fingerprint?

Constructor Details

This class inherits a constructor from Cyoi::Providers::Clients::FogProviderClient

Instance Method Details

#associate_ip_address_with_server(ip_address, server) ⇒ Object



75
76
77
78
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 75

def associate_ip_address_with_server(ip_address, server)
  address = fog_compute.addresses.get(ip_address)
  address.server = server
end

#authorize_port_range(sg, port_range, protocol, ip_range) ⇒ Object



142
143
144
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 142

def authorize_port_range(sg, port_range, protocol, ip_range)
  sg.authorize_port_range(port_range, {:ip_protocol => protocol, :cidr_ip => ip_range})
end

#aws_compute_flavor_idsObject



55
56
57
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 55

def aws_compute_flavor_ids
  aws_compute_flavors.map { |fl| fl[:id] }
end

#aws_compute_flavorsArray

Example [Hash] { :bits => 0, :cores => 2, :disk => 0,

:id => 't1.micro', :name => 'Micro Instance', :ram => 613}

Returns:

  • (Array)

    of [Hash] for each supported compute flavor



51
52
53
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 51

def aws_compute_flavors
  Fog::Compute::AWS::FLAVORS
end

#bootstrap(new_attributes = {}) ⇒ Object



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 201

def bootstrap(new_attributes = {})
  new_attributes[:image_id] ||= trusty_image_id(fog_compute.region)
  vpc = new_attributes[:subnet_id]

  server = fog_compute.servers.new(new_attributes)

  unless new_attributes[:key_name]
    raise "please provide :key_name attribute"
  end
  unless private_key_path = new_attributes.delete(:private_key_path)
    raise "please provide :private_key_path attribute"
  end

  if vpc
    # TODO setup security group on new server
  else
    # make sure port 22 is open in the first security group
    security_group = fog_compute.security_groups.get(server.groups.first)
    authorized = security_group.ip_permissions.detect do |ip_permission|
      ip_permission['ipRanges'].first && ip_permission['ipRanges'].first['cidrIp'] == '0.0.0.0/0' &&
      ip_permission['fromPort'] == 22 &&
      ip_permission['ipProtocol'] == 'tcp' &&
      ip_permission['toPort'] == 22
    end
    unless authorized
      security_group.authorize_port_range(22..22)
    end
  end

  server.save
  unless Fog.mocking?
    server.wait_for { ready? }
    server.setup(:keys => [private_key_path])
  end
  server
end

#create_and_attach_volume(name, disk_size, server, device) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 150

def create_and_attach_volume(name, disk_size, server, device)
  volume = fog_compute.volumes.create(
      size: disk_size,
      name: name,
      description: '',
      device: device,
      availability_zone: server.availability_zone)
  # TODO: the following works in fog 1.9.0+ (but which has a bug in bootstrap)
  # https://github.com/fog/fog/issues/1516
  #
  # volume.wait_for { volume.status == 'available' }
  # volume.attach(server.id, "/dev/vdc")
  # volume.wait_for { volume.status == 'in-use' }
  #
  # Instead, using:
  volume.server = server
end

#create_blobstore(blobstore_name) ⇒ Object

Creates a bucket and makes it publicly read-only



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 13

def create_blobstore(blobstore_name)
  super
  policy = {
    "Version" => "2008-10-17",
    "Statement" => [
      {
        "Sid" => "AddPerm",
        "Effect" => "Allow",
        "Principal" => {
          "AWS" => "*"
        },
        "Action" => "s3:GetObject",
        "Resource" => "arn:aws:s3:::#{blobstore_name}/*"
      }
    ]
  }
  fog_storage.put_bucket_policy(blobstore_name, policy)
end

#create_internet_gateway(vpc_id) ⇒ Object



124
125
126
127
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 124

def create_internet_gateway(vpc_id)
  gateway = fog_compute.internet_gateways.create(vpc_id: vpc_id)
  gateway.id
end

#create_subnet(vpc_id, cidr_block) ⇒ String

Creates a VPC subnet

Returns:

  • (String)

    the subnet_id



119
120
121
122
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 119

def create_subnet(vpc_id, cidr_block)
  subnet = fog_compute.subnets.create(vpc_id: vpc_id, cidr_block: cidr_block)
  subnet.subnet_id
end

#create_vpc(name, cidr_block) ⇒ Object



99
100
101
102
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 99

def create_vpc(name, cidr_block)
  vpc = fog_compute.vpcs.create(name: name, cidr_block: cidr_block)
  vpc.id
end

#find_server_device(server, device) ⇒ Object



146
147
148
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 146

def find_server_device(server, device)
  server.volumes.all.find {|v| v.device == device}
end

#fog_compute_flavor(server_flavor_id) ⇒ Hash

or nil if server_flavor_id is not a supported flavor ID

Returns:

  • (Hash)

    e.g. { :bits => 0, :cores => 2, :disk => 0, :id => ‘t1.micro’, :name => ‘Micro Instance’, :ram => 613}



44
45
46
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 44

def fog_compute_flavor(server_flavor_id)
  aws_compute_flavors.find { |fl| fl[:id] == server_flavor_id }
end

#fog_networkObject

Fog::Network does not exist for aws, use Fog::Compute instead



247
248
249
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 247

def fog_network
  fog_compute
end

#fog_storageObject



238
239
240
241
242
243
244
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 238

def fog_storage
  @fog_storage ||= begin
    configuration = Fog.symbolize_credentials(attributes.credentials)
    configuration[:provider] = "AWS"
    Fog::Storage.new(configuration)
  end
end

#ip_addresses_assigned_to_serversObject



94
95
96
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 94

def ip_addresses_assigned_to_servers
  fog_compute.servers.map {|s| s.private_ip_address}
end

#ip_permissions(sg) ⇒ Object



129
130
131
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 129

def ip_permissions(sg)
  sg.ip_permissions
end

#networks?boolean

Returns true if target OpenStack running Neutron networks.

Returns:

  • (boolean)

    true if target OpenStack running Neutron networks



105
106
107
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 105

def networks?
  vpcs.size > 0
end

#next_available_ip_in_subnet(subnet) ⇒ String

AWS reserves both the first four IP addresses and the last IP address in each subnet CIDR block. They’re not available for you to use.

Returns:

  • (String)

    IP that is available for a new VM to use in a subnet



83
84
85
86
87
88
89
90
91
92
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 83

def next_available_ip_in_subnet(subnet)
  return nil if subnet.available_ip_address_count.to_i < 1
  ip = IPAddr.new(subnet.cidr_block)
  4.times { ip = ip.succ }
  skip_ips = ip_addresses_assigned_to_servers
  while skip_ips.include?(ip.to_s)
    ip = ip.succ
  end
  ip.to_s
end

#port_open?(ip_permissions, port_range, protocol, ip_range) ⇒ Boolean

Returns:

  • (Boolean)


133
134
135
136
137
138
139
140
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 133

def port_open?(ip_permissions, port_range, protocol, ip_range)
  ip_permissions && ip_permissions.find do |ip|
   ip["ipProtocol"] == protocol \
   && ip["ipRanges"].detect { |range| range["cidrIp"] == ip_range } \
   && ip["fromPort"] <= port_range.min \
   && ip["toPort"] >= port_range.max
  end
end

#provision_public_ip_address(options = {}) ⇒ String

Provision an EC2 or VPC elastic IP addess.

  • VPC - provision_public_ip_address(vpc: true)

  • EC2 - provision_public_ip_address

TODO nil if none available

Returns:

  • (String)

    provisions a new public IP address in target region



64
65
66
67
68
69
70
71
72
73
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 64

def provision_public_ip_address(options={})
  if options.delete(:vpc)
    options[:domain] = "vpc"
  else
    options[:domain] = options.delete(:domain) || "standard"
  end
  address = fog_compute.addresses.create(options)
  address.public_ip
  # TODO catch error and return nil
end

#ram_for_server_flavor(server_flavor_id) ⇒ Integer

Returns megabytes of RAM for requested flavor of server.

Returns:

  • (Integer)

    megabytes of RAM for requested flavor of server



33
34
35
36
37
38
39
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 33

def ram_for_server_flavor(server_flavor_id)
  if flavor = fog_compute_flavor(server_flavor_id)
    flavor[:ram]
  else
    raise "Unknown AWS flavor '#{server_flavor_id}'"
  end
end

#setup_fog_connectionObject

Construct a Fog::Compute object Uses attributes which normally originates from settings.provider



253
254
255
256
257
258
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 253

def setup_fog_connection
  configuration = Fog.symbolize_credentials(attributes.credentials)
  configuration[:provider] = "AWS"
  configuration[:region] = attributes.region
  @fog_compute = Fog::Compute.new(configuration)
end

#subnetsObject



113
114
115
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 113

def subnets
  fog_compute.subnets
end

#trusty_image_id(region = nil) ⇒ Object

Ubuntu 14.04



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 169

def trusty_image_id(region=nil)
  region = fog_compute.region
  # http://cloud-images.ubuntu.com/locator/ec2/
  # version: 14.04 LTS
  # arch: amd64
  # instance type: ebs-ssd (not hvm)
  # Using release 20140927
  image_id = case region.to_s
  when "ap-northeast-1"
    "ami-df4b60de"
  when "ap-southeast-1"
    "ami-2ce7c07e"
  when "eu-west-1"
    "ami-f6b11181"
  when "sa-east-1"
    "ami-71d2676c"
  when "us-east-1"
    "ami-98aa1cf0"
  when "us-west-1"
    "ami-736e6536"
  when "eu-central-1"
    "ami-423c0a5f"
  when "cn-north-1"
    "ami-e642d0df"
  when "ap-southeast-2"
    "ami-1f117325"
  when "us-west-2"
    "ami-37501207"
  end
  image_id || raise("Please add Ubuntu 14.04 64bit (EBS SSD) AMI image id to aws.rb#trusty_image_id method for region '#{region}'")
end

#vpcsObject



109
110
111
# File 'lib/cyoi/providers/clients/aws_provider_client.rb', line 109

def vpcs
  fog_compute.vpcs
end