steamcannon-deltacloud-core 0.0.7.1-java
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/COPYING +176 -0
- data/Rakefile +106 -0
- data/bin/deltacloudd +120 -0
- data/config.ru +5 -0
- data/deltacloud.rb +20 -0
- data/lib/deltacloud/base_driver/base_driver.rb +259 -0
- data/lib/deltacloud/base_driver/features.rb +173 -0
- data/lib/deltacloud/base_driver/mock_driver.rb +58 -0
- data/lib/deltacloud/base_driver.rb +20 -0
- data/lib/deltacloud/drivers/azure/azure_driver.rb +127 -0
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +580 -0
- data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +170 -0
- data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +50 -0
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +343 -0
- data/lib/deltacloud/drivers/gogrid/test.rb +13 -0
- data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob1.yml +5 -0
- data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob2.yml +5 -0
- data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob3.yml +5 -0
- data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob4.yml +5 -0
- data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob5.yml +5 -0
- data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +2 -0
- data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +2 -0
- data/lib/deltacloud/drivers/mock/data/images/img1.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/images/img2.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/images/img3.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +16 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +9 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +9 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +6 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +6 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +6 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +356 -0
- data/lib/deltacloud/drivers/opennebula/cloud_client.rb +116 -0
- data/lib/deltacloud/drivers/opennebula/occi_client.rb +204 -0
- data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +241 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +130 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +290 -0
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +258 -0
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +85 -0
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +166 -0
- data/lib/deltacloud/drivers/terremark/terremark_driver.rb +295 -0
- data/lib/deltacloud/hardware_profile.rb +153 -0
- data/lib/deltacloud/helpers/application_helper.rb +122 -0
- data/lib/deltacloud/helpers/blob_stream.rb +51 -0
- data/lib/deltacloud/helpers/conversion_helper.rb +39 -0
- data/lib/deltacloud/helpers/hardware_profiles_helper.rb +35 -0
- data/lib/deltacloud/helpers.rb +5 -0
- data/lib/deltacloud/method_serializer.rb +85 -0
- data/lib/deltacloud/models/base_model.rb +59 -0
- data/lib/deltacloud/models/blob.rb +26 -0
- data/lib/deltacloud/models/bucket.rb +24 -0
- data/lib/deltacloud/models/image.rb +27 -0
- data/lib/deltacloud/models/instance.rb +38 -0
- data/lib/deltacloud/models/instance_profile.rb +48 -0
- data/lib/deltacloud/models/key.rb +35 -0
- data/lib/deltacloud/models/realm.rb +26 -0
- data/lib/deltacloud/models/storage_snapshot.rb +27 -0
- data/lib/deltacloud/models/storage_volume.rb +28 -0
- data/lib/deltacloud/state_machine.rb +84 -0
- data/lib/deltacloud/validation.rb +70 -0
- data/lib/drivers.rb +51 -0
- data/lib/sinatra/accept_media_types.rb +128 -0
- data/lib/sinatra/lazy_auth.rb +56 -0
- data/lib/sinatra/rabbit.rb +279 -0
- data/lib/sinatra/respond_to.rb +238 -0
- data/lib/sinatra/static_assets.rb +83 -0
- data/lib/sinatra/url_for.rb +53 -0
- data/public/favicon.ico +0 -0
- data/public/images/grid.png +0 -0
- data/public/images/logo-wide.png +0 -0
- data/public/images/rails.png +0 -0
- data/public/images/topbar-bg.png +0 -0
- data/public/javascripts/application.js +32 -0
- data/public/javascripts/jquery-1.4.2.min.js +154 -0
- data/public/stylesheets/compiled/application.css +613 -0
- data/public/stylesheets/compiled/ie.css +31 -0
- data/public/stylesheets/compiled/print.css +27 -0
- data/public/stylesheets/compiled/screen.css +456 -0
- data/server.rb +516 -0
- data/support/fedora/deltacloudd +68 -0
- data/support/fedora/rubygem-deltacloud-core.spec +91 -0
- data/tests/api_test.rb +37 -0
- data/tests/hardware_profiles_test.rb +120 -0
- data/tests/images_test.rb +111 -0
- data/tests/instance_states_test.rb +51 -0
- data/tests/instances_test.rb +222 -0
- data/tests/realms_test.rb +78 -0
- data/tests/url_for_test.rb +50 -0
- data/views/accounts/index.html.haml +11 -0
- data/views/accounts/show.html.haml +30 -0
- data/views/api/show.html.haml +15 -0
- data/views/api/show.xml.haml +5 -0
- 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/docs/collection.html.haml +37 -0
- data/views/docs/collection.xml.haml +14 -0
- data/views/docs/index.html.haml +15 -0
- data/views/docs/index.xml.haml +5 -0
- data/views/docs/operation.html.haml +31 -0
- data/views/docs/operation.xml.haml +10 -0
- data/views/errors/auth_exception.html.haml +8 -0
- data/views/errors/auth_exception.xml.haml +2 -0
- data/views/errors/backend_error.html.haml +19 -0
- data/views/errors/backend_error.xml.haml +8 -0
- data/views/errors/not_found.html.haml +6 -0
- data/views/errors/not_found.xml.haml +2 -0
- data/views/errors/validation_failure.html.haml +11 -0
- data/views/errors/validation_failure.xml.haml +7 -0
- data/views/hardware_profiles/index.html.haml +25 -0
- data/views/hardware_profiles/index.xml.haml +4 -0
- data/views/hardware_profiles/show.html.haml +19 -0
- data/views/hardware_profiles/show.xml.haml +18 -0
- data/views/images/index.html.haml +30 -0
- data/views/images/index.xml.haml +8 -0
- data/views/images/show.html.haml +21 -0
- data/views/images/show.xml.haml +5 -0
- data/views/instance_states/show.html.haml +31 -0
- data/views/instance_states/show.png.erb +45 -0
- data/views/instance_states/show.xml.haml +8 -0
- data/views/instances/index.html.haml +30 -0
- data/views/instances/index.xml.haml +21 -0
- data/views/instances/new.html.haml +55 -0
- data/views/instances/show.html.haml +43 -0
- data/views/instances/show.xml.haml +49 -0
- data/views/keys/index.html.haml +26 -0
- data/views/keys/index.xml.haml +4 -0
- data/views/keys/new.html.haml +8 -0
- data/views/keys/show.html.haml +22 -0
- data/views/keys/show.xml.haml +20 -0
- data/views/layout.html.haml +26 -0
- data/views/realms/index.html.haml +29 -0
- data/views/realms/index.xml.haml +10 -0
- data/views/realms/show.html.haml +15 -0
- data/views/realms/show.xml.haml +9 -0
- data/views/root/index.html.haml +4 -0
- data/views/storage_snapshots/index.html.haml +20 -0
- data/views/storage_snapshots/index.xml.haml +9 -0
- data/views/storage_snapshots/show.html.haml +14 -0
- data/views/storage_snapshots/show.xml.haml +7 -0
- data/views/storage_volumes/index.html.haml +21 -0
- data/views/storage_volumes/index.xml.haml +23 -0
- data/views/storage_volumes/show.html.haml +20 -0
- data/views/storage_volumes/show.xml.haml +24 -0
- metadata +367 -0
data/server.rb
ADDED
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
require 'sinatra'
|
|
2
|
+
require 'deltacloud'
|
|
3
|
+
require 'drivers'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'sinatra/respond_to'
|
|
6
|
+
require 'sinatra/static_assets'
|
|
7
|
+
require 'sinatra/rabbit'
|
|
8
|
+
require 'sinatra/lazy_auth'
|
|
9
|
+
require 'erb'
|
|
10
|
+
require 'haml'
|
|
11
|
+
require 'open3'
|
|
12
|
+
require 'lib/deltacloud/helpers/blob_stream'
|
|
13
|
+
|
|
14
|
+
configure do
|
|
15
|
+
set :raise_errors => false
|
|
16
|
+
set :show_exceptions, false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
configure :development do
|
|
20
|
+
# So we can just use puts for logging
|
|
21
|
+
$stdout.sync = true
|
|
22
|
+
$stderr.sync = true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# You could use $API_HOST environment variable to change your hostname to
|
|
26
|
+
# whatever you want (eg. if you running API behind NAT)
|
|
27
|
+
HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
|
|
28
|
+
|
|
29
|
+
error Deltacloud::Validation::Failure do
|
|
30
|
+
report_error(400, "validation_failure")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
error Deltacloud::AuthException do
|
|
34
|
+
report_error(403, "auth_exception")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
error Deltacloud::BackendError do
|
|
38
|
+
report_error(500, "backend_error")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
Sinatra::Application.register Sinatra::RespondTo
|
|
42
|
+
|
|
43
|
+
# Redirect to /api
|
|
44
|
+
get '/' do redirect url_for('/api'); end
|
|
45
|
+
|
|
46
|
+
get '/api\/?' do
|
|
47
|
+
@version = 0.1
|
|
48
|
+
if params[:force_auth]
|
|
49
|
+
return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
|
|
50
|
+
end
|
|
51
|
+
respond_to do |format|
|
|
52
|
+
format.xml { haml :"api/show" }
|
|
53
|
+
format.json do
|
|
54
|
+
{ :api => {
|
|
55
|
+
:version => @version,
|
|
56
|
+
:driver => DRIVER,
|
|
57
|
+
:links => entry_points.collect { |l| { :rel => l[0], :href => l[1]} }
|
|
58
|
+
}
|
|
59
|
+
}.to_json
|
|
60
|
+
end
|
|
61
|
+
format.html { haml :"api/show" }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Rabbit DSL
|
|
66
|
+
|
|
67
|
+
collection :realms do
|
|
68
|
+
description <<END
|
|
69
|
+
Within a cloud provider a realm represents a boundary containing resources.
|
|
70
|
+
The exact definition of a realm is left to the cloud provider.
|
|
71
|
+
In some cases, a realm may represent different datacenters, different continents,
|
|
72
|
+
or different pools of resources within a single datacenter.
|
|
73
|
+
A cloud provider may insist that resources must all exist within a single realm in
|
|
74
|
+
order to cooperate. For instance, storage volumes may only be allowed to be mounted to
|
|
75
|
+
instances within the same realm.
|
|
76
|
+
END
|
|
77
|
+
|
|
78
|
+
operation :index do
|
|
79
|
+
description <<END
|
|
80
|
+
Operation will list all available realms. Realms can be filtered using
|
|
81
|
+
the "architecture" parameter.
|
|
82
|
+
END
|
|
83
|
+
param :id, :string
|
|
84
|
+
param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
|
|
85
|
+
control { filter_all(:realms) }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
#FIXME: It always shows whole list
|
|
89
|
+
operation :show do
|
|
90
|
+
description 'Show an realm identified by "id" parameter.'
|
|
91
|
+
param :id, :string, :required
|
|
92
|
+
control { show(:realm) }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
collection :images do
|
|
98
|
+
description <<END
|
|
99
|
+
An image is a platonic form of a machine. Images are not directly executable,
|
|
100
|
+
but are a template for creating actual instances of machines."
|
|
101
|
+
END
|
|
102
|
+
|
|
103
|
+
operation :index do
|
|
104
|
+
description <<END
|
|
105
|
+
The images collection will return a set of all images
|
|
106
|
+
available to the current use. Images can be filtered using the
|
|
107
|
+
"owner_id" and "architecture" parameters.
|
|
108
|
+
END
|
|
109
|
+
param :id, :string
|
|
110
|
+
param :architecture, :string, :optional
|
|
111
|
+
control { filter_all(:images) }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
operation :show do
|
|
115
|
+
description 'Show an image identified by "id" parameter.'
|
|
116
|
+
param :id, :string, :required
|
|
117
|
+
control { show(:image) }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
collection :instance_states do
|
|
123
|
+
description "The possible states of an instance, and how to traverse between them "
|
|
124
|
+
|
|
125
|
+
operation :index do
|
|
126
|
+
control do
|
|
127
|
+
@machine = driver.instance_state_machine
|
|
128
|
+
respond_to do |format|
|
|
129
|
+
format.xml { haml :'instance_states/show', :layout => false }
|
|
130
|
+
format.json do
|
|
131
|
+
out = []
|
|
132
|
+
@machine.states.each do |state|
|
|
133
|
+
transitions = state.transitions.collect do |t|
|
|
134
|
+
t.automatically? ? {:to => t.destination, :auto => 'true'} : {:to => t.destination, :action => t.action}
|
|
135
|
+
end
|
|
136
|
+
out << { :name => state, :transitions => transitions }
|
|
137
|
+
end
|
|
138
|
+
out.to_json
|
|
139
|
+
end
|
|
140
|
+
format.html { haml :'instance_states/show'}
|
|
141
|
+
format.gv { erb :"instance_states/show" }
|
|
142
|
+
format.png do
|
|
143
|
+
# Trick respond_to into looking up the right template for the
|
|
144
|
+
# graphviz file
|
|
145
|
+
format_backup = format
|
|
146
|
+
format(:gv)
|
|
147
|
+
gv = erb(:"instance_states/show")
|
|
148
|
+
format(format_backup)
|
|
149
|
+
png = ''
|
|
150
|
+
cmd = 'dot -Kdot -Gpad="0.2,0.2" -Gsize="5.0,8.0" -Gdpi="180" -Tpng'
|
|
151
|
+
Open3.popen3( cmd ) do |stdin, stdout, stderr|
|
|
152
|
+
stdin.write( gv )
|
|
153
|
+
stdin.close()
|
|
154
|
+
png = stdout.read
|
|
155
|
+
end
|
|
156
|
+
content_type 'image/png'
|
|
157
|
+
png
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
get "/api/instances/new" do
|
|
165
|
+
@instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
|
|
166
|
+
@image = driver.image( credentials, :id => params[:image_id] )
|
|
167
|
+
@hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
|
|
168
|
+
@realms = driver.realms(credentials)
|
|
169
|
+
respond_to do |format|
|
|
170
|
+
format.html { haml :"instances/new" }
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
collection :instances do
|
|
175
|
+
description <<END
|
|
176
|
+
An instance is a concrete machine realized from an image.
|
|
177
|
+
The images collection may be obtained by following the link from the primary entry-point."
|
|
178
|
+
END
|
|
179
|
+
|
|
180
|
+
operation :index do
|
|
181
|
+
description "List all instances."
|
|
182
|
+
param :id, :string, :optional
|
|
183
|
+
param :state, :string, :optional
|
|
184
|
+
control { filter_all(:instances) }
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
operation :show do
|
|
188
|
+
description 'Show an instance identified by "id" parameter.'
|
|
189
|
+
param :id, :string, :required
|
|
190
|
+
control { show(:instance) }
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
operation :create do
|
|
194
|
+
description "Create a new instance."
|
|
195
|
+
param :image_id, :string, :required
|
|
196
|
+
param :realm_id, :string, :optional
|
|
197
|
+
param :hwp_id, :string, :optional
|
|
198
|
+
control do
|
|
199
|
+
@image = driver.image(credentials, :id => params[:image_id])
|
|
200
|
+
instance = driver.create_instance(credentials, @image.id, params)
|
|
201
|
+
respond_to do |format|
|
|
202
|
+
format.xml do
|
|
203
|
+
response.status = 201 # Created
|
|
204
|
+
response['Location'] = instance_url(instance.id)
|
|
205
|
+
@instance = instance
|
|
206
|
+
haml :"instances/show"
|
|
207
|
+
end
|
|
208
|
+
format.html do
|
|
209
|
+
redirect instance_url(instance.id) if instance and instance.id
|
|
210
|
+
redirect instances_url
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
operation :reboot, :method => :post, :member => true do
|
|
217
|
+
description "Reboot a running instance."
|
|
218
|
+
param :id, :string, :required
|
|
219
|
+
control { instance_action(:reboot) }
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
operation :start, :method => :post, :member => true do
|
|
223
|
+
description "Start an instance."
|
|
224
|
+
param :id, :string, :required
|
|
225
|
+
control { instance_action(:start) }
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
operation :stop, :method => :post, :member => true do
|
|
229
|
+
description "Stop a running instance."
|
|
230
|
+
param :id, :string, :required
|
|
231
|
+
control { instance_action(:stop) }
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
operation :destroy do
|
|
235
|
+
description "Destroy an instance."
|
|
236
|
+
param :id, :string, :required
|
|
237
|
+
control { instance_action(:destroy) }
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
collection :hardware_profiles do
|
|
242
|
+
description <<END
|
|
243
|
+
A hardware profile represents a configuration of resources upon which a
|
|
244
|
+
machine may be deployed. It defines aspects such as local disk storage,
|
|
245
|
+
available RAM, and architecture. Each provider is free to define as many
|
|
246
|
+
(or as few) hardware profiles as desired.
|
|
247
|
+
END
|
|
248
|
+
|
|
249
|
+
operation :index do
|
|
250
|
+
description "List of available hardware profiles."
|
|
251
|
+
param :id, :string
|
|
252
|
+
param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
|
|
253
|
+
control do
|
|
254
|
+
@profiles = driver.hardware_profiles(credentials, params)
|
|
255
|
+
respond_to do |format|
|
|
256
|
+
format.xml { haml :'hardware_profiles/index' }
|
|
257
|
+
format.html { haml :'hardware_profiles/index' }
|
|
258
|
+
format.json { convert_to_json(:hardware_profile, @profiles) }
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
operation :show do
|
|
264
|
+
description "Show specific hardware profile."
|
|
265
|
+
param :id, :string, :required
|
|
266
|
+
control do
|
|
267
|
+
@profile = driver.hardware_profile(credentials, params[:id])
|
|
268
|
+
if @profile
|
|
269
|
+
respond_to do |format|
|
|
270
|
+
format.xml { haml :'hardware_profiles/show', :layout => false }
|
|
271
|
+
format.html { haml :'hardware_profiles/show' }
|
|
272
|
+
format.json { convert_to_json(:hardware_profile, @profile) }
|
|
273
|
+
end
|
|
274
|
+
else
|
|
275
|
+
report_error(404, 'not_found')
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
collection :storage_snapshots do
|
|
283
|
+
description "Storage snapshots description here"
|
|
284
|
+
|
|
285
|
+
operation :index do
|
|
286
|
+
description "List of storage snapshots."
|
|
287
|
+
param :id, :string
|
|
288
|
+
control { filter_all(:storage_snapshots) }
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
operation :show do
|
|
292
|
+
description "Show storage snapshot."
|
|
293
|
+
param :id, :string, :required
|
|
294
|
+
control { show(:storage_snapshot) }
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# get '/api/storage_volumes/new' do
|
|
299
|
+
# respond_to do |format|
|
|
300
|
+
# format.html { haml :"storage_volumes/new" }
|
|
301
|
+
# end
|
|
302
|
+
# end
|
|
303
|
+
|
|
304
|
+
collection :storage_volumes do
|
|
305
|
+
description "Storage volumes description here"
|
|
306
|
+
|
|
307
|
+
operation :index do
|
|
308
|
+
description "List of storage volumes."
|
|
309
|
+
param :id, :string
|
|
310
|
+
control { filter_all(:storage_volumes) }
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
operation :show do
|
|
314
|
+
description "Show storage volume."
|
|
315
|
+
param :id, :string, :required
|
|
316
|
+
control { show(:storage_volume) }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
operation :create do
|
|
320
|
+
description "Create new storage volume if backend supports them."
|
|
321
|
+
param :realm_id, :string, :required
|
|
322
|
+
param :capacity, :string, :required
|
|
323
|
+
control(:with_feature => :create_storage_volume) do
|
|
324
|
+
volume = driver.create_storage_volume(credentials, params)
|
|
325
|
+
respond_to do |format|
|
|
326
|
+
format.xml do
|
|
327
|
+
response.status = 201 # Created
|
|
328
|
+
response['Location'] = storage_volume_url(volume.id)
|
|
329
|
+
@storage_volume = volume
|
|
330
|
+
haml :"storage_volumes/show"
|
|
331
|
+
end
|
|
332
|
+
format.html do
|
|
333
|
+
redirect storage_volume_url(volume.id) if volume and volume.id
|
|
334
|
+
redirect storage_volumes_url
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
operation :destroy do
|
|
341
|
+
param :id, :string, :required
|
|
342
|
+
control :with_feature => :destroy_storage_volume do
|
|
343
|
+
driver.destroy_storage_volume(credentials, params[:id])
|
|
344
|
+
redirect(storage_volumes_url)
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
operation :attach, :method => :post, :member => true do
|
|
349
|
+
param :id, :string, :required
|
|
350
|
+
param :instance_id, :string, :required
|
|
351
|
+
param :device, :string, :required
|
|
352
|
+
|
|
353
|
+
control :with_feature => :attach_storage_volume do
|
|
354
|
+
volume = driver.attach_storage_volume(credentials, params)
|
|
355
|
+
respond_to do |format|
|
|
356
|
+
format.xml do
|
|
357
|
+
response.status = 200
|
|
358
|
+
response['Location'] = storage_volume_url(volume.id)
|
|
359
|
+
@storage_volume = volume
|
|
360
|
+
haml :"storage_volumes/show"
|
|
361
|
+
end
|
|
362
|
+
format.html do
|
|
363
|
+
redirect storage_volume_url(volume.id)
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
operation :detach, :method => :post, :member => true do
|
|
371
|
+
param :id, :string, :required
|
|
372
|
+
|
|
373
|
+
control :with_feature => :detach_storage_volume do
|
|
374
|
+
volume = driver.detach_storage_volume(credentials, params[:id])
|
|
375
|
+
respond_to do |format|
|
|
376
|
+
format.xml do
|
|
377
|
+
response.status = 200
|
|
378
|
+
response['Location'] = storage_volume_url(volume.id)
|
|
379
|
+
@storage_volume = volume
|
|
380
|
+
haml :"storage_volumes/show"
|
|
381
|
+
end
|
|
382
|
+
format.html do
|
|
383
|
+
redirect storage_volume_url(volume.id)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
get '/api/keys/new' do
|
|
392
|
+
respond_to do |format|
|
|
393
|
+
format.html { haml :"keys/new" }
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
collection :keys do
|
|
398
|
+
description "Instance authentication credentials."
|
|
399
|
+
|
|
400
|
+
operation :index do
|
|
401
|
+
description "List all available credentials which could be used for instance authentication."
|
|
402
|
+
control do
|
|
403
|
+
filter_all :keys
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
operation :show do
|
|
408
|
+
description "Show details about given instance credential."
|
|
409
|
+
param :id, :string, :required
|
|
410
|
+
control { show :key }
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
operation :create do
|
|
414
|
+
description "Create a new instance credential if backend supports this."
|
|
415
|
+
param :name, :string, :required
|
|
416
|
+
control do
|
|
417
|
+
unless driver.respond_to?(:create_key)
|
|
418
|
+
raise Deltacloud::BackendFeatureUnsupported.new('501',
|
|
419
|
+
'Creating instance credentials is not supported in backend')
|
|
420
|
+
end
|
|
421
|
+
@key = driver.create_key(credentials, { :key_name => params[:name] })
|
|
422
|
+
respond_to do |format|
|
|
423
|
+
format.html { haml :"keys/show" }
|
|
424
|
+
format.xml { haml :"keys/show" }
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
operation :destroy do
|
|
430
|
+
description "Destroy given instance credential if backend supports this."
|
|
431
|
+
param :id, :string, :required
|
|
432
|
+
control do
|
|
433
|
+
unless driver.respond_to?(:destroy_key)
|
|
434
|
+
raise Deltacloud::BackendFeatureUnsupported.new('501',
|
|
435
|
+
'Creating instance credentials is not supported in backend')
|
|
436
|
+
end
|
|
437
|
+
driver.destroy_key(credentials, { :key_name => params[:id]})
|
|
438
|
+
redirect(keys_url)
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
get '/api/buckets/:bucket/:blob' do
|
|
445
|
+
@blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
|
|
446
|
+
if @blob
|
|
447
|
+
respond_to do |format|
|
|
448
|
+
format.html { haml :"blobs/show" }
|
|
449
|
+
format.xml { haml :"blobs/show" }
|
|
450
|
+
format.json { convert_to_json(blobs, @blob) }
|
|
451
|
+
end
|
|
452
|
+
else
|
|
453
|
+
report_error(404, 'not_found')
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
get '/api/buckets/new' do
|
|
458
|
+
respond_to do |format|
|
|
459
|
+
format.html { haml :"buckets/new" }
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
get '/api/buckets/:bucket/:blob/content' do
|
|
465
|
+
@blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
|
|
466
|
+
params['content_length'] = @blob.content_length
|
|
467
|
+
params['content_type'] = @blob.content_type
|
|
468
|
+
BlobStream.call(env, credentials, params)
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
collection :buckets do
|
|
472
|
+
description "Cloud Storage buckets - aka buckets|directories|folders"
|
|
473
|
+
|
|
474
|
+
operation :index do
|
|
475
|
+
description "List buckets associated with this account"
|
|
476
|
+
param :id, :string
|
|
477
|
+
param :name, :string
|
|
478
|
+
param :size, :string
|
|
479
|
+
control { filter_all(:buckets) }
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
operation :show do
|
|
483
|
+
description "Show bucket"
|
|
484
|
+
param :id, :string
|
|
485
|
+
control { show(:bucket) }
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
operation :create do
|
|
489
|
+
description "Create a new bucket (POST /api/buckets)"
|
|
490
|
+
param :name, :string, :required
|
|
491
|
+
control do
|
|
492
|
+
@bucket = driver.create_bucket(credentials, params[:name], params)
|
|
493
|
+
respond_to do |format|
|
|
494
|
+
format.xml do
|
|
495
|
+
response.status = 201 # Created
|
|
496
|
+
response['Location'] = bucket_url(@bucket.id)
|
|
497
|
+
haml :"buckets/show"
|
|
498
|
+
end
|
|
499
|
+
format.html do
|
|
500
|
+
redirect bucket_url(@bucket.id) if @bucket and @bucket.id
|
|
501
|
+
redirect buckets_url
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
operation :destroy do
|
|
508
|
+
description "Delete a bucket by name - bucket must be empty"
|
|
509
|
+
param :id, :string, :required
|
|
510
|
+
control do
|
|
511
|
+
driver.delete_bucket(credentials, params[:id], params)
|
|
512
|
+
redirect(buckets_url)
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
require 'thin'
|
|
6
|
+
|
|
7
|
+
options = {
|
|
8
|
+
:env => 'production'
|
|
9
|
+
}
|
|
10
|
+
optparse = OptionParser.new do |opts|
|
|
11
|
+
|
|
12
|
+
opts.banner = <<BANNER
|
|
13
|
+
Usage:
|
|
14
|
+
deltacloudd -i <driver> [options]
|
|
15
|
+
|
|
16
|
+
Options:
|
|
17
|
+
BANNER
|
|
18
|
+
opts.on( '-i', '--driver DRIVER', 'Driver to use') do |driver|
|
|
19
|
+
ENV["API_DRIVER"] = driver
|
|
20
|
+
end
|
|
21
|
+
opts.on( '-r', '--hostname HOSTNAME',
|
|
22
|
+
'Bind to HOST address (default: localhost)') do |host|
|
|
23
|
+
ENV["API_HOST"] = host
|
|
24
|
+
end
|
|
25
|
+
opts.on( '-p', '--port PORT', 'Use PORT (default: 3001)') do |port|
|
|
26
|
+
ENV["API_PORT"] = port
|
|
27
|
+
end
|
|
28
|
+
opts.on( '-e', '--env ENV', 'Environment (default: "development")') { |env| options[:env] = env }
|
|
29
|
+
opts.on( '-h', '--help', '') { options[:help] = true }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
optparse.parse!
|
|
33
|
+
|
|
34
|
+
if options[:help]
|
|
35
|
+
puts optparse
|
|
36
|
+
exit(0)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
unless ENV["API_DRIVER"]
|
|
40
|
+
puts "You need to specify a driver to use (-i <driver>)"
|
|
41
|
+
exit(1)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
ENV["API_HOST"] = "localhost" unless ENV["API_HOST"]
|
|
45
|
+
ENV["API_PORT"] = "3001" unless ENV["API_PORT"]
|
|
46
|
+
|
|
47
|
+
dirname="#{File.dirname(__FILE__)}/.."
|
|
48
|
+
|
|
49
|
+
argv_opts = ARGV.clone
|
|
50
|
+
argv_opts << ['start'] unless Thin::Runner.commands.include?(options[0])
|
|
51
|
+
argv_opts << ['--address', ENV["API_HOST"] ]
|
|
52
|
+
argv_opts << ['--port', ENV["API_PORT"] ]
|
|
53
|
+
argv_opts << ['--rackup', 'config.ru' ]
|
|
54
|
+
argv_opts << ['--chdir', dirname ]
|
|
55
|
+
argv_opts << ['-e', options[:env] ]
|
|
56
|
+
argv_opts << ['--threaded', '-D', '--stats', '/stats']
|
|
57
|
+
|
|
58
|
+
argv_opts.flatten!
|
|
59
|
+
|
|
60
|
+
puts "Starting Deltacloud API :: #{ENV["API_DRIVER"]} :: http://#{ENV["API_HOST"]}:#{ENV["API_PORT"]}/api"
|
|
61
|
+
puts
|
|
62
|
+
|
|
63
|
+
thin = Thin::Runner.new(argv_opts)
|
|
64
|
+
begin
|
|
65
|
+
thin.run!
|
|
66
|
+
rescue Exception => e
|
|
67
|
+
puts "ERROR: #{e.message}"
|
|
68
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
%global ruby_sitelib %(ruby -rrbconfig -e "puts Config::CONFIG['sitelibdir']")
|
|
2
|
+
%global gemdir %(ruby -rubygems -e 'puts Gem::dir' 2>/dev/null)
|
|
3
|
+
%global gemname deltacloud-core
|
|
4
|
+
%global geminstdir %{gemdir}/gems/%{gemname}-%{version}
|
|
5
|
+
|
|
6
|
+
Summary: Deltacloud REST API
|
|
7
|
+
Name: rubygem-%{gemname}
|
|
8
|
+
Version: 0.0.1
|
|
9
|
+
Release: 2%{?dist}
|
|
10
|
+
Group: Development/Languages
|
|
11
|
+
License: ASL 2.0 and MIT
|
|
12
|
+
URL: http://www.deltacloud.org
|
|
13
|
+
Source0: http://gems.rubyforge.org/gems/%{gemname}-%{version}.gem
|
|
14
|
+
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
|
15
|
+
Requires: rubygems
|
|
16
|
+
Requires: ruby(abi) = 1.8
|
|
17
|
+
Requires: rubygem(eventmachine) >= 0.12.10
|
|
18
|
+
Requires: rubygem(haml) >= 2.2.17
|
|
19
|
+
Requires: rubygem(sinatra) >= 0.9.4
|
|
20
|
+
Requires: rubygem(rack) >= 1.0.0
|
|
21
|
+
Requires: rubygem(thin) >= 1.2.5
|
|
22
|
+
Requires: rubygem(builder) >= 2.1.2
|
|
23
|
+
Requires: rubygem(json) >= 1.2.3
|
|
24
|
+
BuildRequires: ruby-json >= 1.1.9
|
|
25
|
+
BuildRequires: rubygem(rake) >= 0.8.7
|
|
26
|
+
BuildRequires: rubygem(rack-test) >= 0.4.0
|
|
27
|
+
BuildRequires: rubygem(cucumber) >= 0.4.0
|
|
28
|
+
BuildRequires: rubygem(rcov) >= 0.9.6
|
|
29
|
+
BuildRequires: rubygems
|
|
30
|
+
BuildRequires: ruby(abi) = 1.8
|
|
31
|
+
BuildArch: noarch
|
|
32
|
+
Provides: rubygem(%{gemname}) = %{version}
|
|
33
|
+
|
|
34
|
+
%description
|
|
35
|
+
The Deltacloud API is built as a service-based REST API.
|
|
36
|
+
You do not directly link a Deltacloud library into your program to use it.
|
|
37
|
+
Instead, a client speaks the Deltacloud API over HTTP to a server
|
|
38
|
+
which implements the REST interface.
|
|
39
|
+
|
|
40
|
+
%prep
|
|
41
|
+
|
|
42
|
+
%build
|
|
43
|
+
|
|
44
|
+
%install
|
|
45
|
+
rm -rf %{buildroot}
|
|
46
|
+
mkdir -p %{buildroot}%{gemdir}
|
|
47
|
+
gem install --local --install-dir %{buildroot}%{gemdir} \
|
|
48
|
+
--force --rdoc %{SOURCE0}
|
|
49
|
+
mkdir -p %{buildroot}/%{_bindir}
|
|
50
|
+
mv %{buildroot}%{geminstdir}/support/fedora/deltacloudd %{buildroot}/%{geminstdir}/bin
|
|
51
|
+
mv %{buildroot}%{gemdir}/bin/* %{buildroot}/%{_bindir}
|
|
52
|
+
rmdir %{buildroot}%{gemdir}/bin
|
|
53
|
+
find %{buildroot}%{geminstdir}/bin -type f | xargs chmod a+x
|
|
54
|
+
|
|
55
|
+
# Needs json_pure gem / not available in Fedora yet
|
|
56
|
+
#%check
|
|
57
|
+
#pushd %{buildroot}%{geminstdir}
|
|
58
|
+
#cucumber features/*.feature
|
|
59
|
+
#popd
|
|
60
|
+
|
|
61
|
+
%clean
|
|
62
|
+
rm -rf %{buildroot}
|
|
63
|
+
|
|
64
|
+
%files
|
|
65
|
+
%defattr(-, root, root, -)
|
|
66
|
+
%{_bindir}/deltacloudd
|
|
67
|
+
%{gemdir}/gems/%{gemname}-%{version}/bin
|
|
68
|
+
%{gemdir}/gems/%{gemname}-%{version}/lib
|
|
69
|
+
%{gemdir}/gems/%{gemname}-%{version}/public/favicon.ico
|
|
70
|
+
%{gemdir}/gems/%{gemname}-%{version}/public/images
|
|
71
|
+
%{gemdir}/gems/%{gemname}-%{version}/public/stylesheets
|
|
72
|
+
%{gemdir}/gems/%{gemname}-%{version}/tests
|
|
73
|
+
%{gemdir}/gems/%{gemname}-%{version}/views
|
|
74
|
+
%{gemdir}/gems/%{gemname}-%{version}/Rakefile
|
|
75
|
+
%{gemdir}/gems/%{gemname}-%{version}/*.rb
|
|
76
|
+
%{gemdir}/gems/%{gemname}-%{version}/config.ru
|
|
77
|
+
%doc %{gemdir}/gems/%{gemname}-%{version}/support/fedora
|
|
78
|
+
%doc %{gemdir}/gems/%{gemname}-%{version}/COPYING
|
|
79
|
+
%doc %{gemdir}/doc/%{gemname}-%{version}
|
|
80
|
+
%{gemdir}/cache/%{gemname}-%{version}.gem
|
|
81
|
+
%{gemdir}/specifications/%{gemname}-%{version}.gemspec
|
|
82
|
+
# MIT
|
|
83
|
+
%{gemdir}/gems/%{gemname}-%{version}/public/javascripts
|
|
84
|
+
|
|
85
|
+
%changelog
|
|
86
|
+
* Mon Apr 26 2010 Michal Fojtik <mfojtik@packager> - 0.0.1-1
|
|
87
|
+
- Initial package
|
|
88
|
+
|
|
89
|
+
* Mon Apr 26 2010 Michal Fojtik <mfojtik@packager> - 0.0.1-2
|
|
90
|
+
- Fixed broken dependencies
|
|
91
|
+
- Added new launcher for Fedora
|
data/tests/api_test.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'tests/common'
|
|
2
|
+
|
|
3
|
+
module DeltacloudUnitTest
|
|
4
|
+
class ApiTest < Test::Unit::TestCase
|
|
5
|
+
include Rack::Test::Methods
|
|
6
|
+
|
|
7
|
+
def app
|
|
8
|
+
Sinatra::Application
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_it_returns_entry_points
|
|
12
|
+
do_xml_request '/api'
|
|
13
|
+
(last_xml_response/'/api/link').map.size.should > 0
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_it_has_correct_attributes_set
|
|
17
|
+
do_xml_request '/api'
|
|
18
|
+
(last_xml_response/'/api/link').each do |link|
|
|
19
|
+
link.attributes.keys.sort.should == [ 'href', 'rel' ]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_it_responses_to_html
|
|
24
|
+
do_request '/api', {}, false, { :format => :html }
|
|
25
|
+
last_response.status.should == 200
|
|
26
|
+
Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_it_responses_to_json
|
|
30
|
+
do_request '/api', {}, false, { :format => :json }
|
|
31
|
+
last_response.status.should == 200
|
|
32
|
+
JSON::parse(last_response.body).class.should == Hash
|
|
33
|
+
JSON::parse(last_response.body)['api'].class.should == Hash
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|