deltacloud-core 0.0.6 → 0.0.7

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.
@@ -13,6 +13,8 @@ require 'deltacloud/models/key'
13
13
  require 'deltacloud/models/instance_profile'
14
14
  require 'deltacloud/models/storage_snapshot'
15
15
  require 'deltacloud/models/storage_volume'
16
+ require 'deltacloud/models/bucket'
17
+ require 'deltacloud/models/blob'
16
18
 
17
19
  require 'deltacloud/validation'
18
20
  require 'deltacloud/helpers'
@@ -185,6 +185,36 @@ module Deltacloud
185
185
  []
186
186
  end
187
187
 
188
+ def buckets(credentials, opts = nil)
189
+ #list of buckets belonging to account
190
+ []
191
+ end
192
+
193
+ 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)
204
+ end
205
+
206
+ def blobs(credentials, opts = nil)
207
+ []
208
+ end
209
+
210
+ def blob(credentials, opts = nil)
211
+ list = blobs(credentials, opts)
212
+ return list.first unless list.empty?
213
+ end
214
+
215
+ def blob_data(credentials, bucket_id, blob_id, opts)
216
+ end
217
+
188
218
  def filter_on(collection, attribute, opts)
189
219
  return collection if opts.nil?
190
220
  return collection if opts[attribute].nil?
@@ -162,5 +162,12 @@ module Deltacloud
162
162
  description "Size instances according to changes to a hardware profile"
163
163
  # The parameters are filled in from the hardware profiles
164
164
  end
165
+
166
+ declare_feature :buckets, :bucket_location do
167
+ description "Take extra location parameter for Bucket creation (e.g. S3, 'eu' or 'us-west-1')"
168
+ operation :create do
169
+ param :location, :string, :optional
170
+ end
171
+ end
165
172
  end
166
173
  end
@@ -3,6 +3,19 @@ require 'deltacloud/method_serializer'
3
3
  # Create 'mock' version of original driver client/gem:
4
4
 
5
5
  module Mock
6
+
7
+ class S3 < RightAws::S3
8
+ include MethodSerializer::Cache
9
+
10
+ def self.cached_methods
11
+ [
12
+ :buckets
13
+ ]
14
+ end
15
+
16
+ MethodSerializer::Cache::wrap_methods(self, :cache_dir => File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'tests', 'ec2', 'support'))
17
+ end
18
+
6
19
  class EC2 < AWS::EC2::Base
7
20
 
8
21
  include MethodSerializer::Cache
@@ -29,6 +42,7 @@ end
29
42
  # Replace original client with mock client
30
43
  Deltacloud::Drivers::EC2::EC2Driver.class_eval do
31
44
  alias_method :original_new_client, :new_client
45
+ alias_method :original_s3_client, :s3_client
32
46
 
33
47
  def new_client(credentials, opts={})
34
48
  Mock::EC2.new(
@@ -37,4 +51,8 @@ Deltacloud::Drivers::EC2::EC2Driver.class_eval do
37
51
  )
38
52
  end
39
53
 
54
+ def s3_client(credentials)
55
+ Mock::S3.new(credentials.user, credentials.password)
56
+ end
57
+
40
58
  end
