debuggers.hg

view tools/libxl/xl.c @ 20656:b2ccd48f2f9b

libxenlight: fix cd-insert cli arguments parsing

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Dec 11 08:47:51 2009 +0000 (2009-12-11)
parents 8fbc74d40739
children 1604ad5c529f
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 p++;
909 disk.physpath = p;
910 libxl_string_to_phystype(&ctx, phys, &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);