debuggers.hg

view tools/libxl/xl.c @ 20933:b48b5e688470

xl: Do not duplicate last line of config file when trying compat mode.

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 03 09:45:25 2010 +0000 (2010-02-03)
parents f300b53520d0
children 71af69a9d393
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 <unistd.h>
24 #include <sys/time.h> /* for time */
25 #include <getopt.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <sys/socket.h>
30 #include <sys/select.h>
31 #include <arpa/inet.h>
32 #include <xenctrl.h>
33 #include <ctype.h>
35 #include "libxl.h"
36 #include "libxl_utils.h"
38 #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
40 int logfile = 2;
42 void log_callback(void *userdata, int loglevel, const char *file, int line, const char *func, char *s)
43 {
44 char str[1024];
46 snprintf(str, sizeof(str), "[%d] %s:%d:%s: %s\n", loglevel, file, line, func, s);
47 write(logfile, str, strlen(str));
48 }
50 static int domain_qualifier_to_domid(struct libxl_ctx *ctx, char *p, uint32_t *domid)
51 {
52 int i, alldigit;
54 alldigit = 1;
55 for (i = 0; p[i]; i++) {
56 if (!isdigit((uint8_t)p[i])) {
57 alldigit = 0;
58 break;
59 }
60 }
62 if (i > 0 && alldigit) {
63 *domid = strtoul(p, NULL, 10);
64 return 0;
65 } else {
66 /* check here if it's a uuid and do proper conversion */
67 }
68 return libxl_name_to_domid(ctx, p, domid);
69 }
71 #define LOG(_f, _a...) dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
73 void dolog(const char *file, int line, const char *func, char *fmt, ...)
74 {
75 va_list ap;
76 char *s;
77 int rc;
79 va_start(ap, fmt);
80 rc = vasprintf(&s, fmt, ap);
81 va_end(ap);
82 if (rc >= 0)
83 write(logfile, s, rc);
84 }
86 static void init_create_info(libxl_domain_create_info *c_info)
87 {
88 memset(c_info, '\0', sizeof(*c_info));
89 c_info->xsdata = NULL;
90 c_info->platformdata = NULL;
91 c_info->hvm = 1;
92 c_info->ssidref = 0;
93 }
95 static void init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info *c_info)
96 {
97 memset(b_info, '\0', sizeof(*b_info));
98 b_info->timer_mode = -1;
99 b_info->hpet = 1;
100 b_info->vpt_align = -1;
101 b_info->max_vcpus = 1;
102 b_info->max_memkb = 32 * 1024;
103 b_info->target_memkb = b_info->max_memkb;
104 if (c_info->hvm) {
105 b_info->shadow_memkb = libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus);
106 b_info->video_memkb = 8 * 1024;
107 b_info->kernel = "/usr/lib/xen/boot/hvmloader";
108 b_info->hvm = 1;
109 b_info->u.hvm.pae = 1;
110 b_info->u.hvm.apic = 1;
111 b_info->u.hvm.acpi = 1;
112 b_info->u.hvm.nx = 1;
113 b_info->u.hvm.viridian = 0;
114 } else {
115 b_info->u.pv.slack_memkb = 8 * 1024;
116 }
117 }
119 static void init_dm_info(libxl_device_model_info *dm_info,
120 libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
121 {
122 int i;
123 memset(dm_info, '\0', sizeof(*dm_info));
125 for (i = 0; i < 16; i++) {
126 dm_info->uuid[i] = rand();
127 }
129 dm_info->dom_name = c_info->name;
130 dm_info->device_model = "/usr/lib/xen/bin/qemu-dm";
131 dm_info->videoram = b_info->video_memkb / 1024;
132 dm_info->apic = b_info->u.hvm.apic;
134 dm_info->stdvga = 0;
135 dm_info->vnc = 1;
136 dm_info->vnclisten = "127.0.0.1";
137 dm_info->vncdisplay = 0;
138 dm_info->vncunused = 0;
139 dm_info->keymap = NULL;
140 dm_info->sdl = 0;
141 dm_info->opengl = 0;
142 dm_info->nographic = 0;
143 dm_info->serial = NULL;
144 dm_info->boot = "cda";
145 dm_info->usb = 0;
146 dm_info->usbdevice = NULL;
147 }
149 static void init_nic_info(libxl_device_nic *nic_info, int devnum)
150 {
151 memset(nic_info, '\0', sizeof(*nic_info));
153 nic_info->backend_domid = 0;
154 nic_info->domid = 0;
155 nic_info->devid = devnum;
156 nic_info->mtu = 1492;
157 nic_info->model = "e1000";
158 nic_info->mac[0] = 0x00;
159 nic_info->mac[1] = 0x16;
160 nic_info->mac[2] = 0x3e;
161 nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
162 nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
163 nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
164 nic_info->ifname = NULL;
165 nic_info->bridge = "xenbr0";
166 nic_info->script = "/etc/xen/scripts/vif-bridge";
167 nic_info->nictype = NICTYPE_IOEMU;
168 }
170 static void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
171 {
172 memset(vfb, 0x00, sizeof(libxl_device_vfb));
173 vfb->devid = dev_num;
174 vfb->vnc = 1;
175 vfb->vnclisten = "127.0.0.1";
176 vfb->vncdisplay = 0;
177 vfb->vncunused = 1;
178 vfb->keymap = NULL;
179 vfb->sdl = 0;
180 vfb->opengl = 0;
181 }
183 static void init_vkb_info(libxl_device_vkb *vkb, int dev_num)
184 {
185 memset(vkb, 0x00, sizeof(libxl_device_vkb));
186 vkb->devid = dev_num;
187 }
189 static void init_console_info(libxl_device_console *console, int dev_num, libxl_domain_build_state *state)
190 {
191 memset(console, 0x00, sizeof(libxl_device_console));
192 console->devid = dev_num;
193 console->constype = CONSTYPE_XENCONSOLED;
194 if (state)
195 console->build_state = state;
196 }
198 static void printf_info(libxl_domain_create_info *c_info,
199 libxl_domain_build_info *b_info,
200 libxl_device_disk *disks,
201 int num_disks,
202 libxl_device_nic *vifs,
203 int num_vifs,
204 libxl_device_pci *pcidevs,
205 int num_pcidevs,
206 libxl_device_vfb *vfbs,
207 int num_vfbs,
208 libxl_device_vkb *vkb,
209 int num_vkbs,
210 libxl_device_model_info *dm_info)
211 {
212 int i;
213 printf("*** domain_create_info ***\n");
214 printf("hvm: %d\n", c_info->hvm);
215 printf("hap: %d\n", c_info->hap);
216 printf("ssidref: %d\n", c_info->ssidref);
217 printf("name: %s\n", c_info->name);
218 printf("uuid: " UUID_FMT "\n",
219 (c_info->uuid)[0], (c_info->uuid)[1], (c_info->uuid)[2], (c_info->uuid)[3],
220 (c_info->uuid)[4], (c_info->uuid)[5], (c_info->uuid)[6], (c_info->uuid)[7],
221 (c_info->uuid)[8], (c_info->uuid)[9], (c_info->uuid)[10], (c_info->uuid)[11],
222 (c_info->uuid)[12], (c_info->uuid)[13], (c_info->uuid)[14], (c_info->uuid)[15]);
223 if (c_info->xsdata)
224 printf("xsdata: contains data\n");
225 else
226 printf("xsdata: (null)\n");
227 if (c_info->platformdata)
228 printf("platformdata: contains data\n");
229 else
230 printf("platformdata: (null)\n");
233 printf("\n\n\n*** domain_build_info ***\n");
234 printf("timer_mode: %d\n", b_info->timer_mode);
235 printf("hpet: %d\n", b_info->hpet);
236 printf("vpt_align: %d\n", b_info->vpt_align);
237 printf("max_vcpus: %d\n", b_info->max_vcpus);
238 printf("max_memkb: %d\n", b_info->max_memkb);
239 printf("target_memkb: %d\n", b_info->target_memkb);
240 printf("kernel: %s\n", b_info->kernel);
241 printf("hvm: %d\n", b_info->hvm);
243 if (c_info->hvm) {
244 printf("video_memkb: %d\n", b_info->video_memkb);
245 printf("shadow_memkb: %d\n", b_info->shadow_memkb);
246 printf(" pae: %d\n", b_info->u.hvm.pae);
247 printf(" apic: %d\n", b_info->u.hvm.apic);
248 printf(" acpi: %d\n", b_info->u.hvm.acpi);
249 printf(" nx: %d\n", b_info->u.hvm.nx);
250 printf(" viridian: %d\n", b_info->u.hvm.viridian);
251 } else {
252 printf("cmdline: %s\n", b_info->u.pv.cmdline);
253 printf("ramdisk: %s\n", b_info->u.pv.ramdisk);
254 }
256 for (i = 0; i < num_disks; i++) {
257 printf("\n\n\n*** disks_info: %d ***\n", i);
258 printf("backend_domid %d\n", disks[i].backend_domid);
259 printf("domid %d\n", disks[i].domid);
260 printf("physpath %s\n", disks[i].physpath);
261 printf("phystype %d\n", disks[i].phystype);
262 printf("virtpath %s\n", disks[i].virtpath);
263 printf("unpluggable %d\n", disks[i].unpluggable);
264 printf("readwrite %d\n", disks[i].readwrite);
265 printf("is_cdrom %d\n", disks[i].is_cdrom);
266 }
268 for (i = 0; i < num_vifs; i++) {
269 printf("\n\n\n*** vifs_info: %d ***\n", i);
270 printf("backend_domid %d\n", vifs[i].backend_domid);
271 printf("domid %d\n", vifs[i].domid);
272 printf("devid %d\n", vifs[i].devid);
273 printf("mtu %d\n", vifs[i].mtu);
274 printf("model %s\n", vifs[i].model);
275 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]);
276 }
278 for (i = 0; i < num_pcidevs; i++) {
279 printf("\n\n\n*** pcidevs_info: %d ***\n", i);
280 printf("pci dev "PCI_BDF_VDEVFN"\n", pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func, pcidevs[i].vdevfn);
281 printf("opts msitranslate %d power_mgmt %d\n", pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
282 }
284 for (i = 0; i < num_vfbs; i++) {
285 printf("\n\n\n*** vfbs_info: %d ***\n", i);
286 printf("backend_domid %d\n", vfbs[i].backend_domid);
287 printf("domid %d\n", vfbs[i].domid);
288 printf("devid %d\n", vfbs[i].devid);
289 printf("vnc: %d\n", vfbs[i].vnc);
290 printf("vnclisten: %s\n", vfbs[i].vnclisten);
291 printf("vncdisplay: %d\n", vfbs[i].vncdisplay);
292 printf("vncunused: %d\n", vfbs[i].vncunused);
293 printf("keymap: %s\n", vfbs[i].keymap);
294 printf("sdl: %d\n", vfbs[i].sdl);
295 printf("opengl: %d\n", vfbs[i].opengl);
296 printf("display: %s\n", vfbs[i].display);
297 printf("xauthority: %s\n", vfbs[i].xauthority);
298 }
300 if (c_info->hvm) {
301 printf("\n\n\n*** device_model_info ***\n");
302 printf("domid: %d\n", dm_info->domid);
303 printf("dom_name: %s\n", dm_info->dom_name);
304 printf("device_model: %s\n", dm_info->device_model);
305 printf("videoram: %d\n", dm_info->videoram);
306 printf("stdvga: %d\n", dm_info->stdvga);
307 printf("vnc: %d\n", dm_info->vnc);
308 printf("vnclisten: %s\n", dm_info->vnclisten);
309 printf("vncdisplay: %d\n", dm_info->vncdisplay);
310 printf("vncunused: %d\n", dm_info->vncunused);
311 printf("keymap: %s\n", dm_info->keymap);
312 printf("sdl: %d\n", dm_info->sdl);
313 printf("opengl: %d\n", dm_info->opengl);
314 printf("nographic: %d\n", dm_info->nographic);
315 printf("serial: %s\n", dm_info->serial);
316 printf("boot: %s\n", dm_info->boot);
317 printf("usb: %d\n", dm_info->usb);
318 printf("usbdevice: %s\n", dm_info->usbdevice);
319 printf("apic: %d\n", dm_info->apic);
320 }
321 }
323 static char* compat_config_file(const char *filename)
324 {
325 char t;
326 char *newfile = (char*) malloc(strlen(filename) + 4);
327 char *buf = (char *) malloc(2048);
328 int size = 2048, i;
329 FILE *s;
330 FILE *d;
332 sprintf(newfile, "%s.xl", filename);
334 s = fopen(filename, "r");
335 if (!s) {
336 perror("cannot open file for reading");
337 return NULL;
338 }
339 d = fopen(newfile, "w");
340 if (!d) {
341 fclose(s);
342 perror("cannot open file for writting");
343 return NULL;
344 }
346 while (!feof(s)) {
347 buf[0] = 0;
348 fgets(buf, size, s);
349 while (buf[strlen(buf) - 1] != '\n' && !feof(s)) {
350 size += 1024;
351 buf = realloc(buf, size + 1024);
352 fgets(buf + (size - 1025), 1025, s);
353 }
354 for (i = 0; i < strlen(buf); i++)
355 if (buf[i] == '\'')
356 buf[i] = '\"';
357 if (strchr(buf, '=') != NULL) {
358 if ((buf[strlen(buf) - 1] == '\n' && buf[strlen(buf) - 2] == ';') ||
359 buf[strlen(buf) - 1] == ';') {
360 fputs(buf, d);
361 } else {
362 t = buf[strlen(buf) - 1];
363 buf[strlen(buf) - 1] = ';';
364 fputs(buf, d);
365 fputc(t, d);
366 }
367 } else if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') {
368 fputs(buf, d);
369 }
370 }
372 fclose(s);
373 fclose(d);
375 free(buf);
377 return newfile;
378 }
380 static void parse_config_file(const char *filename,
381 libxl_domain_create_info *c_info,
382 libxl_domain_build_info *b_info,
383 libxl_device_disk **disks,
384 int *num_disks,
385 libxl_device_nic **vifs,
386 int *num_vifs,
387 libxl_device_pci **pcidevs,
388 int *num_pcidevs,
389 libxl_device_vfb **vfbs,
390 int *num_vfbs,
391 libxl_device_vkb **vkbs,
392 int *num_vkbs,
393 libxl_device_model_info *dm_info)
394 {
395 const char *buf;
396 long l;
397 struct config_t config;
398 struct config_setting_t *vbds, *nics, *pcis, *cvfbs;
399 int pci_power_mgmt = 0;
400 int pci_msitranslate = 1;
401 int i;
403 config_init (&config);
405 if (!config_read_file(&config, filename)) {
406 char *newfilename;
407 config_destroy(&config);
408 newfilename = compat_config_file(filename);
409 config_init (&config);
410 if (!config_read_file(&config, newfilename)) {
411 fprintf(stderr, "Failed to parse config file %s on line %d, try removing any embedded python code\n", config_error_text(&config), config_error_line(&config));
412 exit(1);
413 }
414 free(newfilename);
415 }
417 init_create_info(c_info);
419 c_info->hvm = 0;
420 if ((config_lookup_string (&config, "builder", &buf) == CONFIG_TRUE) &&
421 !strncmp(buf, "hvm", strlen(buf)))
422 c_info->hvm = 1;
424 /* hap is missing */
425 if (config_lookup_string (&config, "name", &buf) == CONFIG_TRUE)
426 c_info->name = strdup(buf);
427 else
428 c_info->name = "test";
429 for (i = 0; i < 16; i++) {
430 c_info->uuid[i] = rand();
431 }
433 init_build_info(b_info, c_info);
435 /* the following is the actual config parsing with overriding values in the structures */
436 if (config_lookup_int (&config, "vcpus", &l) == CONFIG_TRUE)
437 b_info->max_vcpus = l;
439 if (config_lookup_int (&config, "memory", &l) == CONFIG_TRUE) {
440 b_info->max_memkb = l * 1024;
441 b_info->target_memkb = b_info->max_memkb;
442 }
444 if (config_lookup_int (&config, "shadow_memory", &l) == CONFIG_TRUE)
445 b_info->shadow_memkb = l * 1024;
447 if (config_lookup_int (&config, "videoram", &l) == CONFIG_TRUE)
448 b_info->video_memkb = l * 1024;
450 if (config_lookup_string (&config, "kernel", &buf) == CONFIG_TRUE)
451 b_info->kernel = strdup(buf);
453 if (c_info->hvm == 1) {
454 if (config_lookup_int (&config, "pae", &l) == CONFIG_TRUE)
455 b_info->u.hvm.pae = l;
456 if (config_lookup_int (&config, "apic", &l) == CONFIG_TRUE)
457 b_info->u.hvm.apic = l;
458 if (config_lookup_int (&config, "acpi", &l) == CONFIG_TRUE)
459 b_info->u.hvm.acpi = l;
460 if (config_lookup_int (&config, "nx", &l) == CONFIG_TRUE)
461 b_info->u.hvm.nx = l;
462 if (config_lookup_int (&config, "viridian", &l) == CONFIG_TRUE)
463 b_info->u.hvm.viridian = l;
464 } else {
465 char *cmdline;
466 if (config_lookup_string (&config, "root", &buf) == CONFIG_TRUE) {
467 asprintf(&cmdline, "root=%s", buf);
468 b_info->u.pv.cmdline = cmdline;
469 }
470 if (config_lookup_string (&config, "ramdisk", &buf) == CONFIG_TRUE)
471 b_info->u.pv.ramdisk = strdup(buf);
472 }
474 if ((vbds = config_lookup (&config, "disk")) != NULL) {
475 *num_disks = 0;
476 *disks = NULL;
477 while ((buf = config_setting_get_string_elem (vbds, *num_disks)) != NULL) {
478 char *buf2 = strdup(buf);
479 char *p, *p2;
480 *disks = (libxl_device_disk *) realloc(*disks, sizeof (libxl_device_disk) * ((*num_disks) + 1));
481 (*disks)[*num_disks].backend_domid = 0;
482 (*disks)[*num_disks].domid = 0;
483 (*disks)[*num_disks].unpluggable = 0;
484 p = strtok(buf2, ",:");
485 while (*p == ' ')
486 p++;
487 if (!strcmp(p, "phy")) {
488 (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
489 } else if (!strcmp(p, "file")) {
490 (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
491 } else if (!strcmp(p, "tap")) {
492 p = strtok(NULL, ":");
493 if (!strcmp(p, "aio")) {
494 (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
495 } else if (!strcmp(p, "vhd")) {
496 (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
497 } else if (!strcmp(p, "qcow")) {
498 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
499 } else if (!strcmp(p, "qcow2")) {
500 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
501 }
502 }
503 p = strtok(NULL, ",");
504 while (*p == ' ')
505 p++;
506 (*disks)[*num_disks].physpath= strdup(p);
507 p = strtok(NULL, ",");
508 while (*p == ' ')
509 p++;
510 p2 = strchr(p, ':');
511 if (p2 == NULL) {
512 (*disks)[*num_disks].virtpath = strdup(p);
513 (*disks)[*num_disks].is_cdrom = 0;
514 (*disks)[*num_disks].unpluggable = 1;
515 } else {
516 *p2 = '\0';
517 (*disks)[*num_disks].virtpath = strdup(p);
518 if (!strcmp(p2 + 1, "cdrom")) {
519 (*disks)[*num_disks].is_cdrom = 1;
520 (*disks)[*num_disks].unpluggable = 1;
521 } else
522 (*disks)[*num_disks].is_cdrom = 0;
523 }
524 p = strtok(NULL, ",");
525 while (*p == ' ')
526 p++;
527 (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
528 free(buf2);
529 *num_disks = (*num_disks) + 1;
530 }
531 }
533 if ((nics = config_lookup (&config, "vif")) != NULL) {
534 *num_vifs = 0;
535 *vifs = NULL;
536 while ((buf = config_setting_get_string_elem (nics, *num_vifs)) != NULL) {
537 char *buf2 = strdup(buf);
538 char *p, *p2;
539 *vifs = (libxl_device_nic *) realloc(*vifs, sizeof (libxl_device_nic) * ((*num_vifs) + 1));
540 init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
541 p = strtok(buf2, ",");
542 if (!p)
543 goto skip;
544 do {
545 while (*p == ' ')
546 p++;
547 if ((p2 = strchr(p, '=')) == NULL)
548 break;
549 *p2 = '\0';
550 if (!strcmp(p, "model")) {
551 (*vifs)[*num_vifs].model = strdup(p2 + 1);
552 } else if (!strcmp(p, "mac")) {
553 char *p3 = p2 + 1;
554 *(p3 + 2) = '\0';
555 (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
556 p3 = p3 + 3;
557 *(p3 + 2) = '\0';
558 (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
559 p3 = p3 + 3;
560 *(p3 + 2) = '\0';
561 (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
562 p3 = p3 + 3;
563 *(p3 + 2) = '\0';
564 (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
565 p3 = p3 + 3;
566 *(p3 + 2) = '\0';
567 (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
568 p3 = p3 + 3;
569 *(p3 + 2) = '\0';
570 (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
571 } else if (!strcmp(p, "bridge")) {
572 (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
573 } else if (!strcmp(p, "type")) {
574 if (!strcmp(p2 + 1, "ioemu"))
575 (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
576 else
577 (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
578 } else if (!strcmp(p, "ip")) {
579 inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
580 } else if (!strcmp(p, "script")) {
581 (*vifs)[*num_vifs].script = strdup(p2 + 1);
582 } else if (!strcmp(p, "vifname")) {
583 (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
584 } else if (!strcmp(p, "rate")) {
585 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
586 } else if (!strcmp(p, "accel")) {
587 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
588 }
589 } while ((p = strtok(NULL, ",")) != NULL);
590 skip:
591 free(buf2);
592 *num_vifs = (*num_vifs) + 1;
593 }
594 }
596 if ((cvfbs = config_lookup (&config, "vfb")) != NULL) {
597 *num_vfbs = 0;
598 *num_vkbs = 0;
599 *vfbs = NULL;
600 *vkbs = NULL;
601 while ((buf = config_setting_get_string_elem (cvfbs, *num_vfbs)) != NULL) {
602 char *buf2 = strdup(buf);
603 char *p, *p2;
604 *vfbs = (libxl_device_vfb *) realloc(*vfbs, sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
605 init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
607 *vkbs = (libxl_device_vkb *) realloc(*vkbs, sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
608 init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
610 p = strtok(buf2, ",");
611 if (!p)
612 goto skip_vfb;
613 do {
614 while (*p == ' ')
615 p++;
616 if ((p2 = strchr(p, '=')) == NULL)
617 break;
618 *p2 = '\0';
619 if (!strcmp(p, "vnc")) {
620 (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
621 } else if (!strcmp(p, "vnclisten")) {
622 (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
623 } else if (!strcmp(p, "vncdisplay")) {
624 (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
625 } else if (!strcmp(p, "vncunused")) {
626 (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
627 } else if (!strcmp(p, "keymap")) {
628 (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
629 } else if (!strcmp(p, "sdl")) {
630 (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
631 } else if (!strcmp(p, "opengl")) {
632 (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
633 } else if (!strcmp(p, "display")) {
634 (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
635 } else if (!strcmp(p, "xauthority")) {
636 (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
637 }
638 } while ((p = strtok(NULL, ",")) != NULL);
639 skip_vfb:
640 free(buf2);
641 *num_vfbs = (*num_vfbs) + 1;
642 *num_vkbs = (*num_vkbs) + 1;
643 }
644 }
646 if (config_lookup_int (&config, "pci_msitranslate", &l) == CONFIG_TRUE)
647 pci_msitranslate = l;
649 if (config_lookup_int (&config, "pci_power_mgmt", &l) == CONFIG_TRUE)
650 pci_power_mgmt = l;
652 if ((pcis = config_lookup (&config, "pci")) != NULL) {
653 *num_pcidevs = 0;
654 *pcidevs = NULL;
655 while ((buf = config_setting_get_string_elem (pcis, *num_pcidevs)) != NULL) {
656 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
657 char *buf2 = strdup(buf);
658 char *p;
659 *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof (libxl_device_pci) * ((*num_pcidevs) + 1));
660 memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
661 p = strtok(buf2, ",");
662 if (!p)
663 goto skip_pci;
664 if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, &vdevfn)) {
665 sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
666 domain = 0;
667 }
668 libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, func, vdevfn);
669 (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
670 (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
671 while ((p = strtok(NULL, ",=")) != NULL) {
672 while (*p == ' ')
673 p++;
674 if (!strcmp(p, "msitranslate")) {
675 p = strtok(NULL, ",=");
676 (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
677 } else if (!strcmp(p, "power_mgmt")) {
678 p = strtok(NULL, ",=");
679 (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
680 }
681 }
682 *num_pcidevs = (*num_pcidevs) + 1;
683 skip_pci:
684 free(buf2);
685 }
686 }
688 if (c_info->hvm == 1) {
689 /* init dm from c and b */
690 init_dm_info(dm_info, c_info, b_info);
692 /* then process config related to dm */
693 if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
694 dm_info->device_model = strdup(buf);
695 if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
696 dm_info->stdvga = l;
697 if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
698 dm_info->vnc = l;
699 if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
700 dm_info->vnclisten = strdup(buf);
701 if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
702 dm_info->vncdisplay = l;
703 if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
704 dm_info->vncunused = l;
705 if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
706 dm_info->keymap = strdup(buf);
707 if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
708 dm_info->sdl = l;
709 if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
710 dm_info->opengl = l;
711 if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
712 dm_info->nographic = l;
713 if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
714 dm_info->serial = strdup(buf);
715 if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
716 dm_info->boot = strdup(buf);
717 if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
718 dm_info->usb = l;
719 if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
720 dm_info->usbdevice = strdup(buf);
721 }
723 config_destroy(&config);
724 }
726 #define MUST( call ) ({ \
727 int must_rc = (call); \
728 if (must_rc) { \
729 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \
730 __FILE__,__LINE__, must_rc, #call); \
731 exit(-must_rc); \
732 } \
733 })
735 static void create_domain(int debug, int daemonize, const char *config_file, const char *restore_file, int paused)
736 {
737 struct libxl_ctx ctx;
738 uint32_t domid;
739 libxl_domain_create_info info1;
740 libxl_domain_build_info info2;
741 libxl_domain_build_state state;
742 libxl_device_model_info dm_info;
743 libxl_device_disk *disks = NULL;
744 libxl_device_nic *vifs = NULL;
745 libxl_device_pci *pcidevs = NULL;
746 libxl_device_vfb *vfbs = NULL;
747 libxl_device_vkb *vkbs = NULL;
748 libxl_device_console console;
749 int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
750 int i, fd;
751 int need_daemon = 1;
752 int ret;
753 libxl_device_model_starting *dm_starting = 0;
754 libxl_waiter *w1 = NULL, *w2 = NULL;
755 memset(&dm_info, 0x00, sizeof(dm_info));
757 printf("Parsing config file %s\n", config_file);
758 parse_config_file(config_file, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
759 if (debug)
760 printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
762 start:
763 domid = 0;
765 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
766 fprintf(stderr, "cannot init xl context\n");
767 return;
768 }
770 libxl_ctx_set_log(&ctx, log_callback, NULL);
772 ret = libxl_domain_make(&ctx, &info1, &domid);
773 if (ret) {
774 fprintf(stderr, "cannot make domain: %d\n", ret);
775 return;
776 }
778 if (!restore_file || !need_daemon) {
779 if (dm_info.saved_state) {
780 free(dm_info.saved_state);
781 dm_info.saved_state = NULL;
782 }
783 ret = libxl_domain_build(&ctx, &info2, domid, &state);
784 } else {
785 int restore_fd;
787 restore_fd = open(restore_file, O_RDONLY);
788 ret = libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, &dm_info);
789 close(restore_fd);
790 }
792 if (ret) {
793 fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
794 return;
795 }
797 for (i = 0; i < num_disks; i++) {
798 disks[i].domid = domid;
799 ret = libxl_device_disk_add(&ctx, domid, &disks[i]);
800 if (ret) {
801 fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
802 return;
803 }
804 }
805 for (i = 0; i < num_vifs; i++) {
806 vifs[i].domid = domid;
807 ret = libxl_device_nic_add(&ctx, domid, &vifs[i]);
808 if (ret) {
809 fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
810 return;
811 }
812 }
813 if (info1.hvm) {
814 dm_info.domid = domid;
815 MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
816 vifs, num_vifs, &dm_starting) );
817 } else {
818 for (i = 0; i < num_vfbs; i++) {
819 vfbs[i].domid = domid;
820 libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
821 vkbs[i].domid = domid;
822 libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
823 }
824 init_console_info(&console, 0, &state);
825 console.domid = domid;
826 if (num_vfbs)
827 console.constype = CONSTYPE_IOEMU;
828 libxl_device_console_add(&ctx, domid, &console);
829 if (num_vfbs)
830 libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
831 }
833 if (dm_starting)
834 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
835 for (i = 0; i < num_pcidevs; i++)
836 libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
838 if (!paused)
839 libxl_domain_unpause(&ctx, domid);
841 if (!daemonize)
842 exit(0);
844 if (need_daemon) {
845 char *fullname, *name;
847 asprintf(&name, "xl-%s", info1.name);
848 libxl_create_logfile(&ctx, name, &fullname);
849 logfile = open(fullname, O_WRONLY|O_CREAT, 0644);
850 free(fullname);
851 free(name);
853 daemon(0, 0);
854 need_daemon = 0;
855 }
856 LOG("Waiting for domain %s (domid %d) to die", info1.name, domid);
857 w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
858 w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
859 libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
860 libxl_wait_for_domain_death(&ctx, domid, w2);
861 libxl_get_wait_fd(&ctx, &fd);
862 while (1) {
863 int ret;
864 fd_set rfds;
865 xc_domaininfo_t info;
866 libxl_event event;
867 libxl_device_disk disk;
868 memset(&info, 0x00, sizeof(xc_dominfo_t));
870 FD_ZERO(&rfds);
871 FD_SET(fd, &rfds);
873 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
874 if (!ret)
875 continue;
876 libxl_get_event(&ctx, &event);
877 switch (event.type) {
878 case DOMAIN_DEATH:
879 if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info)) {
880 LOG("Domain %d is dead", domid);
881 if (info.flags & XEN_DOMINF_dying || (info.flags & XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) {
882 LOG("Domain %d needs to be clean: destroying the domain", domid);
883 libxl_domain_destroy(&ctx, domid, 0);
884 if (info.flags & XEN_DOMINF_shutdown &&
885 (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) == SHUTDOWN_reboot)) {
886 libxl_free_waiter(w1);
887 libxl_free_waiter(w2);
888 free(w1);
889 free(w2);
890 libxl_ctx_free(&ctx);
891 LOG("Done. Rebooting now");
892 goto start;
893 }
894 LOG("Done. Exiting now");
895 }
896 LOG("Domain %d does not need to be clean, exiting now", domid);
897 exit(0);
898 }
899 break;
900 case DISK_EJECT:
901 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
902 libxl_cdrom_insert(&ctx, domid, &disk);
903 break;
904 }
905 libxl_free_event(&event);
906 }
908 close(logfile);
909 free(disks);
910 free(vifs);
911 free(vfbs);
912 free(vkbs);
913 free(pcidevs);
914 }
916 static void help(char *command)
917 {
918 if (!command || !strcmp(command, "help")) {
919 printf("Usage xl <subcommand> [args]\n\n");
920 printf("xl full list of subcommands:\n\n");
921 printf(" create create a domain from config file <filename>\n\n");
922 printf(" list list information about all domains\n\n");
923 printf(" destroy terminate a domain immediately\n\n");
924 printf(" pci-attach insert a new pass-through pci device\n\n");
925 printf(" pci-detach remove a domain's pass-through pci device\n\n");
926 printf(" pci-list list pass-through pci devices for a domain\n\n");
927 printf(" pause pause execution of a domain\n\n");
928 printf(" unpause unpause a paused domain\n\n");
929 printf(" console attach to domain's console\n\n");
930 printf(" save save a domain state to restore later\n\n");
931 printf(" restore restore a domain from a saved state\n\n");
932 printf(" cd-insert insert a cdrom into a guest's cd drive\n\n");
933 printf(" cd-eject eject a cdrom from a guest's cd drive\n\n");
934 printf(" mem-set set the current memory usage for a domain\n\n");
935 printf(" button-press indicate an ACPI button press to the domain\n\n");
936 } else if(!strcmp(command, "create")) {
937 printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
938 printf("Create a domain based on <ConfigFile>.\n\n");
939 printf("Options:\n\n");
940 printf("-h Print this help.\n");
941 printf("-d Enable debug messages.\n");
942 printf("-e Do not wait in the background for the death of the domain.\n");
943 } else if(!strcmp(command, "list")) {
944 printf("Usage: xl list [Domain]\n\n");
945 printf("List information about all/some domains.\n\n");
946 } else if(!strcmp(command, "pci-attach")) {
947 printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
948 printf("Insert a new pass-through pci device.\n\n");
949 } else if(!strcmp(command, "pci-detach")) {
950 printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
951 printf("Remove a domain's pass-through pci device.\n\n");
952 } else if(!strcmp(command, "pci-list")) {
953 printf("Usage: xl pci-list <Domain>\n\n");
954 printf("List pass-through pci devices for a domain.\n\n");
955 } else if(!strcmp(command, "pause")) {
956 printf("Usage: xl pause <Domain>\n\n");
957 printf("Pause execution of a domain.\n\n");
958 } else if(!strcmp(command, "unpause")) {
959 printf("Usage: xl unpause <Domain>\n\n");
960 printf("Unpause a paused domain.\n\n");
961 } else if(!strcmp(command, "save")) {
962 printf("Usage: xl save [options] <Domain> <CheckpointFile>\n\n");
963 printf("Save a domain state to restore later.\n\n");
964 printf("Options:\n\n");
965 printf("-h Print this help.\n");
966 printf("-c Leave domain running after creating the snapshot.\n");
967 } else if(!strcmp(command, "restore")) {
968 printf("Usage: xl restore [options] <ConfigFile> <CheckpointFile>\n\n");
969 printf("Restore a domain from a saved state.\n\n");
970 printf("Options:\n\n");
971 printf("-h Print this help.\n");
972 printf("-p Do not unpause domain after restoring it.\n");
973 printf("-e Do not wait in the background for the death of the domain.\n");
974 } else if(!strcmp(command, "destroy")) {
975 printf("Usage: xl destroy <Domain>\n\n");
976 printf("Terminate a domain immediately.\n\n");
977 } else if (!strcmp(command, "console")) {
978 printf("Usage: xl console <Domain>\n\n");
979 printf("Attach to domain's console.\n\n");
980 } else if (!strcmp(command, "cd-insert")) {
981 printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
982 printf("Insert a cdrom into a guest's cd drive.\n\n");
983 } else if (!strcmp(command, "cd-eject")) {
984 printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
985 printf("Eject a cdrom from a guest's cd drive.\n\n");
986 } else if (!strcmp(command, "mem-set")) {
987 printf("Usage: xl mem-set <Domain> <MemKB>\n\n");
988 printf("Set the current memory usage for a domain.\n\n");
989 } else if (!strcmp(command, "button-press")) {
990 printf("Usage: xl button-press <Domain> <Button>\n\n");
991 printf("Indicate <Button> press to a domain.\n");
992 printf("<Button> may be 'power' or 'sleep'.\n\n");
993 }
994 }
996 void set_memory_target(char *p, char *mem)
997 {
998 struct libxl_ctx ctx;
999 uint32_t domid;
1000 uint32_t memorykb;
1001 char *endptr;
1003 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1004 fprintf(stderr, "cannot init xl context\n");
1005 return;
1007 libxl_ctx_set_log(&ctx, log_callback, NULL);
1009 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1010 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1011 exit(2);
1013 memorykb = strtoul(mem, &endptr, 10);
1014 if (*endptr != '\0') {
1015 fprintf(stderr, "invalid memory size: %s\n", mem);
1016 exit(3);
1018 printf("setting domid %d memory to : %d\n", domid, memorykb);
1019 libxl_set_memory_target(&ctx, domid, memorykb);
1022 int main_memset(int argc, char **argv)
1024 int opt = 0;
1025 char *p = NULL, *mem;
1027 while ((opt = getopt(argc, argv, "h:")) != -1) {
1028 switch (opt) {
1029 case 'h':
1030 help("mem-set");
1031 exit(0);
1032 default:
1033 fprintf(stderr, "option not supported\n");
1034 break;
1037 if (optind >= argc - 1) {
1038 help("mem-set");
1039 exit(2);
1042 p = argv[optind];
1043 mem = argv[optind + 1];
1045 set_memory_target(p, mem);
1046 exit(0);
1049 void console(char *p, int cons_num)
1051 struct libxl_ctx ctx;
1052 uint32_t domid;
1054 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1055 fprintf(stderr, "cannot init xl context\n");
1056 return;
1058 libxl_ctx_set_log(&ctx, log_callback, NULL);
1060 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1061 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1062 exit(2);
1064 libxl_console_attach(&ctx, domid, cons_num);
1067 void cd_insert(char *dom, char *virtdev, char *phys)
1069 struct libxl_ctx ctx;
1070 uint32_t domid;
1071 libxl_device_disk disk;
1072 char *p;
1074 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1075 fprintf(stderr, "cannot init xl context\n");
1076 return;
1078 libxl_ctx_set_log(&ctx, log_callback, NULL);
1080 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1081 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1082 exit(2);
1085 disk.backend_domid = 0;
1086 disk.domid = domid;
1087 if (phys) {
1088 p = strchr(phys, ':');
1089 if (!p) {
1090 fprintf(stderr, "No type specified, ");
1091 disk.physpath = phys;
1092 if (!strncmp(phys, "/dev", 4)) {
1093 fprintf(stderr, "assuming phy:\n");
1094 disk.phystype = PHYSTYPE_PHY;
1095 } else {
1096 fprintf(stderr, "assuming file:\n");
1097 disk.phystype = PHYSTYPE_FILE;
1099 } else {
1100 *p = '\0';
1101 p++;
1102 disk.physpath = p;
1103 libxl_string_to_phystype(&ctx, phys, &disk.phystype);
1105 } else {
1106 disk.physpath = NULL;
1107 disk.phystype = 0;
1109 disk.virtpath = virtdev;
1110 disk.unpluggable = 1;
1111 disk.readwrite = 0;
1112 disk.is_cdrom = 1;
1114 libxl_cdrom_insert(&ctx, domid, &disk);
1117 int main_cd_eject(int argc, char **argv)
1119 int opt = 0;
1120 char *p = NULL, *virtdev;
1122 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1123 switch (opt) {
1124 case 'h':
1125 help("cd-eject");
1126 exit(0);
1127 default:
1128 fprintf(stderr, "option not supported\n");
1129 break;
1132 if (optind >= argc - 1) {
1133 help("cd-eject");
1134 exit(2);
1137 p = argv[optind];
1138 virtdev = argv[optind + 1];
1140 cd_insert(p, virtdev, NULL);
1141 exit(0);
1144 int main_cd_insert(int argc, char **argv)
1146 int opt = 0;
1147 char *p = NULL, *file = NULL, *virtdev;
1149 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1150 switch (opt) {
1151 case 'h':
1152 help("cd-insert");
1153 exit(0);
1154 default:
1155 fprintf(stderr, "option not supported\n");
1156 break;
1159 if (optind >= argc - 2) {
1160 help("cd-insert");
1161 exit(2);
1164 p = argv[optind];
1165 virtdev = argv[optind + 1];
1166 file = argv[optind + 2];
1168 cd_insert(p, virtdev, file);
1169 exit(0);
1172 int main_console(int argc, char **argv)
1174 int opt = 0, cons_num = 0;
1175 char *p = NULL;
1177 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1178 switch (opt) {
1179 case 'h':
1180 help("console");
1181 exit(0);
1182 case 'n':
1183 if (optarg) {
1184 cons_num = strtol(optarg, NULL, 10);
1186 break;
1187 default:
1188 fprintf(stderr, "option not supported\n");
1189 break;
1192 if (optind >= argc) {
1193 help("console");
1194 exit(2);
1197 p = argv[optind];
1199 console(p, cons_num);
1200 exit(0);
1203 void pcilist(char *dom)
1205 struct libxl_ctx ctx;
1206 uint32_t domid;
1207 libxl_device_pci *pcidevs;
1208 int num, i;
1210 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1211 fprintf(stderr, "cannot init xl context\n");
1212 return;
1214 libxl_ctx_set_log(&ctx, log_callback, NULL);
1216 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1217 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1218 exit(2);
1220 pcidevs = libxl_device_pci_list(&ctx, domid, &num);
1221 if (!num)
1222 return;
1223 printf("VFn domain bus slot func\n");
1224 for (i = 0; i < num; i++) {
1225 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);
1227 free(pcidevs);
1230 int main_pcilist(int argc, char **argv)
1232 int opt;
1233 char *domname = NULL;
1235 while ((opt = getopt(argc, argv, "h")) != -1) {
1236 switch (opt) {
1237 case 'h':
1238 help("pci-list");
1239 exit(0);
1240 default:
1241 fprintf(stderr, "option not supported\n");
1242 break;
1245 if (optind >= argc) {
1246 help("pci-list");
1247 exit(2);
1250 domname = argv[optind];
1252 pcilist(domname);
1253 exit(0);
1256 void pcidetach(char *dom, char *bdf)
1258 struct libxl_ctx ctx;
1259 uint32_t domid;
1260 libxl_device_pci pcidev;
1261 unsigned int domain, bus, dev, func;
1263 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1264 fprintf(stderr, "cannot init xl context\n");
1265 return;
1267 libxl_ctx_set_log(&ctx, log_callback, NULL);
1269 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1270 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1271 exit(2);
1273 memset(&pcidev, 0x00, sizeof(pcidev));
1274 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1275 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1276 libxl_device_pci_remove(&ctx, domid, &pcidev);
1279 int main_pcidetach(int argc, char **argv)
1281 int opt;
1282 char *domname = NULL, *bdf = NULL;
1284 while ((opt = getopt(argc, argv, "h")) != -1) {
1285 switch (opt) {
1286 case 'h':
1287 help("pci-attach");
1288 exit(0);
1289 default:
1290 fprintf(stderr, "option not supported\n");
1291 break;
1294 if (optind >= argc - 1) {
1295 help("pci-detach");
1296 exit(2);
1299 domname = argv[optind];
1300 bdf = argv[optind + 1];
1302 pcidetach(domname, bdf);
1303 exit(0);
1305 void pciattach(char *dom, char *bdf, char *vs)
1307 struct libxl_ctx ctx;
1308 uint32_t domid;
1309 libxl_device_pci pcidev;
1310 unsigned int domain, bus, dev, func;
1312 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1313 fprintf(stderr, "cannot init xl context\n");
1314 return;
1316 libxl_ctx_set_log(&ctx, log_callback, NULL);
1318 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1319 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1320 exit(2);
1322 memset(&pcidev, 0x00, sizeof(pcidev));
1323 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1324 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1325 libxl_device_pci_add(&ctx, domid, &pcidev);
1328 int main_pciattach(int argc, char **argv)
1330 int opt;
1331 char *domname = NULL, *bdf = NULL, *vs = NULL;
1333 while ((opt = getopt(argc, argv, "h")) != -1) {
1334 switch (opt) {
1335 case 'h':
1336 help("pci-attach");
1337 exit(0);
1338 default:
1339 fprintf(stderr, "option not supported\n");
1340 break;
1343 if (optind >= argc - 1) {
1344 help("pci-attach");
1345 exit(2);
1348 domname = argv[optind];
1349 bdf = argv[optind + 1];
1351 if (optind + 1 < argc)
1352 vs = argv[optind + 2];
1354 pciattach(domname, bdf, vs);
1355 exit(0);
1358 void pause_domain(char *p)
1360 struct libxl_ctx ctx;
1361 uint32_t domid;
1363 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1364 fprintf(stderr, "cannot init xl context\n");
1365 return;
1367 libxl_ctx_set_log(&ctx, log_callback, NULL);
1369 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1370 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1371 exit(2);
1373 libxl_domain_pause(&ctx, domid);
1376 void unpause_domain(char *p)
1378 struct libxl_ctx ctx;
1379 uint32_t domid;
1381 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1382 fprintf(stderr, "cannot init xl context\n");
1383 return;
1385 libxl_ctx_set_log(&ctx, log_callback, NULL);
1387 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1388 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1389 exit(2);
1391 libxl_domain_unpause(&ctx, domid);
1394 void destroy_domain(char *p)
1396 struct libxl_ctx ctx;
1397 uint32_t domid;
1399 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1400 fprintf(stderr, "cannot init xl context\n");
1401 return;
1403 libxl_ctx_set_log(&ctx, log_callback, NULL);
1405 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1406 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1407 exit(2);
1409 libxl_domain_destroy(&ctx, domid, 0);
1412 void list_domains(void)
1414 struct libxl_ctx ctx;
1415 struct libxl_dominfo *info;
1416 int nb_domain, i;
1418 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1419 fprintf(stderr, "cannot init xl context\n");
1420 return;
1422 libxl_ctx_set_log(&ctx, log_callback, NULL);
1424 info = libxl_list_domain(&ctx, &nb_domain);
1426 if (info < 0) {
1427 fprintf(stderr, "libxl_domain_infolist failed.\n");
1428 exit(1);
1430 printf("Name ID Mem VCPUs\tState\tTime(s)\n");
1431 for (i = 0; i < nb_domain; i++) {
1432 printf("%-40s %5d %5lu %5d %c%c%c %8.1f\n",
1433 libxl_domid_to_name(&ctx, info[i].domid),
1434 info[i].domid,
1435 (unsigned long) (info[i].max_memkb / 1024),
1436 info[i].vcpu_online,
1437 info[i].running ? 'r' : '-',
1438 info[i].paused ? 'p' : '-',
1439 info[i].dying ? 'd' : '-',
1440 ((float)info[i].cpu_time / 1e9));
1442 free(info);
1445 void list_vm(void)
1447 struct libxl_ctx ctx;
1448 struct libxl_vminfo *info;
1449 int nb_vm, i;
1451 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1452 fprintf(stderr, "cannot init xl context\n");
1453 return;
1455 libxl_ctx_set_log(&ctx, log_callback, NULL);
1457 info = libxl_list_vm(&ctx, &nb_vm);
1459 if (info < 0) {
1460 fprintf(stderr, "libxl_domain_infolist failed.\n");
1461 exit(1);
1463 printf("UUID ID name\n");
1464 for (i = 0; i < nb_vm; i++) {
1465 printf(UUID_FMT " %d %-30s\n",
1466 info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
1467 info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
1468 info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], info[i].uuid[11],
1469 info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], info[i].uuid[15],
1470 info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
1472 free(info);
1475 int save_domain(char *p, char *filename, int checkpoint)
1477 struct libxl_ctx ctx;
1478 uint32_t domid;
1479 int fd;
1481 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1482 fprintf(stderr, "cannot init xl context\n");
1483 exit(2);
1485 libxl_ctx_set_log(&ctx, log_callback, NULL);
1487 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1488 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1489 exit(2);
1491 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1492 if (fd < 0) {
1493 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
1494 exit(2);
1496 libxl_domain_suspend(&ctx, NULL, domid, fd);
1497 close(fd);
1499 if (checkpoint)
1500 libxl_domain_unpause(&ctx, domid);
1501 else
1502 libxl_domain_destroy(&ctx, domid, 0);
1504 exit(0);
1507 int main_restore(int argc, char **argv)
1509 char *checkpoint_file = NULL;
1510 char *config_file = NULL;
1511 int paused = 0, debug = 0, daemonize = 1;
1512 int opt;
1514 while ((opt = getopt(argc, argv, "hpde")) != -1) {
1515 switch (opt) {
1516 case 'p':
1517 paused = 1;
1518 break;
1519 case 'd':
1520 debug = 1;
1521 break;
1522 case 'e':
1523 daemonize = 0;
1524 break;
1525 case 'h':
1526 help("restore");
1527 exit(0);
1528 default:
1529 fprintf(stderr, "option not supported\n");
1530 break;
1534 if (optind >= argc - 1) {
1535 help("restore");
1536 exit(2);
1539 config_file = argv[optind];
1540 checkpoint_file = argv[optind + 1];
1541 create_domain(debug, daemonize, config_file, checkpoint_file, paused);
1542 exit(0);
1545 int main_save(int argc, char **argv)
1547 char *filename = NULL, *p = NULL;
1548 int checkpoint = 0;
1549 int opt;
1551 while ((opt = getopt(argc, argv, "hc")) != -1) {
1552 switch (opt) {
1553 case 'c':
1554 checkpoint = 1;
1555 break;
1556 case 'h':
1557 help("save");
1558 exit(0);
1559 default:
1560 fprintf(stderr, "option not supported\n");
1561 break;
1565 if (optind >= argc - 1) {
1566 help("save");
1567 exit(2);
1570 p = argv[optind];
1571 filename = argv[optind + 1];
1572 save_domain(p, filename, checkpoint);
1573 exit(0);
1576 int main_pause(int argc, char **argv)
1578 int opt;
1579 char *p;
1582 while ((opt = getopt(argc, argv, "h")) != -1) {
1583 switch (opt) {
1584 case 'h':
1585 help("pause");
1586 exit(0);
1587 default:
1588 fprintf(stderr, "option not supported\n");
1589 break;
1592 if (optind >= argc) {
1593 help("pause");
1594 exit(2);
1597 p = argv[optind];
1599 pause_domain(p);
1600 exit(0);
1603 int main_unpause(int argc, char **argv)
1605 int opt;
1606 char *p;
1609 while ((opt = getopt(argc, argv, "h")) != -1) {
1610 switch (opt) {
1611 case 'h':
1612 help("unpause");
1613 exit(0);
1614 default:
1615 fprintf(stderr, "option not supported\n");
1616 break;
1619 if (optind >= argc) {
1620 help("unpause");
1621 exit(2);
1624 p = argv[optind];
1626 unpause_domain(p);
1627 exit(0);
1630 int main_destroy(int argc, char **argv)
1632 int opt;
1633 char *p;
1635 while ((opt = getopt(argc, argv, "h")) != -1) {
1636 switch (opt) {
1637 case 'h':
1638 help("destroy");
1639 exit(0);
1640 default:
1641 fprintf(stderr, "option not supported\n");
1642 break;
1645 if (optind >= argc) {
1646 help("destroy");
1647 exit(2);
1650 p = argv[optind];
1652 destroy_domain(p);
1653 exit(0);
1656 int main_list(int argc, char **argv)
1658 int opt;
1660 while ((opt = getopt(argc, argv, "h")) != -1) {
1661 switch (opt) {
1662 case 'h':
1663 help("list");
1664 exit(0);
1665 default:
1666 fprintf(stderr, "option not supported\n");
1667 break;
1671 list_domains();
1672 exit(0);
1675 int main_list_vm(int argc, char **argv)
1677 int opt;
1679 while ((opt = getopt(argc, argv, "h")) != -1) {
1680 switch (opt) {
1681 case 'h':
1682 help("list-vm");
1683 exit(0);
1684 default:
1685 fprintf(stderr, "option not supported\n");
1686 break;
1690 list_vm();
1691 exit(0);
1694 int main_create(int argc, char **argv)
1696 char *filename = NULL;
1697 int debug = 0, daemonize = 1;
1698 int opt;
1700 while ((opt = getopt(argc, argv, "hde")) != -1) {
1701 switch (opt) {
1702 case 'd':
1703 debug = 1;
1704 break;
1705 case 'e':
1706 daemonize = 0;
1707 break;
1708 case 'h':
1709 help("create");
1710 exit(0);
1711 default:
1712 fprintf(stderr, "option not supported\n");
1713 break;
1717 if (optind >= argc) {
1718 help("create");
1719 exit(2);
1722 filename = argv[optind];
1723 create_domain(debug, daemonize, filename, NULL, 0);
1724 exit(0);
1727 void button_press(char *p, char *b)
1729 struct libxl_ctx ctx;
1730 uint32_t domid;
1731 libxl_button button;
1733 libxl_ctx_init(&ctx, LIBXL_VERSION);
1734 libxl_ctx_set_log(&ctx, log_callback, NULL);
1736 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1737 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1738 exit(2);
1741 if (!strcmp(b, "power")) {
1742 button = POWER_BUTTON;
1743 } else if (!strcmp(b, "sleep")) {
1744 button = SLEEP_BUTTON;
1745 } else {
1746 fprintf(stderr, "%s is an invalid button identifier\n", b);
1747 exit(2);
1750 libxl_button_press(&ctx, domid, button);
1753 int main_button_press(int argc, char **argv)
1755 int opt;
1756 char *p;
1757 char *b;
1759 while ((opt = getopt(argc, argv, "h")) != -1) {
1760 switch (opt) {
1761 case 'h':
1762 help("button-press");
1763 exit(0);
1764 default:
1765 fprintf(stderr, "option not supported\n");
1766 break;
1769 if (optind >= argc - 1) {
1770 help("button-press");
1771 exit(2);
1774 p = argv[optind];
1775 b = argv[optind + 1];
1777 button_press(p, b);
1778 exit(0);
1781 int main(int argc, char **argv)
1783 if (argc < 2) {
1784 help(NULL);
1785 exit(1);
1788 srand(time(0));
1790 if (!strcmp(argv[1], "create")) {
1791 main_create(argc - 1, argv + 1);
1792 } else if (!strcmp(argv[1], "list")) {
1793 main_list(argc - 1, argv + 1);
1794 } else if (!strcmp(argv[1], "list-vm")) {
1795 main_list_vm(argc - 1, argv + 1);
1796 } else if (!strcmp(argv[1], "destroy")) {
1797 main_destroy(argc - 1, argv + 1);
1798 } else if (!strcmp(argv[1], "pci-attach")) {
1799 main_pciattach(argc - 1, argv + 1);
1800 } else if (!strcmp(argv[1], "pci-detach")) {
1801 main_pcidetach(argc - 1, argv + 1);
1802 } else if (!strcmp(argv[1], "pci-list")) {
1803 main_pcilist(argc - 1, argv + 1);
1804 } else if (!strcmp(argv[1], "pause")) {
1805 main_pause(argc - 1, argv + 1);
1806 } else if (!strcmp(argv[1], "unpause")) {
1807 main_unpause(argc - 1, argv + 1);
1808 } else if (!strcmp(argv[1], "console")) {
1809 main_console(argc - 1, argv + 1);
1810 } else if (!strcmp(argv[1], "save")) {
1811 main_save(argc - 1, argv + 1);
1812 } else if (!strcmp(argv[1], "restore")) {
1813 main_restore(argc - 1, argv + 1);
1814 } else if (!strcmp(argv[1], "cd-insert")) {
1815 main_cd_insert(argc - 1, argv + 1);
1816 } else if (!strcmp(argv[1], "cd-eject")) {
1817 main_cd_eject(argc - 1, argv + 1);
1818 } else if (!strcmp(argv[1], "mem-set")) {
1819 main_memset(argc - 1, argv + 1);
1820 } else if (!strcmp(argv[1], "button-press")) {
1821 main_button_press(argc - 1, argv + 1);
1822 } else if (!strcmp(argv[1], "help")) {
1823 if (argc > 2)
1824 help(argv[2]);
1825 else
1826 help(NULL);
1827 exit(0);
1828 } else {
1829 fprintf(stderr, "command not implemented\n");
1830 exit(1);