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} |
---|