debuggers.hg

view tools/libxl/xl.c @ 20637:91555131e235

libxenlight: implement cdrom insert/eject

This patch implements functions in libxenlight to change the cdrom in
a VM at run time and to handle cdrom eject requests from guests.

This patch adds two new commands to xl: cd-insert and cd-eject; it
also modifies xl to handle cdrom eject requests coming from guests
(actually coming from qemu).

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Dec 08 07:47:52 2009 +0000 (2009-12-08)
parents 093cd0e7d537
children 2c6a04fdf8fb
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("kernel: %s\n", b_info->kernel);
89 printf("hvm: %d\n", b_info->hvm);
91 if (c_info->hvm) {
92 printf("video_memkb: %d\n", b_info->video_memkb);
93 printf("shadow_memkb: %d\n", b_info->shadow_memkb);
94 printf(" pae: %d\n", b_info->u.hvm.pae);
95 printf(" apic: %d\n", b_info->u.hvm.apic);
96 printf(" acpi: %d\n", b_info->u.hvm.acpi);
97 printf(" nx: %d\n", b_info->u.hvm.nx);
98 printf(" viridian: %d\n", b_info->u.hvm.viridian);
99 } else {
100 printf("cmdline: %s\n", b_info->u.pv.cmdline);
101 printf("ramdisk: %s\n", b_info->u.pv.ramdisk);
102 }
104 for (i = 0; i < num_disks; i++) {
105 printf("\n\n\n*** disks_info: %d ***\n", i);
106 printf("backend_domid %d\n", disks[i].backend_domid);
107 printf("domid %d\n", disks[i].domid);
108 printf("physpath %s\n", disks[i].physpath);
109 printf("phystype %d\n", disks[i].phystype);
110 printf("virtpath %s\n", disks[i].virtpath);
111 printf("unpluggable %d\n", disks[i].unpluggable);
112 printf("readwrite %d\n", disks[i].readwrite);
113 printf("is_cdrom %d\n", disks[i].is_cdrom);
114 }
116 for (i = 0; i < num_vifs; i++) {
117 printf("\n\n\n*** vifs_info: %d ***\n", i);
118 printf("backend_domid %d\n", vifs[i].backend_domid);
119 printf("domid %d\n", vifs[i].domid);
120 printf("devid %d\n", vifs[i].devid);
121 printf("mtu %d\n", vifs[i].mtu);
122 printf("model %s\n", vifs[i].model);
123 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]);
124 printf("smac %s\n", vifs[i].mac);
125 }
127 for (i = 0; i < num_pcidevs; i++) {
128 printf("\n\n\n*** pcidevs_info: %d ***\n", i);
129 printf("pci dev "PCI_BDF_VDEVFN"\n", pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func, pcidevs[i].vdevfn);
130 printf("opts msitranslate %d power_mgmt %d\n", pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
131 }
133 for (i = 0; i < num_vfbs; i++) {
134 printf("\n\n\n*** vfbs_info: %d ***\n", i);
135 printf("backend_domid %d\n", vfbs[i].backend_domid);
136 printf("domid %d\n", vfbs[i].domid);
137 printf("devid %d\n", vfbs[i].devid);
138 printf("vnc: %d\n", vfbs[i].vnc);
139 printf("vnclisten: %s\n", vfbs[i].vnclisten);
140 printf("vncdisplay: %d\n", vfbs[i].vncdisplay);
141 printf("vncunused: %d\n", vfbs[i].vncunused);
142 printf("keymap: %s\n", vfbs[i].keymap);
143 printf("sdl: %d\n", vfbs[i].sdl);
144 printf("opengl: %d\n", vfbs[i].opengl);
145 printf("display: %s\n", vfbs[i].display);
146 printf("xauthority: %s\n", vfbs[i].xauthority);
147 }
149 if (c_info->hvm) {
150 printf("\n\n\n*** device_model_info ***\n");
151 printf("domid: %d\n", dm_info->domid);
152 printf("dom_name: %s\n", dm_info->dom_name);
153 printf("device_model: %s\n", dm_info->device_model);
154 printf("videoram: %d\n", dm_info->videoram);
155 printf("stdvga: %d\n", dm_info->stdvga);
156 printf("vnc: %d\n", dm_info->vnc);
157 printf("vnclisten: %s\n", dm_info->vnclisten);
158 printf("vncdisplay: %d\n", dm_info->vncdisplay);
159 printf("vncunused: %d\n", dm_info->vncunused);
160 printf("keymap: %s\n", dm_info->keymap);
161 printf("sdl: %d\n", dm_info->sdl);
162 printf("opengl: %d\n", dm_info->opengl);
163 printf("nographic: %d\n", dm_info->nographic);
164 printf("serial: %s\n", dm_info->serial);
165 printf("boot: %s\n", dm_info->boot);
166 printf("usb: %d\n", dm_info->usb);
167 printf("usbdevice: %s\n", dm_info->usbdevice);
168 printf("apic: %d\n", dm_info->apic);
169 }
170 }
172 static char* compat_config_file(const char *filename)
173 {
174 char t;
175 char *newfile = (char*) malloc(strlen(filename) + 4);
176 char *buf = (char *) malloc(2048);
177 int size = 2048, i;
178 FILE *s;
179 FILE *d;
181 sprintf(newfile, "%s.xl", filename);
183 s = fopen(filename, "r");
184 if (!s) {
185 perror("cannot open file for reading");
186 return NULL;
187 }
188 d = fopen(newfile, "w");
189 if (!d) {
190 fclose(s);
191 perror("cannot open file for writting");
192 return NULL;
193 }
195 while (!feof(s)) {
196 fgets(buf, size, s);
197 while (buf[strlen(buf) - 1] != '\n' && !feof(s)) {
198 size += 1024;
199 buf = realloc(buf, size + 1024);
200 fgets(buf + (size - 1025), 1025, s);
201 }
202 for (i = 0; i < strlen(buf); i++)
203 if (buf[i] == '\'')
204 buf[i] = '\"';
205 if (strchr(buf, '=') != NULL) {
206 if ((buf[strlen(buf) - 1] == '\n' && buf[strlen(buf) - 2] == ';') ||
207 buf[strlen(buf) - 1] == ';') {
208 fputs(buf, d);
209 } else {
210 t = buf[strlen(buf) - 1];
211 buf[strlen(buf) - 1] = ';';
212 fputs(buf, d);
213 fputc(t, d);
214 }
215 } else if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') {
216 fputs(buf, d);
217 }
218 }
220 fclose(s);
221 fclose(d);
223 free(buf);
225 return newfile;
226 }
228 static void parse_config_file(const char *filename,
229 libxl_domain_create_info *c_info,
230 libxl_domain_build_info *b_info,
231 libxl_device_disk **disks,
232 int *num_disks,
233 libxl_device_nic **vifs,
234 int *num_vifs,
235 libxl_device_pci **pcidevs,
236 int *num_pcidevs,
237 libxl_device_vfb **vfbs,
238 int *num_vfbs,
239 libxl_device_vkb **vkbs,
240 int *num_vkbs,
241 libxl_device_model_info *dm_info)
242 {
243 const char *buf;
244 xen_uuid_t uuid[16];
245 long l;
246 struct config_t config;
247 struct config_setting_t *vbds, *nics, *pcis, *cvfbs;
248 int pci_power_mgmt = 0;
249 int pci_msitranslate = 1;
251 config_init (&config);
253 if (!config_read_file(&config, filename)) {
254 char *newfilename;
255 config_destroy(&config);
256 newfilename = compat_config_file(filename);
257 config_init (&config);
258 if (!config_read_file(&config, newfilename)) {
259 fprintf(stderr, "Failed to parse config file %s, try removing any embedded python code\n", config_error_text(&config));
260 exit(1);
261 }
262 free(newfilename);
263 }
265 init_create_info(c_info);
267 c_info->hvm = 0;
268 if ((config_lookup_string (&config, "builder", &buf) == CONFIG_TRUE) &&
269 !strncmp(buf, "hvm", strlen(buf)))
270 c_info->hvm = 1;
272 /* hap is missing */
273 if (config_lookup_string (&config, "name", &buf) == CONFIG_TRUE)
274 c_info->name = strdup(buf);
275 else
276 c_info->name = "test";
277 xen_uuid_generate(uuid);
278 c_info->uuid = uuid;
280 init_build_info(b_info, c_info);
282 /* the following is the actual config parsing with overriding values in the structures */
283 if (config_lookup_int (&config, "vcpus", &l) == CONFIG_TRUE)
284 b_info->max_vcpus = l;
286 if (config_lookup_int (&config, "memory", &l) == CONFIG_TRUE)
287 b_info->max_memkb = l * 1024;
289 if (config_lookup_int (&config, "shadow_memory", &l) == CONFIG_TRUE)
290 b_info->shadow_memkb = l * 1024;
292 if (config_lookup_int (&config, "videoram", &l) == CONFIG_TRUE)
293 b_info->video_memkb = l * 1024;
295 if (config_lookup_string (&config, "kernel", &buf) == CONFIG_TRUE)
296 b_info->kernel = strdup(buf);
298 if (c_info->hvm == 1) {
299 if (config_lookup_int (&config, "pae", &l) == CONFIG_TRUE)
300 b_info->u.hvm.pae = l;
301 if (config_lookup_int (&config, "apic", &l) == CONFIG_TRUE)
302 b_info->u.hvm.apic = l;
303 if (config_lookup_int (&config, "acpi", &l) == CONFIG_TRUE)
304 b_info->u.hvm.acpi = l;
305 if (config_lookup_int (&config, "nx", &l) == CONFIG_TRUE)
306 b_info->u.hvm.nx = l;
307 if (config_lookup_int (&config, "viridian", &l) == CONFIG_TRUE)
308 b_info->u.hvm.viridian = l;
309 } else {
310 char *cmdline;
311 if (config_lookup_string (&config, "root", &buf) == CONFIG_TRUE) {
312 asprintf(&cmdline, "root=%s", buf);
313 b_info->u.pv.cmdline = cmdline;
314 }
315 if (config_lookup_string (&config, "ramdisk", &buf) == CONFIG_TRUE)
316 b_info->u.pv.ramdisk = strdup(buf);
317 }
319 if ((vbds = config_lookup (&config, "disk")) != NULL) {
320 *num_disks = 0;
321 *disks = NULL;
322 while ((buf = config_setting_get_string_elem (vbds, *num_disks)) != NULL) {
323 char *buf2 = strdup(buf);
324 char *p, *p2;
325 *disks = (libxl_device_disk *) realloc(*disks, sizeof (libxl_device_disk) * ((*num_disks) + 1));
326 (*disks)[*num_disks].backend_domid = 0;
327 (*disks)[*num_disks].domid = 0;
328 (*disks)[*num_disks].unpluggable = 0;
329 p = strtok(buf2, ",:");
330 while (*p == ' ')
331 p++;
332 if (!strcmp(p, "phy")) {
333 (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
334 } else if (!strcmp(p, "file")) {
335 (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
336 } else if (!strcmp(p, "tap")) {
337 p = strtok(NULL, ":");
338 if (!strcmp(p, "aio")) {
339 (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
340 } else if (!strcmp(p, "vhd")) {
341 (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
342 } else if (!strcmp(p, "qcow")) {
343 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
344 } else if (!strcmp(p, "qcow2")) {
345 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
346 }
347 }
348 p = strtok(NULL, ",");
349 while (*p == ' ')
350 p++;
351 (*disks)[*num_disks].physpath= strdup(p);
352 p = strtok(NULL, ",");
353 while (*p == ' ')
354 p++;
355 p2 = strchr(p, ':');
356 if (p2 == NULL) {
357 (*disks)[*num_disks].virtpath = strdup(p);
358 (*disks)[*num_disks].is_cdrom = 0;
359 (*disks)[*num_disks].unpluggable = 1;
360 } else {
361 *p2 = '\0';
362 (*disks)[*num_disks].virtpath = strdup(p);
363 if (!strcmp(p2 + 1, "cdrom")) {
364 (*disks)[*num_disks].is_cdrom = 1;
365 (*disks)[*num_disks].unpluggable = 1;
366 } else
367 (*disks)[*num_disks].is_cdrom = 0;
368 }
369 p = strtok(NULL, ",");
370 while (*p == ' ')
371 p++;
372 (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
373 free(buf2);
374 *num_disks = (*num_disks) + 1;
375 }
376 }
378 if ((nics = config_lookup (&config, "vif")) != NULL) {
379 *num_vifs = 0;
380 *vifs = NULL;
381 while ((buf = config_setting_get_string_elem (nics, *num_vifs)) != NULL) {
382 char *buf2 = strdup(buf);
383 char *p, *p2;
384 *vifs = (libxl_device_nic *) realloc(*vifs, sizeof (libxl_device_nic) * ((*num_vifs) + 1));
385 init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
386 p = strtok(buf2, ",");
387 if (!p)
388 goto skip;
389 do {
390 while (*p == ' ')
391 p++;
392 if ((p2 = strchr(p, '=')) == NULL)
393 break;
394 *p2 = '\0';
395 if (!strcmp(p, "model")) {
396 (*vifs)[*num_vifs].model = strdup(p2 + 1);
397 } else if (!strcmp(p, "mac")) {
398 char *p3 = p2 + 1;
399 (*vifs)[*num_vifs].smac = strdup(p3);
400 *(p3 + 2) = '\0';
401 (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
402 p3 = p3 + 3;
403 *(p3 + 2) = '\0';
404 (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
405 p3 = p3 + 3;
406 *(p3 + 2) = '\0';
407 (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
408 p3 = p3 + 3;
409 *(p3 + 2) = '\0';
410 (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
411 p3 = p3 + 3;
412 *(p3 + 2) = '\0';
413 (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
414 p3 = p3 + 3;
415 *(p3 + 2) = '\0';
416 (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
417 } else if (!strcmp(p, "bridge")) {
418 (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
419 } else if (!strcmp(p, "type")) {
420 if (!strcmp(p2 + 1, "ioemu"))
421 (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
422 else
423 (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
424 } else if (!strcmp(p, "ip")) {
425 inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
426 } else if (!strcmp(p, "script")) {
427 (*vifs)[*num_vifs].script = strdup(p2 + 1);
428 } else if (!strcmp(p, "vifname")) {
429 (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
430 } else if (!strcmp(p, "rate")) {
431 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
432 } else if (!strcmp(p, "accel")) {
433 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
434 }
435 } while ((p = strtok(NULL, ",")) != NULL);
436 skip:
437 free(buf2);
438 *num_vifs = (*num_vifs) + 1;
439 }
440 }
442 if ((cvfbs = config_lookup (&config, "vfb")) != NULL) {
443 *num_vfbs = 0;
444 *num_vkbs = 0;
445 *vfbs = NULL;
446 *vkbs = NULL;
447 while ((buf = config_setting_get_string_elem (cvfbs, *num_vfbs)) != NULL) {
448 char *buf2 = strdup(buf);
449 char *p, *p2;
450 *vfbs = (libxl_device_vfb *) realloc(*vfbs, sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
451 init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
453 *vkbs = (libxl_device_vkb *) realloc(*vkbs, sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
454 init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
456 p = strtok(buf2, ",");
457 if (!p)
458 goto skip_vfb;
459 do {
460 while (*p == ' ')
461 p++;
462 if ((p2 = strchr(p, '=')) == NULL)
463 break;
464 *p2 = '\0';
465 if (!strcmp(p, "vnc")) {
466 (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
467 } else if (!strcmp(p, "vnclisten")) {
468 (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
469 } else if (!strcmp(p, "vncdisplay")) {
470 (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
471 } else if (!strcmp(p, "vncunused")) {
472 (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
473 } else if (!strcmp(p, "keymap")) {
474 (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
475 } else if (!strcmp(p, "sdl")) {
476 (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
477 } else if (!strcmp(p, "opengl")) {
478 (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
479 } else if (!strcmp(p, "display")) {
480 (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
481 } else if (!strcmp(p, "xauthority")) {
482 (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
483 }
484 } while ((p = strtok(NULL, ",")) != NULL);
485 skip_vfb:
486 free(buf2);
487 *num_vfbs = (*num_vfbs) + 1;
488 *num_vkbs = (*num_vkbs) + 1;
489 }
490 }
492 if (config_lookup_int (&config, "pci_msitranslate", &l) == CONFIG_TRUE)
493 pci_msitranslate = l;
495 if (config_lookup_int (&config, "pci_power_mgmt", &l) == CONFIG_TRUE)
496 pci_power_mgmt = l;
498 if ((pcis = config_lookup (&config, "pci")) != NULL) {
499 *num_pcidevs = 0;
500 *pcidevs = NULL;
501 while ((buf = config_setting_get_string_elem (pcis, *num_pcidevs)) != NULL) {
502 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
503 char *buf2 = strdup(buf);
504 char *p;
505 *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof (libxl_device_pci) * ((*num_pcidevs) + 1));
506 memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
507 p = strtok(buf2, ",");
508 if (!p)
509 goto skip_pci;
510 if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, &vdevfn)) {
511 sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
512 domain = 0;
513 }
514 libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, func, vdevfn);
515 (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
516 (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
517 while ((p = strtok(NULL, ",=")) != NULL) {
518 while (*p == ' ')
519 p++;
520 if (!strcmp(p, "msitranslate")) {
521 p = strtok(NULL, ",=");
522 (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
523 } else if (!strcmp(p, "power_mgmt")) {
524 p = strtok(NULL, ",=");
525 (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
526 }
527 }
528 *num_pcidevs = (*num_pcidevs) + 1;
529 skip_pci:
530 free(buf2);
531 }
532 }
534 if (c_info->hvm == 1) {
535 /* init dm from c and b */
536 init_dm_info(dm_info, c_info, b_info);
538 /* then process config related to dm */
539 if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
540 dm_info->device_model = strdup(buf);
541 if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
542 dm_info->stdvga = l;
543 if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
544 dm_info->vnc = l;
545 if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
546 dm_info->vnclisten = strdup(buf);
547 if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
548 dm_info->vncdisplay = l;
549 if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
550 dm_info->vncunused = l;
551 if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
552 dm_info->keymap = strdup(buf);
553 if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
554 dm_info->sdl = l;
555 if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
556 dm_info->opengl = l;
557 if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
558 dm_info->nographic = l;
559 if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
560 dm_info->serial = strdup(buf);
561 if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
562 dm_info->boot = strdup(buf);
563 if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
564 dm_info->usb = l;
565 if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
566 dm_info->usbdevice = strdup(buf);
567 }
569 config_destroy(&config);
570 }
572 #define MUST( call ) ({ \
573 int must_rc = (call); \
574 if (must_rc) { \
575 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \
576 __FILE__,__LINE__, must_rc, #call); \
577 exit(-must_rc); \
578 } \
579 })
581 static void create_domain(int debug, const char *config_file, const char *restore_file, int paused)
582 {
583 struct libxl_ctx ctx;
584 uint32_t domid;
585 libxl_domain_create_info info1;
586 libxl_domain_build_info info2;
587 libxl_domain_build_state state;
588 libxl_device_model_info dm_info;
589 libxl_device_disk *disks = NULL;
590 libxl_device_nic *vifs = NULL;
591 libxl_device_pci *pcidevs = NULL;
592 libxl_device_vfb *vfbs = NULL;
593 libxl_device_vkb *vkbs = NULL;
594 libxl_device_console console;
595 int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
596 int i, fd;
597 int need_daemon = 1;
598 libxl_device_model_starting *dm_starting = 0;
599 libxl_waiter *w1 = NULL, *w2 = NULL;
600 memset(&dm_info, 0x00, sizeof(dm_info));
602 printf("Parsing config file %s\n", config_file);
603 parse_config_file(config_file, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
604 if (debug)
605 printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
607 start:
608 domid = 0;
610 libxl_ctx_init(&ctx);
611 libxl_ctx_set_log(&ctx, log_callback, NULL);
612 libxl_domain_make(&ctx, &info1, &domid);
614 if (!restore_file || !need_daemon) {
615 if (dm_info.saved_state) {
616 free(dm_info.saved_state);
617 dm_info.saved_state = NULL;
618 }
619 libxl_domain_build(&ctx, &info2, domid, &state);
620 } else {
621 int restore_fd;
623 restore_fd = open(restore_file, O_RDONLY);
624 libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, &dm_info);
625 close(restore_fd);
626 }
628 for (i = 0; i < num_disks; i++) {
629 disk_info_domid_fixup(disks + i, domid);
630 libxl_device_disk_add(&ctx, domid, &disks[i]);
631 }
632 for (i = 0; i < num_vifs; i++) {
633 nic_info_domid_fixup(vifs + i, domid);
634 libxl_device_nic_add(&ctx, domid, &vifs[i]);
635 }
636 if (info1.hvm) {
637 device_model_info_domid_fixup(&dm_info, domid);
638 MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
639 vifs, num_vifs, &dm_starting) );
640 } else {
641 for (i = 0; i < num_vfbs; i++) {
642 vfb_info_domid_fixup(vfbs + i, domid);
643 libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
644 vkb_info_domid_fixup(vkbs + i, domid);
645 libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
646 }
647 init_console_info(&console, 0, &state);
648 console_info_domid_fixup(&console, domid);
649 if (num_vfbs)
650 console.constype = CONSTYPE_IOEMU;
651 libxl_device_console_add(&ctx, domid, &console);
652 if (num_vfbs)
653 libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
654 }
656 if (dm_starting)
657 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
658 for (i = 0; i < num_pcidevs; i++)
659 libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
661 if (!paused)
662 libxl_domain_unpause(&ctx, domid);
664 if (need_daemon) {
665 char *fullname, *name;
667 asprintf(&name, "xl-%s", info1.name);
668 libxl_create_logfile(&ctx, name, &fullname);
669 logfile = open(fullname, O_WRONLY|O_CREAT, 0644);
670 free(fullname);
671 free(name);
673 daemon(0, 0);
674 need_daemon = 0;
675 }
676 XL_LOG(&ctx, XL_LOG_DEBUG, "Waiting for domain %s (domid %d) to die", info1.name, domid);
677 w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
678 w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
679 libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
680 libxl_wait_for_domain_death(&ctx, domid, w2);
681 libxl_get_wait_fd(&ctx, &fd);
682 while (1) {
683 int ret;
684 fd_set rfds;
685 xc_dominfo_t info;
686 libxl_event event;
687 libxl_device_disk disk;
688 memset(&info, 0x00, sizeof(xc_dominfo_t));
690 FD_ZERO(&rfds);
691 FD_SET(fd, &rfds);
693 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
694 if (!ret)
695 continue;
696 libxl_get_event(&ctx, &event);
697 switch (event.type) {
698 case DOMAIN_DEATH:
699 if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info)) {
700 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
701 if (info.crashed || info.dying || (info.shutdown && (info.shutdown_reason != SHUTDOWN_suspend))) {
702 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be clean: destroying the domain", domid);
703 libxl_domain_destroy(&ctx, domid, 0);
704 if (info.shutdown && (info.shutdown_reason == SHUTDOWN_reboot)) {
705 libxl_free_waiter(w1);
706 libxl_free_waiter(w2);
707 free(w1);
708 free(w2);
709 libxl_ctx_free(&ctx);
710 XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
711 goto start;
712 }
713 XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
714 }
715 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be clean, exiting now", domid);
716 exit(0);
717 }
718 break;
719 case DISK_EJECT:
720 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
721 libxl_cdrom_insert(&ctx, domid, &disk);
722 break;
723 }
724 libxl_free_event(&event);
725 }
727 close(logfile);
728 for (i = 0; i < num_vifs; i++) {
729 free(vifs[i].smac);
730 free(vifs[i].ifname);
731 }
732 free(disks);
733 free(vifs);
734 free(vfbs);
735 free(vkbs);
736 free(pcidevs);
737 }
739 static void help(char *command)
740 {
741 if (!command || !strcmp(command, "help")) {
742 printf("Usage xl <subcommand> [args]\n\n");
743 printf("xl full list of subcommands:\n\n");
744 printf(" create create a domain from config file <filename>\n\n");
745 printf(" list list information about all domains\n\n");
746 printf(" destroy terminate a domain immediately\n\n");
747 printf(" pci-attach insert a new pass-through pci device\n\n");
748 printf(" pci-detach remove a domain's pass-through pci device\n\n");
749 printf(" pci-list list pass-through pci devices for a domain\n\n");
750 printf(" pause pause execution of a domain\n\n");
751 printf(" unpause unpause a paused domain\n\n");
752 printf(" console attach to domain's console\n\n");
753 printf(" save save a domain state to restore later\n\n");
754 printf(" restore restore a domain from a saved state\n\n");
755 printf(" cd-insert insert a cdrom into a guest's cd drive\n\n");
756 printf(" cd-eject eject a cdrom from a guest's cd drive\n\n");
757 } else if(!strcmp(command, "create")) {
758 printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
759 printf("Create a domain based on <ConfigFile>.\n\n");
760 printf("Options:\n\n");
761 printf("-h Print this help.\n");
762 printf("-d Enable debug messages.\n");
763 } else if(!strcmp(command, "list")) {
764 printf("Usage: xl list [Domain]\n\n");
765 printf("List information about all/some domains.\n\n");
766 } else if(!strcmp(command, "pci-attach")) {
767 printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
768 printf("Insert a new pass-through pci device.\n\n");
769 } else if(!strcmp(command, "pci-detach")) {
770 printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
771 printf("Remove a domain's pass-through pci device.\n\n");
772 } else if(!strcmp(command, "pci-list")) {
773 printf("Usage: xl pci-list <Domain>\n\n");
774 printf("List pass-through pci devices for a domain.\n\n");
775 } else if(!strcmp(command, "pause")) {
776 printf("Usage: xl pause <Domain>\n\n");
777 printf("Pause execution of a domain.\n\n");
778 } else if(!strcmp(command, "unpause")) {
779 printf("Usage: xl unpause <Domain>\n\n");
780 printf("Unpause a paused domain.\n\n");
781 } else if(!strcmp(command, "save")) {
782 printf("Usage: xl save [options] <Domain> <CheckpointFile>\n\n");
783 printf("Save a domain state to restore later.\n\n");
784 printf("Options:\n\n");
785 printf("-h Print this help.\n");
786 printf("-c Leave domain running after creating the snapshot.\n");
787 } else if(!strcmp(command, "restore")) {
788 printf("Usage: xl restore [options] <ConfigFile> <CheckpointFile>\n\n");
789 printf("Restore a domain from a saved state.\n\n");
790 printf("Options:\n\n");
791 printf("-h Print this help.\n");
792 printf("-p Do not unpause domain after restoring it.\n");
793 } else if(!strcmp(command, "destroy")) {
794 printf("Usage: xl destroy <Domain>\n\n");
795 printf("Terminate a domain immediately.\n\n");
796 } else if (!strcmp(command, "console")) {
797 printf("Usage: xl console <Domain>\n\n");
798 printf("Attach to domain's console.\n\n");
799 } else if (!strcmp(command, "cd-insert")) {
800 printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
801 printf("Insert a cdrom into a guest's cd drive.\n\n");
802 } else if (!strcmp(command, "cd-eject")) {
803 printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
804 printf("Eject a cdrom from a guest's cd drive.\n\n");
805 }
806 }
808 void console(char *p, int cons_num)
809 {
810 struct libxl_ctx ctx;
811 uint32_t domid;
813 libxl_ctx_init(&ctx);
814 libxl_ctx_set_log(&ctx, log_callback, NULL);
816 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
817 fprintf(stderr, "%s is an invalid domain identifier\n", p);
818 exit(2);
819 }
820 libxl_console_attach(&ctx, domid, cons_num);
821 }
823 void cd_insert(char *dom, char *virtdev, char *phys)
824 {
825 struct libxl_ctx ctx;
826 uint32_t domid;
827 libxl_device_disk disk;
828 char *p;
830 libxl_ctx_init(&ctx);
831 libxl_ctx_set_log(&ctx, log_callback, NULL);
833 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
834 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
835 exit(2);
836 }
838 disk.backend_domid = 0;
839 disk.domid = domid;
840 if (phys) {
841 p = strchr(phys, ':');
842 if (!p) {
843 fprintf(stderr, "No type specified, ");
844 disk.physpath = phys;
845 if (!strncmp(phys, "/dev", 4)) {
846 fprintf(stderr, "assuming phy:\n");
847 disk.phystype = PHYSTYPE_PHY;
848 } else {
849 fprintf(stderr, "assuming file:\n");
850 disk.phystype = PHYSTYPE_FILE;
851 }
852 } else {
853 p = '\0';
854 disk.physpath = strdup(p);
855 p++;
856 libxl_string_to_phystype(&ctx, p, &disk.phystype);
857 }
858 } else {
859 disk.physpath = NULL;
860 disk.phystype = 0;
861 }
862 disk.virtpath = virtdev;
863 disk.unpluggable = 1;
864 disk.readwrite = 0;
865 disk.is_cdrom = 1;
867 libxl_cdrom_insert(&ctx, domid, &disk);
868 }
870 int main_cd_eject(int argc, char **argv)
871 {
872 int opt = 0;
873 char *p = NULL, *virtdev;
875 while ((opt = getopt(argc, argv, "hn:")) != -1) {
876 switch (opt) {
877 case 'h':
878 help("cd-eject");
879 exit(0);
880 default:
881 fprintf(stderr, "option not supported\n");
882 break;
883 }
884 }
885 if (optind >= argc - 1) {
886 help("cd-eject");
887 exit(2);
888 }
890 p = argv[optind];
891 virtdev = argv[optind + 1];
893 cd_insert(p, virtdev, NULL);
894 exit(0);
895 }
897 int main_cd_insert(int argc, char **argv)
898 {
899 int opt = 0;
900 char *p = NULL, *file = NULL, *virtdev;
902 while ((opt = getopt(argc, argv, "hn:")) != -1) {
903 switch (opt) {
904 case 'h':
905 help("cd-insert");
906 exit(0);
907 default:
908 fprintf(stderr, "option not supported\n");
909 break;
910 }
911 }
912 if (optind >= argc - 2) {
913 help("cd-insert");
914 exit(2);
915 }
917 p = argv[optind];
918 virtdev = argv[optind + 1];
919 file = argv[optind + 2];
921 cd_insert(p, virtdev, file);
922 exit(0);
923 }
925 int main_console(int argc, char **argv)
926 {
927 int opt = 0, cons_num = 0;
928 char *p = NULL;
930 while ((opt = getopt(argc, argv, "hn:")) != -1) {
931 switch (opt) {
932 case 'h':
933 help("console");
934 exit(0);
935 case 'n':
936 if (optarg) {
937 cons_num = strtol(optarg, NULL, 10);
938 }
939 break;
940 default:
941 fprintf(stderr, "option not supported\n");
942 break;
943 }
944 }
945 if (optind >= argc) {
946 help("console");
947 exit(2);
948 }
950 p = argv[optind];
952 console(p, cons_num);
953 exit(0);
954 }
956 void pcilist(char *dom)
957 {
958 struct libxl_ctx ctx;
959 uint32_t domid;
960 libxl_device_pci *pcidevs;
961 int num, i;
963 libxl_ctx_init(&ctx);
964 libxl_ctx_set_log(&ctx, log_callback, NULL);
966 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
967 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
968 exit(2);
969 }
970 pcidevs = libxl_device_pci_list(&ctx, domid, &num);
971 if (!num)
972 return;
973 printf("VFn domain bus slot func\n");
974 for (i = 0; i < num; i++) {
975 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);
976 }
977 free(pcidevs);
978 }
980 int main_pcilist(int argc, char **argv)
981 {
982 int opt;
983 char *domname = NULL;
985 while ((opt = getopt(argc, argv, "h")) != -1) {
986 switch (opt) {
987 case 'h':
988 help("pci-list");
989 exit(0);
990 default:
991 fprintf(stderr, "option not supported\n");
992 break;
993 }
994 }
995 if (optind >= argc) {
996 help("pci-list");
997 exit(2);
998 }
1000 domname = argv[optind];
1002 pcilist(domname);
1003 exit(0);
1006 void pcidetach(char *dom, char *bdf)
1008 struct libxl_ctx ctx;
1009 uint32_t domid;
1010 libxl_device_pci pcidev;
1011 unsigned int domain, bus, dev, func;
1013 libxl_ctx_init(&ctx);
1014 libxl_ctx_set_log(&ctx, log_callback, NULL);
1016 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
1017 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1018 exit(2);
1020 memset(&pcidev, 0x00, sizeof(pcidev));
1021 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1022 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1023 libxl_device_pci_remove(&ctx, domid, &pcidev);
1026 int main_pcidetach(int argc, char **argv)
1028 int opt;
1029 char *domname = NULL, *bdf = NULL;
1031 while ((opt = getopt(argc, argv, "h")) != -1) {
1032 switch (opt) {
1033 case 'h':
1034 help("pci-attach");
1035 exit(0);
1036 default:
1037 fprintf(stderr, "option not supported\n");
1038 break;
1041 if (optind >= argc - 1) {
1042 help("pci-detach");
1043 exit(2);
1046 domname = argv[optind];
1047 bdf = argv[optind + 1];
1049 pcidetach(domname, bdf);
1050 exit(0);
1052 void pciattach(char *dom, char *bdf, char *vs)
1054 struct libxl_ctx ctx;
1055 uint32_t domid;
1056 libxl_device_pci pcidev;
1057 unsigned int domain, bus, dev, func;
1059 libxl_ctx_init(&ctx);
1060 libxl_ctx_set_log(&ctx, log_callback, NULL);
1062 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
1063 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1064 exit(2);
1066 memset(&pcidev, 0x00, sizeof(pcidev));
1067 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1068 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1069 libxl_device_pci_add(&ctx, domid, &pcidev);
1072 int main_pciattach(int argc, char **argv)
1074 int opt;
1075 char *domname = NULL, *bdf = NULL, *vs = NULL;
1077 while ((opt = getopt(argc, argv, "h")) != -1) {
1078 switch (opt) {
1079 case 'h':
1080 help("pci-attach");
1081 exit(0);
1082 default:
1083 fprintf(stderr, "option not supported\n");
1084 break;
1087 if (optind >= argc - 1) {
1088 help("pci-attach");
1089 exit(2);
1092 domname = argv[optind];
1093 bdf = argv[optind + 1];
1095 if (optind + 1 < argc)
1096 vs = argv[optind + 2];
1098 pciattach(domname, bdf, vs);
1099 exit(0);
1102 void pause_domain(char *p)
1104 struct libxl_ctx ctx;
1105 uint32_t domid;
1107 libxl_ctx_init(&ctx);
1108 libxl_ctx_set_log(&ctx, log_callback, NULL);
1110 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1111 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1112 exit(2);
1114 libxl_domain_pause(&ctx, domid);
1117 void unpause_domain(char *p)
1119 struct libxl_ctx ctx;
1120 uint32_t domid;
1122 libxl_ctx_init(&ctx);
1123 libxl_ctx_set_log(&ctx, log_callback, NULL);
1125 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1126 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1127 exit(2);
1129 libxl_domain_unpause(&ctx, domid);
1132 void destroy_domain(char *p)
1134 struct libxl_ctx ctx;
1135 uint32_t domid;
1137 libxl_ctx_init(&ctx);
1138 libxl_ctx_set_log(&ctx, log_callback, NULL);
1140 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1141 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1142 exit(2);
1144 libxl_domain_destroy(&ctx, domid, 0);
1147 void list_domains(void)
1149 struct libxl_ctx ctx;
1150 xc_dominfo_t *info;
1151 int nb_domain, i;
1153 libxl_ctx_init(&ctx);
1154 libxl_ctx_set_log(&ctx, log_callback, NULL);
1156 info = libxl_domain_infolist(&ctx, &nb_domain);
1158 if (info < 0) {
1159 fprintf(stderr, "libxl_domain_infolist failed.\n");
1160 exit(1);
1162 printf("Name ID Mem VCPUs\tState\tTime(s)\n");
1163 for (i = 0; i < nb_domain; i++) {
1164 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f\n",
1165 libxl_domid_to_name(&ctx, info[i].domid),
1166 info[i].domid,
1167 info[i].nr_pages * XC_PAGE_SIZE/(1024*1024),
1168 info[i].nr_online_vcpus,
1169 info[i].running ? 'r' : '-',
1170 info[i].blocked ? 'b' : '-',
1171 info[i].paused ? 'p' : '-',
1172 info[i].shutdown ? 's' : '-',
1173 info[i].crashed ? 'c' : '-',
1174 info[i].dying ? 'd' : '-',
1175 ((float)info[i].cpu_time / 1e9));
1177 free(info);
1180 int save_domain(char *p, char *filename, int checkpoint)
1182 struct libxl_ctx ctx;
1183 uint32_t domid;
1184 int fd;
1186 libxl_ctx_init(&ctx);
1187 libxl_ctx_set_log(&ctx, log_callback, NULL);
1189 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1190 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1191 exit(2);
1193 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1194 if (fd < 0) {
1195 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
1196 exit(2);
1198 libxl_domain_suspend(&ctx, NULL, domid, fd);
1199 close(fd);
1201 if (checkpoint)
1202 libxl_domain_unpause(&ctx, domid);
1203 else
1204 libxl_domain_destroy(&ctx, domid, 0);
1206 exit(0);
1209 int main_restore(int argc, char **argv)
1211 char *checkpoint_file = NULL;
1212 char *config_file = NULL;
1213 int paused = 0, debug = 0;
1214 int opt;
1216 while ((opt = getopt(argc, argv, "hpd")) != -1) {
1217 switch (opt) {
1218 case 'p':
1219 paused = 1;
1220 break;
1221 case 'd':
1222 debug = 1;
1223 break;
1224 case 'h':
1225 help("restore");
1226 exit(0);
1227 default:
1228 fprintf(stderr, "option not supported\n");
1229 break;
1233 if (optind >= argc - 1) {
1234 help("restore");
1235 exit(2);
1238 config_file = argv[optind];
1239 checkpoint_file = argv[optind + 1];
1240 create_domain(debug, config_file, checkpoint_file, paused);
1241 exit(0);
1244 int main_save(int argc, char **argv)
1246 char *filename = NULL, *p = NULL;
1247 int checkpoint = 0;
1248 int opt;
1250 while ((opt = getopt(argc, argv, "hc")) != -1) {
1251 switch (opt) {
1252 case 'c':
1253 checkpoint = 1;
1254 break;
1255 case 'h':
1256 help("save");
1257 exit(0);
1258 default:
1259 fprintf(stderr, "option not supported\n");
1260 break;
1264 if (optind >= argc - 1) {
1265 help("save");
1266 exit(2);
1269 p = argv[optind];
1270 filename = argv[optind + 1];
1271 save_domain(p, filename, checkpoint);
1272 exit(0);
1275 int main_pause(int argc, char **argv)
1277 int opt;
1278 char *p;
1281 while ((opt = getopt(argc, argv, "h")) != -1) {
1282 switch (opt) {
1283 case 'h':
1284 help("pause");
1285 exit(0);
1286 default:
1287 fprintf(stderr, "option not supported\n");
1288 break;
1291 if (optind >= argc) {
1292 help("pause");
1293 exit(2);
1296 p = argv[optind];
1298 pause_domain(p);
1299 exit(0);
1302 int main_unpause(int argc, char **argv)
1304 int opt;
1305 char *p;
1308 while ((opt = getopt(argc, argv, "h")) != -1) {
1309 switch (opt) {
1310 case 'h':
1311 help("unpause");
1312 exit(0);
1313 default:
1314 fprintf(stderr, "option not supported\n");
1315 break;
1318 if (optind >= argc) {
1319 help("unpause");
1320 exit(2);
1323 p = argv[optind];
1325 unpause_domain(p);
1326 exit(0);
1329 int main_destroy(int argc, char **argv)
1331 int opt;
1332 char *p;
1334 while ((opt = getopt(argc, argv, "h")) != -1) {
1335 switch (opt) {
1336 case 'h':
1337 help("destroy");
1338 exit(0);
1339 default:
1340 fprintf(stderr, "option not supported\n");
1341 break;
1344 if (optind >= argc) {
1345 help("destroy");
1346 exit(2);
1349 p = argv[optind];
1351 destroy_domain(p);
1352 exit(0);
1355 int main_list(int argc, char **argv)
1357 int opt;
1359 while ((opt = getopt(argc, argv, "h")) != -1) {
1360 switch (opt) {
1361 case 'h':
1362 help("list");
1363 exit(0);
1364 default:
1365 fprintf(stderr, "option not supported\n");
1366 break;
1370 list_domains();
1371 exit(0);
1374 int main_create(int argc, char **argv)
1376 char *filename = NULL;
1377 int debug = 0;
1378 int opt;
1380 while ((opt = getopt(argc, argv, "hd")) != -1) {
1381 switch (opt) {
1382 case 'd':
1383 debug = 1;
1384 break;
1385 case 'h':
1386 help("create");
1387 exit(0);
1388 default:
1389 fprintf(stderr, "option not supported\n");
1390 break;
1394 if (optind >= argc) {
1395 help("create");
1396 exit(2);
1399 filename = argv[optind];
1400 create_domain(debug, filename, NULL, 0);
1401 exit(0);
1404 int main(int argc, char **argv)
1406 if (argc < 2) {
1407 help(NULL);
1408 exit(1);
1411 if (!strcmp(argv[1], "create")) {
1412 main_create(argc - 1, argv + 1);
1413 } else if (!strcmp(argv[1], "list")) {
1414 main_list(argc - 1, argv + 1);
1415 } else if (!strcmp(argv[1], "destroy")) {
1416 main_destroy(argc - 1, argv + 1);
1417 } else if (!strcmp(argv[1], "pci-attach")) {
1418 main_pciattach(argc - 1, argv + 1);
1419 } else if (!strcmp(argv[1], "pci-detach")) {
1420 main_pcidetach(argc - 1, argv + 1);
1421 } else if (!strcmp(argv[1], "pci-list")) {
1422 main_pcilist(argc - 1, argv + 1);
1423 } else if (!strcmp(argv[1], "pause")) {
1424 main_pause(argc - 1, argv + 1);
1425 } else if (!strcmp(argv[1], "unpause")) {
1426 main_unpause(argc - 1, argv + 1);
1427 } else if (!strcmp(argv[1], "console")) {
1428 main_console(argc - 1, argv + 1);
1429 } else if (!strcmp(argv[1], "save")) {
1430 main_save(argc - 1, argv + 1);
1431 } else if (!strcmp(argv[1], "restore")) {
1432 main_restore(argc - 1, argv + 1);
1433 } else if (!strcmp(argv[1], "cd-insert")) {
1434 main_cd_insert(argc - 1, argv + 1);
1435 } else if (!strcmp(argv[1], "cd-eject")) {
1436 main_cd_eject(argc - 1, argv + 1);
1437 } else if (!strcmp(argv[1], "help")) {
1438 if (argc > 2)
1439 help(argv[2]);
1440 else
1441 help(NULL);
1442 exit(0);
1443 } else {
1444 fprintf(stderr, "command not implemented\n");
1445 exit(1);