@@ -0,0 +1,127 @@
1
+ #
2
+ # Copyright (C) 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
+
19
+ #Windows Azure (WAZ) gem at http://github.com/johnnyhalife/waz-storage
20
+ require 'waz-blobs'
21
+ require 'deltacloud/base_driver'
22
+ module Deltacloud
23
+ module Drivers
24
+ module Azure
25
+
26
+ class AzureDriver < Deltacloud::BaseDriver
27
+
28
+ def supported_collections; [:buckets]
29
+ end
30
+
31
+ #--
32
+ # Buckets
33
+ #--
34
+ def buckets(credentials, opts)
35
+ buckets = []
36
+ azure_connect(credentials)
37
+ safely do
38
+ WAZ::Blobs::Container.list.each do |waz_container|
39
+ buckets << convert_container(waz_container)
40
+ end
41
+ end
42
+ buckets = filter_on(buckets, :id, opts)
43
+ end
44
+
45
+ #--
46
+ # Create bucket
47
+ #--
48
+ def create_bucket(credentials, name, opts)
49
+ bucket = nil
50
+ azure_connect(credentials)
51
+ safely do
52
+ waz_container = WAZ::Blobs::Container.create(name)
53
+ bucket = convert_container(waz_container)
54
+ end
55
+ bucket
56
+ end
57
+
58
+ #--
59
+ # Delete bucket
60
+ #--
61
+ def delete_bucket(credentials, name, opts)
62
+ azure_connect(credentials)
63
+ safely do
64
+ WAZ::Blobs::Container.find(name).destroy!
65
+ end
66
+ end
67
+
68
+ #--
69
+ # Blobs
70
+ #--
71
+ def blobs(credentials, opts)
72
+ blob_list = []
73
+ azure_connect(credentials)
74
+ safely do
75
+ the_bucket = WAZ::Blobs::Container.find(opts['bucket'])
76
+ the_bucket.blobs.each do |waz_blob|
77
+ blob_list << convert_blob(waz_blob)
78
+ end
79
+ end
80
+ blob_list = filter_on(blob_list, :id, opts)
81
+ blob_list
82
+ end
83
+
84
+ def blob_data(credentials, bucket_id, blob_id, opts)
85
+ azure_connect(credentials)
86
+ # WAZ get blob data methods cant accept blocks for 'streaming'... FIXME
87
+ yield WAZ::Blobs::Container.find(bucket_id)[blob_id].value
88
+ end
89
+
90
+ private
91
+
92
+ def azure_connect(credentials)
93
+ options = {:account_name => credentials.user, :access_key => credentials.password}
94
+ safely do
95
+ WAZ::Storage::Base.establish_connection!(options)
96
+ end
97
+ end
98
+
99
+ def convert_container(waz_container)
100
+ blob_list = []
101
+ waz_container.blobs.each do |blob|
102
+ blob_list << blob.name
103
+ end
104
+ Bucket.new({ :id => waz_container.name,
105
+ :name => waz_container.name,
106
+ :size => blob_list.size,
107
+ :blob_list => blob_list
108
+ })
109
+ end
110
+
111
+ def convert_blob(waz_blob)
112
+ url = waz_blob.url.split('/')
113
+ bucket = url[url.length-2] #FIXME
114
+ Blob.new({ :id => waz_blob.name,
115
+ :bucket => bucket,
116
+ :content_length => waz_blob.metadata[:content_length],
117
+ :content_type => waz_blob.metadata[:content_type],
118
+ :last_modified => waz_blob.metadata[:last_modified]
119
+ })
120
+ end
121
+
122
+
123
+ end
124
+
125
+ end #module Azure
126
+ end #module Drivers
127
+ end #module Deltacloud
@@ -18,7 +18,9 @@
18
18
 
19
19
 
20
20
  require 'deltacloud/base_driver'
21
+ require 'active_support'
21
22
  require 'AWS'
23
+ require 'right_aws'
22
24
 
23
25
  class Instance
24
26
  attr_accessor :keyname
@@ -36,12 +38,13 @@ module Deltacloud
36
38
  class EC2Driver < Deltacloud::BaseDriver
37
39
 
38
40
  def supported_collections
39
- DEFAULT_COLLECTIONS + [ :keys ]
41
+ DEFAULT_COLLECTIONS + [ :keys, :buckets ]
40
42
  end
41
43
 
42
44
  feature :instances, :user_data
43
45
  feature :instances, :authentication_key
44
46
  feature :images, :owner_id
47
+ feature :buckets, :bucket_location
45
48
 
46
49
  define_hardware_profile('m1.small') do
47
50
  cpu 1
@@ -201,7 +204,7 @@ class EC2Driver < Deltacloud::BaseDriver
201
204
  # at this point, the action has succeeded but our follow-up
202
205
  # "describe_instances" failed for some reason. Create a simple Instance
203
206
  # object with only the ID and new state in place
