ovirt-engine-sdk 4.0.2 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ /*
2
+ Copyright (c) 2016 Red Hat, Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ #ifndef __OV_HTTP_RESPONSE_H__
18
+ #define __OV_HTTP_RESPONSE_H__
19
+
20
+ /* Classes: */
21
+ VALUE ov_http_response_class;
22
+
23
+ /* Content: */
24
+ typedef struct {
25
+ VALUE body; /* String */
26
+ VALUE code; /* Integer */
27
+ VALUE headers; /* Hash<String, String> */
28
+ VALUE message; /* String */
29
+ } ov_http_response_object;
30
+
31
+ /* Initialization function: */
32
+ extern void ov_http_response_define(void);
33
+
34
+ #endif
@@ -18,15 +18,21 @@ limitations under the License.
18
18
 
19
19
  #include "ov_module.h"
20
20
  #include "ov_error.h"
21
+ #include "ov_http_client.h"
22
+ #include "ov_http_request.h"
23
+ #include "ov_http_response.h"
21
24
  #include "ov_xml_reader.h"
22
25
  #include "ov_xml_writer.h"
23
26
 
24
27
  void Init_ovirtsdk4c(void) {
25
- // Define the module:
28
+ /* Define the module: */
26
29
  ov_module_define();
27
30
 
28
- // Define the classes:
31
+ /* Define the classes: */
29
32
  ov_error_define();
33
+ ov_http_client_define();
34
+ ov_http_request_define();
35
+ ov_http_response_define();
30
36
  ov_xml_reader_define();
31
37
  ov_xml_writer_define();
32
38
  }
@@ -14,76 +14,27 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'curb'
18
17
  require 'json'
19
18
  require 'uri'
20
19
 
21
20
  module OvirtSDK4
22
21
 
23
- #
24
- # This class represents an HTTP request.
25
- #
26
- # @api private
27
- #
28
- class Request
29
- attr_accessor :method
30
- attr_accessor :path
31
- attr_accessor :query
32
- attr_accessor :headers
33
- attr_accessor :body
34
-
35
- #
36
- # Creates a new HTTP request.
37
- #
38
- def initialize(opts = {})
39
- self.method = opts[:method] || :GET
40
- self.path = opts[:path] || ''
41
- self.headers = opts[:headers] || {}
42
- self.query = opts[:query] || {}
43
- self.body = opts[:body]
44
- end
45
-
46
- end
47
-
48
- #
49
- # This class represents an HTTP response.
50
- #
51
- # @api private
52
- #
53
- class Response
54
- attr_accessor :body
55
- attr_accessor :code
56
- attr_accessor :headers
57
- attr_accessor :message
58
-
59
- #
60
- # Creates a new HTTP response.
61
- #
62
- def initialize(opts = {})
63
- self.body = opts[:body]
64
- self.code = opts[:code]
65
- self.headers = opts[:headers]
66
- self.message = opts[:message]
67
- end
68
- end
69
-
70
22
  #
71
23
  # This class is responsible for managing an HTTP connection to the engine server. It is intended as the entry
72
24
  # point for the SDK, and it provides access to the `system` service and, from there, to the rest of the services
73
25
  # provided by the API.
74
26
  #
75
27
  class Connection
76
-
77
28
  #
78
29
  # Creates a new connection to the API server.
79
30
  #
80
31
  # [source,ruby]
81
32
  # ----
82
33
  # connection = OvirtSDK4::Connection.new(
83
- # :url => 'https://engine.example.com/ovirt-engine/api',
34
+ # :url => 'https://engine.example.com/ovirt-engine/api',
84
35
  # :username => 'admin@internal',
85
36
  # :password => '...',
86
- # :ca_file => '/etc/pki/ovirt-engine/ca.pem',
37
+ # :ca_file => '/etc/pki/ovirt-engine/ca.pem',
87
38
  # )
88
39
  # ----
89
40
  #
@@ -92,11 +43,11 @@ module OvirtSDK4
92
43
  # @option opts [String] :url A string containing the base URL of the server, usually something like
93
44
  # `\https://server.example.com/ovirt-engine/api`.
94
45
  #
95
- # @option opts [String] :user The name of the user, something like `admin@internal`.
46
+ # @option opts [String] :username The name of the user, something like `admin@internal`.
96
47
  #
97
48
  # @option opts [String] :password The password of the user.
