debuggers.hg

view tools/xfrd/xen_domain.c @ 2628:98bdf2c88015

bitkeeper revision 1.1159.1.201 (41600e1fkVMoQU0dVgk1h6vT502hEg)

Merge
author iap10@labyrinth.cl.cam.ac.uk
date Sun Oct 03 14:35:11 2004 +0000 (2004-10-03)
parents 1bd15a9e5016 05ae99de2d3f
children e442cedb12d8
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;
143 }
145 err = xc_linux_restore(xcinit(), ioctxt);
146 *dom = ioctxt->domain;
147 *vmconfig = ioctxt->vmconfig;
148 *vmconfig_n = ioctxt->vmconfig_n;
149 *configured = (ioctxt->flags & XCFLAGS_CONFIGURE);
150 #endif
151 dprintf("< err=%d\n", err);
152 return err;
153 }
155 #include <curl/curl.h>
156 #include "http.h"
158 /** Flag indicating whether we need to initialize libcurl.
159 */
160 static int do_curl_global_init = 1;
162 /** Get a curl handle, initializing libcurl if needed.
163 *
164 * @return curl handle
165 */
166 static CURL *curlinit(void){
167 if(do_curl_global_init){
168 do_curl_global_init = 0;
169 // Stop libcurl using the proxy. There's a curl option to
170 // set the proxy - but no option to defeat it.
171 unsetenv("http_proxy");
172 curl_global_init(CURL_GLOBAL_ALL);
173 }
174 return curl_easy_init();
175 }
177 /** Curl debug function.
178 */
179 int curldebug(CURL *curl, curl_infotype ty, char *buf, size_t buf_n, void *data){
180 printf("%*s\n", buf_n, buf);
181 return 0;
182 }
184 /** Setup a curl handle with a url.
185 * Creates the url by formatting 'fmt' and the remaining arguments.
186 *
187 * @param pcurl return parameter for the curl handle
188 * @param url url buffer
189 * @param url_n size of url
190 * @param fmt url format string, followed by parameters
191 * @return 0 on success, error code otherwise
192 */
193 static int curlsetup(CURL **pcurl, char *url, int url_n, char *fmt, ...){
194 int err = 0;
195 va_list args;
196 CURL *curl = 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);
228 exit:
229 if(err && curl){
230 curl_easy_cleanup(curl);
231 curl = NULL;
232 }
233 *pcurl = curl;
234 return err;
235 }
237 /** Make the http request stored in the curl handle and get
238 * the result code from the curl code and the http return code.
239 *
240 * @param curl curl handle
241 * @return 0 for success, error code otherwise
242 */
243 int curlresult(CURL *curl){
244 int err = 0;
245 CURLcode curlcode = 0;
246 long httpcode = 0;
248 curlcode = curl_easy_perform(curl);
249 if(curlcode){
250 eprintf("> curlcode=%d\n", curlcode);
251 err = -EINVAL;
252 goto exit;
253 }
254 curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &httpcode);
255 if(httpcode != HTTP_OK){
256 eprintf("> httpcode=%d\n", (int)httpcode);
257 err = -EINVAL;
258 goto exit;
259 }
260 exit:
261 return err;
262 }
264 /** Get xend to list domains.
265 * We use this to force xend to refresh its domain list.
266 *
267 * @return 0 on success, error code otherwise
268 */
269 int xen_domain_ls(void){
270 int err = 0;
271 CURL *curl = NULL;
272 char url[128] = {};
273 int url_n = sizeof(url);
275 dprintf(">\n");
276 err = curlsetup(&curl, url, url_n, "http://localhost:%d/xend/domain", XEND_PORT);
277 if(err) goto exit;
278 err = curlresult(curl);
279 exit:
280 if(curl) curl_easy_cleanup(curl);
281 dprintf("< err=%d\n", err);
282 return err;
283 }
285 /** Get xend to configure a new domain.
286 *
287 * @param dom domain id
288 * @param vmconfig configuration string
289 * @param vmconfig_n length of vmconfig
290 * @return 0 on success, error code otherwise
291 */
292 int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n){
293 int err = 0;
294 CURL *curl = NULL;
295 char url[128] = {};
296 int url_n = sizeof(url);
297 struct curl_httppost *form = NULL, *last = NULL;
298 CURLFORMcode formcode = 0;
300 dprintf("> dom=%u\n", dom);
301 // List domains so that xend will update its domain list and notice the new domain.
302 xen_domain_ls();
304 err = curlsetup(&curl, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
305 if(err) goto exit;
307 // Config field - set from vmconfig.
308 formcode = curl_formadd(&form, &last,
309 CURLFORM_COPYNAME, "config",
310 CURLFORM_BUFFER, "config",
311 CURLFORM_BUFFERPTR, vmconfig,
312 CURLFORM_BUFFERLENGTH, vmconfig_n,
313 CURLFORM_CONTENTTYPE, "application/octet-stream",
314 CURLFORM_END);
315 if(formcode){
316 eprintf("> Error adding config field.\n");
317 goto exit;
318 }
319 // Op field.
320 formcode = curl_formadd(&form, &last,
321 CURLFORM_COPYNAME, "op",
322 CURLFORM_COPYCONTENTS, "configure",
323 CURLFORM_END);
324 if(formcode){
325 eprintf("> Error adding op field.\n");
326 err = -EINVAL;
327 goto exit;
328 }
329 // POST the form.
330 curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
331 err = curlresult(curl);
332 exit:
333 if(curl) curl_easy_cleanup(curl);
334 if(form) curl_formfree(form);
335 dprintf("< err=%d\n", err);
336 return err;
337 }
339 /** Get xend to unpause a domain.
340 *
341 * @param dom domain id
342 * @return 0 on success, error code otherwise
343 */
344 int xen_domain_unpause(uint32_t dom){
345 int err = 0;
346 CURL *curl = NULL;
347 char url[128] = {};
348 int url_n = sizeof(url);
349 struct curl_httppost *form = NULL, *last = NULL;
350 CURLFORMcode formcode = 0;
352 dprintf("> dom=%u\n", dom);
354 err = curlsetup(&curl, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
355 if(err) goto exit;
357 // Op field.
358 formcode = curl_formadd(&form, &last,
359 CURLFORM_COPYNAME, "op",
360 CURLFORM_COPYCONTENTS, "unpause",
361 CURLFORM_END);
362 if(formcode){
363 eprintf("> Error adding op field.\n");
364 err = -EINVAL;
365 goto exit;
366 }
367 // POST the form.
368 curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
369 err = curlresult(curl);
370 exit:
371 if(curl) curl_easy_cleanup(curl);
372 if(form) curl_formfree(form);
373 dprintf("< err=%d\n", err);
374 return err;
375 }