204
- state = backup.instancesSet.item.first.currentState.name
207
+ state = convert_state(backup.instancesSet.item.first.currentState.name)
205
208
  Instance.new( {
206
209
  :id => id,
207
210
  :state => state,
@@ -319,6 +322,83 @@ class EC2Driver < Deltacloud::BaseDriver
319
322
  return realms ? true : false
320
323
  end
321
324
 
325
+ #--
326
+ # Buckets
327
+ #-- get a list of your buckets from the s3 service
328
+ def buckets(credentials, opts)
329
+ buckets = []
330
+ safely do
331
+ s3_client = s3_client(credentials)
332
+ bucket_list = s3_client.buckets
333
+ bucket_list.each do |current|
334
+ buckets << convert_bucket(current)
335
+ end
336
+ end
337
+ buckets = filter_on(buckets, :id, opts)
338
+ buckets
339
+ end
340
+
341
+ #--
342
+ # Create bucket
343
+ #--
344
+ #valid values for bucket location: 'EU'|'us-west1'|'ap-southeast-1' - if you
345
+ #don't specify a location then by default buckets are created in 'us-east'
346
+ #[but if you *do* specify 'us-east' things blow up]
347
+ def create_bucket(credentials, name, opts={})
348
+ bucket = nil
349
+ safely do
350
+ begin
351
+ s3_client = s3_client(credentials)
352
+ bucket_location = opts['location']
353
+ if bucket_location
354
+ bucket = RightAws::S3::Bucket.create(s3_client, name, true, nil, :location => bucket_location)
355
+ else
356
+ bucket = RightAws::S3::Bucket.create(s3_client, name, true)
357
+ end #if
358
+ rescue RightAws::AwsError => e
359
+ raise e unless e.message =~ /BucketAlreadyExists/
360
+ raise Deltacloud::BackendError.new(409, e.class.to_s, e.message, e.backtrace)
361
+ end #begin
362
+ end #do
363
+ convert_bucket(bucket)
364
+ end
365
+
366
+ #--
367
+ # Delete_bucket
368
+ #--
369
+ def delete_bucket(credentials, name, opts={})
370
+ s3_client = s3_client(credentials)
371
+ safely do
372
+ s3_client.interface.delete_bucket(name)
373
+ end
374
+ end
375
+
376
+ #--
377
+ # Blobs
378
+ #--
379
+ def blobs(credentials, opts = nil)
380
+ s3_client = s3_client(credentials)
381
+ blobs = []
382
+ safely do
383
+ s3_bucket = s3_client.bucket(opts['bucket'])
384
+ s3_bucket.keys({}, true).each do |s3_object|
385
+ blobs << convert_object(s3_object)
386
+ end
387
+ end
388
+ blobs = filter_on(blobs, :id, opts)
389
+ blobs
390
+ end
391
+
392
+ #--
393
+ # Blob data
394
+ #--
395
+ def blob_data(credentials, bucket_id, blob_id, opts)
396
+ s3_client = s3_client(credentials)
397
+ s3_client.interface.get(bucket_id, blob_id) do |chunk|
398
+ yield chunk
399
+ end
400
+ end
401
+
322
402
  private
323
403
 
324
404
  def new_client(credentials)
@@ -360,9 +440,23 @@ class EC2Driver < Deltacloud::BaseDriver
360
440
  } )
361
441
  end
362
442
 
443
+ def convert_state(ec2_state)
444
+ case ec2_state
445
+ when "terminated"
446
+ "STOPPED"
447
+ when "stopped"
448
+ "STOPPED"
449
+ when "running"
450
+ "RUNNING"
451
+ when "pending"
452
+ "PENDING"
453
+ when "shutting-down"
454
+ "STOPPED"
455
+ end
456
+ end
457
+
363
458
  def convert_instance(ec2_instance, owner_id)
364
- state = ec2_instance['instanceState']['name'].upcase
365
- state_key = state.downcase.underscore.to_sym
459
+ state = convert_state(ec2_instance['instanceState']['name'])
366
460
  realm_id = ec2_instance['placement']['availabilityZone']
367
461
  (realm_id = nil ) if ( realm_id == '' )
368
462
  hwp_name = ec2_instance['instanceType']
@@ -404,6 +498,36 @@ class EC2Driver < Deltacloud::BaseDriver
404
498
  } )
405
499
  end
406
500
 
