deltacloud-core 0.0.9 → 0.1.0

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 (43) hide show
  1. data/deltacloud.rb +1 -0
  2. data/lib/deltacloud/backend_capability.rb +21 -0
  3. data/lib/deltacloud/base_driver/base_driver.rb +6 -0
  4. data/lib/deltacloud/base_driver/features.rb +16 -0
  5. data/lib/deltacloud/base_driver/mock_driver.rb +25 -5
  6. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +137 -15
  7. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +4 -7
  8. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +116 -3
  9. data/lib/deltacloud/drivers/mock/mock_driver.rb +56 -2
  10. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +5 -19
  11. data/lib/deltacloud/helpers/application_helper.rb +22 -2
  12. data/lib/deltacloud/models/instance.rb +22 -5
  13. data/lib/deltacloud/models/key.rb +16 -0
  14. data/lib/deltacloud/models/{tag.rb → load_balancer.rb} +14 -18
  15. data/lib/sinatra/rabbit.rb +3 -0
  16. data/parse.rb +7 -0
  17. data/public/javascripts/application.js +10 -24
  18. data/public/stylesheets/compiled/application.css +2 -0
  19. data/server.rb +141 -15
  20. data/test.rb +3 -0
  21. data/views/blobs/new.html.haml +10 -0
  22. data/views/blobs/show.html.haml +21 -15
  23. data/views/buckets/index.html.haml +1 -1
  24. data/views/buckets/show.html.haml +5 -2
  25. data/views/errors/backend_capability_failure.html.haml +11 -0
  26. data/views/errors/backend_capability_failure.xml.haml +4 -0
  27. data/views/errors/not_allowed.html.haml +6 -0
  28. data/views/errors/not_allowed.xml.haml +2 -0
  29. data/views/instances/index.html.haml +1 -1
  30. data/views/instances/new.html.haml +8 -0
  31. data/views/instances/show.html.haml +1 -1
  32. data/views/keys/index.html.haml +1 -1
  33. data/views/load_balancers/index.html.haml +33 -0
  34. data/views/load_balancers/index.xml.haml +5 -0
  35. data/views/load_balancers/new.html.haml +38 -0
  36. data/views/load_balancers/show.html.haml +37 -0
  37. data/views/load_balancers/show.xml.haml +21 -0
  38. data/views/storage_snapshots/index.xml.haml +0 -2
  39. data/views/storage_snapshots/show.xml.haml +0 -2
  40. data/views/storage_volumes/index.xml.haml +6 -6
  41. data/views/storage_volumes/show.xml.haml +7 -7
  42. metadata +48 -36
  43. data/views/tags/index.html.haml +0 -1
@@ -26,7 +26,7 @@ module Deltacloud
26
26
  class MockDriver < Deltacloud::BaseDriver
27
27
 
28
28
  def supported_collections
29
- DEFAULT_COLLECTIONS + [ :buckets ]
29
+ DEFAULT_COLLECTIONS + [ :buckets, :keys]
30
30
  end
31
31
 
