ovirt-engine-sdk 4.1.5 → 4.1.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.
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2015-2016 Red Hat, Inc.
2
+ Copyright (c) 2015-2017 Red Hat, Inc.
3
3
 
4
4
  Licensed under the Apache License, Version 2.0 (the "License");
5
5
  you may not use this file except in compliance with the License.
@@ -17,10 +17,27 @@ limitations under the License.
17
17
  #ifndef __OV_XML_READER_H__
18
18
  #define __OV_XML_READER_H__
19
19
 
20
- // Classes:
20
+ #include <ruby.h>
21
+
22
+ #include <libxml/xmlreader.h>
23
+ #include <stdbool.h>
24
+
25
+ /* Data type and class: */
26
+ extern rb_data_type_t ov_xml_reader_type;
21
27
  extern VALUE ov_xml_reader_class;
22
28
 
23
- // Initialization function:
29
+ /* Content: */
30
+ typedef struct {
31
+ VALUE io;
32
+ xmlTextReaderPtr reader;
33
+ bool closed;
34
+ } ov_xml_reader_object;
35
+
36
+ /* Macro to get the pointer: */
37
+ #define ov_xml_reader_ptr(object, ptr) \
38
+ TypedData_Get_Struct((object), ov_xml_reader_object, &ov_xml_reader_type, (ptr))
39
+
40
+ /* Initialization function: */
24
41
  extern void ov_xml_reader_define(void);
25
42
 
26
43
  #endif
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2015-2016 Red Hat, Inc.
2
+ Copyright (c) 2015-2017 Red Hat, Inc.
3
3
 
4
4
  Licensed under the Apache License, Version 2.0 (the "License");
5
5
  you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@ limitations under the License.
16
16
 
17
17
  #include <ruby.h>
18
18
 
19
- #include <stdbool.h>
20
19
  #include <libxml/xmlwriter.h>
21
20
 
22
21
  #include "ov_module.h"
@@ -31,57 +30,76 @@ static ID STRING_ID;
31
30
  static ID STRING_IO_ID;
32
31
  static ID WRITE_ID;
33
32
 