98
49
  #
99
- # @options opts [String] :token The token used to authenticate. Optionally the caller can explicitly provide
50
+ # @option opts [String] :token The token used to authenticate. Optionally the caller can explicitly provide
100
51
  # the token, instead of the user name and password. If the token isn't provided then it will be automatically
101
52
  # created.
102
53
  #
@@ -113,8 +64,8 @@ module OvirtSDK4
113
64
  #
114
65
  # @option opts [Logger] :log The logger where the log messages will be written.
115
66
  #
116
- # @option opts [Boolean] :kerberos (false) A boolean flag indicating if Kerberos uthentication should be used
117
- # instead of the default basic authentication.
67
+ # @option opts [Boolean] :kerberos (false) A boolean flag indicating if Kerberos authentication should be used
68
+ # instead of user name and password to obtain the OAuth token.
118
69
  #
119
70
  # @option opts [Integer] :timeout (0) The maximun total time to wait for the response, in seconds. A value of zero
120
71
  # (the default) means wait for ever. If the timeout expires before the response is received an exception will be
@@ -137,58 +88,16 @@ module OvirtSDK4
137
88
  @kerberos = opts[:kerberos] || false
138
89
  @timeout = opts[:timeout] || 0
139
90
  @compress = opts[:compress] || false
140
- @auth = opts[:auth] || :oauth
141
-
142
- # Check mandatory parameters:
143
- if url.nil?
144
- raise ArgumentError.new("The 'url' parameter is mandatory.")
145
- end
146
-
147
- # Save the URL:
148
- @url = URI(@url)
149
-
150
- # Create the cURL handle:
151
- @curl = Curl::Easy.new
152
-
153
- # Configure TLS parameters:
154
- if @url.scheme == 'https'
155
- if @insecure
156
- @curl.ssl_verify_peer = false
157
- @curl.ssl_verify_host = false
158
- elsif !@ca_file.nil?
159
- raise ArgumentError.new("The CA file '#{@ca_file}' doesn't exist.") unless ::File.file?(@ca_file)
160
- @curl.cacert = @ca_file
161
- end
162
- end
163
-
164
- # Configure the timeout:
165
- @curl.timeout = @timeout
166
91
 
167
- # Configure compression of responses (setting the value to a zero length string means accepting all the
168
- # compression types that libcurl supports):
169
- if @compress
170
- @curl.encoding = ''
171
- end
172
-
173
- # Configure debug mode:
174
- if @debug && @log
175
- @curl.verbose = true
176
- @curl.on_debug do |_, data|
177
- lines = data.gsub("\r\n", "\n").strip.split("\n")
178
- lines.each do |line|
179
- @log.debug(line)
180
- end
181
- end
182
- end
183
- end
184
-
185
- #
186
- # Returns the base URL of this connection.
187
- #
188
- # @return [String]
189
- #
190
- def url
191
- return @url
92
+ # Create the HTTP client:
93
+ @client = HttpClient.new(
94
+ :insecure => @insecure,
95
+ :ca_file => @ca_file,
96
+ :debug => @debug,
97
+ :log => @log,
98
+ :timeout => @timeout,
99
+ :compress => @compress,
100
+ )
192
101
  end
193
102
 
194
103
  #
@@ -198,7 +107,6 @@ module OvirtSDK4
198
107
  #
199
108
  def system_service
200
109
  @system_service ||= SystemService.new(self, "")
201
- return @system_service
202
110
  end
203
111
 
204
112
  #
@@ -217,40 +125,38 @@ module OvirtSDK4
217
125
  #
218
126
  # Sends an HTTP request and waits for the response.
219
127
  #
220
- # @param request [Request] The Request object containing the details of the HTTP request to send.
128
+ # @param request [HttpRequest] The request object containing the details of the HTTP request to send.
221
129
  # @return [Response] A request object containing the details of the HTTP response received.
222
130
  #
223
131
  # @api private
224
132
  #
225
133
  def send(request)
