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.
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