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.
- data/deltacloud.rb +2 -0
- data/lib/deltacloud/base_driver/base_driver.rb +30 -0
- data/lib/deltacloud/base_driver/features.rb +7 -0
- data/lib/deltacloud/base_driver/mock_driver.rb +18 -0
- data/lib/deltacloud/drivers/azure/azure_driver.rb +127 -0
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +128 -4
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +5 -2
- data/lib/deltacloud/drivers/mock/mock_driver.rb +10 -16
- data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +1 -1
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +110 -11
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +7 -4
- data/lib/deltacloud/helpers/application_helper.rb +8 -1
- data/lib/deltacloud/helpers/blob_stream.rb +51 -0
- data/lib/deltacloud/models/blob.rb +26 -0
- data/lib/deltacloud/models/bucket.rb +24 -0
- data/lib/drivers.rb +1 -0
- data/lib/sinatra/respond_to.rb +147 -181
- data/lib/sinatra/respond_to_old.rb +253 -0
- data/server.rb +104 -22
- data/tests/instance_states_test.rb +1 -2
- data/tests/instances_test.rb +12 -9
- data/tests/url_for_test.rb +1 -1
- data/views/blobs/show.html.haml +20 -0
- data/views/blobs/show.xml.haml +7 -0
- data/views/buckets/index.html.haml +33 -0
- data/views/buckets/index.xml.haml +10 -0
- data/views/buckets/new.html.haml +13 -0
- data/views/buckets/show.html.haml +19 -0
- data/views/buckets/show.xml.haml +8 -0
- data/views/instance_states/show.html.haml +1 -1
- data/views/instance_states/{show.gv.erb → show.png.erb} +0 -0
- metadata +61 -33
data/deltacloud.rb
CHANGED
@@ -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']
|
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 =>
|
300
|
-
:actions => instance_actions_for(
|
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
|
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[:
|
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
|
-
|
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
|
-
|
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
|
|