debuggers.hg

view tools/xfrd/xen_domain.c @ 2658:1594b2cbd611

bitkeeper revision 1.1159.106.1 (416a8109xgmei-w5YEUGhvGcsR-fow)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xeno.bk-26dom0
into freefall.cl.cam.ac.uk:/local/scratch/cl349/xeno.bk-26dom0
author cl349@freefall.cl.cam.ac.uk
date Mon Oct 11 12:48:09 2004 +0000 (2004-10-11)
parents e442cedb12d8 f00a106e5d16
children 9402048e2325
line source
1 #include <unistd.h>
2 #include <stdlib.h>
3 #include <stdio.h>
5 #ifdef _XEN_XFR_STUB_
6 typedef unsigned long u32;
7 #else
8 #include "xc.h"
9 #include "xc_io.h"
10 #endif
12 #include "xen_domain.h"
13 #include "marshal.h"
14 #include "xdr.h"
15 #include "xfrd.h"
17 #define MODULE_NAME "XFRD"
18 #define DEBUG 1
19 #undef DEBUG
20 #include "debug.h"
22 int domain_suspend(void *data, u32 dom){
23 int err = 0;
24 Conn *xend = data;
26 dprintf("> dom=%lu data=%p\n", dom, data);
27 err = xfr_vm_suspend(xend, dom);
28 dprintf("< err=%d\n", err);
29 return err;
30 }
32 int domain_configure(void *data, u32 dom, char *vmconfig, int vmconfig_n){
33 return xen_domain_configure(dom, vmconfig, vmconfig_n);
34 }
36 #ifndef _XEN_XFR_STUB_
37 static int xc_handle = 0;
39 int xcinit(void){
40 if(xc_handle <= 0){
41 xc_handle = xc_interface_open();
42 }
43 dprintf("< xc_handle=%d\n", xc_handle);
44 return xc_handle;
45 }
47 void xcfini(void){
48 if(xc_handle > 0){
49 xc_interface_close(xc_handle);
50 xc_handle = 0;
51 }
52 }
53 #endif
55 /** Write domain state.
56 *
57 * At some point during this the domain is suspended, and then there's no way back.
58 * Even if something later goes wrong we can't restart the domain.
59 */
60 int xen_domain_snd(Conn *xend, IOStream *io,
61 uint32_t dom,
62 char *vmconfig, int vmconfig_n,
63 int live){
64 int err = 0;
65 #ifdef _XEN_XFR_STUB_
66 char buf[1024];
67 int n, k, d, buf_n;
68 dprintf("> dom=%d\n", dom);
69 err = marshal_uint32(io, dom);
70 if(err) goto exit;
71 err = marshal_string(io, vmconfig, vmconfig_n);
72 if(err) goto exit;
73 n = 32 * 1024 * 1024;
74 n = 32 * 1024;
75 buf_n = sizeof(buf);
76 err = marshal_uint32(io, n);
77 for(k = 0; k < n; k += d){
78 d = n - k;
79 if(d > buf_n) d = buf_n;
80 err = marshal_bytes(io, buf, d);
81 if(err) goto exit;
82 dprintf("> k=%d n=%d\n", k, n);
83 }
85 dom = 99;
86 err = domain_suspend(dom, xend);
87 IOStream_close(io);
88 exit:
89 #else
90 XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt;
91 ioctxt->domain = dom;
92 ioctxt->io = io;
93 ioctxt->info = iostdout;
94 ioctxt->err = iostderr;
95 ioctxt->data = xend;
96 ioctxt->suspend = domain_suspend;
97 ioctxt->vmconfig = vmconfig;
98 ioctxt->vmconfig_n = vmconfig_n;
99 if(live){
100 ioctxt->flags |= XCFLAGS_LIVE;
101 }
102 err = xc_linux_save(xcinit(), ioctxt);
103 #endif
104 dprintf("< err=%d\n", err);
105 return err;
106 }
108 /** Receive domain state.
109 * Create a new domain and store the received state into it.
110 */
111 int xen_domain_rcv(IOStream *io,
112 uint32_t *dom,
113 char **vmconfig, int *vmconfig_n,
114 int *configured){
115 int err = 0;
116 #ifdef _XEN_XFR_STUB_
117 char buf[1024];
118 int n, k, d, buf_n;
119 dprintf(">\n");
120 err = unmarshal_uint32(io, dom);
121 if(err) goto exit;
122 err = unmarshal_new_string(io, vmconfig, vmconfig_n);
123 if(err) goto exit;
124 err = unmarshal_uint32(io, &n);
125 buf_n = sizeof(buf);
126 for(k = 0; k < n; k += d){
127 d = n - k;
128 if(d > buf_n) d = buf_n;
129 err = unmarshal_bytes(io, buf, d);
130 if(err) goto exit;
131 dprintf("> k=%d n=%d\n", k, n);
132 }
133 exit:
134 #else
135 XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt;
136 dprintf(">\n");
137 ioctxt->io = io;
138 ioctxt->info = iostdout;
139 ioctxt->err = iostderr;
140 ioctxt->configure = domain_configure;
141 if ( !*configured )
142 ioctxt->flags |= XCFLAGS_CONFIGURE;
144 err = xc_linux_restore(xcinit(), ioctxt);
145 *dom = ioctxt->domain;
146 *vmconfig = ioctxt->vmconfig;
147 *vmconfig_n = ioctxt->vmconfig_n;
148 *configured = (ioctxt->flags & XCFLAGS_CONFIGURE);
149 #endif
150 dprintf("< err=%d\n", err);
151 return err;
152 }
154 #include <curl/curl.h>
155 #include "http.h"
157 /** Flag indicating whether we need to initialize libcurl.
158 */
159 static int do_curl_global_init = 1;
161 /** Get a curl handle, initializing libcurl if needed.
162 *
163 * @return curl handle
164 */
165 static CURL *curlinit(void){
166 if(do_curl_global_init){
167 do_curl_global_init = 0;
168 // Stop libcurl using the proxy. There's a curl option to
169 // set the proxy - but no option to defeat it.
170 unsetenv("http_proxy");
171 curl_global_init(CURL_GLOBAL_ALL);
172 }
173 return curl_easy_init();
174 }
176 /** Curl debug function.
177 */
178 int curldebug(CURL *curl, curl_infotype ty, char *buf, size_t buf_n, void *data){
179 printf("%*s\n", buf_n, buf);
180 return 0;
181 }
183 /** Setup a curl handle with a url.
184 * Creates the url by formatting 'fmt' and the remaining arguments.
185 *
186 * @param pcurl return parameter for the curl handle
187 * @param url url buffer
188 * @param url_n size of url
189 * @param fmt url format string, followed by parameters
190 * @return 0 on success, error code otherwise
191 */
192 static int curlsetup(CURL **pcurl, struct curl_slist **pheaders, char *url, int url_n, char *fmt, ...){
193 int err = 0;
194 va_list args;
195 CURL *curl = NULL;
196 struct curl_slist *headers = NULL;
197 int n = 0;
199 curl = curlinit();
200 if(!curl){
201 eprintf("> Could not init libcurl\n");
202 err = -ENOMEM;
203 goto exit;
204 }
205 url_n -= 1;
206 va_start(args, fmt);
207 n = vsnprintf(url, url_n, fmt, args);
208 va_end(args);
209 if(n <= 0 || n >= url_n){
210 err = -ENOMEM;
211 eprintf("> Out of memory in url\n");
212 goto exit;
213 }
214 dprintf("> url=%s\n", url);
215 #if DEBUG
216 // Verbose.
217 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
218 // Call the debug function on data received.
219 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curldebug);
220 #else
221 // No progress meter.
222 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
223 // Completely quiet.
224 curl_easy_setopt(curl, CURLOPT_MUTE, 1);
225 #endif
226 // Set the URL.
227 curl_easy_setopt(curl, CURLOPT_URL, url);
229 headers = curl_slist_append(headers, "Expect:");
230 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
232 exit:
233 if(err && curl){
234 curl_easy_cleanup(curl);
235 curl = NULL;
236 }
237 *pcurl = curl;
238 if (pheaders)
239 *pheaders = headers;
240 return err;
241 }
243 static void curlcleanup(CURL **pcurl, struct curl_slist **pheaders){
244 if (*pcurl)
245 curl_easy_cleanup(*pcurl);
246 if (*pheaders)
247 curl_slist_free_all(*pheaders);
248 *pcurl = NULL;
249 *pheaders = NULL;
250 }
251 /** Make the http request stored in the curl handle and get
252 * the result code from the curl code and the http return code.
253 *
254 * @param curl curl handle
255 * @return 0 for success, error code otherwise
256 */
257 int curlresult(CURL *curl){
258 int err = 0;
259 CURLcode curlcode = 0;
260 long httpcode = 0;
262 curlcode = curl_easy_perform(curl);
263 if(curlcode){
264 eprintf("> curlcode=%d\n", curlcode);
265 err = -EINVAL;
266 goto exit;
267 }
268 curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &httpcode);
269 if(httpcode != HTTP_OK){
270 eprintf("> httpcode=%d\n", (int)httpcode);
271 err = -EINVAL;
272 goto exit;
273 }
274 exit:
275 return err;
276 }
278 /** Get xend to list domains.
279 * We use this to force xend to refresh its domain list.
280 *
281 * @return 0 on success, error code otherwise
282 */
283 int xen_domain_ls(void){
284 int err = 0;
285 CURL *curl = NULL;
286 struct curl_slist *headers = NULL;
287 char url[128] = {};
288 int url_n = sizeof(url);
290 dprintf(">\n");
291 err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain", XEND_PORT);
292 if(err) goto exit;
293 err = curlresult(curl);
294 exit:
295 curlcleanup(&curl, &headers);
296 dprintf("< err=%d\n", err);
297 return err;
298 }
300 /** Get xend to configure a new domain.
301 *
302 * @param dom domain id
303 * @param vmconfig configuration string
304 * @param vmconfig_n length of vmconfig
305 * @return 0 on success, error code otherwise
306 */
307 int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n){
308 int err = 0;
309 CURL *curl = NULL;
310 struct curl_slist *headers = NULL;
311 char url[128] = {};
312 int url_n = sizeof(url);
313 struct curl_httppost *form = NULL, *last = NULL;
314 CURLFORMcode formcode = 0;
316 dprintf("> dom=%u\n", dom);
317 // List domains so that xend will update its domain list and notice the new domain.
318 xen_domain_ls();
320 err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
321 if(err) goto exit;
323 // Config field - set from vmconfig.
324 formcode = curl_formadd(&form, &last,
325 CURLFORM_COPYNAME, "config",
326 CURLFORM_BUFFER, "config",
327 CURLFORM_BUFFERPTR, vmconfig,
328 CURLFORM_BUFFERLENGTH, vmconfig_n,
329 CURLFORM_CONTENTTYPE, "application/octet-stream",
330 CURLFORM_END);
331 if(formcode){
332 eprintf("> Error adding config field.\n");
333 goto exit;
334 }
335 // Op field.
336 formcode = curl_formadd(&form, &last,
337 CURLFORM_COPYNAME, "op",
338 CURLFORM_COPYCONTENTS, "configure",
339 CURLFORM_END);
340 if(formcode){
341 eprintf("> Error adding op field.\n");
342 err = -EINVAL;
343 goto exit;
344 }
345 // POST the form.
346 curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
347 err = curlresult(curl);
348 exit:
349 curlcleanup(&curl, &headers);
350 if(form) curl_formfree(form);
351 dprintf("< err=%d\n", err);
352 return err;
353 }
355 /** Get xend to unpause a domain.
356 *
357 * @param dom domain id
358 * @return 0 on success, error code otherwise
359 */
360 int xen_domain_unpause(uint32_t dom){
361 int err = 0;
362 CURL *curl = NULL;
363 struct curl_slist *headers = NULL;
364 char url[128] = {};
365 int url_n = sizeof(url);
366 struct curl_httppost *form = NULL, *last = NULL;
367 CURLFORMcode formcode = 0;
369 dprintf("> dom=%u\n", dom);
371 err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
372 if(err) goto exit;
374 // Op field.
375 formcode = curl_formadd(&form, &last,
376 CURLFORM_COPYNAME, "op",
377 CURLFORM_COPYCONTENTS, "unpause",
378 CURLFORM_END);
379 if(formcode){
380 eprintf("> Error adding op field.\n");
381 err = -EINVAL;
382 goto exit;
383 }
384 // POST the form.
385 curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
386 err = curlresult(curl);
387 exit:
388 curlcleanup(&curl, &headers);
389 if(form) curl_formfree(form);
390 dprintf("< err=%d\n", err);
391 return err;
392 }