steamcannon-deltacloud-core 0.1.1.3 → 0.1.2.1

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.
Files changed (50) hide show
  1. data/bin/deltacloudd +7 -1
  2. data/config.ru +19 -1
  3. data/deltacloud.rb +20 -1
  4. data/lib/deltacloud/backend_capability.rb +33 -1
  5. data/lib/deltacloud/base_driver.rb +1 -1
  6. data/lib/deltacloud/base_driver/base_driver.rb +62 -73
  7. data/lib/deltacloud/base_driver/features.rb +6 -6
  8. data/lib/deltacloud/drivers/azure/azure_driver.rb +32 -1
  9. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +107 -23
  10. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +18 -0
  11. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +0 -1
  12. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +20 -5
  13. data/lib/deltacloud/drivers/mock/mock_driver.rb +1 -1
  14. data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +1 -1
  15. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +28 -1
  16. data/lib/deltacloud/hardware_profile.rb +17 -0
  17. data/lib/deltacloud/helpers.rb +18 -0
  18. data/lib/deltacloud/helpers/application_helper.rb +2 -2
  19. data/lib/deltacloud/helpers/blob_stream.rb +5 -1
  20. data/lib/deltacloud/helpers/conversion_helper.rb +1 -2
  21. data/lib/deltacloud/helpers/hardware_profiles_helper.rb +17 -0
  22. data/lib/deltacloud/method_serializer.rb +1 -1
  23. data/lib/deltacloud/models/base_model.rb +1 -1
  24. data/lib/deltacloud/models/blob.rb +3 -1
  25. data/lib/deltacloud/models/bucket.rb +2 -1
  26. data/lib/deltacloud/models/image.rb +1 -1
  27. data/lib/deltacloud/models/instance.rb +1 -2
  28. data/lib/deltacloud/models/instance_profile.rb +2 -1
  29. data/lib/deltacloud/models/key.rb +1 -1
  30. data/lib/deltacloud/models/load_balancer.rb +1 -1
  31. data/lib/deltacloud/models/realm.rb +1 -1
  32. data/lib/deltacloud/models/storage_snapshot.rb +1 -1
  33. data/lib/deltacloud/models/storage_volume.rb +1 -1
  34. data/lib/deltacloud/state_machine.rb +17 -0
  35. data/lib/deltacloud/validation.rb +18 -0
  36. data/lib/drivers.rb +69 -43
  37. data/lib/sinatra/lazy_auth.rb +1 -1
  38. data/lib/sinatra/rabbit.rb +5 -5
  39. data/lib/sinatra/rack_driver_select.rb +29 -0
  40. data/server.rb +45 -16
  41. data/views/api/drivers.xml.haml +6 -0
  42. data/views/api/show.html.haml +2 -2
  43. data/views/api/show.xml.haml +1 -1
  44. data/views/buckets/index.html.haml +2 -1
  45. data/views/buckets/show.html.haml +4 -3
  46. data/views/errors/backend_error.xml.haml +1 -1
  47. data/views/images/index.xml.haml +5 -1
  48. data/views/layout.html.haml +1 -1
  49. metadata +6 -5
  50. data/lib/deltacloud/drivers/gogrid/test.rb +0 -13
data/bin/deltacloudd CHANGED
@@ -36,6 +36,9 @@ BANNER
36
36
  opts.on( '-p', '--port PORT', 'Use PORT (default: 3001)') do |port|
37
37
  ENV["API_PORT"] = port
38
38
  end
39
+ opts.on( '-P', '--provider PROVIDER', 'Use PROVIDER (default is set in the driver)') do |provider|
40
+ ENV['API_PROVIDER'] = provider
41
+ end
39
42
  opts.on( '-e', '--env ENV', 'Environment (default: "development")') { |env| options[:env] = env }
40
43
  opts.on( '-h', '--help', '') { options[:help] = true }
41
44
  end
@@ -55,7 +58,10 @@ end
55
58
  ENV["API_HOST"] = "localhost" unless ENV["API_HOST"]
56
59
  ENV["API_PORT"] = "3001" unless ENV["API_PORT"]
57
60
 
