debuggers.hg

view tools/libxl/xl.c @ 20861:ff2d29e6ab9c

libxenlight: add a list-vm options to xl that only list vms uuid, domid, name

Signed-off-by: Vincent Hanquez <vincent.hanquez@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Sun Jan 17 18:05:32 2010 +0000 (2010-01-17)
parents abc717dc6c2a
children d7e8b6a66a3d
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 fgets(buf, size, s);
348 while (buf[strlen(buf) - 1] != '\n' && !feof(s)) {
349 size += 1024;
350 buf = realloc(buf, size + 1024);
351 fgets(buf + (size - 1025), 1025, s);
352 }
353 for (i = 0; i < strlen(buf); i++)
354 if (buf[i] == '\'')
355 buf[i] = '\"';
356 if (strchr(buf, '=') != NULL) {
357 if ((buf[strlen(buf) - 1] == '\n' && buf[strlen(buf) - 2] == ';') ||
358 buf[strlen(buf) - 1] == ';') {
359 fputs(buf, d);
360 } else {
361 t = buf[strlen(buf) - 1];
362 buf[strlen(buf) - 1] = ';';
363 fputs(buf, d);
364 fputc(t, d);
365 }
366 } else if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') {
367 fputs(buf, d);
368 }
369 }
371 fclose(s);
372 fclose(d);
374 free(buf);
376 return newfile;
377 }
379 static void parse_config_file(const char *filename,
380 libxl_domain_create_info *c_info,
381 libxl_domain_build_info *b_info,
382 libxl_device_disk **disks,
383 int *num_disks,
384 libxl_device_nic **vifs,
385 int *num_vifs,
386 libxl_device_pci **pcidevs,
387 int *num_pcidevs,
388 libxl_device_vfb **vfbs,
389 int *num_vfbs,
390 libxl_device_vkb **vkbs,
391 int *num_vkbs,
392 libxl_device_model_info *dm_info)
393 {
394 const char *buf;
395 long l;
396 struct config_t config;
397 struct config_setting_t *vbds, *nics, *pcis, *cvfbs;
398 int pci_power_mgmt = 0;
399 int pci_msitranslate = 1;
400 int i;
402 config_init (&config);
404 if (!config_read_file(&config, filename)) {
405 char *newfilename;
406 config_destroy(&config);
407 newfilename = compat_config_file(filename);
408 config_init (&config);
409 if (!config_read_file(&config, newfilename)) {
410 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));
411 exit(1);
412 }
413 free(newfilename);
414 }
416 init_create_info(c_info);
418 c_info->hvm = 0;
419 if ((config_lookup_string (&config, "builder", &buf) == CONFIG_TRUE) &&
420 !strncmp(buf, "hvm", strlen(buf)))
421 c_info->hvm = 1;
423 /* hap is missing */
424 if (config_lookup_string (&config, "name", &buf) == CONFIG_TRUE)
425 c_info->name = strdup(buf);
426 else
427 c_info->name = "test";
428 for (i = 0; i < 16; i++) {
429 c_info->uuid[i] = rand();
430 }
432 init_build_info(b_info, c_info);
434 /* the following is the actual config parsing with overriding values in the structures */
435 if (config_lookup_int (&config, "vcpus", &l) == CONFIG_TRUE)
436 b_info->max_vcpus = l;
438 if (config_lookup_int (&config, "memory", &l) == CONFIG_TRUE) {
439 b_info->max_memkb = l * 1024;
440 b_info->target_memkb = b_info->max_memkb;
441 }
443 if (config_lookup_int (&config, "shadow_memory", &l) == CONFIG_TRUE)
444 b_info->shadow_memkb = l * 1024;
446 if (config_lookup_int (&config, "videoram", &l) == CONFIG_TRUE)
447 b_info->video_memkb = l * 1024;
449 if (config_lookup_string (&config, "kernel", &buf) == CONFIG_TRUE)
450 b_info->kernel = strdup(buf);
452 if (c_info->hvm == 1) {
453 if (config_lookup_int (&config, "pae", &l) == CONFIG_TRUE)
454 b_info->u.hvm.pae = l;
455 if (config_lookup_int (&config, "apic", &l) == CONFIG_TRUE)
456 b_info->u.hvm.apic = l;
457 if (config_lookup_int (&config, "acpi", &l) == CONFIG_TRUE)
458 b_info->u.hvm.acpi = l;
459 if (config_lookup_int (&config, "nx", &l) == CONFIG_TRUE)
460 b_info->u.hvm.nx = l;
461 if (config_lookup_int (&config, "viridian", &l) == CONFIG_TRUE)
462 b_info->u.hvm.viridian = l;
463 } else {
464 char *cmdline;
465 if (config_lookup_string (&config, "root", &buf) == CONFIG_TRUE) {
466 asprintf(&cmdline, "root=%s", buf);
467 b_info->u.pv.cmdline = cmdline;
468 }
469 if (config_lookup_string (&config, "ramdisk", &buf) == CONFIG_TRUE)
470 b_info->u.pv.ramdisk = strdup(buf);
471 }
473 if ((vbds = config_lookup (&config, "disk")) != NULL) {
474 *num_disks = 0;
475 *disks = NULL;
476 while ((buf = config_setting_get_string_elem (vbds, *num_disks)) != NULL) {
477 char *buf2 = strdup(buf);
478 char *p, *p2;
479 *disks = (libxl_device_disk *) realloc(*disks, sizeof (libxl_device_disk) * ((*num_disks) + 1));
480 (*disks)[*num_disks].backend_domid = 0;
481 (*disks)[*num_disks].domid = 0;
482 (*disks)[*num_disks].unpluggable = 0;
483 p = strtok(buf2, ",:");
484 while (*p == ' ')
485 p++;
486 if (!strcmp(p, "phy")) {
487 (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
488 } else if (!strcmp(p, "file")) {
489 (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
490 } else if (!strcmp(p, "tap")) {
491 p = strtok(NULL, ":");
492 if (!strcmp(p, "aio")) {
493 (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
494 } else if (!strcmp(p, "vhd")) {
495 (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
496 } else if (!strcmp(p, "qcow")) {
497 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
498 } else if (!strcmp(p, "qcow2")) {
499 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
500 }
501 }
502 p = strtok(NULL, ",");
503 while (*p == ' ')
504 p++;
505 (*disks)[*num_disks].physpath= strdup(p);
506 p = strtok(NULL, ",");
507 while (*p == ' ')
508 p++;
509 p2 = strchr(p, ':');
510 if (p2 == NULL) {
511 (*disks)[*num_disks].virtpath = strdup(p);
512 (*disks)[*num_disks].is_cdrom = 0;
513 (*disks)[*num_disks].unpluggable = 1;
514 } else {
515 *p2 = '\0';
516 (*disks)[*num_disks].virtpath = strdup(p);
517 if (!strcmp(p2 + 1, "cdrom")) {
518 (*disks)[*num_disks].is_cdrom = 1;
519 (*disks)[*num_disks].unpluggable = 1;
520 } else
521 (*disks)[*num_disks].is_cdrom = 0;
522 }
523 p = strtok(NULL, ",");
524 while (*p == ' ')
525 p++;
526 (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
527 free(buf2);
528 *num_disks = (*num_disks) + 1;
529 }
530 }
532 if ((nics = config_lookup (&config, "vif")) != NULL) {
533 *num_vifs = 0;
534 *vifs = NULL;
535 while ((buf = config_setting_get_string_elem (nics, *num_vifs)) != NULL) {
536 char *buf2 = strdup(buf);
537 char *p, *p2;
538 *vifs = (libxl_device_nic *) realloc(*vifs, sizeof (libxl_device_nic) * ((*num_vifs) + 1));
539 init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
540 p = strtok(buf2, ",");
541 if (!p)
542 goto skip;
543 do {
544 while (*p == ' ')
545 p++;
546 if ((p2 = strchr(p, '=')) == NULL)
547 break;
548 *p2 = '\0';
549 if (!strcmp(p, "model")) {
550 (*vifs)[*num_vifs].model = strdup(p2 + 1);
551 } else if (!strcmp(p, "mac")) {
552 char *p3 = p2 + 1;
553 *(p3 + 2) = '\0';
554 (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
555 p3 = p3 + 3;
556 *(p3 + 2) = '\0';
557 (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
558 p3 = p3 + 3;
559 *(p3 + 2) = '\0';
560 (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
561 p3 = p3 + 3;
562 *(p3 + 2) = '\0';
563 (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
564 p3 = p3 + 3;
565 *(p3 + 2) = '\0';
566 (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
567 p3 = p3 + 3;
568 *(p3 + 2) = '\0';
569 (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
570 } else if (!strcmp(p, "bridge")) {
571 (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
572 } else if (!strcmp(p, "type")) {
573 if (!strcmp(p2 + 1, "ioemu"))
574 (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
575 else
576 (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
577 } else if (!strcmp(p, "ip")) {
578 inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
579 } else if (!strcmp(p, "script")) {
580 (*vifs)[*num_vifs].script = strdup(p2 + 1);
581 } else if (!strcmp(p, "vifname")) {
582 (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
583 } else if (!strcmp(p, "rate")) {
584 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
585 } else if (!strcmp(p, "accel")) {
586 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
587 }
588 } while ((p = strtok(NULL, ",")) != NULL);
589 skip:
590 free(buf2);
591 *num_vifs = (*num_vifs) + 1;
592 }
593 }
595 if ((cvfbs = config_lookup (&config, "vfb")) != NULL) {
596 *num_vfbs = 0;
597 *num_vkbs = 0;
598 *vfbs = NULL;
599 *vkbs = NULL;
600 while ((buf = config_setting_get_string_elem (cvfbs, *num_vfbs)) != NULL) {
601 char *buf2 = strdup(buf);
602 char *p, *p2;
603 *vfbs = (libxl_device_vfb *) realloc(*vfbs, sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
604 init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
606 *vkbs = (libxl_device_vkb *) realloc(*vkbs, sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
607 init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
609 p = strtok(buf2, ",");
610 if (!p)
611 goto skip_vfb;
612 do {
613 while (*p == ' ')
614 p++;
615 if ((p2 = strchr(p, '=')) == NULL)
616 break;
617 *p2 = '\0';
618 if (!strcmp(p, "vnc")) {
619 (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
620 } else if (!strcmp(p, "vnclisten")) {
621 (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
622 } else if (!strcmp(p, "vncdisplay")) {
623 (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
624 } else if (!strcmp(p, "vncunused")) {
625 (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
626 } else if (!strcmp(p, "keymap")) {
627 (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
628 } else if (!strcmp(p, "sdl")) {
629 (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
630 } else if (!strcmp(p, "opengl")) {
631 (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
632 } else if (!strcmp(p, "display")) {
633 (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
634 } else if (!strcmp(p, "xauthority")) {
635 (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
636 }
637 } while ((p = strtok(NULL, ",")) != NULL);
638 skip_vfb:
639 free(buf2);
640 *num_vfbs = (*num_vfbs) + 1;
641 *num_vkbs = (*num_vkbs) + 1;
642 }
643 }
645 if (config_lookup_int (&config, "pci_msitranslate", &l) == CONFIG_TRUE)
646 pci_msitranslate = l;
648 if (config_lookup_int (&config, "pci_power_mgmt", &l) == CONFIG_TRUE)
649 pci_power_mgmt = l;
651 if ((pcis = config_lookup (&config, "pci")) != NULL) {
652 *num_pcidevs = 0;
653 *pcidevs = NULL;
654 while ((buf = config_setting_get_string_elem (pcis, *num_pcidevs)) != NULL) {
655 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
656 char *buf2 = strdup(buf);
657 char *p;
658 *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof (libxl_device_pci) * ((*num_pcidevs) + 1));
659 memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
660 p = strtok(buf2, ",");
661 if (!p)
662 goto skip_pci;
663 if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, &vdevfn)) {
664 sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
665 domain = 0;
666 }
667 libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, func, vdevfn);
668 (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
669 (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
670 while ((p = strtok(NULL, ",=")) != NULL) {
671 while (*p == ' ')
672 p++;
673 if (!strcmp(p, "msitranslate")) {
674 p = strtok(NULL, ",=");
675 (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
676 } else if (!strcmp(p, "power_mgmt")) {
677 p = strtok(NULL, ",=");
678 (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
679 }
680 }
681 *num_pcidevs = (*num_pcidevs) + 1;
682 skip_pci:
683 free(buf2);
684 }
685 }
687 if (c_info->hvm == 1) {
688 /* init dm from c and b */
689 init_dm_info(dm_info, c_info, b_info);
691 /* then process config related to dm */
692 if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
693 dm_info->device_model = strdup(buf);
694 if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
695 dm_info->stdvga = l;
696 if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
697 dm_info->vnc = l;
698 if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
699 dm_info->vnclisten = strdup(buf);
700 if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
701 dm_info->vncdisplay = l;
702 if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
703 dm_info->vncunused = l;
704 if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
705 dm_info->keymap = strdup(buf);
706 if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
707 dm_info->sdl = l;
708 if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
709 dm_info->opengl = l;
710 if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
711 dm_info->nographic = l;
712 if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
713 dm_info->serial = strdup(buf);
714 if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
715 dm_info->boot = strdup(buf);
716 if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
717 dm_info->usb = l;
718 if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
719 dm_info->usbdevice = strdup(buf);
720 }
722 config_destroy(&config);
723 }
725 #define MUST( call ) ({ \
726 int must_rc = (call); \
727 if (must_rc) { \
728 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \
729 __FILE__,__LINE__, must_rc, #call); \
730 exit(-must_rc); \
731 } \
732 })
734 static void create_domain(int debug, int daemonize, const char *config_file, const char *restore_file, int paused)
735 {
736 struct libxl_ctx ctx;
737 uint32_t domid;
738 libxl_domain_create_info info1;
739 libxl_domain_build_info info2;
740 libxl_domain_build_state state;
741 libxl_device_model_info dm_info;
742 libxl_device_disk *disks = NULL;
743 libxl_device_nic *vifs = NULL;
744 libxl_device_pci *pcidevs = NULL;
745 libxl_device_vfb *vfbs = NULL;
746 libxl_device_vkb *vkbs = NULL;
747 libxl_device_console console;
748 int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
749 int i, fd;
750 int need_daemon = 1;
751 int ret;
752 libxl_device_model_starting *dm_starting = 0;
753 libxl_waiter *w1 = NULL, *w2 = NULL;
754 memset(&dm_info, 0x00, sizeof(dm_info));
756 printf("Parsing config file %s\n", config_file);
757 parse_config_file(config_file, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
758 if (debug)
759 printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
761 start:
762 domid = 0;
764 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
765 fprintf(stderr, "cannot init xl context\n");
766 return;
767 }
769 libxl_ctx_set_log(&ctx, log_callback, NULL);
771 ret = libxl_domain_make(&ctx, &info1, &domid);
772 if (ret) {
773 fprintf(stderr, "cannot make domain: %d\n", ret);
774 return;
775 }
777 if (!restore_file || !need_daemon) {
778 if (dm_info.saved_state) {
779 free(dm_info.saved_state);
780 dm_info.saved_state = NULL;
781 }
782 ret = libxl_domain_build(&ctx, &info2, domid, &state);
783 } else {
784 int restore_fd;
786 restore_fd = open(restore_file, O_RDONLY);
787 ret = libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, &dm_info);
788 close(restore_fd);
789 }
791 if (ret) {
792 fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
793 return;
794 }
796 for (i = 0; i < num_disks; i++) {
797 disks[i].domid = domid;
798 ret = libxl_device_disk_add(&ctx, domid, &disks[i]);
799 if (ret) {
800 fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
801 return;
802 }
803 }
804 for (i = 0; i < num_vifs; i++) {
805 vifs[i].domid = domid;
806 ret = libxl_device_nic_add(&ctx, domid, &vifs[i]);
807 if (ret) {
808 fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
809 return;
810 }
811 }
812 if (info1.hvm) {
813 dm_info.domid = domid;
814 MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
815 vifs, num_vifs, &dm_starting) );
816 } else {
817 for (i = 0; i < num_vfbs; i++) {
818 vfbs[i].domid = domid;
819 libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
820 vkbs[i].domid = domid;
821 libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
822 }
823 init_console_info(&console, 0, &state);
824 console.domid = domid;
825 if (num_vfbs)
826 console.constype = CONSTYPE_IOEMU;
827 libxl_device_console_add(&ctx, domid, &console);
828 if (num_vfbs)
829 libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
830 }
832 if (dm_starting)
833 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
834 for (i = 0; i < num_pcidevs; i++)
835 libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
837 if (!paused)
838 libxl_domain_unpause(&ctx, domid);
840 if (!daemonize)
841 exit(0);
843 if (need_daemon) {
844 char *fullname, *name;
846 asprintf(&name, "xl-%s", info1.name);
847 libxl_create_logfile(&ctx, name, &fullname);
848 logfile = open(fullname, O_WRONLY|O_CREAT, 0644);
849 free(fullname);
850 free(name);
852 daemon(0, 0);
853 need_daemon = 0;
854 }
855 LOG("Waiting for domain %s (domid %d) to die", info1.name, domid);
856 w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
857 w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
858 libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
859 libxl_wait_for_domain_death(&ctx, domid, w2);
860 libxl_get_wait_fd(&ctx, &fd);
861 while (1) {
862 int ret;
863 fd_set rfds;
864 xc_domaininfo_t info;
865 libxl_event event;
866 libxl_device_disk disk;
867 memset(&info, 0x00, sizeof(xc_dominfo_t));
869 FD_ZERO(&rfds);
870 FD_SET(fd, &rfds);
872 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
873 if (!ret)
874 continue;
875 libxl_get_event(&ctx, &event);
876 switch (event.type) {
877 case DOMAIN_DEATH:
878 if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info)) {
879 LOG("Domain %d is dead", domid);
880 if (info.flags & XEN_DOMINF_dying || (info.flags & XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) {
881 LOG("Domain %d needs to be clean: destroying the domain", domid);
882 libxl_domain_destroy(&ctx, domid, 0);
883 if (info.flags & XEN_DOMINF_shutdown &&
884 (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) == SHUTDOWN_reboot)) {
885 libxl_free_waiter(w1);
886 libxl_free_waiter(w2);
887 free(w1);
888 free(w2);
889 libxl_ctx_free(&ctx);
890 LOG("Done. Rebooting now");
891 goto start;
892 }
893 LOG("Done. Exiting now");
894 }
895 LOG("Domain %d does not need to be clean, exiting now", domid);
896 exit(0);
897 }
898 break;
899 case DISK_EJECT:
900 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
901 libxl_cdrom_insert(&ctx, domid, &disk);
902 break;
903 }
904 libxl_free_event(&event);
905 }
907 close(logfile);
908 free(disks);
909 free(vifs);
910 free(vfbs);
911 free(vkbs);
912 free(pcidevs);
913 }
915 static void help(char *command)
916 {
917 if (!command || !strcmp(command, "help")) {
918 printf("Usage xl <subcommand> [args]\n\n");
919 printf("xl full list of subcommands:\n\n");
920 printf(" create create a domain from config file <filename>\n\n");
921 printf(" list list information about all domains\n\n");
922 printf(" destroy terminate a domain immediately\n\n");
923 printf(" pci-attach insert a new pass-through pci device\n\n");
924 printf(" pci-detach remove a domain's pass-through pci device\n\n");
925 printf(" pci-list list pass-through pci devices for a domain\n\n");
926 printf(" pause pause execution of a domain\n\n");
927 printf(" unpause unpause a paused domain\n\n");
928 printf(" console attach to domain's console\n\n");
929 printf(" save save a domain state to restore later\n\n");
930 printf(" restore restore a domain from a saved state\n\n");
931 printf(" cd-insert insert a cdrom into a guest's cd drive\n\n");
932 printf(" cd-eject eject a cdrom from a guest's cd drive\n\n");
933 printf(" mem-set set the current memory usage for a domain\n\n");
934 } else if(!strcmp(command, "create")) {
935 printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
936 printf("Create a domain based on <ConfigFile>.\n\n");
937 printf("Options:\n\n");
938 printf("-h Print this help.\n");
939 printf("-d Enable debug messages.\n");
940 printf("-e Do not wait in the background for the death of the domain.\n");
941 } else if(!strcmp(command, "list")) {
942 printf("Usage: xl list [Domain]\n\n");
943 printf("List information about all/some domains.\n\n");
944 } else if(!strcmp(command, "pci-attach")) {
945 printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
946 printf("Insert a new pass-through pci device.\n\n");
947 } else if(!strcmp(command, "pci-detach")) {
948 printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
949 printf("Remove a domain's pass-through pci device.\n\n");
950 } else if(!strcmp(command, "pci-list")) {
951 printf("Usage: xl pci-list <Domain>\n\n");
952 printf("List pass-through pci devices for a domain.\n\n");
953 } else if(!strcmp(command, "pause")) {
954 printf("Usage: xl pause <Domain>\n\n");
955 printf("Pause execution of a domain.\n\n");
956 } else if(!strcmp(command, "unpause")) {
957 printf("Usage: xl unpause <Domain>\n\n");
958 printf("Unpause a paused domain.\n\n");
959 } else if(!strcmp(command, "save")) {
960 printf("Usage: xl save [options] <Domain> <CheckpointFile>\n\n");
961 printf("Save a domain state to restore later.\n\n");
962 printf("Options:\n\n");
963 printf("-h Print this help.\n");
964 printf("-c Leave domain running after creating the snapshot.\n");
965 } else if(!strcmp(command, "restore")) {
966 printf("Usage: xl restore [options] <ConfigFile> <CheckpointFile>\n\n");
967 printf("Restore a domain from a saved state.\n\n");
968 printf("Options:\n\n");
969 printf("-h Print this help.\n");
970 printf("-p Do not unpause domain after restoring it.\n");
971 printf("-e Do not wait in the background for the death of the domain.\n");
972 } else if(!strcmp(command, "destroy")) {
973 printf("Usage: xl destroy <Domain>\n\n");
974 printf("Terminate a domain immediately.\n\n");
975 } else if (!strcmp(command, "console")) {
976 printf("Usage: xl console <Domain>\n\n");
977 printf("Attach to domain's console.\n\n");
978 } else if (!strcmp(command, "cd-insert")) {
979 printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
980 printf("Insert a cdrom into a guest's cd drive.\n\n");
981 } else if (!strcmp(command, "cd-eject")) {
982 printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
983 printf("Eject a cdrom from a guest's cd drive.\n\n");
984 } else if (!strcmp(command, "mem-set")) {
985 printf("Usage: xl mem-set <Domain> <MemKB>\n\n");
986 printf("Set the current memory usage for a domain.\n\n");
987 }
988 }
990 void set_memory_target(char *p, char *mem)
991 {
992 struct libxl_ctx ctx;
993 uint32_t domid;
994 uint32_t memorykb;
995 char *endptr;
997 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
998 fprintf(stderr, "cannot init xl context\n");
999 return;
1001 libxl_ctx_set_log(&ctx, log_callback, NULL);
1003 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1004 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1005 exit(2);
1007 memorykb = strtoul(mem, &endptr, 10);
1008 if (*endptr != '\0') {
1009 fprintf(stderr, "invalid memory size: %s\n", mem);
1010 exit(3);
1012 printf("setting domid %d memory to : %d\n", domid, memorykb);
1013 libxl_set_memory_target(&ctx, domid, memorykb);
1016 int main_memset(int argc, char **argv)
1018 int opt = 0;
1019 char *p = NULL, *mem;
1021 while ((opt = getopt(argc, argv, "h:")) != -1) {
1022 switch (opt) {
1023 case 'h':
1024 help("mem-set");
1025 exit(0);
1026 default:
1027 fprintf(stderr, "option not supported\n");
1028 break;
1031 if (optind >= argc - 1) {
1032 help("mem-set");
1033 exit(2);
1036 p = argv[optind];
1037 mem = argv[optind + 1];
1039 set_memory_target(p, mem);
1040 exit(0);
1043 void console(char *p, int cons_num)
1045 struct libxl_ctx ctx;
1046 uint32_t domid;
1048 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1049 fprintf(stderr, "cannot init xl context\n");
1050 return;
1052 libxl_ctx_set_log(&ctx, log_callback, NULL);
1054 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1055 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1056 exit(2);
1058 libxl_console_attach(&ctx, domid, cons_num);
1061 void cd_insert(char *dom, char *virtdev, char *phys)
1063 struct libxl_ctx ctx;
1064 uint32_t domid;
1065 libxl_device_disk disk;
1066 char *p;
1068 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1069 fprintf(stderr, "cannot init xl context\n");
1070 return;
1072 libxl_ctx_set_log(&ctx, log_callback, NULL);
1074 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1075 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1076 exit(2);
1079 disk.backend_domid = 0;
1080 disk.domid = domid;
1081 if (phys) {
1082 p = strchr(phys, ':');
1083 if (!p) {
1084 fprintf(stderr, "No type specified, ");
1085 disk.physpath = phys;
1086 if (!strncmp(phys, "/dev", 4)) {
1087 fprintf(stderr, "assuming phy:\n");
1088 disk.phystype = PHYSTYPE_PHY;
1089 } else {
1090 fprintf(stderr, "assuming file:\n");
1091 disk.phystype = PHYSTYPE_FILE;
1093 } else {
1094 *p = '\0';
1095 p++;
1096 disk.physpath = p;
1097 libxl_string_to_phystype(&ctx, phys, &disk.phystype);
1099 } else {
1100 disk.physpath = NULL;
1101 disk.phystype = 0;
1103 disk.virtpath = virtdev;
1104 disk.unpluggable = 1;
1105 disk.readwrite = 0;
1106 disk.is_cdrom = 1;
1108 libxl_cdrom_insert(&ctx, domid, &disk);
1111 int main_cd_eject(int argc, char **argv)
1113 int opt = 0;
1114 char *p = NULL, *virtdev;
1116 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1117 switch (opt) {
1118 case 'h':
1119 help("cd-eject");
1120 exit(0);
1121 default:
1122 fprintf(stderr, "option not supported\n");
1123 break;
1126 if (optind >= argc - 1) {
1127 help("cd-eject");
1128 exit(2);
1131 p = argv[optind];
1132 virtdev = argv[optind + 1];
1134 cd_insert(p, virtdev, NULL);
1135 exit(0);
1138 int main_cd_insert(int argc, char **argv)
1140 int opt = 0;
1141 char *p = NULL, *file = NULL, *virtdev;
1143 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1144 switch (opt) {
1145 case 'h':
1146 help("cd-insert");
1147 exit(0);
1148 default:
1149 fprintf(stderr, "option not supported\n");
1150 break;
1153 if (optind >= argc - 2) {
1154 help("cd-insert");
1155 exit(2);
1158 p = argv[optind];
1159 virtdev = argv[optind + 1];
1160 file = argv[optind + 2];
1162 cd_insert(p, virtdev, file);
1163 exit(0);
1166 int main_console(int argc, char **argv)
1168 int opt = 0, cons_num = 0;
1169 char *p = NULL;
1171 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1172 switch (opt) {
1173 case 'h':
1174 help("console");
1175 exit(0);
1176 case 'n':
1177 if (optarg) {
1178 cons_num = strtol(optarg, NULL, 10);
1180 break;
1181 default:
1182 fprintf(stderr, "option not supported\n");
1183 break;
1186 if (optind >= argc) {
1187 help("console");
1188 exit(2);
1191 p = argv[optind];
1193 console(p, cons_num);
1194 exit(0);
1197 void pcilist(char *dom)
1199 struct libxl_ctx ctx;
1200 uint32_t domid;
1201 libxl_device_pci *pcidevs;
1202 int num, i;
1204 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1205 fprintf(stderr, "cannot init xl context\n");
1206 return;
1208 libxl_ctx_set_log(&ctx, log_callback, NULL);
1210 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1211 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1212 exit(2);
1214 pcidevs = libxl_device_pci_list(&ctx, domid, &num);
1215 if (!num)
1216 return;
1217 printf("VFn domain bus slot func\n");
1218 for (i = 0; i < num; i++) {
1219 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);
1221 free(pcidevs);
1224 int main_pcilist(int argc, char **argv)
1226 int opt;
1227 char *domname = NULL;
1229 while ((opt = getopt(argc, argv, "h")) != -1) {
1230 switch (opt) {
1231 case 'h':
1232 help("pci-list");
1233 exit(0);
1234 default:
1235 fprintf(stderr, "option not supported\n");
1236 break;
1239 if (optind >= argc) {
1240 help("pci-list");
1241 exit(2);
1244 domname = argv[optind];
1246 pcilist(domname);
1247 exit(0);
1250 void pcidetach(char *dom, char *bdf)
1252 struct libxl_ctx ctx;
1253 uint32_t domid;
1254 libxl_device_pci pcidev;
1255 unsigned int domain, bus, dev, func;
1257 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1258 fprintf(stderr, "cannot init xl context\n");
1259 return;
1261 libxl_ctx_set_log(&ctx, log_callback, NULL);
1263 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1264 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1265 exit(2);
1267 memset(&pcidev, 0x00, sizeof(pcidev));
1268 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1269 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1270 libxl_device_pci_remove(&ctx, domid, &pcidev);
1273 int main_pcidetach(int argc, char **argv)
1275 int opt;
1276 char *domname = NULL, *bdf = NULL;
1278 while ((opt = getopt(argc, argv, "h")) != -1) {
1279 switch (opt) {
1280 case 'h':
1281 help("pci-attach");
1282 exit(0);
1283 default:
1284 fprintf(stderr, "option not supported\n");
1285 break;
1288 if (optind >= argc - 1) {
1289 help("pci-detach");
1290 exit(2);
1293 domname = argv[optind];
1294 bdf = argv[optind + 1];
1296 pcidetach(domname, bdf);
1297 exit(0);
1299 void pciattach(char *dom, char *bdf, char *vs)
1301 struct libxl_ctx ctx;
1302 uint32_t domid;
1303 libxl_device_pci pcidev;
1304 unsigned int domain, bus, dev, func;
1306 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1307 fprintf(stderr, "cannot init xl context\n");
1308 return;
1310 libxl_ctx_set_log(&ctx, log_callback, NULL);
1312 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1313 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1314 exit(2);
1316 memset(&pcidev, 0x00, sizeof(pcidev));
1317 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1318 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1319 libxl_device_pci_add(&ctx, domid, &pcidev);
1322 int main_pciattach(int argc, char **argv)
1324 int opt;
1325 char *domname = NULL, *bdf = NULL, *vs = NULL;
1327 while ((opt = getopt(argc, argv, "h")) != -1) {
1328 switch (opt) {
1329 case 'h':
1330 help("pci-attach");
1331 exit(0);
1332 default:
1333 fprintf(stderr, "option not supported\n");
1334 break;
1337 if (optind >= argc - 1) {
1338 help("pci-attach");
1339 exit(2);
1342 domname = argv[optind];
1343 bdf = argv[optind + 1];
1345 if (optind + 1 < argc)
1346 vs = argv[optind + 2];
1348 pciattach(domname, bdf, vs);
1349 exit(0);
1352 void pause_domain(char *p)
1354 struct libxl_ctx ctx;
1355 uint32_t domid;
1357 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1358 fprintf(stderr, "cannot init xl context\n");
1359 return;
1361 libxl_ctx_set_log(&ctx, log_callback, NULL);
1363 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1364 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1365 exit(2);
1367 libxl_domain_pause(&ctx, domid);
1370 void unpause_domain(char *p)
1372 struct libxl_ctx ctx;
1373 uint32_t domid;
1375 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1376 fprintf(stderr, "cannot init xl context\n");
1377 return;
1379 libxl_ctx_set_log(&ctx, log_callback, NULL);
1381 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1382 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1383 exit(2);
1385 libxl_domain_unpause(&ctx, domid);
1388 void destroy_domain(char *p)
1390 struct libxl_ctx ctx;
1391 uint32_t domid;
1393 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1394 fprintf(stderr, "cannot init xl context\n");
1395 return;
1397 libxl_ctx_set_log(&ctx, log_callback, NULL);
1399 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1400 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1401 exit(2);
1403 libxl_domain_destroy(&ctx, domid, 0);
1406 void list_domains(void)
1408 struct libxl_ctx ctx;
1409 struct libxl_dominfo *info;
1410 int nb_domain, i;
1412 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1413 fprintf(stderr, "cannot init xl context\n");
1414 return;
1416 libxl_ctx_set_log(&ctx, log_callback, NULL);
1418 info = libxl_list_domain(&ctx, &nb_domain);
1420 if (info < 0) {
1421 fprintf(stderr, "libxl_domain_infolist failed.\n");
1422 exit(1);
1424 printf("Name ID \tState\n");
1425 for (i = 0; i < nb_domain; i++) {
1426 printf("%-40s %5d %c%c%c\n",
1427 libxl_domid_to_name(&ctx, info[i].domid),
1428 info[i].domid,
1429 info[i].running ? 'r' : '-',
1430 info[i].paused ? 'p' : '-',
1431 info[i].dying ? 'd' : '-');
1433 free(info);
1436 void list_vm(void)
1438 struct libxl_ctx ctx;
1439 struct libxl_vminfo *info;
1440 int nb_vm, i;
1442 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1443 fprintf(stderr, "cannot init xl context\n");
1444 return;
1446 libxl_ctx_set_log(&ctx, log_callback, NULL);
1448 info = libxl_list_vm(&ctx, &nb_vm);
1450 if (info < 0) {
1451 fprintf(stderr, "libxl_domain_infolist failed.\n");
1452 exit(1);
1454 printf("UUID ID name\n");
1455 for (i = 0; i < nb_vm; i++) {
1456 printf(UUID_FMT " %d %-30s\n",
1457 info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
1458 info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
1459 info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], info[i].uuid[11],
1460 info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], info[i].uuid[15],
1461 info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
1463 free(info);
1466 int save_domain(char *p, char *filename, int checkpoint)
1468 struct libxl_ctx ctx;
1469 uint32_t domid;
1470 int fd;
1472 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1473 fprintf(stderr, "cannot init xl context\n");
1474 exit(2);
1476 libxl_ctx_set_log(&ctx, log_callback, NULL);
1478 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1479 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1480 exit(2);
1482 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1483 if (fd < 0) {
1484 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
1485 exit(2);
1487 libxl_domain_suspend(&ctx, NULL, domid, fd);
1488 close(fd);
1490 if (checkpoint)
1491 libxl_domain_unpause(&ctx, domid);
1492 else
1493 libxl_domain_destroy(&ctx, domid, 0);
1495 exit(0);
1498 int main_restore(int argc, char **argv)
1500 char *checkpoint_file = NULL;
1501 char *config_file = NULL;
1502 int paused = 0, debug = 0, daemonize = 1;
1503 int opt;
1505 while ((opt = getopt(argc, argv, "hpde")) != -1) {
1506 switch (opt) {
1507 case 'p':
1508 paused = 1;
1509 break;
1510 case 'd':
1511 debug = 1;
1512 break;
1513 case 'e':
1514 daemonize = 0;
1515 break;
1516 case 'h':
1517 help("restore");
1518 exit(0);
1519 default:
1520 fprintf(stderr, "option not supported\n");
1521 break;
1525 if (optind >= argc - 1) {
1526 help("restore");
1527 exit(2);
1530 config_file = argv[optind];
1531 checkpoint_file = argv[optind + 1];
1532 create_domain(debug, daemonize, config_file, checkpoint_file, paused);
1533 exit(0);
1536 int main_save(int argc, char **argv)
1538 char *filename = NULL, *p = NULL;
1539 int checkpoint = 0;
1540 int opt;
1542 while ((opt = getopt(argc, argv, "hc")) != -1) {
1543 switch (opt) {
1544 case 'c':
1545 checkpoint = 1;
1546 break;
1547 case 'h':
1548 help("save");
1549 exit(0);
1550 default:
1551 fprintf(stderr, "option not supported\n");
1552 break;
1556 if (optind >= argc - 1) {
1557 help("save");
1558 exit(2);
1561 p = argv[optind];
1562 filename = argv[optind + 1];
1563 save_domain(p, filename, checkpoint);
1564 exit(0);
1567 int main_pause(int argc, char **argv)
1569 int opt;
1570 char *p;
1573 while ((opt = getopt(argc, argv, "h")) != -1) {
1574 switch (opt) {
1575 case 'h':
1576 help("pause");
1577 exit(0);
1578 default:
1579 fprintf(stderr, "option not supported\n");
1580 break;
1583 if (optind >= argc) {
1584 help("pause");
1585 exit(2);
1588 p = argv[optind];
1590 pause_domain(p);
1591 exit(0);
1594 int main_unpause(int argc, char **argv)
1596 int opt;
1597 char *p;
1600 while ((opt = getopt(argc, argv, "h")) != -1) {
1601 switch (opt) {
1602 case 'h':
1603 help("unpause");
1604 exit(0);
1605 default:
1606 fprintf(stderr, "option not supported\n");
1607 break;
1610 if (optind >= argc) {
1611 help("unpause");
1612 exit(2);
1615 p = argv[optind];
1617 unpause_domain(p);
1618 exit(0);
1621 int main_destroy(int argc, char **argv)
1623 int opt;
1624 char *p;
1626 while ((opt = getopt(argc, argv, "h")) != -1) {
1627 switch (opt) {
1628 case 'h':
1629 help("destroy");
1630 exit(0);
1631 default:
1632 fprintf(stderr, "option not supported\n");
1633 break;
1636 if (optind >= argc) {
1637 help("destroy");
1638 exit(2);
1641 p = argv[optind];
1643 destroy_domain(p);
1644 exit(0);
1647 int main_list(int argc, char **argv)
1649 int opt;
1651 while ((opt = getopt(argc, argv, "h")) != -1) {
1652 switch (opt) {
1653 case 'h':
1654 help("list");
1655 exit(0);
1656 default:
1657 fprintf(stderr, "option not supported\n");
1658 break;
1662 list_domains();
1663 exit(0);
1666 int main_list_vm(int argc, char **argv)
1668 int opt;
1670 while ((opt = getopt(argc, argv, "h")) != -1) {
1671 switch (opt) {
1672 case 'h':
1673 help("list-vm");
1674 exit(0);
1675 default:
1676 fprintf(stderr, "option not supported\n");
1677 break;
1681 list_vm();
1682 exit(0);
1685 int main_create(int argc, char **argv)
1687 char *filename = NULL;
1688 int debug = 0, daemonize = 1;
1689 int opt;
1691 while ((opt = getopt(argc, argv, "hde")) != -1) {
1692 switch (opt) {
1693 case 'd':
1694 debug = 1;
1695 break;
1696 case 'e':
1697 daemonize = 0;
1698 break;
1699 case 'h':
1700 help("create");
1701 exit(0);
1702 default:
1703 fprintf(stderr, "option not supported\n");
1704 break;
1708 if (optind >= argc) {
1709 help("create");
1710 exit(2);
1713 filename = argv[optind];
1714 create_domain(debug, daemonize, filename, NULL, 0);
1715 exit(0);
1718 int main(int argc, char **argv)
1720 if (argc < 2) {
1721 help(NULL);
1722 exit(1);
1725 srand(time(0));
1727 if (!strcmp(argv[1], "create")) {
1728 main_create(argc - 1, argv + 1);
1729 } else if (!strcmp(argv[1], "list")) {
1730 main_list(argc - 1, argv + 1);
1731 } else if (!strcmp(argv[1], "list-vm")) {
1732 main_list_vm(argc - 1, argv + 1);
1733 } else if (!strcmp(argv[1], "destroy")) {
1734 main_destroy(argc - 1, argv + 1);
1735 } else if (!strcmp(argv[1], "pci-attach")) {
1736 main_pciattach(argc - 1, argv + 1);
1737 } else if (!strcmp(argv[1], "pci-detach")) {
1738 main_pcidetach(argc - 1, argv + 1);
1739 } else if (!strcmp(argv[1], "pci-list")) {
1740 main_pcilist(argc - 1, argv + 1);
1741 } else if (!strcmp(argv[1], "pause")) {
1742 main_pause(argc - 1, argv + 1);
1743 } else if (!strcmp(argv[1], "unpause")) {
1744 main_unpause(argc - 1, argv + 1);
1745 } else if (!strcmp(argv[1], "console")) {
1746 main_console(argc - 1, argv + 1);
1747 } else if (!strcmp(argv[1], "save")) {
1748 main_save(argc - 1, argv + 1);
1749 } else if (!strcmp(argv[1], "restore")) {
1750 main_restore(argc - 1, argv + 1);
1751 } else if (!strcmp(argv[1], "cd-insert")) {
1752 main_cd_insert(argc - 1, argv + 1);
1753 } else if (!strcmp(argv[1], "cd-eject")) {
1754 main_cd_eject(argc - 1, argv + 1);
1755 } else if (!strcmp(argv[1], "mem-set")) {
1756 main_memset(argc - 1, argv + 1);
1757 } else if (!strcmp(argv[1], "help")) {
1758 if (argc > 2)
1759 help(argv[2]);
1760 else
1761 help(NULL);
1762 exit(0);
1763 } else {
1764 fprintf(stderr, "command not implemented\n");
1765 exit(1);