occi 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/occi/server.rb DELETED
@@ -1,594 +0,0 @@
1
- ##############################################################################
2
- # Copyright 2011 Service Computing group, TU Dortmund
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- ##############################################################################
16
-
17
- ##############################################################################
18
- # Description: OCCI RESTful Web Service
19
- # Author(s): Hayati Bice, Florian Feldhaus, Piotr Kasprzak
20
- ##############################################################################
21
-
22
- ##############################################################################
23
- # Require Ruby Gems
24
-
25
- # gems
26
- require 'rubygems'
27
-
28
- # sinatra
29
- require 'sinatra'
30
- require 'sinatra/multi_route'
31
- require 'sinatra/cross_origin'
32
- require 'sinatra/respond_with'
33
-
34
- # Ruby standard library
35
- require 'uri'
36
- require 'fileutils'
37
-
38
- # Server configuration
39
- require 'occi/configuration'
40
-
41
- # Active support notifications
42
- require 'active_support/notifications'
43
-
44
- # Active support for xml rendering
45
- require 'active_support/core_ext'
46
-
47
- ##############################################################################
48
- # Require OCCI classes
49
-
50
- # Exceptions
51
- require 'occi/exceptions'
52
-
53
- # Category registry
54
- require 'occi/registry'
55
-
56
- # OCCI Core classes
57
- require 'occi/core/action'
58
- require 'occi/core/category'
59
- require 'occi/core/entity'
60
- require 'occi/core/kind'
61
- require 'occi/core/link'
62
- require 'occi/core/mixin'
63
- require 'occi/core/resource'
64
-
65
- # OCCI parser
66
- require 'occi/parse'
67
-
68
- # Backend support
69
- require 'occi/backend/manager'
70
-
71
- ##############################################################################
72
- # Sinatra methods for handling HTTP requests
73
-
74
- module OCCI
75
- class Server < Sinatra::Application
76
-
77
- register Sinatra::MultiRoute
78
- register Sinatra::CrossOrigin
79
- register Sinatra::RespondWith
80
-
81
- enable cross_origin
82
-
83
- # Read configuration file
84
- def self.config
85
- @@config ||= OCCI::Configuration.new('etc/occi-server.conf')
86
- end
87
-
88
- def self.location
89
- OCCI::Server.config[:server].chomp('/')
90
- end
91
-
92
- def self.port
93
- OCCI::Server.config[:port]
94
- end
95
-
96
- def self.uri
97
- self.port.nil? ? self.location : self.location + ':' + self.port
98
- end
99
-
100
- def initialize(config = {})
101
- # create logger
102
- config[:log_dest] ||= STDOUT
103
- config[:log_level] ||= Logger::INFO
104
- config[:log_level] = case OCCI::Server.config[:log_level]
105
- when "debug"
106
- Logger::DEBUG
107
- when "info"
108
- Logger::INFO
109
- when "warn"
110
- Logger::WARN
111
- when "error"
112
- Logger::ERROR
113
- when "fatal"
114
- Logger::FATAL
115
- else
116
- Logger::INFO
117
- end
118
-
119
- @logger = Logger.new(config[:log_dest])
120
- @logger.level = config[:log_level]
121
-
122
- # subscribe to log messages and send to logger
123
- @log_subscriber = ActiveSupport::Notifications.subscribe("log") do |name, start, finish, id, payload|
124
- @logger.log(payload[:level], payload[:message])
125
- end
126
-
127
- # Configuration of HTTP Authentication
128
- if OCCI::Server.config['username'] != nil and OCCI::Server.config['password'] != nil
129
- use Rack::Auth::Basic, "Restricted Area" do |username, password|
130
- [username, password] == [OCCI::Server.config['username'], OCCI::Server.config['password']]
131
- end
132
- end
133
-
134
- OCCI::Server.initialize_core_model
135
- OCCI::Server.initialize_model(OCCI::Server.config['occi_model_path'])
136
-
137
- # set views explicitly
138
- set :views, File.dirname(__FILE__) + "/../../views"
139
-
140
- super
141
- end
142
-
143
- # ---------------------------------------------------------------------------------------------------------------------
144
-
145
- def self.initialize_core_model
146
- OCCI::Log.info("### Initializing OCCI Core Model ###")
147
- OCCI::Core::Entity.register
148
- OCCI::Core::Resource.register
149
- OCCI::Core::Link.register
150
- end
151
-
152
- def self.initialize_model(path)
153
- OCCI::Log.info("### Initializing OCCI Model from #{path} ###")
154
- Dir.glob(path + '/**/*.json').each do |file|
155
- collection = Hashie::Mash.new(JSON.parse(File.read(file)))
156
- # add location of service provider to scheme if it has a relative location
157
- collection.kinds.collect { |kind| kind.scheme = self.location + kind.scheme if kind.scheme.start_with? '/' } if collection.kinds
158
- collection.mixins.collect { |mixin| mixin.scheme = self.location + mixin.scheme if mixin.scheme.start_with? '/' } if collection.mixins
159
- collection.actions.collect { |action| action.scheme = self.location + action.scheme if action.scheme.start_with? '/' } if collection.actions
160
- # register categories
161
- collection.kinds.each { |kind| OCCI::Registry.register(OCCI::Core::Kind.new(kind)) } if collection.kinds
162
- collection.mixins.each { |mixin| OCCI::Registry.register(OCCI::Core::Mixin.new(mixin)) } if collection.mixins
163
- collection.actions.each { |action| OCCI::Registry.register(OCCI::Core::Action.new(action)) } if collection.actions
164
- end
165
- end
166
-
167
- # ---------------------------------------------------------------------------------------------------------------------
168
- def initialize_backend(auth)
169
-
170
- if auth.provided? && auth.basic? && auth.credentials
171
- user, password = auth.credentials
172
- else
173
- user, password = [OCCI::Server.config['one_user'], OCCI::Server.config['one_password']]
174
- logger.debug("No basic auth data provided: using defaults from config (user = '#{user}')")
175
- end
176
-
177
- @backend = case OCCI::Server.config["backend"]
178
- when "opennebula"
179
- require 'occi/backend/opennebula/opennebula'
180
- OCCI::Server.initialize_model('etc/backend/opennebula')
181
- OCCI::Backend::Manager.register_backend(OCCI::Backend::OpenNebula::OpenNebula, OCCI::Backend::OpenNebula::OpenNebula::OPERATIONS)
182
- OCCI::Backend::OpenNebula::OpenNebula.new(user, password)
183
- when "ec2"
184
- require 'occi/backend/ec2/ec2'
185
- Bundler.require(:ec2)
186
- OCCI::Server.initialize_model('etc/backend/ec2')
187
- OCCI::Backend::Manager.register_backend(OCCI::Backend::EC2::EC2, OCCI::Backend::EC2::EC2::OPERATIONS)
188
- OCCI::Backend::EC2::EC2.new(user, password)
189
- when "dummy" then
190
- require 'occi/backend/dummy'
191
- OCCI::Backend::Manager.register_backend(OCCI::Backend::Dummy, OCCI::Backend::Dummy::OPERATIONS)
192
- OCCI::Backend::Dummy.new()
193
- else
194
- raise "Backend '" + OCCI::Server.config["backend"] + "' not found"
195
- end
196
-
197
-
198
- end
199
-
200
- # Parses a Rack/Sinatra Request and extract OCCI relevant information
201
- def parse(request)
202
- OCCI::Log.debug('### Parsing request data to OCCI data structure ###')
203
- body = request.body.read
204
- header = request.env
205
- collection = OCCI::Core::Collection.new
206
- locations = []
207
- # always check headers
208
- locations = OCCI::Parse.header_locations(header)
209
- if locations.empty?
210
- if request.path_info.include?('/-/')
211
- collection = OCCI::Parse.header_categories(header)
212
- else
213
- collection = OCCI::Parse.header_entity(header)
214
- end
215
- end
216
-
217
- case request.media_type
218
- when 'text/uri-list'
219
- body.each_line do |line|
220
- locations << URI.parse(line)
221
- end
222
- when 'text/plain', nil
223
- locations = OCCI::Parse.text_locations(body)
224
- if locations.empty?
225
- if request.path_info.include?('/-/')
226
- collection = OCCI::Parse.text_categories(body)
227
- else
228
- collection = OCCI::Parse.text_entity(body)
229
- end
230
- end
231
- when 'application/occi+json', 'application/json'
232
- collection = OCCI::Parse.json(body)
233
- when 'application/occi+xml', 'application/xml'
234
- collection = OCCI::Parse.xml(body)
235
- else
236
- raise OCCI::ContentTypeNotSupported
237
- end
238
- return locations, collection
239
- end
240
-
241
- # ---------------------------------------------------------------------------------------------------------------------
242
-
243
- # GET request
244
-
245
- # tasks to be executed before the request is handled
246
- before do
247
- OCCI::Log.debug('--------------------------------------------------------------------')
248
- OCCI::Log.debug("### Client IP: #{request.ip}")
249
- OCCI::Log.debug("### Client Accept: #{request.accept}")
250
- OCCI::Log.debug("### Client User Agent: #{request.user_agent}")
251
- OCCI::Log.debug("### Client Request URL: #{request.url}")
252
- OCCI::Log.debug("### Client Request method: #{request.request_method}")
253
- OCCI::Log.debug("### Client Request Media Type: #{request.media_type}")
254
- OCCI::Log.debug('--------------------------------------------------------------------')
255
-
256
- OCCI::Log.debug('### Prepare response ###')
257
- response['Accept'] = "application/occi+json,application/json,text/plain,text/uri-list,application/xml,text/xml,application/occi+xml"
258
- response['Server'] = "rOCCI/#{VERSION_NUMBER} OCCI/1.1"
259
- OCCI::Log.debug('### Initialize response OCCI collection ###')
260
- @collection = Hashie::Mash.new(:kinds => [], :mixins => [], :actions => [], :resources => [], :links => [])
261
- @locations = Array.new
262
- OCCI::Log.debug('### Preparing authentication handling ###')
263
- authentication = Rack::Auth::Basic::Request.new(request.env)
264
- OCCI::Log.debug('### Initializing backend ###')
265
- initialize_backend(authentication)
266
- OCCI::Log.debug('### Reset OCCI model ###')
267
- OCCI::Registry.reset
268
- @request_locations, @request_collection = parse(request)
269
- OCCI::Log.debug('### Fill OCCI model with entities from backend ###')
270
- @backend.register_existing_resources
271
- end
272
-
273
- after do
274
- # OCCI::Log.debug((@collection.resources.to_a + @collection.links.to_a).collect {|entity| entity.location}.join("\n"))
275
- OCCI::Log.debug('### Rendering response ###')
276
- @collection.delete_if { |k, v| v.empty? } # remove empty entries
277
- respond_to do |f|
278
- f.txt { erb :collection, :locals => {:collection => @collection, :locations => @locations} }
279
- f.on('*/*') { erb :collection, :locals => {:collection => @collection, :locations => @locations} }
280
- # f.html { haml :collection, :locals => {:collection => @collection} }
281
- f.json { @collection.to_json }
282
- f.on('application/occi+json') { @collection.to_json }
283
- f.xml { @collection.to_xml(:root => "collection") }
284
- f.on('application/occi+xml') { @collection.to_xml(:root => "collection") }
285
- f.on('text/uri-list') { @locations.join("\n") }
286
- end
287
- OCCI::Log.debug('### Successfully rendered ###')
288
- end
289
-
290
- # discovery interface
291
- # returns all kinds, mixins and actions registered for the server
292
- get '/-/', '/.well-known/org/ogf/occi/-/' do
293
- OCCI::Log.info("### Listing all kinds, mixins and actions ###")
294
- @collection = OCCI::Registry.get(@request_collection.categories)
295
- status 200
296
- end
297
-
298
- # Resource retrieval
299
- # returns entities either below a certain path or belonging to a certain kind or mixin
300
- get '*' do
301
- if request.path_info.end_with?('/')
302
- if request.path_info == '/'
303
- kinds = OCCI::Registry.get.kinds
304
- else
305
- kinds = [OCCI::Registry.get_by_location(request.path_info)]
306
- end
307
-
308
- kinds.each do |kind|
309
- OCCI::Log.info("### Listing all entities of kind #{kind.type_identifier} ###")
310
- @collection.resources.concat kind.entities if kind.entity_type == OCCI::Core::Resource.name
311
- @collection.links.concat kind.entities if kind.entity_type == OCCI::Core::Link.name
312
- @locations.concat kind.entities.collect { |entity| OCCI::Server.uri + entity.location }
313
- end
314
- else
315
- kind = OCCI::Registry.get_by_location(request.path_info.rpartition('/').first + '/')
316
- uuid = request.path_info.rpartition('/').last
317
- error 404 if kind.nil? or uuid.nil?
318
- OCCI::Log.info("### Listing entity with uuid #{uuid} ###")
319
- @collection.resources = kind.entities.select { |entity| entity.id == uuid } if kind.entity_type == OCCI::Core::Resource.name
320
- @collection.links = kind.entities.select { |entity| entity.id == uuid } if kind.entity_type == OCCI::Core::Link.name
321
- end
322
- status 200
323
- end
324
-
325
- # ---------------------------------------------------------------------------------------------------------------------
326
- # POST request
327
- post '/-/', '/.well-known/org/ogf/occi/-/' do
328
- logger.info("## Creating user defined mixin ###")
329
- raise OCCI::MixinAlreadyExistsError, "Mixin already exists!" if OCCI::Registry.get(@request_collection.mixins)
330
- @request_collection.mixins.each do |mixin|
331
- OCCI::CategoryRegistry.register(mixin)
332
- # TODO: inform backend about new mixin
333
- end
334
- end
335
-
336
- # Create an instance appropriate to category field and optionally link an instance to another one
337
- post '*' do
338
-
339
- category = OCCI::Registry.get_by_location(request.path_info.rpartition('/').first + '/')
340
-
341
- if category.nil?
342
- OCCI::Log.debug("### No category found for request location #{request.path_info} ###")
343
- status 404
344
- end
345
-
346
- # if action
347
- if params[:action]
348
- if @request_collection.actions.any?
349
- action = @request_collection.actions.first
350
- params[:method] ||= action.attributes!.method if action
351
- else
352
- action = OCCI::Registry.get_by_id(category.actions.select { |action| action.split('#').last == params[:action] }.first)
353
- end
354
-
355
- category.entities.each do |entity|
356
- OCCI::Backend::Manager.delegate_action(@backend, action, params, entity)
357
- status 200
358
- end
359
- elsif category.kind_of?(OCCI::Core::Kind)
360
- @request_collection.resources.each do |resource|
361
- OCCI::Log.debug("Deploying resource with title #{resource.title} in backend #{@backend.class.name}")
362
- OCCI::Backend::Manager.signal_resource(@backend, OCCI::Backend::RESOURCE_DEPLOY, resource)
363
- @locations << OCCI::Server.uri + resource.location
364
- status 201
365
- end
366
- elsif category.kind_of?(OCCI::Core::Mixin)
367
- @request_collection.locations.each do |location|
368
- OCCI::Log.debug("Attaching resource #{resource.title} to mixin #{mixin.type_identifier} in backend #{@backend.class.name}")
369
- # TODO: let backend carry out tasks related to the added mixin
370
- category.entities << OCCI::Rendering::HTTP::LocationRegistry.get_object(location)
371
- status 200
372
- end
373
- else
374
- status 400
375
- end
376
-
377
- end
378
-
379
- # ---------------------------------------------------------------------------------------------------------------------
380
- # PUT request
381
-
382
- put '*' do
383
-
384
- # Add an resource instance to a mixin
385
- unless @occi_request.mixins.empty?
386
- mixin = OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info)
387
-
388
- @occi_request.locations.each do |location|
389
- entity = OCCI::Rendering::HTTP::LocationRegistry.get_object(URI.parse(location).path)
390
-
391
- raise "No entity found at location: #{entity_location}" if entity == nil
392
- raise "Object referenced by uri [#{entity_location}] is not a OCCI::Core::Resource instance!" if !entity.kind_of?(OCCI::Core::Resource)
393
-
394
- logger.debug("Associating entity [#{entity}] at location #{entity_location} with mixin #{mixin}")
395
-
396
- entity.mixins << mixin
397
- end
398
- break
399
- end
400
-
401
- # Update resource instance(s) at the given location
402
- unless OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info).nil?
403
- entities = []
404
- # Determine set of resources to be updated
405
- if OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info).kind_of?(OCCI::Core::Resource)
406
- entities = [OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info)]
407
- elsif not OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info).kind_of?(OCCI::Core::Category)
408
- entities = OCCI::Rendering::HTTP::LocationRegistry.get_resources_below_location(request.path_info, OCCI::CategoryRegistry.get_all)
409
- elsif OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info).kind_of?(OCCI::Core::Category)
410
- object = OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info)
411
- @occi_request.locations.each do |loc|
412
- entities << OCCI::Rendering::HTTP::LocationRegistry.get_object(URI.parse(loc.chomp('"').reverse.chomp('"').reverse).path)
413
- end
414
- end
415
- logger.info("Full update for [#{entities.size}] entities...")
416
-
417
- # full update of mixins
418
- object.entities.each do |entity|
419
- entity.mixins.delete(object)
420
- object.entities.delete(entity)
421
- end if object.kind_of?(OCCI::Core::Mixin)
422
-
423
- entities.each do |entity|
424
- logger.debug("Adding entity: #{entity.get_location} to mixin #{object.type_identifier}")
425
- entity.mixins.push(object).uniq!
426
- object.entities.push(entity).uniq!
427
- end if object.kind_of?(OCCI::Core::Mixin)
428
-
429
- # full update of attributes
430
- entities.each do |entity|
431
- # Refresh information from backend for entities of type resource
432
- # TODO: full update
433
- entity.attributes.merge!(@occi_request.attributes)
434
- # TODO: update entity in backend
435
- end unless @occi_request.attributes.empty?
436
-
437
- # full update of links
438
- # TODO: full update e.g. delete old links first
439
- @occi_request.links.each do |link_data|
440
- logger.debug("Extracted link data: #{link_data}")
441
- raise "Mandatory information missing (related | target | category)!" unless link_data.related != nil && link_data.target != nil && link_data.category != nil
442
-
443
- link_mixins = []
444
- link_kind = nil
445
- link_data.category.split(' ').each do |link_category|
446
- begin
447
- cat = OCCI::CategoryRegistry.get_by_id(link_category)
448
- rescue OCCI::CategoryNotFoundException => e
449
- logger.info("Category #{link_category} not found")
450
- next
451
- end
452
- link_kind = cat if cat.kind_of?(OCCI::Core::Kind)
453
- link_mixins << cat if cat.kind_of?(OCCI::Core::Mixin)
454
- end
455
-
456
- raise "No kind for link category #{link_data.category} found" if link_kind.nil?
457
-
458
- target_location = link_data.target_attr
459
- target = OCCI::Rendering::HTTP::LocationRegistry.get_object(target_location)
460
-
461
- entities.each do |entity|
462
-
463
- source_location = OCCI::Rendering::HTTP::LocationRegistry.get_location_of_object(entity)
464
-
465
- link_attributes = link_data.attributes.clone
466
- link_attributes["occi.core.target"] = target_location.chomp('"').reverse.chomp('"').reverse
467
- link_attributes["occi.core.source"] = source_location
468
-
469
- link = link_kind.entity_type.new(link_attributes, link_mixins)
470
- OCCI::Rendering::HTTP::LocationRegistry.register_location(link.get_location(), link)
471
-
472
- target.links << link
473
- entity.links << link
474
- end
475
- end
476
- break
477
- end
478
-
479
- response.status = OCCI::Rendering::HTTP::Response::HTTP_NOT_FOUND
480
- # Create resource instance at the given location
481
- raise "Creating resources with method 'put' is currently not possible!"
482
-
483
- # This must be the last statement in this block, so that sinatra does not try to respond with random body content
484
- # (or fail utterly while trying to do that!)
485
- nil
486
-
487
- end
488
-
489
- # ---------------------------------------------------------------------------------------------------------------------
490
- # DELETE request
491
-
492
- delete '/-/', '/.well-known/org/ogf/occi/-/' do
493
- # Location references query interface => delete provided mixin
494
- raise OCCI::CategoryMissingException if @request_collection.mixins.nil?
495
- mixins = OCCI::Registry.get(@request_collection.mixins)
496
- raise OCCI::MixinNotFoundException if mixins.nil?
497
- mixins.each do |mixin|
498
- OCCI::Log.debug("### Deleting mixin #{mixin.type_identifier} ###")
499
- mixin.entities.each do |entity|
500
- entity.mixins.delete(mixin)
501
- end
502
- # TODO: Notify backend to delete mixin and unassociate entities
503
- OCCI::Registry.unregister(mixin)
504
- end
505
- status 200
506
- end
507
-
508
- delete '*' do
509
-
510
- # unassociate resources specified by URI in payload from mixin specified by request location
511
- if request.path_info == '/'
512
- categories = OCCI::Registry.get.kinds
513
- else
514
- categories = [OCCI::Registry.get_by_location(request.path_info.rpartition('/').first + '/')]
515
- end
516
-
517
- categories.each do |category|
518
- case category
519
- when OCCI::Core::Mixin
520
- mixin = category
521
- OCCI::Log.debug("### Deleting entities from mixin #{mixin.type_identifier} ###")
522
- @request_collection.locations.each do |location|
523
- uuid = location.to_s.rpartition('/').last
524
- mixin.entities.delete_if { |entity| entity.id == uuid }
525
- end
526
- when OCCI::Core::Kind
527
- kind = category
528
- if request.path_info.end_with?('/')
529
- if @request_collection.mixins.any?
530
- @request_collection.mixins.each do |mixin|
531
- OCCI::Log.debug("### Deleting entities from kind #{kind.type_identifier} with mixin #{mixin.type_identifier} ###")
532
- kind.entities.each { |entity| OCCI::Backend::Manager.signal_resource(@backend, OCCI::Backend::RESOURCE_DELETE, entity) if mixin.include?(entity) }
533
- kind.entities.delete_if? { |entity| mixin.include?(entity) }
534
- # TODO: links
535
- end
536
- else
537
- # TODO: links
538
- OCCI::Log.debug("### Deleting entities from kind #{kind.type_identifier} ###")
539
- kind.entities.each { |resource| OCCI::Backend::Manager.signal_resource(@backend, OCCI::Backend::RESOURCE_DELETE, resource) }
540
- kind.entities.clear
541
- end
542
- else
543
- uuid = request.path_info.rpartition('/').last
544
- OCCI::Log.debug("### Deleting entity with id #{uuid} from kind #{kind.type_identifier} ###")
545
- OCCI::Backend::Manager.signal_resource(@backend, OCCI::Backend::RESOURCE_DELETE, entity)
546
- kind.entities.delete_if? { |entity| entity.id == uuid }
547
- end
548
- end
549
- end
550
-
551
- # delete entities
552
-
553
-
554
- # # Location references a mixin => unassociate all provided resources (by X_OCCI_LOCATION) from it
555
- # object = OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info)
556
- # if object != nil && object.kind_of?(OCCI::Core::Mixin)
557
- # mixin = OCCI::Rendering::HTTP::LocationRegistry.get_object(request.path_info)
558
- # logger.info("Unassociating entities from mixin: #{mixin}")
559
- #
560
- # @occi_request.locations.each do |loc|
561
- # entity = OCCI::Rendering::HTTP::LocationRegistry.get_object(URI.parse(loc.chomp('"').reverse.chomp('"').reverse).path)
562
- # mixin.entities.delete(entity)
563
- # entity.mixins.delete(mixin)
564
- # end
565
- # break
566
- # end
567
- #
568
- # entities = OCCI::Rendering::HTTP::LocationRegistry.get_resources_below_location(request.path_info, @occi_request.categories)
569
- #
570
- # unless entities.nil?
571
- # entities.each do |entity|
572
- # location = entity.get_location
573
- # OCCI::Backend::Manager.signal_resource(@backend, OCCI::Backend::RESOURCE_DELETE, entity) if entity.kind_of? OCCI::Core::Resource
574
- # # TODO: delete links in backend!
575
- # entity.delete
576
- # OCCI::Rendering::HTTP::LocationRegistry.unregister(location)
577
- # end
578
- # break
579
- # end
580
- #
581
- # response.status = OCCI::Rendering::HTTP::Response::HTTP_NOT_FOUND
582
- # # This must be the last statement in this block, so that sinatra does not try to respond with random body content
583
- # # (or fail utterly while trying to do that!)
584
- # nil
585
-
586
- end
587
-
588
- error do
589
- OCCI::Log.error(sinatra.error)
590
- 'Sorry there was a nasty error - ' + env['sinatra.error'].name
591
- end
592
-
593
- end
594
- end