58
- puts "Starting Deltacloud API :: #{ENV["API_DRIVER"]} :: http://#{ENV["API_HOST"]}:#{ENV["API_PORT"]}/api"
61
+ msg = "Starting Deltacloud API :: #{ENV["API_DRIVER"]} "
62
+ msg << ":: #{ENV['API_PROVIDER']} " if ENV['API_PROVIDER']
63
+ msg << ":: http://#{ENV["API_HOST"]}:#{ENV["API_PORT"]}/api"
64
+ puts msg
59
65
  puts
60
66
 
61
67
  dirname="#{File.dirname(__FILE__)}/.."
data/config.ru CHANGED
@@ -1,7 +1,25 @@
1
+ #
2
+ # Copyright (C) 2009,2010 Red Hat, Inc.
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one or more
5
+ # contributor license agreements. See the NOTICE file distributed with
6
+ # this work for additional information regarding copyright ownership. The
7
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance with the
9
+ # License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+ # License for the specific language governing permissions and limitations
17
+ # under the License.
18
+
1
19
  require 'rubygems'
2
- require 'sinatra'
3
20
 
4
21
  $:.unshift File.join(File.dirname(__FILE__), '.')
5
22
 
6
23
  require 'server.rb'
24
+
7
25
  run Sinatra::Application
data/deltacloud.rb CHANGED
@@ -1,6 +1,25 @@
1
- # Add ./lib into load path
1
+ #
2
+ # Copyright (C) 2009,2010 Red Hat, Inc.
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one or more
5
+ # contributor license agreements. See the NOTICE file distributed with
6
+ # this work for additional information regarding copyright ownership. The
7
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance with the
9
+ # License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+ # License for the specific language governing permissions and limitations
17
+ # under the License.
18
+
2
19
  $:.unshift File.join(File.dirname(__FILE__), 'lib')
3
20
 
21
+ require 'drivers'
22
+
4
23
  require 'deltacloud/base_driver'
5
24
  require 'deltacloud/hardware_profile'
6
25
  require 'deltacloud/state_machine'
@@ -1,7 +1,26 @@
1
+ #
2
+ # Copyright (C) 2009, 2010 Red Hat, Inc.
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one or more
5
+ # contributor license agreements. See the NOTICE file distributed with
6
+ # this work for additional information regarding copyright ownership. The
7
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance with the
9
+ # License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+ # License for the specific language governing permissions and limitations
17
+ # under the License.
18
+
1
19
  module Deltacloud::BackendCapability
2
20
 
3
21
  class Failure < StandardError
4
22
  attr_reader :capability
23
+
5
24
  def initialize(capability, msg='')
6
25
  super(msg)
7
26
  @capability = capability
@@ -9,13 +28,26 @@ module Deltacloud::BackendCapability
9
28
  end
10
29
 
11
30
  attr_reader :capability
31
+
12
32
  def with_capability(capability)
13
33
  @capability = capability
14
34
  end
15
35
 
36
+ def has_capability?(backend)
37
+ !capability or backend.has_capability?(capability)
38
+ end
39
+
16
40
  def check_capability(backend)
17
- if capability and !backend.respond_to?(capability)
41
+ if !has_capability?(backend)
18
42
  raise Failure.new(capability, "#{capability} capability not supported by backend #{backend.class.name}")
19
43
  end
20
44
  end
45
+
46
+ module Helpers
47
+ def operations_for_collection(collection)
48
+ collections[collection].operations.values.select { |op| op.has_capability?(driver) }
49
+ end
50
+ end
51
+
52
+ helpers Helpers
21
53
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (C) 2009 Red Hat, Inc.
2
+ # Copyright (C) 2009,2010 Red Hat, Inc.
3
3
  #
4
4
  # Licensed to the Apache Software Foundation (ASF) under one or more
5
5
  # contributor license agreements. See the NOTICE file distributed with
@@ -42,7 +42,7 @@ module Deltacloud
42
42
  end
43
43
 
44
44
  class BaseDriver
45
-
45
+
46
46
  def self.define_hardware_profile(name,&block)
47
47
  @hardware_profiles ||= []
48
48
  hw_profile = @hardware_profiles.find{|e| e.name == name}
@@ -126,100 +126,90 @@ module Deltacloud
126
126
  actions
127
127
  end
128
128
 
