| 1 | % |
|---|
| 2 | % Copyright (c) 2006-2007 XenSource, Inc. |
|---|
| 3 | % |
|---|
| 4 | % Permission is granted to copy, distribute and/or modify this document under |
|---|
| 5 | % the terms of the GNU Free Documentation License, Version 1.2 or any later |
|---|
| 6 | % version published by the Free Software Foundation; with no Invariant |
|---|
| 7 | % Sections, no Front-Cover Texts and no Back-Cover Texts. A copy of the |
|---|
| 8 | % license is included in the section entitled |
|---|
| 9 | % "GNU Free Documentation License" or the file fdl.tex. |
|---|
| 10 | % |
|---|
| 11 | % Authors: Ewan Mellor, Richard Sharp, Dave Scott, Jon Harrop. |
|---|
| 12 | % |
|---|
| 13 | |
|---|
| 14 | \section{Wire Protocol for Remote API Calls} |
|---|
| 15 | |
|---|
| 16 | API calls are sent over a network to a Xen-enabled host using |
|---|
| 17 | the XML-RPC protocol. In this Section we describe how the |
|---|
| 18 | higher-level types used in our API Reference are mapped to |
|---|
| 19 | primitive XML-RPC types. |
|---|
| 20 | |
|---|
| 21 | In our API Reference we specify the signatures of API functions in the following |
|---|
| 22 | style: |
|---|
| 23 | \begin{verbatim} |
|---|
| 24 | (ref_vm Set) VM.get_all() |
|---|
| 25 | \end{verbatim} |
|---|
| 26 | This specifies that the function with name {\tt VM.get\_all} takes |
|---|
| 27 | no parameters and returns a Set of {\tt ref\_vm}s. |
|---|
| 28 | These types are mapped onto XML-RPC types in a straight-forward manner: |
|---|
| 29 | \begin{itemize} |
|---|
| 30 | \item Floats, Bools, DateTimes and Strings map directly to the XML-RPC {\tt |
|---|
| 31 | double}, {\tt boolean}, {\tt dateTime.iso8601}, and {\tt string} elements. |
|---|
| 32 | |
|---|
| 33 | \item all ``{\tt ref\_}'' types are opaque references, encoded as the |
|---|
| 34 | XML-RPC's {\tt String} type. Users of the API should not make assumptions |
|---|
| 35 | about the concrete form of these strings and should not expect them to |
|---|
| 36 | remain valid after the client's session with the server has terminated. |
|---|
| 37 | |
|---|
| 38 | \item fields named ``{\tt uuid}'' of type ``{\tt String}'' are mapped to |
|---|
| 39 | the XML-RPC {\tt String} type. The string itself is the OSF |
|---|
| 40 | DCE UUID presentation format (as output by {\tt uuidgen}, etc). |
|---|
| 41 | |
|---|
| 42 | \item ints are all assumed to be 64-bit in our API and are encoded as a |
|---|
| 43 | string of decimal digits (rather than using XML-RPC's built-in 32-bit {\tt |
|---|
| 44 | i4} type). |
|---|
| 45 | |
|---|
| 46 | \item values of enum types are encoded as strings. For example, a value of |
|---|
| 47 | {\tt destroy} of type {\tt on\_normal\_exit}, would be conveyed as: |
|---|
| 48 | \begin{verbatim} |
|---|
| 49 | <value><string>destroy</string></value> |
|---|
| 50 | \end{verbatim} |
|---|
| 51 | |
|---|
| 52 | \item for all our types, {\tt t}, our type {\tt t Set} simply maps to |
|---|
| 53 | XML-RPC's {\tt Array} type, so for example a value of type {\tt cpu\_feature |
|---|
| 54 | Set} would be transmitted like this: |
|---|
| 55 | |
|---|
| 56 | \begin{verbatim} |
|---|
| 57 | <array> |
|---|
| 58 | <data> |
|---|
| 59 | <value><string>CX8</string></value> |
|---|
| 60 | <value><string>PSE36</string></value> |
|---|
| 61 | <value><string>FPU</string></value> |
|---|
| 62 | </data> |
|---|
| 63 | </array> |
|---|
| 64 | \end{verbatim} |
|---|
| 65 | |
|---|
| 66 | \item for types {\tt k} and {\tt v}, our type {\tt (k, v) Map} maps onto an |
|---|
| 67 | XML-RPC struct, with the key as the name of the struct. Note that the {\tt |
|---|
| 68 | (k, v) Map} type is only valid when {\tt k} is a {\tt String}, {\tt Ref}, or |
|---|
| 69 | {\tt Int}, and in each case the keys of the maps are stringified as |
|---|
| 70 | above. For example, the {\tt (String, double) Map} containing a the mappings |
|---|
| 71 | Mike $\rightarrow$ 2.3 and John $\rightarrow$ 1.2 would be represented as: |
|---|
| 72 | |
|---|
| 73 | \begin{verbatim} |
|---|
| 74 | <value> |
|---|
| 75 | <struct> |
|---|
| 76 | <member> |
|---|
| 77 | <name>Mike</name> |
|---|
| 78 | <value><double>2.3</double></value> |
|---|
| 79 | </member> |
|---|
| 80 | <member> |
|---|
| 81 | <name>John</name> |
|---|
| 82 | <value><double>1.2</double></value> |
|---|
| 83 | </member> |
|---|
| 84 | </struct> |
|---|
| 85 | </value> |
|---|
| 86 | \end{verbatim} |
|---|
| 87 | |
|---|
| 88 | \item our {\tt Void} type is transmitted as an empty string. |
|---|
| 89 | |
|---|
| 90 | \end{itemize} |
|---|
| 91 | |
|---|
| 92 | \subsection{Note on References vs UUIDs} |
|---|
| 93 | |
|---|
| 94 | References are opaque types --- encoded as XML-RPC strings on the wire --- understood |
|---|
| 95 | only by the particular server which generated them. Servers are free to choose |
|---|
| 96 | any concrete representation they find convenient; clients should not make any |
|---|
| 97 | assumptions or attempt to parse the string contents. References are not guaranteed |
|---|
| 98 | to be permanent identifiers for objects; clients should not assume that references |
|---|
| 99 | generated during one session are valid for any future session. References do not |
|---|
| 100 | allow objects to be compared for equality. Two references to the same object are |
|---|
| 101 | not guaranteed to be textually identical. |
|---|
| 102 | |
|---|
| 103 | UUIDs are intended to be permanent names for objects. They are |
|---|
| 104 | guaranteed to be in the OSF DCE UUID presentation format (as output by {\tt uuidgen}. |
|---|
| 105 | Clients may store UUIDs on disk and use them to lookup objects in subsequent sessions |
|---|
| 106 | with the server. Clients may also test equality on objects by comparing UUID strings. |
|---|
| 107 | |
|---|
| 108 | The API provides mechanisms |
|---|
| 109 | for translating between UUIDs and opaque references. Each class that contains a UUID |
|---|
| 110 | field provides: |
|---|
| 111 | \begin{itemize} |
|---|
| 112 | \item A ``{\tt get\_by\_uuid}'' method that takes a UUID, $u$, and returns an opaque reference |
|---|
| 113 | to the server-side object that has UUID=$u$; |
|---|
| 114 | \item A {\tt get\_uuid} function (a regular ``field getter'' RPC) that takes an opaque reference, |
|---|
| 115 | $r$, and returns the UUID of the server-side object that is referenced by $r$. |
|---|
| 116 | \end{itemize} |
|---|
| 117 | |
|---|
| 118 | \subsection{Return Values/Status Codes} |
|---|
| 119 | \label{synchronous-result} |
|---|
| 120 | |
|---|
| 121 | The return value of an RPC call is an XML-RPC {\tt Struct}. |
|---|
| 122 | |
|---|
| 123 | \begin{itemize} |
|---|
| 124 | \item The first element of the struct is named {\tt Status}; it |
|---|
| 125 | contains a string value indicating whether the result of the call was |
|---|
| 126 | a ``{\tt Success}'' or a ``{\tt Failure}''. |
|---|
| 127 | \end{itemize} |
|---|
| 128 | |
|---|
| 129 | If {\tt Status} was set to {\tt Success} then the Struct contains a second |
|---|
| 130 | element named {\tt Value}: |
|---|
| 131 | \begin{itemize} |
|---|
| 132 | \item The element of the struct named {\tt Value} contains the function's return value. |
|---|
| 133 | \end{itemize} |
|---|
| 134 | |
|---|
| 135 | In the case where {\tt Status} is set to {\tt Failure} then |
|---|
| 136 | the struct contains a second element named {\tt ErrorDescription}: |
|---|
| 137 | \begin{itemize} |
|---|
| 138 | \item The element of the struct named {\tt ErrorDescription} contains |
|---|
| 139 | an array of string values. The first element of the array is an error code; |
|---|
| 140 | the remainder of the array are strings representing error parameters relating |
|---|
| 141 | to that code. |
|---|
| 142 | \end{itemize} |
|---|
| 143 | |
|---|
| 144 | For example, an XML-RPC return value from the {\tt host.get\_resident\_VMs} |
|---|
| 145 | function above |
|---|
| 146 | may look like this: |
|---|
| 147 | \begin{verbatim} |
|---|
| 148 | <struct> |
|---|
| 149 | <member> |
|---|
| 150 | <name>Status</name> |
|---|
| 151 | <value>Success</value> |
|---|
| 152 | </member> |
|---|
| 153 | <member> |
|---|
| 154 | <name>Value</name> |
|---|
| 155 | <value> |
|---|
| 156 | <array> |
|---|
| 157 | <data> |
|---|
| 158 | <value>81547a35-205c-a551-c577-00b982c5fe00</value> |
|---|
| 159 | <value>61c85a22-05da-b8a2-2e55-06b0847da503</value> |
|---|
| 160 | <value>1d401ec4-3c17-35a6-fc79-cee6bd9811fe</value> |
|---|
| 161 | </data> |
|---|
| 162 | </array> |
|---|
| 163 | </value> |
|---|
| 164 | </member> |
|---|
| 165 | </struct> |
|---|
| 166 | \end{verbatim} |
|---|
| 167 | |
|---|
| 168 | \section{Making XML-RPC Calls} |
|---|
| 169 | |
|---|
| 170 | \subsection{Transport Layer} |
|---|
| 171 | |
|---|
| 172 | The following transport layers are currently supported: |
|---|
| 173 | \begin{itemize} |
|---|
| 174 | \item HTTP/S for remote administration |
|---|
| 175 | \item HTTP over Unix domain sockets for local administration |
|---|
| 176 | \end{itemize} |
|---|
| 177 | |
|---|
| 178 | \subsection{Session Layer} |
|---|
| 179 | |
|---|
| 180 | The XML-RPC interface is session-based; before you can make arbitrary RPC calls |
|---|
| 181 | you must login and initiate a session. For example: |
|---|
| 182 | \begin{verbatim} |
|---|
| 183 | session_id session.login_with_password(string uname, string pwd) |
|---|
| 184 | \end{verbatim} |
|---|
| 185 | Where {\tt uname} and {\tt password} refer to your username and password |
|---|
| 186 | respectively, as defined by the Xen administrator. |
|---|
| 187 | The {\tt session\_id} returned by {\tt session.login\_with\_password} is passed |
|---|
| 188 | to subequent RPC calls as an authentication token. |
|---|
| 189 | |
|---|
| 190 | A session can be terminated with the {\tt session.logout} function: |
|---|
| 191 | \begin{verbatim} |
|---|
| 192 | void session.logout(session_id session) |
|---|
| 193 | \end{verbatim} |
|---|
| 194 | |
|---|
| 195 | \subsection{Synchronous and Asynchronous invocation} |
|---|
| 196 | |
|---|
| 197 | Each method call (apart from methods on ``Session'' and ``Task'' objects |
|---|
| 198 | and ``getters'' and ``setters'' derived from fields) |
|---|
| 199 | can be made either synchronously or asynchronously. |
|---|
| 200 | A synchronous RPC call blocks until the |
|---|
| 201 | return value is received; the return value of a synchronous RPC call is |
|---|
| 202 | exactly as specified in Section~\ref{synchronous-result}. |
|---|
| 203 | |
|---|
| 204 | Only synchronous API calls are listed explicitly in this document. |
|---|
| 205 | All asynchronous versions are in the special {\tt Async} namespace. |
|---|
| 206 | For example, synchronous call {\tt VM.clone(...)} |
|---|
| 207 | (described in Chapter~\ref{api-reference}) |
|---|
| 208 | has an asynchronous counterpart, {\tt |
|---|
| 209 | Async.VM.clone(...)}, that is non-blocking. |
|---|
| 210 | |
|---|
| 211 | Instead of returning its result directly, an asynchronous RPC call |
|---|
| 212 | returns a {\tt task-id}; this identifier is subsequently used |
|---|
| 213 | to track the status of a running asynchronous RPC. Note that an asychronous |
|---|
| 214 | call may fail immediately, before a {\tt task-id} has even been created---to |
|---|
| 215 | represent this eventuality, the returned {\tt task-id} |
|---|
| 216 | is wrapped in an XML-RPC struct with a {\tt Status}, {\tt ErrorDescription} and |
|---|
| 217 | {\tt Value} fields, exactly as specified in Section~\ref{synchronous-result}. |
|---|
| 218 | |
|---|
| 219 | The {\tt task-id} is provided in the {\tt Value} field if {\tt Status} is set to |
|---|
| 220 | {\tt Success}. |
|---|
| 221 | |
|---|
| 222 | The RPC call |
|---|
| 223 | \begin{verbatim} |
|---|
| 224 | (ref_task Set) Task.get_all(session_id s) |
|---|
| 225 | \end{verbatim} |
|---|
| 226 | returns a set of all task IDs known to the system. The status (including any |
|---|
| 227 | returned result and error codes) of these tasks |
|---|
| 228 | can then be queried by accessing the fields of the Task object in the usual way. |
|---|
| 229 | Note that, in order to get a consistent snapshot of a task's state, it is advisable to call the ``get\_record'' function. |
|---|
| 230 | |
|---|
| 231 | \section{Example interactive session} |
|---|
| 232 | |
|---|
| 233 | This section describes how an interactive session might look, using the python |
|---|
| 234 | XML-RPC client library. |
|---|
| 235 | |
|---|
| 236 | First, initialise python and import the library {\tt xmlrpclib}: |
|---|
| 237 | |
|---|
| 238 | \begin{verbatim} |
|---|
| 239 | \$ python2.4 |
|---|
| 240 | ... |
|---|
| 241 | >>> import xmlrpclib |
|---|
| 242 | \end{verbatim} |
|---|
| 243 | |
|---|
| 244 | Create a python object referencing the remote server: |
|---|
| 245 | |
|---|
| 246 | \begin{verbatim} |
|---|
| 247 | >>> xen = xmlrpclib.Server("http://test:4464") |
|---|
| 248 | \end{verbatim} |
|---|
| 249 | |
|---|
| 250 | Acquire a session token by logging in with a username and password |
|---|
| 251 | (error-handling ommitted for brevity; the session token is pointed to by the |
|---|
| 252 | key {\tt 'Value'} in the returned dictionary) |
|---|
| 253 | |
|---|
| 254 | \begin{verbatim} |
|---|
| 255 | >>> session = session.login_with_password("user", "passwd")['Value'] |
|---|
| 256 | \end{verbatim} |
|---|
| 257 | |
|---|
| 258 | When serialised, this call looks like the following: |
|---|
| 259 | |
|---|
| 260 | \begin{verbatim} |
|---|
| 261 | <?xml version='1.0'?> |
|---|
| 262 | <methodCall> |
|---|
| 263 | <methodName>session.login_with_password</methodName> |
|---|
| 264 | <params> |
|---|
| 265 | <param> |
|---|
| 266 | <value><string>user</string></value> |
|---|
| 267 | </param> |
|---|
| 268 | <param> |
|---|
| 269 | <value><string>passwd</string></value> |
|---|
| 270 | </param> |
|---|
| 271 | </params> |
|---|
| 272 | </methodCall> |
|---|
| 273 | \end{verbatim} |
|---|
| 274 | |
|---|
| 275 | Next, the user may acquire a list of all the VMs known to the host: (Note the |
|---|
| 276 | call takes the session token as the only parameter) |
|---|
| 277 | |
|---|
| 278 | \begin{verbatim} |
|---|
| 279 | >>> all_vms = host.get_resident_VMs(session)['Value'] |
|---|
| 280 | >>> all_vms |
|---|
| 281 | ['OpaqueRef:1', 'OpaqueRef:2', 'OpaqueRef:3', 'OpaqueRef:4' ] |
|---|
| 282 | \end{verbatim} |
|---|
| 283 | |
|---|
| 284 | The VM references here have the form {\tt OpaqueRef:X}, though they may not be |
|---|
| 285 | that simple in the future, and you should treat them as opaque strings. |
|---|
| 286 | Once a reference to a VM has been acquired a lifecycle operation may be invoked: |
|---|
| 287 | |
|---|
| 288 | \begin{verbatim} |
|---|
| 289 | >>> xen.VM.start(session, all_vms[3], False) |
|---|
| 290 | {'Status': 'Failure', 'ErrorDescription': ['VM_BAD_POWER_STATE', 'Halted', 'Running']} |
|---|
| 291 | \end{verbatim} |
|---|
| 292 | |
|---|
| 293 | In this case the {\tt start} message has been rejected, because the VM is |
|---|
| 294 | already running, and so an error response has been returned. These high-level |
|---|
| 295 | errors are returned as structured data (rather than as XML-RPC faults), |
|---|
| 296 | allowing them to be internationalised. Finally, here are some examples of |
|---|
| 297 | using accessors for object fields: |
|---|
| 298 | |
|---|
| 299 | \begin{verbatim} |
|---|
| 300 | >>> xen.VM.get_name_label(session, all_vms[3])['Value'] |
|---|
| 301 | 'SMP' |
|---|
| 302 | >>> xen.VM.get_name_description(session, all_vms[3])['Value'] |
|---|
| 303 | 'Debian for Xen' |
|---|
| 304 | \end{verbatim} |
|---|