debuggers.hg

view tools/libxl/xl.c @ 20655:8fbc74d40739

libxenlight: add a cli option to exit right after domain creation

This patch adds a command line option in xl to exit right after domain
creation and not wait in background for the death of the domain.
Users should be aware that if they use this option, they always have
to destroy the domain manually after the guest shuts down.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Dec 11 08:46:02 2009 +0000 (2009-12-11)
parents 2c6a04fdf8fb
children b2ccd48f2f9b
line source
1 /*
2 * Copyright (C) 2009 Citrix Ltd.
3 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
4 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; version 2.1 only. with the special
9 * exception on linking described in file LICENSE.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 */
17 #include "libxl_osdeps.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <libconfig.h>
23 #include "xen_uuid.h"
24 #include <unistd.h>
25 #include <sys/time.h> /* for time */
26 #include <getopt.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <sys/socket.h>
31 #include <sys/select.h>
32 #include <arpa/inet.h>
33 #include <xenctrl.h>
36 #include "libxl.h"
37 #include "libxl_utils.h"
39 int logfile = 2;
41 void log_callback(void *userdata, int loglevel, const char *file, int line, const char *func, char *s)
42 {
43 char str[1024];
45 snprintf(str, sizeof(str), "[%d] %s:%d:%s: %s\n", loglevel, file, line, func, s);
46 write(logfile, str, strlen(str));
47 }
49 static void printf_info(libxl_domain_create_info *c_info,
50 libxl_domain_build_info *b_info,
51 libxl_device_disk *disks,
52 int num_disks,
53 libxl_device_nic *vifs,
54 int num_vifs,
55 libxl_device_pci *pcidevs,
56 int num_pcidevs,
57 libxl_device_vfb *vfbs,
58 int num_vfbs,
59 libxl_device_vkb *vkb,
60 int num_vkbs,
61 libxl_device_model_info *dm_info)
62 {
63 int i;
64 char uuid_str[37];
65 printf("*** domain_create_info ***\n");
66 printf("hvm: %d\n", c_info->hvm);
67 printf("hap: %d\n", c_info->hap);
68 printf("ssidref: %d\n", c_info->ssidref);
69 printf("name: %s\n", c_info->name);
70 xen_uuid_to_string(c_info->uuid, uuid_str, sizeof(uuid_str));
71 printf("uuid: %s\n", uuid_str);
72 if (c_info->xsdata)
73 printf("xsdata: contains data\n");
74 else
75 printf("xsdata: (null)\n");
76 if (c_info->platformdata)
77 printf("platformdata: contains data\n");
78 else
79 printf("platformdata: (null)\n");
82 printf("\n\n\n*** domain_build_info ***\n");
83 printf("timer_mode: %d\n", b_info->timer_mode);
84 printf("hpet: %d\n", b_info->hpet);
85 printf("vpt_align: %d\n", b_info->vpt_align);
86 printf("max_vcpus: %d\n", b_info->max_vcpus);
87 printf("max_memkb: %d\n", b_info->max_memkb);
88 printf("target_memkb: %d\n", b_info->target_memkb);
89 printf("kernel: %s\n", b_info->kernel);
90 printf("hvm: %d\n", b_info->hvm);
92 if (c_info->hvm) {
93 printf("video_memkb: %d\n", b_info->video_memkb);
94 printf("shadow_memkb: %d\n", b_info->shadow_memkb);
95 printf(" pae: %d\n", b_info->u.hvm.pae);
96 printf(" apic: %d\n", b_info->u.hvm.apic);
97 printf(" acpi: %d\n", b_info->u.hvm.acpi);
98 printf(" nx: %d\n", b_info->u.hvm.nx);
99 printf(" viridian: %d\n", b_info->u.hvm.viridian);
100 } else {
101 printf("cmdline: %s\n", b_info->u.pv.cmdline);
102 printf("ramdisk: %s\n", b_info->u.pv.ramdisk);
103 }
105 for (i = 0; i < num_disks; i++) {
106 printf("\n\n\n*** disks_info: %d ***\n", i);
107 printf("backend_domid %d\n", disks[i].backend_domid);
108 printf("domid %d\n", disks[i].domid);
109 printf("physpath %s\n", disks[i].physpath);
110 printf("phystype %d\n", disks[i].phystype);
111 printf("virtpath %s\n", disks[i].virtpath);
112 printf("unpluggable %d\n", disks[i].unpluggable);
113 printf("readwrite %d\n", disks[i].readwrite);
114 printf("is_cdrom %d\n", disks[i].is_cdrom);
115 }
117 for (i = 0; i < num_vifs; i++) {
118 printf("\n\n\n*** vifs_info: %d ***\n", i);
119 printf("backend_domid %d\n", vifs[i].backend_domid);
120 printf("domid %d\n", vifs[i].domid);
121 printf("devid %d\n", vifs[i].devid);
122 printf("mtu %d\n", vifs[i].mtu);
123 printf("model %s\n", vifs[i].model);
124 printf("mac %02x:%02x:%02x:%02x:%02x:%02x\n", vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2], vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
125 printf("smac %s\n", vifs[i].mac);
126 }
128 for (i = 0; i < num_pcidevs; i++) {
129 printf("\n\n\n*** pcidevs_info: %d ***\n", i);
130 printf("pci dev "PCI_BDF_VDEVFN"\n", pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func, pcidevs[i].vdevfn);
131 printf("opts msitranslate %d power_mgmt %d\n", pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
132 }
134 for (i = 0; i < num_vfbs; i++) {
135 printf("\n\n\n*** vfbs_info: %d ***\n", i);
136 printf("backend_domid %d\n", vfbs[i].backend_domid);
137 printf("domid %d\n", vfbs[i].domid);
138 printf("devid %d\n", vfbs[i].devid);
139 printf("vnc: %d\n", vfbs[i].vnc);
140 printf("vnclisten: %s\n", vfbs[i].vnclisten);
141 printf("vncdisplay: %d\n", vfbs[i].vncdisplay);
142 printf("vncunused: %d\n", vfbs[i].vncunused);
143 printf("keymap: %s\n", vfbs[i].keymap);
144 printf("sdl: %d\n", vfbs[i].sdl);
145 printf("opengl: %d\n", vfbs[i].opengl);
146 printf("display: %s\n", vfbs[i].display);
147 printf("xauthority: %s\n", vfbs[i].xauthority);
148 }
150 if (c_info->hvm) {
151 printf("\n\n\n*** device_model_info ***\n");
152 printf("domid: %d\n", dm_info->domid);
153 printf("dom_name: %s\n", dm_info->dom_name);
154 printf("device_model: %s\n", dm_info->device_model);
155 printf("videoram: %d\n", dm_info->videoram);
156 printf("stdvga: %d\n", dm_info->stdvga);
157 printf("vnc: %d\n", dm_info->vnc);
158 printf("vnclisten: %s\n", dm_info->vnclisten);
159 printf("vncdisplay: %d\n", dm_info->vncdisplay);
160 printf("vncunused: %d\n", dm_info->vncunused);
161 printf("keymap: %s\n", dm_info->keymap);
162 printf("sdl: %d\n", dm_info->sdl);
163 printf("opengl: %d\n", dm_info->opengl);
164 printf("nographic: %d\n", dm_info->nographic);
165 printf("serial: %s\n", dm_info->serial);
166 printf("boot: %s\n", dm_info->boot);
167 printf("usb: %d\n", dm_info->usb);
168 printf("usbdevice: %s\n", dm_info->usbdevice);
169 printf("apic: %d\n", dm_info->apic);
170 }
171 }
173 static char* compat_config_file(const char *filename)
174 {
175 char t;
176 char *newfile = (char*) malloc(strlen(filename) + 4);
177 char *buf = (char *) malloc(2048);
178 int size = 2048, i;
179 FILE *s;
180 FILE *d;
182 sprintf(newfile, "%s.xl", filename);
184 s = fopen(filename, "r");
185 if (!s) {
186 perror("cannot open file for reading");
187 return NULL;
188 }
189 d = fopen(newfile, "w");
190 if (!d) {
191 fclose(s);
192 perror("cannot open file for writting");
193 return NULL;
194 }
196 while (!feof(s)) {
197 fgets(buf, size, s);
198 while (buf[strlen(buf) - 1] != '\n' && !feof(s)) {
199 size += 1024;
200 buf = realloc(buf, size + 1024);
201 fgets(buf + (size - 1025), 1025, s);
202 }
203 for (i = 0; i < strlen(buf); i++)
204 if (buf[i] == '\'')
205 buf[i] = '\"';
206 if (strchr(buf, '=') != NULL) {
207 if ((buf[strlen(buf) - 1] == '\n' && buf[strlen(buf) - 2] == ';') ||
208 buf[strlen(buf) - 1] == ';') {
209 fputs(buf, d);
210 } else {
211 t = buf[strlen(buf) - 1];
212 buf[strlen(buf) - 1] = ';';
213 fputs(buf, d);
214 fputc(t, d);
215 }
216 } else if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') {
217 fputs(buf, d);
218 }
219 }
221 fclose(s);
222 fclose(d);
224 free(buf);
226 return newfile;
227 }
229 static void parse_config_file(const char *filename,
230 libxl_domain_create_info *c_info,
231 libxl_domain_build_info *b_info,
232 libxl_device_disk **disks,
233 int *num_disks,
234 libxl_device_nic **vifs,
235 int *num_vifs,
236 libxl_device_pci **pcidevs,
237 int *num_pcidevs,
238 libxl_device_vfb **vfbs,
239 int *num_vfbs,
240 libxl_device_vkb **vkbs,
241 int *num_vkbs,
242 libxl_device_model_info *dm_info)
243 {
244 const char *buf;
245 xen_uuid_t uuid[16];
246 long l;
247 struct config_t config;
248 struct config_setting_t *vbds, *nics, *pcis, *cvfbs;
249 int pci_power_mgmt = 0;
250 int pci_msitranslate = 1;
252 config_init (&config);
254 if (!config_read_file(&config, filename)) {
255 char *newfilename;
256 config_destroy(&config);
257 newfilename = compat_config_file(filename);
258 config_init (&config);
259 if (!config_read_file(&config, newfilename)) {
260 fprintf(stderr, "Failed to parse config file %s, try removing any embedded python code\n", config_error_text(&config));
261 exit(1);
262 }
263 free(newfilename);
264 }
266 init_create_info(c_info);
268 c_info->hvm = 0;
269 if ((config_lookup_string (&config, "builder", &buf) == CONFIG_TRUE) &&
270 !strncmp(buf, "hvm", strlen(buf)))
271 c_info->hvm = 1;
273 /* hap is missing */
274 if (config_lookup_string (&config, "name", &buf) == CONFIG_TRUE)
275 c_info->name = strdup(buf);
276 else
277 c_info->name = "test";
278 xen_uuid_generate(uuid);
279 c_info->uuid = uuid;
281 init_build_info(b_info, c_info);
283 /* the following is the actual config parsing with overriding values in the structures */
284 if (config_lookup_int (&config, "vcpus", &l) == CONFIG_TRUE)
285 b_info->max_vcpus = l;
287 if (config_lookup_int (&config, "memory", &l) == CONFIG_TRUE) {
288 b_info->max_memkb = l * 1024;
289 b_info->target_memkb = b_info->max_memkb;
290 }
292 if (config_lookup_int (&config, "shadow_memory", &l) == CONFIG_TRUE)
293 b_info->shadow_memkb = l * 1024;
295 if (config_lookup_int (&config, "videoram", &l) == CONFIG_TRUE)
296 b_info->video_memkb = l * 1024;
298 if (config_lookup_string (&config, "kernel", &buf) == CONFIG_TRUE)
299 b_info->kernel = strdup(buf);
301 if (c_info->hvm == 1) {
302 if (config_lookup_int (&config, "pae", &l) == CONFIG_TRUE)
303 b_info->u.hvm.pae = l;
304 if (config_lookup_int (&config, "apic", &l) == CONFIG_TRUE)
305 b_info->u.hvm.apic = l;
306 if (config_lookup_int (&config, "acpi", &l) == CONFIG_TRUE)
307 b_info->u.hvm.acpi = l;
308 if (config_lookup_int (&config, "nx", &l) == CONFIG_TRUE)
309 b_info->u.hvm.nx = l;
310 if (config_lookup_int (&config, "viridian", &l) == CONFIG_TRUE)
311 b_info->u.hvm.viridian = l;
312 } else {
313 char *cmdline;
314 if (config_lookup_string (&config, "root", &buf) == CONFIG_TRUE) {
315 asprintf(&cmdline, "root=%s", buf);
316 b_info->u.pv.cmdline = cmdline;
317 }
318 if (config_lookup_string (&config, "ramdisk", &buf) == CONFIG_TRUE)
319 b_info->u.pv.ramdisk = strdup(buf);
320 }
322 if ((vbds = config_lookup (&config, "disk")) != NULL) {
323 *num_disks = 0;
324 *disks = NULL;
325 while ((buf = config_setting_get_string_elem (vbds, *num_disks)) != NULL) {
326 char *buf2 = strdup(buf);
327 char *p, *p2;
328 *disks = (libxl_device_disk *) realloc(*disks, sizeof (libxl_device_disk) * ((*num_disks) + 1));
329 (*disks)[*num_disks].backend_domid = 0;
330 (*disks)[*num_disks].domid = 0;
331 (*disks)[*num_disks].unpluggable = 0;
332 p = strtok(buf2, ",:");
333 while (*p == ' ')
334 p++;
335 if (!strcmp(p, "phy")) {
336 (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
337 } else if (!strcmp(p, "file")) {
338 (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
339 } else if (!strcmp(p, "tap")) {
340 p = strtok(NULL, ":");
341 if (!strcmp(p, "aio")) {
342 (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
343 } else if (!strcmp(p, "vhd")) {
344 (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
345 } else if (!strcmp(p, "qcow")) {
346 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
347 } else if (!strcmp(p, "qcow2")) {
348 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
349 }
350 }
351 p = strtok(NULL, ",");
352 while (*p == ' ')
353 p++;
354 (*disks)[*num_disks].physpath= strdup(p);
355 p = strtok(NULL, ",");
356 while (*p == ' ')
357 p++;
358 p2 = strchr(p, ':');
359 if (p2 == NULL) {
360 (*disks)[*num_disks].virtpath = strdup(p);
361 (*disks)[*num_disks].is_cdrom = 0;
362 (*disks)[*num_disks].unpluggable = 1;
363 } else {
364 *p2 = '\0';
365 (*disks)[*num_disks].virtpath = strdup(p);
366 if (!strcmp(p2 + 1, "cdrom")) {
367 (*disks)[*num_disks].is_cdrom = 1;
368 (*disks)[*num_disks].unpluggable = 1;
369 } else
370 (*disks)[*num_disks].is_cdrom = 0;
371 }
372 p = strtok(NULL, ",");
373 while (*p == ' ')
374 p++;
375 (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
376 free(buf2);
377 *num_disks = (*num_disks) + 1;
378 }
379 }
381 if ((nics = config_lookup (&config, "vif")) != NULL) {
382 *num_vifs = 0;
383 *vifs = NULL;
384 while ((buf = config_setting_get_string_elem (nics, *num_vifs)) != NULL) {
385 char *buf2 = strdup(buf);
386 char *p, *p2;
387 *vifs = (libxl_device_nic *) realloc(*vifs, sizeof (libxl_device_nic) * ((*num_vifs) + 1));
388 init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
389 p = strtok(buf2, ",");
390 if (!p)
391 goto skip;
392 do {
393 while (*p == ' ')
394 p++;
395 if ((p2 = strchr(p, '=')) == NULL)
396 break;
397 *p2 = '\0';
398 if (!strcmp(p, "model")) {
399 (*vifs)[*num_vifs].model = strdup(p2 + 1);
400 } else if (!strcmp(p, "mac")) {
401 char *p3 = p2 + 1;
402 (*vifs)[*num_vifs].smac = strdup(p3);
403 *(p3 + 2) = '\0';
404 (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
405 p3 = p3 + 3;
406 *(p3 + 2) = '\0';
407 (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
408 p3 = p3 + 3;
409 *(p3 + 2) = '\0';
410 (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
411 p3 = p3 + 3;
412 *(p3 + 2) = '\0';
413 (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
414 p3 = p3 + 3;
415 *(p3 + 2) = '\0';
416 (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
417 p3 = p3 + 3;
418 *(p3 + 2) = '\0';
419 (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
420 } else if (!strcmp(p, "bridge")) {
421 (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
422 } else if (!strcmp(p, "type")) {
423 if (!strcmp(p2 + 1, "ioemu"))
424 (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
425 else
426 (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
427 } else if (!strcmp(p, "ip")) {
428 inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
429 } else if (!strcmp(p, "script")) {
430 (*vifs)[*num_vifs].script = strdup(p2 + 1);
431 } else if (!strcmp(p, "vifname")) {
432 (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
433 } else if (!strcmp(p, "rate")) {
434 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
435 } else if (!strcmp(p, "accel")) {
436 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
437 }
438 } while ((p = strtok(NULL, ",")) != NULL);
439 skip:
440 free(buf2);
441 *num_vifs = (*num_vifs) + 1;
442 }
443 }
445 if ((cvfbs = config_lookup (&config, "vfb")) != NULL) {
446 *num_vfbs = 0;
447 *num_vkbs = 0;
448 *vfbs = NULL;
449 *vkbs = NULL;
450 while ((buf = config_setting_get_string_elem (cvfbs, *num_vfbs)) != NULL) {
451 char *buf2 = strdup(buf);
452 char *p, *p2;
453 *vfbs = (libxl_device_vfb *) realloc(*vfbs, sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
454 init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
456 *vkbs = (libxl_device_vkb *) realloc(*vkbs, sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
457 init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
459 p = strtok(buf2, ",");
460 if (!p)
461 goto skip_vfb;
462 do {
463 while (*p == ' ')
464 p++;
465 if ((p2 = strchr(p, '=')) == NULL)
466 break;
467 *p2 = '\0';
468 if (!strcmp(p, "vnc")) {
469 (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
470 } else if (!strcmp(p, "vnclisten")) {
471 (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
472 } else if (!strcmp(p, "vncdisplay")) {
473 (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
474 } else if (!strcmp(p, "vncunused")) {
475 (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
476 } else if (!strcmp(p, "keymap")) {
477 (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
478 } else if (!strcmp(p, "sdl")) {
479 (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
480 } else if (!strcmp(p, "opengl")) {
481 (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
482 } else if (!strcmp(p, "display")) {
483 (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
484 } else if (!strcmp(p, "xauthority")) {
485 (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
486 }
487 } while ((p = strtok(NULL, ",")) != NULL);
488 skip_vfb:
489 free(buf2);
490 *num_vfbs = (*num_vfbs) + 1;
491 *num_vkbs = (*num_vkbs) + 1;
492 }
493 }
495 if (config_lookup_int (&config, "pci_msitranslate", &l) == CONFIG_TRUE)
496 pci_msitranslate = l;
498 if (config_lookup_int (&config, "pci_power_mgmt", &l) == CONFIG_TRUE)
499 pci_power_mgmt = l;
501 if ((pcis = config_lookup (&config, "pci")) != NULL) {
502 *num_pcidevs = 0;
503 *pcidevs = NULL;
504 while ((buf = config_setting_get_string_elem (pcis, *num_pcidevs)) != NULL) {
505 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
506 char *buf2 = strdup(buf);
507 char *p;
508 *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof (libxl_device_pci) * ((*num_pcidevs) + 1));
509 memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
510 p = strtok(buf2, ",");
511 if (!p)
512 goto skip_pci;
513 if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, &vdevfn)) {
514 sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
515 domain = 0;
516 }
517 libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, func, vdevfn);
518 (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
519 (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
520 while ((p = strtok(NULL, ",=")) != NULL) {
521 while (*p == ' ')
522 p++;
523 if (!strcmp(p, "msitranslate")) {
524 p = strtok(NULL, ",=");
525 (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
526 } else if (!strcmp(p, "power_mgmt")) {
527 p = strtok(NULL, ",=");
528 (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
529 }
530 }
531 *num_pcidevs = (*num_pcidevs) + 1;
532 skip_pci:
533 free(buf2);
534 }
535 }
537 if (c_info->hvm == 1) {
538 /* init dm from c and b */
539 init_dm_info(dm_info, c_info, b_info);
541 /* then process config related to dm */
542 if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
543 dm_info->device_model = strdup(buf);
544 if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
545 dm_info->stdvga = l;
546 if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
547 dm_info->vnc = l;
548 if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
549 dm_info->vnclisten = strdup(buf);
550 if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
551 dm_info->vncdisplay = l;
552 if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
553 dm_info->vncunused = l;
554 if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
555 dm_info->keymap = strdup(buf);
556 if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
557 dm_info->sdl = l;
558 if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
559 dm_info->opengl = l;
560 if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
561 dm_info->nographic = l;
562 if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
563 dm_info->serial = strdup(buf);
564 if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
565 dm_info->boot = strdup(buf);
566 if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
567 dm_info->usb = l;
568 if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
569 dm_info->usbdevice = strdup(buf);
570 }
572 config_destroy(&config);
573 }
575 #define MUST( call ) ({ \
576 int must_rc = (call); \
577 if (must_rc) { \
578 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \
579 __FILE__,__LINE__, must_rc, #call); \
580 exit(-must_rc); \
581 } \
582 })
584 static void create_domain(int debug, int daemonize, const char *config_file, const char *restore_file, int paused)
585 {
586 struct libxl_ctx ctx;
587 uint32_t domid;
588 libxl_domain_create_info info1;
589 libxl_domain_build_info info2;
590 libxl_domain_build_state state;
591 libxl_device_model_info dm_info;
592 libxl_device_disk *disks = NULL;
593 libxl_device_nic *vifs = NULL;
594 libxl_device_pci *pcidevs = NULL;
595 libxl_device_vfb *vfbs = NULL;
596 libxl_device_vkb *vkbs = NULL;
597 libxl_device_console console;
598 int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
599 int i, fd;
600 int need_daemon = 1;
601 libxl_device_model_starting *dm_starting = 0;
602 libxl_waiter *w1 = NULL, *w2 = NULL;
603 memset(&dm_info, 0x00, sizeof(dm_info));
605 printf("Parsing config file %s\n", config_file);
606 parse_config_file(config_file, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
607 if (debug)
608 printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
610 start:
611 domid = 0;
613 libxl_ctx_init(&ctx);
614 libxl_ctx_set_log(&ctx, log_callback, NULL);
615 libxl_domain_make(&ctx, &info1, &domid);
617 if (!restore_file || !need_daemon) {
618 if (dm_info.saved_state) {
619 free(dm_info.saved_state);
620 dm_info.saved_state = NULL;
621 }
622 libxl_domain_build(&ctx, &info2, domid, &state);
623 } else {
624 int restore_fd;
626 restore_fd = open(restore_file, O_RDONLY);
627 libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, &dm_info);
628 close(restore_fd);
629 }
631 for (i = 0; i < num_disks; i++) {
632 disk_info_domid_fixup(disks + i, domid);
633 libxl_device_disk_add(&ctx, domid, &disks[i]);
634 }
635 for (i = 0; i < num_vifs; i++) {
636 nic_info_domid_fixup(vifs + i, domid);
637 libxl_device_nic_add(&ctx, domid, &vifs[i]);
638 }
639 if (info1.hvm) {
640 device_model_info_domid_fixup(&dm_info, domid);
641 MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
642 vifs, num_vifs, &dm_starting) );
643 } else {
644 for (i = 0; i < num_vfbs; i++) {
645 vfb_info_domid_fixup(vfbs + i, domid);
646 libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
647 vkb_info_domid_fixup(vkbs + i, domid);
648 libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
649 }
650 init_console_info(&console, 0, &state);
651 console_info_domid_fixup(&console, domid);
652 if (num_vfbs)
653 console.constype = CONSTYPE_IOEMU;
654 libxl_device_console_add(&ctx, domid, &console);
655 if (num_vfbs)
656 libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
657 }
659 if (dm_starting)
660 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
661 for (i = 0; i < num_pcidevs; i++)
662 libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
664 if (!paused)
665 libxl_domain_unpause(&ctx, domid);
667 if (!daemonize)
668 exit(0);
670 if (need_daemon) {
671 char *fullname, *name;
673 asprintf(&name, "xl-%s", info1.name);
674 libxl_create_logfile(&ctx, name, &fullname);
675 logfile = open(fullname, O_WRONLY|O_CREAT, 0644);
676 free(fullname);
677 free(name);
679 daemon(0, 0);
680 need_daemon = 0;
681 }
682 XL_LOG(&ctx, XL_LOG_DEBUG, "Waiting for domain %s (domid %d) to die", info1.name, domid);
683 w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
684 w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
685 libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
686 libxl_wait_for_domain_death(&ctx, domid, w2);
687 libxl_get_wait_fd(&ctx, &fd);
688 while (1) {
689 int ret;
690 fd_set rfds;
691 xc_dominfo_t info;
692 libxl_event event;
693 libxl_device_disk disk;
694 memset(&info, 0x00, sizeof(xc_dominfo_t));
696 FD_ZERO(&rfds);
697 FD_SET(fd, &rfds);
699 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
700 if (!ret)
701 continue;
702 libxl_get_event(&ctx, &event);
703 switch (event.type) {
704 case DOMAIN_DEATH:
705 if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info)) {
706 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
707 if (info.crashed || info.dying || (info.shutdown && (info.shutdown_reason != SHUTDOWN_suspend))) {
708 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be clean: destroying the domain", domid);
709 libxl_domain_destroy(&ctx, domid, 0);
710 if (info.shutdown && (info.shutdown_reason == SHUTDOWN_reboot)) {
711 libxl_free_waiter(w1);
712 libxl_free_waiter(w2);
713 free(w1);
714 free(w2);
715 libxl_ctx_free(&ctx);
716 XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
717 goto start;
718 }
719 XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
720 }
721 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be clean, exiting now", domid);
722 exit(0);
723 }
724 break;
725 case DISK_EJECT:
726 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
727 libxl_cdrom_insert(&ctx, domid, &disk);
728 break;
729 }
730 libxl_free_event(&event);
731 }
733 close(logfile);
734 for (i = 0; i < num_vifs; i++) {
735 free(vifs[i].smac);
736 free(vifs[i].ifname);
737 }
738 free(disks);
739 free(vifs);
740 free(vfbs);
741 free(vkbs);
742 free(pcidevs);
743 }
745 static void help(char *command)
746 {
747 if (!command || !strcmp(command, "help")) {
748 printf("Usage xl <subcommand> [args]\n\n");
749 printf("xl full list of subcommands:\n\n");
750 printf(" create create a domain from config file <filename>\n\n");
751 printf(" list list information about all domains\n\n");
752 printf(" destroy terminate a domain immediately\n\n");
753 printf(" pci-attach insert a new pass-through pci device\n\n");
754 printf(" pci-detach remove a domain's pass-through pci device\n\n");
755 printf(" pci-list list pass-through pci devices for a domain\n\n");
756 printf(" pause pause execution of a domain\n\n");
757 printf(" unpause unpause a paused domain\n\n");
758 printf(" console attach to domain's console\n\n");
759 printf(" save save a domain state to restore later\n\n");
760 printf(" restore restore a domain from a saved state\n\n");
761 printf(" cd-insert insert a cdrom into a guest's cd drive\n\n");
762 printf(" cd-eject eject a cdrom from a guest's cd drive\n\n");
763 printf(" mem-set set the current memory usage for a domain\n\n");
764 } else if(!strcmp(command, "create")) {
765 printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
766 printf("Create a domain based on <ConfigFile>.\n\n");
767 printf("Options:\n\n");
768 printf("-h Print this help.\n");
769 printf("-d Enable debug messages.\n");
770 printf("-e Do not wait in the background for the death of the domain.\n");
771 } else if(!strcmp(command, "list")) {
772 printf("Usage: xl list [Domain]\n\n");
773 printf("List information about all/some domains.\n\n");
774 } else if(!strcmp(command, "pci-attach")) {
775 printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
776 printf("Insert a new pass-through pci device.\n\n");
777 } else if(!strcmp(command, "pci-detach")) {
778 printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
779 printf("Remove a domain's pass-through pci device.\n\n");
780 } else if(!strcmp(command, "pci-list")) {
781 printf("Usage: xl pci-list <Domain>\n\n");
782 printf("List pass-through pci devices for a domain.\n\n");
783 } else if(!strcmp(command, "pause")) {
784 printf("Usage: xl pause <Domain>\n\n");
785 printf("Pause execution of a domain.\n\n");
786 } else if(!strcmp(command, "unpause")) {
787 printf("Usage: xl unpause <Domain>\n\n");
788 printf("Unpause a paused domain.\n\n");
789 } else if(!strcmp(command, "save")) {
790 printf("Usage: xl save [options] <Domain> <CheckpointFile>\n\n");
791 printf("Save a domain state to restore later.\n\n");
792 printf("Options:\n\n");
793 printf("-h Print this help.\n");
794 printf("-c Leave domain running after creating the snapshot.\n");
795 } else if(!strcmp(command, "restore")) {
796 printf("Usage: xl restore [options] <ConfigFile> <CheckpointFile>\n\n");
797 printf("Restore a domain from a saved state.\n\n");
798 printf("Options:\n\n");
799 printf("-h Print this help.\n");
800 printf("-p Do not unpause domain after restoring it.\n");
801 printf("-e Do not wait in the background for the death of the domain.\n");
802 } else if(!strcmp(command, "destroy")) {
803 printf("Usage: xl destroy <Domain>\n\n");
804 printf("Terminate a domain immediately.\n\n");
805 } else if (!strcmp(command, "console")) {
806 printf("Usage: xl console <Domain>\n\n");
807 printf("Attach to domain's console.\n\n");
808 } else if (!strcmp(command, "cd-insert")) {
809 printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
810 printf("Insert a cdrom into a guest's cd drive.\n\n");
811 } else if (!strcmp(command, "cd-eject")) {
812 printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
813 printf("Eject a cdrom from a guest's cd drive.\n\n");
814 } else if (!strcmp(command, "mem-set")) {
815 printf("Usage: xl mem-set <Domain> <MemKB>\n\n");
816 printf("Set the current memory usage for a domain.\n\n");
817 }
818 }
820 void set_memory_target(char *p, char *mem)
821 {
822 struct libxl_ctx ctx;
823 uint32_t domid;
825 libxl_ctx_init(&ctx);
826 libxl_ctx_set_log(&ctx, log_callback, NULL);
828 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
829 fprintf(stderr, "%s is an invalid domain identifier\n", p);
830 exit(2);
831 }
832 libxl_set_memory_target(&ctx, domid, atoi(mem));
833 }
835 int main_memset(int argc, char **argv)
836 {
837 int opt = 0;
838 char *p = NULL, *mem;
840 while ((opt = getopt(argc, argv, "h:")) != -1) {
841 switch (opt) {
842 case 'h':
843 help("mem-set");
844 exit(0);
845 default:
846 fprintf(stderr, "option not supported\n");
847 break;
848 }
849 }
850 if (optind >= argc - 1) {
851 help("mem-set");
852 exit(2);
853 }
855 p = argv[optind];
856 mem = argv[optind + 1];
858 set_memory_target(p, mem);
859 exit(0);
860 }
862 void console(char *p, int cons_num)
863 {
864 struct libxl_ctx ctx;
865 uint32_t domid;
867 libxl_ctx_init(&ctx);
868 libxl_ctx_set_log(&ctx, log_callback, NULL);
870 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
871 fprintf(stderr, "%s is an invalid domain identifier\n", p);
872 exit(2);
873 }
874 libxl_console_attach(&ctx, domid, cons_num);
875 }
877 void cd_insert(char *dom, char *virtdev, char *phys)
878 {
879 struct libxl_ctx ctx;
880 uint32_t domid;
881 libxl_device_disk disk;
882 char *p;
884 libxl_ctx_init(&ctx);
885 libxl_ctx_set_log(&ctx, log_callback, NULL);
887 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
888 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
889 exit(2);
890 }
892 disk.backend_domid = 0;
893 disk.domid = domid;
894 if (phys) {
895 p = strchr(phys, ':');
896 if (!p) {
897 fprintf(stderr, "No type specified, ");
898 disk.physpath = phys;
899 if (!strncmp(phys, "/dev", 4)) {
900 fprintf(stderr, "assuming phy:\n");
901 disk.phystype = PHYSTYPE_PHY;
902 } else {
903 fprintf(stderr, "assuming file:\n");
904 disk.phystype = PHYSTYPE_FILE;
905 }
906 } else {
907 p = '\0';
908 disk.physpath = strdup(p);
909 p++;
910 libxl_string_to_phystype(&ctx, p, &disk.phystype);
911 }
912 } else {
913 disk.physpath = NULL;
914 disk.phystype = 0;
915 }
916 disk.virtpath = virtdev;
917 disk.unpluggable = 1;
918 disk.readwrite = 0;
919 disk.is_cdrom = 1;
921 libxl_cdrom_insert(&ctx, domid, &disk);
922 }
924 int main_cd_eject(int argc, char **argv)
925 {
926 int opt = 0;
927 char *p = NULL, *virtdev;
929 while ((opt = getopt(argc, argv, "hn:")) != -1) {
930 switch (opt) {
931 case 'h':
932 help("cd-eject");
933 exit(0);
934 default:
935 fprintf(stderr, "option not supported\n");
936 break;
937 }
938 }
939 if (optind >= argc - 1) {
940 help("cd-eject");
941 exit(2);
942 }
944 p = argv[optind];
945 virtdev = argv[optind + 1];
947 cd_insert(p, virtdev, NULL);
948 exit(0);
949 }
951 int main_cd_insert(int argc, char **argv)
952 {
953 int opt = 0;
954 char *p = NULL, *file = NULL, *virtdev;
956 while ((opt = getopt(argc, argv, "hn:")) != -1) {
957 switch (opt) {
958 case 'h':
959 help("cd-insert");
960 exit(0);
961 default:
962 fprintf(stderr, "option not supported\n");
963 break;
964 }
965 }
966 if (optind >= argc - 2) {
967 help("cd-insert");
968 exit(2);
969 }
971 p = argv[optind];
972 virtdev = argv[optind + 1];
973 file = argv[optind + 2];
975 cd_insert(p, virtdev, file);
976 exit(0);
977 }
979 int main_console(int argc, char **argv)
980 {
981 int opt = 0, cons_num = 0;
982 char *p = NULL;
984 while ((opt = getopt(argc, argv, "hn:")) != -1) {
985 switch (opt) {
986 case 'h':
987 help("console");
988 exit(0);
989 case 'n':
990 if (optarg) {
991 cons_num = strtol(optarg, NULL, 10);
992 }
993 break;
994 default:
995 fprintf(stderr, "option not supported\n");
996 break;
997 }
998 }
999 if (optind >= argc) {
1000 help("console");
1001 exit(2);
1004 p = argv[optind];
1006 console(p, cons_num);
1007 exit(0);
1010 void pcilist(char *dom)
1012 struct libxl_ctx ctx;
1013 uint32_t domid;
1014 libxl_device_pci *pcidevs;
1015 int num, i;
1017 libxl_ctx_init(&ctx);
1018 libxl_ctx_set_log(&ctx, log_callback, NULL);
1020 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
1021 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1022 exit(2);
1024 pcidevs = libxl_device_pci_list(&ctx, domid, &num);
1025 if (!num)
1026 return;
1027 printf("VFn domain bus slot func\n");
1028 for (i = 0; i < num; i++) {
1029 printf("0x%02x 0x%04x 0x%02x 0x%02x 0x%01x\n", pcidevs[i].vdevfn, pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
1031 free(pcidevs);
1034 int main_pcilist(int argc, char **argv)
1036 int opt;
1037 char *domname = NULL;
1039 while ((opt = getopt(argc, argv, "h")) != -1) {
1040 switch (opt) {
1041 case 'h':
1042 help("pci-list");
1043 exit(0);
1044 default:
1045 fprintf(stderr, "option not supported\n");
1046 break;
1049 if (optind >= argc) {
1050 help("pci-list");
1051 exit(2);
1054 domname = argv[optind];
1056 pcilist(domname);
1057 exit(0);
1060 void pcidetach(char *dom, char *bdf)
1062 struct libxl_ctx ctx;
1063 uint32_t domid;
1064 libxl_device_pci pcidev;
1065 unsigned int domain, bus, dev, func;
1067 libxl_ctx_init(&ctx);
1068 libxl_ctx_set_log(&ctx, log_callback, NULL);
1070 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
1071 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1072 exit(2);
1074 memset(&pcidev, 0x00, sizeof(pcidev));
1075 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1076 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1077 libxl_device_pci_remove(&ctx, domid, &pcidev);
1080 int main_pcidetach(int argc, char **argv)
1082 int opt;
1083 char *domname = NULL, *bdf = NULL;
1085 while ((opt = getopt(argc, argv, "h")) != -1) {
1086 switch (opt) {
1087 case 'h':
1088 help("pci-attach");
1089 exit(0);
1090 default:
1091 fprintf(stderr, "option not supported\n");
1092 break;
1095 if (optind >= argc - 1) {
1096 help("pci-detach");
1097 exit(2);
1100 domname = argv[optind];
1101 bdf = argv[optind + 1];
1103 pcidetach(domname, bdf);
1104 exit(0);
1106 void pciattach(char *dom, char *bdf, char *vs)
1108 struct libxl_ctx ctx;
1109 uint32_t domid;
1110 libxl_device_pci pcidev;
1111 unsigned int domain, bus, dev, func;
1113 libxl_ctx_init(&ctx);
1114 libxl_ctx_set_log(&ctx, log_callback, NULL);
1116 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
1117 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1118 exit(2);
1120 memset(&pcidev, 0x00, sizeof(pcidev));
1121 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1122 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1123 libxl_device_pci_add(&ctx, domid, &pcidev);
1126 int main_pciattach(int argc, char **argv)
1128 int opt;
1129 char *domname = NULL, *bdf = NULL, *vs = NULL;
1131 while ((opt = getopt(argc, argv, "h")) != -1) {
1132 switch (opt) {
1133 case 'h':
1134 help("pci-attach");
1135 exit(0);
1136 default:
1137 fprintf(stderr, "option not supported\n");
1138 break;
1141 if (optind >= argc - 1) {
1142 help("pci-attach");
1143 exit(2);
1146 domname = argv[optind];
1147 bdf = argv[optind + 1];
1149 if (optind + 1 < argc)
1150 vs = argv[optind + 2];
1152 pciattach(domname, bdf, vs);
1153 exit(0);
1156 void pause_domain(char *p)
1158 struct libxl_ctx ctx;
1159 uint32_t domid;
1161 libxl_ctx_init(&ctx);
1162 libxl_ctx_set_log(&ctx, log_callback, NULL);
1164 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1165 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1166 exit(2);
1168 libxl_domain_pause(&ctx, domid);
1171 void unpause_domain(char *p)
1173 struct libxl_ctx ctx;
1174 uint32_t domid;
1176 libxl_ctx_init(&ctx);
1177 libxl_ctx_set_log(&ctx, log_callback, NULL);
1179 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1180 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1181 exit(2);
1183 libxl_domain_unpause(&ctx, domid);
1186 void destroy_domain(char *p)
1188 struct libxl_ctx ctx;
1189 uint32_t domid;
1191 libxl_ctx_init(&ctx);
1192 libxl_ctx_set_log(&ctx, log_callback, NULL);
1194 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1195 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1196 exit(2);
1198 libxl_domain_destroy(&ctx, domid, 0);
1201 void list_domains(void)
1203 struct libxl_ctx ctx;
1204 xc_dominfo_t *info;
1205 int nb_domain, i;
1207 libxl_ctx_init(&ctx);
1208 libxl_ctx_set_log(&ctx, log_callback, NULL);
1210 info = libxl_domain_infolist(&ctx, &nb_domain);
1212 if (info < 0) {
1213 fprintf(stderr, "libxl_domain_infolist failed.\n");
1214 exit(1);
1216 printf("Name ID Mem VCPUs\tState\tTime(s)\n");
1217 for (i = 0; i < nb_domain; i++) {
1218 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f\n",
1219 libxl_domid_to_name(&ctx, info[i].domid),
1220 info[i].domid,
1221 info[i].nr_pages * XC_PAGE_SIZE/(1024*1024),
1222 info[i].nr_online_vcpus,
1223 info[i].running ? 'r' : '-',
1224 info[i].blocked ? 'b' : '-',
1225 info[i].paused ? 'p' : '-',
1226 info[i].shutdown ? 's' : '-',
1227 info[i].crashed ? 'c' : '-',
1228 info[i].dying ? 'd' : '-',
1229 ((float)info[i].cpu_time / 1e9));
1231 free(info);
1234 int save_domain(char *p, char *filename, int checkpoint)
1236 struct libxl_ctx ctx;
1237 uint32_t domid;
1238 int fd;
1240 libxl_ctx_init(&ctx);
1241 libxl_ctx_set_log(&ctx, log_callback, NULL);
1243 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1244 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1245 exit(2);
1247 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1248 if (fd < 0) {
1249 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
1250 exit(2);
1252 libxl_domain_suspend(&ctx, NULL, domid, fd);
1253 close(fd);
1255 if (checkpoint)
1256 libxl_domain_unpause(&ctx, domid);
1257 else
1258 libxl_domain_destroy(&ctx, domid, 0);
1260 exit(0);
1263 int main_restore(int argc, char **argv)
1265 char *checkpoint_file = NULL;
1266 char *config_file = NULL;
1267 int paused = 0, debug = 0, daemonize = 1;
1268 int opt;
1270 while ((opt = getopt(argc, argv, "hpde")) != -1) {
1271 switch (opt) {
1272 case 'p':
1273 paused = 1;
1274 break;
1275 case 'd':
1276 debug = 1;
1277 break;
1278 case 'e':
1279 daemonize = 0;
1280 break;
1281 case 'h':
1282 help("restore");
1283 exit(0);
1284 default:
1285 fprintf(stderr, "option not supported\n");
1286 break;
1290 if (optind >= argc - 1) {
1291 help("restore");
1292 exit(2);
1295 config_file = argv[optind];
1296 checkpoint_file = argv[optind + 1];
1297 create_domain(debug, daemonize, config_file, checkpoint_file, paused);
1298 exit(0);
1301 int main_save(int argc, char **argv)
1303 char *filename = NULL, *p = NULL;
1304 int checkpoint = 0;
1305 int opt;
1307 while ((opt = getopt(argc, argv, "hc")) != -1) {
1308 switch (opt) {
1309 case 'c':
1310 checkpoint = 1;
1311 break;
1312 case 'h':
1313 help("save");
1314 exit(0);
1315 default:
1316 fprintf(stderr, "option not supported\n");
1317 break;
1321 if (optind >= argc - 1) {
1322 help("save");
1323 exit(2);
1326 p = argv[optind];
1327 filename = argv[optind + 1];
1328 save_domain(p, filename, checkpoint);
1329 exit(0);
1332 int main_pause(int argc, char **argv)
1334 int opt;
1335 char *p;
1338 while ((opt = getopt(argc, argv, "h")) != -1) {
1339 switch (opt) {
1340 case 'h':
1341 help("pause");
1342 exit(0);
1343 default:
1344 fprintf(stderr, "option not supported\n");
1345 break;
1348 if (optind >= argc) {
1349 help("pause");
1350 exit(2);
1353 p = argv[optind];
1355 pause_domain(p);
1356 exit(0);
1359 int main_unpause(int argc, char **argv)
1361 int opt;
1362 char *p;
1365 while ((opt = getopt(argc, argv, "h")) != -1) {
1366 switch (opt) {
1367 case 'h':
1368 help("unpause");
1369 exit(0);
1370 default:
1371 fprintf(stderr, "option not supported\n");
1372 break;
1375 if (optind >= argc) {
1376 help("unpause");
1377 exit(2);
1380 p = argv[optind];
1382 unpause_domain(p);
1383 exit(0);
1386 int main_destroy(int argc, char **argv)
1388 int opt;
1389 char *p;
1391 while ((opt = getopt(argc, argv, "h")) != -1) {
1392 switch (opt) {
1393 case 'h':
1394 help("destroy");
1395 exit(0);
1396 default:
1397 fprintf(stderr, "option not supported\n");
1398 break;
1401 if (optind >= argc) {
1402 help("destroy");
1403 exit(2);
1406 p = argv[optind];
1408 destroy_domain(p);
1409 exit(0);
1412 int main_list(int argc, char **argv)
1414 int opt;
1416 while ((opt = getopt(argc, argv, "h")) != -1) {
1417 switch (opt) {
1418 case 'h':
1419 help("list");
1420 exit(0);
1421 default:
1422 fprintf(stderr, "option not supported\n");
1423 break;
1427 list_domains();
1428 exit(0);
1431 int main_create(int argc, char **argv)
1433 char *filename = NULL;
1434 int debug = 0, daemonize = 1;
1435 int opt;
1437 while ((opt = getopt(argc, argv, "hde")) != -1) {
1438 switch (opt) {
1439 case 'd':
1440 debug = 1;
1441 break;
1442 case 'e':
1443 daemonize = 0;
1444 break;
1445 case 'h':
1446 help("create");
1447 exit(0);
1448 default:
1449 fprintf(stderr, "option not supported\n");
1450 break;
1454 if (optind >= argc) {
1455 help("create");
1456 exit(2);
1459 filename = argv[optind];
1460 create_domain(debug, daemonize, filename, NULL, 0);
1461 exit(0);
1464 int main(int argc, char **argv)
1466 if (argc < 2) {
1467 help(NULL);
1468 exit(1);
1471 if (!strcmp(argv[1], "create")) {
1472 main_create(argc - 1, argv + 1);
1473 } else if (!strcmp(argv[1], "list")) {
1474 main_list(argc - 1, argv + 1);
1475 } else if (!strcmp(argv[1], "destroy")) {
1476 main_destroy(argc - 1, argv + 1);
1477 } else if (!strcmp(argv[1], "pci-attach")) {
1478 main_pciattach(argc - 1, argv + 1);
1479 } else if (!strcmp(argv[1], "pci-detach")) {
1480 main_pcidetach(argc - 1, argv + 1);
1481 } else if (!strcmp(argv[1], "pci-list")) {
1482 main_pcilist(argc - 1, argv + 1);
1483 } else if (!strcmp(argv[1], "pause")) {
1484 main_pause(argc - 1, argv + 1);
1485 } else if (!strcmp(argv[1], "unpause")) {
1486 main_unpause(argc - 1, argv + 1);
1487 } else if (!strcmp(argv[1], "console")) {
1488 main_console(argc - 1, argv + 1);
1489 } else if (!strcmp(argv[1], "save")) {
1490 main_save(argc - 1, argv + 1);
1491 } else if (!strcmp(argv[1], "restore")) {
1492 main_restore(argc - 1, argv + 1);
1493 } else if (!strcmp(argv[1], "cd-insert")) {
1494 main_cd_insert(argc - 1, argv + 1);
1495 } else if (!strcmp(argv[1], "cd-eject")) {
1496 main_cd_eject(argc - 1, argv + 1);
1497 } else if (!strcmp(argv[1], "mem-set")) {
1498 main_memset(argc - 1, argv + 1);
1499 } else if (!strcmp(argv[1], "help")) {
1500 if (argc > 2)
1501 help(argv[2]);
1502 else
1503 help(NULL);
1504 exit(0);
1505 } else {
1506 fprintf(stderr, "command not implemented\n");
1507 exit(1);