226
- # Build the URL:
227
- @curl.url = build_url({
228
- :path => request.path,
229
- :query => request.query,
230
- })
231
-
232
- set_headers!(request)
233
- set_authentication!
234
- # Clear any data that may be in the buffers:
235
- @curl.post_body = nil
236
- # Send the request and wait for the response:
237
- case request.method
238
- when :DELETE
239
- @curl.http_delete
240
- when :GET
241
- @curl.http_get
242
- when :PUT
243
- @curl.http_put(request.body)
244
- when :HEAD
245
- @curl.http_head
246
- when :POST
247
- @curl.http_post(request.body)
134
+ # Add the base URL to the request:
135
+ if request.url.nil?
136
+ request.url = @url
137
+ else
138
+ request.url = "#{@url}#{request.url}"
248
139
  end
249
140
 
141
+ # Set the headers:
142
+ request.headers.merge!(
143
+ 'User-Agent' => "RubySDK/#{VERSION}",
144
+ 'Version' => '4',
145
+ 'Content-Type' => 'application/xml',
146
+ 'Accept' => 'application/xml',
147
+ )
148
+
149
+ # Set the authentication token:
150
+ @token ||= get_access_token
151
+ request.token = @token
152
+
153
+ # Create an empty response:
154
+ response = HttpResponse.new
155
+
156
+ # Send the request and wait for the response:
157
+ @client.send(request, response)
158
+
250
159
  # Return the response:
251
- response = Response.new
252
- response.body = @curl.body_str
253
- response.code = @curl.response_code
254
160
  return response
255
161
  end
256
162
 
@@ -273,7 +179,7 @@ module OvirtSDK4
273
179
  end
274
180
 
275
181
  unless response['error'].nil?
276
- raise Error.new("Error during SSO authentication #{response['error_code']}: #{response['error']}")
182
+ raise Error.new("Error during SSO authentication: #{response['error_code']}: #{response['error']}")
277
183
  end
278
184
 
279
185
  response['access_token']
@@ -295,7 +201,7 @@ module OvirtSDK4
295
201
  end
296
202
 
297
203
  unless response['error'].nil?
298
- raise Error.new("Error during SSO revoke #{response['error_code']}: #{response['error']}")
204
+ raise Error.new("Error during SSO revoke: #{response['error_code']}: #{response['error']}")
299
205
  end
300
206
  end
301
207
 
@@ -311,56 +217,26 @@ module OvirtSDK4
311
217
  # @api private
312
218
  #
313
219
  def get_sso_response(url, parameters)
314
- # Create the cURL handle for SSO:
315
- sso_curl = Curl::Easy.new
316
-
317
- # Configure the timeout:
318
- sso_curl.timeout = @timeout
319
-
320
- # Configure debug mode:
321
- if @debug && @log
322
- sso_curl.verbose = true
323
- sso_curl.on_debug do |_, data|
324
- lines = data.gsub("\r\n", "\n").strip.split("\n")
325
- lines.each do |line|
326
- @log.debug(line)
327
- end
328
- end
329
- end
220
+ # Create the request:
221
+ request = HttpRequest.new(
222
+ :method => :POST,
223
+ :url => url,
224
+ :headers => {
225
+ 'User-Agent' => "RubySDK/#{VERSION}",
226
+ 'Content-Type' => 'application/x-www-form-urlencoded',
227
+ 'Accept' => 'application/json',
228
+ },
229
+ :body => URI.encode_www_form(parameters),
230
+ )
231
+
232
+ # Create an empty response:
233
+ response = HttpResponse.new
330
234
 
331
- begin
332
- # Configure TLS parameters:
333
- if url.scheme == 'https'
334
- if @insecure
335
- sso_curl.ssl_verify_peer = false
336
- sso_curl.ssl_verify_host = false
337
- elsif !@ca_file.nil?
338
- raise ArgumentError.new("The CA file \"#{@ca_file}\" doesn't exist.") unless ::File.file?(@ca_file)
339
- sso_curl.cacert = @ca_file
340
- end
341
- end
342
-
343
- # Configure authentication:
344
- sso_curl.http_auth_types = @kerberos ? :gssnegotiate : 0
345
-
346
- # Build the SSO access_token request url:
347
- sso_curl.url = url.to_s
348
-
349
- # Add headers:
350
- sso_curl.headers['User-Agent'] = "RubySDK/#{VERSION}"
351
- sso_curl.headers['Content-Type'] = 'application/x-www-form-urlencoded'
352
- sso_curl.headers['Accept'] = 'application/json'
353
-
354
- # Request access token:
355
- body = URI.encode_www_form(parameters)
356
- sso_curl.http_post(body)
357
-
358
- # Parse and return the JSON response:
359
- body = sso_curl.body_str
360
- return JSON.parse(body)
361
- ensure
362
- sso_curl.close
363
- end
235
+ # Send the request and wait for the response:
236
+ @client.send(request, response)
237
+
238
+ # Parse and return the JSON response:
239
+ JSON.parse(response.body)
364
240
  end
