% % Copyright (c) 2006-2007 XenSource, Inc. % Copyright (c) 2009 flonatel GmbH & Co. KG % % Permission is granted to copy, distribute and/or modify this document under % the terms of the GNU Free Documentation License, Version 1.2 or any later % version published by the Free Software Foundation; with no Invariant % Sections, no Front-Cover Texts and no Back-Cover Texts. A copy of the % license is included in the section entitled % "GNU Free Documentation License" or the file fdl.tex. % % Authors: Ewan Mellor, Richard Sharp, Dave Scott, Jon Harrop. % Contributor: Andreas Florath % \section{Wire Protocol for Remote API Calls} API calls are sent over a network to a Xen-enabled host using the XML-RPC protocol. In this Section we describe how the higher-level types used in our API Reference are mapped to primitive XML-RPC types. In our API Reference we specify the signatures of API functions in the following style: \begin{verbatim} (ref_vm Set) VM.get_all() \end{verbatim} This specifies that the function with name {\tt VM.get\_all} takes no parameters and returns a Set of {\tt ref\_vm}s. These types are mapped onto XML-RPC types in a straight-forward manner: \begin{itemize} \item Floats, Bools, DateTimes and Strings map directly to the XML-RPC {\tt double}, {\tt boolean}, {\tt dateTime.iso8601}, and {\tt string} elements. \item all ``{\tt ref\_}'' types are opaque references, encoded as the XML-RPC's {\tt String} type. Users of the API should not make assumptions about the concrete form of these strings and should not expect them to remain valid after the client's session with the server has terminated. \item fields named ``{\tt uuid}'' of type ``{\tt String}'' are mapped to the XML-RPC {\tt String} type. The string itself is the OSF DCE UUID presentation format (as output by {\tt uuidgen}, etc). \item ints are all assumed to be 64-bit in our API and are encoded as a string of decimal digits (rather than using XML-RPC's built-in 32-bit {\tt i4} type). \item values of enum types are encoded as strings. For example, a value of {\tt destroy} of type {\tt on\_normal\_exit}, would be conveyed as: \begin{verbatim} destroy \end{verbatim} \item for all our types, {\tt t}, our type {\tt t Set} simply maps to XML-RPC's {\tt Array} type, so for example a value of type {\tt cpu\_feature Set} would be transmitted like this: \begin{verbatim} CX8 PSE36 FPU \end{verbatim} \item for types {\tt k} and {\tt v}, our type {\tt (k, v) Map} maps onto an XML-RPC struct, with the key as the name of the struct. Note that the {\tt (k, v) Map} type is only valid when {\tt k} is a {\tt String}, {\tt Ref}, or {\tt Int}, and in each case the keys of the maps are stringified as above. For example, the {\tt (String, double) Map} containing a the mappings Mike $\rightarrow$ 2.3 and John $\rightarrow$ 1.2 would be represented as: \begin{verbatim} Mike 2.3 John 1.2 \end{verbatim} \item our {\tt Void} type is transmitted as an empty string. \end{itemize} \subsection{Note on References vs UUIDs} References are opaque types --- encoded as XML-RPC strings on the wire --- understood only by the particular server which generated them. Servers are free to choose any concrete representation they find convenient; clients should not make any assumptions or attempt to parse the string contents. References are not guaranteed to be permanent identifiers for objects; clients should not assume that references generated during one session are valid for any future session. References do not allow objects to be compared for equality. Two references to the same object are not guaranteed to be textually identical. UUIDs are intended to be permanent names for objects. They are guaranteed to be in the OSF DCE UUID presentation format (as output by {\tt uuidgen}. Clients may store UUIDs on disk and use them to lookup objects in subsequent sessions with the server. Clients may also test equality on objects by comparing UUID strings. The API provides mechanisms for translating between UUIDs and opaque references. Each class that contains a UUID field provides: \begin{itemize} \item A ``{\tt get\_by\_uuid}'' method that takes a UUID, $u$, and returns an opaque reference to the server-side object that has UUID=$u$; \item A {\tt get\_uuid} function (a regular ``field getter'' RPC) that takes an opaque reference, $r$, and returns the UUID of the server-side object that is referenced by $r$. \end{itemize} \subsection{Return Values/Status Codes} \label{synchronous-result} The return value of an RPC call is an XML-RPC {\tt Struct}. \begin{itemize} \item The first element of the struct is named {\tt Status}; it contains a string value indicating whether the result of the call was a ``{\tt Success}'' or a ``{\tt Failure}''. \end{itemize} If {\tt Status} was set to {\tt Success} then the Struct contains a second element named {\tt Value}: \begin{itemize} \item The element of the struct named {\tt Value} contains the function's return value. \end{itemize} In the case where {\tt Status} is set to {\tt Failure} then the struct contains a second element named {\tt ErrorDescription}: \begin{itemize} \item The element of the struct named {\tt ErrorDescription} contains an array of string values. The first element of the array is an error code; the remainder of the array are strings representing error parameters relating to that code. \end{itemize} For example, an XML-RPC return value from the {\tt host.get\_resident\_VMs} function above may look like this: \begin{verbatim} Status Success Value 81547a35-205c-a551-c577-00b982c5fe00 61c85a22-05da-b8a2-2e55-06b0847da503 1d401ec4-3c17-35a6-fc79-cee6bd9811fe \end{verbatim} \section{Making XML-RPC Calls} \subsection{Transport Layer} The following transport layers are currently supported: \begin{itemize} \item HTTP/S for remote administration \item HTTP over Unix domain sockets for local administration \end{itemize} \subsection{Session Layer} The XML-RPC interface is session-based; before you can make arbitrary RPC calls you must login and initiate a session. For example: \begin{verbatim} session_id session.login_with_password(string uname, string pwd) \end{verbatim} Where {\tt uname} and {\tt password} refer to your username and password respectively, as defined by the Xen administrator. The {\tt session\_id} returned by {\tt session.login\_with\_password} is passed to subsequent RPC calls as an authentication token. A session can be terminated with the {\tt session.logout} function: \begin{verbatim} void session.logout(session_id session) \end{verbatim} \subsection{Synchronous and Asynchronous invocation} Each method call (apart from methods on ``Session'' and ``Task'' objects and ``getters'' and ``setters'' derived from fields) can be made either synchronously or asynchronously. A synchronous RPC call blocks until the return value is received; the return value of a synchronous RPC call is exactly as specified in Section~\ref{synchronous-result}. Only synchronous API calls are listed explicitly in this document. All asynchronous versions are in the special {\tt Async} namespace. For example, synchronous call {\tt VM.clone(...)} (described in Chapter~\ref{api-reference}) has an asynchronous counterpart, {\tt Async.VM.clone(...)}, that is non-blocking. Instead of returning its result directly, an asynchronous RPC call returns a {\tt task-id}; this identifier is subsequently used to track the status of a running asynchronous RPC. Note that an asynchronous call may fail immediately, before a {\tt task-id} has even been created---to represent this eventuality, the returned {\tt task-id} is wrapped in an XML-RPC struct with a {\tt Status}, {\tt ErrorDescription} and {\tt Value} fields, exactly as specified in Section~\ref{synchronous-result}. The {\tt task-id} is provided in the {\tt Value} field if {\tt Status} is set to {\tt Success}. The RPC call \begin{verbatim} (ref_task Set) Task.get_all(session_id s) \end{verbatim} returns a set of all task IDs known to the system. The status (including any returned result and error codes) of these tasks can then be queried by accessing the fields of the Task object in the usual way. Note that, in order to get a consistent snapshot of a task's state, it is advisable to call the ``get\_record'' function. \section{Example interactive session} This section describes how an interactive session might look, using the python API. All python versions starting from 2.4 should work. The examples in this section use a remote Xen host with the ip address of \texttt{192.168.7.20} and the xmlrpc port \texttt{9363}. No authentication is used. Note that the remote server must be configured in the way, that it accepts remote connections. Some lines must be added to the xend-config.sxp configuration file: \begin{verbatim} (xen-api-server ((9363 none) (unix none))) (xend-tcp-xmlrpc-server yes) \end{verbatim} The xend must be restarted after changing the configuration. Before starting python, the \texttt{PYTHONPATH} must be set that the \texttt{XenAPI.py} can be found. Typically the \texttt{XenAPI.py} is installed with one of the Xen helper packages which the last part of the path is \texttt{xen/xm/XenAPI.py}. Example: Under Debian 5.0 the package which contains the \texttt{XenAPI.py} is \texttt{xen-utils-3.2-1}. \texttt{XenAPI.py} is located in \texttt{/usr/lib/xen-3.2-1/lib/python/xen/xm}. The following command will set the \texttt{PYTHONPATH} environment variable in a bash: \begin{verbatim} $ export PYTHONPATH=/usr/lib/xen-3.2-1/lib/python \end{verbatim} Then python can be started and the XenAPI must be imported: \begin{verbatim} $ python ... >>> import xen.xm.XenAPI \end{verbatim} To create a session to the remote server, the \texttt{xen.xm.XenAPI.Session} constructor is used: \begin{verbatim} >>> session = xen.xm.XenAPI.Session("http://192.168.7.20:9363") \end{verbatim} For authentication with a username and password the \texttt{login\_with\_password} is used: \begin{verbatim} >>> session.login_with_password("", "") \end{verbatim} When serialised, this call looks like: \begin{verbatim} POST /RPC2 HTTP/1.0 Host: 192.168.7.20:9363 User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com) Content-Type: text/xml Content-Length: 221 session.login_with_password \end{verbatim} And the response: \begin{verbatim} HTTP/1.1 200 OK Server: BaseHTTP/0.3 Python/2.5.2 Date: Fri, 10 Jul 2009 09:01:27 GMT Content-Type: text/xml Content-Length: 313 Status Success Value 68e3a009-0249-725b-246b-7fc43cf4f154 \end{verbatim} Next, the user may acquire a list of all the VMs known to the host: \begin{verbatim} >>> vms = session.xenapi.VM.get_all() >>> vms ['00000000-0000-0000-0000-000000000000', 'b28e4ee3-216f-fa85-9cae-615e954dbbe7'] \end{verbatim} The VM references here have the form of an uuid, though they may change in the future, and they should be treated as opaque strings. Some examples of using accessors for object fields: \begin{verbatim} >>> session.xenapi.VM.get_name_label(vms[1]) 'guest002' >>> session.xenapi.VM.get_actions_after_reboot(vms[1]) 'restart' \end{verbatim} Grab the actual memory and cpu utilisation of one vm: \begin{verbatim} >>> m = session.xenapi.VM.get_metrics(vms[1]) >>> session.xenapi.VM_metrics.get_memory_actual(m) '268435456' >>> session.xenapi.VM_metrics.get_VCPUs_utilisation(m) {'0': 0.00041759955632935362} \end{verbatim} (The virtual machine has about 256 MByte RAM and is idle.) Pausing and unpausing a vm: \begin{verbatim} >>> session.xenapi.VM.pause(vms[1]) '' >>> session.xenapi.VM.unpause(vms[1]) '' \end{verbatim} Trying to start an vm: \begin{verbatim} >>> session.xenapi.VM.start(vms[1], False) ... : Xen-API failure: ['VM_BAD_POWER_STATE', \ 'b28e4ee3-216f-fa85-9cae-615e954dbbe7', 'Halted', 'Running'] \end{verbatim} In this case the {\tt start} message has been rejected, because the VM is already running, and so an error response has been returned. These high-level errors are returned as structured data (rather than as XML-RPC faults), allowing them to be internationalised.