debuggers.hg

view tools/libxl/xl_cmdimpl.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents 6ec61438713a
children b457e2520074
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 <assert.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <time.h>
25 #include <getopt.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/time.h>
29 #include <fcntl.h>
30 #include <signal.h>
31 #include <sys/socket.h>
32 #include <sys/select.h>
33 #include <arpa/inet.h>
34 #include <sys/utsname.h> /* for utsname in xl info */
35 #include <xenctrl.h>
36 #include <ctype.h>
37 #include <inttypes.h>
39 #include "libxl.h"
40 #include "libxl_utils.h"
41 #include "libxlutil.h"
42 #include "xl.h"
44 #define CHK_ERRNO( call ) ({ \
45 int chk_errno = (call); \
46 if (chk_errno < 0) { \
47 fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n", \
48 __FILE__,__LINE__, strerror(chk_errno), #call); \
49 exit(-ERROR_FAIL); \
50 } \
51 })
53 #define MUST( call ) ({ \
54 int must_rc = (call); \
55 if (must_rc < 0) { \
56 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \
57 __FILE__,__LINE__, must_rc, #call); \
58 exit(-must_rc); \
59 } \
60 })
63 int logfile = 2;
65 /* every libxl action in xl uses this same libxl context */
66 libxl_ctx ctx;
68 /* when we operate on a domain, it is this one: */
69 static uint32_t domid;
70 static const char *common_domname;
71 static int fd_lock = -1;
74 static const char savefileheader_magic[32]=
75 "Xen saved domain, xl format\n \0 \r";
77 static const char migrate_receiver_banner[]=
78 "xl migration receiver ready, send binary domain data.\n";
79 static const char migrate_receiver_ready[]=
80 "domain received, ready to unpause";
81 static const char migrate_permission_to_go[]=
82 "domain is yours, you are cleared to unpause";
83 static const char migrate_report[]=
84 "my copy unpause results are as follows";
85 /* followed by one byte:
86 * 0: everything went well, domain is running
87 * next thing is we all exit
88 * non-0: things went badly
89 * next thing should be a migrate_permission_to_go
90 * from target to source
91 */
93 struct save_file_header {
94 char magic[32]; /* savefileheader_magic */
95 /* All uint32_ts are in domain's byte order. */
96 uint32_t byteorder; /* SAVEFILE_BYTEORDER_VALUE */
97 uint32_t mandatory_flags; /* unknown flags => reject restore */
98 uint32_t optional_flags; /* unknown flags => reject restore */
99 uint32_t optional_data_len; /* skip, or skip tail, if not understood */
100 };
103 static const char *action_on_shutdown_names[] = {
104 [LIBXL_ACTION_DESTROY] = "destroy",
106 [LIBXL_ACTION_RESTART] = "restart",
107 [LIBXL_ACTION_RESTART_RENAME] = "rename-restart",
109 [LIBXL_ACTION_PRESERVE] = "preserve",
111 [LIBXL_ACTION_COREDUMP_DESTROY] = "coredump-destroy",
112 [LIBXL_ACTION_COREDUMP_RESTART] = "coredump-restart",
113 };
115 /* Optional data, in order:
116 * 4 bytes uint32_t config file size
117 * n bytes config file in Unix text file format
118 */
120 #define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
122 static int qualifier_to_id(const char *p, uint32_t *id_r)
123 {
124 int i, alldigit;
126 alldigit = 1;
127 for (i = 0; p[i]; i++) {
128 if (!isdigit((uint8_t)p[i])) {
129 alldigit = 0;
130 break;
131 }
132 }
134 if (i > 0 && alldigit) {
135 *id_r = strtoul(p, NULL, 10);
136 return 0;
137 } else {
138 /* check here if it's a uuid and do proper conversion */
139 }
140 return 1;
141 }
143 static int domain_qualifier_to_domid(const char *p, uint32_t *domid_r,
144 int *was_name_r)
145 {
146 int was_name;
148 was_name = qualifier_to_id(p, domid_r);
149 if (was_name_r) *was_name_r = was_name;
150 return was_name ? libxl_name_to_domid(&ctx, p, domid_r) : 0;
151 }
153 static int cpupool_qualifier_to_cpupoolid(const char *p, uint32_t *poolid_r,
154 int *was_name_r)
155 {
156 int was_name;
158 was_name = qualifier_to_id(p, poolid_r);
159 if (was_name_r) *was_name_r = was_name;
160 return was_name ? libxl_name_to_cpupoolid(&ctx, p, poolid_r) : 0;
161 }
163 static void find_domain(const char *p)
164 {
165 int rc, was_name;
167 rc = domain_qualifier_to_domid(p, &domid, &was_name);
168 if (rc) {
169 fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
170 exit(2);
171 }
172 common_domname = was_name ? p : libxl_domid_to_name(&ctx, domid);
173 }
175 static int acquire_lock(void)
176 {
177 int rc;
178 struct flock fl;
180 /* lock already acquired */
181 if (fd_lock >= 0)
182 return ERROR_INVAL;
184 fl.l_type = F_WRLCK;
185 fl.l_whence = SEEK_SET;
186 fl.l_start = 0;
187 fl.l_len = 0;
188 fd_lock = open(lockfile, O_WRONLY|O_CREAT, S_IWUSR);
189 if (fd_lock < 0) {
190 fprintf(stderr, "cannot open the lockfile %s errno=%d\n", lockfile, errno);
191 return ERROR_FAIL;
192 }
193 get_lock:
194 rc = fcntl(fd_lock, F_SETLKW, &fl);
195 if (rc < 0 && errno == EINTR)
196 goto get_lock;
197 if (rc < 0) {
198 fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
199 rc = ERROR_FAIL;
200 } else
201 rc = 0;
202 return rc;
203 }
205 static int release_lock(void)
206 {
207 int rc;
208 struct flock fl;
210 /* lock not acquired */
211 if (fd_lock < 0)
212 return ERROR_INVAL;
214 release_lock:
215 fl.l_type = F_UNLCK;
216 fl.l_whence = SEEK_SET;
217 fl.l_start = 0;
218 fl.l_len = 0;
220 rc = fcntl(fd_lock, F_SETLKW, &fl);
221 if (rc < 0 && errno == EINTR)
222 goto release_lock;
223 if (rc < 0) {
224 fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
225 rc = ERROR_FAIL;
226 } else
227 rc = 0;
228 close(fd_lock);
229 fd_lock = -1;
231 return rc;
232 }
234 #define LOG(_f, _a...) dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
236 static void dolog(const char *file, int line, const char *func, char *fmt, ...)
237 __attribute__((format(printf,4,5)));
239 static void dolog(const char *file, int line, const char *func, char *fmt, ...)
240 {
241 va_list ap;
242 char *s;
243 int rc;
245 va_start(ap, fmt);
246 rc = vasprintf(&s, fmt, ap);
247 va_end(ap);
248 if (rc >= 0)
249 libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
250 }
252 static void printf_info(int domid,
253 libxl_domain_config *d_config,
254 libxl_device_model_info *dm_info)
255 {
256 int i;
257 libxl_dominfo info;
259 libxl_domain_create_info *c_info = &d_config->c_info;
260 libxl_domain_build_info *b_info = &d_config->b_info;
262 printf("(domain\n\t(domid %d)\n", domid);
263 printf("\t(domain_create_info)\n");
264 printf("\t(hvm %d)\n", c_info->hvm);
265 printf("\t(hap %d)\n", c_info->hap);
266 printf("\t(oos %d)\n", c_info->oos);
267 printf("\t(ssidref %d)\n", c_info->ssidref);
268 printf("\t(name %s)\n", c_info->name);
270 /* retrieve the UUID from dominfo, since it is probably generated
271 * during parsing and thus does not match the real one
272 */
273 if (libxl_domain_info(&ctx, &info, domid) == 0) {
274 printf("\t(uuid " LIBXL_UUID_FMT ")\n", LIBXL_UUID_BYTES(info.uuid));
275 } else {
276 printf("\t(uuid <unknown>)\n");
277 }
279 printf("\t(cpupool %s)\n", c_info->poolname);
280 if (c_info->xsdata)
281 printf("\t(xsdata contains data)\n");
282 else
283 printf("\t(xsdata (null))\n");
284 if (c_info->platformdata)
285 printf("\t(platformdata contains data)\n");
286 else
287 printf("\t(platformdata (null))\n");
290 printf("\t(domain_build_info)\n");
291 printf("\t(max_vcpus %d)\n", b_info->max_vcpus);
292 printf("\t(tsc_mode %d)\n", b_info->tsc_mode);
293 printf("\t(max_memkb %d)\n", b_info->max_memkb);
294 printf("\t(target_memkb %d)\n", b_info->target_memkb);
295 printf("\t(nomigrate %d)\n", b_info->disable_migrate);
297 if (!c_info->hvm && b_info->u.pv.bootloader) {
298 printf("\t(bootloader %s)\n", b_info->u.pv.bootloader);
299 if (b_info->u.pv.bootloader_args)
300 printf("\t(bootloader_args %s)\n", b_info->u.pv.bootloader_args);
301 }
303 printf("\t(image\n");
304 if (c_info->hvm) {
305 printf("\t\t(hvm\n");
306 printf("\t\t\t(loader %s)\n", b_info->kernel.path);
307 printf("\t\t\t(video_memkb %d)\n", b_info->video_memkb);
308 printf("\t\t\t(shadow_memkb %d)\n", b_info->shadow_memkb);
309 printf("\t\t\t(pae %d)\n", b_info->u.hvm.pae);
310 printf("\t\t\t(apic %d)\n", b_info->u.hvm.apic);
311 printf("\t\t\t(acpi %d)\n", b_info->u.hvm.acpi);
312 printf("\t\t\t(nx %d)\n", b_info->u.hvm.nx);
313 printf("\t\t\t(viridian %d)\n", b_info->u.hvm.viridian);
314 printf("\t\t\t(hpet %d)\n", b_info->u.hvm.hpet);
315 printf("\t\t\t(vpt_align %d)\n", b_info->u.hvm.vpt_align);
316 printf("\t\t\t(timer_mode %d)\n", b_info->u.hvm.timer_mode);
318 printf("\t\t\t(device_model %s)\n", dm_info->device_model);
319 printf("\t\t\t(videoram %d)\n", dm_info->videoram);
320 printf("\t\t\t(stdvga %d)\n", dm_info->stdvga);
321 printf("\t\t\t(vnc %d)\n", dm_info->vnc);
322 printf("\t\t\t(vnclisten %s)\n", dm_info->vnclisten);
323 printf("\t\t\t(vncdisplay %d)\n", dm_info->vncdisplay);
324 printf("\t\t\t(vncunused %d)\n", dm_info->vncunused);
325 printf("\t\t\t(keymap %s)\n", dm_info->keymap);
326 printf("\t\t\t(sdl %d)\n", dm_info->sdl);
327 printf("\t\t\t(gfx_passthru %d)\n", dm_info->gfx_passthru);
328 printf("\t\t\t(opengl %d)\n", dm_info->opengl);
329 printf("\t\t\t(nographic %d)\n", dm_info->nographic);
330 printf("\t\t\t(serial %s)\n", dm_info->serial);
331 printf("\t\t\t(boot %s)\n", dm_info->boot);
332 printf("\t\t\t(usb %d)\n", dm_info->usb);
333 printf("\t\t\t(usbdevice %s)\n", dm_info->usbdevice);
334 printf("\t\t\t(apic %d)\n", dm_info->apic);
335 printf("\t\t)\n");
336 } else {
337 printf("\t\t(linux %d)\n", b_info->hvm);
338 printf("\t\t\t(kernel %s)\n", b_info->kernel.path);
339 printf("\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
340 printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk.path);
341 printf("\t\t)\n");
342 }
343 printf("\t)\n");
345 for (i = 0; i < d_config->num_disks; i++) {
346 printf("\t(device\n");
347 printf("\t\t(tap\n");
348 printf("\t\t\t(backend_domid %d)\n", d_config->disks[i].backend_domid);
349 printf("\t\t\t(domid %d)\n", d_config->disks[i].domid);
350 printf("\t\t\t(physpath %s)\n", d_config->disks[i].physpath);
351 printf("\t\t\t(phystype %d)\n", d_config->disks[i].phystype);
352 printf("\t\t\t(virtpath %s)\n", d_config->disks[i].virtpath);
353 printf("\t\t\t(unpluggable %d)\n", d_config->disks[i].unpluggable);
354 printf("\t\t\t(readwrite %d)\n", d_config->disks[i].readwrite);
355 printf("\t\t\t(is_cdrom %d)\n", d_config->disks[i].is_cdrom);
356 printf("\t\t)\n");
357 printf("\t)\n");
358 }
360 for (i = 0; i < d_config->num_vifs; i++) {
361 printf("\t(device\n");
362 printf("\t\t(vif\n");
363 printf("\t\t\t(backend_domid %d)\n", d_config->vifs[i].backend_domid);
364 printf("\t\t\t(domid %d)\n", d_config->vifs[i].domid);
365 printf("\t\t\t(devid %d)\n", d_config->vifs[i].devid);
366 printf("\t\t\t(mtu %d)\n", d_config->vifs[i].mtu);
367 printf("\t\t\t(model %s)\n", d_config->vifs[i].model);
368 printf("\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n",
369 d_config->vifs[i].mac[0], d_config->vifs[i].mac[1],
370 d_config->vifs[i].mac[2], d_config->vifs[i].mac[3],
371 d_config->vifs[i].mac[4], d_config->vifs[i].mac[5]);
372 printf("\t\t)\n");
373 printf("\t)\n");
374 }
376 for (i = 0; i < d_config->num_pcidevs; i++) {
377 printf("\t(device\n");
378 printf("\t\t(pci\n");
379 printf("\t\t\t(pci dev %04x:%02x:%02x.%01x@%02x)\n",
380 d_config->pcidevs[i].domain, d_config->pcidevs[i].bus,
381 d_config->pcidevs[i].dev, d_config->pcidevs[i].func,
382 d_config->pcidevs[i].vdevfn);
383 printf("\t\t\t(opts msitranslate %d power_mgmt %d)\n",
384 d_config->pcidevs[i].msitranslate,
385 d_config->pcidevs[i].power_mgmt);
386 printf("\t\t)\n");
387 printf("\t)\n");
388 }
390 for (i = 0; i < d_config->num_vfbs; i++) {
391 printf("\t(device\n");
392 printf("\t\t(vfb\n");
393 printf("\t\t\t(backend_domid %d)\n", d_config->vfbs[i].backend_domid);
394 printf("\t\t\t(domid %d)\n", d_config->vfbs[i].domid);
395 printf("\t\t\t(devid %d)\n", d_config->vfbs[i].devid);
396 printf("\t\t\t(vnc %d)\n", d_config->vfbs[i].vnc);
397 printf("\t\t\t(vnclisten %s)\n", d_config->vfbs[i].vnclisten);
398 printf("\t\t\t(vncdisplay %d)\n", d_config->vfbs[i].vncdisplay);
399 printf("\t\t\t(vncunused %d)\n", d_config->vfbs[i].vncunused);
400 printf("\t\t\t(keymap %s)\n", d_config->vfbs[i].keymap);
401 printf("\t\t\t(sdl %d)\n", d_config->vfbs[i].sdl);
402 printf("\t\t\t(opengl %d)\n", d_config->vfbs[i].opengl);
403 printf("\t\t\t(display %s)\n", d_config->vfbs[i].display);
404 printf("\t\t\t(xauthority %s)\n", d_config->vfbs[i].xauthority);
405 printf("\t\t)\n");
406 printf("\t)\n");
407 }
408 printf(")\n");
409 }
411 static int parse_action_on_shutdown(const char *buf, enum libxl_action_on_shutdown *a)
412 {
413 int i;
414 const char *n;
416 for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
417 n = action_on_shutdown_names[i];
419 if (strcmp(buf, n) == 0) {
420 *a = i;
421 return 1;
422 }
423 }
424 return 0;
425 }
427 #define DSTATE_INITIAL 0
428 #define DSTATE_TAP 1
429 #define DSTATE_PHYSPATH 2
430 #define DSTATE_VIRTPATH 3
431 #define DSTATE_VIRTTYPE 4
432 #define DSTATE_RW 5
433 #define DSTATE_TERMINAL 6
435 static int parse_disk_config(libxl_device_disk *disk, char *buf2)
436 {
437 int state = DSTATE_INITIAL;
438 char *p, *end, *tok;
440 memset(disk, 0, sizeof(*disk));
442 for(tok = p = buf2, end = buf2 + strlen(buf2) + 1; p < end; p++) {
443 switch(state){
444 case DSTATE_INITIAL:
445 if ( *p == ':' ) {
446 *p = '\0';
447 if ( !strcmp(tok, "phy") ) {
448 state = DSTATE_PHYSPATH;
449 disk->phystype = PHYSTYPE_PHY;
450 }else if ( !strcmp(tok, "file") ) {
451 state = DSTATE_PHYSPATH;
452 disk->phystype = PHYSTYPE_FILE;
453 }else if ( !strcmp(tok, "tap") ) {
454 state = DSTATE_TAP;
455 }else{
456 fprintf(stderr, "Unknown disk type: %s\n", tok);
457 return 0;
458 }
459 tok = p + 1;
460 } else if (*p == ',') {
461 state = DSTATE_VIRTPATH;
462 disk->phystype = PHYSTYPE_EMPTY;
463 disk->physpath = strdup("");
464 tok = p + 1;
465 }
466 break;
467 case DSTATE_TAP:
468 if ( *p == ':' ) {
469 *p = '\0';
470 if ( !strcmp(tok, "aio") ) {
471 disk->phystype = PHYSTYPE_AIO;
472 }else if ( !strcmp(tok, "vhd") ) {
473 disk->phystype = PHYSTYPE_VHD;
474 }else if ( !strcmp(tok, "qcow") ) {
475 disk->phystype = PHYSTYPE_QCOW;
476 }else if ( !strcmp(tok, "qcow2") ) {
477 disk->phystype = PHYSTYPE_QCOW2;
478 }else {
479 fprintf(stderr, "Unknown tapdisk type: %s\n", tok);
480 return 0;
481 }
483 tok = p + 1;
484 state = DSTATE_PHYSPATH;
485 }
486 break;
487 case DSTATE_PHYSPATH:
488 if ( *p == ',' ) {
489 int ioemu_len;
491 *p = '\0';
492 disk->physpath = (*tok) ? strdup(tok) : NULL;
493 tok = p + 1;
495 /* hack for ioemu disk spec */
496 ioemu_len = strlen("ioemu:");
497 state = DSTATE_VIRTPATH;
498 if ( tok + ioemu_len < end &&
499 !strncmp(tok, "ioemu:", ioemu_len)) {
500 tok += ioemu_len;
501 p += ioemu_len;
502 }
503 }
504 break;
505 case DSTATE_VIRTPATH:
506 if ( *p == ',' || *p == ':' || *p == '\0' ) {
507 switch(*p) {
508 case ':':
509 state = DSTATE_VIRTTYPE;
510 break;
511 case ',':
512 state = DSTATE_RW;
513 break;
514 case '\0':
515 state = DSTATE_TERMINAL;
516 break;
517 }
518 if ( tok == p )
519 goto out;
520 *p = '\0';
521 disk->virtpath = (*tok) ? strdup(tok) : NULL;
522 tok = p + 1;
523 }
524 break;
525 case DSTATE_VIRTTYPE:
526 if ( *p == ',' || *p == '\0' ) {
527 *p = '\0';
528 if ( !strcmp(tok, "cdrom") ) {
529 disk->is_cdrom = 1;
530 disk->unpluggable = 1;
531 }else{
532 fprintf(stderr, "Unknown virtual disk type: %s\n", tok);
533 return 0;
534 }
535 tok = p + 1;
536 state = (*p == ',') ? DSTATE_RW : DSTATE_TERMINAL;
537 }
538 break;
539 case DSTATE_RW:
540 if ( *p == '\0' ) {
541 disk->readwrite = (tok[0] == 'w');
542 tok = p + 1;
543 state = DSTATE_TERMINAL;
544 }
545 break;
546 case DSTATE_TERMINAL:
547 goto out;
548 }
549 }
551 out:
552 if ( tok != p || state != DSTATE_TERMINAL ) {
553 fprintf(stderr, "parse error in disk config near '%s'\n", tok);
554 return 0;
555 }
557 return 1;
558 }
560 static void parse_config_data(const char *configfile_filename_report,
561 const char *configfile_data,
562 int configfile_len,
563 libxl_domain_config *d_config,
564 libxl_device_model_info *dm_info)
565 {
566 const char *buf;
567 long l;
568 XLU_Config *config;
569 XLU_ConfigList *vbds, *nics, *pcis, *cvfbs, *net2s, *cpuids;
570 int pci_power_mgmt = 0;
571 int pci_msitranslate = 1;
572 int e;
574 libxl_domain_create_info *c_info = &d_config->c_info;
575 libxl_domain_build_info *b_info = &d_config->b_info;
577 config= xlu_cfg_init(stderr, configfile_filename_report);
578 if (!config) {
579 fprintf(stderr, "Failed to allocate for configuration\n");
580 exit(1);
581 }
583 e= xlu_cfg_readdata(config, configfile_data, configfile_len);
584 if (e) {
585 fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
586 exit(1);
587 }
589 libxl_init_create_info(c_info);
591 c_info->hvm = 0;
592 if (!xlu_cfg_get_string (config, "builder", &buf) &&
593 !strncmp(buf, "hvm", strlen(buf)))
594 c_info->hvm = 1;
596 if (!xlu_cfg_get_long (config, "hap", &l))
597 c_info->hap = l;
599 if (xlu_cfg_replace_string (config, "name", &c_info->name))
600 c_info->name = strdup("test");
602 if (!xlu_cfg_get_string (config, "uuid", &buf) ) {
603 if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
604 fprintf(stderr, "Failed to parse UUID: %s\n", buf);
605 exit(1);
606 }
607 }else{
608 libxl_uuid_generate(&c_info->uuid);
609 }
611 if (!xlu_cfg_get_long(config, "oos", &l))
612 c_info->oos = l;
614 if (!xlu_cfg_get_string (config, "pool", &buf)) {
615 c_info->poolid = -1;
616 cpupool_qualifier_to_cpupoolid(buf, &c_info->poolid, NULL);
617 }
618 c_info->poolname = libxl_cpupoolid_to_name(&ctx, c_info->poolid);
619 if (!c_info->poolname) {
620 fprintf(stderr, "Illegal pool specified\n");
621 exit(1);
622 }
624 libxl_init_build_info(b_info, c_info);
626 /* the following is the actual config parsing with overriding values in the structures */
627 if (!xlu_cfg_get_long (config, "vcpus", &l)) {
628 b_info->max_vcpus = l;
629 b_info->cur_vcpus = (1 << l) - 1;
630 }
632 if (!xlu_cfg_get_long (config, "maxvcpus", &l))
633 b_info->max_vcpus = l;
635 if (!xlu_cfg_get_long (config, "memory", &l)) {
636 b_info->max_memkb = l * 1024;
637 b_info->target_memkb = b_info->max_memkb;
638 }
640 if (!xlu_cfg_get_long (config, "maxmem", &l))
641 b_info->max_memkb = l * 1024;
643 if (xlu_cfg_get_string (config, "on_poweroff", &buf))
644 buf = "destroy";
645 if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
646 fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
647 exit(1);
648 }
650 if (xlu_cfg_get_string (config, "on_reboot", &buf))
651 buf = "restart";
652 if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
653 fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
654 exit(1);
655 }
657 if (xlu_cfg_get_string (config, "on_watchdog", &buf))
658 buf = "destroy";
659 if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
660 fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
661 exit(1);
662 }
665 if (xlu_cfg_get_string (config, "on_crash", &buf))
666 buf = "destroy";
667 if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
668 fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
669 exit(1);
670 }
672 /* libxl_get_required_shadow_memory() must be called after final values
673 * (default or specified) for vcpus and memory are set, because the
674 * calculation depends on those values. */
675 b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l)
676 ? l * 1024
677 : libxl_get_required_shadow_memory(b_info->max_memkb,
678 b_info->max_vcpus);
680 if (!xlu_cfg_get_long (config, "nomigrate", &l))
681 b_info->disable_migrate = l;
683 if (!xlu_cfg_get_long(config, "tsc_mode", &l))
684 b_info->tsc_mode = l;
686 if (!xlu_cfg_get_long (config, "videoram", &l))
687 b_info->video_memkb = l * 1024;
689 xlu_cfg_replace_string (config, "kernel", &b_info->kernel.path);
691 if (!xlu_cfg_get_long (config, "gfx_passthru", &l))
692 dm_info->gfx_passthru = l;
694 if (c_info->hvm == 1) {
695 if (!xlu_cfg_get_long (config, "pae", &l))
696 b_info->u.hvm.pae = l;
697 if (!xlu_cfg_get_long (config, "apic", &l))
698 b_info->u.hvm.apic = l;
699 if (!xlu_cfg_get_long (config, "acpi", &l))
700 b_info->u.hvm.acpi = l;
701 if (!xlu_cfg_get_long (config, "nx", &l))
702 b_info->u.hvm.nx = l;
703 if (!xlu_cfg_get_long (config, "viridian", &l))
704 b_info->u.hvm.viridian = l;
705 if (!xlu_cfg_get_long (config, "hpet", &l))
706 b_info->u.hvm.hpet = l;
707 if (!xlu_cfg_get_long (config, "vpt_align", &l))
708 b_info->u.hvm.vpt_align = l;
709 if (!xlu_cfg_get_long (config, "timer_mode", &l))
710 b_info->u.hvm.timer_mode = l;
711 } else {
712 char *cmdline = NULL;
713 const char *root = NULL, *extra = "";
715 xlu_cfg_get_string (config, "root", &root);
716 xlu_cfg_get_string (config, "extra", &extra);
718 if (root) {
719 if (asprintf(&cmdline, "root=%s %s", root, extra) == -1)
720 cmdline = NULL;
721 } else {
722 cmdline = strdup(extra);
723 }
725 if ((root || extra) && !cmdline) {
726 fprintf(stderr, "Failed to allocate memory for cmdline\n");
727 exit(1);
728 }
730 xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader);
731 xlu_cfg_replace_string (config, "bootloader_args", &b_info->u.pv.bootloader_args);
733 if (!b_info->u.pv.bootloader && !b_info->kernel.path) {
734 fprintf(stderr, "Neither kernel nor bootloader specified\n");
735 exit(1);
736 }
738 b_info->u.pv.cmdline = cmdline;
739 xlu_cfg_replace_string (config, "ramdisk", &b_info->u.pv.ramdisk.path);
740 }
742 if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
743 d_config->num_disks = 0;
744 d_config->disks = NULL;
745 while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
746 libxl_device_disk *disk;
747 char *buf2 = strdup(buf);
749 d_config->disks = (libxl_device_disk *) realloc(d_config->disks, sizeof (libxl_device_disk) * (d_config->num_disks + 1));
750 disk = d_config->disks + d_config->num_disks;
751 if ( !parse_disk_config(disk, buf2) ) {
752 exit(1);
753 }
755 free(buf2);
756 d_config->num_disks++;
757 }
758 }
760 if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
761 d_config->num_vifs = 0;
762 d_config->vifs = NULL;
763 while ((buf = xlu_cfg_get_listitem (nics, d_config->num_vifs)) != NULL) {
764 libxl_device_nic *nic;
765 char *buf2 = strdup(buf);
766 char *p, *p2;
768 d_config->vifs = (libxl_device_nic *) realloc(d_config->vifs, sizeof (libxl_device_nic) * (d_config->num_vifs+1));
769 nic = d_config->vifs + d_config->num_vifs;
770 CHK_ERRNO( libxl_device_nic_init(nic, d_config->num_vifs) );
772 p = strtok(buf2, ",");
773 if (!p)
774 goto skip;
775 do {
776 while (*p == ' ')
777 p++;
778 if ((p2 = strchr(p, '=')) == NULL)
779 break;
780 *p2 = '\0';
781 if (!strcmp(p, "model")) {
782 free(nic->model);
783 nic->model = strdup(p2 + 1);
784 } else if (!strcmp(p, "mac")) {
785 char *p3 = p2 + 1;
786 *(p3 + 2) = '\0';
787 nic->mac[0] = strtol(p3, NULL, 16);
788 p3 = p3 + 3;
789 *(p3 + 2) = '\0';
790 nic->mac[1] = strtol(p3, NULL, 16);
791 p3 = p3 + 3;
792 *(p3 + 2) = '\0';
793 nic->mac[2] = strtol(p3, NULL, 16);
794 p3 = p3 + 3;
795 *(p3 + 2) = '\0';
796 nic->mac[3] = strtol(p3, NULL, 16);
797 p3 = p3 + 3;
798 *(p3 + 2) = '\0';
799 nic->mac[4] = strtol(p3, NULL, 16);
800 p3 = p3 + 3;
801 *(p3 + 2) = '\0';
802 nic->mac[5] = strtol(p3, NULL, 16);
803 } else if (!strcmp(p, "bridge")) {
804 free(nic->bridge);
805 nic->bridge = strdup(p2 + 1);
806 } else if (!strcmp(p, "type")) {
807 if (!strcmp(p2 + 1, "ioemu"))
808 nic->nictype = NICTYPE_IOEMU;
809 else
810 nic->nictype = NICTYPE_VIF;
811 } else if (!strcmp(p, "ip")) {
812 inet_pton(AF_INET, p2 + 1, &nic->ip);
813 } else if (!strcmp(p, "script")) {
814 free(nic->script);
815 nic->script = strdup(p2 + 1);
816 } else if (!strcmp(p, "vifname")) {
817 free(nic->ifname);
818 nic->ifname = strdup(p2 + 1);
819 } else if (!strcmp(p, "backend")) {
820 if(libxl_name_to_domid(&ctx, (p2 + 1), &(nic->backend_domid))) {
821 fprintf(stderr, "Specified backend domain does not exist, defaulting to Dom0\n");
822 nic->backend_domid = 0;
823 }
824 } else if (!strcmp(p, "rate")) {
825 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
826 } else if (!strcmp(p, "accel")) {
827 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
828 }
829 } while ((p = strtok(NULL, ",")) != NULL);
830 skip:
831 free(buf2);
832 d_config->num_vifs++;
833 }
834 }
836 if (!xlu_cfg_get_list(config, "vif2", &net2s, 0, 0)) {
837 d_config->num_vif2s = 0;
838 d_config->vif2s = NULL;
839 while ((buf = xlu_cfg_get_listitem(net2s, d_config->num_vif2s))) {
840 libxl_device_net2 *net2;
841 char *buf2 = strdup(buf);
842 char *p;
844 d_config->vif2s = realloc(d_config->vif2s, sizeof (libxl_device_net2) * (d_config->num_vif2s + 1));
845 net2 = d_config->vif2s + d_config->num_vif2s;
847 libxl_device_net2_init(net2, d_config->num_vif2s);
849 for (p = strtok(buf2, ","); p; p = strtok(NULL, ",")) {
850 char* val;
851 while (isblank(*p))
852 p++;
853 val = strchr(p, '=');
854 if (val == NULL)
855 continue;
856 *val++ = 0;
857 if (!strcmp("front_mac", p)) {
858 libxl_strtomac(val, net2->front_mac);
859 } else if (!strcmp("back_mac", p)) {
860 libxl_strtomac(val, net2->back_mac);
861 } else if (!strcmp("backend", p)) {
862 domain_qualifier_to_domid(val, &net2->backend_domid, 0);
863 } else if (!strcmp("trusted", p)) {
864 net2->trusted = (*val == '1');
865 } else if (!strcmp("back_trusted", p)) {
866 net2->back_trusted = (*val == '1');
867 } else if (!strcmp("bridge", p)) {
868 free(net2->bridge);
869 net2->bridge = strdup(val);
870 } else if (!strcmp("filter_mac", p)) {
871 net2->filter_mac = (*val == '1');
872 } else if (!strcmp("front_filter_mac", p)) {
873 net2->front_filter_mac = (*val == '1');
874 } else if (!strcmp("pdev", p)) {
875 net2->pdev = strtoul(val, NULL, 10);
876 } else if (!strcmp("max_bypasses", p)) {
877 net2->max_bypasses = strtoul(val, NULL, 10);
878 }
879 }
880 free(buf2);
881 d_config->num_vif2s++;
882 }
883 }
885 if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
886 d_config->num_vfbs = 0;
887 d_config->num_vkbs = 0;
888 d_config->vfbs = NULL;
889 d_config->vkbs = NULL;
890 while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
891 libxl_device_vfb *vfb;
892 libxl_device_vkb *vkb;
894 char *buf2 = strdup(buf);
895 char *p, *p2;
897 d_config->vfbs = (libxl_device_vfb *) realloc(d_config->vfbs, sizeof(libxl_device_vfb) * (d_config->num_vfbs + 1));
898 vfb = d_config->vfbs + d_config->num_vfbs;
899 libxl_device_vfb_init(vfb, d_config->num_vfbs);
901 d_config->vkbs = (libxl_device_vkb *) realloc(d_config->vkbs, sizeof(libxl_device_vkb) * (d_config->num_vkbs + 1));
902 vkb = d_config->vkbs + d_config->num_vkbs;
903 libxl_device_vkb_init(vkb, d_config->num_vkbs);
905 p = strtok(buf2, ",");
906 if (!p)
907 goto skip_vfb;
908 do {
909 while (*p == ' ')
910 p++;
911 if ((p2 = strchr(p, '=')) == NULL)
912 break;
913 *p2 = '\0';
914 if (!strcmp(p, "vnc")) {
915 vfb->vnc = atoi(p2 + 1);
916 } else if (!strcmp(p, "vnclisten")) {
917 free(vfb->vnclisten);
918 vfb->vnclisten = strdup(p2 + 1);
919 } else if (!strcmp(p, "vncpasswd")) {
920 free(vfb->vncpasswd);
921 vfb->vncpasswd = strdup(p2 + 1);
922 } else if (!strcmp(p, "vncdisplay")) {
923 vfb->vncdisplay = atoi(p2 + 1);
924 } else if (!strcmp(p, "vncunused")) {
925 vfb->vncunused = atoi(p2 + 1);
926 } else if (!strcmp(p, "keymap")) {
927 free(vfb->keymap);
928 vfb->keymap = strdup(p2 + 1);
929 } else if (!strcmp(p, "sdl")) {
930 vfb->sdl = atoi(p2 + 1);
931 } else if (!strcmp(p, "opengl")) {
932 vfb->opengl = atoi(p2 + 1);
933 } else if (!strcmp(p, "display")) {
934 free(vfb->display);
935 vfb->display = strdup(p2 + 1);
936 } else if (!strcmp(p, "xauthority")) {
937 free(vfb->xauthority);
938 vfb->xauthority = strdup(p2 + 1);
939 }
940 } while ((p = strtok(NULL, ",")) != NULL);
941 skip_vfb:
942 free(buf2);
943 d_config->num_vfbs++;
944 d_config->num_vkbs++;
945 }
946 }
948 if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
949 pci_msitranslate = l;
951 if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
952 pci_power_mgmt = l;
954 if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
955 int i;
956 d_config->num_pcidevs = 0;
957 d_config->pcidevs = NULL;
958 for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
959 libxl_device_pci *pcidev;
961 d_config->pcidevs = (libxl_device_pci *) realloc(d_config->pcidevs, sizeof (libxl_device_pci) * (d_config->num_pcidevs + 1));
962 pcidev = d_config->pcidevs + d_config->num_pcidevs;
963 memset(pcidev, 0x00, sizeof(libxl_device_pci));
965 pcidev->msitranslate = pci_msitranslate;
966 pcidev->power_mgmt = pci_power_mgmt;
967 if (!libxl_device_pci_parse_bdf(&ctx, pcidev, buf))
968 d_config->num_pcidevs++;
969 }
970 }
972 switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
973 case 0:
974 {
975 int i;
976 const char *errstr;
978 for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
979 e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
980 switch (e) {
981 case 0: continue;
982 case 1:
983 errstr = "illegal leaf number";
984 break;
985 case 2:
986 errstr = "illegal subleaf number";
987 break;
988 case 3:
989 errstr = "missing colon";
990 break;
991 case 4:
992 errstr = "invalid register name (must be e[abcd]x)";
993 break;
994 case 5:
995 errstr = "policy string must be exactly 32 characters long";
996 break;
997 default:
998 errstr = "unknown error";
999 break;
1001 fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
1002 fprintf(stderr, " error #%i: %s\n", e, errstr);
1005 break;
1006 case EINVAL: /* config option is not a list, parse as a string */
1007 if (!xlu_cfg_get_string(config, "cpuid", &buf)) {
1008 char *buf2, *p, *strtok_ptr = NULL;
1009 const char *errstr;
1011 buf2 = strdup(buf);
1012 p = strtok_r(buf2, ",", &strtok_ptr);
1013 if (p == NULL) {
1014 free(buf2);
1015 break;
1017 if (strcmp(p, "host")) {
1018 fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
1019 fprintf(stderr, " error: first word must be \"host\"\n");
1020 free(buf2);
1021 break;
1023 for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
1024 p = strtok_r(NULL, ",", &strtok_ptr)) {
1025 e = libxl_cpuid_parse_config(&b_info->cpuid, p);
1026 switch (e) {
1027 case 0: continue;
1028 case 1:
1029 errstr = "missing \"=\" in key=value";
1030 break;
1031 case 2:
1032 errstr = "unknown CPUID flag name";
1033 break;
1034 case 3:
1035 errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
1036 break;
1037 default:
1038 errstr = "unknown error";
1039 break;
1041 fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
1042 fprintf(stderr, " error #%i: %s\n", e, errstr);
1044 free(buf2);
1046 break;
1047 default:
1048 break;
1051 if (c_info->hvm == 1) {
1052 /* init dm from c and b */
1053 libxl_init_dm_info(dm_info, c_info, b_info);
1055 /* then process config related to dm */
1056 xlu_cfg_replace_string (config, "device_model", &dm_info->device_model);
1057 if (!xlu_cfg_get_long (config, "stdvga", &l))
1058 dm_info->stdvga = l;
1059 if (!xlu_cfg_get_long (config, "vnc", &l))
1060 dm_info->vnc = l;
1061 xlu_cfg_replace_string (config, "vnclisten", &dm_info->vnclisten);
1062 xlu_cfg_replace_string (config, "vncpasswd", &dm_info->vncpasswd);
1063 if (!xlu_cfg_get_long (config, "vncdisplay", &l))
1064 dm_info->vncdisplay = l;
1065 if (!xlu_cfg_get_long (config, "vncunused", &l))
1066 dm_info->vncunused = l;
1067 xlu_cfg_replace_string (config, "keymap", &dm_info->keymap);
1068 if (!xlu_cfg_get_long (config, "sdl", &l))
1069 dm_info->sdl = l;
1070 if (!xlu_cfg_get_long (config, "opengl", &l))
1071 dm_info->opengl = l;
1072 if (!xlu_cfg_get_long (config, "nographic", &l))
1073 dm_info->nographic = l;
1074 if (!xlu_cfg_get_long (config, "gfx_passthru", &l))
1075 dm_info->gfx_passthru = l;
1076 xlu_cfg_replace_string (config, "serial", &dm_info->serial);
1077 xlu_cfg_replace_string (config, "boot", &dm_info->boot);
1078 if (!xlu_cfg_get_long (config, "usb", &l))
1079 dm_info->usb = l;
1080 xlu_cfg_replace_string (config, "usbdevice", &dm_info->usbdevice);
1081 xlu_cfg_replace_string (config, "soundhw", &dm_info->soundhw);
1082 if (!xlu_cfg_get_long (config, "xen_platform_pci", &l))
1083 dm_info->xen_platform_pci = l;
1086 dm_info->type = c_info->hvm ? XENFV : XENPV;
1088 xlu_cfg_destroy(config);
1091 static void *xmalloc(size_t sz) {
1092 void *r;
1093 r = malloc(sz);
1094 if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
1095 (unsigned long)sz); exit(-ERROR_FAIL); }
1096 return r;
1099 static void *xrealloc(void *ptr, size_t sz) {
1100 void *r;
1101 if (!sz) { free(ptr); return 0; }
1102 /* realloc(non-0, 0) has a useless return value;
1103 * but xrealloc(anything, 0) is like free
1104 */
1105 r = realloc(ptr, sz);
1106 if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
1107 (unsigned long)sz); exit(-ERROR_FAIL); }
1108 return r;
1111 /* Returns 1 if domain should be restarted, 2 if domain should be renamed then restarted */
1112 static int handle_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1113 libxl_domain_config *d_config, libxl_dominfo *info)
1115 int restart = 0;
1116 enum libxl_action_on_shutdown action;
1118 switch (info->shutdown_reason) {
1119 case SHUTDOWN_poweroff:
1120 action = d_config->on_poweroff;
1121 break;
1122 case SHUTDOWN_reboot:
1123 action = d_config->on_reboot;
1124 break;
1125 case SHUTDOWN_suspend:
1126 return 0;
1127 case SHUTDOWN_crash:
1128 action = d_config->on_crash;
1129 break;
1130 case SHUTDOWN_watchdog:
1131 action = d_config->on_watchdog;
1132 break;
1133 default:
1134 LOG("Unknown shutdown reason code %d. Destroying domain.", info->shutdown_reason);
1135 action = LIBXL_ACTION_DESTROY;
1138 LOG("Action for shutdown reason code %d is %s", info->shutdown_reason, action_on_shutdown_names[action]);
1140 if (action == LIBXL_ACTION_COREDUMP_DESTROY || action == LIBXL_ACTION_COREDUMP_RESTART) {
1141 char *corefile;
1142 int rc;
1144 if (asprintf(&corefile, "/var/xen/dump/%s", d_config->c_info.name) < 0) {
1145 LOG("failed to construct core dump path");
1146 } else {
1147 LOG("dumping core to %s", corefile);
1148 rc=libxl_domain_core_dump(ctx, domid, corefile);
1149 if (rc) LOG("core dump failed (rc=%d).", rc);
1151 /* No point crying over spilled milk, continue on failure. */
1153 if (action == LIBXL_ACTION_COREDUMP_DESTROY)
1154 action = LIBXL_ACTION_DESTROY;
1155 else
1156 action = LIBXL_ACTION_RESTART;
1159 switch (action) {
1160 case LIBXL_ACTION_PRESERVE:
1161 break;
1163 case LIBXL_ACTION_RESTART_RENAME:
1164 restart = 2;
1165 break;
1167 case LIBXL_ACTION_RESTART:
1168 restart = 1;
1169 /* fall-through */
1170 case LIBXL_ACTION_DESTROY:
1171 LOG("Domain %d needs to be cleaned up: destroying the domain", domid);
1172 libxl_domain_destroy(ctx, domid, 0);
1173 break;
1175 case LIBXL_ACTION_COREDUMP_DESTROY:
1176 case LIBXL_ACTION_COREDUMP_RESTART:
1177 /* Already handled these above. */
1178 abort();
1181 return restart;
1184 static int preserve_domain(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1185 libxl_domain_config *d_config, libxl_dominfo *info)
1187 time_t now;
1188 struct tm tm;
1189 char stime[24];
1191 libxl_uuid new_uuid;
1193 int rc;
1195 now = time(NULL);
1196 if (now == ((time_t) -1)) {
1197 LOG("Failed to get current time for domain rename");
1198 return 0;
1201 tzset();
1202 if (gmtime_r(&now, &tm) == NULL) {
1203 LOG("Failed to convert time to UTC");
1204 return 0;
1207 if (!strftime(&stime[0], sizeof(stime), "-%Y%m%dT%H%MZ", &tm)) {
1208 LOG("Failed to format time as a string");
1209 return 0;
1212 libxl_uuid_generate(&new_uuid);
1214 LOG("Preserving domain %d %s with suffix%s", domid, d_config->c_info.name, stime);
1215 rc = libxl_domain_preserve(ctx, domid, &d_config->c_info, stime, new_uuid);
1217 return rc == 0 ? 1 : 0;
1220 struct domain_create {
1221 int debug;
1222 int daemonize;
1223 int paused;
1224 int dryrun;
1225 int quiet;
1226 int console_autoconnect;
1227 const char *config_file;
1228 const char *extra_config; /* extra config string */
1229 const char *restore_file;
1230 int migrate_fd; /* -1 means none */
1231 char **migration_domname_r; /* from malloc */
1232 };
1234 static int freemem(libxl_domain_build_info *b_info, libxl_device_model_info *dm_info)
1236 int rc, retries = 3;
1237 uint32_t need_memkb, free_memkb;
1239 if (!autoballoon)
1240 return 0;
1242 rc = libxl_domain_need_memory(&ctx, b_info, dm_info, &need_memkb);
1243 if (rc < 0)
1244 return rc;
1246 do {
1247 rc = libxl_get_free_memory(&ctx, &free_memkb);
1248 if (rc < 0)
1249 return rc;
1251 if (free_memkb >= need_memkb)
1252 return 0;
1254 rc = libxl_set_memory_target(&ctx, 0, free_memkb - need_memkb, 1, 0);
1255 if (rc < 0)
1256 return rc;
1258 rc = libxl_wait_for_free_memory(&ctx, domid, need_memkb, 10);
1259 if (!rc)
1260 return 0;
1261 else if (rc != ERROR_NOMEM)
1262 return rc;
1264 /* the memory target has been reached but the free memory is still
1265 * not enough: loop over again */
1266 rc = libxl_wait_for_memory_target(&ctx, 0, 1);
1267 if (rc < 0)
1268 return rc;
1270 retries--;
1271 } while (retries > 0);
1273 return ERROR_NOMEM;
1276 static int autoconnect_console(libxl_ctx *ctx, uint32_t domid, void *priv)
1278 pid_t *pid = priv;
1280 *pid = fork();
1281 if (*pid < 0) {
1282 perror("unable to fork xenconsole");
1283 return ERROR_FAIL;
1284 } else if (*pid > 0)
1285 return 0;
1287 libxl_ctx_postfork(ctx);
1289 sleep(1);
1290 libxl_primary_console_exec(ctx, domid);
1291 /* Do not return. xl continued in child process */
1292 fprintf(stderr, "Unable to attach console\n");
1293 _exit(1);
1296 static int create_domain(struct domain_create *dom_info)
1298 libxl_domain_config d_config;
1300 int debug = dom_info->debug;
1301 int daemonize = dom_info->daemonize;
1302 int paused = dom_info->paused;
1303 const char *config_file = dom_info->config_file;
1304 const char *extra_config = dom_info->extra_config;
1305 const char *restore_file = dom_info->restore_file;
1306 int migrate_fd = dom_info->migrate_fd;
1308 int fd;
1309 int need_daemon = 1;
1310 int ret, rc;
1311 libxl_waiter *w1 = NULL, *w2 = NULL;
1312 void *config_data = 0;
1313 int config_len = 0;
1314 int restore_fd = -1;
1315 int status = 0;
1316 libxl_console_ready cb;
1317 pid_t child_console_pid = -1;
1318 struct save_file_header hdr;
1320 memset(&d_config, 0x00, sizeof(d_config));
1322 if (restore_file) {
1323 uint8_t *optdata_begin = 0;
1324 const uint8_t *optdata_here = 0;
1325 union { uint32_t u32; char b[4]; } u32buf;
1326 uint32_t badflags;
1328 restore_fd = migrate_fd >= 0 ? migrate_fd :
1329 open(restore_file, O_RDONLY);
1331 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
1332 sizeof(hdr), restore_file, "header") );
1333 if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
1334 fprintf(stderr, "File has wrong magic number -"
1335 " corrupt or for a different tool?\n");
1336 return ERROR_INVAL;
1338 if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
1339 fprintf(stderr, "File has wrong byte order\n");
1340 return ERROR_INVAL;
1342 fprintf(stderr, "Loading new save file %s"
1343 " (new xl fmt info"
1344 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
1345 restore_file, hdr.mandatory_flags, hdr.optional_flags,
1346 hdr.optional_data_len);
1348 badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
1349 if (badflags) {
1350 fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
1351 "which are not supported; need newer xl\n",
1352 badflags);
1353 return ERROR_INVAL;
1355 if (hdr.optional_data_len) {
1356 optdata_begin = xmalloc(hdr.optional_data_len);
1357 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
1358 hdr.optional_data_len, restore_file, "optdata") );
1361 #define OPTDATA_LEFT (hdr.optional_data_len - (optdata_here - optdata_begin))
1362 #define WITH_OPTDATA(amt, body) \
1363 if (OPTDATA_LEFT < (amt)) { \
1364 fprintf(stderr, "Savefile truncated.\n"); \
1365 return ERROR_INVAL; \
1366 } else { \
1367 body; \
1368 optdata_here += (amt); \
1371 optdata_here = optdata_begin;
1373 if (OPTDATA_LEFT) {
1374 fprintf(stderr, " Savefile contains xl domain config\n");
1375 WITH_OPTDATA(4, {
1376 memcpy(u32buf.b, optdata_here, 4);
1377 config_len = u32buf.u32;
1378 });
1379 WITH_OPTDATA(config_len, {
1380 config_data = xmalloc(config_len);
1381 memcpy(config_data, optdata_here, config_len);
1382 });
1387 if (config_file) {
1388 free(config_data); config_data = 0;
1389 ret = libxl_read_file_contents(&ctx, config_file,
1390 &config_data, &config_len);
1391 if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
1392 config_file, strerror(errno)); return ERROR_FAIL; }
1393 if (!restore_file && extra_config && strlen(extra_config)) {
1394 if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
1395 fprintf(stderr, "Failed to attach extra configration\n");
1396 return ERROR_FAIL;
1398 /* allocate space for the extra config plus two EOLs plus \0 */
1399 config_data = realloc(config_data, config_len
1400 + strlen(extra_config) + 2 + 1);
1401 if (!config_data) {
1402 fprintf(stderr, "Failed to realloc config_data\n");
1403 return ERROR_FAIL;
1405 config_len += sprintf(config_data + config_len, "\n%s\n",
1406 extra_config);
1408 } else {
1409 if (!config_data) {
1410 fprintf(stderr, "Config file not specified and"
1411 " none in save file\n");
1412 return ERROR_INVAL;
1414 config_file = "<saved>";
1417 if (!dom_info->quiet)
1418 printf("Parsing config file %s\n", config_file);
1420 parse_config_data(config_file, config_data, config_len, &d_config, &d_config.dm_info);
1422 ret = 0;
1423 if (dom_info->dryrun)
1424 goto out;
1426 if (migrate_fd >= 0) {
1427 if (d_config.c_info.name) {
1428 /* when we receive a domain we get its name from the config
1429 * file; and we receive it to a temporary name */
1430 assert(!common_domname);
1432 common_domname = d_config.c_info.name;
1433 d_config.c_info.name = 0; /* steals allocation from config */
1435 if (asprintf(&d_config.c_info.name,
1436 "%s--incoming", common_domname) < 0) {
1437 fprintf(stderr, "Failed to allocate memory in asprintf\n");
1438 exit(1);
1440 *dom_info->migration_domname_r = strdup(d_config.c_info.name);
1444 if (debug)
1445 printf_info(-1, &d_config, &d_config.dm_info);
1447 start:
1448 domid = -1;
1450 rc = acquire_lock();
1451 if (rc < 0)
1452 goto error_out;
1454 ret = freemem(&d_config.b_info, &d_config.dm_info);
1455 if (ret < 0) {
1456 fprintf(stderr, "failed to free memory for the domain\n");
1457 ret = ERROR_FAIL;
1458 goto error_out;
1461 if ( dom_info->console_autoconnect ) {
1462 cb = autoconnect_console;
1463 }else{
1464 cb = NULL;
1467 if ( restore_file ) {
1468 ret = libxl_domain_create_restore(&ctx, &d_config,
1469 cb, &child_console_pid,
1470 &domid, restore_fd);
1471 }else{
1472 ret = libxl_domain_create_new(&ctx, &d_config,
1473 cb, &child_console_pid, &domid);
1475 if ( ret )
1476 goto error_out;
1478 ret = libxl_userdata_store(&ctx, domid, "xl",
1479 config_data, config_len);
1480 if (ret) {
1481 perror("cannot save config file");
1482 ret = ERROR_FAIL;
1483 goto error_out;
1486 release_lock();
1488 if (!paused)
1489 libxl_domain_unpause(&ctx, domid);
1491 ret = domid; /* caller gets success in parent */
1492 if (!daemonize)
1493 goto out;
1495 if (need_daemon) {
1496 char *fullname, *name;
1497 pid_t child1, got_child;
1498 int nullfd;
1500 child1 = libxl_fork(&ctx);
1501 if (child1) {
1502 printf("Daemon running with PID %d\n", child1);
1504 for (;;) {
1505 got_child = waitpid(child1, &status, 0);
1506 if (got_child == child1) break;
1507 assert(got_child == -1);
1508 if (errno != EINTR) {
1509 perror("failed to wait for daemonizing child");
1510 ret = ERROR_FAIL;
1511 goto error_out;
1514 if (status) {
1515 libxl_report_child_exitstatus(&ctx, XTL_ERROR,
1516 "daemonizing child", child1, status);
1517 ret = ERROR_FAIL;
1518 goto error_out;
1520 ret = domid;
1521 goto out;
1524 rc = libxl_ctx_postfork(&ctx);
1525 if (rc) {
1526 LOG("failed to reinitialise context after fork");
1527 exit(-1);
1530 if (asprintf(&name, "xl-%s", d_config.c_info.name) < 0) {
1531 LOG("Failed to allocate memory in asprintf");
1532 exit(1);
1534 rc = libxl_create_logfile(&ctx, name, &fullname);
1535 if (rc) {
1536 LOG("failed to open logfile %s: %s",fullname,strerror(errno));
1537 exit(-1);
1540 CHK_ERRNO(( logfile = open(fullname, O_WRONLY|O_CREAT, 0644) )<0);
1541 free(fullname);
1542 free(name);
1544 CHK_ERRNO(( nullfd = open("/dev/null", O_RDONLY) )<0);
1545 dup2(nullfd, 0);
1546 dup2(logfile, 1);
1547 dup2(logfile, 2);
1549 CHK_ERRNO(daemon(0, 1) < 0);
1550 need_daemon = 0;
1552 LOG("Waiting for domain %s (domid %d) to die [pid %ld]",
1553 d_config.c_info.name, domid, (long)getpid());
1554 w1 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter) * d_config.num_disks);
1555 w2 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter));
1556 libxl_wait_for_disk_ejects(&ctx, domid, d_config.disks, d_config.num_disks, w1);
1557 libxl_wait_for_domain_death(&ctx, domid, w2);
1558 libxl_get_wait_fd(&ctx, &fd);
1559 while (1) {
1560 int ret;
1561 fd_set rfds;
1562 libxl_dominfo info;
1563 libxl_event event;
1564 libxl_device_disk disk;
1566 FD_ZERO(&rfds);
1567 FD_SET(fd, &rfds);
1569 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
1570 if (!ret)
1571 continue;
1572 libxl_get_event(&ctx, &event);
1573 switch (event.type) {
1574 case LIBXL_EVENT_DOMAIN_DEATH:
1575 ret = libxl_event_get_domain_death_info(&ctx, domid, &event, &info);
1577 if (ret < 0) continue;
1579 LOG("Domain %d is dead", domid);
1581 if (ret) {
1582 switch (handle_domain_death(&ctx, domid, &event, &d_config, &info)) {
1583 case 2:
1584 if (!preserve_domain(&ctx, domid, &event, &d_config, &info)) {
1585 /* If we fail then exit leaving the old domain in place. */
1586 ret = -1;
1587 goto out;
1590 /* Otherwise fall through and restart. */
1591 case 1:
1593 libxl_free_waiter(w1);
1594 libxl_free_waiter(w2);
1595 free(w1);
1596 free(w2);
1598 /*
1599 * Do not attempt to reconnect if we come round again due to a
1600 * guest reboot -- the stdin/out will be disconnected by then.
1601 */
1602 dom_info->console_autoconnect = 0;
1604 /* Some settings only make sense on first boot. */
1605 paused = 0;
1606 if (common_domname
1607 && strcmp(d_config.c_info.name, common_domname)) {
1608 d_config.c_info.name = strdup(common_domname);
1611 /*
1612 * XXX FIXME: If this sleep is not there then domain
1613 * re-creation fails sometimes.
1614 */
1615 LOG("Done. Rebooting now");
1616 sleep(2);
1617 goto start;
1618 case 0:
1619 LOG("Done. Exiting now");
1620 ret = 0;
1621 goto out;
1623 } else {
1624 LOG("Unable to get domain death info, quitting");
1625 goto out;
1627 break;
1628 case LIBXL_EVENT_DISK_EJECT:
1629 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
1630 libxl_cdrom_insert(&ctx, domid, &disk);
1631 break;
1633 libxl_free_event(&event);
1636 error_out:
1637 release_lock();
1638 if (domid > 0)
1639 libxl_domain_destroy(&ctx, domid, 0);
1641 out:
1642 if (logfile != 2)
1643 close(logfile);
1645 libxl_domain_config_destroy(&d_config);
1647 free(config_data);
1649 waitpid_out:
1650 if (child_console_pid > 0 &&
1651 waitpid(child_console_pid, &status, 0) < 0 && errno == EINTR)
1652 goto waitpid_out;
1654 /*
1655 * If we have daemonized then do not return to the caller -- this has
1656 * already happened in the parent.
1657 */
1658 if ( !need_daemon )
1659 exit(ret);
1661 return ret;
1664 void help(const char *command)
1666 int i;
1667 struct cmd_spec *cmd;
1669 if (!command || !strcmp(command, "help")) {
1670 printf("Usage xl [-v] <subcommand> [args]\n\n");
1671 printf("xl full list of subcommands:\n\n");
1672 for (i = 0; i < cmdtable_len; i++)
1673 printf(" %-20s%s\n",
1674 cmd_table[i].cmd_name, cmd_table[i].cmd_desc);
1675 } else {
1676 cmd = cmdtable_lookup(command);
1677 if (cmd) {
1678 printf("Usage: xl [-v] %s %s\n\n%s.\n\n",
1679 cmd->cmd_name,
1680 cmd->cmd_usage,
1681 cmd->cmd_desc);
1682 if (cmd->cmd_option)
1683 printf("Options:\n\n%s\n", cmd->cmd_option);
1685 else {
1686 printf("command \"%s\" not implemented\n", command);
1691 static int64_t parse_mem_size_kb(const char *mem)
1693 char *endptr;
1694 int64_t kbytes;
1696 kbytes = strtoll(mem, &endptr, 10);
1698 if (strlen(endptr) > 1)
1699 return -1;
1701 switch (tolower((uint8_t)*endptr)) {
1702 case 't':
1703 kbytes <<= 10;
1704 case 'g':
1705 kbytes <<= 10;
1706 case '\0':
1707 case 'm':
1708 kbytes <<= 10;
1709 case 'k':
1710 break;
1711 case 'b':
1712 kbytes >>= 10;
1713 break;
1714 default:
1715 return -1;
1718 return kbytes;
1721 static int set_memory_max(const char *p, const char *mem)
1723 int64_t memorykb;
1724 int rc;
1726 find_domain(p);
1728 memorykb = parse_mem_size_kb(mem);
1729 if (memorykb == -1) {
1730 fprintf(stderr, "invalid memory size: %s\n", mem);
1731 exit(3);
1734 rc = libxl_domain_setmaxmem(&ctx, domid, memorykb);
1736 return rc;
1739 int main_memmax(int argc, char **argv)
1741 int opt = 0;
1742 char *p = NULL, *mem;
1743 int rc;
1745 while ((opt = getopt(argc, argv, "h")) != -1) {
1746 switch (opt) {
1747 case 'h':
1748 help("mem-max");
1749 exit(0);
1750 default:
1751 fprintf(stderr, "option not supported\n");
1752 break;
1755 if (optind >= argc - 1) {
1756 help("mem-max");
1757 return 2;
1760 p = argv[optind];
1761 mem = argv[optind + 1];
1763 rc = set_memory_max(p, mem);
1764 if (rc) {
1765 fprintf(stderr, "cannot set domid %d static max memory to : %s\n", domid, mem);
1766 return 1;
1769 return 0;
1772 static void set_memory_target(const char *p, const char *mem)
1774 long long int memorykb;
1776 find_domain(p);
1778 memorykb = parse_mem_size_kb(mem);
1779 if (memorykb == -1) {
1780 fprintf(stderr, "invalid memory size: %s\n", mem);
1781 exit(3);
1784 libxl_set_memory_target(&ctx, domid, memorykb, 0, /* enforce */ 1);
1787 int main_memset(int argc, char **argv)
1789 int opt = 0;
1790 const char *p = NULL, *mem;
1792 while ((opt = getopt(argc, argv, "h:")) != -1) {
1793 switch (opt) {
1794 case 'h':
1795 help("mem-set");
1796 return 0;
1797 default:
1798 fprintf(stderr, "option not supported\n");
1799 break;
1802 if (optind >= argc - 1) {
1803 help("mem-set");
1804 return 2;
1807 p = argv[optind];
1808 mem = argv[optind + 1];
1810 set_memory_target(p, mem);
1811 return 0;
1814 static void cd_insert(const char *dom, const char *virtdev, char *phys)
1816 libxl_device_disk disk; /* we don't free disk's contents */
1817 char *p;
1819 find_domain(dom);
1821 disk.backend_domid = 0;
1822 disk.domid = domid;
1823 if (phys) {
1824 p = strchr(phys, ':');
1825 if (!p) {
1826 fprintf(stderr, "No type specified, ");
1827 disk.physpath = phys;
1828 if (!strncmp(phys, "/dev", 4)) {
1829 fprintf(stderr, "assuming phy:\n");
1830 disk.phystype = PHYSTYPE_PHY;
1831 } else {
1832 fprintf(stderr, "assuming file:\n");
1833 disk.phystype = PHYSTYPE_FILE;
1835 } else {
1836 *p = '\0';
1837 p++;
1838 disk.physpath = p;
1839 libxl_string_to_phystype(&ctx, phys, &disk.phystype);
1841 } else {
1842 disk.physpath = strdup("");
1843 disk.phystype = PHYSTYPE_EMPTY;
1845 disk.virtpath = (char*)virtdev;
1846 disk.unpluggable = 1;
1847 disk.readwrite = 0;
1848 disk.is_cdrom = 1;
1850 libxl_cdrom_insert(&ctx, domid, &disk);
1853 int main_cd_eject(int argc, char **argv)
1855 int opt = 0;
1856 const char *p = NULL, *virtdev;
1858 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1859 switch (opt) {
1860 case 'h':
1861 help("cd-eject");
1862 return 0;
1863 default:
1864 fprintf(stderr, "option not supported\n");
1865 break;
1868 if (optind >= argc - 1) {
1869 help("cd-eject");
1870 return 2;
1873 p = argv[optind];
1874 virtdev = argv[optind + 1];
1876 cd_insert(p, virtdev, NULL);
1877 return 0;
1880 int main_cd_insert(int argc, char **argv)
1882 int opt = 0;
1883 const char *p = NULL, *virtdev;
1884 char *file = NULL; /* modified by cd_insert tokenising it */
1886 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1887 switch (opt) {
1888 case 'h':
1889 help("cd-insert");
1890 return 0;
1891 default:
1892 fprintf(stderr, "option not supported\n");
1893 break;
1896 if (optind >= argc - 2) {
1897 help("cd-insert");
1898 return 2;
1901 p = argv[optind];
1902 virtdev = argv[optind + 1];
1903 file = argv[optind + 2];
1905 cd_insert(p, virtdev, file);
1906 return 0;
1909 int main_console(int argc, char **argv)
1911 int opt = 0, num = 0;
1912 libxl_console_constype type = 0;
1914 while ((opt = getopt(argc, argv, "hn:t:")) != -1) {
1915 switch (opt) {
1916 case 'h':
1917 help("console");
1918 return 0;
1919 case 't':
1920 if (!strcmp(optarg, "pv"))
1921 type = LIBXL_CONSTYPE_PV;
1922 else if (!strcmp(optarg, "serial"))
1923 type = LIBXL_CONSTYPE_SERIAL;
1924 else {
1925 fprintf(stderr, "console type supported are: pv, serial\n");
1926 return 2;
1928 break;
1929 case 'n':
1930 num = atoi(optarg);
1931 break;
1932 default:
1933 fprintf(stderr, "option not supported\n");
1934 break;
1937 if (optind >= argc) {
1938 help("console");
1939 return 2;
1942 find_domain(argv[optind]);
1943 if (!type)
1944 libxl_primary_console_exec(&ctx, domid);
1945 else
1946 libxl_console_exec(&ctx, domid, num, type);
1947 fprintf(stderr, "Unable to attach console\n");
1948 return 1;
1951 static int vncviewer(const char *domain_spec, int autopass)
1953 find_domain(domain_spec);
1954 libxl_vncviewer_exec(&ctx, domid, autopass);
1955 fprintf(stderr, "Unable to execute vncviewer\n");
1956 return 1;
1959 int main_vncviewer(int argc, char **argv)
1961 static const struct option long_options[] = {
1962 {"autopass", 0, 0, 'a'},
1963 {"vncviewer-autopass", 0, 0, 'a'},
1964 {"help", 0, 0, 'h'},
1965 {0, 0, 0, 0}
1966 };
1967 int opt, autopass = 0;
1969 while (1) {
1970 opt = getopt_long(argc, argv, "ah", long_options, NULL);
1971 if (opt == -1)
1972 break;
1974 switch (opt) {
1975 case 'a':
1976 autopass = 1;
1977 break;
1978 case 'h':
1979 help("vncviewer");
1980 return 0;
1981 default:
1982 fprintf(stderr, "option not supported\n");
1983 break;
1987 if (argc - optind != 1) {
1988 help("vncviewer");
1989 return 2;
1992 if (vncviewer(argv[optind], autopass))
1993 return 1;
1994 return 0;
1997 static void pcilist_assignable(void)
1999 libxl_device_pci *pcidevs;
2000 int num, i;
2002 if ( libxl_device_pci_list_assignable(&ctx, &pcidevs, &num) )
2003 return;
2004 for (i = 0; i < num; i++) {
2005 printf("%04x:%02x:%02x.%01x\n",
2006 pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
2008 free(pcidevs);
2011 int main_pcilist_assignable(int argc, char **argv)
2013 int opt;
2015 while ((opt = getopt(argc, argv, "h")) != -1) {
2016 switch (opt) {
2017 case 'h':
2018 help("pci-list-assignable-devices");
2019 return 0;
2020 default:
2021 fprintf(stderr, "option not supported\n");
2022 break;
2026 pcilist_assignable();
2027 return 0;
2030 static void pcilist(const char *dom)
2032 libxl_device_pci *pcidevs;
2033 int num, i;
2035 find_domain(dom);
2037 if (libxl_device_pci_list_assigned(&ctx, &pcidevs, domid, &num))
2038 return;
2039 printf("VFn domain bus slot func\n");
2040 for (i = 0; i < num; i++) {
2041 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);
2042 libxl_device_pci_destroy(&pcidevs[i]);
2044 free(pcidevs);
2047 int main_pcilist(int argc, char **argv)
2049 int opt;
2050 const char *domname = NULL;
2052 while ((opt = getopt(argc, argv, "h")) != -1) {
2053 switch (opt) {
2054 case 'h':
2055 help("pci-list");
2056 return 0;
2057 default:
2058 fprintf(stderr, "option not supported\n");
2059 break;
2062 if (optind >= argc) {
2063 help("pci-list");
2064 return 2;
2067 domname = argv[optind];
2069 pcilist(domname);
2070 return 0;
2073 static void pcidetach(const char *dom, const char *bdf, int force)
2075 libxl_device_pci pcidev;
2077 find_domain(dom);
2079 memset(&pcidev, 0x00, sizeof(pcidev));
2080 if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
2081 fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
2082 exit(2);
2084 libxl_device_pci_remove(&ctx, domid, &pcidev, force);
2085 libxl_device_pci_destroy(&pcidev);
2088 int main_pcidetach(int argc, char **argv)
2090 int opt;
2091 int force = 0;
2092 const char *domname = NULL, *bdf = NULL;
2094 while ((opt = getopt(argc, argv, "hf")) != -1) {
2095 switch (opt) {
2096 case 'h':
2097 help("pci-detach");
2098 return 0;
2099 case 'f':
2100 force = 1;
2101 break;
2102 default:
2103 fprintf(stderr, "option not supported\n");
2104 break;
2107 if (optind >= argc - 1) {
2108 help("pci-detach");
2109 return 2;
2112 domname = argv[optind];
2113 bdf = argv[optind + 1];
2115 pcidetach(domname, bdf, force);
2116 return 0;
2118 static void pciattach(const char *dom, const char *bdf, const char *vs)
2120 libxl_device_pci pcidev;
2122 find_domain(dom);
2124 memset(&pcidev, 0x00, sizeof(pcidev));
2125 if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
2126 fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
2127 exit(2);
2129 libxl_device_pci_add(&ctx, domid, &pcidev);
2130 libxl_device_pci_destroy(&pcidev);
2133 int main_pciattach(int argc, char **argv)
2135 int opt;
2136 const char *domname = NULL, *bdf = NULL, *vs = NULL;
2138 while ((opt = getopt(argc, argv, "h")) != -1) {
2139 switch (opt) {
2140 case 'h':
2141 help("pci-attach");
2142 return 0;
2143 default:
2144 fprintf(stderr, "option not supported\n");
2145 break;
2148 if (optind >= argc - 1) {
2149 help("pci-attach");
2150 return 2;
2153 domname = argv[optind];
2154 bdf = argv[optind + 1];
2156 if (optind + 1 < argc)
2157 vs = argv[optind + 2];
2159 pciattach(domname, bdf, vs);
2160 return 0;
2163 static void pause_domain(const char *p)
2165 find_domain(p);
2166 libxl_domain_pause(&ctx, domid);
2169 static void unpause_domain(const char *p)
2171 find_domain(p);
2172 libxl_domain_unpause(&ctx, domid);
2175 static void destroy_domain(const char *p)
2177 int rc;
2178 find_domain(p);
2179 if (domid == 0) {
2180 fprintf(stderr, "Cannot destroy privileged domain 0.\n\n");
2181 exit(-1);
2183 rc = libxl_domain_destroy(&ctx, domid, 0);
2184 if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n.",rc); exit(-1); }
2187 static void shutdown_domain(const char *p, int wait)
2189 int rc;
2191 find_domain(p);
2192 rc=libxl_domain_shutdown(&ctx, domid, 0);
2193 if (rc) { fprintf(stderr,"shutdown failed (rc=%d)\n.",rc);exit(-1); }
2195 if (wait) {
2196 libxl_waiter waiter;
2197 int fd;
2199 libxl_wait_for_domain_death(&ctx, domid, &waiter);
2201 libxl_get_wait_fd(&ctx, &fd);
2203 while (wait) {
2204 fd_set rfds;
2205 libxl_event event;
2206 libxl_dominfo info;
2208 FD_ZERO(&rfds);
2209 FD_SET(fd, &rfds);
2211 if (!select(fd + 1, &rfds, NULL, NULL, NULL))
2212 continue;
2214 libxl_get_event(&ctx, &event);
2216 if (event.type == LIBXL_EVENT_DOMAIN_DEATH) {
2217 if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info) < 0)
2218 continue;
2220 LOG("Domain %d is dead", domid);
2221 wait = 0;
2224 libxl_free_event(&event);
2226 libxl_free_waiter(&waiter);
2230 static void reboot_domain(const char *p)
2232 int rc;
2233 find_domain(p);
2234 rc=libxl_domain_shutdown(&ctx, domid, 1);
2235 if (rc) { fprintf(stderr,"reboot failed (rc=%d)\n.",rc);exit(-1); }
2238 static void list_domains_details(const libxl_dominfo *info, int nb_domain)
2240 libxl_domain_config d_config;
2242 char *config_file;
2243 uint8_t *data;
2244 int i, len, rc;
2245 libxl_device_model_info dm_info;
2247 for (i = 0; i < nb_domain; i++) {
2248 /* no detailed info available on dom0 */
2249 if (info[i].domid == 0)
2250 continue;
2251 rc = libxl_userdata_retrieve(&ctx, info[i].domid, "xl", &data, &len);
2252 if (rc)
2253 continue;
2254 CHK_ERRNO(asprintf(&config_file, "<domid %d data>", info[i].domid));
2255 memset(&d_config, 0x00, sizeof(d_config));
2256 parse_config_data(config_file, (char *)data, len, &d_config, &dm_info);
2257 printf_info(info[i].domid, &d_config, &dm_info);
2258 libxl_domain_config_destroy(&d_config);
2259 free(data);
2260 free(config_file);
2264 static void list_domains(int verbose, const libxl_dominfo *info, int nb_domain)
2266 int i;
2267 static const char shutdown_reason_letters[]= "-rscw";
2269 printf("Name ID Mem VCPUs\tState\tTime(s)");
2270 if (verbose) printf(" UUID Reason-Code");
2271 printf("\n");
2272 for (i = 0; i < nb_domain; i++) {
2273 char *domname;
2274 unsigned shutdown_reason;
2275 domname = libxl_domid_to_name(&ctx, info[i].domid);
2276 shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
2277 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f",
2278 domname,
2279 info[i].domid,
2280 (unsigned long) (info[i].current_memkb / 1024),
2281 info[i].vcpu_online,
2282 info[i].running ? 'r' : '-',
2283 info[i].blocked ? 'b' : '-',
2284 info[i].paused ? 'p' : '-',
2285 info[i].shutdown ? 's' : '-',
2286 (shutdown_reason >= 0 &&
2287 shutdown_reason < sizeof(shutdown_reason_letters)-1
2288 ? shutdown_reason_letters[shutdown_reason] : '?'),
2289 info[i].dying ? 'd' : '-',
2290 ((float)info[i].cpu_time / 1e9));
2291 free(domname);
2292 if (verbose) {
2293 printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
2294 if (info[i].shutdown) printf(" %8x", shutdown_reason);
2295 else printf(" %8s", "-");
2297 putchar('\n');
2301 static void list_vm(void)
2303 libxl_vminfo *info;
2304 char *domname;
2305 int nb_vm, i;
2307 info = libxl_list_vm(&ctx, &nb_vm);
2309 if (info < 0) {
2310 fprintf(stderr, "libxl_domain_infolist failed.\n");
2311 exit(1);
2313 printf("UUID ID name\n");
2314 for (i = 0; i < nb_vm; i++) {
2315 domname = libxl_domid_to_name(&ctx, info[i].domid);
2316 printf(LIBXL_UUID_FMT " %d %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
2317 info[i].domid, domname);
2318 free(domname);
2320 free(info);
2323 static void save_domain_core_begin(const char *domain_spec,
2324 const char *override_config_file,
2325 uint8_t **config_data_r,
2326 int *config_len_r)
2328 int rc;
2330 find_domain(domain_spec);
2332 /* configuration file in optional data: */
2334 if (override_config_file) {
2335 void *config_v = 0;
2336 rc = libxl_read_file_contents(&ctx, override_config_file,
2337 &config_v, config_len_r);
2338 *config_data_r = config_v;
2339 } else {
2340 rc = libxl_userdata_retrieve(&ctx, domid, "xl",
2341 config_data_r, config_len_r);
2343 if (rc) {
2344 fputs("Unable to get config file\n",stderr);
2345 exit(2);
2349 static void save_domain_core_writeconfig(int fd, const char *filename,
2350 const uint8_t *config_data, int config_len)
2352 struct save_file_header hdr;
2353 uint8_t *optdata_begin;
2354 union { uint32_t u32; char b[4]; } u32buf;
2356 memset(&hdr, 0, sizeof(hdr));
2357 memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
2358 hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
2360 optdata_begin= 0;
2362 #define ADD_OPTDATA(ptr, len) ({ \
2363 if ((len)) { \
2364 hdr.optional_data_len += (len); \
2365 optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
2366 memcpy(optdata_begin + hdr.optional_data_len - (len), \
2367 (ptr), (len)); \
2368 } \
2369 })
2371 u32buf.u32 = config_len;
2372 ADD_OPTDATA(u32buf.b, 4);
2373 ADD_OPTDATA(config_data, config_len);
2375 /* that's the optional data */
2377 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2378 &hdr, sizeof(hdr), filename, "header") );
2379 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2380 optdata_begin, hdr.optional_data_len, filename, "header") );
2382 fprintf(stderr, "Saving to %s new xl format (info"
2383 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
2384 filename, hdr.mandatory_flags, hdr.optional_flags,
2385 hdr.optional_data_len);
2388 static int save_domain(const char *p, const char *filename, int checkpoint,
2389 const char *override_config_file)
2391 int fd;
2392 uint8_t *config_data;
2393 int config_len;
2395 save_domain_core_begin(p, override_config_file, &config_data, &config_len);
2397 if (!config_len) {
2398 fputs(" Savefile will not contain xl domain config\n", stderr);
2401 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
2402 if (fd < 0) {
2403 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
2404 exit(2);
2407 save_domain_core_writeconfig(fd, filename, config_data, config_len);
2409 CHK_ERRNO(libxl_domain_suspend(&ctx, NULL, domid, fd));
2410 close(fd);
2412 if (checkpoint)
2413 libxl_domain_unpause(&ctx, domid);
2414 else
2415 libxl_domain_destroy(&ctx, domid, 0);
2417 exit(0);
2420 static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
2421 const char *what, const char *rune) {
2422 char buf[msgsz];
2423 const char *stream;
2424 int rc;
2426 stream = rune ? "migration receiver stream" : "migration stream";
2427 rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
2428 if (rc) return ERROR_FAIL;
2430 if (memcmp(buf, msg, msgsz)) {
2431 fprintf(stderr, "%s contained unexpected data instead of %s\n",
2432 stream, what);
2433 if (rune)
2434 fprintf(stderr, "(command run was: %s )\n", rune);
2435 return ERROR_FAIL;
2437 return 0;
2440 static void migration_child_report(pid_t migration_child, int recv_fd) {
2441 pid_t child;
2442 int status, sr;
2443 struct timeval now, waituntil, timeout;
2444 static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
2446 if (!migration_child) return;
2448 CHK_ERRNO( gettimeofday(&waituntil, 0) );
2449 waituntil.tv_sec += 2;
2451 for (;;) {
2452 child = waitpid(migration_child, &status, WNOHANG);
2454 if (child == migration_child) {
2455 if (status)
2456 libxl_report_child_exitstatus(&ctx, XTL_INFO,
2457 "migration target process",
2458 migration_child, status);
2459 break;
2461 if (child == -1) {
2462 if (errno == EINTR) continue;
2463 fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
2464 (long)migration_child, strerror(errno));
2465 break;
2467 assert(child == 0);
2469 CHK_ERRNO( gettimeofday(&now, 0) );
2470 if (timercmp(&now, &waituntil, >)) {
2471 fprintf(stderr, "migration child [%ld] not exiting, no longer"
2472 " waiting (exit status will be unreported)\n",
2473 (long)migration_child);
2474 break;
2476 timersub(&waituntil, &now, &timeout);
2478 if (recv_fd >= 0) {
2479 fd_set readfds, exceptfds;
2480 FD_ZERO(&readfds);
2481 FD_ZERO(&exceptfds);
2482 FD_SET(recv_fd, &readfds);
2483 FD_SET(recv_fd, &exceptfds);
2484 sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
2485 } else {
2486 if (timercmp(&timeout, &pollinterval, >))
2487 timeout = pollinterval;
2488 sr = select(0,0,0,0, &timeout);
2490 if (sr > 0) {
2491 recv_fd = -1;
2492 } else if (sr == 0) {
2493 } else if (sr == -1) {
2494 if (errno != EINTR) {
2495 fprintf(stderr, "migration child [%ld] exit wait select"
2496 " failed unexpectedly: %s\n",
2497 (long)migration_child, strerror(errno));
2498 break;
2502 migration_child = 0;
2505 static void migrate_domain(const char *domain_spec, const char *rune,
2506 const char *override_config_file)
2508 pid_t child = -1;
2509 int rc;
2510 int sendpipe[2], recvpipe[2];
2511 int send_fd, recv_fd;
2512 libxl_domain_suspend_info suspinfo;
2513 char *away_domname;
2514 char rc_buf;
2515 uint8_t *config_data;
2516 int config_len;
2518 save_domain_core_begin(domain_spec, override_config_file,
2519 &config_data, &config_len);
2521 if (!config_len) {
2522 fprintf(stderr, "No config file stored for running domain and "
2523 "none supplied - cannot migrate.\n");
2524 exit(1);
2527 MUST( libxl_pipe(&ctx, sendpipe) );
2528 MUST( libxl_pipe(&ctx, recvpipe) );
2530 child = libxl_fork(&ctx);
2531 if (child==-1) exit(1);
2533 if (!child) {
2534 dup2(sendpipe[0], 0);
2535 dup2(recvpipe[1], 1);
2536 close(sendpipe[0]); close(sendpipe[1]);
2537 close(recvpipe[0]); close(recvpipe[1]);
2538 execlp("sh","sh","-c",rune,(char*)0);
2539 perror("failed to exec sh");
2540 exit(-1);
2543 close(sendpipe[0]);
2544 close(recvpipe[1]);
2545 send_fd = sendpipe[1];
2546 recv_fd = recvpipe[0];
2548 signal(SIGPIPE, SIG_IGN);
2549 /* if receiver dies, we get an error and can clean up
2550 rather than just dying */
2552 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
2553 sizeof(migrate_receiver_banner)-1,
2554 "banner", rune);
2555 if (rc) {
2556 close(send_fd);
2557 migration_child_report(child, recv_fd);
2558 exit(-rc);
2561 save_domain_core_writeconfig(send_fd, "migration stream",
2562 config_data, config_len);
2564 xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
2566 memset(&suspinfo, 0, sizeof(suspinfo));
2567 suspinfo.flags |= XL_SUSPEND_LIVE;
2568 rc = libxl_domain_suspend(&ctx, &suspinfo, domid, send_fd);
2569 if (rc) {
2570 fprintf(stderr, "migration sender: libxl_domain_suspend failed"
2571 " (rc=%d)\n", rc);
2572 goto failed_resume;
2575 //fprintf(stderr, "migration sender: Transfer complete.\n");
2576 // Should only be printed when debugging as it's a bit messy with
2577 // progress indication.
2579 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
2580 sizeof(migrate_receiver_ready),
2581 "ready message", rune);
2582 if (rc) goto failed_resume;
2584 xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
2586 /* right, at this point we are about give the destination
2587 * permission to rename and resume, so we must first rename the
2588 * domain away ourselves */
2590 fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
2592 if (common_domname) {
2593 if (asprintf(&away_domname, "%s--migratedaway", common_domname) < 0)
2594 goto failed_resume;
2595 rc = libxl_domain_rename(&ctx, domid,
2596 common_domname, away_domname, 0);
2597 if (rc) goto failed_resume;
2600 /* point of no return - as soon as we have tried to say
2601 * "go" to the receiver, it's not safe to carry on. We leave
2602 * the domain renamed to %s--migratedaway in case that's helpful.
2603 */
2605 fprintf(stderr, "migration sender: Giving target permission to start.\n");
2607 rc = libxl_write_exactly(&ctx, send_fd,
2608 migrate_permission_to_go,
2609 sizeof(migrate_permission_to_go),
2610 "migration stream", "GO message");
2611 if (rc) goto failed_badly;
2613 rc = migrate_read_fixedmessage(recv_fd, migrate_report,
2614 sizeof(migrate_report),
2615 "success/failure report message", rune);
2616 if (rc) goto failed_badly;
2618 rc = libxl_read_exactly(&ctx, recv_fd,
2619 &rc_buf, 1,
2620 "migration ack stream", "success/failure status");
2621 if (rc) goto failed_badly;
2623 if (rc_buf) {
2624 fprintf(stderr, "migration sender: Target reports startup failure"
2625 " (status code %d).\n", rc_buf);
2627 rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
2628 sizeof(migrate_permission_to_go),
2629 "permission for sender to resume",
2630 rune);
2631 if (rc) goto failed_badly;
2633 fprintf(stderr, "migration sender: Trying to resume at our end.\n");
2635 if (common_domname) {
2636 libxl_domain_rename(&ctx, domid,
2637 away_domname, common_domname, 0);
2639 rc = libxl_domain_resume(&ctx, domid);
2640 if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
2642 fprintf(stderr, "Migration failed due to problems at target.\n");
2643 exit(-ERROR_FAIL);
2646 fprintf(stderr, "migration sender: Target reports successful startup.\n");
2647 libxl_domain_destroy(&ctx, domid, 1); /* bang! */
2648 fprintf(stderr, "Migration successful.\n");
2649 exit(0);
2651 failed_resume:
2652 close(send_fd);
2653 migration_child_report(child, recv_fd);
2654 fprintf(stderr, "Migration failed, resuming at sender.\n");
2655 libxl_domain_resume(&ctx, domid);
2656 exit(-ERROR_FAIL);
2658 failed_badly:
2659 fprintf(stderr,
2660 "** Migration failed during final handshake **\n"
2661 "Domain state is now undefined !\n"
2662 "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
2663 " resuming at most one instance. Two simultaneous instances of the domain\n"
2664 " would probably result in SEVERE DATA LOSS and it is now your\n"
2665 " responsibility to avoid that. Sorry.\n");
2667 close(send_fd);
2668 migration_child_report(child, recv_fd);
2669 exit(-ERROR_BADFAIL);
2672 static void core_dump_domain(const char *domain_spec, const char *filename)
2674 int rc;
2675 find_domain(domain_spec);
2676 rc=libxl_domain_core_dump(&ctx, domid, filename);
2677 if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n.",rc);exit(-1); }
2680 static void migrate_receive(int debug, int daemonize)
2682 int rc, rc2;
2683 char rc_buf;
2684 char *migration_domname;
2685 struct domain_create dom_info;
2687 signal(SIGPIPE, SIG_IGN);
2688 /* if we get SIGPIPE we'd rather just have it as an error */
2690 fprintf(stderr, "migration target: Ready to receive domain.\n");
2692 CHK_ERRNO( libxl_write_exactly(&ctx, 1,
2693 migrate_receiver_banner,
2694 sizeof(migrate_receiver_banner)-1,
2695 "migration ack stream",
2696 "banner") );
2698 memset(&dom_info, 0, sizeof(dom_info));
2699 dom_info.debug = debug;
2700 dom_info.daemonize = daemonize;
2701 dom_info.paused = 1;
2702 dom_info.restore_file = "incoming migration stream";
2703 dom_info.migrate_fd = 0; /* stdin */
2704 dom_info.migration_domname_r = &migration_domname;
2706 rc = create_domain(&dom_info);
2707 if (rc < 0) {
2708 fprintf(stderr, "migration target: Domain creation failed"
2709 " (code %d).\n", rc);
2710 exit(-rc);
2713 fprintf(stderr, "migration target: Transfer complete,"
2714 " requesting permission to start domain.\n");
2716 rc = libxl_write_exactly(&ctx, 1,
2717 migrate_receiver_ready,
2718 sizeof(migrate_receiver_ready),
2719 "migration ack stream", "ready message");
2720 if (rc) exit(-rc);
2722 rc = migrate_read_fixedmessage(0, migrate_permission_to_go,
2723 sizeof(migrate_permission_to_go),
2724 "GO message", 0);
2725 if (rc) goto perhaps_destroy_notify_rc;
2727 fprintf(stderr, "migration target: Got permission, starting domain.\n");
2729 if (migration_domname) {
2730 rc = libxl_domain_rename(&ctx, domid,
2731 migration_domname, common_domname, 0);
2732 if (rc) goto perhaps_destroy_notify_rc;
2735 rc = libxl_domain_unpause(&ctx, domid);
2736 if (rc) goto perhaps_destroy_notify_rc;
2738 fprintf(stderr, "migration target: Domain started successsfully.\n");
2739 rc = 0;
2741 perhaps_destroy_notify_rc:
2742 rc2 = libxl_write_exactly(&ctx, 1,
2743 migrate_report, sizeof(migrate_report),
2744 "migration ack stream",
2745 "success/failure report");
2746 if (rc2) exit(-ERROR_BADFAIL);
2748 rc_buf = -rc;
2749 assert(!!rc_buf == !!rc);
2750 rc2 = libxl_write_exactly(&ctx, 1, &rc_buf, 1,
2751 "migration ack stream",
2752 "success/failure code");
2753 if (rc2) exit(-ERROR_BADFAIL);
2755 if (rc) {
2756 fprintf(stderr, "migration target: Failure, destroying our copy.\n");
2758 rc2 = libxl_domain_destroy(&ctx, domid, 1);
2759 if (rc2) {
2760 fprintf(stderr, "migration target: Failed to destroy our copy"
2761 " (code %d).\n", rc2);
2762 exit(-ERROR_BADFAIL);
2765 fprintf(stderr, "migration target: Cleanup OK, granting sender"
2766 " permission to resume.\n");
2768 rc2 = libxl_write_exactly(&ctx, 1,
2769 migrate_permission_to_go,
2770 sizeof(migrate_permission_to_go),
2771 "migration ack stream",
2772 "permission to sender to have domain back");
2773 if (rc2) exit(-ERROR_BADFAIL);
2776 exit(0);
2779 int main_restore(int argc, char **argv)
2781 const char *checkpoint_file = NULL;
2782 const char *config_file = NULL;
2783 struct domain_create dom_info;
2784 int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0;
2785 int opt, rc;
2787 while ((opt = getopt(argc, argv, "chpde")) != -1) {
2788 switch (opt) {
2789 case 'c':
2790 console_autoconnect = 1;
2791 break;
2792 case 'p':
2793 paused = 1;
2794 break;
2795 case 'd':
2796 debug = 1;
2797 break;
2798 case 'e':
2799 daemonize = 0;
2800 break;
2801 case 'h':
2802 help("restore");
2803 return 0;
2804 default:
2805 fprintf(stderr, "option not supported\n");
2806 break;
2810 if (argc-optind == 1) {
2811 checkpoint_file = argv[optind];
2812 } else if (argc-optind == 2) {
2813 config_file = argv[optind];
2814 checkpoint_file = argv[optind + 1];
2815 } else {
2816 help("restore");
2817 return 2;
2820 memset(&dom_info, 0, sizeof(dom_info));
2821 dom_info.debug = debug;
2822 dom_info.daemonize = daemonize;
2823 dom_info.paused = paused;
2824 dom_info.config_file = config_file;
2825 dom_info.restore_file = checkpoint_file;
2826 dom_info.migrate_fd = -1;
2827 dom_info.console_autoconnect = console_autoconnect;
2829 rc = create_domain(&dom_info);
2830 if (rc < 0)
2831 return -rc;
2833 return 0;
2836 int main_migrate_receive(int argc, char **argv)
2838 int debug = 0, daemonize = 1;
2839 int opt;
2841 while ((opt = getopt(argc, argv, "hed")) != -1) {
2842 switch (opt) {
2843 case 'h':
2844 help("migrate-receive");
2845 return 2;
2846 break;
2847 case 'e':
2848 daemonize = 0;
2849 break;
2850 case 'd':
2851 debug = 1;
2852 break;
2853 default:
2854 fprintf(stderr, "option not supported\n");
2855 break;
2859 if (argc-optind != 0) {
2860 help("migrate-receive");
2861 return 2;
2863 migrate_receive(debug, daemonize);
2864 return 0;
2867 int main_save(int argc, char **argv)
2869 const char *filename = NULL, *p = NULL;
2870 const char *config_filename;
2871 int checkpoint = 0;
2872 int opt;
2874 while ((opt = getopt(argc, argv, "hc")) != -1) {
2875 switch (opt) {
2876 case 'c':
2877 checkpoint = 1;
2878 break;
2879 case 'h':
2880 help("save");
2881 return 0;
2882 default:
2883 fprintf(stderr, "option not supported\n");
2884 break;
2888 if (argc-optind < 1 || argc-optind > 3) {
2889 help("save");
2890 return 2;
2893 p = argv[optind];
2894 filename = argv[optind + 1];
2895 config_filename = argv[optind + 2];
2896 save_domain(p, filename, checkpoint, config_filename);
2897 return 0;
2900 int main_migrate(int argc, char **argv)
2902 const char *p = NULL;
2903 const char *config_filename = NULL;
2904 const char *ssh_command = "ssh";
2905 char *rune = NULL;
2906 char *host;
2907 int opt, daemonize = 1, debug = 0;
2909 while ((opt = getopt(argc, argv, "hC:s:ed")) != -1) {
2910 switch (opt) {
2911 case 'h':
2912 help("migrate");
2913 return 0;
2914 case 'C':
2915 config_filename = optarg;
2916 break;
2917 case 's':
2918 ssh_command = optarg;
2919 break;
2920 case 'e':
2921 daemonize = 0;
2922 break;
2923 case 'd':
2924 debug = 1;
2925 break;
2926 default:
2927 fprintf(stderr, "option not supported\n");
2928 break;
2932 if (argc-optind < 2 || argc-optind > 2) {
2933 help("migrate");
2934 return 2;
2937 p = argv[optind];
2938 host = argv[optind + 1];
2940 if (!ssh_command[0]) {
2941 rune= host;
2942 } else {
2943 if (asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
2944 ssh_command, host,
2945 daemonize ? "" : " -e",
2946 debug ? " -d" : "") < 0)
2947 return 1;
2950 migrate_domain(p, rune, config_filename);
2951 return 0;
2954 int main_dump_core(int argc, char **argv)
2956 int opt;
2957 while ((opt = getopt(argc, argv, "h")) != -1) {
2958 switch (opt) {
2959 case 'h':
2960 help("dump-core");
2961 return 0;
2962 default:
2963 fprintf(stderr, "option `%c' not supported.\n", opt);
2964 break;
2967 if ( argc-optind < 2 ) {
2968 help("dump-core");
2969 return 2;
2971 core_dump_domain(argv[optind], argv[optind + 1]);
2972 return 0;
2975 int main_pause(int argc, char **argv)
2977 int opt;
2978 const char *p;
2981 while ((opt = getopt(argc, argv, "h")) != -1) {
2982 switch (opt) {
2983 case 'h':
2984 help("pause");
2985 return 0;
2986 default:
2987 fprintf(stderr, "option not supported\n");
2988 break;
2991 if (optind >= argc) {
2992 help("pause");
2993 return 2;
2996 p = argv[optind];
2998 pause_domain(p);
2999 return 0;
3002 int main_unpause(int argc, char **argv)
3004 int opt;
3005 const char *p;
3008 while ((opt = getopt(argc, argv, "h")) != -1) {
3009 switch (opt) {
3010 case 'h':
3011 help("unpause");
3012 return 0;
3013 default:
3014 fprintf(stderr, "option not supported\n");
3015 break;
3018 if (optind >= argc) {
3019 help("unpause");
3020 return 2;
3023 p = argv[optind];
3025 unpause_domain(p);
3026 return 0;
3029 int main_destroy(int argc, char **argv)
3031 int opt;
3032 const char *p;
3034 while ((opt = getopt(argc, argv, "h")) != -1) {
3035 switch (opt) {
3036 case 'h':
3037 help("destroy");
3038 return 0;
3039 default:
3040 fprintf(stderr, "option not supported\n");
3041 break;
3044 if (optind >= argc) {
3045 help("destroy");
3046 return 2;
3049 p = argv[optind];
3051 destroy_domain(p);
3052 return 0;
3055 int main_shutdown(int argc, char **argv)
3057 int opt;
3058 int wait = 0;
3059 const char *p;
3061 while ((opt = getopt(argc, argv, "hw")) != -1) {
3062 switch (opt) {
3063 case 'h':
3064 help("shutdown");
3065 return 0;
3066 case 'w':
3067 wait = 1;
3068 break;
3069 default:
3070 fprintf(stderr, "option not supported\n");
3071 break;
3074 if (optind >= argc) {
3075 help("shutdown");
3076 return 2;
3079 p = argv[optind];
3081 shutdown_domain(p, wait);
3082 return 0;
3085 int main_reboot(int argc, char **argv)
3087 int opt;
3088 const char *p;
3090 while ((opt = getopt(argc, argv, "h")) != -1) {
3091 switch (opt) {
3092 case 'h':
3093 help("reboot");
3094 return 0;
3095 default:
3096 fprintf(stderr, "option not supported\n");
3097 break;
3100 if (optind >= argc) {
3101 help("reboot");
3102 return 2;
3105 p = argv[optind];
3107 reboot_domain(p);
3108 return 0;
3110 int main_list(int argc, char **argv)
3112 int opt, verbose = 0;
3113 int details = 0;
3114 int option_index = 0;
3115 static struct option long_options[] = {
3116 {"long", 0, 0, 'l'},
3117 {"help", 0, 0, 'h'},
3118 {"verbose", 0, 0, 'v'},
3119 {0, 0, 0, 0}
3120 };
3122 libxl_dominfo info_buf;
3123 libxl_dominfo *info, *info_free=0;
3124 int nb_domain, rc;
3126 while (1) {
3127 opt = getopt_long(argc, argv, "lvh", long_options, &option_index);
3128 if (opt == -1)
3129 break;
3131 switch (opt) {
3132 case 'l':
3133 details = 1;
3134 break;
3135 case 'h':
3136 help("list");
3137 return 0;
3138 case 'v':
3139 verbose = 1;
3140 break;
3141 default:
3142 fprintf(stderr, "option not supported\n");
3143 break;
3147 if (optind >= argc) {
3148 info = libxl_list_domain(&ctx, &nb_domain);
3149 if (!info) {
3150 fprintf(stderr, "libxl_domain_infolist failed.\n");
3151 return 1;
3153 info_free = info;
3154 } else if (optind == argc-1) {
3155 find_domain(argv[optind]);
3156 rc = libxl_domain_info(&ctx, &info_buf, domid);
3157 if (rc == ERROR_INVAL) {
3158 fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
3159 argv[optind]);
3160 return -rc;
3162 if (rc) {
3163 fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
3164 return -rc;
3166 info = &info_buf;
3167 nb_domain = 1;
3168 } else {
3169 help("list");
3170 return 2;
3173 if (details)
3174 list_domains_details(info, nb_domain);
3175 else
3176 list_domains(verbose, info, nb_domain);
3178 free(info_free);
3180 return 0;
3183 int main_list_vm(int argc, char **argv)
3185 int opt;
3187 while ((opt = getopt(argc, argv, "h")) != -1) {
3188 switch (opt) {
3189 case 'h':
3190 help("list-vm");
3191 return 0;
3192 default:
3193 fprintf(stderr, "option not supported\n");
3194 break;
3198 list_vm();
3199 return 0;
3202 int main_create(int argc, char **argv)
3204 const char *filename = NULL;
3205 char *p;
3206 char extra_config[1024];
3207 struct domain_create dom_info;
3208 int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
3209 dryrun = 0, quiet = 0;
3210 int opt, rc;
3211 int option_index = 0;
3212 static struct option long_options[] = {
3213 {"dryrun", 0, 0, 'n'},
3214 {"quiet", 0, 0, 'q'},
3215 {"help", 0, 0, 'h'},
3216 {"defconfig", 1, 0, 'f'},
3217 {0, 0, 0, 0}
3218 };
3220 while (1) {
3221 opt = getopt_long(argc, argv, "hnqf:pcde", long_options, &option_index);
3222 if (opt == -1)
3223 break;
3225 switch (opt) {
3226 case 'f':
3227 filename = optarg;
3228 break;
3229 case 'p':
3230 paused = 1;
3231 break;
3232 case 'c':
3233 console_autoconnect = 1;
3234 break;
3235 case 'd':
3236 debug = 1;
3237 break;
3238 case 'e':
3239 daemonize = 0;
3240 break;
3241 case 'h':
3242 help("create");
3243 return 0;
3244 case 'n':
3245 dryrun = 1;
3246 break;
3247 case 'q':
3248 quiet = 1;
3249 break;
3250 default:
3251 fprintf(stderr, "option not supported\n");
3252 break;
3256 extra_config[0] = '\0';
3257 for (p = extra_config; optind < argc; optind++) {
3258 if (strchr(argv[optind], '=') != NULL) {
3259 p += snprintf(p, sizeof(extra_config) - (p - extra_config),
3260 "%s\n", argv[optind]);
3261 } else if (!filename) {
3262 filename = argv[optind];
3263 } else {
3264 help("create");
3265 return 2;
3269 memset(&dom_info, 0, sizeof(dom_info));
3270 dom_info.debug = debug;
3271 dom_info.daemonize = daemonize;
3272 dom_info.paused = paused;
3273 dom_info.dryrun = dryrun;
3274 dom_info.quiet = quiet;
3275 dom_info.config_file = filename;
3276 dom_info.extra_config = extra_config;
3277 dom_info.migrate_fd = -1;
3278 dom_info.console_autoconnect = console_autoconnect;
3280 rc = create_domain(&dom_info);
3281 if (rc < 0)
3282 return -rc;
3284 return 0;
3287 static void button_press(const char *p, const char *b)
3289 libxl_button button;
3291 find_domain(p);
3293 if (!strcmp(b, "power")) {
3294 button = POWER_BUTTON;
3295 } else if (!strcmp(b, "sleep")) {
3296 button = SLEEP_BUTTON;
3297 } else {
3298 fprintf(stderr, "%s is an invalid button identifier\n", b);
3299 exit(2);
3302 libxl_button_press(&ctx, domid, button);
3305 int main_button_press(int argc, char **argv)
3307 int opt;
3308 const char *p;
3309 const char *b;
3311 while ((opt = getopt(argc, argv, "h")) != -1) {
3312 switch (opt) {
3313 case 'h':
3314 help("button-press");
3315 return 0;
3316 default:
3317 fprintf(stderr, "option not supported\n");
3318 break;
3321 if (optind >= argc - 1) {
3322 help("button-press");
3323 return 2;
3326 p = argv[optind];
3327 b = argv[optind + 1];
3329 button_press(p, b);
3330 return 0;
3333 static void print_vcpuinfo(uint32_t tdomid,
3334 const libxl_vcpuinfo *vcpuinfo,
3335 uint32_t nr_cpus)
3337 int i, l;
3338 uint8_t *cpumap;
3339 uint8_t pcpumap;
3340 char *domname;
3342 /* NAME ID VCPU */
3343 domname = libxl_domid_to_name(&ctx, tdomid);
3344 printf("%-32s %5u %5u",
3345 domname, tdomid, vcpuinfo->vcpuid);
3346 free(domname);
3347 if (!vcpuinfo->online) {
3348 /* CPU STA */
3349 printf("%5c %3c%cp ", '-', '-', '-');
3350 } else {
3351 /* CPU STA */
3352 printf("%5u %3c%c- ", vcpuinfo->cpu,
3353 vcpuinfo->running ? 'r' : '-',
3354 vcpuinfo->blocked ? 'b' : '-');
3356 /* TIM */
3357 printf("%9.1f ", ((float)vcpuinfo->vcpu_time / 1e9));
3358 /* CPU AFFINITY */
3359 pcpumap = nr_cpus > 8 ? (uint8_t)-1 : ((1 << nr_cpus) - 1);
3360 for (cpumap = vcpuinfo->cpumap.map; nr_cpus; ++cpumap) {
3361 if (*cpumap < pcpumap) {
3362 break;
3364 if (nr_cpus > 8) {
3365 pcpumap = -1;
3366 nr_cpus -= 8;
3367 } else {
3368 pcpumap = ((1 << nr_cpus) - 1);
3369 nr_cpus = 0;
3372 if (!nr_cpus) {
3373 printf("any cpu\n");
3374 } else {
3375 for (cpumap = vcpuinfo->cpumap.map; nr_cpus; ++cpumap) {
3376 pcpumap = *cpumap;
3377 for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1)
3379 printf("%u", i);
3380 for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
3382 if (l < i) {
3383 printf("-%u", i);
3385 for (++i; pcpumap; ++i, pcpumap >>= 1) {
3386 if (pcpumap & 1) {
3387 printf(",%u", i);
3388 for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
3390 if (l < i) {
3391 printf("-%u", i);
3393 ++i;
3396 printf("\n");
3397 nr_cpus = nr_cpus > 8 ? nr_cpus - 8 : 0;
3402 static void print_domain_vcpuinfo(uint32_t domid, uint32_t nr_cpus)
3404 libxl_vcpuinfo *vcpuinfo;
3405 int i, nb_vcpu, nrcpus;
3407 vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &nrcpus);
3409 if (!vcpuinfo) {
3410 fprintf(stderr, "libxl_list_vcpu failed.\n");
3411 return;
3414 for (i = 0; i < nb_vcpu; i++) {
3415 print_vcpuinfo(domid, &vcpuinfo[i], nr_cpus);
3416 libxl_vcpuinfo_destroy(&vcpuinfo[i]);
3419 free(vcpuinfo);
3422 static void vcpulist(int argc, char **argv)
3424 libxl_dominfo *dominfo;
3425 libxl_physinfo physinfo;
3426 int i, nb_domain;
3428 if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
3429 fprintf(stderr, "libxl_physinfo failed.\n");
3430 goto vcpulist_out;
3433 printf("%-32s %5s %5s %5s %5s %9s %s\n",
3434 "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
3435 if (!argc) {
3436 if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
3437 fprintf(stderr, "libxl_list_domain failed.\n");
3438 goto vcpulist_out;
3441 for (i = 0; i<nb_domain; i++)
3442 print_domain_vcpuinfo(dominfo[i].domid, physinfo.nr_cpus);
3444 free(dominfo);
3446 } else {
3447 for (; argc > 0; ++argv, --argc) {
3448 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
3449 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
3450 goto vcpulist_out;
3453 print_domain_vcpuinfo(domid, physinfo.nr_cpus);
3456 vcpulist_out:
3460 int main_vcpulist(int argc, char **argv)
3462 int opt;
3464 while ((opt = getopt(argc, argv, "h")) != -1) {
3465 switch (opt) {
3466 case 'h':
3467 help("vcpu-list");
3468 return 0;
3469 default:
3470 fprintf(stderr, "option `%c' not supported.\n", opt);
3471 break;
3475 vcpulist(argc - optind, argv + optind);
3476 return 0;
3479 static void vcpupin(const char *d, const char *vcpu, char *cpu)
3481 libxl_vcpuinfo *vcpuinfo;
3482 libxl_cpumap cpumap;
3484 uint32_t vcpuid, cpuida, cpuidb;
3485 char *endptr, *toka, *tokb;
3486 int i, nb_vcpu;
3488 vcpuid = strtoul(vcpu, &endptr, 10);
3489 if (vcpu == endptr) {
3490 if (strcmp(vcpu, "all")) {
3491 fprintf(stderr, "Error: Invalid argument.\n");
3492 return;
3494 vcpuid = -1;
3497 find_domain(d);
3499 if (libxl_cpumap_alloc(&ctx, &cpumap)) {
3500 goto vcpupin_out;
3502 if (strcmp(cpu, "all")) {
3503 for (toka = strtok(cpu, ","), i = 0; toka; toka = strtok(NULL, ","), ++i) {
3504 cpuida = strtoul(toka, &endptr, 10);
3505 if (toka == endptr) {
3506 fprintf(stderr, "Error: Invalid argument.\n");
3507 goto vcpupin_out1;
3509 if (*endptr == '-') {
3510 tokb = endptr + 1;
3511 cpuidb = strtoul(tokb, &endptr, 10);
3512 if ((tokb == endptr) || (cpuida > cpuidb)) {
3513 fprintf(stderr, "Error: Invalid argument.\n");
3514 goto vcpupin_out1;
3516 while (cpuida <= cpuidb) {
3517 libxl_cpumap_set(&cpumap, cpuida);
3518 ++cpuida;
3520 } else {
3521 libxl_cpumap_set(&cpumap, cpuida);
3525 else {
3526 memset(cpumap.map, -1, cpumap.size);
3529 if (vcpuid != -1) {
3530 if (libxl_set_vcpuaffinity(&ctx, domid, vcpuid, &cpumap) == -1) {
3531 fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
3534 else {
3535 if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &i))) {
3536 fprintf(stderr, "libxl_list_vcpu failed.\n");
3537 goto vcpupin_out1;
3539 for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
3540 if (libxl_set_vcpuaffinity(&ctx, domid, vcpuinfo->vcpuid, &cpumap) == -1) {
3541 fprintf(stderr, "libxl_set_vcpuaffinity failed on vcpu `%u'.\n", vcpuinfo->vcpuid);
3545 vcpupin_out1:
3546 libxl_cpumap_destroy(&cpumap);
3547 vcpupin_out:
3551 int main_vcpupin(int argc, char **argv)
3553 int opt;
3555 while ((opt = getopt(argc, argv, "h")) != -1) {
3556 switch (opt) {
3557 case 'h':
3558 help("vcpu-pin");
3559 return 0;
3560 default:
3561 fprintf(stderr, "option `%c' not supported.\n", opt);
3562 break;
3566 if (optind != argc - 3) {
3567 help("vcpu-pin");
3568 return 2;
3571 vcpupin(argv[optind], argv[optind+1] , argv[optind+2]);
3572 return 0;
3575 static void vcpuset(const char *d, const char* nr_vcpus)
3577 char *endptr;
3578 unsigned int max_vcpus, i;
3579 uint32_t bitmask = 0;
3581 max_vcpus = strtoul(nr_vcpus, &endptr, 10);
3582 if (nr_vcpus == endptr) {
3583 fprintf(stderr, "Error: Invalid argument.\n");
3584 return;
3587 find_domain(d);
3589 for (i = 0; i < max_vcpus; i++)
3590 bitmask |= 1 << i;
3592 if (libxl_set_vcpuonline(&ctx, domid, bitmask) < 0)
3593 fprintf(stderr, "libxl_set_vcpuonline failed domid=%d bitmask=%x\n", domid, bitmask);
3596 int main_vcpuset(int argc, char **argv)
3598 int opt;
3600 while ((opt = getopt(argc, argv, "h")) != -1) {
3601 switch (opt) {
3602 case 'h':
3603 help("vcpu-set");
3604 return 0;
3605 default:
3606 fprintf(stderr, "option `%c' not supported.\n", opt);
3607 break;
3611 if (optind >= argc - 1) {
3612 help("vcpu-set");
3613 return 2;
3615 vcpuset(argv[optind], argv[optind+1]);
3616 return 0;
3619 static void output_xeninfo(void)
3621 const libxl_version_info *info;
3622 int sched_id;
3624 if (!(info = libxl_get_version_info(&ctx))) {
3625 fprintf(stderr, "libxl_get_version_info failed.\n");
3626 return;
3629 if ((sched_id = libxl_get_sched_id(&ctx)) < 0) {
3630 fprintf(stderr, "get_sched_id sysctl failed.\n");
3631 return;
3634 printf("xen_major : %d\n", info->xen_version_major);
3635 printf("xen_minor : %d\n", info->xen_version_minor);
3636 printf("xen_extra : %s\n", info->xen_version_extra);
3637 printf("xen_caps : %s\n", info->capabilities);
3638 printf("xen_scheduler : %s\n", libxl_schedid_to_name(&ctx, sched_id));
3639 printf("xen_pagesize : %lu\n", info->pagesize);
3640 printf("platform_params : virt_start=0x%lx\n", info->virt_start);
3641 printf("xen_changeset : %s\n", info->changeset);
3642 printf("xen_commandline : %s\n", info->commandline);
3643 printf("cc_compiler : %s\n", info->compiler);
3644 printf("cc_compile_by : %s\n", info->compile_by);
3645 printf("cc_compile_domain : %s\n", info->compile_domain);
3646 printf("cc_compile_date : %s\n", info->compile_date);
3648 return;
3651 static void output_nodeinfo(void)
3653 struct utsname utsbuf;
3655 if (uname(&utsbuf) < 0)
3656 return;
3658 printf("host : %s\n", utsbuf.nodename);
3659 printf("release : %s\n", utsbuf.release);
3660 printf("version : %s\n", utsbuf.version);
3661 printf("machine : %s\n", utsbuf.machine);
3664 static void output_physinfo(void)
3666 libxl_physinfo info;
3667 const libxl_version_info *vinfo;
3668 unsigned int i;
3669 libxl_cpumap cpumap;
3670 int n = 0;
3672 if (libxl_get_physinfo(&ctx, &info) != 0) {
3673 fprintf(stderr, "libxl_physinfo failed.\n");
3674 return;
3677 printf("nr_cpus : %d\n", info.nr_cpus);
3678 printf("nr_nodes : %d\n", info.nr_nodes);
3679 printf("cores_per_socket : %d\n", info.cores_per_socket);
3680 printf("threads_per_core : %d\n", info.threads_per_core);
3681 printf("cpu_mhz : %d\n", info.cpu_khz / 1000);
3682 printf("hw_caps : ");
3683 for (i = 0; i < 8; i++)
3684 printf("%08x%c", info.hw_cap[i], i < 7 ? ':' : '\n');
3685 printf("virt_caps :");
3686 if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm)
3687 printf(" hvm");
3688 if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm_directio)
3689 printf(" hvm_directio");
3690 printf("\n");
3691 vinfo = libxl_get_version_info(&ctx);
3692 if (vinfo) {
3693 i = (1 << 20) / vinfo->pagesize;
3694 printf("total_memory : %"PRIu64"\n", info.total_pages / i);
3695 printf("free_memory : %"PRIu64"\n", info.free_pages / i);
3697 if (!libxl_get_freecpus(&ctx, &cpumap)) {
3698 libxl_for_each_cpu(i, cpumap)
3699 if (libxl_cpumap_test(&cpumap, i))
3700 n++;
3701 printf("free_cpus : %d\n", n);
3702 free(cpumap.map);
3705 return;
3708 static void output_topologyinfo(void)
3710 libxl_topologyinfo info;
3711 int i;
3713 if (libxl_get_topologyinfo(&ctx, &info)) {
3714 fprintf(stderr, "libxl_get_topologyinfo failed.\n");
3715 return;
3718 printf("cpu_topology :\n");
3719 printf("cpu: core socket node\n");
3721 for (i = 0; i < info.coremap.entries; i++) {
3722 if (info.coremap.array[i] != LIBXL_CPUARRAY_INVALID_ENTRY)
3723 printf("%3d: %4d %4d %4d\n", i, info.coremap.array[i],
3724 info.socketmap.array[i], info.nodemap.array[i]);
3727 printf("numa_info : none\n");
3729 libxl_topologyinfo_destroy(&info);
3731 return;
3734 static void info(int numa)
3736 output_nodeinfo();
3738 output_physinfo();
3740 if (numa)
3741 output_topologyinfo();
3743 output_xeninfo();
3745 printf("xend_config_format : 4\n");
3747 return;
3750 int main_info(int argc, char **argv)
3752 int opt;
3753 int option_index = 0;
3754 static struct option long_options[] = {
3755 {"help", 0, 0, 'h'},
3756 {"numa", 0, 0, 'n'},
3757 {0, 0, 0, 0}
3758 };
3759 int numa = 0;
3761 while ((opt = getopt_long(argc, argv, "hn", long_options, &option_index)) != -1) {
3762 switch (opt) {
3763 case 'h':
3764 help("info");
3765 return 0;
3766 case 'n':
3767 numa = 1;
3768 break;
3769 default:
3770 fprintf(stderr, "option `%c' not supported.\n", opt);
3771 break;
3775 info(numa);
3776 return 0;
3779 static int sched_credit_domain_get(
3780 int domid, libxl_sched_credit *scinfo)
3782 int rc;
3784 rc = libxl_sched_credit_domain_get(&ctx, domid, scinfo);
3785 if (rc)
3786 fprintf(stderr, "libxl_sched_credit_domain_get failed.\n");
3788 return rc;
3791 static int sched_credit_domain_set(
3792 int domid, libxl_sched_credit *scinfo)
3794 int rc;
3796 rc = libxl_sched_credit_domain_set(&ctx, domid, scinfo);
3797 if (rc)
3798 fprintf(stderr, "libxl_sched_credit_domain_set failed.\n");
3800 return rc;
3803 static void sched_credit_domain_output(
3804 int domid, libxl_sched_credit *scinfo)
3806 char *domname;
3807 domname = libxl_domid_to_name(&ctx, domid);
3808 printf("%-33s %4d %6d %4d\n",
3809 domname,
3810 domid,
3811 scinfo->weight,
3812 scinfo->cap);
3813 free(domname);
3816 int main_sched_credit(int argc, char **argv)
3818 libxl_dominfo *info;
3819 libxl_sched_credit scinfo;
3820 int nb_domain, i;
3821 const char *dom = NULL;
3822 int weight = 256, cap = 0, opt_w = 0, opt_c = 0;
3823 int opt, rc;
3825 while ((opt = getopt(argc, argv, "hd:w:c:")) != -1) {
3826 switch (opt) {
3827 case 'd':
3828 dom = optarg;
3829 break;
3830 case 'w':
3831 weight = strtol(optarg, NULL, 10);
3832 opt_w = 1;
3833 break;
3834 case 'c':
3835 cap = strtol(optarg, NULL, 10);
3836 opt_c = 1;
3837 break;
3838 case 'h':
3839 help("sched-credit");
3840 return 0;
3841 default:
3842 fprintf(stderr, "option `%c' not supported.\n", opt);
3843 break;
3847 if (!dom && (opt_w || opt_c)) {
3848 fprintf(stderr, "Must specify a domain.\n");
3849 return 1;
3852 if (!dom) { /* list all domain's credit scheduler info */
3853 info = libxl_list_domain(&ctx, &nb_domain);
3854 if (!info) {
3855 fprintf(stderr, "libxl_domain_infolist failed.\n");
3856 return 1;
3859 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
3860 for (i = 0; i < nb_domain; i++) {
3861 rc = sched_credit_domain_get(info[i].domid, &scinfo);
3862 if (rc)
3863 return -rc;
3864 sched_credit_domain_output(info[i].domid, &scinfo);
3866 } else {
3867 find_domain(dom);
3869 rc = sched_credit_domain_get(domid, &scinfo);
3870 if (rc)
3871 return -rc;
3873 if (!opt_w && !opt_c) { /* output credit scheduler info */
3874 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
3875 sched_credit_domain_output(domid, &scinfo);
3876 } else { /* set credit scheduler paramaters */
3877 if (opt_w)
3878 scinfo.weight = weight;
3879 if (opt_c)
3880 scinfo.cap = cap;
3881 rc = sched_credit_domain_set(domid, &scinfo);
3882 if (rc)
3883 return -rc;
3887 return 0;
3890 int main_domid(int argc, char **argv)
3892 int opt;
3893 const char *domname = NULL;
3895 while ((opt = getopt(argc, argv, "h")) != -1) {
3896 switch (opt) {
3897 case 'h':
3898 help("domid");
3899 return 0;
3900 default:
3901 fprintf(stderr, "option `%c' not supported.\n", opt);
3902 break;
3906 domname = argv[optind];
3907 if (!domname) {
3908 fprintf(stderr, "Must specify a domain name.\n\n");
3909 help("domid");
3910 return 1;
3913 if (libxl_name_to_domid(&ctx, domname, &domid)) {
3914 fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
3915 return 1;
3918 printf("%d\n", domid);
3920 return 0;
3923 int main_domname(int argc, char **argv)
3925 int opt;
3926 char *domname = NULL;
3927 char *endptr = NULL;
3929 while ((opt = getopt(argc, argv, "h")) != -1) {
3930 switch (opt) {
3931 case 'h':
3932 help("domname");
3933 return 0;
3934 default:
3935 fprintf(stderr, "option `%c' not supported.\n", opt);
3936 break;
3940 if (!argv[optind]) {
3941 fprintf(stderr, "Must specify a domain id.\n\n");
3942 help("domname");
3943 return 1;
3945 domid = strtol(argv[optind], &endptr, 10);
3946 if (domid == 0 && !strcmp(endptr, argv[optind])) {
3947 /*no digits at all*/
3948 fprintf(stderr, "Invalid domain id.\n\n");
3949 return 1;
3952 domname = libxl_domid_to_name(&ctx, domid);
3953 if (!domname) {
3954 fprintf(stderr, "Can't get domain name of domain id '%d', maybe this domain does not exist.\n", domid);
3955 return 1;
3958 printf("%s\n", domname);
3959 free(domname);
3961 return 0;
3964 int main_rename(int argc, char **argv)
3966 int opt;
3967 const char *dom;
3968 const char *new_name;
3970 while ((opt = getopt(argc, argv, "h")) != -1) {
3971 switch (opt) {
3972 case 'h':
3973 help("rename");
3974 return 0;
3975 default:
3976 fprintf(stderr, "option `%c' not supported.\n", opt);
3977 break;
3981 dom = argv[optind++];
3982 if (!dom || !argv[optind]) {
3983 fprintf(stderr, "'xl rename' requires 2 arguments.\n\n");
3984 help("rename");
3985 return 1;
3988 find_domain(dom);
3989 new_name = argv[optind];
3991 if (libxl_domain_rename(&ctx, domid, common_domname, new_name, 0)) {
3992 fprintf(stderr, "Can't rename domain '%s'.\n", dom);
3993 return 1;
3996 return 0;
3999 int main_trigger(int argc, char **argv)
4001 int opt;
4002 char *trigger_name = NULL;
4003 char *endptr = NULL;
4004 const char *dom = NULL;
4005 int vcpuid = 0;
4007 while ((opt = getopt(argc, argv, "h")) != -1) {
4008 switch (opt) {
4009 case 'h':
4010 help("trigger");
4011 return 0;
4012 default:
4013 fprintf(stderr, "option `%c' not supported.\n", opt);
4014 break;
4018 dom = argv[optind++];
4019 if (!dom || !argv[optind]) {
4020 fprintf(stderr, "'xl trigger' requires between 2 and 3 arguments.\n\n");
4021 help("trigger");
4022 return 1;
4025 find_domain(dom);
4027 trigger_name = argv[optind++];
4029 if (argv[optind]) {
4030 vcpuid = strtol(argv[optind], &endptr, 10);
4031 if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
4032 fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
4036 libxl_send_trigger(&ctx, domid, trigger_name, vcpuid);
4038 return 0;
4042 int main_sysrq(int argc, char **argv)
4044 int opt;
4045 const char *sysrq = NULL;
4046 const char *dom = NULL;
4048 while ((opt = getopt(argc, argv, "h")) != -1) {
4049 switch (opt) {
4050 case 'h':
4051 help("sysrq");
4052 return 0;
4053 default:
4054 fprintf(stderr, "option `%c' not supported.\n", opt);
4055 break;
4059 dom = argv[optind++];
4060 if (!dom || !argv[optind]) {
4061 fprintf(stderr, "'xl sysrq' requires 2 arguments.\n\n");
4062 help("sysrq");
4063 return 1;
4066 find_domain(dom);
4068 sysrq = argv[optind];
4070 if (sysrq[1] != '\0') {
4071 fprintf(stderr, "Invalid sysrq.\n\n");
4072 help("sysrq");
4073 return 1;
4076 libxl_send_sysrq(&ctx, domid, sysrq[0]);
4078 return 0;
4081 int main_debug_keys(int argc, char **argv)
4083 int opt;
4084 char *keys;
4086 while ((opt = getopt(argc, argv, "h")) != -1) {
4087 switch (opt) {
4088 case 'h':
4089 help("debug-keys");
4090 return 0;
4091 default:
4092 fprintf(stderr, "option not supported\n");
4093 break;
4096 if (optind >= argc) {
4097 help("debug-keys");
4098 return 2;
4101 keys = argv[optind];
4103 if (libxl_send_debug_keys(&ctx, keys)) {
4104 fprintf(stderr, "cannot send debug keys: %s\n", keys);
4105 return 1;
4108 return 0;
4111 int main_dmesg(int argc, char **argv)
4113 unsigned int clear = 0;
4114 libxl_xen_console_reader *cr;
4115 char *line;
4116 int opt, ret = 1;
4118 while ((opt = getopt(argc, argv, "hc")) != -1) {
4119 switch (opt) {
4120 case 'c':
4121 clear = 1;
4122 break;
4123 case 'h':
4124 help("dmesg");
4125 return 0;
4126 default:
4127 fprintf(stderr, "option not supported\n");
4128 break;
4132 cr = libxl_xen_console_read_start(&ctx, clear);
4133 if (!cr)
4134 goto finish;
4136 while ((ret = libxl_xen_console_read_line(&ctx, cr, &line)) > 0)
4137 printf("%s", line);
4139 finish:
4140 libxl_xen_console_read_finish(&ctx, cr);
4141 return ret;
4144 int main_top(int argc, char **argv)
4146 int opt;
4148 while ((opt = getopt(argc, argv, "h")) != -1) {
4149 switch (opt) {
4150 case 'h':
4151 help("top");
4152 return 0;
4153 default:
4154 fprintf(stderr, "option `%c' not supported.\n", opt);
4155 break;
4159 return system("xentop");
4162 int main_networkattach(int argc, char **argv)
4164 int opt;
4165 libxl_device_nic nic;
4166 char *endptr;
4167 const char *tok;
4168 int i;
4169 unsigned int val;
4171 while ((opt = getopt(argc, argv, "h")) != -1) {
4172 switch (opt) {
4173 case 'h':
4174 help("network-attach");
4175 return 0;
4176 default:
4177 fprintf(stderr, "option `%c' not supported.\n", opt);
4178 break;
4181 if ((argc-optind < 2) || (argc-optind > 11)) {
4182 help("network-attach");
4183 return 0;
4186 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4187 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4188 return 1;
4190 libxl_device_nic_init(&nic, -1);
4191 for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
4192 if (!strncmp("type=", *argv, 5)) {
4193 if (!strncmp("vif", (*argv) + 5, 4)) {
4194 nic.nictype = NICTYPE_VIF;
4195 } else if (!strncmp("ioemu", (*argv) + 5, 5)) {
4196 nic.nictype = NICTYPE_IOEMU;
4197 } else {
4198 fprintf(stderr, "Invalid parameter `type'.\n");
4199 return 1;
4201 } else if (!strncmp("mac=", *argv, 4)) {
4202 tok = strtok((*argv) + 4, ":");
4203 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4204 val = strtoul(tok, &endptr, 16);
4205 if ((tok == endptr) || (val > 255)) {
4206 fprintf(stderr, "Invalid parameter `mac'.\n");
4207 return 1;
4209 nic.mac[i] = val;
4211 } else if (!strncmp("bridge=", *argv, 7)) {
4212 nic.bridge = (*argv) + 7;
4213 } else if (!strncmp("ip=", *argv, 3)) {
4214 if (!inet_aton((*argv) + 3, &(nic.ip))) {
4215 fprintf(stderr, "Invalid parameter `ip'.\n");
4216 return 1;
4218 } else if (!strncmp("script=", *argv, 6)) {
4219 nic.script = (*argv) + 6;
4220 } else if (!strncmp("backend=", *argv, 8)) {
4221 if(libxl_name_to_domid(&ctx, ((*argv) + 8), &val)) {
4222 fprintf(stderr, "Specified backend domain does not exist, defaulting to Dom0\n");
4223 val = 0;
4225 nic.backend_domid = val;
4226 } else if (!strncmp("vifname=", *argv, 8)) {
4227 nic.ifname = (*argv) + 8;
4228 } else if (!strncmp("model=", *argv, 6)) {
4229 nic.model = (*argv) + 6;
4230 } else if (!strncmp("rate=", *argv, 5)) {
4231 } else if (!strncmp("accel=", *argv, 6)) {
4232 } else {
4233 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4234 return 1;
4237 nic.domid = domid;
4238 if (libxl_device_nic_add(&ctx, domid, &nic)) {
4239 fprintf(stderr, "libxl_device_nic_add failed.\n");
4240 return 1;
4242 libxl_device_nic_destroy(&nic);
4243 return 0;
4246 int main_networklist(int argc, char **argv)
4248 int opt;
4249 libxl_nicinfo *nics;
4250 unsigned int nb, i;
4252 while ((opt = getopt(argc, argv, "h")) != -1) {
4253 switch (opt) {
4254 case 'h':
4255 help("network-list");
4256 return 0;
4257 default:
4258 fprintf(stderr, "option `%c' not supported.\n", opt);
4259 break;
4262 if (argc-optind < 1) {
4263 help("network-list");
4264 return 1;
4267 /* Idx BE MAC Hdl Sta evch txr/rxr BE-path */
4268 printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
4269 "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
4270 for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
4271 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4272 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4273 continue;
4275 if (!(nics = libxl_list_nics(&ctx, domid, &nb))) {
4276 continue;
4278 for (i = 0; i < nb; ++i) {
4279 /* Idx BE */
4280 printf("%-3d %-2d ", nics[i].devid, nics[i].backend_id);
4281 /* MAC */
4282 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4283 nics[i].mac[0], nics[i].mac[1], nics[i].mac[2],
4284 nics[i].mac[3], nics[i].mac[4], nics[i].mac[5]);
4285 /* Hdl Sta evch txr/rxr BE-path */
4286 printf("%6d %5d %6d %5d/%-11d %-30s\n",
4287 nics[i].devid, nics[i].state, nics[i].evtch,
4288 nics[i].rref_tx, nics[i].rref_rx, nics[i].backend);
4289 libxl_nicinfo_destroy(&nics[i]);
4291 free(nics);
4293 return 0;
4296 int main_networkdetach(int argc, char **argv)
4298 int opt;
4299 libxl_device_nic nic;
4301 while ((opt = getopt(argc, argv, "h")) != -1) {
4302 switch (opt) {
4303 case 'h':
4304 help("network-detach");
4305 return 0;
4306 default:
4307 fprintf(stderr, "option `%c' not supported.\n", opt);
4308 break;
4311 if (argc-optind != 2) {
4312 help("network-detach");
4313 return 0;
4316 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4317 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4318 return 1;
4321 if (!strchr(argv[optind+1], ':')) {
4322 if (libxl_devid_to_device_nic(&ctx, domid, argv[optind+1], &nic)) {
4323 fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
4324 return 1;
4326 } else {
4327 if (libxl_mac_to_device_nic(&ctx, domid, argv[optind+1], &nic)) {
4328 fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
4329 return 1;
4332 if (libxl_device_nic_del(&ctx, &nic, 1)) {
4333 fprintf(stderr, "libxl_device_nic_del failed.\n");
4334 return 1;
4336 libxl_device_nic_destroy(&nic);
4337 return 0;
4340 int main_blockattach(int argc, char **argv)
4342 int opt;
4343 const char *tok;
4344 uint32_t fe_domid, be_domid = 0;
4345 libxl_device_disk disk = { 0 };
4347 while ((opt = getopt(argc, argv, "h")) != -1) {
4348 switch (opt) {
4349 case 'h':
4350 help("block-attach");
4351 return 0;
4352 default:
4353 fprintf(stderr, "option `%c' not supported.\n", opt);
4354 break;
4357 if ((argc-optind < 3) || (argc-optind > 5)) {
4358 help("block-attach");
4359 return 0;
4362 tok = strtok(argv[optind+1], ":");
4363 if (!strcmp(tok, "phy")) {
4364 disk.phystype = PHYSTYPE_PHY;
4365 } else if (!strcmp(tok, "file")) {
4366 disk.phystype = PHYSTYPE_FILE;
4367 } else if (!strcmp(tok, "tap")) {
4368 tok = strtok(NULL, ":");
4369 if (!strcmp(tok, "aio")) {
4370 disk.phystype = PHYSTYPE_AIO;
4371 } else if (!strcmp(tok, "vhd")) {
4372 disk.phystype = PHYSTYPE_VHD;
4373 } else if (!strcmp(tok, "qcow")) {
4374 disk.phystype = PHYSTYPE_QCOW;
4375 } else if (!strcmp(tok, "qcow2")) {
4376 disk.phystype = PHYSTYPE_QCOW2;
4377 } else {
4378 fprintf(stderr, "Error: `%s' is not a valid disk image.\n", tok);
4379 return 1;
4381 } else {
4382 fprintf(stderr, "Error: `%s' is not a valid block device.\n", tok);
4383 return 1;
4385 disk.physpath = strtok(NULL, "\0");
4386 if (!disk.physpath) {
4387 fprintf(stderr, "Error: missing path to disk image.\n");
4388 return 1;
4390 disk.virtpath = argv[optind+2];
4391 disk.unpluggable = 1;
4392 disk.readwrite = ((argc-optind <= 3) || (argv[optind+3][0] == 'w'));
4394 if (domain_qualifier_to_domid(argv[optind], &fe_domid, 0) < 0) {
4395 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4396 return 1;
4398 if (argc-optind == 5) {
4399 if (domain_qualifier_to_domid(argv[optind+4], &be_domid, 0) < 0) {
4400 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind+4]);
4401 return 1;
4404 disk.domid = fe_domid;
4405 disk.backend_domid = be_domid;
4407 if (libxl_device_disk_add(&ctx, fe_domid, &disk)) {
4408 fprintf(stderr, "libxl_device_disk_add failed.\n");
4410 return 0;
4413 int main_blocklist(int argc, char **argv)
4415 int opt;
4416 int i, nb;
4417 libxl_device_disk *disks;
4418 libxl_diskinfo diskinfo;
4420 while ((opt = getopt(argc, argv, "h")) != -1) {
4421 switch (opt) {
4422 case 'h':
4423 help("block-list");
4424 return 0;
4425 default:
4426 fprintf(stderr, "option `%c' not supported.\n", opt);
4427 break;
4430 if (argc-optind < 1) {
4431 help("block-list");
4432 return 0;
4435 printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
4436 "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
4437 for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
4438 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4439 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4440 continue;
4442 disks = libxl_device_disk_list(&ctx, domid, &nb);
4443 if (!disks) {
4444 continue;
4446 for (i=0; i<nb; i++) {
4447 if (!libxl_device_disk_getinfo(&ctx, domid, &disks[i], &diskinfo)) {
4448 /* Vdev BE hdl st evch rref BE-path*/
4449 printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
4450 diskinfo.devid, diskinfo.backend_id, diskinfo.frontend_id,
4451 diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
4452 libxl_diskinfo_destroy(&diskinfo);
4454 libxl_device_disk_destroy(&disks[i]);
4456 free(disks);
4458 return 0;
4461 int main_blockdetach(int argc, char **argv)
4463 int opt;
4464 libxl_device_disk disk;
4466 while ((opt = getopt(argc, argv, "h")) != -1) {
4467 switch (opt) {
4468 case 'h':
4469 help("block-detach");
4470 return 0;
4471 default:
4472 fprintf(stderr, "option `%c' not supported.\n", opt);
4473 break;
4476 if (argc-optind != 2) {
4477 help("block-detach");
4478 return 0;
4481 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4482 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4483 return 1;
4485 if (libxl_devid_to_device_disk(&ctx, domid, argv[optind+1], &disk)) {
4486 fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
4487 return 1;
4489 if (libxl_device_disk_del(&ctx, &disk, 1)) {
4490 fprintf(stderr, "libxl_device_disk_del failed.\n");
4492 return 0;
4495 int main_network2attach(int argc, char **argv)
4497 int opt;
4498 const char *tok;
4499 char *endptr;
4500 const char *back_dom = NULL;
4501 uint32_t domid, back_domid;
4502 unsigned int val, i;
4503 libxl_device_net2 net2;
4505 while ((opt = getopt(argc, argv, "h")) != -1) {
4506 switch (opt) {
4507 case 'h':
4508 help("network2-attach");
4509 return 0;
4510 default:
4511 fprintf(stderr, "option `%c' not supported.\n", opt);
4512 break;
4515 if ((argc-optind < 1) || (argc-optind > 10)) {
4516 help("network2-attach");
4517 return 0;
4520 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4521 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4522 return 1;
4524 libxl_device_net2_init(&net2, -1);
4525 for (argv += optind+1, argc -= optind+1; argc > 0; --argc, ++argv) {
4526 if (!strncmp("front_mac=", *argv, 10)) {
4527 tok = strtok((*argv) + 10, ":");
4528 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4529 val = strtoul(tok, &endptr, 16);
4530 if ((tok == endptr) || (val > 255)) {
4531 fprintf(stderr, "Invalid parameter `front_mac'.\n");
4532 return 1;
4534 net2.front_mac[i] = val;
4536 } else if (!strncmp("back_mac=", *argv, 9)) {
4537 tok = strtok((*argv) + 10, ":");
4538 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4539 val = strtoul(tok, &endptr, 16);
4540 if ((tok == endptr) || (val > 255)) {
4541 fprintf(stderr, "Invalid parameter back_mac=%s.\n", *argv + 9);
4542 return 1;
4544 net2.back_mac[i] = val;
4546 } else if (!strncmp("backend=", *argv, 8)) {
4547 back_dom = *argv;
4548 } else if (!strncmp("trusted=", *argv, 8)) {
4549 net2.trusted = (*((*argv) + 8) == '1');
4550 } else if (!strncmp("back_trusted=", *argv, 13)) {
4551 net2.back_trusted = (*((*argv) + 13) == '1');
4552 } else if (!strncmp("bridge=", *argv, 7)) {
4553 net2.bridge = *argv + 13;
4554 } else if (!strncmp("filter_mac=", *argv, 11)) {
4555 net2.filter_mac = (*((*argv) + 11) == '1');
4556 } else if (!strncmp("front_filter_mac=", *argv, 17)) {
4557 net2.front_filter_mac = (*((*argv) + 17) == '1');
4558 } else if (!strncmp("pdev=", *argv, 5)) {
4559 val = strtoul(*argv + 5, &endptr, 10);
4560 if (endptr == (*argv + 5)) {
4561 fprintf(stderr, "Invalid parameter pdev=%s.\n", *argv + 5);
4562 return 1;
4564 net2.pdev = val;
4565 } else if (!strncmp("max_bypasses=", *argv, 13)) {
4566 val = strtoul(*argv + 13, &endptr, 10);
4567 if (endptr == (*argv + 13)) {
4568 fprintf(stderr, "Invalid parameter max_bypasses=%s.\n", *argv + 13);
4569 return 1;
4571 net2.max_bypasses = val;
4572 } else {
4573 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4574 return 1;
4578 if (back_dom) {
4579 if (domain_qualifier_to_domid(back_dom, &back_domid, 0) < 0) {
4580 fprintf(stderr, "%s is an invalid domain identifier\n", back_dom);
4581 return 1;
4584 net2.domid = domid;
4585 net2.backend_domid = back_domid;
4586 if (libxl_device_net2_add(&ctx, domid, &net2)) {
4587 fprintf(stderr, "libxl_device_net2_add failed.\n");
4589 return 0;
4592 int main_network2list(int argc, char **argv)
4594 int opt;
4595 unsigned int nb;
4596 libxl_net2info *net2s;
4598 while ((opt = getopt(argc, argv, "h")) != -1) {
4599 switch (opt) {
4600 case 'h':
4601 help("network2-list");
4602 return 0;
4603 default:
4604 fprintf(stderr, "option `%c' not supported.\n", opt);
4605 break;
4608 if (argc - optind < 1) {
4609 help("network2-list");
4610 return 0;
4613 printf("%-3s %-2s %-5s %-17s %-17s %-7s %-6s %-30s\n",
4614 "Idx", "BE", "state", "Mac Addr.", "Remote Mac Addr.",
4615 "trusted", "filter", "backend");
4616 for (argv += optind, argc -=optind; argc > 0; --argc, ++argv) {
4617 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4618 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4619 continue;
4621 if ((net2s = libxl_device_net2_list(&ctx, domid, &nb))) {
4622 for (; nb > 0; --nb, ++net2s) {
4623 printf("%3d %2d %5d ", net2s->devid, net2s->backend_id, net2s->state);
4624 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4625 net2s->mac[0], net2s->mac[1], net2s->mac[2],
4626 net2s->mac[3], net2s->mac[4], net2s->mac[5]);
4627 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4628 net2s->back_mac[0], net2s->back_mac[1], net2s->back_mac[2],
4629 net2s->back_mac[3], net2s->back_mac[4], net2s->back_mac[5]);
4630 printf("%-7d %-6d %-30s\n", net2s->trusted, net2s->filter_mac, net2s->backend);
4634 return 0;
4637 int main_network2detach(int argc, char **argv)
4639 int opt;
4640 libxl_device_net2 net2;
4642 while ((opt = getopt(argc, argv, "h")) != -1) {
4643 switch (opt) {
4644 case 'h':
4645 help("network2-detach");
4646 return 0;
4647 default:
4648 fprintf(stderr, "option `%c' not supported.\n", opt);
4649 break;
4652 if (argc-optind != 2) {
4653 help("network2-detach");
4654 return 0;
4657 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4658 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4659 return 1;
4661 if (libxl_devid_to_device_net2(&ctx, domid, argv[optind+1], &net2)) {
4662 fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
4663 return 1;
4665 if (libxl_device_net2_del(&ctx, &net2, 1)) {
4666 fprintf(stderr, "libxl_device_net2_del failed.\n");
4667 return 1;
4669 return 0;
4672 static char *uptime_to_string(unsigned long time, int short_mode)
4674 int sec, min, hour, day;
4675 char *time_string;
4676 int ret;
4678 day = (int)(time / 86400);
4679 time -= (day * 86400);
4680 hour = (int)(time / 3600);
4681 time -= (hour * 3600);
4682 min = (int)(time / 60);
4683 time -= (min * 60);
4684 sec = time;
4686 if (short_mode)
4687 if (day > 1)
4688 ret = asprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
4689 else if (day == 1)
4690 ret = asprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
4691 else
4692 ret = asprintf(&time_string, "%2d:%02d", hour, min);
4693 else
4694 if (day > 1)
4695 ret = asprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
4696 else if (day == 1)
4697 ret = asprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
4698 else
4699 ret = asprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
4701 if (ret < 0)
4702 return NULL;
4703 return time_string;
4706 static char *current_time_to_string(time_t now)
4708 char now_str[100];
4709 struct tm *tmp;
4711 tmp = localtime(&now);
4712 if (tmp == NULL) {
4713 fprintf(stderr, "Get localtime error");
4714 exit(-1);
4716 if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
4717 fprintf(stderr, "strftime returned 0");
4718 exit(-1);
4720 return strdup(now_str);
4723 static void print_dom0_uptime(int short_mode, time_t now)
4725 int fd;
4726 char buf[512];
4727 uint32_t uptime = 0;
4728 char *uptime_str = NULL;
4729 char *now_str = NULL;
4730 char *domname;
4732 fd = open("/proc/uptime", O_RDONLY);
4733 if (fd == -1)
4734 goto err;
4736 if (read(fd, buf, sizeof(buf)) == -1) {
4737 close(fd);
4738 goto err;
4740 close(fd);
4742 strtok(buf, " ");
4743 uptime = strtoul(buf, NULL, 10);
4745 domname = libxl_domid_to_name(&ctx, 0);
4746 if (short_mode)
4748 now_str = current_time_to_string(now);
4749 uptime_str = uptime_to_string(uptime, 1);
4750 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
4751 domname, 0);
4753 else
4755 now_str = NULL;
4756 uptime_str = uptime_to_string(uptime, 0);
4757 printf("%-33s %4d %s\n", domname,
4758 0, uptime_str);
4761 free(now_str);
4762 free(uptime_str);
4763 free(domname);
4764 return;
4765 err:
4766 fprintf(stderr, "Can not get Dom0 uptime.\n");
4767 exit(-1);
4770 static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
4772 uint32_t s_time = 0;
4773 uint32_t uptime = 0;
4774 char *uptime_str = NULL;
4775 char *now_str = NULL;
4776 char *domname;
4778 s_time = libxl_vm_get_start_time(&ctx, domuid);
4779 if (s_time == -1)
4780 return;
4781 uptime = now - s_time;
4782 domname = libxl_domid_to_name(&ctx, domuid);
4783 if (short_mode)
4785 now_str = current_time_to_string(now);
4786 uptime_str = uptime_to_string(uptime, 1);
4787 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
4788 domname, domuid);
4790 else
4792 now_str = NULL;
4793 uptime_str = uptime_to_string(uptime, 0);
4794 printf("%-33s %4d %s\n", domname,
4795 domuid, uptime_str);
4798 free(domname);
4799 free(now_str);
4800 free(uptime_str);
4801 return;
4804 static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
4806 libxl_vminfo *info;
4807 time_t now;
4808 int nb_vm, i;
4810 now = time(NULL);
4812 if (!short_mode)
4813 printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
4815 if (nb_doms == 0) {
4816 print_dom0_uptime(short_mode, now);
4817 info = libxl_list_vm(&ctx, &nb_vm);
4818 for (i = 0; i < nb_vm; i++)
4819 print_domU_uptime(info[i].domid, short_mode, now);
4820 } else {
4821 for (i = 0; i < nb_doms; i++) {
4822 if (doms[i] == 0)
4823 print_dom0_uptime(short_mode, now);
4824 else
4825 print_domU_uptime(doms[i], short_mode, now);
4830 int main_uptime(int argc, char **argv)
4832 const char *dom = NULL;
4833 int short_mode = 0;
4834 uint32_t domains[100];
4835 int nb_doms = 0;
4836 int opt;
4838 while ((opt = getopt(argc, argv, "hs")) != -1) {
4839 switch (opt) {
4840 case 's':
4841 short_mode = 1;
4842 break;
4843 case 'h':
4844 help("uptime");
4845 return 0;
4846 default:
4847 fprintf(stderr, "option `%c' not supported.\n", opt);
4848 break;
4852 for (;(dom = argv[optind]) != NULL; nb_doms++,optind++) {
4853 find_domain(dom);
4854 domains[nb_doms] = domid;
4857 print_uptime(short_mode, domains, nb_doms);
4859 return 0;
4862 int main_tmem_list(int argc, char **argv)
4864 const char *dom = NULL;
4865 char *buf = NULL;
4866 int use_long = 0;
4867 int all = 0;
4868 int opt;
4870 while ((opt = getopt(argc, argv, "alh")) != -1) {
4871 switch (opt) {
4872 case 'l':
4873 use_long = 1;
4874 break;
4875 case 'a':
4876 all = 1;
4877 break;
4878 case 'h':
4879 help("tmem-list");
4880 return 0;
4881 default:
4882 fprintf(stderr, "option `%c' not supported.\n", opt);
4883 break;
4887 dom = argv[optind];
4888 if (!dom && all == 0) {
4889 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4890 help("tmem-list");
4891 return 1;
4894 if (all)
4895 domid = -1;
4896 else
4897 find_domain(dom);
4899 buf = libxl_tmem_list(&ctx, domid, use_long);
4900 if (buf == NULL)
4901 return -1;
4903 printf("%s\n", buf);
4904 free(buf);
4905 return 0;
4908 int main_tmem_freeze(int argc, char **argv)
4910 const char *dom = NULL;
4911 int all = 0;
4912 int opt;
4914 while ((opt = getopt(argc, argv, "ah")) != -1) {
4915 switch (opt) {
4916 case 'a':
4917 all = 1;
4918 break;
4919 case 'h':
4920 help("tmem-freeze");
4921 return 0;
4922 default:
4923 fprintf(stderr, "option `%c' not supported.\n", opt);
4924 break;
4928 dom = argv[optind];
4929 if (!dom && all == 0) {
4930 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4931 help("tmem-freeze");
4932 return 1;
4935 if (all)
4936 domid = -1;
4937 else
4938 find_domain(dom);
4940 libxl_tmem_freeze(&ctx, domid);
4941 return 0;
4944 int main_tmem_destroy(int argc, char **argv)
4946 const char *dom = NULL;
4947 int all = 0;
4948 int opt;
4950 while ((opt = getopt(argc, argv, "ah")) != -1) {
4951 switch (opt) {
4952 case 'a':
4953 all = 1;
4954 break;
4955 case 'h':
4956 help("tmem-destroy");
4957 return 0;
4958 default:
4959 fprintf(stderr, "option `%c' not supported.\n", opt);
4960 break;
4964 dom = argv[optind];
4965 if (!dom && all == 0) {
4966 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4967 help("tmem-destroy");
4968 return 1;
4971 if (all)
4972 domid = -1;
4973 else
4974 find_domain(dom);
4976 libxl_tmem_destroy(&ctx, domid);
4977 return 0;
4980 int main_tmem_thaw(int argc, char **argv)
4982 const char *dom = NULL;
4983 int all = 0;
4984 int opt;
4986 while ((opt = getopt(argc, argv, "ah")) != -1) {
4987 switch (opt) {
4988 case 'a':
4989 all = 1;
4990 break;
4991 case 'h':
4992 help("tmem-thaw");
4993 return 0;
4994 default:
4995 fprintf(stderr, "option `%c' not supported.\n", opt);
4996 break;
5000 dom = argv[optind];
5001 if (!dom && all == 0) {
5002 fprintf(stderr, "You must specify -a or a domain id.\n\n");
5003 help("tmem-thaw");
5004 return 1;
5007 if (all)
5008 domid = -1;
5009 else
5010 find_domain(dom);
5012 libxl_tmem_thaw(&ctx, domid);
5013 return 0;
5016 int main_tmem_set(int argc, char **argv)
5018 const char *dom = NULL;
5019 uint32_t weight = 0, cap = 0, compress = 0;
5020 int opt_w = 0, opt_c = 0, opt_p = 0;
5021 int all = 0;
5022 int opt;
5024 while ((opt = getopt(argc, argv, "aw:c:p:h")) != -1) {
5025 switch (opt) {
5026 case 'a':
5027 all = 1;
5028 break;
5029 case 'w':
5030 weight = strtol(optarg, NULL, 10);
5031 opt_w = 1;
5032 break;
5033 case 'c':
5034 cap = strtol(optarg, NULL, 10);
5035 opt_c = 1;
5036 break;
5037 case 'p':
5038 compress = strtol(optarg, NULL, 10);
5039 opt_p = 1;
5040 break;
5041 case 'h':
5042 help("tmem-set");
5043 return 0;
5044 default:
5045 fprintf(stderr, "option `%c' not supported.\n", opt);
5046 break;
5050 dom = argv[optind];
5051 if (!dom && all == 0) {
5052 fprintf(stderr, "You must specify -a or a domain id.\n\n");
5053 help("tmem-set");
5054 return 1;
5057 if (all)
5058 domid = -1;
5059 else
5060 find_domain(dom);
5062 if (!opt_w && !opt_c && !opt_p) {
5063 fprintf(stderr, "No set value specified.\n\n");
5064 help("tmem-set");
5065 return 1;
5068 if (opt_w)
5069 libxl_tmem_set(&ctx, domid, "weight", weight);
5070 if (opt_c)
5071 libxl_tmem_set(&ctx, domid, "cap", cap);
5072 if (opt_p)
5073 libxl_tmem_set(&ctx, domid, "compress", compress);
5075 return 0;
5078 int main_tmem_shared_auth(int argc, char **argv)
5080 const char *autharg = NULL;
5081 char *endptr = NULL;
5082 const char *dom = NULL;
5083 char *uuid = NULL;
5084 int auth = -1;
5085 int all = 0;
5086 int opt;
5088 while ((opt = getopt(argc, argv, "au:A:h")) != -1) {
5089 switch (opt) {
5090 case 'a':
5091 all = 1;
5092 break;
5093 case 'u':
5094 uuid = optarg;
5095 break;
5096 case 'A':
5097 autharg = optarg;
5098 break;
5099 case 'h':
5100 help("tmem-shared-auth");
5101 return 0;
5102 default:
5103 fprintf(stderr, "option `%c' not supported.\n", opt);
5104 break;
5108 dom = argv[optind];
5109 if (!dom && all == 0) {
5110 fprintf(stderr, "You must specify -a or a domain id.\n\n");
5111 help("tmem-shared-auth");
5112 return 1;
5115 if (all)
5116 domid = -1;
5117 else
5118 find_domain(dom);
5120 if (uuid == NULL || autharg == NULL) {
5121 fprintf(stderr, "No uuid or auth specified.\n\n");
5122 help("tmem-shared-auth");
5123 return 1;
5126 auth = strtol(autharg, &endptr, 10);
5127 if (*endptr != '\0') {
5128 fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
5129 return 1;
5132 libxl_tmem_shared_auth(&ctx, domid, uuid, auth);
5134 return 0;
5137 int main_tmem_freeable(int argc, char **argv)
5139 int opt;
5140 int mb;
5142 while ((opt = getopt(argc, argv, "h")) != -1) {
5143 switch (opt) {
5144 case 'h':
5145 help("tmem-freeable");
5146 return 0;
5147 default:
5148 fprintf(stderr, "option `%c' not supported.\n", opt);
5149 break;
5153 mb = libxl_tmem_freeable(&ctx);
5154 if (mb == -1)
5155 return -1;
5157 printf("%d\n", mb);
5158 return 0;
5161 int main_cpupoolcreate(int argc, char **argv)
5163 const char *filename = NULL;
5164 const char *p;
5165 char extra_config[1024];
5166 int dryrun = 0;
5167 int opt;
5168 int option_index = 0;
5169 static struct option long_options[] = {
5170 {"help", 0, 0, 'h'},
5171 {"defconfig", 1, 0, 'f'},
5172 {"dryrun", 0, 0, 'n'},
5173 {0, 0, 0, 0}
5174 };
5175 int ret;
5176 void *config_data = 0;
5177 int config_len = 0;
5178 XLU_Config *config;
5179 const char *buf;
5180 const char *name;
5181 const char *sched;
5182 uint32_t poolid;
5183 int schedid = -1;
5184 XLU_ConfigList *cpus;
5185 XLU_ConfigList *nodes;
5186 int n_cpus, n_nodes, i, n;
5187 libxl_cpumap freemap;
5188 libxl_cpumap cpumap;
5189 libxl_uuid uuid;
5190 libxl_topologyinfo topology;
5192 while (1) {
5193 opt = getopt_long(argc, argv, "hnf:", long_options, &option_index);
5194 if (opt == -1)
5195 break;
5197 switch (opt) {
5198 case 'f':
5199 filename = optarg;
5200 break;
5201 case 'h':
5202 help("cpupool-create");
5203 return 0;
5204 case 'n':
5205 dryrun = 1;
5206 break;
5207 default:
5208 fprintf(stderr, "option not supported\n");
5209 break;
5213 memset(extra_config, 0, sizeof(extra_config));
5214 while (optind < argc) {
5215 if ((p = strchr(argv[optind], '='))) {
5216 if (strlen(extra_config) + 1 < sizeof(extra_config)) {
5217 if (strlen(extra_config))
5218 strcat(extra_config, "\n");
5219 strcat(extra_config, argv[optind]);
5221 } else if (!filename) {
5222 filename = argv[optind];
5223 } else {
5224 help("cpupool-create");
5225 return -ERROR_FAIL;
5227 optind++;
5230 if (!filename) {
5231 help("cpupool-create");
5232 return -ERROR_FAIL;
5235 if (libxl_read_file_contents(&ctx, filename, &config_data, &config_len)) {
5236 fprintf(stderr, "Failed to read config file: %s: %s\n",
5237 filename, strerror(errno));
5238 return -ERROR_FAIL;
5240 if (strlen(extra_config)) {
5241 if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
5242 fprintf(stderr, "Failed to attach extra configration\n");
5243 return -ERROR_FAIL;
5245 config_data = xrealloc(config_data,
5246 config_len + strlen(extra_config) + 2);
5247 if (!config_data) {
5248 fprintf(stderr, "Failed to realloc config_data\n");
5249 return -ERROR_FAIL;
5251 strcat(config_data, "\n");
5252 strcat(config_data, extra_config);
5253 strcat(config_data, "\n");
5254 config_len += (strlen(extra_config) + 2);
5257 config = xlu_cfg_init(stderr, filename);
5258 if (!config) {
5259 fprintf(stderr, "Failed to allocate for configuration\n");
5260 return -ERROR_FAIL;
5263 ret = xlu_cfg_readdata(config, config_data, config_len);
5264 if (ret) {
5265 fprintf(stderr, "Failed to parse config file: %s\n", strerror(ret));
5266 return -ERROR_FAIL;
5269 if (!xlu_cfg_get_string (config, "name", &buf))
5270 name = strdup(buf);
5271 else
5272 name = libxl_basename(filename);
5273 if (!libxl_name_to_cpupoolid(&ctx, name, &poolid)) {
5274 fprintf(stderr, "Pool name \"%s\" already exists\n", name);
5275 return -ERROR_FAIL;
5278 if (!xlu_cfg_get_string (config, "sched", &buf)) {
5279 if ((schedid = libxl_name_to_schedid(&ctx, buf)) < 0) {
5280 fprintf(stderr, "Unknown scheduler\n");
5281 return -ERROR_FAIL;
5283 } else {
5284 if ((schedid = libxl_get_sched_id(&ctx)) < 0) {
5285 fprintf(stderr, "get_sched_id sysctl failed.\n");
5286 return -ERROR_FAIL;
5289 sched = libxl_schedid_to_name(&ctx, schedid);
5291 if (libxl_get_freecpus(&ctx, &freemap)) {
5292 fprintf(stderr, "libxl_get_freecpus failed\n");
5293 return -ERROR_FAIL;
5295 if (libxl_cpumap_alloc(&ctx, &cpumap)) {
5296 fprintf(stderr, "Failed to allocate cpumap\n");
5297 return -ERROR_FAIL;
5299 if (!xlu_cfg_get_list(config, "nodes", &nodes, 0, 0)) {
5300 n_cpus = 0;
5301 n_nodes = 0;
5302 if (libxl_get_topologyinfo(&ctx, &topology)) {
5303 fprintf(stderr, "libxl_get_topologyinfo failed\n");
5304 return -ERROR_FAIL;
5306 while ((buf = xlu_cfg_get_listitem(nodes, n_nodes)) != NULL) {
5307 n = atoi(buf);
5308 for (i = 0; i < topology.nodemap.entries; i++) {
5309 if ((topology.nodemap.array[i] == n) &&
5310 libxl_cpumap_test(&freemap, i)) {
5311 libxl_cpumap_set(&cpumap, i);
5312 n_cpus++;
5315 n_nodes++;
5318 libxl_topologyinfo_destroy(&topology);
5320 if (n_cpus == 0) {
5321 fprintf(stderr, "no free cpu found\n");
5322 return -ERROR_FAIL;
5324 } else if (!xlu_cfg_get_list(config, "cpus", &cpus, 0, 0)) {
5325 n_cpus = 0;
5326 while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) {
5327 i = atoi(buf);
5328 if ((i < 0) || (i >= freemap.size * 8) ||
5329 !libxl_cpumap_test(&freemap, i)) {
5330 fprintf(stderr, "cpu %d illegal or not free\n", i);
5331 return -ERROR_FAIL;
5333 libxl_cpumap_set(&cpumap, i);
5334 n_cpus++;
5336 } else {
5337 n_cpus = 1;
5338 n = 0;
5339 libxl_for_each_cpu(i, freemap)
5340 if (libxl_cpumap_test(&freemap, i)) {
5341 n++;
5342 libxl_cpumap_set(&cpumap, i);
5343 break;
5345 if (n < n_cpus) {
5346 fprintf(stderr, "no free cpu found\n");
5347 return -ERROR_FAIL;
5351 libxl_uuid_generate(&uuid);
5353 printf("Using config file \"%s\"\n", filename);
5354 printf("cpupool name: %s\n", name);
5355 printf("scheduler: %s\n", sched);
5356 printf("number of cpus: %d\n", n_cpus);
5358 if (dryrun)
5359 return 0;
5361 poolid = 0;
5362 if (libxl_create_cpupool(&ctx, name, schedid, cpumap, &uuid, &poolid)) {
5363 fprintf(stderr, "error on creating cpupool\n");
5364 return -ERROR_FAIL;
5367 return 0;
5370 int main_cpupoollist(int argc, char **argv)
5372 int opt;
5373 int option_index = 0;
5374 static struct option long_options[] = {
5375 {"help", 0, 0, 'h'},
5376 {"long", 0, 0, 'l'},
5377 {"cpus", 0, 0, 'c'},
5378 {0, 0, 0, 0}
5379 };
5380 int opt_long = 0;
5381 int opt_cpus = 0;
5382 const char *pool = NULL;
5383 libxl_cpupoolinfo *poolinfo;
5384 int n_pools, p, c, n;
5385 uint32_t poolid;
5386 char *name;
5387 int ret = 0;
5389 while (1) {
5390 opt = getopt_long(argc, argv, "hlc", long_options, &option_index);
5391 if (opt == -1)
5392 break;
5394 switch (opt) {
5395 case 'h':
5396 help("cpupool-list");
5397 return 0;
5398 case 'l':
5399 opt_long = 1;
5400 break;
5401 case 'c':
5402 opt_cpus = 1;
5403 break;
5404 default:
5405 fprintf(stderr, "option not supported\n");
5406 break;
5410 if ((optind + 1) < argc) {
5411 help("cpupool-list");
5412 return -ERROR_FAIL;
5414 if (optind < argc) {
5415 pool = argv[optind];
5416 if (libxl_name_to_cpupoolid(&ctx, pool, &poolid)) {
5417 fprintf(stderr, "Pool \'%s\' does not exist\n", pool);
5418 return -ERROR_FAIL;
5422 poolinfo = libxl_list_cpupool(&ctx, &n_pools);
5423 if (!poolinfo) {
5424 fprintf(stderr, "error getting cpupool info\n");
5425 return -ERROR_NOMEM;
5428 if (!opt_long) {
5429 printf("%-19s", "Name");
5430 if (opt_cpus)
5431 printf("CPU list\n");
5432 else
5433 printf("CPUs Sched Active Domain count\n");
5436 for (p = 0; p < n_pools; p++) {
5437 if (!ret && (!pool || (poolinfo[p].poolid != poolid))) {
5438 name = libxl_cpupoolid_to_name(&ctx, poolinfo[p].poolid);
5439 if (!name) {
5440 fprintf(stderr, "error getting cpupool info\n");
5441 ret = -ERROR_NOMEM;
5443 else if (opt_long) {
5444 ret = -ERROR_NI;
5445 } else {
5446 printf("%-19s", name);
5447 free(name);
5448 n = 0;
5449 libxl_for_each_cpu(c, poolinfo[p].cpumap)
5450 if (libxl_cpumap_test(&poolinfo[p].cpumap, c)) {
5451 if (n && opt_cpus) printf(",");
5452 if (opt_cpus) printf("%d", c);
5453 n++;
5455 if (!opt_cpus) {
5456 printf("%3d %9s y %4d", n,
5457 libxl_schedid_to_name(&ctx, poolinfo[p].sched_id),
5458 poolinfo[p].n_dom);
5460 printf("\n");
5463 libxl_cpupoolinfo_destroy(poolinfo + p);
5466 return ret;
5469 int main_cpupooldestroy(int argc, char **argv)
5471 int opt;
5472 const char *pool;
5473 uint32_t poolid;
5475 while ((opt = getopt(argc, argv, "h")) != -1) {
5476 switch (opt) {
5477 case 'h':
5478 help("cpupool-destroy");
5479 return 0;
5480 default:
5481 fprintf(stderr, "option `%c' not supported.\n", opt);
5482 break;
5486 pool = argv[optind];
5487 if (!pool) {
5488 fprintf(stderr, "no cpupool specified\n");
5489 help("cpupool-destroy");
5490 return -ERROR_FAIL;
5493 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5494 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5495 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5496 return -ERROR_FAIL;
5499 return -libxl_destroy_cpupool(&ctx, poolid);
5502 int main_cpupoolrename(int argc, char **argv)
5504 int opt;
5505 const char *pool;
5506 const char *new_name;
5507 uint32_t poolid;
5509 while ((opt = getopt(argc, argv, "h")) != -1) {
5510 switch (opt) {
5511 case 'h':
5512 help("cpupool-rename");
5513 return 0;
5514 default:
5515 fprintf(stderr, "option `%c' not supported.\n", opt);
5516 break;
5520 pool = argv[optind++];
5521 if (!pool || !argv[optind]) {
5522 fprintf(stderr, "'xl cpupool-rename' requires 2 arguments.\n\n");
5523 help("cpupool-rename");
5524 return 1;
5527 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5528 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5529 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5530 return -ERROR_FAIL;
5533 new_name = argv[optind];
5535 if (libxl_cpupool_rename(&ctx, new_name, poolid)) {
5536 fprintf(stderr, "Can't rename cpupool '%s'.\n", pool);
5537 return 1;
5540 return 0;
5543 int main_cpupoolcpuadd(int argc, char **argv)
5545 int opt;
5546 const char *pool;
5547 uint32_t poolid;
5548 int cpu;
5549 int node;
5550 int n;
5552 while ((opt = getopt(argc, argv, "h")) != -1) {
5553 switch (opt) {
5554 case 'h':
5555 help("cpupool-cpu-add");
5556 return 0;
5557 default:
5558 fprintf(stderr, "option `%c' not supported.\n", opt);
5559 break;
5563 pool = argv[optind++];
5564 if (!pool) {
5565 fprintf(stderr, "no cpupool specified\n");
5566 help("cpupool-cpu-add");
5567 return -ERROR_FAIL;
5570 if (!argv[optind]) {
5571 fprintf(stderr, "no cpu specified\n");
5572 help("cpupool-cpu-add");
5573 return -ERROR_FAIL;
5575 node = -1;
5576 cpu = -1;
5577 if (strncmp(argv[optind], "node:", 5) == 0) {
5578 node = atoi(argv[optind] + 5);
5579 } else {
5580 cpu = atoi(argv[optind]);
5583 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5584 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5585 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5586 return -ERROR_FAIL;
5589 if (cpu >= 0) {
5590 return -libxl_cpupool_cpuadd(&ctx, poolid, cpu);
5593 if (libxl_cpupool_cpuadd_node(&ctx, poolid, node, &n)) {
5594 fprintf(stderr, "libxl_cpupool_cpuadd_node failed\n");
5595 return -ERROR_FAIL;
5598 if (n > 0) {
5599 return 0;
5602 fprintf(stderr, "no free cpu found\n");
5603 return -ERROR_FAIL;
5606 int main_cpupoolcpuremove(int argc, char **argv)
5608 int opt;
5609 const char *pool;
5610 uint32_t poolid;
5611 int cpu;
5612 int node;
5613 int n;
5615 while ((opt = getopt(argc, argv, "h")) != -1) {
5616 switch (opt) {
5617 case 'h':
5618 help("cpupool-cpu-remove");
5619 return 0;
5620 default:
5621 fprintf(stderr, "option `%c' not supported.\n", opt);
5622 break;
5626 pool = argv[optind++];
5627 if (!pool) {
5628 fprintf(stderr, "no cpupool specified\n");
5629 help("cpupool-cpu-remove");
5630 return -ERROR_FAIL;
5633 if (!argv[optind]) {
5634 fprintf(stderr, "no cpu specified\n");
5635 help("cpupool-cpu-remove");
5636 return -ERROR_FAIL;
5638 node = -1;
5639 cpu = -1;
5640 if (strncmp(argv[optind], "node:", 5) == 0) {
5641 node = atoi(argv[optind] + 5);
5642 } else {
5643 cpu = atoi(argv[optind]);
5646 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5647 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5648 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5649 return -ERROR_FAIL;
5652 if (cpu >= 0) {
5653 return -libxl_cpupool_cpuremove(&ctx, poolid, cpu);
5656 if (libxl_cpupool_cpuremove_node(&ctx, poolid, node, &n)) {
5657 fprintf(stderr, "libxl_cpupool_cpuremove_node failed\n");
5658 return -ERROR_FAIL;
5661 if (n == 0) {
5662 fprintf(stderr, "no cpu of node found in cpupool\n");
5663 return -ERROR_FAIL;
5666 return 0;
5669 int main_cpupoolmigrate(int argc, char **argv)
5671 int opt;
5672 const char *pool;
5673 uint32_t poolid;
5674 const char *dom;
5675 uint32_t domid;
5677 while ((opt = getopt(argc, argv, "h")) != -1) {
5678 switch (opt) {
5679 case 'h':
5680 help("cpupool-migrate");
5681 return 0;
5682 default:
5683 fprintf(stderr, "option `%c' not supported.\n", opt);
5684 break;
5688 dom = argv[optind++];
5689 if (!dom) {
5690 fprintf(stderr, "no domain specified\n");
5691 help("cpupool-migrate");
5692 return -ERROR_FAIL;
5695 pool = argv[optind++];
5696 if (!pool) {
5697 fprintf(stderr, "no cpupool specified\n");
5698 help("cpupool-migrate");
5699 return -ERROR_FAIL;
5702 if (domain_qualifier_to_domid(dom, &domid, NULL) ||
5703 !libxl_domid_to_name(&ctx, domid)) {
5704 fprintf(stderr, "unknown domain \'%s\'\n", dom);
5705 return -ERROR_FAIL;
5708 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5709 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5710 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5711 return -ERROR_FAIL;
5714 return -libxl_cpupool_movedomain(&ctx, poolid, domid);
5717 int main_cpupoolnumasplit(int argc, char **argv)
5719 int ret;
5720 int opt;
5721 int p;
5722 int c;
5723 int n;
5724 uint32_t poolid;
5725 int schedid;
5726 int n_pools;
5727 int node;
5728 char name[16];
5729 libxl_uuid uuid;
5730 libxl_cpumap cpumap;
5731 libxl_cpupoolinfo *poolinfo;
5732 libxl_topologyinfo topology;
5734 while ((opt = getopt(argc, argv, "h")) != -1) {
5735 switch (opt) {
5736 case 'h':
5737 help("cpupool-numa-split");
5738 return 0;
5739 default:
5740 fprintf(stderr, "option `%c' not supported.\n", opt);
5741 break;
5744 ret = 0;
5746 poolinfo = libxl_list_cpupool(&ctx, &n_pools);
5747 if (!poolinfo) {
5748 fprintf(stderr, "error getting cpupool info\n");
5749 return -ERROR_NOMEM;
5751 poolid = poolinfo[0].poolid;
5752 schedid = poolinfo[0].sched_id;
5753 for (p = 0; p < n_pools; p++) {
5754 libxl_cpupoolinfo_destroy(poolinfo + p);
5756 if (n_pools > 1) {
5757 fprintf(stderr, "splitting not possible, already cpupools in use\n");
5758 return -ERROR_FAIL;
5761 if (libxl_get_topologyinfo(&ctx, &topology)) {
5762 fprintf(stderr, "libxl_get_topologyinfo failed\n");
5763 return -ERROR_FAIL;
5766 if (libxl_cpumap_alloc(&ctx, &cpumap)) {
5767 fprintf(stderr, "Failed to allocate cpumap\n");
5768 libxl_topologyinfo_destroy(&topology);
5769 return -ERROR_FAIL;
5772 /* Reset Pool-0 to 1st node: first add cpus, then remove cpus to avoid
5773 a cpupool without cpus in between */
5775 node = topology.nodemap.array[0];
5776 if (libxl_cpupool_cpuadd_node(&ctx, 0, node, &n)) {
5777 fprintf(stderr, "error on adding cpu to Pool 0\n");
5778 return -ERROR_FAIL;
5781 snprintf(name, 15, "Pool-node%d", node);
5782 ret = -libxl_cpupool_rename(&ctx, name, 0);
5783 if (ret) {
5784 fprintf(stderr, "error on renaming Pool 0\n");
5785 goto out;
5788 for (c = 0; c < topology.nodemap.entries; c++) {
5789 if (topology.nodemap.array[c] == node) {
5790 topology.nodemap.array[c] = LIBXL_CPUARRAY_INVALID_ENTRY;
5794 for (c = 0; c < topology.nodemap.entries; c++) {
5795 if (topology.nodemap.array[c] == LIBXL_CPUARRAY_INVALID_ENTRY) {
5796 continue;
5799 node = topology.nodemap.array[c];
5800 ret = -libxl_cpupool_cpuremove_node(&ctx, 0, node, &n);
5801 if (ret) {
5802 fprintf(stderr, "error on removing cpu from Pool 0\n");
5803 goto out;
5806 snprintf(name, 15, "Pool-node%d", node);
5807 libxl_uuid_generate(&uuid);
5808 ret = -libxl_create_cpupool(&ctx, name, schedid, cpumap, &uuid, &poolid);
5809 if (ret) {
5810 fprintf(stderr, "error on creating cpupool\n");
5811 goto out;
5814 ret = -libxl_cpupool_cpuadd_node(&ctx, 0, node, &n);
5815 if (ret) {
5816 fprintf(stderr, "error on adding cpus to cpupool\n");
5817 goto out;
5820 for (p = c; p < topology.nodemap.entries; p++) {
5821 if (topology.nodemap.array[p] == node) {
5822 topology.nodemap.array[p] = LIBXL_CPUARRAY_INVALID_ENTRY;
5827 out:
5828 libxl_topologyinfo_destroy(&topology);
5829 libxl_cpumap_destroy(&cpumap);
5831 return ret;