debuggers.hg

view tools/libxl/xl.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents f0777eafb73b
children 71dddee38e65
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 <unistd.h>
23 #include <sys/time.h> /* for time */
24 #include <getopt.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <sys/socket.h>
29 #include <sys/select.h>
30 #include <arpa/inet.h>
31 #include <xenctrl.h>
32 #include <ctype.h>
34 #include "libxl.h"
35 #include "libxl_utils.h"
36 #include "libxlutil.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 void parse_config_file(const char *filename,
324 libxl_domain_create_info *c_info,
325 libxl_domain_build_info *b_info,
326 libxl_device_disk **disks,
327 int *num_disks,
328 libxl_device_nic **vifs,
329 int *num_vifs,
330 libxl_device_pci **pcidevs,
331 int *num_pcidevs,
332 libxl_device_vfb **vfbs,
333 int *num_vfbs,
334 libxl_device_vkb **vkbs,
335 int *num_vkbs,
336 libxl_device_model_info *dm_info)
337 {
338 const char *buf;
339 long l;
340 XLU_Config *config;
341 XLU_ConfigList *vbds, *nics, *pcis, *cvfbs;
342 int pci_power_mgmt = 0;
343 int pci_msitranslate = 1;
344 int i, e;
346 config= xlu_cfg_init(stderr, filename);
347 if (!config) {
348 fprintf(stderr, "Failed to allocate for configuration\n");
349 exit(1);
350 }
352 e= xlu_cfg_readfile (config, filename);
353 if (e) {
354 fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
355 exit(1);
356 }
358 init_create_info(c_info);
360 c_info->hvm = 0;
361 if (!xlu_cfg_get_string (config, "builder", &buf) &&
362 !strncmp(buf, "hvm", strlen(buf)))
363 c_info->hvm = 1;
365 /* hap is missing */
366 if (!xlu_cfg_get_string (config, "name", &buf))
367 c_info->name = strdup(buf);
368 else
369 c_info->name = "test";
370 for (i = 0; i < 16; i++) {
371 c_info->uuid[i] = rand();
372 }
374 init_build_info(b_info, c_info);
376 /* the following is the actual config parsing with overriding values in the structures */
377 if (!xlu_cfg_get_long (config, "vcpus", &l))
378 b_info->max_vcpus = l;
380 if (!xlu_cfg_get_long (config, "memory", &l)) {
381 b_info->max_memkb = l * 1024;
382 b_info->target_memkb = b_info->max_memkb;
383 }
385 if (!xlu_cfg_get_long (config, "shadow_memory", &l))
386 b_info->shadow_memkb = l * 1024;
388 if (!xlu_cfg_get_long (config, "videoram", &l))
389 b_info->video_memkb = l * 1024;
391 if (!xlu_cfg_get_string (config, "kernel", &buf))
392 b_info->kernel = strdup(buf);
394 if (c_info->hvm == 1) {
395 if (!xlu_cfg_get_long (config, "pae", &l))
396 b_info->u.hvm.pae = l;
397 if (!xlu_cfg_get_long (config, "apic", &l))
398 b_info->u.hvm.apic = l;
399 if (!xlu_cfg_get_long (config, "acpi", &l))
400 b_info->u.hvm.acpi = l;
401 if (!xlu_cfg_get_long (config, "nx", &l))
402 b_info->u.hvm.nx = l;
403 if (!xlu_cfg_get_long (config, "viridian", &l))
404 b_info->u.hvm.viridian = l;
405 } else {
406 char *cmdline;
407 if (!xlu_cfg_get_string (config, "root", &buf)) {
408 asprintf(&cmdline, "root=%s", buf);
409 b_info->u.pv.cmdline = cmdline;
410 }
411 if (!xlu_cfg_get_string (config, "ramdisk", &buf))
412 b_info->u.pv.ramdisk = strdup(buf);
413 }
415 if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
416 *num_disks = 0;
417 *disks = NULL;
418 while ((buf = xlu_cfg_get_listitem (vbds, *num_disks)) != NULL) {
419 char *buf2 = strdup(buf);
420 char *p, *p2;
421 *disks = (libxl_device_disk *) realloc(*disks, sizeof (libxl_device_disk) * ((*num_disks) + 1));
422 (*disks)[*num_disks].backend_domid = 0;
423 (*disks)[*num_disks].domid = 0;
424 (*disks)[*num_disks].unpluggable = 0;
425 p = strtok(buf2, ",:");
426 while (*p == ' ')
427 p++;
428 if (!strcmp(p, "phy")) {
429 (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
430 } else if (!strcmp(p, "file")) {
431 (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
432 } else if (!strcmp(p, "tap")) {
433 p = strtok(NULL, ":");
434 if (!strcmp(p, "aio")) {
435 (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
436 } else if (!strcmp(p, "vhd")) {
437 (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
438 } else if (!strcmp(p, "qcow")) {
439 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
440 } else if (!strcmp(p, "qcow2")) {
441 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
442 }
443 }
444 p = strtok(NULL, ",");
445 while (*p == ' ')
446 p++;
447 (*disks)[*num_disks].physpath= strdup(p);
448 p = strtok(NULL, ",");
449 while (*p == ' ')
450 p++;
451 p2 = strchr(p, ':');
452 if (p2 == NULL) {
453 (*disks)[*num_disks].virtpath = strdup(p);
454 (*disks)[*num_disks].is_cdrom = 0;
455 (*disks)[*num_disks].unpluggable = 1;
456 } else {
457 *p2 = '\0';
458 (*disks)[*num_disks].virtpath = strdup(p);
459 if (!strcmp(p2 + 1, "cdrom")) {
460 (*disks)[*num_disks].is_cdrom = 1;
461 (*disks)[*num_disks].unpluggable = 1;
462 } else
463 (*disks)[*num_disks].is_cdrom = 0;
464 }
465 p = strtok(NULL, ",");
466 while (*p == ' ')
467 p++;
468 (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
469 free(buf2);
470 *num_disks = (*num_disks) + 1;
471 }
472 }
474 if (!xlu_cfg_get_list (config, "vif", &nics, 0)) {
475 *num_vifs = 0;
476 *vifs = NULL;
477 while ((buf = xlu_cfg_get_listitem (nics, *num_vifs)) != NULL) {
478 char *buf2 = strdup(buf);
479 char *p, *p2;
480 *vifs = (libxl_device_nic *) realloc(*vifs, sizeof (libxl_device_nic) * ((*num_vifs) + 1));
481 init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
482 p = strtok(buf2, ",");
483 if (!p)
484 goto skip;
485 do {
486 while (*p == ' ')
487 p++;
488 if ((p2 = strchr(p, '=')) == NULL)
489 break;
490 *p2 = '\0';
491 if (!strcmp(p, "model")) {
492 (*vifs)[*num_vifs].model = strdup(p2 + 1);
493 } else if (!strcmp(p, "mac")) {
494 char *p3 = p2 + 1;
495 *(p3 + 2) = '\0';
496 (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
497 p3 = p3 + 3;
498 *(p3 + 2) = '\0';
499 (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
500 p3 = p3 + 3;
501 *(p3 + 2) = '\0';
502 (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
503 p3 = p3 + 3;
504 *(p3 + 2) = '\0';
505 (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
506 p3 = p3 + 3;
507 *(p3 + 2) = '\0';
508 (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
509 p3 = p3 + 3;
510 *(p3 + 2) = '\0';
511 (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
512 } else if (!strcmp(p, "bridge")) {
513 (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
514 } else if (!strcmp(p, "type")) {
515 if (!strcmp(p2 + 1, "ioemu"))
516 (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
517 else
518 (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
519 } else if (!strcmp(p, "ip")) {
520 inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
521 } else if (!strcmp(p, "script")) {
522 (*vifs)[*num_vifs].script = strdup(p2 + 1);
523 } else if (!strcmp(p, "vifname")) {
524 (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
525 } else if (!strcmp(p, "rate")) {
526 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
527 } else if (!strcmp(p, "accel")) {
528 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
529 }
530 } while ((p = strtok(NULL, ",")) != NULL);
531 skip:
532 free(buf2);
533 *num_vifs = (*num_vifs) + 1;
534 }
535 }
537 if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
538 *num_vfbs = 0;
539 *num_vkbs = 0;
540 *vfbs = NULL;
541 *vkbs = NULL;
542 while ((buf = xlu_cfg_get_listitem (cvfbs, *num_vfbs)) != NULL) {
543 char *buf2 = strdup(buf);
544 char *p, *p2;
545 *vfbs = (libxl_device_vfb *) realloc(*vfbs, sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
546 init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
548 *vkbs = (libxl_device_vkb *) realloc(*vkbs, sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
549 init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
551 p = strtok(buf2, ",");
552 if (!p)
553 goto skip_vfb;
554 do {
555 while (*p == ' ')
556 p++;
557 if ((p2 = strchr(p, '=')) == NULL)
558 break;
559 *p2 = '\0';
560 if (!strcmp(p, "vnc")) {
561 (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
562 } else if (!strcmp(p, "vnclisten")) {
563 (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
564 } else if (!strcmp(p, "vncdisplay")) {
565 (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
566 } else if (!strcmp(p, "vncunused")) {
567 (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
568 } else if (!strcmp(p, "keymap")) {
569 (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
570 } else if (!strcmp(p, "sdl")) {
571 (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
572 } else if (!strcmp(p, "opengl")) {
573 (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
574 } else if (!strcmp(p, "display")) {
575 (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
576 } else if (!strcmp(p, "xauthority")) {
577 (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
578 }
579 } while ((p = strtok(NULL, ",")) != NULL);
580 skip_vfb:
581 free(buf2);
582 *num_vfbs = (*num_vfbs) + 1;
583 *num_vkbs = (*num_vkbs) + 1;
584 }
585 }
587 if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
588 pci_msitranslate = l;
590 if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
591 pci_power_mgmt = l;
593 if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
594 *num_pcidevs = 0;
595 *pcidevs = NULL;
596 while ((buf = xlu_cfg_get_listitem (pcis, *num_pcidevs)) != NULL) {
597 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
598 char *buf2 = strdup(buf);
599 char *p;
600 *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof (libxl_device_pci) * ((*num_pcidevs) + 1));
601 memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
602 p = strtok(buf2, ",");
603 if (!p)
604 goto skip_pci;
605 if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, &vdevfn)) {
606 sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
607 domain = 0;
608 }
609 libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, func, vdevfn);
610 (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
611 (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
612 while ((p = strtok(NULL, ",=")) != NULL) {
613 while (*p == ' ')
614 p++;
615 if (!strcmp(p, "msitranslate")) {
616 p = strtok(NULL, ",=");
617 (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
618 } else if (!strcmp(p, "power_mgmt")) {
619 p = strtok(NULL, ",=");
620 (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
621 }
622 }
623 *num_pcidevs = (*num_pcidevs) + 1;
624 skip_pci:
625 free(buf2);
626 }
627 }
629 if (c_info->hvm == 1) {
630 /* init dm from c and b */
631 init_dm_info(dm_info, c_info, b_info);
633 /* then process config related to dm */
634 if (!xlu_cfg_get_string (config, "device_model", &buf))
635 dm_info->device_model = strdup(buf);
636 if (!xlu_cfg_get_long (config, "stdvga", &l))
637 dm_info->stdvga = l;
638 if (!xlu_cfg_get_long (config, "vnc", &l))
639 dm_info->vnc = l;
640 if (!xlu_cfg_get_string (config, "vnclisten", &buf))
641 dm_info->vnclisten = strdup(buf);
642 if (!xlu_cfg_get_long (config, "vncdisplay", &l))
643 dm_info->vncdisplay = l;
644 if (!xlu_cfg_get_long (config, "vncunused", &l))
645 dm_info->vncunused = l;
646 if (!xlu_cfg_get_string (config, "keymap", &buf))
647 dm_info->keymap = strdup(buf);
648 if (!xlu_cfg_get_long (config, "sdl", &l))
649 dm_info->sdl = l;
650 if (!xlu_cfg_get_long (config, "opengl", &l))
651 dm_info->opengl = l;
652 if (!xlu_cfg_get_long (config, "nographic", &l))
653 dm_info->nographic = l;
654 if (!xlu_cfg_get_string (config, "serial", &buf))
655 dm_info->serial = strdup(buf);
656 if (!xlu_cfg_get_string (config, "boot", &buf))
657 dm_info->boot = strdup(buf);
658 if (!xlu_cfg_get_long (config, "usb", &l))
659 dm_info->usb = l;
660 if (!xlu_cfg_get_string (config, "usbdevice", &buf))
661 dm_info->usbdevice = strdup(buf);
662 }
664 xlu_cfg_destroy(config);
665 }
667 #define MUST( call ) ({ \
668 int must_rc = (call); \
669 if (must_rc) { \
670 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \
671 __FILE__,__LINE__, must_rc, #call); \
672 exit(-must_rc); \
673 } \
674 })
676 static void create_domain(int debug, int daemonize, const char *config_file, const char *restore_file, int paused)
677 {
678 struct libxl_ctx ctx;
679 uint32_t domid;
680 libxl_domain_create_info info1;
681 libxl_domain_build_info info2;
682 libxl_domain_build_state state;
683 libxl_device_model_info dm_info;
684 libxl_device_disk *disks = NULL;
685 libxl_device_nic *vifs = NULL;
686 libxl_device_pci *pcidevs = NULL;
687 libxl_device_vfb *vfbs = NULL;
688 libxl_device_vkb *vkbs = NULL;
689 libxl_device_console console;
690 int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
691 int i, fd;
692 int need_daemon = 1;
693 int ret;
694 libxl_device_model_starting *dm_starting = 0;
695 libxl_waiter *w1 = NULL, *w2 = NULL;
696 memset(&dm_info, 0x00, sizeof(dm_info));
698 printf("Parsing config file %s\n", config_file);
699 parse_config_file(config_file, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
700 if (debug)
701 printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
703 start:
704 domid = 0;
706 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
707 fprintf(stderr, "cannot init xl context\n");
708 return;
709 }
711 libxl_ctx_set_log(&ctx, log_callback, NULL);
713 ret = libxl_domain_make(&ctx, &info1, &domid);
714 if (ret) {
715 fprintf(stderr, "cannot make domain: %d\n", ret);
716 return;
717 }
719 if (!restore_file || !need_daemon) {
720 if (dm_info.saved_state) {
721 free(dm_info.saved_state);
722 dm_info.saved_state = NULL;
723 }
724 ret = libxl_domain_build(&ctx, &info2, domid, &state);
725 } else {
726 int restore_fd;
728 restore_fd = open(restore_file, O_RDONLY);
729 ret = libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, &dm_info);
730 close(restore_fd);
731 }
733 if (ret) {
734 fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
735 return;
736 }
738 for (i = 0; i < num_disks; i++) {
739 disks[i].domid = domid;
740 ret = libxl_device_disk_add(&ctx, domid, &disks[i]);
741 if (ret) {
742 fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
743 return;
744 }
745 }
746 for (i = 0; i < num_vifs; i++) {
747 vifs[i].domid = domid;
748 ret = libxl_device_nic_add(&ctx, domid, &vifs[i]);
749 if (ret) {
750 fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
751 return;
752 }
753 }
754 if (info1.hvm) {
755 dm_info.domid = domid;
756 MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
757 vifs, num_vifs, &dm_starting) );
758 } else {
759 for (i = 0; i < num_vfbs; i++) {
760 vfbs[i].domid = domid;
761 libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
762 vkbs[i].domid = domid;
763 libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
764 }
765 init_console_info(&console, 0, &state);
766 console.domid = domid;
767 if (num_vfbs)
768 console.constype = CONSTYPE_IOEMU;
769 libxl_device_console_add(&ctx, domid, &console);
770 if (num_vfbs)
771 libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
772 }
774 if (dm_starting)
775 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
776 for (i = 0; i < num_pcidevs; i++)
777 libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
779 if (!paused)
780 libxl_domain_unpause(&ctx, domid);
782 if (!daemonize)
783 exit(0);
785 if (need_daemon) {
786 char *fullname, *name;
788 asprintf(&name, "xl-%s", info1.name);
789 libxl_create_logfile(&ctx, name, &fullname);
790 logfile = open(fullname, O_WRONLY|O_CREAT, 0644);
791 free(fullname);
792 free(name);
794 daemon(0, 0);
795 need_daemon = 0;
796 }
797 LOG("Waiting for domain %s (domid %d) to die", info1.name, domid);
798 w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
799 w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
800 libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
801 libxl_wait_for_domain_death(&ctx, domid, w2);
802 libxl_get_wait_fd(&ctx, &fd);
803 while (1) {
804 int ret;
805 fd_set rfds;
806 xc_domaininfo_t info;
807 libxl_event event;
808 libxl_device_disk disk;
809 memset(&info, 0x00, sizeof(xc_dominfo_t));
811 FD_ZERO(&rfds);
812 FD_SET(fd, &rfds);
814 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
815 if (!ret)
816 continue;
817 libxl_get_event(&ctx, &event);
818 switch (event.type) {
819 case DOMAIN_DEATH:
820 if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info)) {
821 LOG("Domain %d is dead", domid);
822 if (info.flags & XEN_DOMINF_dying || (info.flags & XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) {
823 LOG("Domain %d needs to be clean: destroying the domain", domid);
824 libxl_domain_destroy(&ctx, domid, 0);
825 if (info.flags & XEN_DOMINF_shutdown &&
826 (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) == SHUTDOWN_reboot)) {
827 libxl_free_waiter(w1);
828 libxl_free_waiter(w2);
829 free(w1);
830 free(w2);
831 libxl_ctx_free(&ctx);
832 LOG("Done. Rebooting now");
833 goto start;
834 }
835 LOG("Done. Exiting now");
836 }
837 LOG("Domain %d does not need to be clean, exiting now", domid);
838 exit(0);
839 }
840 break;
841 case DISK_EJECT:
842 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
843 libxl_cdrom_insert(&ctx, domid, &disk);
844 break;
845 }
846 libxl_free_event(&event);
847 }
849 close(logfile);
850 free(disks);
851 free(vifs);
852 free(vfbs);
853 free(vkbs);
854 free(pcidevs);
855 }
857 static void help(char *command)
858 {
859 if (!command || !strcmp(command, "help")) {
860 printf("Usage xl <subcommand> [args]\n\n");
861 printf("xl full list of subcommands:\n\n");
862 printf(" create create a domain from config file <filename>\n\n");
863 printf(" list list information about all domains\n\n");
864 printf(" destroy terminate a domain immediately\n\n");
865 printf(" pci-attach insert a new pass-through pci device\n\n");
866 printf(" pci-detach remove a domain's pass-through pci device\n\n");
867 printf(" pci-list list pass-through pci devices for a domain\n\n");
868 printf(" pause pause execution of a domain\n\n");
869 printf(" unpause unpause a paused domain\n\n");
870 printf(" console attach to domain's console\n\n");
871 printf(" save save a domain state to restore later\n\n");
872 printf(" restore restore a domain from a saved state\n\n");
873 printf(" cd-insert insert a cdrom into a guest's cd drive\n\n");
874 printf(" cd-eject eject a cdrom from a guest's cd drive\n\n");
875 printf(" mem-set set the current memory usage for a domain\n\n");
876 printf(" button-press indicate an ACPI button press to the domain\n\n");
877 } else if(!strcmp(command, "create")) {
878 printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
879 printf("Create a domain based on <ConfigFile>.\n\n");
880 printf("Options:\n\n");
881 printf("-h Print this help.\n");
882 printf("-d Enable debug messages.\n");
883 printf("-e Do not wait in the background for the death of the domain.\n");
884 } else if(!strcmp(command, "list")) {
885 printf("Usage: xl list [Domain]\n\n");
886 printf("List information about all/some domains.\n\n");
887 } else if(!strcmp(command, "pci-attach")) {
888 printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
889 printf("Insert a new pass-through pci device.\n\n");
890 } else if(!strcmp(command, "pci-detach")) {
891 printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
892 printf("Remove a domain's pass-through pci device.\n\n");
893 } else if(!strcmp(command, "pci-list")) {
894 printf("Usage: xl pci-list <Domain>\n\n");
895 printf("List pass-through pci devices for a domain.\n\n");
896 } else if(!strcmp(command, "pause")) {
897 printf("Usage: xl pause <Domain>\n\n");
898 printf("Pause execution of a domain.\n\n");
899 } else if(!strcmp(command, "unpause")) {
900 printf("Usage: xl unpause <Domain>\n\n");
901 printf("Unpause a paused domain.\n\n");
902 } else if(!strcmp(command, "save")) {
903 printf("Usage: xl save [options] <Domain> <CheckpointFile>\n\n");
904 printf("Save a domain state to restore later.\n\n");
905 printf("Options:\n\n");
906 printf("-h Print this help.\n");
907 printf("-c Leave domain running after creating the snapshot.\n");
908 } else if(!strcmp(command, "restore")) {
909 printf("Usage: xl restore [options] <ConfigFile> <CheckpointFile>\n\n");
910 printf("Restore a domain from a saved state.\n\n");
911 printf("Options:\n\n");
912 printf("-h Print this help.\n");
913 printf("-p Do not unpause domain after restoring it.\n");
914 printf("-e Do not wait in the background for the death of the domain.\n");
915 } else if(!strcmp(command, "destroy")) {
916 printf("Usage: xl destroy <Domain>\n\n");
917 printf("Terminate a domain immediately.\n\n");
918 } else if (!strcmp(command, "console")) {
919 printf("Usage: xl console <Domain>\n\n");
920 printf("Attach to domain's console.\n\n");
921 } else if (!strcmp(command, "cd-insert")) {
922 printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
923 printf("Insert a cdrom into a guest's cd drive.\n\n");
924 } else if (!strcmp(command, "cd-eject")) {
925 printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
926 printf("Eject a cdrom from a guest's cd drive.\n\n");
927 } else if (!strcmp(command, "mem-set")) {
928 printf("Usage: xl mem-set <Domain> <MemKB>\n\n");
929 printf("Set the current memory usage for a domain.\n\n");
930 } else if (!strcmp(command, "button-press")) {
931 printf("Usage: xl button-press <Domain> <Button>\n\n");
932 printf("Indicate <Button> press to a domain.\n");
933 printf("<Button> may be 'power' or 'sleep'.\n\n");
934 }
935 }
937 void set_memory_target(char *p, char *mem)
938 {
939 struct libxl_ctx ctx;
940 uint32_t domid;
941 uint32_t memorykb;
942 char *endptr;
944 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
945 fprintf(stderr, "cannot init xl context\n");
946 return;
947 }
948 libxl_ctx_set_log(&ctx, log_callback, NULL);
950 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
951 fprintf(stderr, "%s is an invalid domain identifier\n", p);
952 exit(2);
953 }
954 memorykb = strtoul(mem, &endptr, 10);
955 if (*endptr != '\0') {
956 fprintf(stderr, "invalid memory size: %s\n", mem);
957 exit(3);
958 }
959 printf("setting domid %d memory to : %d\n", domid, memorykb);
960 libxl_set_memory_target(&ctx, domid, memorykb);
961 }
963 int main_memset(int argc, char **argv)
964 {
965 int opt = 0;
966 char *p = NULL, *mem;
968 while ((opt = getopt(argc, argv, "h:")) != -1) {
969 switch (opt) {
970 case 'h':
971 help("mem-set");
972 exit(0);
973 default:
974 fprintf(stderr, "option not supported\n");
975 break;
976 }
977 }
978 if (optind >= argc - 1) {
979 help("mem-set");
980 exit(2);
981 }
983 p = argv[optind];
984 mem = argv[optind + 1];
986 set_memory_target(p, mem);
987 exit(0);
988 }
990 void console(char *p, int cons_num)
991 {
992 struct libxl_ctx ctx;
993 uint32_t domid;
995 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
996 fprintf(stderr, "cannot init xl context\n");
997 return;
998 }
999 libxl_ctx_set_log(&ctx, log_callback, NULL);
1001 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1002 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1003 exit(2);
1005 libxl_console_attach(&ctx, domid, cons_num);
1008 void cd_insert(char *dom, char *virtdev, char *phys)
1010 struct libxl_ctx ctx;
1011 uint32_t domid;
1012 libxl_device_disk disk;
1013 char *p;
1015 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1016 fprintf(stderr, "cannot init xl context\n");
1017 return;
1019 libxl_ctx_set_log(&ctx, log_callback, NULL);
1021 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1022 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1023 exit(2);
1026 disk.backend_domid = 0;
1027 disk.domid = domid;
1028 if (phys) {
1029 p = strchr(phys, ':');
1030 if (!p) {
1031 fprintf(stderr, "No type specified, ");
1032 disk.physpath = phys;
1033 if (!strncmp(phys, "/dev", 4)) {
1034 fprintf(stderr, "assuming phy:\n");
1035 disk.phystype = PHYSTYPE_PHY;
1036 } else {
1037 fprintf(stderr, "assuming file:\n");
1038 disk.phystype = PHYSTYPE_FILE;
1040 } else {
1041 *p = '\0';
1042 p++;
1043 disk.physpath = p;
1044 libxl_string_to_phystype(&ctx, phys, &disk.phystype);
1046 } else {
1047 disk.physpath = NULL;
1048 disk.phystype = 0;
1050 disk.virtpath = virtdev;
1051 disk.unpluggable = 1;
1052 disk.readwrite = 0;
1053 disk.is_cdrom = 1;
1055 libxl_cdrom_insert(&ctx, domid, &disk);
1058 int main_cd_eject(int argc, char **argv)
1060 int opt = 0;
1061 char *p = NULL, *virtdev;
1063 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1064 switch (opt) {
1065 case 'h':
1066 help("cd-eject");
1067 exit(0);
1068 default:
1069 fprintf(stderr, "option not supported\n");
1070 break;
1073 if (optind >= argc - 1) {
1074 help("cd-eject");
1075 exit(2);
1078 p = argv[optind];
1079 virtdev = argv[optind + 1];
1081 cd_insert(p, virtdev, NULL);
1082 exit(0);
1085 int main_cd_insert(int argc, char **argv)
1087 int opt = 0;
1088 char *p = NULL, *file = NULL, *virtdev;
1090 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1091 switch (opt) {
1092 case 'h':
1093 help("cd-insert");
1094 exit(0);
1095 default:
1096 fprintf(stderr, "option not supported\n");
1097 break;
1100 if (optind >= argc - 2) {
1101 help("cd-insert");
1102 exit(2);
1105 p = argv[optind];
1106 virtdev = argv[optind + 1];
1107 file = argv[optind + 2];
1109 cd_insert(p, virtdev, file);
1110 exit(0);
1113 int main_console(int argc, char **argv)
1115 int opt = 0, cons_num = 0;
1116 char *p = NULL;
1118 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1119 switch (opt) {
1120 case 'h':
1121 help("console");
1122 exit(0);
1123 case 'n':
1124 if (optarg) {
1125 cons_num = strtol(optarg, NULL, 10);
1127 break;
1128 default:
1129 fprintf(stderr, "option not supported\n");
1130 break;
1133 if (optind >= argc) {
1134 help("console");
1135 exit(2);
1138 p = argv[optind];
1140 console(p, cons_num);
1141 exit(0);
1144 void pcilist(char *dom)
1146 struct libxl_ctx ctx;
1147 uint32_t domid;
1148 libxl_device_pci *pcidevs;
1149 int num, i;
1151 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1152 fprintf(stderr, "cannot init xl context\n");
1153 return;
1155 libxl_ctx_set_log(&ctx, log_callback, NULL);
1157 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1158 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1159 exit(2);
1161 pcidevs = libxl_device_pci_list(&ctx, domid, &num);
1162 if (!num)
1163 return;
1164 printf("VFn domain bus slot func\n");
1165 for (i = 0; i < num; i++) {
1166 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);
1168 free(pcidevs);
1171 int main_pcilist(int argc, char **argv)
1173 int opt;
1174 char *domname = NULL;
1176 while ((opt = getopt(argc, argv, "h")) != -1) {
1177 switch (opt) {
1178 case 'h':
1179 help("pci-list");
1180 exit(0);
1181 default:
1182 fprintf(stderr, "option not supported\n");
1183 break;
1186 if (optind >= argc) {
1187 help("pci-list");
1188 exit(2);
1191 domname = argv[optind];
1193 pcilist(domname);
1194 exit(0);
1197 void pcidetach(char *dom, char *bdf)
1199 struct libxl_ctx ctx;
1200 uint32_t domid;
1201 libxl_device_pci pcidev;
1202 unsigned int domain, bus, dev, func;
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 memset(&pcidev, 0x00, sizeof(pcidev));
1215 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1216 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1217 libxl_device_pci_remove(&ctx, domid, &pcidev);
1220 int main_pcidetach(int argc, char **argv)
1222 int opt;
1223 char *domname = NULL, *bdf = NULL;
1225 while ((opt = getopt(argc, argv, "h")) != -1) {
1226 switch (opt) {
1227 case 'h':
1228 help("pci-attach");
1229 exit(0);
1230 default:
1231 fprintf(stderr, "option not supported\n");
1232 break;
1235 if (optind >= argc - 1) {
1236 help("pci-detach");
1237 exit(2);
1240 domname = argv[optind];
1241 bdf = argv[optind + 1];
1243 pcidetach(domname, bdf);
1244 exit(0);
1246 void pciattach(char *dom, char *bdf, char *vs)
1248 struct libxl_ctx ctx;
1249 uint32_t domid;
1250 libxl_device_pci pcidev;
1251 unsigned int domain, bus, dev, func;
1253 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1254 fprintf(stderr, "cannot init xl context\n");
1255 return;
1257 libxl_ctx_set_log(&ctx, log_callback, NULL);
1259 if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
1260 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1261 exit(2);
1263 memset(&pcidev, 0x00, sizeof(pcidev));
1264 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1265 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1266 libxl_device_pci_add(&ctx, domid, &pcidev);
1269 int main_pciattach(int argc, char **argv)
1271 int opt;
1272 char *domname = NULL, *bdf = NULL, *vs = NULL;
1274 while ((opt = getopt(argc, argv, "h")) != -1) {
1275 switch (opt) {
1276 case 'h':
1277 help("pci-attach");
1278 exit(0);
1279 default:
1280 fprintf(stderr, "option not supported\n");
1281 break;
1284 if (optind >= argc - 1) {
1285 help("pci-attach");
1286 exit(2);
1289 domname = argv[optind];
1290 bdf = argv[optind + 1];
1292 if (optind + 1 < argc)
1293 vs = argv[optind + 2];
1295 pciattach(domname, bdf, vs);
1296 exit(0);
1299 void pause_domain(char *p)
1301 struct libxl_ctx ctx;
1302 uint32_t domid;
1304 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1305 fprintf(stderr, "cannot init xl context\n");
1306 return;
1308 libxl_ctx_set_log(&ctx, log_callback, NULL);
1310 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1311 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1312 exit(2);
1314 libxl_domain_pause(&ctx, domid);
1317 void unpause_domain(char *p)
1319 struct libxl_ctx ctx;
1320 uint32_t domid;
1322 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1323 fprintf(stderr, "cannot init xl context\n");
1324 return;
1326 libxl_ctx_set_log(&ctx, log_callback, NULL);
1328 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1329 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1330 exit(2);
1332 libxl_domain_unpause(&ctx, domid);
1335 void destroy_domain(char *p)
1337 struct libxl_ctx ctx;
1338 uint32_t domid;
1340 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1341 fprintf(stderr, "cannot init xl context\n");
1342 return;
1344 libxl_ctx_set_log(&ctx, log_callback, NULL);
1346 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1347 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1348 exit(2);
1350 libxl_domain_destroy(&ctx, domid, 0);
1353 void list_domains(void)
1355 struct libxl_ctx ctx;
1356 struct libxl_dominfo *info;
1357 int nb_domain, i;
1359 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1360 fprintf(stderr, "cannot init xl context\n");
1361 return;
1363 libxl_ctx_set_log(&ctx, log_callback, NULL);
1365 info = libxl_list_domain(&ctx, &nb_domain);
1367 if (info < 0) {
1368 fprintf(stderr, "libxl_domain_infolist failed.\n");
1369 exit(1);
1371 printf("Name ID Mem VCPUs\tState\tTime(s)\n");
1372 for (i = 0; i < nb_domain; i++) {
1373 printf("%-40s %5d %5lu %5d %c%c%c %8.1f\n",
1374 libxl_domid_to_name(&ctx, info[i].domid),
1375 info[i].domid,
1376 (unsigned long) (info[i].max_memkb / 1024),
1377 info[i].vcpu_online,
1378 info[i].running ? 'r' : '-',
1379 info[i].paused ? 'p' : '-',
1380 info[i].dying ? 'd' : '-',
1381 ((float)info[i].cpu_time / 1e9));
1383 free(info);
1386 void list_vm(void)
1388 struct libxl_ctx ctx;
1389 struct libxl_vminfo *info;
1390 int nb_vm, i;
1392 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1393 fprintf(stderr, "cannot init xl context\n");
1394 return;
1396 libxl_ctx_set_log(&ctx, log_callback, NULL);
1398 info = libxl_list_vm(&ctx, &nb_vm);
1400 if (info < 0) {
1401 fprintf(stderr, "libxl_domain_infolist failed.\n");
1402 exit(1);
1404 printf("UUID ID name\n");
1405 for (i = 0; i < nb_vm; i++) {
1406 printf(UUID_FMT " %d %-30s\n",
1407 info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
1408 info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
1409 info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], info[i].uuid[11],
1410 info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], info[i].uuid[15],
1411 info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
1413 free(info);
1416 int save_domain(char *p, char *filename, int checkpoint)
1418 struct libxl_ctx ctx;
1419 uint32_t domid;
1420 int fd;
1422 if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
1423 fprintf(stderr, "cannot init xl context\n");
1424 exit(2);
1426 libxl_ctx_set_log(&ctx, log_callback, NULL);
1428 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1429 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1430 exit(2);
1432 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1433 if (fd < 0) {
1434 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
1435 exit(2);
1437 libxl_domain_suspend(&ctx, NULL, domid, fd);
1438 close(fd);
1440 if (checkpoint)
1441 libxl_domain_unpause(&ctx, domid);
1442 else
1443 libxl_domain_destroy(&ctx, domid, 0);
1445 exit(0);
1448 int main_restore(int argc, char **argv)
1450 char *checkpoint_file = NULL;
1451 char *config_file = NULL;
1452 int paused = 0, debug = 0, daemonize = 1;
1453 int opt;
1455 while ((opt = getopt(argc, argv, "hpde")) != -1) {
1456 switch (opt) {
1457 case 'p':
1458 paused = 1;
1459 break;
1460 case 'd':
1461 debug = 1;
1462 break;
1463 case 'e':
1464 daemonize = 0;
1465 break;
1466 case 'h':
1467 help("restore");
1468 exit(0);
1469 default:
1470 fprintf(stderr, "option not supported\n");
1471 break;
1475 if (optind >= argc - 1) {
1476 help("restore");
1477 exit(2);
1480 config_file = argv[optind];
1481 checkpoint_file = argv[optind + 1];
1482 create_domain(debug, daemonize, config_file, checkpoint_file, paused);
1483 exit(0);
1486 int main_save(int argc, char **argv)
1488 char *filename = NULL, *p = NULL;
1489 int checkpoint = 0;
1490 int opt;
1492 while ((opt = getopt(argc, argv, "hc")) != -1) {
1493 switch (opt) {
1494 case 'c':
1495 checkpoint = 1;
1496 break;
1497 case 'h':
1498 help("save");
1499 exit(0);
1500 default:
1501 fprintf(stderr, "option not supported\n");
1502 break;
1506 if (optind >= argc - 1) {
1507 help("save");
1508 exit(2);
1511 p = argv[optind];
1512 filename = argv[optind + 1];
1513 save_domain(p, filename, checkpoint);
1514 exit(0);
1517 int main_pause(int argc, char **argv)
1519 int opt;
1520 char *p;
1523 while ((opt = getopt(argc, argv, "h")) != -1) {
1524 switch (opt) {
1525 case 'h':
1526 help("pause");
1527 exit(0);
1528 default:
1529 fprintf(stderr, "option not supported\n");
1530 break;
1533 if (optind >= argc) {
1534 help("pause");
1535 exit(2);
1538 p = argv[optind];
1540 pause_domain(p);
1541 exit(0);
1544 int main_unpause(int argc, char **argv)
1546 int opt;
1547 char *p;
1550 while ((opt = getopt(argc, argv, "h")) != -1) {
1551 switch (opt) {
1552 case 'h':
1553 help("unpause");
1554 exit(0);
1555 default:
1556 fprintf(stderr, "option not supported\n");
1557 break;
1560 if (optind >= argc) {
1561 help("unpause");
1562 exit(2);
1565 p = argv[optind];
1567 unpause_domain(p);
1568 exit(0);
1571 int main_destroy(int argc, char **argv)
1573 int opt;
1574 char *p;
1576 while ((opt = getopt(argc, argv, "h")) != -1) {
1577 switch (opt) {
1578 case 'h':
1579 help("destroy");
1580 exit(0);
1581 default:
1582 fprintf(stderr, "option not supported\n");
1583 break;
1586 if (optind >= argc) {
1587 help("destroy");
1588 exit(2);
1591 p = argv[optind];
1593 destroy_domain(p);
1594 exit(0);
1597 int main_list(int argc, char **argv)
1599 int opt;
1601 while ((opt = getopt(argc, argv, "h")) != -1) {
1602 switch (opt) {
1603 case 'h':
1604 help("list");
1605 exit(0);
1606 default:
1607 fprintf(stderr, "option not supported\n");
1608 break;
1612 list_domains();
1613 exit(0);
1616 int main_list_vm(int argc, char **argv)
1618 int opt;
1620 while ((opt = getopt(argc, argv, "h")) != -1) {
1621 switch (opt) {
1622 case 'h':
1623 help("list-vm");
1624 exit(0);
1625 default:
1626 fprintf(stderr, "option not supported\n");
1627 break;
1631 list_vm();
1632 exit(0);
1635 int main_create(int argc, char **argv)
1637 char *filename = NULL;
1638 int debug = 0, daemonize = 1;
1639 int opt;
1641 while ((opt = getopt(argc, argv, "hde")) != -1) {
1642 switch (opt) {
1643 case 'd':
1644 debug = 1;
1645 break;
1646 case 'e':
1647 daemonize = 0;
1648 break;
1649 case 'h':
1650 help("create");
1651 exit(0);
1652 default:
1653 fprintf(stderr, "option not supported\n");
1654 break;
1658 if (optind >= argc) {
1659 help("create");
1660 exit(2);
1663 filename = argv[optind];
1664 create_domain(debug, daemonize, filename, NULL, 0);
1665 exit(0);
1668 void button_press(char *p, char *b)
1670 struct libxl_ctx ctx;
1671 uint32_t domid;
1672 libxl_button button;
1674 libxl_ctx_init(&ctx, LIBXL_VERSION);
1675 libxl_ctx_set_log(&ctx, log_callback, NULL);
1677 if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
1678 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1679 exit(2);
1682 if (!strcmp(b, "power")) {
1683 button = POWER_BUTTON;
1684 } else if (!strcmp(b, "sleep")) {
1685 button = SLEEP_BUTTON;
1686 } else {
1687 fprintf(stderr, "%s is an invalid button identifier\n", b);
1688 exit(2);
1691 libxl_button_press(&ctx, domid, button);
1694 int main_button_press(int argc, char **argv)
1696 int opt;
1697 char *p;
1698 char *b;
1700 while ((opt = getopt(argc, argv, "h")) != -1) {
1701 switch (opt) {
1702 case 'h':
1703 help("button-press");
1704 exit(0);
1705 default:
1706 fprintf(stderr, "option not supported\n");
1707 break;
1710 if (optind >= argc - 1) {
1711 help("button-press");
1712 exit(2);
1715 p = argv[optind];
1716 b = argv[optind + 1];
1718 button_press(p, b);
1719 exit(0);
1722 int main(int argc, char **argv)
1724 if (argc < 2) {
1725 help(NULL);
1726 exit(1);
1729 srand(time(0));
1731 if (!strcmp(argv[1], "create")) {
1732 main_create(argc - 1, argv + 1);
1733 } else if (!strcmp(argv[1], "list")) {
1734 main_list(argc - 1, argv + 1);
1735 } else if (!strcmp(argv[1], "list-vm")) {
1736 main_list_vm(argc - 1, argv + 1);
1737 } else if (!strcmp(argv[1], "destroy")) {
1738 main_destroy(argc - 1, argv + 1);
1739 } else if (!strcmp(argv[1], "pci-attach")) {
1740 main_pciattach(argc - 1, argv + 1);
1741 } else if (!strcmp(argv[1], "pci-detach")) {
1742 main_pcidetach(argc - 1, argv + 1);
1743 } else if (!strcmp(argv[1], "pci-list")) {
1744 main_pcilist(argc - 1, argv + 1);
1745 } else if (!strcmp(argv[1], "pause")) {
1746 main_pause(argc - 1, argv + 1);
1747 } else if (!strcmp(argv[1], "unpause")) {
1748 main_unpause(argc - 1, argv + 1);
1749 } else if (!strcmp(argv[1], "console")) {
1750 main_console(argc - 1, argv + 1);
1751 } else if (!strcmp(argv[1], "save")) {
1752 main_save(argc - 1, argv + 1);
1753 } else if (!strcmp(argv[1], "restore")) {
1754 main_restore(argc - 1, argv + 1);
1755 } else if (!strcmp(argv[1], "cd-insert")) {
1756 main_cd_insert(argc - 1, argv + 1);
1757 } else if (!strcmp(argv[1], "cd-eject")) {
1758 main_cd_eject(argc - 1, argv + 1);
1759 } else if (!strcmp(argv[1], "mem-set")) {
1760 main_memset(argc - 1, argv + 1);
1761 } else if (!strcmp(argv[1], "button-press")) {
1762 main_button_press(argc - 1, argv + 1);
1763 } else if (!strcmp(argv[1], "help")) {
1764 if (argc > 2)
1765 help(argv[2]);
1766 else
1767 help(NULL);
1768 exit(0);
1769 } else {
1770 fprintf(stderr, "command not implemented\n");
1771 exit(1);