129
+ ## Capabilities
130
+ # The rabbit dsl supports declaring a capability that is required
131
+ # in the backend driver for the call to succeed. A driver can
132
+ # provide a capability by implementing the method with the same
133
+ # name as the capability. Below is a list of the capabilities as
134
+ # the expected method signatures.
135
+ #
136
+ # Following the capability list are the resource member show
137
+ # methods. They each require that the corresponding collection
138
+ # method be defined
139
+ #
140
+ # TODO: standardize all of these to the same signature (credentials, opts)
141
+ #
142
+ # def realms(credentials, opts=nil)
143
+ #
144
+ # def images(credentials, ops)
145
+ #
146
+ # def instances(credentials, ops)
147
+ # def create_instance(credentials, image_id, opts)
148
+ # def start_instance(credentials, id)
149
+ # def stop_instance(credentials, id)
150
+ # def reboot_instance(credentials, id)
151
+ #
152
+ # def storage_volumes(credentials, ops)
153
+ #
154
+ # def storage_snapshots(credentials, ops)
155
+ #
156
+ # def buckets(credentials, opts = nil)
157
+ # def create_bucket(credentials, name, opts=nil)
158
+ # def delete_bucket(credentials, name, opts=nil)
159
+ #
160
+ # def blobs(credentials, opts = nil)
161
+ # def blob_data(credentials, bucket_id, blob_id, opts)
162
+ # def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
163
+ # def delete_blob(credentials, bucket_id, blob_id, opts=nil)
164
+ #
165
+ # def keys(credentials, opts)
166
+ # def create_key(credentials, opts)
167
+ # def destroy_key(credentials, opts)
168
+
129
169
  def realm(credentials, opts)
130
- realms = realms(credentials, opts)
131
- return realms.first unless realms.empty?
132
- nil
133
- end
134
-
135
- def realms(credentials, opts=nil)
136
- []
170
+ realms = realms(credentials, opts).first if has_capability?(:realms)
137
171
  end
138
172
 
139
173
  def image(credentials, opts)
140
- images = images(credentials, opts)
141
- return images.first unless images.empty?
142
- nil
143
- end
144
-
145
- def images(credentials, ops)
146
- []
174
+ images(credentials, opts).first if has_capability?(:images)
147
175
  end
148
176
 
149
177
  def instance(credentials, opts)
150
- instances = instances(credentials, opts)
151
- return instances.first unless instances.empty?
152
- nil
153
- end
154
-
155
- def instances(credentials, ops)
156
- []
157
- end
158
-
159
- def create_instance(credentials, image_id, opts)
160
- end
161
- def start_instance(credentials, id)
162
- end
163
- def stop_instance(credentials, id)
164
- end
165
- def reboot_instance(credentials, id)
178
+ instances(credentials, opts).first if has_capability?(:instances)
166
179
  end
167
180
 
168
181
  def storage_volume(credentials, opts)
169
- volumes = storage_volumes(credentials, opts)
170
- return volumes.first unless volumes.empty?
171
- nil
172
- end
173
-
174
- def storage_volumes(credentials, ops)
175
- []
182
+ storage_volumes(credentials, opts).first if has_capability?(:storage_volumes)
176
183
  end
177
184
 
178
185
  def storage_snapshot(credentials, opts)
179
- snapshots = storage_snapshots(credentials, opts)
180
- return snapshots.first unless snapshots.empty?
181
- nil
182
- end
183
-
184
- def storage_snapshots(credentials, ops)
185
- []
186
- end
187
-
188
- def buckets(credentials, opts = nil)
189
- #list of buckets belonging to account
190
- []
186
+ storage_snapshots(credentials, opts).first if has_capability?(:storage_snapshots)
191
187
  end
192
188
 
193
189
  def bucket(credentials, opts = nil)
194
- #list of objects within bucket
195
- list = buckets(credentials, opts)
196
- return list.first unless list.empty?
197
- nil
198
- end
199
-
200
- def create_bucket(credentials, name, opts=nil)
201
- end
202
-
203
- def delete_bucket(credentials, name, opts=nil)
190
+ #list of objects within bucket
191
+ buckets(credentials, opts).first if has_capability?(:buckets)
204
192
  end
205
-
206
- def blobs(credentials, opts = nil)
207
- []
208
- end
209
-
193
+
210
194
  def blob(credentials, opts = nil)
211
- list = blobs(credentials, opts)
212
- return list.first unless list.empty?
195
+ blobs(credentials, opts).first if has_capability?(:blobs)
213
196
  end
214
197
 