32
32
  ( REALMS = [
@@ -81,6 +81,7 @@ class MockDriver < Deltacloud::BaseDriver
81
81
  end
82
82
 
83
83
  feature :instances, :user_name
84
+ feature :instances, :authentication_key
84
85
 
85
86
  def initialize
86
87
  if ENV["DELTACLOUD_MOCK_STORAGE"]
@@ -131,11 +132,21 @@ class MockDriver < Deltacloud::BaseDriver
131
132
  # Instances
132
133
  #
133
134
 
135
+ def instance(credentials, opts={})
136
+ check_credentials( credentials )
137
+ instance_filename = File.join(@storage_root, 'instances', "#{opts[:id]}.yml")
138
+ return nil unless File.exists?(instance_filename)
139
+ instance = YAML::load_file(instance_filename)
140
+ instance[:actions] = instance_actions_for( instance[:state] )
141
+ instance[:id] = File::basename(instance_filename, ".yml")
142
+ Instance.new(instance)
143
+ end
144
+
134
145
  def instances(credentials, opts=nil)
135
146
  check_credentials( credentials )
136
147
  instances = []
137
148
  Dir[ "#{@storage_root}/instances/*.yml" ].each do |instance_file|
138
- instance = YAML.load( File.read( instance_file ) )
149
+ instance = YAML::load_file(instance_file)
139
150
  if ( instance[:owner_id] == credentials.user )
140
151
  instance[:id] = File.basename( instance_file, ".yml" )
141
152
  instance[:actions] = instance_actions_for( instance[:state] )
@@ -254,6 +265,49 @@ class MockDriver < Deltacloud::BaseDriver
254
265
  snapshots
255
266
  end
256
267
 
268
+ def keys(credentials, opts={})
269
+ check_credentials(credentials)
270
+ result = []
271
+ key_dir = File.join(@storage_root, 'keys')
272
+ Dir[key_dir + '/*.yml'].each do |key_file|
273
+ result << Key.new(YAML::load(File.read(key_file)))
274
+ end
275
+ result = filter_on( result, :id, opts )
276
+ result
277
+ end
278
+
279
+ def key(credentials, opts={})
280
+ keys(credentials, opts).first
281
+ end
282
+
283
+ def create_key(credentials, opts={})
284
+ check_credentials(credentials)
285
+ key_hash = {
286
+ :id => opts[:key_name],
287
+ :credential_type => :key,
288
+ :fingerprint => Key::generate_mock_fingerprint,
289
+ :pem_rsa_key => Key::generate_mock_pem
290
+ }
291
+ key_dir = File.join(@storage_root, 'keys')
292
+ if File.exists?(key_dir + "/#{key_hash[:id]}.yml")
293
+ raise Deltacloud::BackendError.new(403, self.class.to_s, "key-exists",
294
+ ["Key with same name already exists"])
295
+ end
296
+ FileUtils.mkdir_p(key_dir) unless File.directory?(key_dir)
297
+ File.open(key_dir + "/#{key_hash[:id]}.yml", 'w') do |f|
298
+ f.puts(YAML::dump(key_hash))
299
+ end
300
+ return Key.new(key_hash)
301
+ end
302
+
303
+ def destroy_key(credentials, opts={})
304
+ key = key(credentials, opts)
305
+ safely do
306
+ key_dir = File.join(@storage_root, 'keys')
307
+ File.delete(key_dir + "/#{key.id}.yml")
308
+ end
309
+ end
310
+
257
311
  #--
258
312
  # Buckets
259
313
  #--
@@ -35,6 +35,10 @@ class RHEVMDriver < Deltacloud::BaseDriver
35
35
 
36
36
  feature :instances, :user_name
37
37
 
38
+ def supported_collections
39
+ DEFAULT_COLLECTIONS.reject { |c| [ :storage_volumes, :storage_snapshots ].include?(c) }
40
+ end
41
+
38
42
  #
39
43
  # Execute a Powershell command, and convert the output
40
44
  # to YAML in order to get back an array of maps.
@@ -85,6 +89,7 @@ class RHEVMDriver < Deltacloud::BaseDriver
85
89
  "STOPPED"
86
90
  when "POWERING UP"
87
91
  "PENDING"
92
+ end
88
93
  end
89
94
 
90
95
  define_hardware_profile 'rhevm'
@@ -232,25 +237,6 @@ class RHEVMDriver < Deltacloud::BaseDriver
232
237
  vm = execute(credentials, "deleteVm.ps1", image_id)
233
238
  vm_to_instance(vm[0])
234
239
  end
235
-
236
- #
237
- # Storage Volumes
238
- #
239
-
240
- def storage_volumes(credentials, ids=nil)
241
- volumes = []
242
- volumes
243
- end
244
-
245
- #
246
- # Storage Snapshots
247
- #
248
-
249
- def storage_snapshots(credentials, ids=nil)
250
- snapshots = []
251
- snapshots
252
- end
253
-
254
240
  end
255
241
 
256
242
  end
@@ -41,8 +41,8 @@ module ApplicationHelper
41
41
  collections[:instances].operations[action.to_sym].method
42
42
  end
43
43
 
44
- def driver_has_feature?(feature_name)
45
- not driver.features(:instances).select{ |f| f.name.eql?(feature_name) }.empty?
44
+ def driver_has_feature?(feature_name, collection_name = :instances)
45
+ not driver.features(collection_name).select{ |f| f.name.eql?(feature_name) }.empty?
46
46
  end
47
47
 
48
48
  def driver_has_auth_features?
@@ -102,6 +102,14 @@ module ApplicationHelper
102
102
  end
103
103
 
104
104
  def instance_action(name)
105
+ original_instance = driver.instance(credentials, :id => params[:id])
106
+
107
+ # If original instance doesn't include called action
108
+ # return with 405 error (Method is not Allowed)
109
+ unless driver.instance_actions_for(original_instance.state).include?(name.to_sym)
110
+ return report_error(405, 'not_allowed')
111
+ end
112
+
105
113
  @instance = driver.send(:"#{name}_instance", credentials, params["id"])
106
114
 
107
115
  return redirect(instances_url) if name.eql?(:destroy) or @instance.class!=Instance
@@ -122,4 +130,16 @@ module ApplicationHelper
122
130
  "<pem><![CDATA[#{text.strip}]]></pem>"
123
131
  end
124
132
 
133
+ def link_to_action(action, url, method)
134
+ return link_to(action, url) if method.eql? :get
135
+ capture_haml do
136
+ haml_tag :form, :method => :post, :action => url, :class => :link do
137
+ haml_tag :input, :type => :hidden, :name => '_method', :value => method
138
+ haml_tag :button, :type => :submit do
139
+ haml_concat action
140
+ end
141
+ end
142
+ end
143
+ end
144
+
125
145
  end
@@ -29,10 +29,27 @@ class Instance < BaseModel
29
29
  attr_accessor :private_addresses
30
30
  attr_accessor :instance_profile
31
31
  attr_accessor :launch_time
32
- def initialize(init=nil)
33
- super(init)
34
- self.actions = [] if self.actions.nil?
35
- self.public_addresses = [] if self.public_addresses.nil?
36
- self.private_addresses = [] if self.private_addresses.nil?
32
+ attr_accessor :keyname
33
+ attr_accessor :authn_error
34
+
35
+ def initialize(init=nil)
36
+ super(init)
37
+ self.actions = [] if self.actions.nil?
38
+ self.public_addresses = [] if self.public_addresses.nil?
39
+ self.private_addresses = [] if self.private_addresses.nil?
40
+ end
41
+
42
+ def method_missing(name, *args)
43
+ if name =~ /is_(\w+)\?/
44
+ return true if self.state.downcase.eql?($1)
45
+ else
46
+ raise NoMethodError
47
+ end
37
48
  end
49
+
50
+ def authn_feature_failed?
51
+ return true unless authn_error.nil?
52
+ end
53
+
54
+
38
55
  end
@@ -32,4 +32,20 @@ class Key < BaseModel
32
32
  true if @credential_type.eql?(:key)
33
33
  end
34
34
 
35
+ # Mock fingerprint generator
36
+ # 1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f
37
+ def self.generate_mock_fingerprint
38
+ (0..19).map { "%02x" % (rand * 0xff) }.join(':')
39
+ end
40
+
41
+ # Mock PEM file
42
+ # NOTE: This is a fake PEM file, it will not work against SSH
43
+ def self.generate_mock_pem
44
+ chars = (('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a + %w(= / + ))
45
+ pem_material = (1..21).map do
46
+ (1..75).collect{|a| chars[rand(chars.size)] }.join
47
+ end.join("\n") + "\n" + (1..68).collect{|a| chars[rand(chars.size)] }.join
48
+ "-----BEGIN RSA PRIVATE KEY-----\n"+pem_material+"-----END RSA PRIVATE KEY-----"
49
+ end
50
+
35
51
  end
@@ -16,28 +16,24 @@
16
16
  # License for the specific language governing permissions and limitations
17
17
  # under the License.
18
18
 
19
- class Tag < BaseModel
20
19
 
21
- attr_accessor :resource_id
22
- attr_accessor :resource_type
23
- attr_accessor :values
20
+ class LoadBalancer < BaseModel
24
21
 
25
- def add_value(name)
26
- self.values << Value.new(name, self)
27
- end
28
-
29
- class Value
30
- attr_accessor :name
31
- attr_accessor :tag_id
32
-
33
- def initialize(name, tag_id)
34
- self.name, self.tag_id = name, tag_id
35
- end
22
+ attr_accessor :realms
23
+ attr_accessor :listeners
24
+ attr_accessor :instances
25
+ attr_accessor :public_addresses
26
+ attr_accessor :created_at
36
27
 
37
- def to_s
38
- self.name
39
- end
28
+ def add_listener(opts)
29
+ @listeners << Listener.new(opts)
30
+ end
40
31
 
32
+ class Listener < BaseModel
33
+ attr_accessor :protocol
34
+ attr_accessor :load_balancer_port
35
+ attr_accessor :instance_port
41
36
  end
42
37
 
43
38
  end
39
+
@@ -1,6 +1,7 @@
1
1
  require 'sinatra/base'
2
2
  require 'sinatra/url_for'
3
3
  require 'deltacloud/validation'
4
+ require 'deltacloud/backend_capability'
4
5
 
5
6
  module Sinatra
6
7
 
@@ -13,6 +14,7 @@ module Sinatra
13
14
  class Operation
14
15
  attr_reader :name, :method
15
16
 
17
+ include ::Deltacloud::BackendCapability
16
18
  include ::Deltacloud::Validation
17
19
 
18
20
  STANDARD = {
@@ -58,6 +60,7 @@ module Sinatra
58
60
  def control(&block)
59
61
  op = self
60
62
  @control = Proc.new do
63
+ op.check_capability(driver)
61
64
  op.validate(params)
62
65
  instance_eval(&block)
63
66
  end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'nokogiri'
3
+ require 'ap'
4
+
5
+ doc = Nokogiri::XML(File.read("/home/mfojtik/Autounattend.xml"))
6
+
7
+ ap (doc/"//*[local-name()='component']/*[local-name()='ProductKey']").text
@@ -3,30 +3,16 @@
3
3
 
4
4
  $(document).ready(function() {
5
5
 
6
- $("a.delete").click(function(e) {
7
- var original_url = $(this).attr('href')
8
- $.ajax({
9
- url : original_url,
10
- type : 'DELETE',
11
- cache : false,
12
- success: function(data) {
13
- window.location = original_url.replace(/\/([\w_-]+)$/i, '')
6
+ if ($('select#list_instances').length) {
7
+ $('select#list_instances').html("<option>Loading instances...</option>");
8
+ $.getJSON("/api/instances?state=RUNNING&format=json",
9
+ function(data){
10
+ $('select#list_instances').empty();
11
+ $.each(data.instances, function(i,item){
12
+ $('select#list_instances').append('<option value="'+item.id+'">'+item.id+'</option>');
13
+ });
14
14
  }
15
- })
16
- return false;
17
- })
18
-
19
- $("a.post").click(function(e) {
20
- var original_url = $(this).attr('href')
21
- $.ajax({
22
- url : original_url,
23
- type : 'POST',
24
- dataType : 'xml',
25
- success: function(data) {
26
- window.location = original_url.replace(/\/([\w_-]+)$/i, '')
27
- }
28
- })
29
- return false;
30
- })
15
+ );
16
+ }
31
17
 
32
18
  })
@@ -611,3 +611,5 @@ input[type='radio'] {
611
611
  table.docs { border : 1px solid #ccc }
612
612
  table.docs td { border : 1px solid #ccc }
613
613
  table.docs table td { border : none }
614
+
615
+ td form.link { display : inline }
data/server.rb CHANGED
@@ -32,6 +32,9 @@ error Deltacloud::Validation::Failure do
32
32
  report_error(400, "validation_failure")
33
33
  end
34
34
 
35
+ error Deltacloud::BackendCapability::Failure do
36
+ report_error(405, "backend_capability_failure")
37
+ end
35
38
  error Deltacloud::AuthException do
36
39
  report_error(403, "auth_exception")
37
40
  end
@@ -82,6 +85,7 @@ END
82
85
  Operation will list all available realms. Realms can be filtered using
83
86
  the "architecture" parameter.
84
87
  END
88
+ with_capability :realms
85
89
  param :id, :string
86
90
  param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
87
91
  control { filter_all(:realms) }
@@ -90,6 +94,7 @@ END
90
94
  #FIXME: It always shows whole list
91
95
  operation :show do
92
96
  description 'Show an realm identified by "id" parameter.'
97
+ with_capability :realm
93
98
  param :id, :string, :required
94
99
  control { show(:realm) }
95
100
  end
@@ -108,6 +113,7 @@ END
108
113
  available to the current use. Images can be filtered using the
109
114
  "owner_id" and "architecture" parameters.
110
115
  END
116
+ with_capability :images
111
117
  param :id, :string
112
118
  param :architecture, :string, :optional
113
119
  control { filter_all(:images) }
@@ -115,6 +121,7 @@ END
115
121
 
116
122
  operation :show do
117
123
  description 'Show an image identified by "id" parameter.'
124
+ with_capability :image
118
125
  param :id, :string, :required
119
126
  control { show(:image) }
120
127
  end
@@ -168,11 +175,87 @@ get "/api/instances/new" do
168
175
  @image = driver.image( credentials, :id => params[:image_id] )
169
176
  @hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
170
177
  @realms = driver.realms(credentials)
178
+ if driver_has_feature?(:register_to_load_balancer)
179
+ @load_balancers = driver.load_balancers(credentials)
180
+ end
171
181
  respond_to do |format|
172
182
  format.html { haml :"instances/new" }
173
183
  end
174
184
  end
175
185
 
186
+ get '/api/load_balancers/new' do
187
+ @realms = driver.realms(credentials)
188
+ @instances = driver.instances(credentials) if driver_has_feature?(:register_instance, :load_balancers)
189
+ respond_to do |format|
190
+ format.html { haml :"load_balancers/new" }
191
+ end
192
+ end
193
+
194
+
195
+ collection :load_balancers do
196
+ description "Load balancers"
197
+
198
+ operation :index do
199
+ description "List of all active load balancers"
200
+ control do
201
+ filter_all :load_balancers
202
+ end
203
+ end
204
+
205
+ operation :show do
206
+ description "Show details about given load balancer"
207
+ param :id, :string, :required
208
+ control { show :load_balancer }
209
+ end
210
+
211
+ operation :create do
212
+ description "Create a new load balancer"
213
+ param :name, :string, :required
214
+ param :realm_id, :string, :required
215
+ param :listener_protocol, :string, :required, ['HTTP', 'TCP']
216
+ param :listener_balancer_port, :string, :required
217
+ param :listener_instance_port, :string, :required
218
+ control do
219
+ @load_balancer = driver.create_load_balancer(credentials, params)
220
+ respond_to do |format|
221
+ format.xml { haml :"load_balancers/show" }
222
+ format.html { haml :"load_balancers/show" }
223
+ end
224
+ end
225
+ end
226
+
227
+ operation :register, :method => :post, :member => true do
228
+ description "Add instance to loadbalancer"
229
+ param :id, :string, :required
230
+ param :instance_id, :string, :required
231
+ control do
232
+ driver.lb_register_instance(credentials, params)
233
+ redirect(load_balancer_url(params[:id]))
234
+ end
235
+ end
236
+
237
+ operation :unregister, :method => :post, :member => true do
238
+ description "Remove instance from loadbalancer"
239
+ param :id, :string, :required
240
+ param :instance_id, :string, :required
241
+ control do
242
+ driver.lb_unregister_instance(credentials, params)
243
+ redirect(load_balancer_url(params[:id]))
244
+ end
245
+ end
246
+
247
+ operation :destroy do
248
+ description "Destroy given load balancer"
249
+ param :id, :string, :required
250
+ control do
251
+ driver.destroy_load_balancer(credentials, params[:id])
252
+ redirect(load_balancers_url)
253
+ end
254
+ end
255
+
256
+ end
257
+
258
+
176
259
  collection :instances do
177
260
  description <<END
178
261
  An instance is a concrete machine realized from an image.
@@ -181,6 +264,7 @@ END
181
264
 
182
265
  operation :index do
183
266
  description "List all instances."
267
+ with_capability :instances
184
268
  param :id, :string, :optional
185
269
  param :state, :string, :optional
186
270
  control { filter_all(:instances) }
@@ -188,12 +272,14 @@ END
188
272
 
189
273
  operation :show do
190
274
  description 'Show an instance identified by "id" parameter.'
275
+ with_capability :instance
191
276
  param :id, :string, :required
192
277
  control { show(:instance) }
193
278
  end
194
279
 
195
280
  operation :create do
196
281
  description "Create a new instance."
282
+ with_capability :create_instance
197
283
  param :image_id, :string, :required
198
284
  param :realm_id, :string, :optional
199
285
  param :hwp_id, :string, :optional
@@ -217,24 +303,28 @@ END
217
303
 
218
304
  operation :reboot, :method => :post, :member => true do
219
305
  description "Reboot a running instance."
306
+ with_capability :reboot_instance
220
307
  param :id, :string, :required
221
308
  control { instance_action(:reboot) }
222
309
  end
223
310
 
224
311
  operation :start, :method => :post, :member => true do
225
312
  description "Start an instance."
313
+ with_capability :start_instance
226
314
  param :id, :string, :required
227
315
  control { instance_action(:start) }
228
316
  end
229
317
 
230
318
  operation :stop, :method => :post, :member => true do
231
319
  description "Stop a running instance."
320
+ with_capability :stop_instance
232
321
  param :id, :string, :required
233
322
  control { instance_action(:stop) }
234
323
  end
235
324
 
236
325
  operation :destroy do
237
326
  description "Destroy an instance."
327
+ with_capability :destroy_instance
238
328
  param :id, :string, :required
239
329
  control { instance_action(:destroy) }
240
330
  end
@@ -250,6 +340,7 @@ END
250
340
 
251
341
  operation :index do
252
342
  description "List of available hardware profiles."
343
+ with_capability :hardware_profiles
253
344
  param :id, :string
254
345
  param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
255
346
  control do
@@ -264,6 +355,7 @@ END
264
355
 
265
356
  operation :show do
266
357
  description "Show specific hardware profile."
358
+ with_capability :hardware_profile
267
359
  param :id, :string, :required
268
360
  control do
269
361
  @profile = driver.hardware_profile(credentials, params[:id])
@@ -286,12 +378,14 @@ collection :storage_snapshots do
286
378
 
287
379
  operation :index do
288
380
  description "List of storage snapshots."
381
+ with_capability :storage_snapshots
289
382
  param :id, :string
290
383
  control { filter_all(:storage_snapshots) }
291
384
  end
292
385
 
293
386
  operation :show do
294
387
  description "Show storage snapshot."
388
+ with_capability :storage_snapshot
295
389
  param :id, :string, :required
296
390
  control { show(:storage_snapshot) }
297
391
  end
@@ -302,12 +396,14 @@ collection :storage_volumes do
302
396
 
303
397
  operation :index do
304
398
  description "List of storage volumes."
399
+ with_capability :storage_volumes
305
400
  param :id, :string
306
401
  control { filter_all(:storage_volumes) }
307
402
  end
308
403
 
309
404
  operation :show do
310
405
  description "Show storage volume."
406
+ with_capability :storage_volume
311
407
  param :id, :string, :required
312
408
  control { show(:storage_volume) }
313
409
  end
@@ -324,6 +420,7 @@ collection :keys do
324
420
 
325
421
  operation :index do
326
422
  description "List all available credentials which could be used for instance authentication."
423
+ with_capability :keys
327
424
  control do
328
425
  filter_all :keys
329
426
  end
@@ -331,18 +428,16 @@ collection :keys do
331
428
 
332
429
  operation :show do
333
430
  description "Show details about given instance credential."
431
+ with_capability :key
334
432
  param :id, :string, :required
335
433
  control { show :key }
336
434
  end
337
435
 
338
436
  operation :create do
339
437
  description "Create a new instance credential if backend supports this."
438
+ with_capability :create_key
340
439
  param :name, :string, :required
341
440
  control do
342
- unless driver.respond_to?(:create_key)
343
- raise Deltacloud::BackendFeatureUnsupported.new('501',
344
- 'Creating instance credentials is not supported in backend')
345
- end
346
441
  @key = driver.create_key(credentials, { :key_name => params[:name] })
347
442
  respond_to do |format|
348
443
  format.html { haml :"keys/show" }
@@ -353,12 +448,9 @@ collection :keys do
353
448
 
354
449
  operation :destroy do
355
450
  description "Destroy given instance credential if backend supports this."
451
+ with_capability :destroy_key
356
452
  param :id, :string, :required
357
453
  control do
358
- unless driver.respond_to?(:destroy_key)
359
- raise Deltacloud::BackendFeatureUnsupported.new('501',
360
- 'Creating instance credentials is not supported in backend')
361
- end
362
454
  driver.destroy_key(credentials, { :key_name => params[:id]})
363
455
  redirect(keys_url)
364
456
  end
@@ -366,6 +458,35 @@ collection :keys do
366
458
 
367
459
  end
368
460
 
461
+ #get html form for creating a new blob
462
+ get '/api/buckets/:bucket/new_blob' do
463
+ @bucket_id = params[:bucket]
464
+ respond_to do |format|
465
+ format.html {haml :"blobs/new"}
466
+ end
467
+ end
468
+
469
+ #create a new blob
470
+ post '/api/buckets/:bucket' do
471
+ bucket_id = params[:bucket]
472
+ blob_id = params['blob_id']
473
+ blob_data = params['blob_data']
474
+ @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data )
475
+ respond_to do |format|
476
+ format.html { haml :"blobs/show"}
477
+ format.xml { haml :"blobs/show" }
478
+ end
479
+ end
480
+
481
+ #delete a blob
482
+ delete '/api/buckets/:bucket/:blob' do
483
+ bucket_id = params[:bucket]
484
+ blob_id = params[:blob]
485
+ driver.delete_blob(credentials, bucket_id, blob_id)
486
+ redirect(bucket_url(bucket_id))
487
+ end
488
+
489
+ #Get a particular blob's particulars (not actual blob data)
369
490
  get '/api/buckets/:bucket/:blob' do
370
491
  @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
371
492
  if @blob
@@ -379,13 +500,7 @@ get '/api/buckets/:bucket/:blob' do
379
500
  end
380
501
  end
381
502
 
382
- get '/api/buckets/new' do
383
- respond_to do |format|
384
- format.html { haml :"buckets/new" }
385
- end
386
- end
387
-
388
-
503
+ #get the content of a particular blob
389
504
  get '/api/buckets/:bucket/:blob/content' do
390
505
  @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
391
506
  params['content_length'] = @blob.content_length
@@ -393,11 +508,19 @@ get '/api/buckets/:bucket/:blob/content' do
393
508
  BlobStream.call(env, credentials, params)
394
509
  end
395
510
 
511
+ #Get html form for creating a new bucket
512
+ get '/api/buckets/new' do
513
+ respond_to do |format|
514
+ format.html { haml :"buckets/new" }
515
+ end
516
+ end
517
+
396
518
  collection :buckets do
397
519
  description "Cloud Storage buckets - aka buckets|directories|folders"
398
520
 
399
521
  operation :index do
400
522
  description "List buckets associated with this account"
523
+ with_capability :buckets
401
524
  param :id, :string
402
525
  param :name, :string
403
526
  param :size, :string
@@ -406,12 +529,14 @@ collection :buckets do
406
529
 
407
530
  operation :show do
408
531
  description "Show bucket"
532
+ with_capability :bucket
409
533
  param :id, :string
410
534
  control { show(:bucket) }
411
535
  end
412
536
 
413
537
  operation :create do
414
538
  description "Create a new bucket (POST /api/buckets)"
539
+ with_capability :create_bucket
415
540
  param :name, :string, :required
416
541
  control do
417
542
  @bucket = driver.create_bucket(credentials, params[:name], params)
@@ -431,6 +556,7 @@ collection :buckets do
431
556
 
432
557
  operation :destroy do
433
558
  description "Delete a bucket by name - bucket must be empty"
559
+ with_capability :delete_bucket
434
560
  param :id, :string, :required
435
561
  control do
436
562
  driver.delete_bucket(credentials, params[:id], params)