occi-api 4.2.0.beta.2 → 4.2.0.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/occi/api/client/client_base.rb +343 -112
- data/lib/occi/api/client/client_http.rb +99 -126
- data/lib/occi/api/client/errors.rb +4 -1
- data/lib/occi/api/client/errors/ambiguous_name_error.rb +5 -0
- data/lib/occi/api/client/errors/authn_error.rb +2 -4
- data/lib/occi/api/client/errors/location_error.rb +5 -0
- data/lib/occi/api/client/errors/not_implemented_error.rb +5 -0
- data/lib/occi/api/client/errors/type_mismatch_error.rb +5 -0
- data/lib/occi/api/client/http/authn_plugins/base.rb +1 -1
- data/lib/occi/api/client/http/authn_plugins/keystone.rb +2 -2
- data/lib/occi/api/version.rb +1 -1
- metadata +6 -2
@@ -5,13 +5,8 @@ module Occi
|
|
5
5
|
class ClientBase
|
6
6
|
|
7
7
|
# a few attributes which should be visible outside the client
|
8
|
-
attr_reader :endpoint
|
9
|
-
attr_reader :
|
10
|
-
attr_reader :media_type
|
11
|
-
attr_reader :connected
|
12
|
-
attr_reader :model
|
13
|
-
attr_reader :logger
|
14
|
-
attr_reader :last_response
|
8
|
+
attr_reader :endpoint, :auth_options, :media_type
|
9
|
+
attr_reader :connected, :model, :logger, :last_response
|
15
10
|
attr_reader :options
|
16
11
|
|
17
12
|
def initialize(options = {})
|
@@ -23,17 +18,17 @@ module Occi
|
|
23
18
|
:media_type => nil
|
24
19
|
}
|
25
20
|
|
26
|
-
options = options.marshal_dump if options.is_a?
|
27
|
-
@options = defaults.merge
|
21
|
+
options = options.marshal_dump if options.is_a?(OpenStruct)
|
22
|
+
@options = defaults.merge(options)
|
28
23
|
|
29
24
|
# set Occi::Log
|
30
|
-
|
25
|
+
@logger = get_logger(@options[:log])
|
31
26
|
|
32
27
|
# check the validity and canonize the endpoint URI
|
33
|
-
|
28
|
+
@endpoint = get_endpoint_uri(@options[:endpoint])
|
34
29
|
|
35
30
|
# pass auth options
|
36
|
-
|
31
|
+
@auth_options = get_auth(@options[:auth])
|
37
32
|
|
38
33
|
# verify authN before attempting actual
|
39
34
|
# message exchange with the server; this
|
@@ -42,7 +37,7 @@ module Occi
|
|
42
37
|
preauthenticate
|
43
38
|
|
44
39
|
# set accepted media types
|
45
|
-
|
40
|
+
@media_type = get_media_type(@options[:media_type])
|
46
41
|
|
47
42
|
@connected = false
|
48
43
|
end
|
@@ -82,7 +77,9 @@ module Occi
|
|
82
77
|
#
|
83
78
|
# @param [String] resource type identifier or just type name
|
84
79
|
# @return [Array<String>] list of links
|
85
|
-
def list(resource_type_identifier=nil)
|
80
|
+
def list(resource_type_identifier=nil)
|
81
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
82
|
+
end
|
86
83
|
|
87
84
|
# Retrieves descriptions for available resources specified by a type
|
88
85
|
# identifier or resource location. If no type identifier or location
|
@@ -101,7 +98,9 @@ module Occi
|
|
101
98
|
#
|
102
99
|
# @param [String] resource type identifier, type name or resource location
|
103
100
|
# @return [Occi::Core::Resources] list of resource descriptions
|
104
|
-
def describe(resource_type_identifier=nil)
|
101
|
+
def describe(resource_type_identifier=nil)
|
102
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
103
|
+
end
|
105
104
|
|
106
105
|
# Creates a new resource on the server. Resource must be provided
|
107
106
|
# as an instance of Occi::Core::Entity, e.g. instantiated using
|
@@ -118,7 +117,9 @@ module Occi
|
|
118
117
|
#
|
119
118
|
# @param [Occi::Core::Entity] resource to be created on the server
|
120
119
|
# @return [String] URI of the new resource
|
121
|
-
def create(entity)
|
120
|
+
def create(entity)
|
121
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
122
|
+
end
|
122
123
|
|
123
124
|
# Deploys a compute resource based on an OVF/OVA descriptor available
|
124
125
|
# on a local file system.
|
@@ -128,7 +129,9 @@ module Occi
|
|
128
129
|
#
|
129
130
|
# @param [String] location of an OVF/OVA file
|
130
131
|
# @return [String] URI of the new resource
|
131
|
-
def deploy(location)
|
132
|
+
def deploy(location)
|
133
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
134
|
+
end
|
132
135
|
|
133
136
|
# Deploys a compute resource based on an OVF descriptor available
|
134
137
|
# directly as a String.
|
@@ -138,7 +141,9 @@ module Occi
|
|
138
141
|
#
|
139
142
|
# @param [String] OVF descriptor (e.g., already read from a file or generated)
|
140
143
|
# @return [String] URI of the new resource
|
141
|
-
def deploy_ovf(descriptor)
|
144
|
+
def deploy_ovf(descriptor)
|
145
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
146
|
+
end
|
142
147
|
|
143
148
|
# Deploys a compute resource based on an OVA descriptor available
|
144
149
|
# directly as a String.
|
@@ -148,7 +153,9 @@ module Occi
|
|
148
153
|
#
|
149
154
|
# @param [String] OVA descriptor (e.g., already read from a file or generated)
|
150
155
|
# @return [String] URI of the new resource
|
151
|
-
def deploy_ova(descriptor)
|
156
|
+
def deploy_ova(descriptor)
|
157
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
158
|
+
end
|
152
159
|
|
153
160
|
# Deletes a resource or all resource of a certain resource type
|
154
161
|
# from the server.
|
@@ -160,17 +167,21 @@ module Occi
|
|
160
167
|
#
|
161
168
|
# @param [String] resource type identifier, type name or location
|
162
169
|
# @return [Boolean] status
|
163
|
-
def delete(resource_type_identifier)
|
170
|
+
def delete(resource_type_identifier)
|
171
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
172
|
+
end
|
164
173
|
|
165
174
|
# Triggers given action on a specific resource.
|
166
175
|
#
|
167
176
|
# @example
|
168
177
|
# TODO: add examples
|
169
178
|
#
|
170
|
-
# @param [String] resource
|
171
|
-
# @param [
|
179
|
+
# @param [String] resource type or type identifier
|
180
|
+
# @param [Occi::Core::ActionInstance] type of action
|
172
181
|
# @return [String] resource location
|
173
|
-
def trigger(resource_type_identifier,
|
182
|
+
def trigger(resource_type_identifier, action_instance)
|
183
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
184
|
+
end
|
174
185
|
|
175
186
|
# Refreshes the Occi::Model used inside the client. Useful for
|
176
187
|
# updating the model without creating a new instance or
|
@@ -178,7 +189,9 @@ module Occi
|
|
178
189
|
#
|
179
190
|
# @example
|
180
191
|
# client.refresh
|
181
|
-
def refresh
|
192
|
+
def refresh
|
193
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
194
|
+
end
|
182
195
|
|
183
196
|
##############################################################################
|
184
197
|
######## STUBS END
|
@@ -196,36 +209,121 @@ module Occi
|
|
196
209
|
# @param [String] resource name or resource identifier
|
197
210
|
# @return [Occi::Core::Resource] new resource instance
|
198
211
|
def get_resource(resource_type)
|
199
|
-
Occi::Log.debug("Instantiating #{resource_type}
|
200
|
-
|
201
|
-
type_id = if @model.get_by_id resource_type
|
202
|
-
# we got a resource type identifier
|
203
|
-
resource_type
|
204
|
-
else
|
205
|
-
# we got a resource type name
|
206
|
-
type_ids = @model.kinds.to_a.select { |kind| kind.term == resource_type }
|
207
|
-
type_ids.first.type_identifier if type_ids.any?
|
208
|
-
end
|
212
|
+
Occi::Log.debug("Instantiating #{resource_type.inspect}")
|
209
213
|
|
214
|
+
type_id = get_resource_type_identifier(resource_type)
|
210
215
|
raise "Unknown resource type! #{resource_type.inspect}" unless type_id
|
211
216
|
|
212
|
-
Occi::Core::Resource.new
|
217
|
+
new_resource = Occi::Core::Resource.new(type_id)
|
218
|
+
new_resource.model = @model
|
219
|
+
|
220
|
+
new_resource
|
213
221
|
end
|
214
222
|
|
215
|
-
# Retrieves all
|
223
|
+
# Retrieves all available category types.
|
216
224
|
#
|
217
225
|
# @example
|
218
|
-
# client.
|
226
|
+
# client.get_category_types # => [ "entity", "resource", "link" ]
|
227
|
+
#
|
228
|
+
# @return [Array<String>] list of available category types in a human-readable format
|
229
|
+
def get_category_types
|
230
|
+
@model.categories.to_a.collect { |category| category.term }
|
231
|
+
end
|
232
|
+
|
233
|
+
# Retrieves all available category type identifiers.
|
234
|
+
#
|
235
|
+
# @example
|
236
|
+
# client.get_category_type_identifiers
|
237
|
+
# # => [ "http://schemas.ogf.org/occi/core#entity",
|
238
|
+
# # "http://schemas.ogf.org/occi/core#resource",
|
239
|
+
# # "http://schemas.ogf.org/occi/core#link" ]
|
240
|
+
#
|
241
|
+
# @return [Array<String>] list of available category type identifiers
|
242
|
+
def get_category_type_identifiers
|
243
|
+
@model.categories.to_a.collect { |category| category.type_identifier }
|
244
|
+
end
|
245
|
+
|
246
|
+
# Retrieves available category type identifier for the given category type.
|
247
|
+
#
|
248
|
+
# @example
|
249
|
+
# client.get_category_type_identifier("compute")
|
250
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#compute'
|
251
|
+
#
|
252
|
+
# @return [String, nil] category type identifier for the given category type
|
253
|
+
def get_category_type_identifier(type)
|
254
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
255
|
+
|
256
|
+
cats = @model.categories.to_a.select { |k| k.term == type }
|
257
|
+
tis = cats.collect { |c| c.type_identifier }
|
258
|
+
tis.uniq!
|
259
|
+
|
260
|
+
if tis.length > 1
|
261
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
262
|
+
"Category type #{type.inspect} is ambiguous, use a type identifier!"
|
263
|
+
end
|
264
|
+
|
265
|
+
tis.first
|
266
|
+
end
|
267
|
+
|
268
|
+
# Retrieves all kind type identifiers related to a given type identifier
|
269
|
+
#
|
270
|
+
# @example
|
271
|
+
# client.get_kind_type_identifiers_related_to 'http://schemas.ogf.org/occi/infrastructure#network'
|
219
272
|
# # => [ "http://schemas.ogf.org/occi/infrastructure#network",
|
220
273
|
# # "http://schemas.ogf.org/occi/infrastructure#ipnetwork" ]
|
221
274
|
#
|
222
|
-
# @param [String]
|
223
|
-
# @return [Array<String>] list of available
|
224
|
-
# given type identifier
|
225
|
-
def
|
226
|
-
Occi::Log.debug("Getting
|
227
|
-
collection = @model.get
|
228
|
-
collection.kinds.collect { |kind| kind.type_identifier }
|
275
|
+
# @param [String] type identifier
|
276
|
+
# @return [Array<String>] list of available kind type identifiers related to
|
277
|
+
# the given type identifier
|
278
|
+
def get_kind_type_identifiers_related_to(type_identifier)
|
279
|
+
Occi::Log.debug("Getting kind type identifiers related to #{type_identifier.inspect}")
|
280
|
+
collection = @model.get(type_identifier)
|
281
|
+
collection.kinds.to_a.collect { |kind| kind.type_identifier }
|
282
|
+
end
|
283
|
+
|
284
|
+
# Retrieves all available kind types.
|
285
|
+
#
|
286
|
+
# @example
|
287
|
+
# client.get_kind_types # => [ "entity", "resource", "link" ]
|
288
|
+
#
|
289
|
+
# @return [Array<String>] list of available kind types in a human-readable format
|
290
|
+
def get_kind_types
|
291
|
+
@model.kinds.to_a.collect { |kind| kind.term }
|
292
|
+
end
|
293
|
+
|
294
|
+
# Retrieves all available kind type identifiers.
|
295
|
+
#
|
296
|
+
# @example
|
297
|
+
# client.get_kind_type_identifiers
|
298
|
+
# # => [ "http://schemas.ogf.org/occi/core#entity",
|
299
|
+
# # "http://schemas.ogf.org/occi/core#resource",
|
300
|
+
# # "http://schemas.ogf.org/occi/core#link" ]
|
301
|
+
#
|
302
|
+
# @return [Array<String>] list of available kind type identifiers
|
303
|
+
def get_kind_type_identifiers
|
304
|
+
@model.kinds.to_a.collect { |kind| kind.type_identifier }
|
305
|
+
end
|
306
|
+
|
307
|
+
# Retrieves available kind type identifier for the given kind type.
|
308
|
+
#
|
309
|
+
# @example
|
310
|
+
# client.get_kind_type_identifier("compute")
|
311
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#compute'
|
312
|
+
#
|
313
|
+
# @return [String, nil] kind type identifier for the given kind type
|
314
|
+
def get_kind_type_identifier(type)
|
315
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
316
|
+
|
317
|
+
kinds = @model.kinds.to_a.select { |k| k.term == type }
|
318
|
+
tis = kinds.collect { |k| k.type_identifier }
|
319
|
+
tis.uniq!
|
320
|
+
|
321
|
+
if tis.length > 1
|
322
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
323
|
+
"Kind type #{type.inspect} is ambiguous, use a type identifier!"
|
324
|
+
end
|
325
|
+
|
326
|
+
tis.first
|
229
327
|
end
|
230
328
|
|
231
329
|
# Retrieves all available entity types.
|
@@ -235,21 +333,44 @@ module Occi
|
|
235
333
|
#
|
236
334
|
# @return [Array<String>] list of available entity types in a human-readable format
|
237
335
|
def get_entity_types
|
238
|
-
Occi::
|
239
|
-
|
336
|
+
collection = @model.get(Occi::Core::Entity.kind.type_identifier)
|
337
|
+
collection.kinds.to_a.collect { |kind| kind.term }
|
240
338
|
end
|
241
339
|
|
242
340
|
# Retrieves all available entity type identifiers.
|
243
341
|
#
|
244
342
|
# @example
|
245
|
-
# client.
|
343
|
+
# client.get_kind_type_identifiers
|
246
344
|
# # => [ "http://schemas.ogf.org/occi/core#entity",
|
247
345
|
# # "http://schemas.ogf.org/occi/core#resource",
|
248
346
|
# # "http://schemas.ogf.org/occi/core#link" ]
|
249
347
|
#
|
250
348
|
# @return [Array<String>] list of available entity types in a OCCI ID format
|
251
349
|
def get_entity_type_identifiers
|
252
|
-
|
350
|
+
get_kind_type_identifiers_related_to Occi::Core::Entity.kind.type_identifier
|
351
|
+
end
|
352
|
+
|
353
|
+
# Retrieves available entity type identifier for the given entity type.
|
354
|
+
#
|
355
|
+
# @example
|
356
|
+
# client.get_entity_type_identifier("compute")
|
357
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#compute'
|
358
|
+
#
|
359
|
+
# @return [String, nil] entity type identifier for the given entity type
|
360
|
+
def get_entity_type_identifier(type)
|
361
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
362
|
+
|
363
|
+
collection = @model.get(Occi::Core::Entity.kind.type_identifier)
|
364
|
+
e_kinds = collection.kinds.to_a.select { |e| e.term == type }
|
365
|
+
tis = e_kinds.collect { |e| e.type_identifier }
|
366
|
+
tis.uniq!
|
367
|
+
|
368
|
+
if tis.length > 1
|
369
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
370
|
+
"Entity type #{type.inspect} is ambiguous, use a type identifier!"
|
371
|
+
end
|
372
|
+
|
373
|
+
tis.first
|
253
374
|
end
|
254
375
|
|
255
376
|
# Retrieves all available resource types.
|
@@ -259,9 +380,8 @@ module Occi
|
|
259
380
|
#
|
260
381
|
# @return [Array<String>] list of available resource types in a human-readable format
|
261
382
|
def get_resource_types
|
262
|
-
Occi::
|
263
|
-
collection
|
264
|
-
collection.kinds.collect { |kind| kind.term }
|
383
|
+
collection = @model.get(Occi::Core::Resource.kind.type_identifier)
|
384
|
+
collection.kinds.to_a.collect { |kind| kind.term }
|
265
385
|
end
|
266
386
|
|
267
387
|
# Retrieves all available resource type identifiers.
|
@@ -274,7 +394,30 @@ module Occi
|
|
274
394
|
#
|
275
395
|
# @return [Array<String>] list of available resource types in a Occi ID format
|
276
396
|
def get_resource_type_identifiers
|
277
|
-
|
397
|
+
get_kind_type_identifiers_related_to Occi::Core::Resource.kind.type_identifier
|
398
|
+
end
|
399
|
+
|
400
|
+
# Retrieves available resource type identifier for the given resource type.
|
401
|
+
#
|
402
|
+
# @example
|
403
|
+
# client.get_resource_type_identifier("compute")
|
404
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#compute'
|
405
|
+
#
|
406
|
+
# @return [String, nil] resource type identifier for the given resource type
|
407
|
+
def get_resource_type_identifier(type)
|
408
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
409
|
+
|
410
|
+
collection = @model.get(Occi::Core::Resource.kind.type_identifier)
|
411
|
+
r_kinds = collection.kinds.to_a.select { |r| r.term == type }
|
412
|
+
tis = r_kinds.collect { |r| r.type_identifier }
|
413
|
+
tis.uniq!
|
414
|
+
|
415
|
+
if tis.length > 1
|
416
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
417
|
+
"Resource type #{type.inspect} is ambiguous, use a type identifier!"
|
418
|
+
end
|
419
|
+
|
420
|
+
tis.first
|
278
421
|
end
|
279
422
|
|
280
423
|
# Retrieves all available link types.
|
@@ -284,9 +427,8 @@ module Occi
|
|
284
427
|
#
|
285
428
|
# @return [Array<String>] list of available link types in a human-readable format
|
286
429
|
def get_link_types
|
287
|
-
Occi::
|
288
|
-
collection
|
289
|
-
collection.kinds.collect { |kind| kind.term }
|
430
|
+
collection = @model.get(Occi::Core::Link.kind.type_identifier)
|
431
|
+
collection.kinds.to_a.collect { |kind| kind.term }
|
290
432
|
end
|
291
433
|
|
292
434
|
# Retrieves all available link type identifiers.
|
@@ -298,7 +440,30 @@ module Occi
|
|
298
440
|
#
|
299
441
|
# @return [Array<String>] list of available link types in a OCCI ID format
|
300
442
|
def get_link_type_identifiers
|
301
|
-
|
443
|
+
get_kind_type_identifiers_related_to Occi::Core::Link.kind.type_identifier
|
444
|
+
end
|
445
|
+
|
446
|
+
# Retrieves available link type identifier for the given link type.
|
447
|
+
#
|
448
|
+
# @example
|
449
|
+
# client.get_link_type_identifier("storagelink")
|
450
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#storagelink'
|
451
|
+
#
|
452
|
+
# @return [String, nil] link type identifier for the given link type
|
453
|
+
def get_link_type_identifier(type)
|
454
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
455
|
+
|
456
|
+
collection = @model.get(Occi::Core::Link.kind.type_identifier)
|
457
|
+
l_kinds = collection.kinds.to_a.select { |r| r.term == type }
|
458
|
+
tis = l_kinds.collect { |r| r.type_identifier }
|
459
|
+
tis.uniq!
|
460
|
+
|
461
|
+
if tis.length > 1
|
462
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
463
|
+
"Link type #{type.inspect} is ambiguous, use a type identifier!"
|
464
|
+
end
|
465
|
+
|
466
|
+
tis.first
|
302
467
|
end
|
303
468
|
|
304
469
|
# Looks up a mixin using its name and, optionally, a type as well.
|
@@ -404,16 +569,16 @@ module Occi
|
|
404
569
|
# @return [Occi::Core::Mixins] collection of available mixins
|
405
570
|
def get_mixins(type = nil)
|
406
571
|
unless type.blank?
|
407
|
-
|
572
|
+
type_id = get_mixin_type_identifier(type)
|
573
|
+
unless type_id
|
408
574
|
raise ArgumentError,
|
409
575
|
"There is no such mixin type registered in the model! #{type.inspect}"
|
410
576
|
end
|
411
577
|
|
412
|
-
|
413
|
-
mixins = @model.mixins.to_a.select { |m| m.related_to?(type) }
|
578
|
+
mixins = @model.mixins.to_a.select { |m| m.related_to?(type_id) }
|
414
579
|
|
415
580
|
# drop the type mixin itself
|
416
|
-
mixins.delete_if { |m| m.type_identifier ==
|
581
|
+
mixins.delete_if { |m| m.type_identifier == type_id }
|
417
582
|
else
|
418
583
|
# we did not get a type, return all mixins
|
419
584
|
mixins = Occi::Core::Mixins.new(@model.mixins)
|
@@ -479,8 +644,18 @@ module Occi
|
|
479
644
|
#
|
480
645
|
# @return [String, nil] mixin type identifier for the given mixin type
|
481
646
|
def get_mixin_type_identifier(type)
|
482
|
-
|
483
|
-
|
647
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
648
|
+
|
649
|
+
mixins = @model.mixins.to_a.select { |m| m.term == type }
|
650
|
+
tis = mixins.collect { |m| m.type_identifier }
|
651
|
+
tis.uniq!
|
652
|
+
|
653
|
+
if tis.length > 1
|
654
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
655
|
+
"Mixin type #{type.inspect} is ambiguous, use a type identifier!"
|
656
|
+
end
|
657
|
+
|
658
|
+
tis.first
|
484
659
|
end
|
485
660
|
|
486
661
|
# Retrieves available os_tpls from the model.
|
@@ -490,7 +665,7 @@ module Occi
|
|
490
665
|
#
|
491
666
|
# @return [Occi::Core::Mixins] collection containing all registered OS templates
|
492
667
|
def get_os_templates
|
493
|
-
get_mixins
|
668
|
+
get_mixins Occi::Infrastructure::OsTpl.mixin.type_identifier
|
494
669
|
end
|
495
670
|
alias_method :get_os_tpls, :get_os_templates
|
496
671
|
|
@@ -501,53 +676,90 @@ module Occi
|
|
501
676
|
#
|
502
677
|
# @return [Occi::Core::Mixins] collection containing all registered resource templates
|
503
678
|
def get_resource_templates
|
504
|
-
get_mixins
|
679
|
+
get_mixins Occi::Infrastructure::ResourceTpl.mixin.type_identifier
|
505
680
|
end
|
506
681
|
alias_method :get_resource_tpls, :get_resource_templates
|
507
682
|
|
508
|
-
# Returns the path for a given
|
683
|
+
# Returns the path for a given kind type identifier
|
509
684
|
#
|
510
685
|
# @example
|
511
|
-
#
|
686
|
+
# path_for_kind_type_identifier "http://schemas.ogf.org/occi/infrastructure#compute"
|
512
687
|
# # => "/compute/"
|
513
|
-
#
|
688
|
+
# path_for_kind_type_identifier "http://localhost:3300/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
514
689
|
# # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
515
690
|
#
|
516
|
-
# @param [String]
|
691
|
+
# @param [String] kind type identifier
|
517
692
|
# @return [String]
|
518
|
-
def
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
if
|
523
|
-
#we got an
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
raise
|
693
|
+
def path_for_kind_type_identifier(kind_type_identifier)
|
694
|
+
raise ArgumentError,
|
695
|
+
"Kind type identifier is a required argument!" if kind_type_identifier.blank?
|
696
|
+
|
697
|
+
if kind_type_identifier.start_with?(@endpoint.to_s) || kind_type_identifier.start_with?('/')
|
698
|
+
#we got an instance link
|
699
|
+
return sanitize_instance_link(kind_type_identifier)
|
700
|
+
end
|
701
|
+
|
702
|
+
kind_type_id = get_kind_type_identifier(kind_type_identifier)
|
703
|
+
unless kind_type_id
|
704
|
+
raise ArgumentError,
|
705
|
+
"There is no such kind type registered in the model! #{kind_type_identifier.inspect}"
|
706
|
+
end
|
707
|
+
|
708
|
+
kinds = @model.kinds.select { |kind| kind.type_identifier == kind_type_id }
|
709
|
+
path_for_instance(kinds.first)
|
710
|
+
end
|
711
|
+
|
712
|
+
# Returns the path for a given instance, instances not providing
|
713
|
+
# path information will raise an exception.
|
714
|
+
#
|
715
|
+
# @example
|
716
|
+
# path_for_instance Occi::Infrastructure::Network.new
|
717
|
+
# # => "/network/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
718
|
+
# path_for_instance Occi::Infrastructure::Compute.new
|
719
|
+
# # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
720
|
+
# path_for_instance Occi::Core::Mixin.new
|
721
|
+
# # => "/mixin/my_mixin/"
|
722
|
+
# path_for_instance Occi::Infrastructure::Storagelink.new
|
723
|
+
# # => "/link/storagelink/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
724
|
+
#
|
725
|
+
# @param [Object] instance
|
726
|
+
# @return [String] path for the given instance
|
727
|
+
def path_for_instance(instance)
|
728
|
+
unless instance.respond_to?(:location)
|
729
|
+
raise Occi::Api::Client::Errors::TypeMismatchError,
|
730
|
+
"Expected an instance responding to #location, " \
|
731
|
+
"got #{instance.class.name.inspect}"
|
732
|
+
end
|
733
|
+
|
734
|
+
if instance.location.blank?
|
735
|
+
raise Occi::Api::Client::Errors::LocationError,
|
736
|
+
"Instance of #{instance.class.name.inspect} has " \
|
737
|
+
"an empty location"
|
530
738
|
end
|
739
|
+
|
740
|
+
instance.location
|
531
741
|
end
|
532
742
|
|
533
|
-
# Extracts
|
743
|
+
# Extracts path from an instance link. It will remove the leading @endpoint
|
534
744
|
# and replace it with a slash.
|
535
745
|
#
|
536
746
|
# @example
|
537
|
-
#
|
747
|
+
# sanitize_instance_link "http://localhost:3300/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
538
748
|
# # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
539
|
-
#
|
749
|
+
# sanitize_instance_link "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
540
750
|
# # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
541
751
|
#
|
542
|
-
# @param [String] string containing the full
|
752
|
+
# @param [String] string containing the full instance link
|
543
753
|
# @return [String] extracted path, with a leading slash
|
544
|
-
def
|
754
|
+
def sanitize_instance_link(instance_link)
|
545
755
|
# everything starting with '/' is considered to be a resource path
|
546
|
-
return
|
756
|
+
return instance_link if instance_link.start_with? '/'
|
547
757
|
|
548
|
-
|
758
|
+
unless instance_link.start_with?(@endpoint.to_s)
|
759
|
+
raise ArgumentError, "Resource link #{instance_link.inspect} is not valid!"
|
760
|
+
end
|
549
761
|
|
550
|
-
|
762
|
+
URI(instance_link).request_uri
|
551
763
|
end
|
552
764
|
|
553
765
|
protected
|
@@ -560,29 +772,36 @@ module Occi
|
|
560
772
|
# are: ["basic", "digest", "x509", "none"]
|
561
773
|
#
|
562
774
|
# @example
|
563
|
-
#
|
564
|
-
#
|
565
|
-
#
|
566
|
-
#
|
775
|
+
# get_auth { :type => "none" }
|
776
|
+
# get_auth { :type => "basic", :username => "123", :password => "321" }
|
777
|
+
# get_auth { :type => "digest", :username => "123", :password => "321" }
|
778
|
+
# get_auth { :type => "x509", :user_cert => "~/cert.pem",
|
567
779
|
# :user_cert_password => "321", :ca_path => nil }
|
568
780
|
#
|
569
781
|
# @param [Hash] authentication options
|
570
782
|
# @param [Boolean] allow fallback-only options
|
571
|
-
|
783
|
+
# @return [Hash] transformed hash with authN information
|
784
|
+
def get_auth(auth_options, fallback = false)
|
785
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
786
|
+
end
|
572
787
|
|
573
788
|
# Attempts to establish a preliminary connection with the server
|
574
789
|
# to verify provided credentials and perform fallback authN
|
575
|
-
# if necessary. Has to be invoked after
|
576
|
-
def preauthenticate
|
790
|
+
# if necessary. Has to be invoked after @auth_options have been set.
|
791
|
+
def preauthenticate
|
792
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
793
|
+
end
|
577
794
|
|
578
795
|
# Sets media type. Will choose either application/occi+json or text/plain
|
579
796
|
# based on the formats supported by the server.
|
580
797
|
#
|
581
798
|
# @example
|
582
|
-
#
|
799
|
+
# get_media_type # => 'application/occi+json'
|
583
800
|
#
|
584
801
|
# @return [String] chosen media type
|
585
|
-
def
|
802
|
+
def get_media_type(force_type = nil)
|
803
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
804
|
+
end
|
586
805
|
|
587
806
|
##############################################################################
|
588
807
|
######## STUBS END
|
@@ -592,40 +811,52 @@ module Occi
|
|
592
811
|
# instances to the rOCCI client.
|
593
812
|
#
|
594
813
|
# @example
|
595
|
-
#
|
814
|
+
# get_logger { :out => STDERR, :level => Occi::Log::WARN, :logger => nil }
|
596
815
|
#
|
597
816
|
# @param [Hash] logger options
|
598
|
-
|
817
|
+
# @return [Occi::Log] instance of the logger
|
818
|
+
def get_logger(log_options)
|
599
819
|
unless log_options[:logger] && log_options[:logger].kind_of?(Occi::Log)
|
600
|
-
|
601
|
-
|
820
|
+
logger = Occi::Log.new(log_options[:out])
|
821
|
+
logger.level = log_options[:level]
|
822
|
+
else
|
823
|
+
logger = log_options[:logger]
|
602
824
|
end
|
825
|
+
|
826
|
+
logger
|
603
827
|
end
|
604
828
|
|
605
|
-
# Checks whether the given endpoint URI is valid and
|
606
|
-
#
|
829
|
+
# Checks whether the given endpoint URI is valid and converts it
|
830
|
+
# to a URI instance.
|
607
831
|
#
|
608
832
|
# @example
|
609
|
-
#
|
833
|
+
# get_endpoint_uri "http://localhost:3300" # => #<URI::*>
|
610
834
|
#
|
611
835
|
# @param [String] endpoint URI in a non-canonical string
|
612
|
-
# @return [
|
613
|
-
def
|
614
|
-
|
615
|
-
|
836
|
+
# @return [URI] canonical endpoint URI
|
837
|
+
def get_endpoint_uri(endpoint)
|
838
|
+
unless endpoint =~ URI::ABS_URI
|
839
|
+
raise "Endpoint not a valid absolute URI! #{endpoint.inspect}"
|
840
|
+
end
|
841
|
+
|
842
|
+
# normalize URIs, remove trailing slashes
|
843
|
+
endpoint = URI(endpoint)
|
844
|
+
endpoint.path = endpoint.path.gsub(/\/+/, '/').chomp('/')
|
845
|
+
|
846
|
+
endpoint
|
616
847
|
end
|
617
848
|
|
618
849
|
# Creates an Occi::Model from data retrieved from the server.
|
619
850
|
#
|
620
851
|
# @example
|
621
|
-
#
|
622
|
-
#
|
852
|
+
# model_collection = get('/-/')
|
853
|
+
# get_model model_collection # => #<Occi::Model>
|
623
854
|
#
|
624
855
|
# @param [Occi::Collection] parsed representation of server's model
|
625
856
|
# @return [Occi::Model] Model instance
|
626
|
-
def
|
857
|
+
def get_model(model_collection)
|
627
858
|
# build model
|
628
|
-
|
859
|
+
Occi::Model.new(model_collection)
|
629
860
|
end
|
630
861
|
|
631
862
|
# Returns mixin type identifiers for os_tpl mixins
|
@@ -88,8 +88,8 @@ module Occi
|
|
88
88
|
|
89
89
|
# get model information from the endpoint
|
90
90
|
# and create Occi::Model instance
|
91
|
-
|
92
|
-
|
91
|
+
model_collection = get('/-/')
|
92
|
+
@model = get_model(model_collection)
|
93
93
|
|
94
94
|
# auto-connect?
|
95
95
|
@connected = @options[:auto_connect]
|
@@ -98,33 +98,18 @@ module Occi
|
|
98
98
|
# @see Occi::Api::Client::ClientBase
|
99
99
|
def list(resource_type_identifier=nil)
|
100
100
|
if resource_type_identifier
|
101
|
-
|
102
|
-
|
103
|
-
|kind| kind.term == resource_type_identifier
|
104
|
-
}
|
105
|
-
if kinds.any?
|
106
|
-
resource_type_identifier = kinds.first.type_identifier
|
107
|
-
end
|
108
|
-
|
109
|
-
raise 'Unkown resource type identifier!' unless resource_type_identifier
|
110
|
-
unless @model.get_by_id resource_type_identifier
|
111
|
-
raise "Resource type identifier not allowed with this model! [#{resource_type_identifier}]"
|
112
|
-
end
|
113
|
-
|
114
|
-
# split the type identifier and get the most important part
|
115
|
-
uri_part = resource_type_identifier.split('#').last
|
116
|
-
|
117
|
-
# request uri-list from the server
|
118
|
-
path = uri_part + '/'
|
101
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
102
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
119
103
|
end
|
120
104
|
|
121
105
|
path = '/' unless path
|
106
|
+
path = "#{@endpoint.to_s}#{path}"
|
122
107
|
|
123
108
|
headers = self.class.headers.clone
|
124
109
|
headers['Accept'] = 'text/uri-list'
|
125
110
|
|
126
111
|
response = self.class.get(
|
127
|
-
|
112
|
+
path,
|
128
113
|
:headers => headers
|
129
114
|
)
|
130
115
|
|
@@ -134,20 +119,13 @@ module Occi
|
|
134
119
|
|
135
120
|
# @see Occi::Api::Client::ClientBase
|
136
121
|
def describe(resource_type_identifier=nil)
|
137
|
-
|
138
|
-
# convert type to type identifier whenever possible
|
139
122
|
if resource_type_identifier
|
140
|
-
|
141
|
-
|kind| kind.term == resource_type_identifier
|
142
|
-
}
|
143
|
-
if kinds.any?
|
144
|
-
resource_type_identifier = kinds.first.type_identifier
|
145
|
-
end
|
123
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
146
124
|
end
|
147
125
|
|
148
126
|
descriptions = Occi::Collection.new
|
149
127
|
|
150
|
-
if resource_type_identifier.
|
128
|
+
if resource_type_identifier.blank?
|
151
129
|
# no filters, describe all available resources
|
152
130
|
descriptions.merge! get('/')
|
153
131
|
elsif @model.get_by_id(resource_type_identifier)
|
@@ -157,13 +135,13 @@ module Occi
|
|
157
135
|
|
158
136
|
# make the requests
|
159
137
|
locations.each do |location|
|
160
|
-
|
138
|
+
path = sanitize_instance_link(location)
|
139
|
+
descriptions.merge! get(path)
|
161
140
|
end
|
162
|
-
elsif resource_type_identifier.start_with?(@endpoint) || resource_type_identifier.start_with?('/')
|
163
|
-
# this is a link of a specific resource (obsolute or relative)
|
164
|
-
descriptions.merge! get(sanitize_resource_link(resource_type_identifier))
|
165
141
|
else
|
166
|
-
|
142
|
+
# this is a link of a specific resource (absolute or relative)
|
143
|
+
path = sanitize_instance_link(resource_type_identifier)
|
144
|
+
descriptions.merge! get(path)
|
167
145
|
end
|
168
146
|
|
169
147
|
descriptions.resources
|
@@ -171,30 +149,27 @@ module Occi
|
|
171
149
|
|
172
150
|
# @see Occi::Api::Client::ClientBase
|
173
151
|
def create(entity)
|
152
|
+
raise "#{entity.class.name.inspect} not an entity!" unless entity.kind_of? Occi::Core::Entity
|
174
153
|
|
175
|
-
|
176
|
-
|
177
|
-
Occi::Log.debug "Entity kind: #{entity.kind}"
|
178
|
-
kind = entity.kind
|
179
|
-
raise "No kind found for #{entity}" unless kind
|
154
|
+
Occi::Log.debug "Entity kind: #{entity.kind.type_identifier.inspect}"
|
155
|
+
raise "No kind found for #{entity.inspect}" unless entity.kind
|
180
156
|
|
181
157
|
# get location for this kind of entity
|
182
|
-
|
183
|
-
location = kind.location
|
158
|
+
path = path_for_kind_type_identifier(entity.kind.type_identifier)
|
184
159
|
collection = Occi::Collection.new
|
185
160
|
|
186
161
|
# is this entity a Resource or a Link?
|
187
|
-
Occi::Log.debug "Entity class: #{entity.class.name}"
|
162
|
+
Occi::Log.debug "Entity class: #{entity.class.name.inspect}"
|
188
163
|
collection.resources << entity if entity.kind_of? Occi::Core::Resource
|
189
164
|
collection.links << entity if entity.kind_of? Occi::Core::Link
|
190
165
|
|
191
166
|
# make the request
|
192
|
-
post
|
167
|
+
post path, collection
|
193
168
|
end
|
194
169
|
|
195
170
|
# @see Occi::Api::Client::ClientBase
|
196
171
|
def deploy(location)
|
197
|
-
raise "File #{location} does not exist!" unless File.exist? location
|
172
|
+
raise "File #{location.inspect} does not exist!" unless File.exist? location
|
198
173
|
|
199
174
|
file = File.read(location)
|
200
175
|
|
@@ -209,12 +184,14 @@ module Occi
|
|
209
184
|
|
210
185
|
# @see Occi::Api::Client::ClientBase
|
211
186
|
def deploy_ovf(descriptor)
|
212
|
-
media_types = self.class.head(@endpoint).headers['accept'].to_s
|
187
|
+
media_types = self.class.head(@endpoint.to_s).headers['accept'].to_s
|
213
188
|
|
189
|
+
path = path_for_kind_type_identifier(Occi::Infrastructure::Compute.type_identifier)
|
190
|
+
path = "#{@endpoint.to_s}#{path}"
|
214
191
|
if media_types.include? 'application/ovf'
|
215
192
|
headers = self.class.headers.clone
|
216
193
|
headers['Content-Type'] = 'application/ovf'
|
217
|
-
self.class.post(
|
194
|
+
self.class.post(path,
|
218
195
|
:body => descriptor,
|
219
196
|
:headers => headers)
|
220
197
|
else
|
@@ -224,12 +201,14 @@ module Occi
|
|
224
201
|
|
225
202
|
# @see Occi::Api::Client::ClientBase
|
226
203
|
def deploy_ova(descriptor)
|
227
|
-
media_types = self.class.head(@endpoint).headers['accept'].to_s
|
204
|
+
media_types = self.class.head(@endpoint.to_s).headers['accept'].to_s
|
228
205
|
|
206
|
+
path = path_for_kind_type_identifier(Occi::Infrastructure::Compute.type_identifier)
|
207
|
+
path = "#{@endpoint.to_s}#{path}"
|
229
208
|
if media_types.include? ' application/ova '
|
230
209
|
headers = self.class.headers.clone
|
231
210
|
headers['Content-Type'] = 'application/ova'
|
232
|
-
self.class.post(
|
211
|
+
self.class.post(path,
|
233
212
|
:body => descriptor,
|
234
213
|
:headers => headers)
|
235
214
|
else
|
@@ -239,47 +218,31 @@ module Occi
|
|
239
218
|
|
240
219
|
# @see Occi::Api::Client::ClientBase
|
241
220
|
def delete(resource_type_identifier)
|
242
|
-
raise 'Resource not provided!'
|
243
|
-
path =
|
221
|
+
raise 'Resource not provided!' if resource_type_identifier.blank?
|
222
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
244
223
|
|
245
|
-
Occi::Log.debug("Deleting #{path}
|
224
|
+
Occi::Log.debug("Deleting #{path.inspect} for #{resource_type_identifier.inspect}")
|
246
225
|
del path
|
247
226
|
end
|
248
227
|
|
249
228
|
# @see Occi::Api::Client::ClientBase
|
250
|
-
def trigger(resource_type_identifier,
|
229
|
+
def trigger(resource_type_identifier, action_instance)
|
251
230
|
# TODO: not tested
|
252
|
-
raise 'Resource not provided!'
|
253
|
-
type_identifiers = @model.kinds.select {
|
254
|
-
|kind| kind.term == resource_type_identifier
|
255
|
-
}
|
256
|
-
|
257
|
-
if type_identifiers.any?
|
258
|
-
type_identifier = @model.kinds.select {
|
259
|
-
|kind| kind.term == resource_type_identifier
|
260
|
-
}.first.type_identifier
|
261
|
-
|
262
|
-
location = @model.get_by_id(type_identifier).location
|
263
|
-
resource_type_identifier = @endpoint + location
|
264
|
-
end
|
265
|
-
|
266
|
-
raise "Unknown resource identifier! #{resource_type_identifier}" unless resource_type_identifier.start_with? @endpoint
|
231
|
+
raise 'Resource not provided!' if resource_type_identifier.blank?
|
267
232
|
|
268
|
-
#
|
269
|
-
|
270
|
-
|
271
|
-
collection.actions << Occi::Core::Action.new(scheme + '#', term)
|
233
|
+
#
|
234
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
235
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
272
236
|
|
273
237
|
# make the request
|
274
|
-
path
|
275
|
-
post path, collection
|
238
|
+
post path, action_instance
|
276
239
|
end
|
277
240
|
|
278
241
|
# @see Occi::Api::Client::ClientBase
|
279
242
|
def refresh
|
280
243
|
# re-download the model from the server
|
281
|
-
|
282
|
-
|
244
|
+
model_collection = get('/-/')
|
245
|
+
@model = get_model(model_collection)
|
283
246
|
end
|
284
247
|
|
285
248
|
private
|
@@ -294,10 +257,10 @@ module Occi
|
|
294
257
|
# @param [String] path for the GET request
|
295
258
|
# @param [Occi::Collection] collection of filters
|
296
259
|
# @return [Occi::Collection] parsed result of the request
|
297
|
-
def get(path='', filter=nil)
|
298
|
-
|
299
|
-
path = path
|
300
|
-
|
260
|
+
def get(path='/', filter=nil)
|
261
|
+
relative_path = path
|
262
|
+
path = "#{@endpoint.to_s}#{path}"
|
263
|
+
# apply filters if present
|
301
264
|
response = if filter
|
302
265
|
categories = filter.categories.collect { |category| category.to_text }.join(',')
|
303
266
|
attributes = filter.entities.collect { |entity| entity.attributes.combine.collect { |k, v| k + '=' + v } }.join(',')
|
@@ -307,28 +270,28 @@ module Occi
|
|
307
270
|
headers['Category'] = categories unless categories.empty?
|
308
271
|
headers['X-OCCI-Attributes'] = attributes unless attributes.empty?
|
309
272
|
|
310
|
-
self.class.get(
|
273
|
+
self.class.get(path, :headers => headers)
|
311
274
|
else
|
312
|
-
self.class.get(
|
275
|
+
self.class.get(path)
|
313
276
|
end
|
314
277
|
|
315
278
|
response_msg = response_message response
|
316
279
|
raise "HTTP GET failed! #{response_msg}" unless response.code.between? 200, 300
|
317
280
|
|
318
|
-
Occi::Log.debug "Response location: #{
|
319
|
-
kind = @model.get_by_location(
|
281
|
+
Occi::Log.debug "Response location: #{relative_path.inspect}"
|
282
|
+
kind = @model.get_by_location(relative_path) if @model
|
320
283
|
|
321
|
-
Occi::Log.debug "Response kind: #{kind}"
|
284
|
+
Occi::Log.debug "Response kind: #{kind.inspect}"
|
322
285
|
|
323
|
-
|
324
|
-
|
325
|
-
entity_type = Occi::Core::Link
|
286
|
+
entity_type = nil
|
287
|
+
if kind && kind.related_to?(Occi::Core::Link)
|
288
|
+
entity_type = Occi::Core::Link
|
326
289
|
end
|
327
290
|
|
328
291
|
entity_type = Occi::Core::Resource unless entity_type
|
329
292
|
|
330
|
-
Occi::Log.debug "Parser call: #{response.content_type} #{path.include?('
|
331
|
-
collection = Occi::Parser.parse(response.content_type, response.body, path.include?('
|
293
|
+
Occi::Log.debug "Parser call: #{response.content_type} #{path.include?('/-/')} #{entity_type} #{response.headers.inspect}"
|
294
|
+
collection = Occi::Parser.parse(response.content_type, response.body, path.include?('/-/'), entity_type, response.headers)
|
332
295
|
|
333
296
|
Occi::Log.debug "Parsed collection: empty? #{collection.empty?}"
|
334
297
|
collection
|
@@ -350,27 +313,28 @@ module Occi
|
|
350
313
|
# @param [Occi::Collection] resource data to be POSTed
|
351
314
|
# @return [String] URI location
|
352
315
|
def post(path, collection)
|
353
|
-
|
354
|
-
path = path.gsub(/\A\//, '')
|
316
|
+
raise ArgumentError, "Path is a required argument!" if path.blank?
|
355
317
|
|
356
318
|
headers = self.class.headers.clone
|
357
319
|
headers['Content-Type'] = @media_type
|
358
320
|
|
321
|
+
path = "#{@endpoint.to_s}#{path}"
|
322
|
+
|
359
323
|
response = case @media_type
|
360
324
|
when 'application/occi+json'
|
361
|
-
self.class.post(
|
325
|
+
self.class.post(path,
|
362
326
|
:body => collection.to_json,
|
363
327
|
:headers => headers)
|
364
328
|
when 'text/occi'
|
365
|
-
self.class.post(
|
329
|
+
self.class.post(path,
|
366
330
|
:headers => collection.to_header.merge(headers))
|
367
331
|
else
|
368
|
-
self.class.post(
|
332
|
+
self.class.post(path,
|
369
333
|
:body => collection.to_text,
|
370
334
|
:headers => headers)
|
371
335
|
end
|
372
336
|
|
373
|
-
response_msg = response_message
|
337
|
+
response_msg = response_message(response)
|
374
338
|
|
375
339
|
case response.code
|
376
340
|
when 200
|
@@ -403,27 +367,28 @@ module Occi
|
|
403
367
|
# @param [Occi::Collection] resource data to send
|
404
368
|
# @return [Occi::Collection] parsed result of the request
|
405
369
|
def put(path, collection)
|
406
|
-
|
407
|
-
path = path.gsub(/\A\//, '')
|
370
|
+
raise ArgumentError, "Path is a required argument!" if path.blank?
|
408
371
|
|
409
372
|
headers = self.class.headers.clone
|
410
373
|
headers['Content-Type'] = @media_type
|
411
374
|
|
375
|
+
path = "#{@endpoint.to_s}#{path}"
|
376
|
+
|
412
377
|
response = case @media_type
|
413
378
|
when 'application/occi+json'
|
414
|
-
self.class.post(
|
379
|
+
self.class.post(path,
|
415
380
|
:body => collection.to_json,
|
416
381
|
:headers => headers)
|
417
382
|
when 'text/occi'
|
418
|
-
self.class.post(
|
383
|
+
self.class.post(path,
|
419
384
|
:headers => collection.to_header.merge(headers))
|
420
385
|
else
|
421
|
-
self.class.post(
|
386
|
+
self.class.post(path,
|
422
387
|
:body => collection.to_text,
|
423
388
|
:headers => headers)
|
424
389
|
end
|
425
390
|
|
426
|
-
response_msg = response_message
|
391
|
+
response_msg = response_message(response)
|
427
392
|
|
428
393
|
case response.code
|
429
394
|
when 200, 201
|
@@ -442,38 +407,37 @@ module Occi
|
|
442
407
|
# @param [Occi::Collection] collection of filters (currently NOT used)
|
443
408
|
# @return [Boolean] status
|
444
409
|
def del(path, filter=nil)
|
445
|
-
|
446
|
-
path = path.gsub(/\A\//, '')
|
410
|
+
raise ArgumentError, "Path is a required argument!" if path.blank?
|
447
411
|
|
448
|
-
response = self.class.delete(@endpoint
|
412
|
+
response = self.class.delete("#{@endpoint.to_s}#{path}")
|
449
413
|
|
450
|
-
response_msg = response_message
|
414
|
+
response_msg = response_message(response)
|
451
415
|
raise "HTTP DELETE failed! #{response_msg}" unless response.code.between? 200, 300
|
452
416
|
|
453
417
|
true
|
454
418
|
end
|
455
419
|
|
456
420
|
# @see Occi::Api::Client::ClientBase
|
457
|
-
def
|
458
|
-
super
|
421
|
+
def get_logger(log_options)
|
422
|
+
logger = super(log_options)
|
423
|
+
self.class.debug_output $stderr if logger.level == Occi::Log::DEBUG
|
459
424
|
|
460
|
-
|
425
|
+
logger
|
461
426
|
end
|
462
427
|
|
463
428
|
# @see Occi::Api::Client::ClientBase
|
464
|
-
def
|
465
|
-
|
466
|
-
|
467
|
-
case @auth_options[:type]
|
429
|
+
def get_auth(auth_options, fallback = false)
|
430
|
+
# select appropriate authN type
|
431
|
+
case auth_options[:type]
|
468
432
|
when "basic"
|
469
|
-
@authn_plugin = Http::AuthnPlugins::Basic.new self,
|
433
|
+
@authn_plugin = Http::AuthnPlugins::Basic.new self, auth_options
|
470
434
|
when "digest"
|
471
|
-
@authn_plugin = Http::AuthnPlugins::Digest.new self,
|
435
|
+
@authn_plugin = Http::AuthnPlugins::Digest.new self, auth_options
|
472
436
|
when "x509"
|
473
|
-
@authn_plugin = Http::AuthnPlugins::X509.new self,
|
437
|
+
@authn_plugin = Http::AuthnPlugins::X509.new self, auth_options
|
474
438
|
when "keystone"
|
475
439
|
raise ::Occi::Api::Client::Errors::AuthnError, "This authN method is for fallback only!" unless fallback
|
476
|
-
@authn_plugin = Http::AuthnPlugins::Keystone.new self,
|
440
|
+
@authn_plugin = Http::AuthnPlugins::Keystone.new self, auth_options
|
477
441
|
when "none", nil
|
478
442
|
@authn_plugin = Http::AuthnPlugins::Dummy.new self
|
479
443
|
else
|
@@ -481,6 +445,8 @@ module Occi
|
|
481
445
|
end
|
482
446
|
|
483
447
|
@authn_plugin.setup
|
448
|
+
|
449
|
+
auth_options
|
484
450
|
end
|
485
451
|
|
486
452
|
# @see Occi::Api::Client::ClientBase
|
@@ -495,7 +461,7 @@ module Occi
|
|
495
461
|
@auth_options[:original_type] = @auth_options[:type]
|
496
462
|
@auth_options[:type] = @authn_plugin.fallbacks.first
|
497
463
|
|
498
|
-
|
464
|
+
@auth_options = get_auth(@auth_options, true)
|
499
465
|
@authn_plugin.authenticate
|
500
466
|
else
|
501
467
|
raise e
|
@@ -504,34 +470,41 @@ module Occi
|
|
504
470
|
end
|
505
471
|
|
506
472
|
# @see Occi::Api::Client::ClientBase
|
507
|
-
def
|
473
|
+
def get_media_type(force_type = nil)
|
508
474
|
# force media_type if provided
|
509
|
-
|
475
|
+
unless force_type.blank?
|
510
476
|
self.class.headers 'Accept' => force_type
|
511
|
-
|
477
|
+
media_type = force_type
|
512
478
|
else
|
513
|
-
media_types = self.class.head(@endpoint).headers['accept']
|
514
|
-
|
515
|
-
|
479
|
+
media_types = self.class.head(@endpoint.to_s).headers['accept']
|
480
|
+
|
481
|
+
Occi::Log.debug("Available media types: #{media_types.inspect}")
|
482
|
+
media_type = case media_types
|
516
483
|
when /application\/occi\+json/
|
517
484
|
'application/occi+json'
|
485
|
+
when /application\/occi\+xml/
|
486
|
+
'application/occi+xml'
|
487
|
+
when /text\/occi/
|
488
|
+
'text/occi'
|
518
489
|
else
|
519
490
|
'text/plain'
|
520
491
|
end
|
521
492
|
end
|
493
|
+
|
494
|
+
media_type
|
522
495
|
end
|
523
496
|
|
524
497
|
# Generates a human-readable response message based on the HTTP response code.
|
525
498
|
#
|
526
499
|
# @example
|
527
|
-
# response_message self.class.delete(@endpoint + path)
|
500
|
+
# response_message self.class.delete(@endpoint.to_s + path)
|
528
501
|
# # => 'HTTP Response status: [200] OK'
|
529
502
|
#
|
530
503
|
# @param [HTTParty::Response] HTTParty response object
|
531
504
|
# @return [String] message
|
532
505
|
def response_message(response)
|
533
506
|
@last_response = response
|
534
|
-
|
507
|
+
"HTTP Response status: [#{response.code.to_s}] #{reason_phrase(response.code)}"
|
535
508
|
end
|
536
509
|
|
537
510
|
# Converts HTTP response codes to human-readable phrases.
|
@@ -16,7 +16,7 @@ module Occi::Api::Client
|
|
16
16
|
def setup(options = {}); end
|
17
17
|
|
18
18
|
def authenticate(options = {})
|
19
|
-
response = @env_ref.class.head
|
19
|
+
response = @env_ref.class.head("#{@env_ref.endpoint.to_s}/-/")
|
20
20
|
raise ::Occi::Api::Client::Errors::AuthnError, "Authentication failed with code #{response.code.to_s}!" unless response.success?
|
21
21
|
end
|
22
22
|
|
@@ -18,7 +18,7 @@ module Occi::Api::Client
|
|
18
18
|
|
19
19
|
def authenticate(options = {})
|
20
20
|
# OCCI-OS doesn't support HEAD method!
|
21
|
-
response = @env_ref.class.get "#{@env_ref.endpoint}
|
21
|
+
response = @env_ref.class.get "#{@env_ref.endpoint.to_s}/-/"
|
22
22
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
23
23
|
"Authentication failed with code #{response.code.to_s}!" unless response.success?
|
24
24
|
end
|
@@ -26,7 +26,7 @@ module Occi::Api::Client
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def set_keystone_base_url
|
29
|
-
response = @env_ref.class.head "#{@env_ref.endpoint}
|
29
|
+
response = @env_ref.class.head "#{@env_ref.endpoint.to_s}/-/"
|
30
30
|
Occi::Log.debug response.inspect
|
31
31
|
|
32
32
|
return if response.success?
|
data/lib/occi/api/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: occi-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.2.0.beta.
|
4
|
+
version: 4.2.0.beta.3
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-12-
|
14
|
+
date: 2013-12-06 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: occi-core
|
@@ -87,7 +87,11 @@ files:
|
|
87
87
|
- lib/occi/api/client/client_base.rb
|
88
88
|
- lib/occi/api/client/client_http.rb
|
89
89
|
- lib/occi/api/client/errors.rb
|
90
|
+
- lib/occi/api/client/errors/ambiguous_name_error.rb
|
90
91
|
- lib/occi/api/client/errors/authn_error.rb
|
92
|
+
- lib/occi/api/client/errors/location_error.rb
|
93
|
+
- lib/occi/api/client/errors/not_implemented_error.rb
|
94
|
+
- lib/occi/api/client/errors/type_mismatch_error.rb
|
91
95
|
- lib/occi/api/client/http/authn_plugins.rb
|
92
96
|
- lib/occi/api/client/http/authn_plugins/base.rb
|
93
97
|
- lib/occi/api/client/http/authn_plugins/basic.rb
|