215
- def blob_data(credentials, bucket_id, blob_id, opts)
198
+ def key(credentials, opts=nil)
199
+ keys(credentials, opts).first if has_capability?(:keys)
216
200
  end
217
201
 
218
- def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
219
- end
202
+ MEMBER_SHOW_METHODS =
203
+ [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key ]
220
204
 
221
- def delete_blob(credentials, bucket_id, blob_id, opts=nil)
205
+ def has_capability?(capability)
206
+ if MEMBER_SHOW_METHODS.include?(capability.to_sym)
207
+ has_capability?(capability.to_s.pluralize)
208
+ else
209
+ respond_to?(capability)
210
+ end
222
211
  end
212
+
223
213
 
224
214
  def filter_on(collection, attribute, opts)
225
215
  return collection if opts.nil?
@@ -237,8 +227,7 @@ module Deltacloud
237
227
  end
238
228
 
239
229
  def has_collection?(collection)
240
- return true if self.supported_collections.include?(collection)
241
- return false
230
+ supported_collections.include?(collection)
242
231
  end
243
232
 
244
233
  def catched_exceptions_list
@@ -117,6 +117,12 @@ module Deltacloud
117
117
  self.class.features[collection] || []
118
118
  end
119
119
 
120
+ def features_for_operation(collection, operation)
121
+ features(collection).select do |f|
122
+ f.operations.detect { |o| o.name == operation }
123
+ end
124
+ end
125
+
120
126
  #
121
127
  # Declaration of optional features
122
128
  #
@@ -185,11 +191,5 @@ module Deltacloud
185
191
  end
186
192
  end
187
193
 
188
- declare_feature :instances, :public_ip do
189
- operation :create do
190
- param :public_ip, :string, :optional
191
- end
192
- end
193
-
194
194
  end
195
195
  end
@@ -17,8 +17,9 @@
17
17
  # under the License.
18
18
 
19
19
  #Windows Azure (WAZ) gem at http://github.com/johnnyhalife/waz-storage
20
- require 'waz-blobs'
21
20
  require 'deltacloud/base_driver'
21
+ require 'waz-blobs'
22
+
22
23
  module Deltacloud
23
24
  module Drivers
24
25
  module Azure
@@ -46,6 +47,9 @@ class AzureDriver < Deltacloud::BaseDriver
46
47
  # Create bucket
47
48
  #--
48
49
  def create_bucket(credentials, name, opts)
50
+ #for whatever reason, bucket names MUST be lowercase...
51
+ #http://msdn.microsoft.com/en-us/library/dd135715.aspx
52
+ name.downcase!
49
53
  bucket = nil
50
54
  azure_connect(credentials)
51
55
  safely do
@@ -87,6 +91,33 @@ class AzureDriver < Deltacloud::BaseDriver
87
91
  yield WAZ::Blobs::Container.find(bucket_id)[blob_id].value
88
92
  end
89
93
 
94
+ #--
95
+ # Create Blob
96
+ #--
97
+ def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
98
+ azure_connect(credentials)
99
+ #get a handle to the bucket in order to put there
100
+ the_bucket = WAZ::Blobs::Container.find(bucket_id)
101
+ the_bucket.store(blob_id, blob_data[:tempfile], blob_data[:type])
102
+ Blob.new( { :id => blob_id,
103
+ :bucket => bucket_id,
104
+ :content_lengh => blob_data[:tempfile].length,
105
+ :content_type => blob_data[:type],
106
+ :last_modified => ''
107
+ } )
108
+ end
109
+
110
+ #--
111
+ # Delete Blob
112
+ #--
113
+ def delete_blob(credentials, bucket_id, blob_id, opts=nil)
114
+ azure_connect(credentials)
115
+ #get a handle to bucket and blob, and destroy!
116
+ the_bucket = WAZ::Blobs::Container.find(bucket_id)
117
+ the_blob = the_bucket[blob_id]
118
+ the_blob.destroy!
119
+ end
120
+
90
121
  private
91
122
 
92
123
  def azure_connect(credentials)
@@ -1,5 +1,4 @@
1
- #
2
- # Copyright (C) 2010 Red Hat, Inc.
1
+ # Copyright (C) 2009, 2010 Red Hat, Inc.
3
2
  #
4
3
  # Licensed to the Apache Software Foundation (ASF) under one or more
