occi-api 4.2.0.beta.4 → 4.2.0.beta.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|