debuggers.hg

view tools/libxl/xl.c @ 20647:2c6a04fdf8fb

libxenlight: implement libxl_set_memory_target

This patch adds a target_memkb parameter to libxl_domain_build_info to
set the target memory for the VM at build time and a new function
called libxl_set_memory_target to dynamically modify the memory target
of a VM at run time. Finally a new command "mem-set" is added to xl
that calls directly libxl_set_memory_target.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Dec 09 10:44:11 2009 +0000 (2009-12-09)
parents 91555131e235
children 8fbc74d40739
line source
1 /*
2 * Copyright (C) 2009 Citrix Ltd.
3 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
4 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; version 2.1 only. with the special
9 * exception on linking described in file LICENSE.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 */
17 #include "libxl_osdeps.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <libconfig.h>
23 #include "xen_uuid.h"
24 #include <unistd.h>
25 #include <sys/time.h> /* for time */
26 #include <getopt.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <sys/socket.h>
31 #include <sys/select.h>
32 #include <arpa/inet.h>
33 #include <xenctrl.h>
36 #include "libxl.h"
37 #include "libxl_utils.h"
39 int logfile = 2;
41 void log_callback(void *userdata, int loglevel, const char *file, int line, const char *func, char *s)
42 {
43 char str[1024];
45 snprintf(str, sizeof(str), "[%d] %s:%d:%s: %s\n", loglevel, file, line, func, s);
46 write(logfile, str, strlen(str));
47 }
49 static void printf_info(libxl_domain_create_info *c_info,
50 libxl_domain_build_info *b_info,
51 libxl_device_disk *disks,
52 int num_disks,
53 libxl_device_nic *vifs,
54 int num_vifs,
55 libxl_device_pci *pcidevs,
56 int num_pcidevs,
57 libxl_device_vfb *vfbs,
58 int num_vfbs,
59 libxl_device_vkb *vkb,
60 int num_vkbs,
61 libxl_device_model_info *dm_info)
62 {
63 int i;
64 char uuid_str[37];
65 printf("*** domain_create_info ***\n");
66 printf("hvm: %d\n", c_info->hvm);
67 printf("hap: %d\n", c_info->hap);
68 printf("ssidref: %d\n", c_info->ssidref);
69 printf("name: %s\n", c_info->name);
70 xen_uuid_to_string(c_info->uuid, uuid_str, sizeof(uuid_str));
71 printf("uuid: %s\n", uuid_str);
72 if (c_info->xsdata)
73 printf("xsdata: contains data\n");
74 else
75 printf("xsdata: (null)\n");
76 if (c_info->platformdata)
77 printf("platformdata: contains data\n");
78 else
79 printf("platformdata: (null)\n");
82 printf("\n\n\n*** domain_build_info ***\n");
83 printf("timer_mode: %d\n", b_info->timer_mode);
84 printf("hpet: %d\n", b_info->hpet);
85 printf("vpt_align: %d\n", b_info->vpt_align);
86 printf("max_vcpus: %d\n", b_info->max_vcpus);
87 printf("max_memkb: %d\n", b_info->max_memkb);
88 printf("target_memkb: %d\n", b_info->target_memkb);
89 printf("kernel: %s\n", b_info->kernel);
90 printf("hvm: %d\n", b_info->hvm);
92 if (c_info->hvm) {
93 printf("video_memkb: %d\n", b_info->video_memkb);
94 printf("shadow_memkb: %d\n", b_info->shadow_memkb);
95 printf(" pae: %d\n", b_info->u.hvm.pae);
96 printf(" apic: %d\n", b_info->u.hvm.apic);
97 printf(" acpi: %d\n", b_info->u.hvm.acpi);
98 printf(" nx: %d\n", b_info->u.hvm.nx);
99 printf(" viridian: %d\n", b_info->u.hvm.viridian);
100 } else {
101 printf("cmdline: %s\n", b_info->u.pv.cmdline);
102 printf("ramdisk: %s\n", b_info->u.pv.ramdisk);
103 }
105 for (i = 0; i < num_disks; i++) {
106 printf("\n\n\n*** disks_info: %d ***\n", i);
107 printf("backend_domid %d\n", disks[i].backend_domid);
108 printf("domid %d\n", disks[i].domid);
109 printf("physpath %s\n", disks[i].physpath);
110 printf("phystype %d\n", disks[i].phystype);
111 printf("virtpath %s\n", disks[i].virtpath);
112 printf("unpluggable %d\n", disks[i].unpluggable);
113 printf("readwrite %d\n", disks[i].readwrite);
114 printf("is_cdrom %d\n", disks[i].is_cdrom);
115 }
117 for (i = 0; i < num_vifs; i++) {
118 printf("\n\n\n*** vifs_info: %d ***\n", i);
119 printf("backend_domid %d\n", vifs[i].backend_domid);
120 printf("domid %d\n", vifs[i].domid);
121 printf("devid %d\n", vifs[i].devid);
122 printf("mtu %d\n", vifs[i].mtu);
123 printf("model %s\n", vifs[i].model);
124 printf("mac %02x:%02x:%02x:%02x:%02x:%02x\n", vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2], vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
125 printf("smac %s\n", vifs[i].mac);
126 }
128 for (i = 0; i < num_pcidevs; i++) {
129 printf("\n\n\n*** pcidevs_info: %d ***\n", i);
130 printf("pci dev "PCI_BDF_VDEVFN"\n", pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func, pcidevs[i].vdevfn);
131 printf("opts msitranslate %d power_mgmt %d\n", pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
132 }
134 for (i = 0; i < num_vfbs; i++) {
135 printf("\n\n\n*** vfbs_info: %d ***\n", i);
136 printf("backend_domid %d\n", vfbs[i].backend_domid);
137 printf("domid %d\n", vfbs[i].domid);
138 printf("devid %d\n", vfbs[i].devid);
139 printf("vnc: %d\n", vfbs[i].vnc);
140 printf("vnclisten: %s\n", vfbs[i].vnclisten);
141 printf("vncdisplay: %d\n", vfbs[i].vncdisplay);
142 printf("vncunused: %d\n", vfbs[i].vncunused);
143 printf("keymap: %s\n", vfbs[i].keymap);
144 printf("sdl: %d\n", vfbs[i].sdl);
145 printf("opengl: %d\n", vfbs[i].opengl);
146 printf("display: %s\n", vfbs[i].display);
147 printf("xauthority: %s\n", vfbs[i].xauthority);
148 }
150 if (c_info->hvm) {
151 printf("\n\n\n*** device_model_info ***\n");
152 printf("domid: %d\n", dm_info->domid);
153 printf("dom_name: %s\n", dm_info->dom_name);
154 printf("device_model: %s\n", dm_info->device_model);
155 printf("videoram: %d\n", dm_info->videoram);
156 printf("stdvga: %d\n", dm_info->stdvga);
157 printf("vnc: %d\n", dm_info->vnc);
158 printf("vnclisten: %s\n", dm_info->vnclisten);
159 printf("vncdisplay: %d\n", dm_info->vncdisplay);
160 printf("vncunused: %d\n", dm_info->vncunused);
161 printf("keymap: %s\n", dm_info->keymap);
162 printf("sdl: %d\n", dm_info->sdl);
163 printf("opengl: %d\n", dm_info->opengl);
164 printf("nographic: %d\n", dm_info->nographic);
165 printf("serial: %s\n", dm_info->serial);
166 printf("boot: %s\n", dm_info->boot);
167 printf("usb: %d\n", dm_info->usb);
168 printf("usbdevice: %s\n", dm_info->usbdevice);
169 printf("apic: %d\n", dm_info->apic);
170 }
171 }
173 static char* compat_config_file(const char *filename)
174 {
175 char t;
176 char *newfile = (char*) malloc(strlen(filename) + 4);
177 char *buf = (char *) malloc(2048);
178 int size = 2048, i;
179 FILE *s;
180 FILE *d;
182 sprintf(newfile, "%s.xl", filename);
184 s = fopen(filename, "r");
185 if (!s) {
186 perror("cannot open file for reading");
187 return NULL;
188 }
189 d = fopen(newfile, "w");
190 if (!d) {
191 fclose(s);
192 perror("cannot open file for writting");
193 return NULL;
194 }
196 while (!feof(s)) {
197 fgets(buf, size, s);
198 while (buf[strlen(buf) - 1] != '\n' && !feof(s)) {
199 size += 1024;
200 buf = realloc(buf, size + 1024);
201 fgets(buf + (size - 1025), 1025, s);
202 }
203 for (i = 0; i < strlen(buf); i++)
204 if (buf[i] == '\'')
205 buf[i] = '\"';
206 if (strchr(buf, '=') != NULL) {
207 if ((buf[strlen(buf) - 1] == '\n' && buf[strlen(buf) - 2] == ';') ||
208 buf[strlen(buf) - 1] == ';') {
209 fputs(buf, d);
210 } else {
211 t = buf[strlen(buf) - 1];
212 buf[strlen(buf) - 1] = ';';
213 fputs(buf, d);
214 fputc(t, d);
215 }
216 } else if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') {
217 fputs(buf, d);
218 }
219 }
221 fclose(s);
222 fclose(d);
224 free(buf);
226 return newfile;
227 }
229 static void parse_config_file(const char *filename,
230 libxl_domain_create_info *c_info,
231 libxl_domain_build_info *b_info,
232 libxl_device_disk **disks,
233 int *num_disks,
234 libxl_device_nic **vifs,
235 int *num_vifs,
236 libxl_device_pci **pcidevs,
237 int *num_pcidevs,
238 libxl_device_vfb **vfbs,
239 int *num_vfbs,
240 libxl_device_vkb **vkbs,
241 int *num_vkbs,
242 libxl_device_model_info *dm_info)
243 {
244 const char *buf;
245 xen_uuid_t uuid[16];
246 long l;
247 struct config_t config;
248 struct config_setting_t *vbds, *nics, *pcis, *cvfbs;
249 int pci_power_mgmt = 0;
250 int pci_msitranslate = 1;
252 config_init (&config);
254 if (!config_read_file(&config, filename)) {
255 char *newfilename;
256 config_destroy(&config);
257 newfilename = compat_config_file(filename);
258 config_init (&config);
259 if (!config_read_file(&config, newfilename)) {
260 fprintf(stderr, "Failed to parse config file %s, try removing any embedded python code\n", config_error_text(&config));
261 exit(1);
262 }
263 free(newfilename);
264 }
266 init_create_info(c_info);
268 c_info->hvm = 0;
269 if ((config_lookup_string (&config, "builder", &buf) == CONFIG_TRUE) &&
270 !strncmp(buf, "hvm", strlen(buf)))
271 c_info->hvm = 1;
273 /* hap is missing */
274 if (config_lookup_string (&config, "name", &buf) == CONFIG_TRUE)
275 c_info->name = strdup(buf);
276 else
277 c_info->name = "test";
278 xen_uuid_generate(uuid);
279 c_info->uuid = uuid;
281 init_build_info(b_info, c_info);
283 /* the following is the actual config parsing with overriding values in the structures */
284 if (config_lookup_int (&config, "vcpus", &l) == CONFIG_TRUE)
285 b_info->max_vcpus = l;
287 if (config_lookup_int (&config, "memory", &l) == CONFIG_TRUE) {
288 b_info->max_memkb = l * 1024;
289 b_info->target_memkb = b_info->max_memkb;
290 }
292 if (config_lookup_int (&config, "shadow_memory", &l) == CONFIG_TRUE)
293 b_info->shadow_memkb = l * 1024;
295 if (config_lookup_int (&config, "videoram", &l) == CONFIG_TRUE)
296 b_info->video_memkb = l * 1024;
298 if (config_lookup_string (&config, "kernel", &buf) == CONFIG_TRUE)
299 b_info->kernel = strdup(buf);
301 if (c_info->hvm == 1) {
302 if (config_lookup_int (&config, "pae", &l) == CONFIG_TRUE)
303 b_info->u.hvm.pae = l;
304 if (config_lookup_int (&config, "apic", &l) == CONFIG_TRUE)
305 b_info->u.hvm.apic = l;
306 if (config_lookup_int (&config, "acpi", &l) == CONFIG_TRUE)
307 b_info->u.hvm.acpi = l;
308 if (config_lookup_int (&config, "nx", &l) == CONFIG_TRUE)
309 b_info->u.hvm.nx = l;
310 if (config_lookup_int (&config, "viridian", &l) == CONFIG_TRUE)
311 b_info->u.hvm.viridian = l;
312 } else {
313 char *cmdline;
314 if (config_lookup_string (&config, "root", &buf) == CONFIG_TRUE) {
315 asprintf(&cmdline, "root=%s", buf);
316 b_info->u.pv.cmdline = cmdline;
317 }
318 if (config_lookup_string (&config, "ramdisk", &buf) == CONFIG_TRUE)
319 b_info->u.pv.ramdisk = strdup(buf);
320 }
322 if ((vbds = config_lookup (&config, "disk")) != NULL) {
323 *num_disks = 0;
324 *disks = NULL;
325 while ((buf = config_setting_get_string_elem (vbds, *num_disks)) != NULL) {
326 char *buf2 = strdup(buf);
327 char *p, *p2;
328 *disks = (libxl_device_disk *) realloc(*disks, sizeof (libxl_device_disk) * ((*num_disks) + 1));
329 (*disks)[*num_disks].backend_domid = 0;
330 (*disks)[*num_disks].domid = 0;
331 (*disks)[*num_disks].unpluggable = 0;
332 p = strtok(buf2, ",:");
333 while (*p == ' ')
334 p++;
335 if (!strcmp(p, "phy")) {
336 (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
337 } else if (!strcmp(p, "file")) {
338 (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
339 } else if (!strcmp(p, "tap")) {
340 p = strtok(NULL, ":");
341 if (!strcmp(p, "aio")) {
342 (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
343 } else if (!strcmp(p, "vhd")) {
344 (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
345 } else if (!strcmp(p, "qcow")) {
346 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
347 } else if (!strcmp(p, "qcow2")) {
348 (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
349 }
350 }
351 p = strtok(NULL, ",");
352 while (*p == ' ')
353 p++;
354 (*disks)[*num_disks].physpath= strdup(p);
355 p = strtok(NULL, ",");
356 while (*p == ' ')
357 p++;
358 p2 = strchr(p, ':');
359 if (p2 == NULL) {
360 (*disks)[*num_disks].virtpath = strdup(p);
361 (*disks)[*num_disks].is_cdrom = 0;
362 (*disks)[*num_disks].unpluggable = 1;
363 } else {
364 *p2 = '\0';
365 (*disks)[*num_disks].virtpath = strdup(p);
366 if (!strcmp(p2 + 1, "cdrom")) {
367 (*disks)[*num_disks].is_cdrom = 1;
368 (*disks)[*num_disks].unpluggable = 1;
369 } else
370 (*disks)[*num_disks].is_cdrom = 0;
371 }
372 p = strtok(NULL, ",");
373 while (*p == ' ')
374 p++;
375 (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
376 free(buf2);
377 *num_disks = (*num_disks) + 1;
378 }
379 }
381 if ((nics = config_lookup (&config, "vif")) != NULL) {
382 *num_vifs = 0;
383 *vifs = NULL;
384 while ((buf = config_setting_get_string_elem (nics, *num_vifs)) != NULL) {
385 char *buf2 = strdup(buf);
386 char *p, *p2;
387 *vifs = (libxl_device_nic *) realloc(*vifs, sizeof (libxl_device_nic) * ((*num_vifs) + 1));
388 init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
389 p = strtok(buf2, ",");
390 if (!p)
391 goto skip;
392 do {
393 while (*p == ' ')
394 p++;
395 if ((p2 = strchr(p, '=')) == NULL)
396 break;
397 *p2 = '\0';
398 if (!strcmp(p, "model")) {
399 (*vifs)[*num_vifs].model = strdup(p2 + 1);
400 } else if (!strcmp(p, "mac")) {
401 char *p3 = p2 + 1;
402 (*vifs)[*num_vifs].smac = strdup(p3);
403 *(p3 + 2) = '\0';
404 (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
405 p3 = p3 + 3;
406 *(p3 + 2) = '\0';
407 (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
408 p3 = p3 + 3;
409 *(p3 + 2) = '\0';
410 (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
411 p3 = p3 + 3;
412 *(p3 + 2) = '\0';
413 (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
414 p3 = p3 + 3;
415 *(p3 + 2) = '\0';
416 (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
417 p3 = p3 + 3;
418 *(p3 + 2) = '\0';
419 (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
420 } else if (!strcmp(p, "bridge")) {
421 (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
422 } else if (!strcmp(p, "type")) {
423 if (!strcmp(p2 + 1, "ioemu"))
424 (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
425 else
426 (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
427 } else if (!strcmp(p, "ip")) {
428 inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
429 } else if (!strcmp(p, "script")) {
430 (*vifs)[*num_vifs].script = strdup(p2 + 1);
431 } else if (!strcmp(p, "vifname")) {
432 (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
433 } else if (!strcmp(p, "rate")) {
434 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
435 } else if (!strcmp(p, "accel")) {
436 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
437 }
438 } while ((p = strtok(NULL, ",")) != NULL);
439 skip:
440 free(buf2);
441 *num_vifs = (*num_vifs) + 1;
442 }
443 }
445 if ((cvfbs = config_lookup (&config, "vfb")) != NULL) {
446 *num_vfbs = 0;
447 *num_vkbs = 0;
448 *vfbs = NULL;
449 *vkbs = NULL;
450 while ((buf = config_setting_get_string_elem (cvfbs, *num_vfbs)) != NULL) {
451 char *buf2 = strdup(buf);
452 char *p, *p2;
453 *vfbs = (libxl_device_vfb *) realloc(*vfbs, sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
454 init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
456 *vkbs = (libxl_device_vkb *) realloc(*vkbs, sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
457 init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
459 p = strtok(buf2, ",");
460 if (!p)
461 goto skip_vfb;
462 do {
463 while (*p == ' ')
464 p++;
465 if ((p2 = strchr(p, '=')) == NULL)
466 break;
467 *p2 = '\0';
468 if (!strcmp(p, "vnc")) {
469 (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
470 } else if (!strcmp(p, "vnclisten")) {
471 (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
472 } else if (!strcmp(p, "vncdisplay")) {
473 (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
474 } else if (!strcmp(p, "vncunused")) {
475 (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
476 } else if (!strcmp(p, "keymap")) {
477 (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
478 } else if (!strcmp(p, "sdl")) {
479 (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
480 } else if (!strcmp(p, "opengl")) {
481 (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
482 } else if (!strcmp(p, "display")) {
483 (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
484 } else if (!strcmp(p, "xauthority")) {
485 (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
486 }
487 } while ((p = strtok(NULL, ",")) != NULL);
488 skip_vfb:
489 free(buf2);
490 *num_vfbs = (*num_vfbs) + 1;
491 *num_vkbs = (*num_vkbs) + 1;
492 }
493 }
495 if (config_lookup_int (&config, "pci_msitranslate", &l) == CONFIG_TRUE)
496 pci_msitranslate = l;
498 if (config_lookup_int (&config, "pci_power_mgmt", &l) == CONFIG_TRUE)
499 pci_power_mgmt = l;
501 if ((pcis = config_lookup (&config, "pci")) != NULL) {
502 *num_pcidevs = 0;
503 *pcidevs = NULL;
504 while ((buf = config_setting_get_string_elem (pcis, *num_pcidevs)) != NULL) {
505 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
506 char *buf2 = strdup(buf);
507 char *p;
508 *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof (libxl_device_pci) * ((*num_pcidevs) + 1));
509 memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
510 p = strtok(buf2, ",");
511 if (!p)
512 goto skip_pci;
513 if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, &vdevfn)) {
514 sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
515 domain = 0;
516 }
517 libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, func, vdevfn);
518 (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
519 (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
520 while ((p = strtok(NULL, ",=")) != NULL) {
521 while (*p == ' ')
522 p++;
523 if (!strcmp(p, "msitranslate")) {
524 p = strtok(NULL, ",=");
525 (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
526 } else if (!strcmp(p, "power_mgmt")) {
527 p = strtok(NULL, ",=");
528 (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
529 }
530 }
531 *num_pcidevs = (*num_pcidevs) + 1;
532 skip_pci:
533 free(buf2);
534 }
535 }
537 if (c_info->hvm == 1) {
538 /* init dm from c and b */
539 init_dm_info(dm_info, c_info, b_info);
541 /* then process config related to dm */
542 if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
543 dm_info->device_model = strdup(buf);
544 if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
545 dm_info->stdvga = l;
546 if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
547 dm_info->vnc = l;
548 if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
549 dm_info->vnclisten = strdup(buf);
550 if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
551 dm_info->vncdisplay = l;
552 if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
553 dm_info->vncunused = l;
554 if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
555 dm_info->keymap = strdup(buf);
556 if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
557 dm_info->sdl = l;
558 if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
559 dm_info->opengl = l;
560 if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
561 dm_info->nographic = l;
562 if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
563 dm_info->serial = strdup(buf);
564 if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
565 dm_info->boot = strdup(buf);
566 if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
567 dm_info->usb = l;
568 if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
569 dm_info->usbdevice = strdup(buf);
570 }
572 config_destroy(&config);
573 }
575 #define MUST( call ) ({ \
576 int must_rc = (call); \
577 if (must_rc) { \
578 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \
579 __FILE__,__LINE__, must_rc, #call); \
580 exit(-must_rc); \
581 } \
582 })
584 static void create_domain(int debug, const char *config_file, const char *restore_file, int paused)
585 {
586 struct libxl_ctx ctx;
587 uint32_t domid;
588 libxl_domain_create_info info1;
589 libxl_domain_build_info info2;
590 libxl_domain_build_state state;
591 libxl_device_model_info dm_info;
592 libxl_device_disk *disks = NULL;
593 libxl_device_nic *vifs = NULL;
594 libxl_device_pci *pcidevs = NULL;
595 libxl_device_vfb *vfbs = NULL;
596 libxl_device_vkb *vkbs = NULL;
597 libxl_device_console console;
598 int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
599 int i, fd;
600 int need_daemon = 1;
601 libxl_device_model_starting *dm_starting = 0;
602 libxl_waiter *w1 = NULL, *w2 = NULL;
603 memset(&dm_info, 0x00, sizeof(dm_info));
605 printf("Parsing config file %s\n", config_file);
606 parse_config_file(config_file, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
607 if (debug)
608 printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
610 start:
611 domid = 0;
613 libxl_ctx_init(&ctx);
614 libxl_ctx_set_log(&ctx, log_callback, NULL);
615 libxl_domain_make(&ctx, &info1, &domid);
617 if (!restore_file || !need_daemon) {
618 if (dm_info.saved_state) {
619 free(dm_info.saved_state);
620 dm_info.saved_state = NULL;
621 }
622 libxl_domain_build(&ctx, &info2, domid, &state);
623 } else {
624 int restore_fd;
626 restore_fd = open(restore_file, O_RDONLY);
627 libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, &dm_info);
628 close(restore_fd);
629 }
631 for (i = 0; i < num_disks; i++) {
632 disk_info_domid_fixup(disks + i, domid);
633 libxl_device_disk_add(&ctx, domid, &disks[i]);
634 }
635 for (i = 0; i < num_vifs; i++) {
636 nic_info_domid_fixup(vifs + i, domid);
637 libxl_device_nic_add(&ctx, domid, &vifs[i]);
638 }
639 if (info1.hvm) {
640 device_model_info_domid_fixup(&dm_info, domid);
641 MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
642 vifs, num_vifs, &dm_starting) );
643 } else {
644 for (i = 0; i < num_vfbs; i++) {
645 vfb_info_domid_fixup(vfbs + i, domid);
646 libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
647 vkb_info_domid_fixup(vkbs + i, domid);
648 libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
649 }
650 init_console_info(&console, 0, &state);
651 console_info_domid_fixup(&console, domid);
652 if (num_vfbs)
653 console.constype = CONSTYPE_IOEMU;
654 libxl_device_console_add(&ctx, domid, &console);
655 if (num_vfbs)
656 libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
657 }
659 if (dm_starting)
660 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
661 for (i = 0; i < num_pcidevs; i++)
662 libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
664 if (!paused)
665 libxl_domain_unpause(&ctx, domid);
667 if (need_daemon) {
668 char *fullname, *name;
670 asprintf(&name, "xl-%s", info1.name);
671 libxl_create_logfile(&ctx, name, &fullname);
672 logfile = open(fullname, O_WRONLY|O_CREAT, 0644);
673 free(fullname);
674 free(name);
676 daemon(0, 0);
677 need_daemon = 0;
678 }
679 XL_LOG(&ctx, XL_LOG_DEBUG, "Waiting for domain %s (domid %d) to die", info1.name, domid);
680 w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
681 w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
682 libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
683 libxl_wait_for_domain_death(&ctx, domid, w2);
684 libxl_get_wait_fd(&ctx, &fd);
685 while (1) {
686 int ret;
687 fd_set rfds;
688 xc_dominfo_t info;
689 libxl_event event;
690 libxl_device_disk disk;
691 memset(&info, 0x00, sizeof(xc_dominfo_t));
693 FD_ZERO(&rfds);
694 FD_SET(fd, &rfds);
696 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
697 if (!ret)
698 continue;
699 libxl_get_event(&ctx, &event);
700 switch (event.type) {
701 case DOMAIN_DEATH:
702 if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info)) {
703 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
704 if (info.crashed || info.dying || (info.shutdown && (info.shutdown_reason != SHUTDOWN_suspend))) {
705 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be clean: destroying the domain", domid);
706 libxl_domain_destroy(&ctx, domid, 0);
707 if (info.shutdown && (info.shutdown_reason == SHUTDOWN_reboot)) {
708 libxl_free_waiter(w1);
709 libxl_free_waiter(w2);
710 free(w1);
711 free(w2);
712 libxl_ctx_free(&ctx);
713 XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
714 goto start;
715 }
716 XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
717 }
718 XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be clean, exiting now", domid);
719 exit(0);
720 }
721 break;
722 case DISK_EJECT:
723 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
724 libxl_cdrom_insert(&ctx, domid, &disk);
725 break;
726 }
727 libxl_free_event(&event);
728 }
730 close(logfile);
731 for (i = 0; i < num_vifs; i++) {
732 free(vifs[i].smac);
733 free(vifs[i].ifname);
734 }
735 free(disks);
736 free(vifs);
737 free(vfbs);
738 free(vkbs);
739 free(pcidevs);
740 }
742 static void help(char *command)
743 {
744 if (!command || !strcmp(command, "help")) {
745 printf("Usage xl <subcommand> [args]\n\n");
746 printf("xl full list of subcommands:\n\n");
747 printf(" create create a domain from config file <filename>\n\n");
748 printf(" list list information about all domains\n\n");
749 printf(" destroy terminate a domain immediately\n\n");
750 printf(" pci-attach insert a new pass-through pci device\n\n");
751 printf(" pci-detach remove a domain's pass-through pci device\n\n");
752 printf(" pci-list list pass-through pci devices for a domain\n\n");
753 printf(" pause pause execution of a domain\n\n");
754 printf(" unpause unpause a paused domain\n\n");
755 printf(" console attach to domain's console\n\n");
756 printf(" save save a domain state to restore later\n\n");
757 printf(" restore restore a domain from a saved state\n\n");
758 printf(" cd-insert insert a cdrom into a guest's cd drive\n\n");
759 printf(" cd-eject eject a cdrom from a guest's cd drive\n\n");
760 printf(" mem-set set the current memory usage for a domain\n\n");
761 } else if(!strcmp(command, "create")) {
762 printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
763 printf("Create a domain based on <ConfigFile>.\n\n");
764 printf("Options:\n\n");
765 printf("-h Print this help.\n");
766 printf("-d Enable debug messages.\n");
767 } else if(!strcmp(command, "list")) {
768 printf("Usage: xl list [Domain]\n\n");
769 printf("List information about all/some domains.\n\n");
770 } else if(!strcmp(command, "pci-attach")) {
771 printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
772 printf("Insert a new pass-through pci device.\n\n");
773 } else if(!strcmp(command, "pci-detach")) {
774 printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
775 printf("Remove a domain's pass-through pci device.\n\n");
776 } else if(!strcmp(command, "pci-list")) {
777 printf("Usage: xl pci-list <Domain>\n\n");
778 printf("List pass-through pci devices for a domain.\n\n");
779 } else if(!strcmp(command, "pause")) {
780 printf("Usage: xl pause <Domain>\n\n");
781 printf("Pause execution of a domain.\n\n");
782 } else if(!strcmp(command, "unpause")) {
783 printf("Usage: xl unpause <Domain>\n\n");
784 printf("Unpause a paused domain.\n\n");
785 } else if(!strcmp(command, "save")) {
786 printf("Usage: xl save [options] <Domain> <CheckpointFile>\n\n");
787 printf("Save a domain state to restore later.\n\n");
788 printf("Options:\n\n");
789 printf("-h Print this help.\n");
790 printf("-c Leave domain running after creating the snapshot.\n");
791 } else if(!strcmp(command, "restore")) {
792 printf("Usage: xl restore [options] <ConfigFile> <CheckpointFile>\n\n");
793 printf("Restore a domain from a saved state.\n\n");
794 printf("Options:\n\n");
795 printf("-h Print this help.\n");
796 printf("-p Do not unpause domain after restoring it.\n");
797 } else if(!strcmp(command, "destroy")) {
798 printf("Usage: xl destroy <Domain>\n\n");
799 printf("Terminate a domain immediately.\n\n");
800 } else if (!strcmp(command, "console")) {
801 printf("Usage: xl console <Domain>\n\n");
802 printf("Attach to domain's console.\n\n");
803 } else if (!strcmp(command, "cd-insert")) {
804 printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
805 printf("Insert a cdrom into a guest's cd drive.\n\n");
806 } else if (!strcmp(command, "cd-eject")) {
807 printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
808 printf("Eject a cdrom from a guest's cd drive.\n\n");
809 } else if (!strcmp(command, "mem-set")) {
810 printf("Usage: xl mem-set <Domain> <MemKB>\n\n");
811 printf("Set the current memory usage for a domain.\n\n");
812 }
813 }
815 void set_memory_target(char *p, char *mem)
816 {
817 struct libxl_ctx ctx;
818 uint32_t domid;
820 libxl_ctx_init(&ctx);
821 libxl_ctx_set_log(&ctx, log_callback, NULL);
823 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
824 fprintf(stderr, "%s is an invalid domain identifier\n", p);
825 exit(2);
826 }
827 libxl_set_memory_target(&ctx, domid, atoi(mem));
828 }
830 int main_memset(int argc, char **argv)
831 {
832 int opt = 0;
833 char *p = NULL, *mem;
835 while ((opt = getopt(argc, argv, "h:")) != -1) {
836 switch (opt) {
837 case 'h':
838 help("mem-set");
839 exit(0);
840 default:
841 fprintf(stderr, "option not supported\n");
842 break;
843 }
844 }
845 if (optind >= argc - 1) {
846 help("mem-set");
847 exit(2);
848 }
850 p = argv[optind];
851 mem = argv[optind + 1];
853 set_memory_target(p, mem);
854 exit(0);
855 }
857 void console(char *p, int cons_num)
858 {
859 struct libxl_ctx ctx;
860 uint32_t domid;
862 libxl_ctx_init(&ctx);
863 libxl_ctx_set_log(&ctx, log_callback, NULL);
865 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
866 fprintf(stderr, "%s is an invalid domain identifier\n", p);
867 exit(2);
868 }
869 libxl_console_attach(&ctx, domid, cons_num);
870 }
872 void cd_insert(char *dom, char *virtdev, char *phys)
873 {
874 struct libxl_ctx ctx;
875 uint32_t domid;
876 libxl_device_disk disk;
877 char *p;
879 libxl_ctx_init(&ctx);
880 libxl_ctx_set_log(&ctx, log_callback, NULL);
882 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
883 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
884 exit(2);
885 }
887 disk.backend_domid = 0;
888 disk.domid = domid;
889 if (phys) {
890 p = strchr(phys, ':');
891 if (!p) {
892 fprintf(stderr, "No type specified, ");
893 disk.physpath = phys;
894 if (!strncmp(phys, "/dev", 4)) {
895 fprintf(stderr, "assuming phy:\n");
896 disk.phystype = PHYSTYPE_PHY;
897 } else {
898 fprintf(stderr, "assuming file:\n");
899 disk.phystype = PHYSTYPE_FILE;
900 }
901 } else {
902 p = '\0';
903 disk.physpath = strdup(p);
904 p++;
905 libxl_string_to_phystype(&ctx, p, &disk.phystype);
906 }
907 } else {
908 disk.physpath = NULL;
909 disk.phystype = 0;
910 }
911 disk.virtpath = virtdev;
912 disk.unpluggable = 1;
913 disk.readwrite = 0;
914 disk.is_cdrom = 1;
916 libxl_cdrom_insert(&ctx, domid, &disk);
917 }
919 int main_cd_eject(int argc, char **argv)
920 {
921 int opt = 0;
922 char *p = NULL, *virtdev;
924 while ((opt = getopt(argc, argv, "hn:")) != -1) {
925 switch (opt) {
926 case 'h':
927 help("cd-eject");
928 exit(0);
929 default:
930 fprintf(stderr, "option not supported\n");
931 break;
932 }
933 }
934 if (optind >= argc - 1) {
935 help("cd-eject");
936 exit(2);
937 }
939 p = argv[optind];
940 virtdev = argv[optind + 1];
942 cd_insert(p, virtdev, NULL);
943 exit(0);
944 }
946 int main_cd_insert(int argc, char **argv)
947 {
948 int opt = 0;
949 char *p = NULL, *file = NULL, *virtdev;
951 while ((opt = getopt(argc, argv, "hn:")) != -1) {
952 switch (opt) {
953 case 'h':
954 help("cd-insert");
955 exit(0);
956 default:
957 fprintf(stderr, "option not supported\n");
958 break;
959 }
960 }
961 if (optind >= argc - 2) {
962 help("cd-insert");
963 exit(2);
964 }
966 p = argv[optind];
967 virtdev = argv[optind + 1];
968 file = argv[optind + 2];
970 cd_insert(p, virtdev, file);
971 exit(0);
972 }
974 int main_console(int argc, char **argv)
975 {
976 int opt = 0, cons_num = 0;
977 char *p = NULL;
979 while ((opt = getopt(argc, argv, "hn:")) != -1) {
980 switch (opt) {
981 case 'h':
982 help("console");
983 exit(0);
984 case 'n':
985 if (optarg) {
986 cons_num = strtol(optarg, NULL, 10);
987 }
988 break;
989 default:
990 fprintf(stderr, "option not supported\n");
991 break;
992 }
993 }
994 if (optind >= argc) {
995 help("console");
996 exit(2);
997 }
999 p = argv[optind];
1001 console(p, cons_num);
1002 exit(0);
1005 void pcilist(char *dom)
1007 struct libxl_ctx ctx;
1008 uint32_t domid;
1009 libxl_device_pci *pcidevs;
1010 int num, i;
1012 libxl_ctx_init(&ctx);
1013 libxl_ctx_set_log(&ctx, log_callback, NULL);
1015 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
1016 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1017 exit(2);
1019 pcidevs = libxl_device_pci_list(&ctx, domid, &num);
1020 if (!num)
1021 return;
1022 printf("VFn domain bus slot func\n");
1023 for (i = 0; i < num; i++) {
1024 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);
1026 free(pcidevs);
1029 int main_pcilist(int argc, char **argv)
1031 int opt;
1032 char *domname = NULL;
1034 while ((opt = getopt(argc, argv, "h")) != -1) {
1035 switch (opt) {
1036 case 'h':
1037 help("pci-list");
1038 exit(0);
1039 default:
1040 fprintf(stderr, "option not supported\n");
1041 break;
1044 if (optind >= argc) {
1045 help("pci-list");
1046 exit(2);
1049 domname = argv[optind];
1051 pcilist(domname);
1052 exit(0);
1055 void pcidetach(char *dom, char *bdf)
1057 struct libxl_ctx ctx;
1058 uint32_t domid;
1059 libxl_device_pci pcidev;
1060 unsigned int domain, bus, dev, func;
1062 libxl_ctx_init(&ctx);
1063 libxl_ctx_set_log(&ctx, log_callback, NULL);
1065 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
1066 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1067 exit(2);
1069 memset(&pcidev, 0x00, sizeof(pcidev));
1070 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1071 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1072 libxl_device_pci_remove(&ctx, domid, &pcidev);
1075 int main_pcidetach(int argc, char **argv)
1077 int opt;
1078 char *domname = NULL, *bdf = NULL;
1080 while ((opt = getopt(argc, argv, "h")) != -1) {
1081 switch (opt) {
1082 case 'h':
1083 help("pci-attach");
1084 exit(0);
1085 default:
1086 fprintf(stderr, "option not supported\n");
1087 break;
1090 if (optind >= argc - 1) {
1091 help("pci-detach");
1092 exit(2);
1095 domname = argv[optind];
1096 bdf = argv[optind + 1];
1098 pcidetach(domname, bdf);
1099 exit(0);
1101 void pciattach(char *dom, char *bdf, char *vs)
1103 struct libxl_ctx ctx;
1104 uint32_t domid;
1105 libxl_device_pci pcidev;
1106 unsigned int domain, bus, dev, func;
1108 libxl_ctx_init(&ctx);
1109 libxl_ctx_set_log(&ctx, log_callback, NULL);
1111 if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
1112 fprintf(stderr, "%s is an invalid domain identifier\n", dom);
1113 exit(2);
1115 memset(&pcidev, 0x00, sizeof(pcidev));
1116 sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
1117 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
1118 libxl_device_pci_add(&ctx, domid, &pcidev);
1121 int main_pciattach(int argc, char **argv)
1123 int opt;
1124 char *domname = NULL, *bdf = NULL, *vs = NULL;
1126 while ((opt = getopt(argc, argv, "h")) != -1) {
1127 switch (opt) {
1128 case 'h':
1129 help("pci-attach");
1130 exit(0);
1131 default:
1132 fprintf(stderr, "option not supported\n");
1133 break;
1136 if (optind >= argc - 1) {
1137 help("pci-attach");
1138 exit(2);
1141 domname = argv[optind];
1142 bdf = argv[optind + 1];
1144 if (optind + 1 < argc)
1145 vs = argv[optind + 2];
1147 pciattach(domname, bdf, vs);
1148 exit(0);
1151 void pause_domain(char *p)
1153 struct libxl_ctx ctx;
1154 uint32_t domid;
1156 libxl_ctx_init(&ctx);
1157 libxl_ctx_set_log(&ctx, log_callback, NULL);
1159 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1160 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1161 exit(2);
1163 libxl_domain_pause(&ctx, domid);
1166 void unpause_domain(char *p)
1168 struct libxl_ctx ctx;
1169 uint32_t domid;
1171 libxl_ctx_init(&ctx);
1172 libxl_ctx_set_log(&ctx, log_callback, NULL);
1174 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1175 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1176 exit(2);
1178 libxl_domain_unpause(&ctx, domid);
1181 void destroy_domain(char *p)
1183 struct libxl_ctx ctx;
1184 uint32_t domid;
1186 libxl_ctx_init(&ctx);
1187 libxl_ctx_set_log(&ctx, log_callback, NULL);
1189 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1190 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1191 exit(2);
1193 libxl_domain_destroy(&ctx, domid, 0);
1196 void list_domains(void)
1198 struct libxl_ctx ctx;
1199 xc_dominfo_t *info;
1200 int nb_domain, i;
1202 libxl_ctx_init(&ctx);
1203 libxl_ctx_set_log(&ctx, log_callback, NULL);
1205 info = libxl_domain_infolist(&ctx, &nb_domain);
1207 if (info < 0) {
1208 fprintf(stderr, "libxl_domain_infolist failed.\n");
1209 exit(1);
1211 printf("Name ID Mem VCPUs\tState\tTime(s)\n");
1212 for (i = 0; i < nb_domain; i++) {
1213 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f\n",
1214 libxl_domid_to_name(&ctx, info[i].domid),
1215 info[i].domid,
1216 info[i].nr_pages * XC_PAGE_SIZE/(1024*1024),
1217 info[i].nr_online_vcpus,
1218 info[i].running ? 'r' : '-',
1219 info[i].blocked ? 'b' : '-',
1220 info[i].paused ? 'p' : '-',
1221 info[i].shutdown ? 's' : '-',
1222 info[i].crashed ? 'c' : '-',
1223 info[i].dying ? 'd' : '-',
1224 ((float)info[i].cpu_time / 1e9));
1226 free(info);
1229 int save_domain(char *p, char *filename, int checkpoint)
1231 struct libxl_ctx ctx;
1232 uint32_t domid;
1233 int fd;
1235 libxl_ctx_init(&ctx);
1236 libxl_ctx_set_log(&ctx, log_callback, NULL);
1238 if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
1239 fprintf(stderr, "%s is an invalid domain identifier\n", p);
1240 exit(2);
1242 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1243 if (fd < 0) {
1244 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
1245 exit(2);
1247 libxl_domain_suspend(&ctx, NULL, domid, fd);
1248 close(fd);
1250 if (checkpoint)
1251 libxl_domain_unpause(&ctx, domid);
1252 else
1253 libxl_domain_destroy(&ctx, domid, 0);
1255 exit(0);
1258 int main_restore(int argc, char **argv)
1260 char *checkpoint_file = NULL;
1261 char *config_file = NULL;
1262 int paused = 0, debug = 0;
1263 int opt;
1265 while ((opt = getopt(argc, argv, "hpd")) != -1) {
1266 switch (opt) {
1267 case 'p':
1268 paused = 1;
1269 break;
1270 case 'd':
1271 debug = 1;
1272 break;
1273 case 'h':
1274 help("restore");
1275 exit(0);
1276 default:
1277 fprintf(stderr, "option not supported\n");
1278 break;
1282 if (optind >= argc - 1) {
1283 help("restore");
1284 exit(2);
1287 config_file = argv[optind];
1288 checkpoint_file = argv[optind + 1];
1289 create_domain(debug, config_file, checkpoint_file, paused);
1290 exit(0);
1293 int main_save(int argc, char **argv)
1295 char *filename = NULL, *p = NULL;
1296 int checkpoint = 0;
1297 int opt;
1299 while ((opt = getopt(argc, argv, "hc")) != -1) {
1300 switch (opt) {
1301 case 'c':
1302 checkpoint = 1;
1303 break;
1304 case 'h':
1305 help("save");
1306 exit(0);
1307 default:
1308 fprintf(stderr, "option not supported\n");
1309 break;
1313 if (optind >= argc - 1) {
1314 help("save");
1315 exit(2);
1318 p = argv[optind];
1319 filename = argv[optind + 1];
1320 save_domain(p, filename, checkpoint);
1321 exit(0);
1324 int main_pause(int argc, char **argv)
1326 int opt;
1327 char *p;
1330 while ((opt = getopt(argc, argv, "h")) != -1) {
1331 switch (opt) {
1332 case 'h':
1333 help("pause");
1334 exit(0);
1335 default:
1336 fprintf(stderr, "option not supported\n");
1337 break;
1340 if (optind >= argc) {
1341 help("pause");
1342 exit(2);
1345 p = argv[optind];
1347 pause_domain(p);
1348 exit(0);
1351 int main_unpause(int argc, char **argv)
1353 int opt;
1354 char *p;
1357 while ((opt = getopt(argc, argv, "h")) != -1) {
1358 switch (opt) {
1359 case 'h':
1360 help("unpause");
1361 exit(0);
1362 default:
1363 fprintf(stderr, "option not supported\n");
1364 break;
1367 if (optind >= argc) {
1368 help("unpause");
1369 exit(2);
1372 p = argv[optind];
1374 unpause_domain(p);
1375 exit(0);
1378 int main_destroy(int argc, char **argv)
1380 int opt;
1381 char *p;
1383 while ((opt = getopt(argc, argv, "h")) != -1) {
1384 switch (opt) {
1385 case 'h':
1386 help("destroy");
1387 exit(0);
1388 default:
1389 fprintf(stderr, "option not supported\n");
1390 break;
1393 if (optind >= argc) {
1394 help("destroy");
1395 exit(2);
1398 p = argv[optind];
1400 destroy_domain(p);
1401 exit(0);
1404 int main_list(int argc, char **argv)
1406 int opt;
1408 while ((opt = getopt(argc, argv, "h")) != -1) {
1409 switch (opt) {
1410 case 'h':
1411 help("list");
1412 exit(0);
1413 default:
1414 fprintf(stderr, "option not supported\n");
1415 break;
1419 list_domains();
1420 exit(0);
1423 int main_create(int argc, char **argv)
1425 char *filename = NULL;
1426 int debug = 0;
1427 int opt;
1429 while ((opt = getopt(argc, argv, "hd")) != -1) {
1430 switch (opt) {
1431 case 'd':
1432 debug = 1;
1433 break;
1434 case 'h':
1435 help("create");
1436 exit(0);
1437 default:
1438 fprintf(stderr, "option not supported\n");
1439 break;
1443 if (optind >= argc) {
1444 help("create");
1445 exit(2);
1448 filename = argv[optind];
1449 create_domain(debug, filename, NULL, 0);
1450 exit(0);
1453 int main(int argc, char **argv)
1455 if (argc < 2) {
1456 help(NULL);
1457 exit(1);
1460 if (!strcmp(argv[1], "create")) {
1461 main_create(argc - 1, argv + 1);
1462 } else if (!strcmp(argv[1], "list")) {
1463 main_list(argc - 1, argv + 1);
1464 } else if (!strcmp(argv[1], "destroy")) {
1465 main_destroy(argc - 1, argv + 1);
1466 } else if (!strcmp(argv[1], "pci-attach")) {
1467 main_pciattach(argc - 1, argv + 1);
1468 } else if (!strcmp(argv[1], "pci-detach")) {
1469 main_pcidetach(argc - 1, argv + 1);
1470 } else if (!strcmp(argv[1], "pci-list")) {
1471 main_pcilist(argc - 1, argv + 1);
1472 } else if (!strcmp(argv[1], "pause")) {
1473 main_pause(argc - 1, argv + 1);
1474 } else if (!strcmp(argv[1], "unpause")) {
1475 main_unpause(argc - 1, argv + 1);
1476 } else if (!strcmp(argv[1], "console")) {
1477 main_console(argc - 1, argv + 1);
1478 } else if (!strcmp(argv[1], "save")) {
1479 main_save(argc - 1, argv + 1);
1480 } else if (!strcmp(argv[1], "restore")) {
1481 main_restore(argc - 1, argv + 1);
1482 } else if (!strcmp(argv[1], "cd-insert")) {
1483 main_cd_insert(argc - 1, argv + 1);
1484 } else if (!strcmp(argv[1], "cd-eject")) {
1485 main_cd_eject(argc - 1, argv + 1);
1486 } else if (!strcmp(argv[1], "mem-set")) {
1487 main_memset(argc - 1, argv + 1);
1488 } else if (!strcmp(argv[1], "help")) {
1489 if (argc > 2)
1490 help(argv[2]);
1491 else
1492 help(NULL);
1493 exit(0);
1494 } else {
1495 fprintf(stderr, "command not implemented\n");
1496 exit(1);