Class: XenApi::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/xenapi/xenapi/client.rb

Overview

This class permits the invocation of XMLRPC API calls through a ruby-like interface

client = XenApi::Client.new('http://xenapi.test')
client.('root', 'password')
client.VM.get_all

Authenticating with the API

Authentication with the API takes place through the API session class, usually using the login_with_password method. The Client handles this method specially to enable it to retain the session identifier to pass to invoked methods and perform reauthentication should the session become stale.

client = XenApi::Client.new('http://xenapi.test')
client.('root', 'password')

It is worth noting that only login* matching methods are specially passed through to the session class.

Running code after API login

The Client provides the ability for running code after the client has successfully authenticated with the API. This is useful for either logging authentication or for registering for certain information from the API.

The best example of this is when needing to make use of the Xen API event class for asynchronous event handling. To use the API event class you first have to register your interest in a specific set of event types.

client = XenApi::Client.new('http://xenapi.test')
client. do |c|
  c.event.register %w(vm) # register for 'vm' events
end

Asynchronous Methods

To call asynchronous methods on the Xen XMLRPC API you first call Async on the Client instance followed by the normal method name. For example:

client = XenApi::Client.new('http://xenapi.test')
client.login_with_password('root', 'password')

vm_ref = client.VM.get_by_name_label('my vm')
task = client.Async.VM.clone(vm_ref)
while client.Task.get_status(task) == "pending":
     progress = client.Task.get_progress(task)
     update_progress_bar(progress)
     time.sleep(1)
client.Task.destroy(task)

Calling either Async or async will work as the capitalised form will always be sent when calling a method asynchronously.

Note that only some methods are available in an asynchronous variant. An XMLRPC::FaultException is thrown if you try to call a method asynchrounously that is not available.

Defined Under Namespace

Classes: LoginRequired, ResponseMissingErrorDescriptionField, ResponseMissingStatusField, ResponseMissingValueField, SessionInvalid

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uris, timeout = 10, ssl_verify = :verify_peer) ⇒ Client

Returns a new instance of Client.

Parameters:

  • uri (String, Array)

    URL to the Xen API endpoint

  • timeout (Integer) (defaults to: 10)

    Maximum number of seconds to wait for an API response

  • ssl_verify (Symbol) (defaults to: :verify_peer)

    SSL certificate verification mode. Can be one of :verify_none or :verify_peer



110
111
112
113
114
115
116
117
118
119
# File 'lib/xenapi/xenapi/client.rb', line 110

def initialize(uris, timeout = 10, ssl_verify = :verify_peer)
  @timeout = timeout
  @ssl_verify = ssl_verify
  @uris = [uris].flatten.map do |uri|
    uri = URI.parse(uri)
    uri.path = '/' if uri.path == ''
    uri
  end.uniq
  @uri = @uris.first
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ true, ...

Note:

meth names are not validated

Handle API method calls.

If the method called starts with login then the method is assumed to be part of the session namespace and will be called directly. For example login_with_password

client = XenApi::Client.new('http://xenapi.test/')
client.login_with_password('root', 'password)

If the method called is async then an AsyncDispatcher will be created to handle the asynchronous API method call.

client = XenApi::Client.new('http://xenapi.test/')
client.async.host.get_servertime(ref)

The final case will create a Dispatcher to handle the subsequent method call such as.

client = XenApi::Client.new('http://xenapi.test/')
client.host.get_servertime(ref)

Parameters:

  • meth (String, Symbol)

    Method name

  • args (...)

    Method args

Returns:



216
217
218
219
220
221
222
223
224
225
# File 'lib/xenapi/xenapi/client.rb', line 216

def method_missing(meth, *args)
  case meth.to_s
  when /^(slave_local_)?login/
    (meth, *args)
  when /^async/i
    AsyncDispatcher.new(self, :_call)
  else
    Dispatcher.new(self, meth, :_call)
  end
end

Instance Attribute Details

#uriObject (readonly)

Returns the value of attribute uri.



121
122
123
# File 'lib/xenapi/xenapi/client.rb', line 121

def uri
  @uri
end

#urisObject (readonly)

Returns the value of attribute uris.



121
122
123
# File 'lib/xenapi/xenapi/client.rb', line 121

def uris
  @uris
end

Instance Method Details

#after_login {|client| ... } ⇒ Client #after_loginClient

Returns receiver.

Overloads:

  • #after_login {|client| ... } ⇒ Client
    Note:

    The block will be called whenever the receiver has to authenticate with the XenAPI. This includes the first time the receiver recieves a login_* method call and any time the session becomes invalid.

    Adds a block to be called after successful login to the XenAPI.

    Yields:

    • client

    Yield Parameters:

    • client (optional, Client)

      Client instance

  • #after_loginClient

    Calls the created block, this is primarily for internal use only

Returns:



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/xenapi/xenapi/client.rb', line 133

def (&block)
  if block
    @after_login = block
  elsif @after_login
    case @after_login.arity
    when 1
      @after_login.call(self)
    else
      @after_login.call
    end
  end
  self
end

#api_versionString

Returns the current API version

Returns:

  • (String)

    API version



180
181
182
183
184
185
186
187
188
# File 'lib/xenapi/xenapi/client.rb', line 180

def api_version
  @api_version ||= begin
    pool = self.pool.get_all[0]
    host = self.pool.get_master(pool)
    major = self.host.get_API_version_major(host)
    minor = self.host.get_API_version_minor(host)
    "#{major}.#{minor}"
  end
end

#before_reconnect {|client| ... } ⇒ Client #before_reconnectClient

Returns receiver.

Overloads:

  • #before_reconnect {|client| ... } ⇒ Client
    Note:

    The block will be called whenever the receiver has to chose a new server because the current connection got invalid.

    Adds a block to be called before an attempted reconnect to another server.

    Yields:

    • client

    Yield Parameters:

    • client (optional, Client)

      Client instance

  • #before_reconnectClient

    Calls the created block, this is primarily for internal use only

Returns:



156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/xenapi/xenapi/client.rb', line 156

def before_reconnect(&block)
  if block
    @before_reconnect = block
  elsif @before_reconnect
    case @before_reconnect.arity
    when 1
      @before_reconnect.call(self)
    else
      @before_reconnect.call
    end
  end
  self
end

#inspectObject

See Also:

  • Object#inspect


102
103
104
# File 'lib/xenapi/xenapi/client.rb', line 102

def inspect
  "#<#{self.class} #{@uri}>"
end

#logoutObject

Logout and destroy the current session. After calling logout, the object state is invalid. No API calls can be performed unless one of the login methods is called again.



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/xenapi/xenapi/client.rb', line 230

def logout
  if @login_meth.to_s.start_with? 'slave_local'
    _do_call('session.local_logout', [@session])
  else
    _do_call('session.logout', [@session])
  end
rescue
  # We don't care about any error. If it works: great, if not: shit happens...
  nil
ensure
  @session = ''
  @login_meth = nil
  @login_args = []
  @api_version = nil
end

#xenapi_sessionString

Returns the current session identifier.

Returns:

  • (String)

    session identifier



173
174
175
# File 'lib/xenapi/xenapi/client.rb', line 173

def xenapi_session
  @session
end