501
+ def s3_client(credentials)
502
+ safely do
503
+ s3_client = RightAws::S3.new(credentials.user, credentials.password)
504
+ end
505
+ end
506
+
507
+ def convert_bucket(s3_bucket)
508
+ #get blob list:
509
+ blob_list = []
510
+ s3_bucket.keys.each do |s3_object|
511
+ blob_list << s3_object.name
512
+ end
513
+ #can use AWS::S3::Owner.current.display_name or current.id
514
+ Bucket.new( { :id => s3_bucket.name,
515
+ :name => s3_bucket.name,
516
+ :size => s3_bucket.keys.length,
517
+ :blob_list => blob_list
518
+ }
519
+ )
520
+ end
521
+
522
+ def convert_object(s3_object)
523
+ Blob.new({ :id => s3_object.name,
524
+ :bucket => s3_object.bucket.name.to_s,
525
+ :content_length => s3_object.size,
526
+ :content_type => s3_object.content_type,
527
+ :last_modified => s3_object.last_modified
528
+ })
529
+ end
530
+
407
531
  def catched_exceptions_list
408
532
  {
409
533
  :auth => [ AWS::AuthFailure ],
@@ -285,6 +285,9 @@ class GogridDriver < Deltacloud::BaseDriver
285
285
  end
286
286
  prof = InstanceProfile.new("server", opts)
287
287
 
288
+ hwp_name = instance['image']['name']
289
+ state = convert_server_state(instance['state']['name'], instance['id'])
290
+
288
291
  Instance.new(
289
292
  # note that we use 'name' as the id here, because newly created instances
290
293
  # don't get a real ID until later on. The name is good enough; from
@@ -296,8 +299,8 @@ class GogridDriver < Deltacloud::BaseDriver
296
299
  :instance_profile => prof,
297
300
  :name => instance['name'],
298
301
  :realm_id => instance['ip']['datacenter']['id'],
299
- :state => convert_server_state(instance['state']['name'], instance['id']),
300
- :actions => instance_actions_for(convert_server_state(instance['state']['name'], instance['id'])),
302
+ :state => state,
303
+ :actions => instance_actions_for(state),
301
304
  :public_addresses => [ instance['ip']['ip'] ],
302
305
  :private_addresses => [],
303
306
  :username => instance['username'],
@@ -185,34 +185,28 @@ class MockDriver < Deltacloud::BaseDriver
185
185
  Instance.new( instance )
186
186
  end
187
187
 
188
- def start_instance(credentials, id)
188
+ def update_instance_state(credentials, id, state)
189
189
  instance_file = "#{@storage_root}/instances/#{id}.yml"
190
190
  instance_yml = YAML.load( File.read( instance_file ) )
191
- instance_yml[:state] = 'RUNNING'
191
+ instance_yml[:id] = id
192
+ instance_yml[:state] = state
193
+ instance_yml[:actions] = instance_actions_for( instance_yml[:state] )
192
194
  File.open( instance_file, 'w' ) do |f|
193
195
  f << YAML.dump( instance_yml )
194
196
  end
195
197
  Instance.new( instance_yml )
196
198
  end
197
199
 
200
+ def start_instance(credentials, id)
201
+ update_instance_state(credentials, id, 'RUNNING')
202
+ end
203
+
198
204
  def reboot_instance(credentials, id)
199
- instance_file = "#{@storage_root}/instances/#{id}.yml"
200
- instance_yml = YAML.load( File.read( instance_file ) )
201
- instance_yml[:state] = 'RUNNING'
202
- File.open( instance_file, 'w' ) do |f|
203
- f << YAML.dump( instance_yml )
204
- end
205
- Instance.new( instance_yml )
205
+ update_instance_state(credentials, id, 'RUNNING')
206
206
  end
207
207
 
208
208
  def stop_instance(credentials, id)
209
- instance_file = "#{@storage_root}/instances/#{id}.yml"
210
- instance_yml = YAML.load( File.read( instance_file ) )
211
- instance_yml[:state] = 'STOPPED'
212
- File.open( instance_file, 'w' ) do |f|
213
- f << YAML.dump( instance_yml )
214
- end
215
- Instance.new( instance_yml )
209
+ update_instance_state(credentials, id, 'STOPPED')
216
210
  end
217
211
 
218
212