5
4
  # contributor license agreements. See the NOTICE file distributed with
@@ -41,11 +40,12 @@ module Deltacloud
41
40
 
42
41
  feature :instances, :user_data
43
42
  feature :instances, :authentication_key
44
- feature :instances, :public_ip
45
43
  feature :instances, :security_group
46
44
  feature :images, :owner_id
47
45
  feature :buckets, :bucket_location
48
46
 
47
+ DEFAULT_REGION = 'us-east-1'
48
+
49
49
  define_hardware_profile('t1.micro') do
50
50
  cpu 1
51
51
  memory 0.63 * 1024
@@ -121,14 +121,6 @@ module Deltacloud
121
121
  stopped.to( :finish ) .automatically
122
122
  end
123
123
 
124
- def valid_credentials?(credentials)
125
- # FIXME: We need to do this call to determine if
126
- # EC2 is working with given credentials. There is no
127
- # other way to check, if given credentials are valid or not.
128
- realms = realms(credentials) rescue false
129
- return realms ? true : false
130
- end
131
-
132
124
  def images(credentials, opts={})
133
125
  ec2 = new_client(credentials)
134
126
  img_arr = []
@@ -168,6 +160,16 @@ module Deltacloud
168
160
  inst_arr = ec2.describe_instances.collect do |instance|
169
161
  convert_instance(instance) if instance
170
162
  end.flatten
163
+ tags = ec2.describe_tags(
164
+ 'Filter.1.Name' => 'resource-type', 'Filter.1.Value' => 'instance'
165
+ )
166
+ inst_arr.each do |inst|
167
+ name_tag = tags.select { |t| (t[:aws_resource_id] == inst.id) and t[:aws_key] == 'name' }
168
+ unless name_tag.empty?
169
+ inst.name = name_tag.first[:aws_value]
170
+ end
171
+ end
172
+ delete_unused_tags(credentials, inst_arr.collect {|inst| inst.id})
171
173
  end
172
174
  inst_arr = filter_on( inst_arr, :id, opts )
173
175
  filter_on( inst_arr, :state, opts )
@@ -183,8 +185,8 @@ module Deltacloud
183
185
  instance_options.merge!(:group_ids => opts[:security_group]) if opts[:security_group]
184
186
  safely do
185
187
  new_instance = convert_instance(ec2.launch_instances(image_id, instance_options).first)
186
- if opts[:public_ip]
187
- ec2.associate_address(new_instance.id, opts[:public_ip])
188
+ if opts[:name]
189
+ tag_instance(credentials, new_instance, opts[:name])
188
190
  end
189
191
  new_instance
190
192
  end
@@ -202,7 +204,9 @@ module Deltacloud
202
204
  def destroy_instance(credentials, instance_id)
203
205
  ec2 = new_client(credentials)
204
206
  puts "Terminating instance #{instance_id}"
207
+ instance_id = instance_id
205
208
  if ec2.terminate_instances([instance_id])
209
+ untag_instance(credentials, instance_id)
206
210
  instance(credentials, instance_id)
207
211
  else
208
212
  raise Deltacloud::BackendError.new(500, "Instance", "Instance cannot be terminated", "")
@@ -221,10 +225,6 @@ module Deltacloud
221
225
  end
222
226
  end
223
227
 
224
- def key(credentials, opts={})
225
- keys(credentials, :id => opts[:id]).first
226
- end
227
-
228
228
  def create_key(credentials, opts={})
229
229
  ec2 = new_client(credentials)
230
230
  safely do
@@ -319,14 +319,18 @@ module Deltacloud
319
319
  #--
320
320
  def delete_blob(credentials, bucket_id, blob_id, opts=nil)
321
321
  s3_client = new_client(credentials, :s3)
322
- s3_client.interface.delete(bucket_id, blob_id)
322
+ safely do
323
+ s3_client.interface.delete(bucket_id, blob_id)
324
+ end
323
325
  end
324
326
 
325
327
 
326
328
  def blob_data(credentials, bucket_id, blob_id, opts)
327
329
  s3_client = new_client(credentials, :s3)
328
- s3_client.interface.get(bucket_id, blob_id) do |chunk|
329
- yield chunk
330
+ safely do
331
+ s3_client.interface.get(bucket_id, blob_id) do |chunk|
332
+ yield chunk
333
+ end
330
334
  end
