ia64/xen-unstable

view tools/xfrd/xen_domain.c @ 2422:2274a0386cc9

bitkeeper revision 1.1159.69.5 (4138e882jA1YaR_OfTfNHe_uT4PDIg)

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