34
- typedef struct {
35
- VALUE io;
36
- xmlTextWriterPtr writer;
37
- } ov_xml_writer_object;
38
-
39
- static void ov_xml_writer_check_closed(ov_xml_writer_object* object) {
40
- if (object->writer == NULL) {
33
+ static void ov_xml_writer_check_closed(ov_xml_writer_object* ptr) {
34
+ if (ptr->writer == NULL) {
41
35
  rb_raise(ov_error_class, "The writer is already closed");
42
36
  }
43
37
  }
44
38
 
45
- static void ov_xml_writer_mark(ov_xml_writer_object *object) {
46
- /* Mark the IO object as reachable: */
47
- if (!NIL_P(object->io)) {
48
- rb_gc_mark(object->io);
49
- }
39
+ static void ov_xml_writer_mark(void* vptr) {
40
+ ov_xml_writer_object* ptr;
41
+
42
+ ptr = vptr;
43
+ rb_gc_mark(ptr->io);
50
44
  }
51
45
 
52
- static void ov_xml_writer_free(ov_xml_writer_object *object) {
46
+ static void ov_xml_writer_free(void* vptr) {
47
+ ov_xml_writer_object* ptr;
48
+
49
+ /* Get the pointer: */
50
+ ptr = vptr;
51
+
53
52
  /* Free the libxml writer, the buffer is automatically closed: */
54
- if (object->writer != NULL) {
55
- xmlTextWriterPtr tmp = object->writer;
56
- object->writer = NULL;
53
+ if (ptr->writer != NULL) {
54
+ xmlTextWriterPtr tmp = ptr->writer;
55
+ ptr->writer = NULL;
57
56
  xmlFreeTextWriter(tmp);
58
57
  }
59
58
 
60
59
  /* Free this object: */
61
- xfree(object);
60
+ xfree(ptr);
62
61
  }
63
62
 
63
+ rb_data_type_t ov_xml_writer_type = {
64
+ .wrap_struct_name = "OVXMLWRITER",
65
+ .function = {
66
+ .dmark = ov_xml_writer_mark,
67
+ .dfree = ov_xml_writer_free,
68
+ .dsize = NULL,
69
+ .reserved = { NULL, NULL }
70
+ },
71
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
72
+ .parent = NULL,
73
+ .data = NULL,
74
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
75
+ #endif
76
+ };
77
+
64
78
  static VALUE ov_xml_writer_alloc(VALUE klass) {
65
- ov_xml_writer_object* object = NULL;
79
+ ov_xml_writer_object* ptr;
66
80
 
67
- object = ALLOC(ov_xml_writer_object);
68
- memset(object, 0, sizeof(ov_xml_writer_object));
69
- return Data_Wrap_Struct(klass, ov_xml_writer_mark, ov_xml_writer_free, object);
81
+ ptr = ALLOC(ov_xml_writer_object);
82
+ ptr->io = Qnil;
83
+ ptr->writer = NULL;
84
+ return TypedData_Wrap_Struct(klass, &ov_xml_writer_type, ptr);
70
85
  }
71
86
 
72
87
  static int ov_xml_writer_callback(void *context, const char *buffer, int length) {
73
88
  VALUE count;
74
89
  VALUE data;
75
- ov_xml_writer_object *object = (ov_xml_writer_object*) context;
90
+ ov_xml_writer_object* ptr;
91
+
92
+ /* Get the pointer: */
93
+ ptr = context;
76
94
 
77
95
  /* Do nothing if the writer is already closed: */
78
- if (object->writer == NULL) {
96
+ if (ptr->writer == NULL) {
79
97
  return 0;
80
98
  }
81
99
 
82
100
  /* Convert the buffer to a Ruby string and write it to the IO object, using the "write" method: */
83
101
  data = rb_str_new(buffer, length);
84
- count = rb_funcall(object->io, WRITE_ID, 1, data);
102
+ count = rb_funcall(ptr->io, WRITE_ID, 1, data);
85
103
 
86
104
  return NUM2INT(count);
87
105
  }
@@ -99,11 +117,11 @@ static VALUE ov_xml_writer_initialize(int argc, VALUE* argv, VALUE self) {
99
117
  VALUE indent;
100
118
  VALUE io;
101
119
  VALUE io_class;
102
- ov_xml_writer_object* object = NULL;
103
- xmlOutputBufferPtr buffer = NULL;
120
+ ov_xml_writer_object* ptr;
121
+ xmlOutputBufferPtr buffer;
104
122
 
105
123
  /* Get the pointer to the object: */
106
- Data_Get_Struct(self, ov_xml_writer_object, object);
124
+ ov_xml_writer_ptr(self, ptr);
107
125
 
108
126
  /* Get the values of the parameters: */
109
127
  if (argc > 2) {
@@ -115,12 +133,12 @@ static VALUE ov_xml_writer_initialize(int argc, VALUE* argv, VALUE self) {
115
133
  /* The first parameter can be an IO object or nil. If it is nil then we need to create a IO object where we can
116
134
  write the generated XML. */
117
135
  if (NIL_P(io)) {
118
- object->io = ov_xml_writer_create_string_io();
136
+ ptr->io = ov_xml_writer_create_string_io();
119
137
  }
120
138
  else {
121
139
  io_class = rb_class_of(io);
122
140
  if (io_class == rb_cIO) {
123
- object->io = io;
141
+ ptr->io = io;
124
142
  }
125
143
  else {
126
144
  rb_raise(
@@ -132,50 +150,50 @@ static VALUE ov_xml_writer_initialize(int argc, VALUE* argv, VALUE self) {
132
150
  }
133
151
 
134
152
  /* Create the libxml buffer that writes to the IO object: */
135
- buffer = xmlOutputBufferCreateIO(ov_xml_writer_callback, NULL, object, NULL);
153
+ buffer = xmlOutputBufferCreateIO(ov_xml_writer_callback, NULL, ptr, NULL);
136
154
  if (buffer == NULL) {
137
155
  rb_raise(ov_error_class, "Can't create XML buffer");
138
156
  }
139
157
 
140
158
  /* Create the libxml writer: */
141
- object->writer = xmlNewTextWriter(buffer);
142
- if (object->writer == NULL) {
159
+ ptr->writer = xmlNewTextWriter(buffer);
160
+ if (ptr->writer == NULL) {
143
161
  xmlOutputBufferClose(buffer);
144
162
  rb_raise(ov_error_class, "Can't create XML writer");
145
163
  }
146
164
 
147
165
  /* Enable indentation: */
148
166
  if (RTEST(indent)) {
149
- xmlTextWriterSetIndent(object->writer, 1);
150
- xmlTextWriterSetIndentString(object->writer, BAD_CAST " ");
167
+ xmlTextWriterSetIndent(ptr->writer, 1);
168
+ xmlTextWriterSetIndentString(ptr->writer, BAD_CAST " ");
151
169
  }
152
170
 
153
171
  return self;
154
172
  }
155
173
 
156
174
  static VALUE ov_xml_writer_string(VALUE self) {
157
- int rc = 0;
158
- ov_xml_writer_object* object = NULL;
175
+ int rc;
176
+ ov_xml_writer_object* ptr;
159
177
 
160
- Data_Get_Struct(self, ov_xml_writer_object, object);
161
- ov_xml_writer_check_closed(object);
162
- rc = xmlTextWriterFlush(object->writer);
178
+ ov_xml_writer_ptr(self, ptr);
179
+ ov_xml_writer_check_closed(ptr);
180
+ rc = xmlTextWriterFlush(ptr->writer);
163
181
  if (rc < 0) {
164
182
  rb_raise(ov_error_class, "Can't flush XML writer");
165
183
  }
166
- return rb_funcall(object->io, STRING_ID, 0, NULL);
184
+ return rb_funcall(ptr->io, STRING_ID, 0, NULL);
167
185
  }
168
186
 
169
187
  static VALUE ov_xml_writer_write_start(VALUE self, VALUE name) {
170
- char* c_name = NULL;
171
- int rc = 0;
172
- ov_xml_writer_object* object = NULL;
188
+ char* c_name;
189
+ int rc;
190
+ ov_xml_writer_object* ptr;
173
191
 
174
- Data_Get_Struct(self, ov_xml_writer_object, object);
175
- ov_xml_writer_check_closed(object);
192
+ ov_xml_writer_ptr(self, ptr);
193
+ ov_xml_writer_check_closed(ptr);
176
194
  Check_Type(name, T_STRING);
177
195
  c_name = StringValueCStr(name);
178
- rc = xmlTextWriterStartElement(object->writer, BAD_CAST c_name);
196
+ rc = xmlTextWriterStartElement(ptr->writer, BAD_CAST c_name);
179
197
  if (rc < 0) {
180
198
  rb_raise(ov_error_class, "Can't start XML element");
181
199
  }
@@ -183,12 +201,12 @@ static VALUE ov_xml_writer_write_start(VALUE self, VALUE name) {
183
201
  }
184
202
 
185
203
  static VALUE ov_xml_writer_write_end(VALUE self) {
186
- int rc = 0;
187
- ov_xml_writer_object* object = NULL;
204
+ int rc;
205
+ ov_xml_writer_object* ptr;
188
206
 
189
- Data_Get_Struct(self, ov_xml_writer_object, object);
190
- ov_xml_writer_check_closed(object);
191
- rc = xmlTextWriterEndElement(object->writer);
207
+ ov_xml_writer_ptr(self, ptr);
208
+ ov_xml_writer_check_closed(ptr);
209
+ rc = xmlTextWriterEndElement(ptr->writer);
192
210
  if (rc < 0) {
193
211
  rb_raise(ov_error_class, "Can't end XML element");
194
212
  }
@@ -196,18 +214,18 @@ static VALUE ov_xml_writer_write_end(VALUE self) {
196
214
  }
197
215
 
198
216
  static VALUE ov_xml_writer_write_attribute(VALUE self, VALUE name, VALUE value) {
199
- char* c_name = NULL;
200
- char* c_value = NULL;
201
- int rc = 0;
202
- ov_xml_writer_object* object = NULL;
217
+ char* c_name;
218
+ char* c_value;
219
+ int rc;
220
+ ov_xml_writer_object* ptr;
203
221
 
204
- Data_Get_Struct(self, ov_xml_writer_object, object);
205
- ov_xml_writer_check_closed(object);
222
+ ov_xml_writer_ptr(self, ptr);
223
+ ov_xml_writer_check_closed(ptr);
206
224
  Check_Type(name, T_STRING);
207
225
  Check_Type(value, T_STRING);
208
226
  c_name = StringValueCStr(name);
209
227
  c_value = StringValueCStr(value);
210
- rc = xmlTextWriterWriteAttribute(object->writer, BAD_CAST c_name, BAD_CAST c_value);
228
+ rc = xmlTextWriterWriteAttribute(ptr->writer, BAD_CAST c_name, BAD_CAST c_value);
211
229
  if (rc < 0) {
212
230
  rb_raise(ov_error_class, "Can't write attribute with name \"%s\" and value \"%s\"", c_name, c_value);
213
231
  }
@@ -215,18 +233,18 @@ static VALUE ov_xml_writer_write_attribute(VALUE self, VALUE name, VALUE value)
215
233
  }
216
234
 
217
235
  static VALUE ov_xml_writer_write_element(VALUE self, VALUE name, VALUE value) {
218
- char* c_name = NULL;
219
- char* c_value = NULL;
220
- int rc = 0;
221
- ov_xml_writer_object* object = NULL;
236
+ char* c_name;
237
+ char* c_value;
238
+ int rc;
239
+ ov_xml_writer_object* ptr;
222
240
 
223
- Data_Get_Struct(self, ov_xml_writer_object, object);
224
- ov_xml_writer_check_closed(object);
241
+ ov_xml_writer_ptr(self, ptr);
242
+ ov_xml_writer_check_closed(ptr);
225
243
  Check_Type(name, T_STRING);
226
244
  Check_Type(value, T_STRING);
227
245
  c_name = StringValueCStr(name);
228
246
  c_value = StringValueCStr(value);
229
- rc = xmlTextWriterWriteElement(object->writer, BAD_CAST c_name, BAD_CAST c_value);
247
+ rc = xmlTextWriterWriteElement(ptr->writer, BAD_CAST c_name, BAD_CAST c_value);
230
248
  if (rc < 0) {
231
249
  rb_raise(ov_error_class, "Can't write element with name \"%s\" and value \"%s\"", c_name, c_value);
232
250
  }
@@ -234,12 +252,12 @@ static VALUE ov_xml_writer_write_element(VALUE self, VALUE name, VALUE value) {
234
252
  }
235
253
 
236
254
  static VALUE ov_xml_writer_flush(VALUE self) {
237
- ov_xml_writer_object* object = NULL;
238
- int rc = 0;
255
+ int rc;
256
+ ov_xml_writer_object* ptr;
239
257
 
240
- Data_Get_Struct(self, ov_xml_writer_object, object);
241
- ov_xml_writer_check_closed(object);
242
- rc = xmlTextWriterFlush(object->writer);
258
+ ov_xml_writer_ptr(self, ptr);
259
+ ov_xml_writer_check_closed(ptr);
260
+ rc = xmlTextWriterFlush(ptr->writer);
243
261
  if (rc < 0) {
244
262
  rb_raise(ov_error_class, "Can't flush XML writer");
245
263
  }
@@ -247,12 +265,12 @@ static VALUE ov_xml_writer_flush(VALUE self) {
247
265
  }
248
266
 
249
267
  static VALUE ov_xml_writer_close(VALUE self) {
250
- ov_xml_writer_object* object = NULL;
268
+ ov_xml_writer_object* ptr;
251
269
 
252
- Data_Get_Struct(self, ov_xml_writer_object, object);
253
- ov_xml_writer_check_closed(object);
254
- xmlFreeTextWriter(object->writer);
255
- object->writer = NULL;
270
+ ov_xml_writer_ptr(self, ptr);
271
+ ov_xml_writer_check_closed(ptr);
272
+ xmlFreeTextWriter(ptr->writer);
273
+ ptr->writer = NULL;
256
274
  return Qnil;
257
275
  }
258
276
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2015-2016 Red Hat, Inc.
2
+ Copyright (c) 2015-2017 Red Hat, Inc.
3
3
 
4
4
  Licensed under the Apache License, Version 2.0 (the "License");
5
5
  you may not use this file except in compliance with the License.
@@ -17,10 +17,25 @@ limitations under the License.
17
17
  #ifndef __OV_XML_WRITER_H__
18
18
  #define __OV_XML_WRITER_H__
19
19
 
20
- // Classes:
20
+ #include <ruby.h>
21
+
22
+ #include <libxml/xmlwriter.h>
23
+
24
+ /* Data type and class: */
25
+ extern rb_data_type_t ov_xml_writer_type;
21
26
  extern VALUE ov_xml_writer_class;
22
27
 
23
- // Initialization function:
28
+ /* Content: */
29
+ typedef struct {
30
+ VALUE io;
31
+ xmlTextWriterPtr writer;
32
+ } ov_xml_writer_object;
33
+
34
+ /* Macro to get the pointer: */
35
+ #define ov_xml_writer_ptr(object, ptr) \
36
+ TypedData_Get_Struct((object), ov_xml_writer_object, &ov_xml_writer_type, (ptr))
37
+
38
+ /* Initialization function: */
24
39
  extern void ov_xml_writer_define(void);
25
40
 
26
41
  #endif
@@ -21,6 +21,7 @@ limitations under the License.
21
21
  #include "ov_http_client.h"
22
22
  #include "ov_http_request.h"
23
23
  #include "ov_http_response.h"
24
+ #include "ov_http_transfer.h"
24
25
  #include "ov_xml_reader.h"
25
26
  #include "ov_xml_writer.h"
26
27
 
@@ -33,6 +34,7 @@ void Init_ovirtsdk4c(void) {
33
34
  ov_http_client_define();
34
35
  ov_http_request_define();
35
36
  ov_http_response_define();
37
+ ov_http_transfer_define();
36
38
  ov_xml_reader_define();
37
39
  ov_xml_writer_define();
38
40
  }
data/lib/ovirtsdk4.rb CHANGED
@@ -28,6 +28,7 @@ require 'ovirtsdk4c'
28
28
  # Own requirements.
29
29
  #
30
30
  require 'ovirtsdk4/version.rb'
31
+ require 'ovirtsdk4/error.rb'
31
32
  require 'ovirtsdk4/connection.rb'
32
33
  require 'ovirtsdk4/type.rb'
33
34
  require 'ovirtsdk4/types.rb'
@@ -95,7 +95,13 @@ module OvirtSDK4
95
95
  # @option opts [Hash] :headers Custom HTTP headers to send with all requests. The keys of the hash can be
96
96
  # strings of symbols, and they will be used as the names of the headers. The values of the hash will be used
97
97
  # as the names of the headers. If the same header is provided here and in the `headers` parameter of a specific
98
- # method call, then the `headers` parameter of the specific method call will have precendence.
98
+ # method call, then the `headers` parameter of the specific method call will have precedence.
99
+ #
100
+ # @option opts [Integer] :connections (0) The maximum number of connections to open to the host. If the value is
101
+ # `0` (the default) then the number of connections will be unlimited.
102
+ #
103
+ # @option opts [Integer] :pipeline (0) The maximum number of request to put in an HTTP pipeline without waiting for
104
+ # the response. If the value is `0` (the default) then pipelining is disabled.
99
105
  #
100
106
  def initialize(opts = {})
101
107
  # Get the values of the parameters and assign default values:
@@ -115,6 +121,8 @@ module OvirtSDK4
115
121
  @proxy_username = opts[:proxy_username]
116
122
  @proxy_password = opts[:proxy_password]
117
123
  @headers = opts[:headers]
124
+ @connections = opts[:connections] || 0
125
+ @pipeline = opts[:pipeline] || 0
118
126
 
119
127
  # Check that the URL has been provided:
120
128
  raise ArgumentError, "The 'url' option is mandatory" unless @url
@@ -147,7 +155,9 @@ module OvirtSDK4
147
155
  compress: @compress,
148
156
  proxy_url: @proxy_url,
149
157
  proxy_username: @proxy_username,
150
- proxy_password: @proxy_password
158
+ proxy_password: @proxy_password,
159
+ connections: @connections,
160
+ pipeline: @pipeline
151
161
  )
152
162
  end
153
163
 
@@ -174,10 +184,9 @@ module OvirtSDK4
174
184
  end
175
185
 
176
186
  #
177
- # Sends an HTTP request and waits for the response.
187
+ # Sends an HTTP request.
178
188
  #
179
189
  # @param request [HttpRequest] The request object containing the details of the HTTP request to send.
180
- # @return [Response] A request object containing the details of the HTTP response received.
181
190
  #
182
191
  # @api private
183
192
  #
@@ -208,13 +217,31 @@ module OvirtSDK4
208
217
  @token ||= create_access_token
209
218
  request.token = @token
210
219
 
211
- # Create an empty response:
212
- response = HttpResponse.new
220
+ # Send the request:
221
+ @client.send(request)
222
+ end
213
223
 
214
- # Send the request and wait for the response:
215
- @client.send(request, response)
224
+ #
225
+ # Waits for the response to the given request.
226
+ #
227
+ # @param request [HttpRequest] The request object whose corresponding response you want to wait for.
228
+ # @return [Response] A request object containing the details of the HTTP response received.
229
+ #
230
+ def wait(request)
231
+ # Wait for the response:
232
+ response = @client.wait(request)
233
+ raise response if response.is_a?(Exception)
234
+
235
+ # If the request failed because of authentication, and it wasn't a request to the SSO service, then the
236
+ # most likely cause is an expired SSO token. In this case we need to request a new token, and try the original
237
+ # request again, but only once. It if fails again, we just return the failed response.
238
+ if response.code == 401 && request.token
239
+ @token = create_access_token
240
+ request.token = @token
241
+ @client.send(request)
242
+ response = @client.wait(request)
243
+ end
216
244
 
217
- # Return the response:
218
245
  response
219
246
  end
220
247
 
@@ -273,25 +300,26 @@ module OvirtSDK4
273
300
  #
274
301
  def get_sso_response(url, parameters)
275
302
  # Create the request:
276
- request = HttpRequest.new(
277
- method: :POST,
278
- url: url,
279
- headers: {
280
- 'User-Agent' => "RubySDK/#{VERSION}",
281
- 'Content-Type' => 'application/x-www-form-urlencoded',
282
- 'Accept' => 'application/json'
283
- },
284
- body: URI.encode_www_form(parameters)
285
- )
303
+ request = HttpRequest.new
304
+ request.method = :POST
305
+ request.url = url
306
+ request.headers = {
307
+ 'User-Agent' => "RubySDK/#{VERSION}",
308
+ 'Content-Type' => 'application/x-www-form-urlencoded',
309
+ 'Accept' => 'application/json'
310
+ }
311
+ request.body = URI.encode_www_form(parameters)
286
312
 
287
313
  # Add the global headers:
288
314
  request.headers.merge!(@headers) if @headers
289
315
 
290
- # Create an empty response:
291
- response = HttpResponse.new
292
-
293
316
  # Send the request and wait for the response:
294
- @client.send(request, response)
317
+ @client.send(request)
318
+ response = @client.wait(request)
319
+ raise response if response.is_a?(Exception)
320
+
321
+ # Check the returned content type:
322
+ check_json_content_type(response)
295
323
 
296
324
  # Parse and return the JSON response:
297
325
  JSON.parse(response.body)
@@ -361,10 +389,14 @@ module OvirtSDK4
361
389
  # `true`.
362
390
  #
363
391
  # @param raise_exception [Boolean]
392
+ #
393
+ # @param timeout [Integer] (nil) The maximun total time to wait for the test to complete, in seconds. If the value
394
+ # is `nil` (the default) then the timeout set globally for the connection will be used.
395
+ #
364
396
  # @return [Boolean]
365
397
  #
366
- def test(raise_exception = false)
367
- system_service.get
398
+ def test(raise_exception = false, timeout = nil)
399
+ system_service.get(timeout: timeout)
368
400
  true
369
401
  rescue StandardError
370
402
  raise if raise_exception
@@ -412,7 +444,7 @@ module OvirtSDK4
412
444
  # Check that the "href" has a value, as it is needed in order to retrieve the representation of the object:
413
445
  href = object.href
414
446
  if href.nil?
415
- raise Error, "Can't follow link because the 'href' attribute does't have a value"
447
+ raise Error, "Can't follow link because the 'href' attribute doesn't have a value"
416
448
  end
417
449
 
418
450
  # Check that the value of the "href" attribute is compatible with the base URL of the connection:
@@ -446,5 +478,123 @@ module OvirtSDK4
446
478
  # Remove the temporary file that contains the trusted CA certificates:
447
479
  @ca_store.unlink if @ca_store
448
480
  end
481
+
482
+ #
483
+ # Checks that the content type of the given response is JSON. If it is JSON then it does nothing. If it isn't
484
+ # JSON then it raises an exception.
485
+ #
486
+ # @param response [HttpResponse] The HTTP response to check.
487
+ #
488
+ # @api private
489
+ #
490
+ def check_json_content_type(response)
491
+ check_content_type(JSON_CONTENT_TYPE_RE, 'JSON', response)
492
+ end
493
+
494
+ #
495
+ # Checks that the content type of the given response is XML. If it is XML then it does nothing. If it isn't
496
+ # XML then it raises an exception.
497
+ #
498
+ # @param response [HttpResponse] The HTTP response to check.
499
+ #
500
+ # @api private
501
+ #
502
+ def check_xml_content_type(response)
503
+ check_content_type(XML_CONTENT_TYPE_RE, 'XML', response)
504
+ end
505
+
506
+ #
507
+ # Creates and raises an error containing the details of the given HTTP response.
508
+ #
509
+ # @param response [HttpResponse] The HTTP response where the details of the raised error will be taken from.
510
+ # @param detail [String, Fault] (nil) The detail of the error. It can be a string or a `Fault` object.
511
+ #
512
+ # @api private
513
+ #
514
+ def raise_error(response, detail = nil)
515
+ # Check if the detail is a fault:
516
+ fault = detail.is_a?(Fault) ? detail : nil
517
+
518
+ # Build the error message from the response and the fault:
519
+ message = ''
520
+ unless fault.nil?
521
+ unless fault.reason.nil?
522
+ message << ' ' unless message.empty?
523
+ message << "Fault reason is \"#{fault.reason}\"."
524
+ end
525
+ unless fault.detail.nil?
526
+ message << ' ' unless message.empty?
527
+ message << "Fault detail is \"#{fault.detail}\"."
528
+ end
529
+ end
530
+ unless response.nil?
531
+ unless response.code.nil?
532
+ message << ' ' unless message.empty?
533
+ message << "HTTP response code is #{response.code}."
534
+ end
535
+ unless response.message.nil?
536
+ message << ' ' unless message.empty?
537
+ message << "HTTP response message is \"#{response.message}\"."
538
+ end
539
+ end
540
+
541
+ # If the detail is a string, append it to the message:
542
+ if detail.is_a?(String)
543
+ message << ' ' unless message.empty?
544
+ message << detail
545
+ message << '.'
546
+ end
547
+
548
+ # Create and populate the error:
549
+ error = Error.new(message)
550
+ error.code = response.code if response
551
+ error.fault = fault
552
+
553
+ raise error
554
+ end
555
+
556
+ private
557
+
558
+ #
559
+ # Regular expression used to check JSON content type.
560
+ #
561
+ # @api private
562
+ #
563
+ JSON_CONTENT_TYPE_RE = %r{^\s*(application|text)/json\s*(;.*)?$}i
564
+
565
+ #
566
+ # Regular expression used to check XML content type.
567
+ #
568
+ # @api private
569
+ #
570
+ XML_CONTENT_TYPE_RE = %r{^\s*(application|text)/xml\s*(;.*)?$}i
571
+
572
+ #
573
+ # The typical URL path, used just to generate informative error messages.
574
+ #
575
+ # @api private
576
+ #
577
+ TYPICAL_PATH = '/ovirt-engine/api'.freeze
578
+
579
+ #
580
+ # Checks the content type of the given HTTP response and raises an exception if it isn't the expected one.
581
+ #
582
+ # @param expected_re [Regex] The regular expression used to check the expected content type.
583
+ # @param expected_name [String] The name of the expected content type.
584
+ # @param response [HttpResponse] The HTTP response to check.
585
+ #
586
+ # @api private
587
+ #
588
+ def check_content_type(expected_re, expected_name, response)
589
+ content_type = response.headers['content-type']
590
+ return if expected_re =~ content_type
591
+ detail = "The response content type '#{content_type}' isn't #{expected_name}"
592
+ url = URI(@url)
593
+ if url.path != TYPICAL_PATH
594
+ detail << ". Is the path '#{url.path}' included in the 'url' parameter correct?"
595
+ detail << " The typical one is '#{TYPICAL_PATH}'"
596
+ end
597
+ raise_error(response, detail)
598
+ end
449
599
  end
450
600
  end