occi-api 4.2.0.beta.4 → 4.2.0.beta.6
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.
- data/lib/occi-api.rb +5 -1
- data/lib/occi/api/client/authn_utils.rb +84 -76
- data/lib/occi/api/client/base/category_methods.rb +54 -0
- data/lib/occi/api/client/base/entity_methods.rb +172 -0
- data/lib/occi/api/client/base/helpers.rb +91 -0
- data/lib/occi/api/client/base/kind_methods.rb +70 -0
- data/lib/occi/api/client/base/mixin_methods.rb +223 -0
- data/lib/occi/api/client/base/protected_helpers.rb +79 -0
- data/lib/occi/api/client/base/protected_stubs.rb +44 -0
- data/lib/occi/api/client/base/stubs.rb +142 -0
- data/lib/occi/api/client/client_base.rb +65 -860
- data/lib/occi/api/client/client_http.rb +181 -492
- data/lib/occi/api/client/errors.rb +0 -2
- data/lib/occi/api/client/http/authn_plugins.rb +3 -6
- data/lib/occi/api/client/http/code_helpers.rb +64 -0
- data/lib/occi/api/client/http/helpers.rb +99 -0
- data/lib/occi/api/client/http/monkey_patches.rb +2 -0
- data/lib/occi/api/client/http/{httparty_fix.rb → monkey_patches/httparty_fix.rb} +4 -0
- data/lib/occi/api/client/http/{net_http_fix.rb → monkey_patches/net_http_fix.rb} +0 -0
- data/lib/occi/api/client/http/party_wrappers.rb +173 -0
- data/lib/occi/api/dsl.rb +32 -193
- data/lib/occi/api/dsl/helper_methods.rb +22 -0
- data/lib/occi/api/dsl/main_methods.rb +47 -0
- data/lib/occi/api/dsl/mixin_methods.rb +32 -0
- data/lib/occi/api/dsl/type_methods.rb +102 -0
- data/lib/occi/api/version.rb +1 -1
- metadata +20 -4
@@ -1,525 +1,214 @@
|
|
1
1
|
require 'httparty'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
"409" => "Conflict",
|
54
|
-
"410" => "Gone",
|
55
|
-
"411" => "Length Required",
|
56
|
-
"412" => "Precondition Failed",
|
57
|
-
"413" => "Request Entity Too Large",
|
58
|
-
"414" => "Request-URI Too Large",
|
59
|
-
"415" => "Unsupported Media Type",
|
60
|
-
"416" => "Requested range not satisfiable",
|
61
|
-
"417" => "Expectation Failed",
|
62
|
-
"500" => "Internal Server Error",
|
63
|
-
"501" => "Not Implemented",
|
64
|
-
"502" => "Bad Gateway",
|
65
|
-
"503" => "Service Unavailable",
|
66
|
-
"504" => "Gateway Time-out",
|
67
|
-
"505" => "HTTP Version not supported"
|
68
|
-
}
|
69
|
-
|
70
|
-
# Initializes client data structures and retrieves OCCI model
|
71
|
-
# from the server.
|
72
|
-
#
|
73
|
-
# @example
|
74
|
-
# options = {
|
75
|
-
# :endpoint => "http://localhost:3300/",
|
76
|
-
# :auth => {:type => "none"},
|
77
|
-
# :log => {:out => STDERR, :level => Occi::Log::WARN, :logger => nil},
|
78
|
-
# :auto_connect => "value", auto_connect => true,
|
79
|
-
# :media_type => nil
|
80
|
-
# }
|
81
|
-
#
|
82
|
-
# Occi::Api::Client::ClientHttp.new options # => #<Occi::Api::Client::ClientHttp>
|
83
|
-
#
|
84
|
-
# @param [Hash] options, for available options and defaults see examples
|
85
|
-
# @return [Occi::Api::Client::ClientHttp] client instance
|
86
|
-
def initialize(options = {})
|
87
|
-
super options
|
88
|
-
|
89
|
-
# get model information from the endpoint
|
90
|
-
# and create Occi::Model instance
|
91
|
-
model_collection = get('/-/')
|
92
|
-
@model = get_model(model_collection)
|
93
|
-
|
94
|
-
# auto-connect?
|
95
|
-
@connected = @options[:auto_connect]
|
96
|
-
end
|
97
|
-
|
98
|
-
# @see Occi::Api::Client::ClientBase
|
99
|
-
def list(resource_type_identifier=nil)
|
100
|
-
if resource_type_identifier
|
101
|
-
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
102
|
-
path = path_for_kind_type_identifier(resource_type_identifier)
|
103
|
-
end
|
104
|
-
|
105
|
-
path = '/' unless path
|
106
|
-
path = "#{@endpoint.to_s}#{path}"
|
107
|
-
|
108
|
-
headers = self.class.headers.clone
|
109
|
-
headers['Accept'] = 'text/uri-list'
|
110
|
-
|
111
|
-
response = self.class.get(
|
112
|
-
path,
|
113
|
-
:headers => headers
|
114
|
-
)
|
115
|
-
|
116
|
-
# TODO: remove the gsub OCCI-OS hack as soon as they stop using 'uri:'
|
117
|
-
response.body.gsub(/\# uri:\/(compute|storage|network)\/[\n]?/, '').split("\n").compact
|
118
|
-
end
|
119
|
-
|
120
|
-
# @see Occi::Api::Client::ClientBase
|
121
|
-
def describe(resource_type_identifier=nil)
|
122
|
-
if resource_type_identifier
|
123
|
-
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
124
|
-
end
|
125
|
-
|
126
|
-
descriptions = Occi::Collection.new
|
127
|
-
|
128
|
-
if resource_type_identifier.blank?
|
129
|
-
# no filters, describe all available resources
|
130
|
-
descriptions.merge! get('/')
|
131
|
-
elsif @model.get_by_id(resource_type_identifier)
|
132
|
-
# we got type identifier
|
133
|
-
# get all available resources of this type
|
134
|
-
locations = list(resource_type_identifier)
|
135
|
-
|
136
|
-
# make the requests
|
137
|
-
locations.each do |location|
|
138
|
-
path = sanitize_instance_link(location)
|
139
|
-
descriptions.merge! get(path)
|
140
|
-
end
|
141
|
-
else
|
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)
|
145
|
-
end
|
146
|
-
|
147
|
-
descriptions.resources
|
148
|
-
end
|
149
|
-
|
150
|
-
# @see Occi::Api::Client::ClientBase
|
151
|
-
def create(entity)
|
152
|
-
raise "#{entity.class.name.inspect} not an entity!" unless entity.kind_of? Occi::Core::Entity
|
153
|
-
|
154
|
-
Occi::Log.debug "Entity kind: #{entity.kind.type_identifier.inspect}"
|
155
|
-
raise "No kind found for #{entity.inspect}" unless entity.kind
|
3
|
+
# load all parts of the ClientHttp
|
4
|
+
Dir[File.join(File.dirname(__FILE__), 'http', '*.rb')].each { |file| require file.gsub('.rb', '') }
|
5
|
+
|
6
|
+
module Occi::Api::Client
|
7
|
+
|
8
|
+
class ClientHttp < ClientBase
|
9
|
+
|
10
|
+
# HTTParty for raw HTTP requests
|
11
|
+
include HTTParty
|
12
|
+
|
13
|
+
# TODO: change default Accept to JSON as soon as it is properly
|
14
|
+
# implemented in OpenStack's OCCI-OS
|
15
|
+
# 'Accept' => 'application/occi+json,text/plain;q=0.8,text/occi;q=0.2'
|
16
|
+
DEFAULT_HEADERS = {
|
17
|
+
'Accept' => 'text/plain,text/occi;q=0.2',
|
18
|
+
'User-Agent' => "rOCCI HTTPClient #{Occi::Api::VERSION}"
|
19
|
+
}
|
20
|
+
headers DEFAULT_HEADERS
|
21
|
+
|
22
|
+
# Initializes client data structures and retrieves OCCI model
|
23
|
+
# from the server.
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# options = {
|
27
|
+
# :endpoint => "http://localhost:3300/",
|
28
|
+
# :timeout => 15
|
29
|
+
# :auth => {:type => "none"},
|
30
|
+
# :log => {:out => STDERR, :level => Occi::Log::WARN, :logger => nil},
|
31
|
+
# :auto_connect => true,
|
32
|
+
# :media_type => nil
|
33
|
+
# }
|
34
|
+
#
|
35
|
+
# Occi::Api::Client::ClientHttp.new options # => #<Occi::Api::Client::ClientHttp>
|
36
|
+
#
|
37
|
+
# @param [Hash] options, for available options and defaults see examples
|
38
|
+
# @return [Occi::Api::Client::ClientHttp] client instance
|
39
|
+
def initialize(options = {})
|
40
|
+
super options
|
41
|
+
|
42
|
+
self.class.base_uri @endpoint.to_s
|
43
|
+
self.class.timeout @options[:timeout].to_i unless @options[:timeout].blank?
|
44
|
+
|
45
|
+
# get model information from the endpoint
|
46
|
+
# and create Occi::Model instance
|
47
|
+
model_collection = get('/-/')
|
48
|
+
@model = get_model(model_collection)
|
49
|
+
|
50
|
+
# auto-connect?
|
51
|
+
@connected = @options[:auto_connect]
|
52
|
+
end
|
156
53
|
|
157
|
-
|
158
|
-
|
159
|
-
|
54
|
+
# @see Occi::Api::Client::ClientBase
|
55
|
+
def list(resource_type_identifier=nil)
|
56
|
+
if resource_type_identifier
|
57
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
58
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
59
|
+
end
|
160
60
|
|
161
|
-
|
162
|
-
Occi::Log.debug "Entity class: #{entity.class.name.inspect}"
|
163
|
-
collection.resources << entity if entity.kind_of? Occi::Core::Resource
|
164
|
-
collection.links << entity if entity.kind_of? Occi::Core::Link
|
61
|
+
path = '/' unless path
|
165
62
|
|
166
|
-
|
167
|
-
|
168
|
-
end
|
63
|
+
headers = self.class.headers.clone
|
64
|
+
headers['Accept'] = 'text/uri-list'
|
169
65
|
|
170
|
-
|
171
|
-
|
172
|
-
|
66
|
+
response = self.class.get(
|
67
|
+
path,
|
68
|
+
:headers => headers
|
69
|
+
)
|
173
70
|
|
174
|
-
|
71
|
+
# TODO: remove the gsub OCCI-OS hack as soon as they stop using 'uri:'
|
72
|
+
response.body.gsub(/\# uri:\/(compute|storage|network)\/[\n]?/, '').split("\n").compact
|
73
|
+
end
|
175
74
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
raise "Unsupported descriptor format! Only OVF or OVA files are supported."
|
182
|
-
end
|
183
|
-
end
|
75
|
+
# @see Occi::Api::Client::ClientBase
|
76
|
+
def describe(resource_type_identifier=nil)
|
77
|
+
if resource_type_identifier
|
78
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
79
|
+
end
|
184
80
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
81
|
+
descriptions = Occi::Collection.new
|
82
|
+
|
83
|
+
if resource_type_identifier.blank?
|
84
|
+
# no filters, describe all available resources
|
85
|
+
descriptions.merge! get('/')
|
86
|
+
elsif @model.get_by_id(resource_type_identifier)
|
87
|
+
# we got type identifier
|
88
|
+
# get all available resources of this type
|
89
|
+
locations = list(resource_type_identifier)
|
90
|
+
|
91
|
+
# make the requests
|
92
|
+
locations.each do |location|
|
93
|
+
path = sanitize_instance_link(location)
|
94
|
+
descriptions.merge! get(path)
|
95
|
+
end
|
96
|
+
else
|
97
|
+
# this is a link of a specific resource (absolute or relative)
|
98
|
+
path = sanitize_instance_link(resource_type_identifier)
|
99
|
+
descriptions.merge! get(path)
|
100
|
+
end
|
201
101
|
|
202
|
-
|
203
|
-
|
204
|
-
media_types = self.class.head(@endpoint.to_s).headers['accept'].to_s
|
205
|
-
|
206
|
-
path = path_for_kind_type_identifier(Occi::Infrastructure::Compute.type_identifier)
|
207
|
-
path = "#{@endpoint.to_s}#{path}"
|
208
|
-
if media_types.include? ' application/ova '
|
209
|
-
headers = self.class.headers.clone
|
210
|
-
headers['Content-Type'] = 'application/ova'
|
211
|
-
self.class.post(path,
|
212
|
-
:body => descriptor,
|
213
|
-
:headers => headers)
|
214
|
-
else
|
215
|
-
raise "Unsupported descriptor format! Server does not support OVA descriptors."
|
216
|
-
end
|
217
|
-
end
|
102
|
+
descriptions.resources
|
103
|
+
end
|
218
104
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
path = path_for_kind_type_identifier(resource_type_identifier)
|
105
|
+
# @see Occi::Api::Client::ClientBase
|
106
|
+
def create(entity)
|
107
|
+
raise "#{entity.class.name.inspect} not an entity!" unless entity.kind_of? Occi::Core::Entity
|
223
108
|
|
224
|
-
|
225
|
-
|
226
|
-
end
|
109
|
+
Occi::Log.debug "Entity kind: #{entity.kind.type_identifier.inspect}"
|
110
|
+
raise "No kind found for #{entity.inspect}" unless entity.kind
|
227
111
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
raise 'Resource not provided!' if resource_type_identifier.blank?
|
112
|
+
# get location for this kind of entity
|
113
|
+
path = path_for_kind_type_identifier(entity.kind.type_identifier)
|
114
|
+
collection = Occi::Collection.new
|
232
115
|
|
233
|
-
|
234
|
-
|
235
|
-
|
116
|
+
# is this entity a Resource or a Link?
|
117
|
+
Occi::Log.debug "Entity class: #{entity.class.name.inspect}"
|
118
|
+
collection.resources << entity if entity.kind_of? Occi::Core::Resource
|
119
|
+
collection.links << entity if entity.kind_of? Occi::Core::Link
|
236
120
|
|
237
|
-
|
238
|
-
|
239
|
-
|
121
|
+
# make the request
|
122
|
+
post path, collection
|
123
|
+
end
|
240
124
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
model_collection = get('/-/')
|
245
|
-
@model = get_model(model_collection)
|
246
|
-
end
|
125
|
+
# @see Occi::Api::Client::ClientBase
|
126
|
+
def deploy(location)
|
127
|
+
raise "File #{location.inspect} does not exist!" unless File.exist? location
|
247
128
|
|
248
|
-
|
249
|
-
|
250
|
-
# Performs GET request and parses the responses to collections.
|
251
|
-
#
|
252
|
-
# @example
|
253
|
-
# get "/-/" # => #<Occi::Collection>
|
254
|
-
# get "/compute/" # => #<Occi::Collection>
|
255
|
-
# get "/compute/fs65g4fs6g-sf54g54gsf-aa12faddf52" # => #<Occi::Collection>
|
256
|
-
#
|
257
|
-
# @param [String] path for the GET request
|
258
|
-
# @param [Occi::Collection] collection of filters
|
259
|
-
# @return [Occi::Collection] parsed result of the request
|
260
|
-
def get(path='/', filter=nil)
|
261
|
-
relative_path = path
|
262
|
-
path = "#{@endpoint.to_s}#{path}"
|
263
|
-
# apply filters if present
|
264
|
-
response = if filter
|
265
|
-
categories = filter.categories.collect { |category| category.to_text }.join(',')
|
266
|
-
attributes = filter.entities.collect { |entity| entity.attributes.combine.collect { |k, v| k + '=' + v } }.join(',')
|
267
|
-
|
268
|
-
headers = self.class.headers.clone
|
269
|
-
headers['Content-Type'] = 'text/occi'
|
270
|
-
headers['Category'] = categories unless categories.empty?
|
271
|
-
headers['X-OCCI-Attributes'] = attributes unless attributes.empty?
|
272
|
-
|
273
|
-
self.class.get(path, :headers => headers)
|
274
|
-
else
|
275
|
-
self.class.get(path)
|
276
|
-
end
|
277
|
-
|
278
|
-
response_msg = response_message response
|
279
|
-
raise "HTTP GET failed! #{response_msg}" unless response.code.between? 200, 300
|
280
|
-
|
281
|
-
Occi::Log.debug "Response location: #{relative_path.inspect}"
|
282
|
-
kind = @model.get_by_location(relative_path) if @model
|
283
|
-
|
284
|
-
Occi::Log.debug "Response kind: #{kind.inspect}"
|
285
|
-
|
286
|
-
entity_type = nil
|
287
|
-
if kind && kind.related_to?(Occi::Core::Link)
|
288
|
-
entity_type = Occi::Core::Link
|
289
|
-
end
|
290
|
-
|
291
|
-
entity_type = Occi::Core::Resource unless entity_type
|
292
|
-
|
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)
|
295
|
-
|
296
|
-
Occi::Log.debug "Parsed collection: empty? #{collection.empty?}"
|
297
|
-
collection
|
298
|
-
end
|
129
|
+
file = File.read(location)
|
299
130
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
# post "/compute/", collection # => "http://localhost:3300/compute/23sf4g65as-asdgsg2-sdfgsf2g"
|
309
|
-
# post "/network/", collection # => "http://localhost:3300/network/23sf4g65as-asdgsg2-sdfgsf2g"
|
310
|
-
# post "/storage/", collection # => "http://localhost:3300/storage/23sf4g65as-asdgsg2-sdfgsf2g"
|
311
|
-
#
|
312
|
-
# @param [String] path for the POST request
|
313
|
-
# @param [Occi::Collection] resource data to be POSTed
|
314
|
-
# @return [String] URI location
|
315
|
-
def post(path, collection)
|
316
|
-
raise ArgumentError, "Path is a required argument!" if path.blank?
|
317
|
-
|
318
|
-
headers = self.class.headers.clone
|
319
|
-
headers['Content-Type'] = @media_type
|
320
|
-
|
321
|
-
path = "#{@endpoint.to_s}#{path}"
|
322
|
-
|
323
|
-
response = case @media_type
|
324
|
-
when 'application/occi+json'
|
325
|
-
self.class.post(path,
|
326
|
-
:body => collection.to_json,
|
327
|
-
:headers => headers)
|
328
|
-
when 'text/occi'
|
329
|
-
self.class.post(path,
|
330
|
-
:headers => collection.to_header.merge(headers))
|
331
|
-
else
|
332
|
-
self.class.post(path,
|
333
|
-
:body => collection.to_text,
|
334
|
-
:headers => headers)
|
335
|
-
end
|
336
|
-
|
337
|
-
response_msg = response_message(response)
|
338
|
-
|
339
|
-
case response.code
|
340
|
-
when 200
|
341
|
-
collection = Occi::Parser.parse(response.header["content-type"].split(";").first, response.body)
|
342
|
-
|
343
|
-
if collection.empty?
|
344
|
-
Occi::Parser.locations(response.header["content-type"].split(";").first, response.body, response.headers).first
|
345
|
-
else
|
346
|
-
collection.resources.first.location if collection.resources.first
|
347
|
-
end
|
348
|
-
when 201
|
349
|
-
# TODO: OCCI-OS hack, look for header Location instead of uri-list
|
350
|
-
# This should be probably implemented in Occi::Parser.locations
|
351
|
-
if response.header['location']
|
352
|
-
response.header['location']
|
353
|
-
else
|
354
|
-
Occi::Parser.locations(response.header["content-type"].split(";").first, response.body, response.headers).first
|
355
|
-
end
|
356
|
-
else
|
357
|
-
raise "HTTP POST failed! #{response_msg}"
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
# Performs PUT requests and parses responses to collections.
|
362
|
-
#
|
363
|
-
# @example
|
364
|
-
# TODO: add examples
|
365
|
-
#
|
366
|
-
# @param [String] path for the PUT request
|
367
|
-
# @param [Occi::Collection] resource data to send
|
368
|
-
# @return [Occi::Collection] parsed result of the request
|
369
|
-
def put(path, collection)
|
370
|
-
raise ArgumentError, "Path is a required argument!" if path.blank?
|
371
|
-
|
372
|
-
headers = self.class.headers.clone
|
373
|
-
headers['Content-Type'] = @media_type
|
374
|
-
|
375
|
-
path = "#{@endpoint.to_s}#{path}"
|
376
|
-
|
377
|
-
response = case @media_type
|
378
|
-
when 'application/occi+json'
|
379
|
-
self.class.post(path,
|
380
|
-
:body => collection.to_json,
|
381
|
-
:headers => headers)
|
382
|
-
when 'text/occi'
|
383
|
-
self.class.post(path,
|
384
|
-
:headers => collection.to_header.merge(headers))
|
385
|
-
else
|
386
|
-
self.class.post(path,
|
387
|
-
:body => collection.to_text,
|
388
|
-
:headers => headers)
|
389
|
-
end
|
390
|
-
|
391
|
-
response_msg = response_message(response)
|
392
|
-
|
393
|
-
case response.code
|
394
|
-
when 200, 201
|
395
|
-
Occi::Parser.parse(response.header["content-type"].split(";").first, response.body)
|
396
|
-
else
|
397
|
-
raise "HTTP POST failed! #{response_msg}"
|
398
|
-
end
|
399
|
-
end
|
131
|
+
if location.include? '.ovf'
|
132
|
+
deploy_ovf file
|
133
|
+
elsif location.include? '.ova'
|
134
|
+
deploy_ova file
|
135
|
+
else
|
136
|
+
raise "Unsupported descriptor format! Only OVF or OVA files are supported."
|
137
|
+
end
|
138
|
+
end
|
400
139
|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
140
|
+
# @see Occi::Api::Client::ClientBase
|
141
|
+
def deploy_ovf(descriptor)
|
142
|
+
media_types = self.class.head('/').headers['accept'].to_s
|
143
|
+
|
144
|
+
path = path_for_kind_type_identifier(Occi::Infrastructure::Compute.type_identifier)
|
145
|
+
if media_types.include? 'application/ovf'
|
146
|
+
headers = self.class.headers.clone
|
147
|
+
headers['Content-Type'] = 'application/ovf'
|
148
|
+
self.class.post(path,
|
149
|
+
:body => descriptor,
|
150
|
+
:headers => headers)
|
151
|
+
else
|
152
|
+
raise "Unsupported descriptor format! Server does not support OVF descriptors."
|
153
|
+
end
|
154
|
+
end
|
411
155
|
|
412
|
-
|
156
|
+
# @see Occi::Api::Client::ClientBase
|
157
|
+
def deploy_ova(descriptor)
|
158
|
+
media_types = self.class.head('/').headers['accept'].to_s
|
159
|
+
|
160
|
+
path = path_for_kind_type_identifier(Occi::Infrastructure::Compute.type_identifier)
|
161
|
+
if media_types.include? ' application/ova '
|
162
|
+
headers = self.class.headers.clone
|
163
|
+
headers['Content-Type'] = 'application/ova'
|
164
|
+
self.class.post(path,
|
165
|
+
:body => descriptor,
|
166
|
+
:headers => headers)
|
167
|
+
else
|
168
|
+
raise "Unsupported descriptor format! Server does not support OVA descriptors."
|
169
|
+
end
|
170
|
+
end
|
413
171
|
|
414
|
-
|
415
|
-
|
172
|
+
# @see Occi::Api::Client::ClientBase
|
173
|
+
def delete(resource_type_identifier)
|
174
|
+
raise 'Resource not provided!' if resource_type_identifier.blank?
|
175
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
416
176
|
|
417
|
-
|
418
|
-
|
177
|
+
Occi::Log.debug("Deleting #{path.inspect} for #{resource_type_identifier.inspect}")
|
178
|
+
del path
|
179
|
+
end
|
419
180
|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
181
|
+
# @see Occi::Api::Client::ClientBase
|
182
|
+
def trigger(resource_type_identifier, action_instance)
|
183
|
+
# TODO: not tested
|
184
|
+
raise 'Resource not provided!' if resource_type_identifier.blank?
|
424
185
|
|
425
|
-
|
426
|
-
|
186
|
+
#
|
187
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
188
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
427
189
|
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
case auth_options[:type]
|
432
|
-
when "basic"
|
433
|
-
@authn_plugin = Http::AuthnPlugins::Basic.new self, auth_options
|
434
|
-
when "digest"
|
435
|
-
@authn_plugin = Http::AuthnPlugins::Digest.new self, auth_options
|
436
|
-
when "x509"
|
437
|
-
@authn_plugin = Http::AuthnPlugins::X509.new self, auth_options
|
438
|
-
when "keystone"
|
439
|
-
raise ::Occi::Api::Client::Errors::AuthnError, "This authN method is for fallback only!" unless fallback
|
440
|
-
@authn_plugin = Http::AuthnPlugins::Keystone.new self, auth_options
|
441
|
-
when "none", nil
|
442
|
-
@authn_plugin = Http::AuthnPlugins::Dummy.new self
|
443
|
-
else
|
444
|
-
raise ::Occi::Api::Client::Errors::AuthnError, "Unknown authN method [#{@auth_options[:type]}]!"
|
445
|
-
end
|
446
|
-
|
447
|
-
@authn_plugin.setup
|
448
|
-
|
449
|
-
auth_options
|
450
|
-
end
|
190
|
+
# make the request
|
191
|
+
post path, action_instance
|
192
|
+
end
|
451
193
|
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
if @authn_plugin.fallbacks.any?
|
460
|
-
# TODO: multiple fallbacks
|
461
|
-
@auth_options[:original_type] = @auth_options[:type]
|
462
|
-
@auth_options[:type] = @authn_plugin.fallbacks.first
|
463
|
-
|
464
|
-
@auth_options = get_auth(@auth_options, true)
|
465
|
-
@authn_plugin.authenticate
|
466
|
-
else
|
467
|
-
raise e
|
468
|
-
end
|
469
|
-
end
|
470
|
-
end
|
194
|
+
# @see Occi::Api::Client::ClientBase
|
195
|
+
def refresh
|
196
|
+
# re-download the model from the server
|
197
|
+
model_collection = get('/-/')
|
198
|
+
@model = get_model(model_collection)
|
199
|
+
end
|
471
200
|
|
472
|
-
|
473
|
-
def get_media_type(force_type = nil)
|
474
|
-
# force media_type if provided
|
475
|
-
unless force_type.blank?
|
476
|
-
self.class.headers 'Accept' => force_type
|
477
|
-
media_type = force_type
|
478
|
-
else
|
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
|
483
|
-
when /application\/occi\+json/
|
484
|
-
'application/occi+json'
|
485
|
-
when /application\/occi\+xml/
|
486
|
-
'application/occi+xml'
|
487
|
-
when /text\/occi/
|
488
|
-
'text/occi'
|
489
|
-
else
|
490
|
-
'text/plain'
|
491
|
-
end
|
492
|
-
end
|
493
|
-
|
494
|
-
media_type
|
495
|
-
end
|
201
|
+
private
|
496
202
|
|
497
|
-
|
498
|
-
|
499
|
-
# @example
|
500
|
-
# response_message self.class.delete(@endpoint.to_s + path)
|
501
|
-
# # => 'HTTP Response status: [200] OK'
|
502
|
-
#
|
503
|
-
# @param [HTTParty::Response] HTTParty response object
|
504
|
-
# @return [String] message
|
505
|
-
def response_message(response)
|
506
|
-
@last_response = response
|
507
|
-
"HTTP Response status: [#{response.code.to_s}] #{reason_phrase(response.code)}"
|
508
|
-
end
|
203
|
+
# include HTTParty wrappers
|
204
|
+
include Occi::Api::Client::Http::PartyWrappers
|
509
205
|
|
510
|
-
|
511
|
-
|
512
|
-
# @example
|
513
|
-
# reason_phrase(500) # => "Internal Server Error"
|
514
|
-
#
|
515
|
-
# @param [Integer] HTTP response code
|
516
|
-
# @return [String] human-readable phrase
|
517
|
-
def reason_phrase(code)
|
518
|
-
HTTP_CODES[code.to_s]
|
519
|
-
end
|
206
|
+
# include various helper methods (media type stuff, authN, etc.)
|
207
|
+
include Occi::Api::Client::Http::Helpers
|
520
208
|
|
521
|
-
|
209
|
+
# include methods dealing with HTTP codes
|
210
|
+
include Occi::Api::Client::Http::CodeHelpers
|
522
211
|
|
523
|
-
end
|
524
212
|
end
|
213
|
+
|
525
214
|
end
|