steamcannon-deltacloud-core 0.0.7.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/COPYING +176 -0
  2. data/Rakefile +106 -0
  3. data/bin/deltacloudd +120 -0
  4. data/config.ru +5 -0
  5. data/deltacloud.rb +20 -0
  6. data/lib/deltacloud/base_driver/base_driver.rb +259 -0
  7. data/lib/deltacloud/base_driver/features.rb +173 -0
  8. data/lib/deltacloud/base_driver/mock_driver.rb +58 -0
  9. data/lib/deltacloud/base_driver.rb +20 -0
  10. data/lib/deltacloud/drivers/azure/azure_driver.rb +127 -0
  11. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +580 -0
  12. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +170 -0
  13. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +50 -0
  14. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +343 -0
  15. data/lib/deltacloud/drivers/gogrid/test.rb +13 -0
  16. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob1.yml +5 -0
  17. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob2.yml +5 -0
  18. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob3.yml +5 -0
  19. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob4.yml +5 -0
  20. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob5.yml +5 -0
  21. data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +2 -0
  22. data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +2 -0
  23. data/lib/deltacloud/drivers/mock/data/images/img1.yml +3 -0
  24. data/lib/deltacloud/drivers/mock/data/images/img2.yml +3 -0
  25. data/lib/deltacloud/drivers/mock/data/images/img3.yml +3 -0
  26. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +16 -0
  27. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +9 -0
  28. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +9 -0
  29. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +4 -0
  30. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +4 -0
  31. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +4 -0
  32. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +6 -0
  33. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +6 -0
  34. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +6 -0
  35. data/lib/deltacloud/drivers/mock/mock_driver.rb +356 -0
  36. data/lib/deltacloud/drivers/opennebula/cloud_client.rb +116 -0
  37. data/lib/deltacloud/drivers/opennebula/occi_client.rb +204 -0
  38. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +241 -0
  39. data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +130 -0
  40. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +290 -0
  41. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +258 -0
  42. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +85 -0
  43. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +166 -0
  44. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +295 -0
  45. data/lib/deltacloud/hardware_profile.rb +153 -0
  46. data/lib/deltacloud/helpers/application_helper.rb +122 -0
  47. data/lib/deltacloud/helpers/blob_stream.rb +51 -0
  48. data/lib/deltacloud/helpers/conversion_helper.rb +39 -0
  49. data/lib/deltacloud/helpers/hardware_profiles_helper.rb +35 -0
  50. data/lib/deltacloud/helpers.rb +5 -0
  51. data/lib/deltacloud/method_serializer.rb +85 -0
  52. data/lib/deltacloud/models/base_model.rb +59 -0
  53. data/lib/deltacloud/models/blob.rb +26 -0
  54. data/lib/deltacloud/models/bucket.rb +24 -0
  55. data/lib/deltacloud/models/image.rb +27 -0
  56. data/lib/deltacloud/models/instance.rb +38 -0
  57. data/lib/deltacloud/models/instance_profile.rb +48 -0
  58. data/lib/deltacloud/models/key.rb +35 -0
  59. data/lib/deltacloud/models/realm.rb +26 -0
  60. data/lib/deltacloud/models/storage_snapshot.rb +27 -0
  61. data/lib/deltacloud/models/storage_volume.rb +28 -0
  62. data/lib/deltacloud/state_machine.rb +84 -0
  63. data/lib/deltacloud/validation.rb +70 -0
  64. data/lib/drivers.rb +51 -0
  65. data/lib/sinatra/accept_media_types.rb +128 -0
  66. data/lib/sinatra/lazy_auth.rb +56 -0
  67. data/lib/sinatra/rabbit.rb +279 -0
  68. data/lib/sinatra/respond_to.rb +238 -0
  69. data/lib/sinatra/static_assets.rb +83 -0
  70. data/lib/sinatra/url_for.rb +53 -0
  71. data/public/favicon.ico +0 -0
  72. data/public/images/grid.png +0 -0
  73. data/public/images/logo-wide.png +0 -0
  74. data/public/images/rails.png +0 -0
  75. data/public/images/topbar-bg.png +0 -0
  76. data/public/javascripts/application.js +32 -0
  77. data/public/javascripts/jquery-1.4.2.min.js +154 -0
  78. data/public/stylesheets/compiled/application.css +613 -0
  79. data/public/stylesheets/compiled/ie.css +31 -0
  80. data/public/stylesheets/compiled/print.css +27 -0
  81. data/public/stylesheets/compiled/screen.css +456 -0
  82. data/server.rb +516 -0
  83. data/support/fedora/deltacloudd +68 -0
  84. data/support/fedora/rubygem-deltacloud-core.spec +91 -0
  85. data/tests/api_test.rb +37 -0
  86. data/tests/hardware_profiles_test.rb +120 -0
  87. data/tests/images_test.rb +111 -0
  88. data/tests/instance_states_test.rb +51 -0
  89. data/tests/instances_test.rb +222 -0
  90. data/tests/realms_test.rb +78 -0
  91. data/tests/url_for_test.rb +50 -0
  92. data/views/accounts/index.html.haml +11 -0
  93. data/views/accounts/show.html.haml +30 -0
  94. data/views/api/show.html.haml +15 -0
  95. data/views/api/show.xml.haml +5 -0
  96. data/views/blobs/show.html.haml +20 -0
  97. data/views/blobs/show.xml.haml +7 -0
  98. data/views/buckets/index.html.haml +33 -0
  99. data/views/buckets/index.xml.haml +10 -0
  100. data/views/buckets/new.html.haml +13 -0
  101. data/views/buckets/show.html.haml +19 -0
  102. data/views/buckets/show.xml.haml +8 -0
  103. data/views/docs/collection.html.haml +37 -0
  104. data/views/docs/collection.xml.haml +14 -0
  105. data/views/docs/index.html.haml +15 -0
  106. data/views/docs/index.xml.haml +5 -0
  107. data/views/docs/operation.html.haml +31 -0
  108. data/views/docs/operation.xml.haml +10 -0
  109. data/views/errors/auth_exception.html.haml +8 -0
  110. data/views/errors/auth_exception.xml.haml +2 -0
  111. data/views/errors/backend_error.html.haml +19 -0
  112. data/views/errors/backend_error.xml.haml +8 -0
  113. data/views/errors/not_found.html.haml +6 -0
  114. data/views/errors/not_found.xml.haml +2 -0
  115. data/views/errors/validation_failure.html.haml +11 -0
  116. data/views/errors/validation_failure.xml.haml +7 -0
  117. data/views/hardware_profiles/index.html.haml +25 -0
  118. data/views/hardware_profiles/index.xml.haml +4 -0
  119. data/views/hardware_profiles/show.html.haml +19 -0
  120. data/views/hardware_profiles/show.xml.haml +18 -0
  121. data/views/images/index.html.haml +30 -0
  122. data/views/images/index.xml.haml +8 -0
  123. data/views/images/show.html.haml +21 -0
  124. data/views/images/show.xml.haml +5 -0
  125. data/views/instance_states/show.html.haml +31 -0
  126. data/views/instance_states/show.png.erb +45 -0
  127. data/views/instance_states/show.xml.haml +8 -0
  128. data/views/instances/index.html.haml +30 -0
  129. data/views/instances/index.xml.haml +21 -0
  130. data/views/instances/new.html.haml +55 -0
  131. data/views/instances/show.html.haml +43 -0
  132. data/views/instances/show.xml.haml +49 -0
  133. data/views/keys/index.html.haml +26 -0
  134. data/views/keys/index.xml.haml +4 -0
  135. data/views/keys/new.html.haml +8 -0
  136. data/views/keys/show.html.haml +22 -0
  137. data/views/keys/show.xml.haml +20 -0
  138. data/views/layout.html.haml +26 -0
  139. data/views/realms/index.html.haml +29 -0
  140. data/views/realms/index.xml.haml +10 -0
  141. data/views/realms/show.html.haml +15 -0
  142. data/views/realms/show.xml.haml +9 -0
  143. data/views/root/index.html.haml +4 -0
  144. data/views/storage_snapshots/index.html.haml +20 -0
  145. data/views/storage_snapshots/index.xml.haml +9 -0
  146. data/views/storage_snapshots/show.html.haml +14 -0
  147. data/views/storage_snapshots/show.xml.haml +7 -0
  148. data/views/storage_volumes/index.html.haml +21 -0
  149. data/views/storage_volumes/index.xml.haml +23 -0
  150. data/views/storage_volumes/show.html.haml +20 -0
  151. data/views/storage_volumes/show.xml.haml +24 -0
  152. 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