365
241
 
366
242
  #
@@ -393,6 +269,7 @@ module OvirtSDK4
393
269
  # Compute the URL:
394
270
  url = URI(@url.to_s)
395
271
  url.path = "/ovirt-engine/sso/oauth/#{entry_point}"
272
+ url = url.to_s
396
273
 
397
274
  # Return the pair containing the URL and the parameters:
398
275
  [url, parameters]
@@ -416,6 +293,7 @@ module OvirtSDK4
416
293
  # Compute the URL:
417
294
  url = URI(@url.to_s)
418
295
  url.path = '/ovirt-engine/services/sso-logout'
296
+ url = url.to_s
419
297
 
420
298
  # Return the pair containing the URL and the parameters:
421
299
  [url, parameters]
@@ -432,10 +310,10 @@ module OvirtSDK4
432
310
  def test(raise_exception = false)
433
311
  begin
434
312
  system_service.get
435
- return true
313
+ true
436
314
  rescue Exception
437
315
  raise if raise_exception
438
- return false
316
+ false
439
317
  end
440
318
  end
441
319
 
@@ -457,7 +335,7 @@ module OvirtSDK4
457
335
  # @return [Boolean]
458
336
  #
459
337
  def is_link?(object)
460
- return !object.href.nil?
338
+ !object.href.nil?
461
339
  end
462
340
 
463
341
  #
@@ -474,7 +352,7 @@ module OvirtSDK4
474
352
  end
475
353
 
476
354
  # Check that the value of the "href" attribute is compatible with the base URL of the connection:
477
- prefix = @url.path
355
+ prefix = URI(@url).path
478
356
  if !prefix.end_with?('/')
479
357
  prefix += '/'
480
358
  end
@@ -498,68 +376,11 @@ module OvirtSDK4
498
376
  #
499
377
  def close
500
378
  # Revoke the SSO access token:
501
- revoke_access_token unless @token.nil?
379
+ revoke_access_token if @token
502
380
 
503
- # Release resources used by the cURL handle:
504
- @curl.close
381
+ # Close the HTTP client:
382
+ @client.close if @client
505
383
  end
506
384
 
507
- #
508
- # Builds a request URL from a path, and the set of query parameters.
509
- #
510
- # @params opts [Hash] The options used to build the URL.
511
- #
512
- # @option opts [String] :path The path that will be added to the base URL. The default is an empty string.
513
- #
514
- # @option opts [Hash<String, String>] :query ({}) A hash containing the query parameters to add to the URL. The
515
- # keys of the hash should be strings containing the names of the parameters, and the values should be strings
516
- # containing the values.
517
- #
518
- # @return [String] The URL.
519
- #
520
- # @api private
521
- #
522
- def build_url(opts = {})
523
- # Get the values of the parameters and assign default values:
524
- path = opts[:path] || ''
525
- query = opts[:query] || {}
526
-
527
- # Add the path and the parameters:
528
- url = @url.to_s + path
529
- if not query.empty?
530
- url = url + '?' + URI.encode_www_form(query)
531
- end
532
- return url
533
- end
534
-
535
- private
536
-
537
- # @api private
538
- def set_authentication!
539
- case @auth
540
- when :oauth
541
- # Check if we already have an SSO access token:
542
- @token ||= get_access_token
543
- @curl.headers['Authorization'] = "Bearer #{@token}"
544
- when :basic
545
- @curl.http_auth_types = :basic
546
- @curl.username = @username
547
- @curl.password = @password
548
- end
549
- end
550
-
551
- # @api private
552
- def set_headers!(request)
553
- # Add headers, avoiding those that have no value:
554
- @curl.headers.clear
555
- @curl.headers['user-agent'] = "RubySDK/#{VERSION}"
556
- @curl.headers['content-type'] = 'application/xml'
557
- @curl.headers['accept'] = 'application/xml'
558
- @curl.headers['version'] = 4
559
- request.headers.each do |k,v|
560
- @curl.headers[k.to_s.downcase] = v
561
- end
562
- end
563
385
  end
564
-
565
386
  end