331
335
  end
332
336
 
@@ -401,12 +405,82 @@ module Deltacloud
401
405
  end
402
406
  end
403
407
 
408
+ def valid_credentials?(credentials)
409
+ retval = true
410
+ begin
411
+ realms(credentials)
412
+ rescue Deltacloud::BackendError
413
+ retval = false
414
+ end
415
+ retval
416
+ end
417
+
404
418
  private
405
419
 
406
420
  def new_client(credentials, type = :ec2)
407
- case type
408
- when :ec2 then Aws::Ec2.new(credentials.user, credentials.password)
409
- when :s3 then Aws::S3.new(credentials.user, credentials.password)
421
+ klass = case type
422
+ when :elb then Aws::Elb
423
+ when :ec2 then Aws::Ec2
424
+ when :s3 then Aws::S3
425
+ end
426
+ klass.new(credentials.user, credentials.password, :server => endpoint_for_service(type))
427
+ end
428
+
429
+ DEFAULT_SERVICE_ENDPOINTS = {
430
+ 'ec2' => {
431
+ 'ap-southeast-1' => 'ec2.ap-southeast-1.amazonaws.com',
432
+ 'eu-west-1' => 'ec2.eu-west-1.amazonaws.com',
433
+ 'us-east-1' => 'ec2.us-east-1.amazonaws.com',
434
+ 'us-west-1' => 'ec2.us-west-1.amazonaws.com'
435
+ },
436
+
437
+ 'elb' => {
438
+ 'ap-southeast-1' => 'elasticloadbalancing.ap-southeast-1.amazonaws.com',
439
+ 'eu-west-1' => 'elasticloadbalancing.eu-west-1.amazonaws.com',
440
+ 'us-east-1' => 'elasticloadbalancing.us-east-1.amazonaws.com',
441
+ 'us-west-1' => 'elasticloadbalancing.us-west-1.amazonaws.com'
442
+ },
443
+
444
+ 's3' => {
445
+ 'ap-southeast-1' => 's3.amazonaws.com',
446
+ 'eu-west-1' => 's3.amazonaws.com',
447
+ 'us-east-1' => 's3.amazonaws.com',
448
+ 'us-west-1' => 's3.amazonaws.com'
449
+ }
450
+ }
451
+
452
+ def endpoint_for_service(service)
453
+ endpoint = (Thread.current[:provider] || ENV['API_PROVIDER'] || DEFAULT_REGION)
454
+ # return the endpoint if it does not map to a default endpoint, allowing
455
+ # the endpoint to be a full hostname instead of a region.
456
+ DEFAULT_SERVICE_ENDPOINTS[service.to_s][endpoint] || endpoint
457
+ end
458
+
459
+ def tag_instance(credentials, instance, name)
460
+ ec2 = new_client(credentials)
461
+ safely do
462
+ ec2.create_tag(instance.id, 'name', name)
463
+ end
464
+ end
465
+
466
+ def untag_instance(credentials, instance_id)
467
+ ec2 = new_client(credentials)
468
+ safely do
469
+ ec2.delete_tag(instance_id, 'name')
470
+ end
471
+ end
472
+
473
+ def delete_unused_tags(credentials, inst_ids)
474
+ ec2 = new_client(credentials)
475
+ tags = []
476
+ safely do
477
+ tags = ec2.describe_tags('Filter.1.Name' => 'resource-type', 'Filter.1.Value' => 'instance')
478
+ tags.collect! { |t| t[:aws_resource_id] }
479
+ inst_ids.each do |inst_id|
480
+ unless tags.include?(inst_id)
481
+ ec2.delete_tag(inst_id, 'name')
482
+ end
483
+ end
410
484
  end
411
485
  end
412
486
 
@@ -425,6 +499,16 @@ module Deltacloud
425
499
  )
426
500
  end
427
501
 
502
+ def convert_object(s3_object)
503
+ Blob.new(
504
+ :id => s3_object.name,
505
+ :bucket => s3_object.bucket.name.to_s,
506
+ :content_length => s3_object.headers['content-length'],
507
+ :content_type => s3_object.headers['content-type'],
508
+ :last_modified => s3_object.last_modified
509
+ )
510
+ end
511
+
428
512
  def convert_realm(realm)
429
513
  Realm.new(
430
514
  :id => realm[:zone_name],