class OvirtSDK4::Connection
This class is responsible for managing an HTTP connection to the engine server. It is intended as the entry point for the SDK, and it provides access to the `system` service and, from there, to the rest of the services provided by the API.
Public Class Methods
Creates a new connection to the API server.
Note that all the parameters with names starting with `sso` are intended for use with external authentication services, using the oauth.net/2/[OAuth2] protocol. But the typical usage doesn't require them, as they are automatically calculated to use the authentication service that is part of the engine. A typical connection can be created specifying just the `url`, `username`, `password` and `ca_file` parameters:
- source,ruby
connection = ::new(
:url => 'https://engine.example.com/ovirt-engine/api', :username => 'admin@internal', :password => '...', :ca_file => '/etc/pki/ovirt-engine/ca.pem',
)
@param opts [Hash] The options used to create the connection.
@option opts [String] :url A string containing the base URL of the server, usually something like
`\https://server.example.com/ovirt-engine/api`.
@option opts [String] :user The name of the user, something like `admin@internal`.
@option opts [String] :password The password of the user.
@option opts [Boolean] :insecure (false) A boolean flag that indicates if the server TLS certificate and host
name should be checked.
@option opts [String] :ca_file The name of a PEM file containing the trusted CA certificates. The certificate
presented by the server will be verified using these CA certificates. If not set then the system wide CA certificates store is used.
@option opts [Boolean] :debug (false) A boolean flag indicating if debug output should be generated. If the
values is `true` and the `log` parameter isn't `nil` then the data sent to and received from the server will be written to the log. Be aware that user names and passwords will also be written, so handle with care.
@option opts [Logger] :log The logger where the log messages will be written.
@option opts [Boolean] :kerberos (false) A boolean flag indicating if Kerberos uthentication should be used
instead of the default basic authentication.
@option opts [Integer] :timeout (0) The maximun total time to wait for the response, in seconds. A value of zero
(the default) means wait for ever. If the timeout expires before the response is received an exception will be raised.
@option opts [Boolean] :compress (false) A boolean flag indicating if the SDK should ask the server to send
compressed responses. Note that this is a hint for the server, and that it may return uncompressed data even when this parameter is set to `true`.
@option opts [String] :sso_url A string containing the base URL of the authentication service. This needs to be
specified only when using an external authentication service. By default this URL is automatically calculated from the value of the `url` parameter, so that authentication will be performed using the authentication service that is part of the engine.
@option opts [String] :sso_revoke_url A string containing the base URL of the SSO revoke service. This needs to be
specified only when using an external authentication service. By default this URL is automatically calculated from the value of the `url` parameter, so that SSO token revoke will be performed using the SSO service that is part of the engine.
@option opts [Boolean] :sso_insecure A boolean flag that indicates if the SSO server TLS certificate and
host name should be checked. Default is value of `insecure`.
@option opts [String] :sso_ca_file The name of a PEM file containing the trusted CA certificates. The
certificate presented by the SSO server will be verified using these CA certificates. Default is value of `ca_file`.
@option opts [Boolean] :sso_timeout The maximun total time to wait for the SSO response, in seconds. A value
of zero means wait for ever. If the timeout expires before the SSO response is received an exception will be raised. Default is value of `timeout`.
@option opts [String] :sso_token_name (access_token) The token name in the JSON SSO response returned from the SSO
server. Default value is %x`access_token`
# File lib/ovirtsdk4/http.rb, line 152 def initialize(opts = {}) # Get the values of the parameters and assign default values: url = opts[:url] username = opts[:username] password = opts[:password] insecure = opts[:insecure] || false ca_file = opts[:ca_file] @debug = opts[:debug] || false @log = opts[:log] kerberos = opts[:kerberos] || false timeout = opts[:timeout] || 0 compress = opts[:compress] || false sso_url = opts[:sso_url] sso_revoke_url = opts[:sso_revoke_url] sso_insecure = opts[:sso_insecure] || insecure sso_ca_file = opts[:sso_ca_file] || ca_file sso_timeout = opts[:sso_timeout] || timeout sso_token_name = opts[:sso_token_name] || 'access_token' # Check mandatory parameters: if url.nil? raise ArgumentError.new("The \"url\" parameter is mandatory.") end # Save the URL: @url = URI(url) # Save SSO parameters: @sso_url = sso_url @sso_revoke_url = sso_revoke_url @username = username @password = password @kerberos = kerberos @sso_insecure = sso_insecure @sso_ca_file = sso_ca_file @sso_timeout = sso_timeout @sso_token_name = sso_token_name # Create the cURL handle: @curl = Curl::Easy.new # Configure TLS parameters: if @url.scheme == 'https' if insecure @curl.ssl_verify_peer = false @curl.ssl_verify_host = false elsif !ca_file.nil? raise ArgumentError.new("The CA file \"#{ca_file}\" doesn't exist.") unless ::File.file?(ca_file) @curl.cacert = ca_file end end # Configure the timeout: @curl.timeout = timeout # Configure compression of responses (setting the value to a zero length string means accepting all the # compression types that libcurl supports): if compress @curl.encoding = '' end # Configure debug mode: if @debug && @log @curl.verbose = true @curl.on_debug do |_, data| lines = data.gsub("\r\n", "\n").strip.split("\n") lines.each do |line| @log.debug(line) end end end end
Public Instance Methods
Builds a request URL to acquire the access token from SSO. The URLS are different for basic auth and Kerberos, @return [String] The URL.
@api private
# File lib/ovirtsdk4/http.rb, line 447 def build_sso_auth_url # Get the base URL: sso_url = @url.to_s[0..@url.to_s.rindex('/')] # The SSO access scope: scope = 'ovirt-app-api' # Set the grant type and entry point to request from SSO: if @kerberos grant_type = 'urn:ovirt:params:oauth:grant-type:http' entry_point = 'token-http-auth' else grant_type = 'password' entry_point = 'token' end # Build and return the SSO URL: return "#{sso_url}sso/oauth/#{entry_point}?grant_type=#{grant_type}&scope=#{scope}" end
Builds a request URL to revoke the SSO access token. @return [String] The URL.
@api private
# File lib/ovirtsdk4/http.rb, line 473 def build_sso_revoke_url # Get the base URL: sso_url = @url.to_s[0..@url.to_s.rindex('/')] # Build and return the SSO revoke URL: return "#{sso_url}services/sso-logout?scope=&token=#{@sso_token}" end
Builds a request URL from a path, and the set of query parameters.
@params opts [Hash] The options used to build the URL.
@option opts [String] :path The path that will be added to the base URL. The default is an empty string.
@option opts [Hash<String, String>] :query ({}) A hash containing the query parameters to add to the URL. The
keys of the hash should be strings containing the names of the parameters, and the values should be strings containing the values.
@return [String] The URL.
@api private
# File lib/ovirtsdk4/http.rb, line 573 def build_url(opts = {}) # Get the values of the parameters and assign default values: path = opts[:path] || '' query = opts[:query] || {} # Add the path and the parameters: url = @url.to_s + path if not query.empty? url = url + '?' + URI.encode_www_form(query) end return url end
Releases the resources used by this connection.
# File lib/ovirtsdk4/http.rb, line 544 def close # Send the last request to indicate the server that the session should be closed: request = Request.new({ :method => :HEAD, }) send(request) # Revoke the SSO access token: revoke_access_token # Release resources used by the cURL handle: @curl.close end
Follows the `href` attribute of the given object, retrieves the target object and returns it.
@param object [Type] The object containing the `href` attribute. @raise [Error] If the `href` attribute has no value, or the link can't be followed.
# File lib/ovirtsdk4/http.rb, line 514 def follow_link(object) # Check that the "href" has a value, as it is needed in order to retrieve the representation of the object: href = object.href if href.nil? raise Error.new("Can't follow link because the 'href' attribute does't have a value") end # Check that the value of the "href" attribute is compatible with the base URL of the connection: prefix = @url.path if !prefix.end_with?('/') prefix += '/' end if !href.start_with?(prefix) raise Error.new("The URL '#{href}' isn't compatible with the base URL of the connection") end # Remove the prefix from the URL, follow the path to the relevant service and invoke the "get" or "list" method # to retrieve its representation: path = href[prefix.length..-1] service = service(path) if object.is_a?(Array) service.list else service.get end end
Obtains the access token from SSO to be used for Bearer authentication.
@return [String] The URL.
@api private
# File lib/ovirtsdk4/http.rb, line 319 def get_access_token # If SSO url is not supplied build default one: if @sso_url.nil? @sso_url = URI(build_sso_auth_url) else @sso_url = URI(@sso_url) end sso_response = get_sso_response(@sso_url) if sso_response.is_a?(Array) sso_response = sso_response[0] end if !sso_response["error"].nil? raise Error.new("Error during SSO authentication #{sso_response['error_code']} : #{sso_response['error']}") end return sso_response[@sso_token_name] end
Execute a get request to the SSO server and return the response.
@return [Hash] The JSON response.
@api private
# File lib/ovirtsdk4/http.rb, line 371 def get_sso_response(sso_base_url) # Create the cURL handle for SSO: sso_curl = Curl::Easy.new # Configure the timeout: sso_curl.timeout = @sso_timeout # Configure debug mode: if @debug && @log sso_curl.verbose = true sso_curl.on_debug do |_, data| lines = data.gsub("\r\n", "\n").strip.split("\n") lines.each do |line| @log.debug(line) end end end begin # Configure TLS parameters: if sso_base_url.scheme == 'https' if @sso_insecure sso_curl.ssl_verify_peer = false sso_curl.ssl_verify_host = false elsif !@sso_ca_file.nil? raise ArgumentError.new("The CA file \"#{@sso_ca_file}\" doesn't exist.") unless ::File.file?(@sso_ca_file) sso_curl.cacert = @sso_ca_file end end # The username and password parameters: params = {} # The base SSO URL: sso_url = sso_base_url.to_s # Configure authentication: if @kerberos sso_curl.http_auth_types = :gssnegotiate sso_curl.username = '' sso_curl.password = '' else sso_curl.http_auth_types = :basic sso_curl.username = @username sso_curl.password = @password if sso_url.index('?').nil? sso_url += '?' end params['username'] = @username params['password'] = @password sso_url = sso_url + '&' + URI.encode_www_form(params) end # Build the SSO access_token request url: sso_curl.url = sso_url # Add headers: sso_curl.headers['User-Agent'] = "RubySDK/#{VERSION}" sso_curl.headers['Accept'] = 'application/json' # Request access token: sso_curl.http_get # Parse and return the JSON response: return JSON.parse(sso_curl.body_str) ensure sso_curl.close end end
Indicates if the given object is a link. An object is a link if it has an `href` attribute.
@return [Boolean]
# File lib/ovirtsdk4/http.rb, line 504 def is_link?(object) return !object.href.nil? end
Revoke the SSO access token.
@api private
# File lib/ovirtsdk4/http.rb, line 345 def revoke_access_token # If SSO revoke url is not supplied build default one: if @sso_revoke_url.nil? @sso_revoke_url = URI(build_sso_revoke_url) else @sso_revoke_url = URI(@sso_revoke_url) end sso_response = get_sso_response(@sso_revoke_url) if sso_response.is_a?(Array) sso_response = sso_response[0] end if !sso_response["error"].nil? raise Error.new("Error during SSO revoke #{sso_response['error_code']} : #{sso_response['error']}") end end
Sends an HTTP request and waits for the response.
@param request [Request] The Request object containing the details of the HTTP request to send. @return [Response] A request object containing the details of the HTTP response received.
@api private
# File lib/ovirtsdk4/http.rb, line 266 def send(request) # Check if we already have an SSO access token: if @sso_token.nil? @sso_token = get_access_token end # Build the URL: @curl.url = build_url({ :path => request.path, :query => request.query, }) # Add headers, avoiding those that have no value: @curl.headers.clear @curl.headers.merge!(request.headers) @curl.headers['User-Agent'] = "RubySDK/#{VERSION}" @curl.headers['Version'] = '4' @curl.headers['Content-Type'] = 'application/xml' @curl.headers['Accept'] = 'application/xml' @curl.headers['Authorization'] = 'Bearer ' + @sso_token # Clear any data that may be in the buffers: @curl.post_body = nil # Send the request and wait for the response: case request.method when :DELETE @curl.http_delete when :GET @curl.http_get when :PUT @curl.http_put(request.body) when :HEAD @curl.http_head when :POST @curl.http_post(request.body) end # Return the response: response = Response.new response.body = @curl.body_str response.code = @curl.response_code return response end
Returns a reference to the service corresponding to the given path. For example, if the `path` parameter is `vms/123/diskattachments` then it will return a reference to the service that manages the disk attachments for the virtual machine with identifier `123`.
@param path [String] The path of the service, for example `vms/123/diskattachments`. @return [Service] @raise [Error] If there is no service corresponding to the given path.
# File lib/ovirtsdk4/http.rb, line 254 def service(path) return system_service.service(path) end
Returns a reference to the root of the services tree.
@return [SystemService]
# File lib/ovirtsdk4/http.rb, line 240 def system_service @system_service ||= SystemService.new(self, "") return @system_service end
Tests the connectivity with the server. If connectivity works correctly it returns `true`. If there is any connectivity problem it will either return `false` or raise an exception if the `raise_exception` parameter is `true`.
@param raise_exception [Boolean] @return [Boolean]
# File lib/ovirtsdk4/http.rb, line 489 def test(raise_exception = false) begin system_service.get return true rescue Exception raise if raise_exception return false end end
Returns the base URL of this connection.
@return [String]
# File lib/ovirtsdk4/http.rb, line 231 def url return @url end