debuggers.hg

view tools/libxl/xl_cmdimpl.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents 47be85d61f11
children 6ec61438713a
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 }
461 break;
462 case DSTATE_TAP:
463 if ( *p == ':' ) {
464 *p = '\0';
465 if ( !strcmp(tok, "aio") ) {
466 disk->phystype = PHYSTYPE_AIO;
467 }else if ( !strcmp(tok, "vhd") ) {
468 disk->phystype = PHYSTYPE_VHD;
469 }else if ( !strcmp(tok, "qcow") ) {
470 disk->phystype = PHYSTYPE_QCOW;
471 }else if ( !strcmp(tok, "qcow2") ) {
472 disk->phystype = PHYSTYPE_QCOW2;
473 }else {
474 fprintf(stderr, "Unknown tapdisk type: %s\n", tok);
475 return 0;
476 }
478 tok = p + 1;
479 state = DSTATE_PHYSPATH;
480 }
481 break;
482 case DSTATE_PHYSPATH:
483 if ( *p == ',' ) {
484 int ioemu_len;
486 *p = '\0';
487 disk->physpath = (*tok) ? strdup(tok) : NULL;
488 tok = p + 1;
490 /* hack for ioemu disk spec */
491 ioemu_len = strlen("ioemu:");
492 state = DSTATE_VIRTPATH;
493 if ( tok + ioemu_len < end &&
494 !strncmp(tok, "ioemu:", ioemu_len)) {
495 tok += ioemu_len;
496 p += ioemu_len;
497 }
498 }
499 break;
500 case DSTATE_VIRTPATH:
501 if ( *p == ',' || *p == ':' || *p == '\0' ) {
502 switch(*p) {
503 case ':':
504 state = DSTATE_VIRTTYPE;
505 break;
506 case ',':
507 state = DSTATE_RW;
508 break;
509 case '\0':
510 state = DSTATE_TERMINAL;
511 break;
512 }
513 if ( tok == p )
514 goto out;
515 *p = '\0';
516 disk->virtpath = (*tok) ? strdup(tok) : NULL;
517 tok = p + 1;
518 }
519 break;
520 case DSTATE_VIRTTYPE:
521 if ( *p == ',' || *p == '\0' ) {
522 *p = '\0';
523 if ( !strcmp(tok, "cdrom") ) {
524 disk->is_cdrom = 1;
525 disk->unpluggable = 1;
526 }else{
527 fprintf(stderr, "Unknown virtual disk type: %s\n", tok);
528 return 0;
529 }
530 tok = p + 1;
531 state = (*p == ',') ? DSTATE_RW : DSTATE_TERMINAL;
532 }
533 break;
534 case DSTATE_RW:
535 if ( *p == '\0' ) {
536 disk->readwrite = (tok[0] == 'w');
537 tok = p + 1;
538 state = DSTATE_TERMINAL;
539 }
540 break;
541 case DSTATE_TERMINAL:
542 goto out;
543 }
544 }
546 out:
547 if ( tok != p || state != DSTATE_TERMINAL ) {
548 fprintf(stderr, "parse error in disk config near '%s'\n", tok);
549 return 0;
550 }
552 return 1;
553 }
555 static void parse_config_data(const char *configfile_filename_report,
556 const char *configfile_data,
557 int configfile_len,
558 libxl_domain_config *d_config,
559 libxl_device_model_info *dm_info)
560 {
561 const char *buf;
562 long l;
563 XLU_Config *config;
564 XLU_ConfigList *vbds, *nics, *pcis, *cvfbs, *net2s, *cpuids;
565 int pci_power_mgmt = 0;
566 int pci_msitranslate = 1;
567 int e;
569 libxl_domain_create_info *c_info = &d_config->c_info;
570 libxl_domain_build_info *b_info = &d_config->b_info;
572 config= xlu_cfg_init(stderr, configfile_filename_report);
573 if (!config) {
574 fprintf(stderr, "Failed to allocate for configuration\n");
575 exit(1);
576 }
578 e= xlu_cfg_readdata(config, configfile_data, configfile_len);
579 if (e) {
580 fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
581 exit(1);
582 }
584 libxl_init_create_info(c_info);
586 c_info->hvm = 0;
587 if (!xlu_cfg_get_string (config, "builder", &buf) &&
588 !strncmp(buf, "hvm", strlen(buf)))
589 c_info->hvm = 1;
591 if (!xlu_cfg_get_long (config, "hap", &l))
592 c_info->hap = l;
594 if (xlu_cfg_replace_string (config, "name", &c_info->name))
595 c_info->name = strdup("test");
597 if (!xlu_cfg_get_string (config, "uuid", &buf) ) {
598 if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
599 fprintf(stderr, "Failed to parse UUID: %s\n", buf);
600 exit(1);
601 }
602 }else{
603 libxl_uuid_generate(&c_info->uuid);
604 }
606 if (!xlu_cfg_get_long(config, "oos", &l))
607 c_info->oos = l;
609 if (!xlu_cfg_get_string (config, "pool", &buf)) {
610 c_info->poolid = -1;
611 cpupool_qualifier_to_cpupoolid(buf, &c_info->poolid, NULL);
612 }
613 c_info->poolname = libxl_cpupoolid_to_name(&ctx, c_info->poolid);
614 if (!c_info->poolname) {
615 fprintf(stderr, "Illegal pool specified\n");
616 exit(1);
617 }
619 libxl_init_build_info(b_info, c_info);
621 /* the following is the actual config parsing with overriding values in the structures */
622 if (!xlu_cfg_get_long (config, "vcpus", &l)) {
623 b_info->max_vcpus = l;
624 b_info->cur_vcpus = (1 << l) - 1;
625 }
627 if (!xlu_cfg_get_long (config, "maxvcpus", &l))
628 b_info->max_vcpus = l;
630 if (!xlu_cfg_get_long (config, "memory", &l)) {
631 b_info->max_memkb = l * 1024;
632 b_info->target_memkb = b_info->max_memkb;
633 }
635 if (!xlu_cfg_get_long (config, "maxmem", &l))
636 b_info->max_memkb = l * 1024;
638 if (xlu_cfg_get_string (config, "on_poweroff", &buf))
639 buf = "destroy";
640 if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
641 fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
642 exit(1);
643 }
645 if (xlu_cfg_get_string (config, "on_reboot", &buf))
646 buf = "restart";
647 if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
648 fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
649 exit(1);
650 }
652 if (xlu_cfg_get_string (config, "on_watchdog", &buf))
653 buf = "destroy";
654 if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
655 fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
656 exit(1);
657 }
660 if (xlu_cfg_get_string (config, "on_crash", &buf))
661 buf = "destroy";
662 if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
663 fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
664 exit(1);
665 }
667 /* libxl_get_required_shadow_memory() must be called after final values
668 * (default or specified) for vcpus and memory are set, because the
669 * calculation depends on those values. */
670 b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l)
671 ? l * 1024
672 : libxl_get_required_shadow_memory(b_info->max_memkb,
673 b_info->max_vcpus);
675 if (!xlu_cfg_get_long (config, "nomigrate", &l))
676 b_info->disable_migrate = l;
678 if (!xlu_cfg_get_long(config, "tsc_mode", &l))
679 b_info->tsc_mode = l;
681 if (!xlu_cfg_get_long (config, "videoram", &l))
682 b_info->video_memkb = l * 1024;
684 xlu_cfg_replace_string (config, "kernel", &b_info->kernel.path);
686 if (!xlu_cfg_get_long (config, "gfx_passthru", &l))
687 dm_info->gfx_passthru = l;
689 if (c_info->hvm == 1) {
690 if (!xlu_cfg_get_long (config, "pae", &l))
691 b_info->u.hvm.pae = l;
692 if (!xlu_cfg_get_long (config, "apic", &l))
693 b_info->u.hvm.apic = l;
694 if (!xlu_cfg_get_long (config, "acpi", &l))
695 b_info->u.hvm.acpi = l;
696 if (!xlu_cfg_get_long (config, "nx", &l))
697 b_info->u.hvm.nx = l;
698 if (!xlu_cfg_get_long (config, "viridian", &l))
699 b_info->u.hvm.viridian = l;
700 if (!xlu_cfg_get_long (config, "hpet", &l))
701 b_info->u.hvm.hpet = l;
702 if (!xlu_cfg_get_long (config, "vpt_align", &l))
703 b_info->u.hvm.vpt_align = l;
704 if (!xlu_cfg_get_long (config, "timer_mode", &l))
705 b_info->u.hvm.timer_mode = l;
706 } else {
707 char *cmdline = NULL;
708 const char *root = NULL, *extra = "";
710 xlu_cfg_get_string (config, "root", &root);
711 xlu_cfg_get_string (config, "extra", &extra);
713 if (root) {
714 if (asprintf(&cmdline, "root=%s %s", root, extra) == -1)
715 cmdline = NULL;
716 } else {
717 cmdline = strdup(extra);
718 }
720 if ((root || extra) && !cmdline) {
721 fprintf(stderr, "Failed to allocate memory for cmdline\n");
722 exit(1);
723 }
725 xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader);
726 xlu_cfg_replace_string (config, "bootloader_args", &b_info->u.pv.bootloader_args);
728 if (!b_info->u.pv.bootloader && !b_info->kernel.path) {
729 fprintf(stderr, "Neither kernel nor bootloader specified\n");
730 exit(1);
731 }
733 b_info->u.pv.cmdline = cmdline;
734 xlu_cfg_replace_string (config, "ramdisk", &b_info->u.pv.ramdisk.path);
735 }
737 if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
738 d_config->num_disks = 0;
739 d_config->disks = NULL;
740 while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
741 libxl_device_disk *disk;
742 char *buf2 = strdup(buf);
744 d_config->disks = (libxl_device_disk *) realloc(d_config->disks, sizeof (libxl_device_disk) * (d_config->num_disks + 1));
745 disk = d_config->disks + d_config->num_disks;
746 if ( !parse_disk_config(disk, buf2) ) {
747 exit(1);
748 }
750 free(buf2);
751 d_config->num_disks++;
752 }
753 }
755 if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
756 d_config->num_vifs = 0;
757 d_config->vifs = NULL;
758 while ((buf = xlu_cfg_get_listitem (nics, d_config->num_vifs)) != NULL) {
759 libxl_device_nic *nic;
760 char *buf2 = strdup(buf);
761 char *p, *p2;
763 d_config->vifs = (libxl_device_nic *) realloc(d_config->vifs, sizeof (libxl_device_nic) * (d_config->num_vifs+1));
764 nic = d_config->vifs + d_config->num_vifs;
765 CHK_ERRNO( libxl_device_nic_init(nic, d_config->num_vifs) );
767 p = strtok(buf2, ",");
768 if (!p)
769 goto skip;
770 do {
771 while (*p == ' ')
772 p++;
773 if ((p2 = strchr(p, '=')) == NULL)
774 break;
775 *p2 = '\0';
776 if (!strcmp(p, "model")) {
777 free(nic->model);
778 nic->model = strdup(p2 + 1);
779 } else if (!strcmp(p, "mac")) {
780 char *p3 = p2 + 1;
781 *(p3 + 2) = '\0';
782 nic->mac[0] = strtol(p3, NULL, 16);
783 p3 = p3 + 3;
784 *(p3 + 2) = '\0';
785 nic->mac[1] = strtol(p3, NULL, 16);
786 p3 = p3 + 3;
787 *(p3 + 2) = '\0';
788 nic->mac[2] = strtol(p3, NULL, 16);
789 p3 = p3 + 3;
790 *(p3 + 2) = '\0';
791 nic->mac[3] = strtol(p3, NULL, 16);
792 p3 = p3 + 3;
793 *(p3 + 2) = '\0';
794 nic->mac[4] = strtol(p3, NULL, 16);
795 p3 = p3 + 3;
796 *(p3 + 2) = '\0';
797 nic->mac[5] = strtol(p3, NULL, 16);
798 } else if (!strcmp(p, "bridge")) {
799 free(nic->bridge);
800 nic->bridge = strdup(p2 + 1);
801 } else if (!strcmp(p, "type")) {
802 if (!strcmp(p2 + 1, "ioemu"))
803 nic->nictype = NICTYPE_IOEMU;
804 else
805 nic->nictype = NICTYPE_VIF;
806 } else if (!strcmp(p, "ip")) {
807 inet_pton(AF_INET, p2 + 1, &nic->ip);
808 } else if (!strcmp(p, "script")) {
809 free(nic->script);
810 nic->script = strdup(p2 + 1);
811 } else if (!strcmp(p, "vifname")) {
812 free(nic->ifname);
813 nic->ifname = strdup(p2 + 1);
814 } else if (!strcmp(p, "backend")) {
815 if(libxl_name_to_domid(&ctx, (p2 + 1), &(nic->backend_domid))) {
816 fprintf(stderr, "Specified backend domain does not exist, defaulting to Dom0\n");
817 nic->backend_domid = 0;
818 }
819 } else if (!strcmp(p, "rate")) {
820 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
821 } else if (!strcmp(p, "accel")) {
822 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
823 }
824 } while ((p = strtok(NULL, ",")) != NULL);
825 skip:
826 free(buf2);
827 d_config->num_vifs++;
828 }
829 }
831 if (!xlu_cfg_get_list(config, "vif2", &net2s, 0, 0)) {
832 d_config->num_vif2s = 0;
833 d_config->vif2s = NULL;
834 while ((buf = xlu_cfg_get_listitem(net2s, d_config->num_vif2s))) {
835 libxl_device_net2 *net2;
836 char *buf2 = strdup(buf);
837 char *p;
839 d_config->vif2s = realloc(d_config->vif2s, sizeof (libxl_device_net2) * (d_config->num_vif2s + 1));
840 net2 = d_config->vif2s + d_config->num_vif2s;
842 libxl_device_net2_init(net2, d_config->num_vif2s);
844 for (p = strtok(buf2, ","); p; p = strtok(NULL, ",")) {
845 char* val;
846 while (isblank(*p))
847 p++;
848 val = strchr(p, '=');
849 if (val == NULL)
850 continue;
851 *val++ = 0;
852 if (!strcmp("front_mac", p)) {
853 libxl_strtomac(val, net2->front_mac);
854 } else if (!strcmp("back_mac", p)) {
855 libxl_strtomac(val, net2->back_mac);
856 } else if (!strcmp("backend", p)) {
857 domain_qualifier_to_domid(val, &net2->backend_domid, 0);
858 } else if (!strcmp("trusted", p)) {
859 net2->trusted = (*val == '1');
860 } else if (!strcmp("back_trusted", p)) {
861 net2->back_trusted = (*val == '1');
862 } else if (!strcmp("bridge", p)) {
863 free(net2->bridge);
864 net2->bridge = strdup(val);
865 } else if (!strcmp("filter_mac", p)) {
866 net2->filter_mac = (*val == '1');
867 } else if (!strcmp("front_filter_mac", p)) {
868 net2->front_filter_mac = (*val == '1');
869 } else if (!strcmp("pdev", p)) {
870 net2->pdev = strtoul(val, NULL, 10);
871 } else if (!strcmp("max_bypasses", p)) {
872 net2->max_bypasses = strtoul(val, NULL, 10);
873 }
874 }
875 free(buf2);
876 d_config->num_vif2s++;
877 }
878 }
880 if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
881 d_config->num_vfbs = 0;
882 d_config->num_vkbs = 0;
883 d_config->vfbs = NULL;
884 d_config->vkbs = NULL;
885 while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
886 libxl_device_vfb *vfb;
887 libxl_device_vkb *vkb;
889 char *buf2 = strdup(buf);
890 char *p, *p2;
892 d_config->vfbs = (libxl_device_vfb *) realloc(d_config->vfbs, sizeof(libxl_device_vfb) * (d_config->num_vfbs + 1));
893 vfb = d_config->vfbs + d_config->num_vfbs;
894 libxl_device_vfb_init(vfb, d_config->num_vfbs);
896 d_config->vkbs = (libxl_device_vkb *) realloc(d_config->vkbs, sizeof(libxl_device_vkb) * (d_config->num_vkbs + 1));
897 vkb = d_config->vkbs + d_config->num_vkbs;
898 libxl_device_vkb_init(vkb, d_config->num_vkbs);
900 p = strtok(buf2, ",");
901 if (!p)
902 goto skip_vfb;
903 do {
904 while (*p == ' ')
905 p++;
906 if ((p2 = strchr(p, '=')) == NULL)
907 break;
908 *p2 = '\0';
909 if (!strcmp(p, "vnc")) {
910 vfb->vnc = atoi(p2 + 1);
911 } else if (!strcmp(p, "vnclisten")) {
912 free(vfb->vnclisten);
913 vfb->vnclisten = strdup(p2 + 1);
914 } else if (!strcmp(p, "vncpasswd")) {
915 free(vfb->vncpasswd);
916 vfb->vncpasswd = strdup(p2 + 1);
917 } else if (!strcmp(p, "vncdisplay")) {
918 vfb->vncdisplay = atoi(p2 + 1);
919 } else if (!strcmp(p, "vncunused")) {
920 vfb->vncunused = atoi(p2 + 1);
921 } else if (!strcmp(p, "keymap")) {
922 free(vfb->keymap);
923 vfb->keymap = strdup(p2 + 1);
924 } else if (!strcmp(p, "sdl")) {
925 vfb->sdl = atoi(p2 + 1);
926 } else if (!strcmp(p, "opengl")) {
927 vfb->opengl = atoi(p2 + 1);
928 } else if (!strcmp(p, "display")) {
929 free(vfb->display);
930 vfb->display = strdup(p2 + 1);
931 } else if (!strcmp(p, "xauthority")) {
932 free(vfb->xauthority);
933 vfb->xauthority = strdup(p2 + 1);
934 }
935 } while ((p = strtok(NULL, ",")) != NULL);
936 skip_vfb:
937 free(buf2);
938 d_config->num_vfbs++;
939 d_config->num_vkbs++;
940 }
941 }
943 if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
944 pci_msitranslate = l;
946 if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
947 pci_power_mgmt = l;
949 if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
950 int i;
951 d_config->num_pcidevs = 0;
952 d_config->pcidevs = NULL;
953 for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
954 libxl_device_pci *pcidev;
956 d_config->pcidevs = (libxl_device_pci *) realloc(d_config->pcidevs, sizeof (libxl_device_pci) * (d_config->num_pcidevs + 1));
957 pcidev = d_config->pcidevs + d_config->num_pcidevs;
958 memset(pcidev, 0x00, sizeof(libxl_device_pci));
960 pcidev->msitranslate = pci_msitranslate;
961 pcidev->power_mgmt = pci_power_mgmt;
962 if (!libxl_device_pci_parse_bdf(&ctx, pcidev, buf))
963 d_config->num_pcidevs++;
964 }
965 }
967 switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
968 case 0:
969 {
970 int i;
971 const char *errstr;
973 for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
974 e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
975 switch (e) {
976 case 0: continue;
977 case 1:
978 errstr = "illegal leaf number";
979 break;
980 case 2:
981 errstr = "illegal subleaf number";
982 break;
983 case 3:
984 errstr = "missing colon";
985 break;
986 case 4:
987 errstr = "invalid register name (must be e[abcd]x)";
988 break;
989 case 5:
990 errstr = "policy string must be exactly 32 characters long";
991 break;
992 default:
993 errstr = "unknown error";
994 break;
995 }
996 fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
997 fprintf(stderr, " error #%i: %s\n", e, errstr);
998 }
999 }
1000 break;
1001 case EINVAL: /* config option is not a list, parse as a string */
1002 if (!xlu_cfg_get_string(config, "cpuid", &buf)) {
1003 char *buf2, *p, *strtok_ptr = NULL;
1004 const char *errstr;
1006 buf2 = strdup(buf);
1007 p = strtok_r(buf2, ",", &strtok_ptr);
1008 if (p == NULL) {
1009 free(buf2);
1010 break;
1012 if (strcmp(p, "host")) {
1013 fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
1014 fprintf(stderr, " error: first word must be \"host\"\n");
1015 free(buf2);
1016 break;
1018 for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
1019 p = strtok_r(NULL, ",", &strtok_ptr)) {
1020 e = libxl_cpuid_parse_config(&b_info->cpuid, p);
1021 switch (e) {
1022 case 0: continue;
1023 case 1:
1024 errstr = "missing \"=\" in key=value";
1025 break;
1026 case 2:
1027 errstr = "unknown CPUID flag name";
1028 break;
1029 case 3:
1030 errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
1031 break;
1032 default:
1033 errstr = "unknown error";
1034 break;
1036 fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
1037 fprintf(stderr, " error #%i: %s\n", e, errstr);
1039 free(buf2);
1041 break;
1042 default:
1043 break;
1046 if (c_info->hvm == 1) {
1047 /* init dm from c and b */
1048 libxl_init_dm_info(dm_info, c_info, b_info);
1050 /* then process config related to dm */
1051 xlu_cfg_replace_string (config, "device_model", &dm_info->device_model);
1052 if (!xlu_cfg_get_long (config, "stdvga", &l))
1053 dm_info->stdvga = l;
1054 if (!xlu_cfg_get_long (config, "vnc", &l))
1055 dm_info->vnc = l;
1056 xlu_cfg_replace_string (config, "vnclisten", &dm_info->vnclisten);
1057 xlu_cfg_replace_string (config, "vncpasswd", &dm_info->vncpasswd);
1058 if (!xlu_cfg_get_long (config, "vncdisplay", &l))
1059 dm_info->vncdisplay = l;
1060 if (!xlu_cfg_get_long (config, "vncunused", &l))
1061 dm_info->vncunused = l;
1062 xlu_cfg_replace_string (config, "keymap", &dm_info->keymap);
1063 if (!xlu_cfg_get_long (config, "sdl", &l))
1064 dm_info->sdl = l;
1065 if (!xlu_cfg_get_long (config, "opengl", &l))
1066 dm_info->opengl = l;
1067 if (!xlu_cfg_get_long (config, "nographic", &l))
1068 dm_info->nographic = l;
1069 if (!xlu_cfg_get_long (config, "gfx_passthru", &l))
1070 dm_info->gfx_passthru = l;
1071 xlu_cfg_replace_string (config, "serial", &dm_info->serial);
1072 xlu_cfg_replace_string (config, "boot", &dm_info->boot);
1073 if (!xlu_cfg_get_long (config, "usb", &l))
1074 dm_info->usb = l;
1075 xlu_cfg_replace_string (config, "usbdevice", &dm_info->usbdevice);
1076 xlu_cfg_replace_string (config, "soundhw", &dm_info->soundhw);
1077 if (!xlu_cfg_get_long (config, "xen_platform_pci", &l))
1078 dm_info->xen_platform_pci = l;
1081 dm_info->type = c_info->hvm ? XENFV : XENPV;
1083 xlu_cfg_destroy(config);
1086 static void *xmalloc(size_t sz) {
1087 void *r;
1088 r = malloc(sz);
1089 if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
1090 (unsigned long)sz); exit(-ERROR_FAIL); }
1091 return r;
1094 static void *xrealloc(void *ptr, size_t sz) {
1095 void *r;
1096 if (!sz) { free(ptr); return 0; }
1097 /* realloc(non-0, 0) has a useless return value;
1098 * but xrealloc(anything, 0) is like free
1099 */
1100 r = realloc(ptr, sz);
1101 if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
1102 (unsigned long)sz); exit(-ERROR_FAIL); }
1103 return r;
1106 /* Returns 1 if domain should be restarted, 2 if domain should be renamed then restarted */
1107 static int handle_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1108 libxl_domain_config *d_config, libxl_dominfo *info)
1110 int restart = 0;
1111 enum libxl_action_on_shutdown action;
1113 switch (info->shutdown_reason) {
1114 case SHUTDOWN_poweroff:
1115 action = d_config->on_poweroff;
1116 break;
1117 case SHUTDOWN_reboot:
1118 action = d_config->on_reboot;
1119 break;
1120 case SHUTDOWN_suspend:
1121 return 0;
1122 case SHUTDOWN_crash:
1123 action = d_config->on_crash;
1124 break;
1125 case SHUTDOWN_watchdog:
1126 action = d_config->on_watchdog;
1127 break;
1128 default:
1129 LOG("Unknown shutdown reason code %d. Destroying domain.", info->shutdown_reason);
1130 action = LIBXL_ACTION_DESTROY;
1133 LOG("Action for shutdown reason code %d is %s", info->shutdown_reason, action_on_shutdown_names[action]);
1135 if (action == LIBXL_ACTION_COREDUMP_DESTROY || action == LIBXL_ACTION_COREDUMP_RESTART) {
1136 char *corefile;
1137 int rc;
1139 if (asprintf(&corefile, "/var/xen/dump/%s", d_config->c_info.name) < 0) {
1140 LOG("failed to construct core dump path");
1141 } else {
1142 LOG("dumping core to %s", corefile);
1143 rc=libxl_domain_core_dump(ctx, domid, corefile);
1144 if (rc) LOG("core dump failed (rc=%d).", rc);
1146 /* No point crying over spilled milk, continue on failure. */
1148 if (action == LIBXL_ACTION_COREDUMP_DESTROY)
1149 action = LIBXL_ACTION_DESTROY;
1150 else
1151 action = LIBXL_ACTION_RESTART;
1154 switch (action) {
1155 case LIBXL_ACTION_PRESERVE:
1156 break;
1158 case LIBXL_ACTION_RESTART_RENAME:
1159 restart = 2;
1160 break;
1162 case LIBXL_ACTION_RESTART:
1163 restart = 1;
1164 /* fall-through */
1165 case LIBXL_ACTION_DESTROY:
1166 LOG("Domain %d needs to be cleaned up: destroying the domain", domid);
1167 libxl_domain_destroy(ctx, domid, 0);
1168 break;
1170 case LIBXL_ACTION_COREDUMP_DESTROY:
1171 case LIBXL_ACTION_COREDUMP_RESTART:
1172 /* Already handled these above. */
1173 abort();
1176 return restart;
1179 static int preserve_domain(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1180 libxl_domain_config *d_config, libxl_dominfo *info)
1182 time_t now;
1183 struct tm tm;
1184 char stime[24];
1186 libxl_uuid new_uuid;
1188 int rc;
1190 now = time(NULL);
1191 if (now == ((time_t) -1)) {
1192 LOG("Failed to get current time for domain rename");
1193 return 0;
1196 tzset();
1197 if (gmtime_r(&now, &tm) == NULL) {
1198 LOG("Failed to convert time to UTC");
1199 return 0;
1202 if (!strftime(&stime[0], sizeof(stime), "-%Y%m%dT%H%MZ", &tm)) {
1203 LOG("Failed to format time as a string");
1204 return 0;
1207 libxl_uuid_generate(&new_uuid);
1209 LOG("Preserving domain %d %s with suffix%s", domid, d_config->c_info.name, stime);
1210 rc = libxl_domain_preserve(ctx, domid, &d_config->c_info, stime, new_uuid);
1212 return rc == 0 ? 1 : 0;
1215 struct domain_create {
1216 int debug;
1217 int daemonize;
1218 int paused;
1219 int dryrun;
1220 int quiet;
1221 int console_autoconnect;
1222 const char *config_file;
1223 const char *extra_config; /* extra config string */
1224 const char *restore_file;
1225 int migrate_fd; /* -1 means none */
1226 char **migration_domname_r; /* from malloc */
1227 };
1229 static int freemem(libxl_domain_build_info *b_info, libxl_device_model_info *dm_info)
1231 int rc, retries = 3;
1232 uint32_t need_memkb, free_memkb;
1234 if (!autoballoon)
1235 return 0;
1237 rc = libxl_domain_need_memory(&ctx, b_info, dm_info, &need_memkb);
1238 if (rc < 0)
1239 return rc;
1241 do {
1242 rc = libxl_get_free_memory(&ctx, &free_memkb);
1243 if (rc < 0)
1244 return rc;
1246 if (free_memkb >= need_memkb)
1247 return 0;
1249 rc = libxl_set_memory_target(&ctx, 0, free_memkb - need_memkb, 1, 0);
1250 if (rc < 0)
1251 return rc;
1253 rc = libxl_wait_for_free_memory(&ctx, domid, need_memkb, 10);
1254 if (!rc)
1255 return 0;
1256 else if (rc != ERROR_NOMEM)
1257 return rc;
1259 /* the memory target has been reached but the free memory is still
1260 * not enough: loop over again */
1261 rc = libxl_wait_for_memory_target(&ctx, 0, 1);
1262 if (rc < 0)
1263 return rc;
1265 retries--;
1266 } while (retries > 0);
1268 return ERROR_NOMEM;
1271 static int autoconnect_console(libxl_ctx *ctx, uint32_t domid, void *priv)
1273 pid_t *pid = priv;
1275 *pid = fork();
1276 if (*pid < 0) {
1277 perror("unable to fork xenconsole");
1278 return ERROR_FAIL;
1279 } else if (*pid > 0)
1280 return 0;
1282 libxl_ctx_postfork(ctx);
1284 sleep(1);
1285 libxl_primary_console_exec(ctx, domid);
1286 /* Do not return. xl continued in child process */
1287 fprintf(stderr, "Unable to attach console\n");
1288 _exit(1);
1291 static int create_domain(struct domain_create *dom_info)
1293 libxl_domain_config d_config;
1295 int debug = dom_info->debug;
1296 int daemonize = dom_info->daemonize;
1297 int paused = dom_info->paused;
1298 const char *config_file = dom_info->config_file;
1299 const char *extra_config = dom_info->extra_config;
1300 const char *restore_file = dom_info->restore_file;
1301 int migrate_fd = dom_info->migrate_fd;
1303 int fd;
1304 int need_daemon = 1;
1305 int ret, rc;
1306 libxl_waiter *w1 = NULL, *w2 = NULL;
1307 void *config_data = 0;
1308 int config_len = 0;
1309 int restore_fd = -1;
1310 int status = 0;
1311 libxl_console_ready cb;
1312 pid_t child_console_pid = -1;
1313 struct save_file_header hdr;
1315 memset(&d_config, 0x00, sizeof(d_config));
1317 if (restore_file) {
1318 uint8_t *optdata_begin = 0;
1319 const uint8_t *optdata_here = 0;
1320 union { uint32_t u32; char b[4]; } u32buf;
1321 uint32_t badflags;
1323 restore_fd = migrate_fd >= 0 ? migrate_fd :
1324 open(restore_file, O_RDONLY);
1326 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
1327 sizeof(hdr), restore_file, "header") );
1328 if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
1329 fprintf(stderr, "File has wrong magic number -"
1330 " corrupt or for a different tool?\n");
1331 return ERROR_INVAL;
1333 if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
1334 fprintf(stderr, "File has wrong byte order\n");
1335 return ERROR_INVAL;
1337 fprintf(stderr, "Loading new save file %s"
1338 " (new xl fmt info"
1339 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
1340 restore_file, hdr.mandatory_flags, hdr.optional_flags,
1341 hdr.optional_data_len);
1343 badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
1344 if (badflags) {
1345 fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
1346 "which are not supported; need newer xl\n",
1347 badflags);
1348 return ERROR_INVAL;
1350 if (hdr.optional_data_len) {
1351 optdata_begin = xmalloc(hdr.optional_data_len);
1352 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
1353 hdr.optional_data_len, restore_file, "optdata") );
1356 #define OPTDATA_LEFT (hdr.optional_data_len - (optdata_here - optdata_begin))
1357 #define WITH_OPTDATA(amt, body) \
1358 if (OPTDATA_LEFT < (amt)) { \
1359 fprintf(stderr, "Savefile truncated.\n"); \
1360 return ERROR_INVAL; \
1361 } else { \
1362 body; \
1363 optdata_here += (amt); \
1366 optdata_here = optdata_begin;
1368 if (OPTDATA_LEFT) {
1369 fprintf(stderr, " Savefile contains xl domain config\n");
1370 WITH_OPTDATA(4, {
1371 memcpy(u32buf.b, optdata_here, 4);
1372 config_len = u32buf.u32;
1373 });
1374 WITH_OPTDATA(config_len, {
1375 config_data = xmalloc(config_len);
1376 memcpy(config_data, optdata_here, config_len);
1377 });
1382 if (config_file) {
1383 free(config_data); config_data = 0;
1384 ret = libxl_read_file_contents(&ctx, config_file,
1385 &config_data, &config_len);
1386 if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
1387 config_file, strerror(errno)); return ERROR_FAIL; }
1388 if (!restore_file && extra_config && strlen(extra_config)) {
1389 if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
1390 fprintf(stderr, "Failed to attach extra configration\n");
1391 return ERROR_FAIL;
1393 /* allocate space for the extra config plus two EOLs plus \0 */
1394 config_data = realloc(config_data, config_len
1395 + strlen(extra_config) + 2 + 1);
1396 if (!config_data) {
1397 fprintf(stderr, "Failed to realloc config_data\n");
1398 return ERROR_FAIL;
1400 config_len += sprintf(config_data + config_len, "\n%s\n",
1401 extra_config);
1403 } else {
1404 if (!config_data) {
1405 fprintf(stderr, "Config file not specified and"
1406 " none in save file\n");
1407 return ERROR_INVAL;
1409 config_file = "<saved>";
1412 if (!dom_info->quiet)
1413 printf("Parsing config file %s\n", config_file);
1415 parse_config_data(config_file, config_data, config_len, &d_config, &d_config.dm_info);
1417 ret = 0;
1418 if (dom_info->dryrun)
1419 goto out;
1421 if (migrate_fd >= 0) {
1422 if (d_config.c_info.name) {
1423 /* when we receive a domain we get its name from the config
1424 * file; and we receive it to a temporary name */
1425 assert(!common_domname);
1427 common_domname = d_config.c_info.name;
1428 d_config.c_info.name = 0; /* steals allocation from config */
1430 if (asprintf(&d_config.c_info.name,
1431 "%s--incoming", common_domname) < 0) {
1432 fprintf(stderr, "Failed to allocate memory in asprintf\n");
1433 exit(1);
1435 *dom_info->migration_domname_r = strdup(d_config.c_info.name);
1439 if (debug)
1440 printf_info(-1, &d_config, &d_config.dm_info);
1442 start:
1443 domid = -1;
1445 rc = acquire_lock();
1446 if (rc < 0)
1447 goto error_out;
1449 ret = freemem(&d_config.b_info, &d_config.dm_info);
1450 if (ret < 0) {
1451 fprintf(stderr, "failed to free memory for the domain\n");
1452 ret = ERROR_FAIL;
1453 goto error_out;
1456 if ( dom_info->console_autoconnect ) {
1457 cb = autoconnect_console;
1458 }else{
1459 cb = NULL;
1462 if ( restore_file ) {
1463 ret = libxl_domain_create_restore(&ctx, &d_config,
1464 cb, &child_console_pid,
1465 &domid, restore_fd);
1466 }else{
1467 ret = libxl_domain_create_new(&ctx, &d_config,
1468 cb, &child_console_pid, &domid);
1470 if ( ret )
1471 goto error_out;
1473 ret = libxl_userdata_store(&ctx, domid, "xl",
1474 config_data, config_len);
1475 if (ret) {
1476 perror("cannot save config file");
1477 ret = ERROR_FAIL;
1478 goto error_out;
1481 release_lock();
1483 if (!paused)
1484 libxl_domain_unpause(&ctx, domid);
1486 ret = domid; /* caller gets success in parent */
1487 if (!daemonize)
1488 goto out;
1490 if (need_daemon) {
1491 char *fullname, *name;
1492 pid_t child1, got_child;
1493 int nullfd;
1495 child1 = libxl_fork(&ctx);
1496 if (child1) {
1497 printf("Daemon running with PID %d\n", child1);
1499 for (;;) {
1500 got_child = waitpid(child1, &status, 0);
1501 if (got_child == child1) break;
1502 assert(got_child == -1);
1503 if (errno != EINTR) {
1504 perror("failed to wait for daemonizing child");
1505 ret = ERROR_FAIL;
1506 goto error_out;
1509 if (status) {
1510 libxl_report_child_exitstatus(&ctx, XTL_ERROR,
1511 "daemonizing child", child1, status);
1512 ret = ERROR_FAIL;
1513 goto error_out;
1515 ret = domid;
1516 goto out;
1519 rc = libxl_ctx_postfork(&ctx);
1520 if (rc) {
1521 LOG("failed to reinitialise context after fork");
1522 exit(-1);
1525 if (asprintf(&name, "xl-%s", d_config.c_info.name) < 0) {
1526 LOG("Failed to allocate memory in asprintf");
1527 exit(1);
1529 rc = libxl_create_logfile(&ctx, name, &fullname);
1530 if (rc) {
1531 LOG("failed to open logfile %s: %s",fullname,strerror(errno));
1532 exit(-1);
1535 CHK_ERRNO(( logfile = open(fullname, O_WRONLY|O_CREAT, 0644) )<0);
1536 free(fullname);
1537 free(name);
1539 CHK_ERRNO(( nullfd = open("/dev/null", O_RDONLY) )<0);
1540 dup2(nullfd, 0);
1541 dup2(logfile, 1);
1542 dup2(logfile, 2);
1544 CHK_ERRNO(daemon(0, 1) < 0);
1545 need_daemon = 0;
1547 LOG("Waiting for domain %s (domid %d) to die [pid %ld]",
1548 d_config.c_info.name, domid, (long)getpid());
1549 w1 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter) * d_config.num_disks);
1550 w2 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter));
1551 libxl_wait_for_disk_ejects(&ctx, domid, d_config.disks, d_config.num_disks, w1);
1552 libxl_wait_for_domain_death(&ctx, domid, w2);
1553 libxl_get_wait_fd(&ctx, &fd);
1554 while (1) {
1555 int ret;
1556 fd_set rfds;
1557 libxl_dominfo info;
1558 libxl_event event;
1559 libxl_device_disk disk;
1561 FD_ZERO(&rfds);
1562 FD_SET(fd, &rfds);
1564 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
1565 if (!ret)
1566 continue;
1567 libxl_get_event(&ctx, &event);
1568 switch (event.type) {
1569 case LIBXL_EVENT_DOMAIN_DEATH:
1570 ret = libxl_event_get_domain_death_info(&ctx, domid, &event, &info);
1572 if (ret < 0) continue;
1574 LOG("Domain %d is dead", domid);
1576 if (ret) {
1577 switch (handle_domain_death(&ctx, domid, &event, &d_config, &info)) {
1578 case 2:
1579 if (!preserve_domain(&ctx, domid, &event, &d_config, &info)) {
1580 /* If we fail then exit leaving the old domain in place. */
1581 ret = -1;
1582 goto out;
1585 /* Otherwise fall through and restart. */
1586 case 1:
1588 libxl_free_waiter(w1);
1589 libxl_free_waiter(w2);
1590 free(w1);
1591 free(w2);
1593 /*
1594 * Do not attempt to reconnect if we come round again due to a
1595 * guest reboot -- the stdin/out will be disconnected by then.
1596 */
1597 dom_info->console_autoconnect = 0;
1599 /* Some settings only make sense on first boot. */
1600 paused = 0;
1601 if (common_domname
1602 && strcmp(d_config.c_info.name, common_domname)) {
1603 d_config.c_info.name = strdup(common_domname);
1606 /*
1607 * XXX FIXME: If this sleep is not there then domain
1608 * re-creation fails sometimes.
1609 */
1610 LOG("Done. Rebooting now");
1611 sleep(2);
1612 goto start;
1613 case 0:
1614 LOG("Done. Exiting now");
1615 ret = 0;
1616 goto out;
1618 } else {
1619 LOG("Unable to get domain death info, quitting");
1620 goto out;
1622 break;
1623 case LIBXL_EVENT_DISK_EJECT:
1624 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
1625 libxl_cdrom_insert(&ctx, domid, &disk);
1626 break;
1628 libxl_free_event(&event);
1631 error_out:
1632 release_lock();
1633 if (domid > 0)
1634 libxl_domain_destroy(&ctx, domid, 0);
1636 out:
1637 if (logfile != 2)
1638 close(logfile);
1640 libxl_domain_config_destroy(&d_config);
1642 free(config_data);
1644 waitpid_out:
1645 if (child_console_pid > 0 &&
1646 waitpid(child_console_pid, &status, 0) < 0 && errno == EINTR)
1647 goto waitpid_out;
1649 /*
1650 * If we have daemonized then do not return to the caller -- this has
1651 * already happened in the parent.
1652 */
1653 if ( !need_daemon )
1654 exit(ret);
1656 return ret;
1659 void help(const char *command)
1661 int i;
1662 struct cmd_spec *cmd;
1664 if (!command || !strcmp(command, "help")) {
1665 printf("Usage xl [-v] <subcommand> [args]\n\n");
1666 printf("xl full list of subcommands:\n\n");
1667 for (i = 0; i < cmdtable_len; i++)
1668 printf(" %-20s%s\n",
1669 cmd_table[i].cmd_name, cmd_table[i].cmd_desc);
1670 } else {
1671 cmd = cmdtable_lookup(command);
1672 if (cmd) {
1673 printf("Usage: xl [-v] %s %s\n\n%s.\n\n",
1674 cmd->cmd_name,
1675 cmd->cmd_usage,
1676 cmd->cmd_desc);
1677 if (cmd->cmd_option)
1678 printf("Options:\n\n%s\n", cmd->cmd_option);
1680 else {
1681 printf("command \"%s\" not implemented\n", command);
1686 static int64_t parse_mem_size_kb(const char *mem)
1688 char *endptr;
1689 int64_t kbytes;
1691 kbytes = strtoll(mem, &endptr, 10);
1693 if (strlen(endptr) > 1)
1694 return -1;
1696 switch (tolower((uint8_t)*endptr)) {
1697 case 't':
1698 kbytes <<= 10;
1699 case 'g':
1700 kbytes <<= 10;
1701 case '\0':
1702 case 'm':
1703 kbytes <<= 10;
1704 case 'k':
1705 break;
1706 case 'b':
1707 kbytes >>= 10;
1708 break;
1709 default:
1710 return -1;
1713 return kbytes;
1716 static int set_memory_max(const char *p, const char *mem)
1718 int64_t memorykb;
1719 int rc;
1721 find_domain(p);
1723 memorykb = parse_mem_size_kb(mem);
1724 if (memorykb == -1) {
1725 fprintf(stderr, "invalid memory size: %s\n", mem);
1726 exit(3);
1729 rc = libxl_domain_setmaxmem(&ctx, domid, memorykb);
1731 return rc;
1734 int main_memmax(int argc, char **argv)
1736 int opt = 0;
1737 char *p = NULL, *mem;
1738 int rc;
1740 while ((opt = getopt(argc, argv, "h")) != -1) {
1741 switch (opt) {
1742 case 'h':
1743 help("mem-max");
1744 exit(0);
1745 default:
1746 fprintf(stderr, "option not supported\n");
1747 break;
1750 if (optind >= argc - 1) {
1751 help("mem-max");
1752 return 2;
1755 p = argv[optind];
1756 mem = argv[optind + 1];
1758 rc = set_memory_max(p, mem);
1759 if (rc) {
1760 fprintf(stderr, "cannot set domid %d static max memory to : %s\n", domid, mem);
1761 return 1;
1764 return 0;
1767 static void set_memory_target(const char *p, const char *mem)
1769 long long int memorykb;
1771 find_domain(p);
1773 memorykb = parse_mem_size_kb(mem);
1774 if (memorykb == -1) {
1775 fprintf(stderr, "invalid memory size: %s\n", mem);
1776 exit(3);
1779 libxl_set_memory_target(&ctx, domid, memorykb, 0, /* enforce */ 1);
1782 int main_memset(int argc, char **argv)
1784 int opt = 0;
1785 const char *p = NULL, *mem;
1787 while ((opt = getopt(argc, argv, "h:")) != -1) {
1788 switch (opt) {
1789 case 'h':
1790 help("mem-set");
1791 return 0;
1792 default:
1793 fprintf(stderr, "option not supported\n");
1794 break;
1797 if (optind >= argc - 1) {
1798 help("mem-set");
1799 return 2;
1802 p = argv[optind];
1803 mem = argv[optind + 1];
1805 set_memory_target(p, mem);
1806 return 0;
1809 static void cd_insert(const char *dom, const char *virtdev, char *phys)
1811 libxl_device_disk disk; /* we don't free disk's contents */
1812 char *p;
1814 find_domain(dom);
1816 disk.backend_domid = 0;
1817 disk.domid = domid;
1818 if (phys) {
1819 p = strchr(phys, ':');
1820 if (!p) {
1821 fprintf(stderr, "No type specified, ");
1822 disk.physpath = phys;
1823 if (!strncmp(phys, "/dev", 4)) {
1824 fprintf(stderr, "assuming phy:\n");
1825 disk.phystype = PHYSTYPE_PHY;
1826 } else {
1827 fprintf(stderr, "assuming file:\n");
1828 disk.phystype = PHYSTYPE_FILE;
1830 } else {
1831 *p = '\0';
1832 p++;
1833 disk.physpath = p;
1834 libxl_string_to_phystype(&ctx, phys, &disk.phystype);
1836 } else {
1837 disk.physpath = NULL;
1838 disk.phystype = 0;
1840 disk.virtpath = (char*)virtdev;
1841 disk.unpluggable = 1;
1842 disk.readwrite = 0;
1843 disk.is_cdrom = 1;
1845 libxl_cdrom_insert(&ctx, domid, &disk);
1848 int main_cd_eject(int argc, char **argv)
1850 int opt = 0;
1851 const char *p = NULL, *virtdev;
1853 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1854 switch (opt) {
1855 case 'h':
1856 help("cd-eject");
1857 return 0;
1858 default:
1859 fprintf(stderr, "option not supported\n");
1860 break;
1863 if (optind >= argc - 1) {
1864 help("cd-eject");
1865 return 2;
1868 p = argv[optind];
1869 virtdev = argv[optind + 1];
1871 cd_insert(p, virtdev, NULL);
1872 return 0;
1875 int main_cd_insert(int argc, char **argv)
1877 int opt = 0;
1878 const char *p = NULL, *virtdev;
1879 char *file = NULL; /* modified by cd_insert tokenising it */
1881 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1882 switch (opt) {
1883 case 'h':
1884 help("cd-insert");
1885 return 0;
1886 default:
1887 fprintf(stderr, "option not supported\n");
1888 break;
1891 if (optind >= argc - 2) {
1892 help("cd-insert");
1893 return 2;
1896 p = argv[optind];
1897 virtdev = argv[optind + 1];
1898 file = argv[optind + 2];
1900 cd_insert(p, virtdev, file);
1901 return 0;
1904 int main_console(int argc, char **argv)
1906 int opt = 0, num = 0;
1907 libxl_console_constype type = 0;
1909 while ((opt = getopt(argc, argv, "hn:t:")) != -1) {
1910 switch (opt) {
1911 case 'h':
1912 help("console");
1913 return 0;
1914 case 't':
1915 if (!strcmp(optarg, "pv"))
1916 type = LIBXL_CONSTYPE_PV;
1917 else if (!strcmp(optarg, "serial"))
1918 type = LIBXL_CONSTYPE_SERIAL;
1919 else {
1920 fprintf(stderr, "console type supported are: pv, serial\n");
1921 return 2;
1923 break;
1924 case 'n':
1925 num = atoi(optarg);
1926 break;
1927 default:
1928 fprintf(stderr, "option not supported\n");
1929 break;
1932 if (optind >= argc) {
1933 help("console");
1934 return 2;
1937 find_domain(argv[optind]);
1938 if (!type)
1939 libxl_primary_console_exec(&ctx, domid);
1940 else
1941 libxl_console_exec(&ctx, domid, num, type);
1942 fprintf(stderr, "Unable to attach console\n");
1943 return 1;
1946 static int vncviewer(const char *domain_spec, int autopass)
1948 find_domain(domain_spec);
1949 libxl_vncviewer_exec(&ctx, domid, autopass);
1950 fprintf(stderr, "Unable to execute vncviewer\n");
1951 return 1;
1954 int main_vncviewer(int argc, char **argv)
1956 static const struct option long_options[] = {
1957 {"autopass", 0, 0, 'a'},
1958 {"vncviewer-autopass", 0, 0, 'a'},
1959 {"help", 0, 0, 'h'},
1960 {0, 0, 0, 0}
1961 };
1962 int opt, autopass = 0;
1964 while (1) {
1965 opt = getopt_long(argc, argv, "ah", long_options, NULL);
1966 if (opt == -1)
1967 break;
1969 switch (opt) {
1970 case 'a':
1971 autopass = 1;
1972 break;
1973 case 'h':
1974 help("vncviewer");
1975 return 0;
1976 default:
1977 fprintf(stderr, "option not supported\n");
1978 break;
1982 if (argc - optind != 1) {
1983 help("vncviewer");
1984 return 2;
1987 if (vncviewer(argv[optind], autopass))
1988 return 1;
1989 return 0;
1992 static void pcilist_assignable(void)
1994 libxl_device_pci *pcidevs;
1995 int num, i;
1997 if ( libxl_device_pci_list_assignable(&ctx, &pcidevs, &num) )
1998 return;
1999 for (i = 0; i < num; i++) {
2000 printf("%04x:%02x:%02x.%01x\n",
2001 pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
2003 free(pcidevs);
2006 int main_pcilist_assignable(int argc, char **argv)
2008 int opt;
2010 while ((opt = getopt(argc, argv, "h")) != -1) {
2011 switch (opt) {
2012 case 'h':
2013 help("pci-list-assignable-devices");
2014 return 0;
2015 default:
2016 fprintf(stderr, "option not supported\n");
2017 break;
2021 pcilist_assignable();
2022 return 0;
2025 static void pcilist(const char *dom)
2027 libxl_device_pci *pcidevs;
2028 int num, i;
2030 find_domain(dom);
2032 if (libxl_device_pci_list_assigned(&ctx, &pcidevs, domid, &num))
2033 return;
2034 printf("VFn domain bus slot func\n");
2035 for (i = 0; i < num; i++) {
2036 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);
2037 libxl_device_pci_destroy(&pcidevs[i]);
2039 free(pcidevs);
2042 int main_pcilist(int argc, char **argv)
2044 int opt;
2045 const char *domname = NULL;
2047 while ((opt = getopt(argc, argv, "h")) != -1) {
2048 switch (opt) {
2049 case 'h':
2050 help("pci-list");
2051 return 0;
2052 default:
2053 fprintf(stderr, "option not supported\n");
2054 break;
2057 if (optind >= argc) {
2058 help("pci-list");
2059 return 2;
2062 domname = argv[optind];
2064 pcilist(domname);
2065 return 0;
2068 static void pcidetach(const char *dom, const char *bdf, int force)
2070 libxl_device_pci pcidev;
2072 find_domain(dom);
2074 memset(&pcidev, 0x00, sizeof(pcidev));
2075 if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
2076 fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
2077 exit(2);
2079 libxl_device_pci_remove(&ctx, domid, &pcidev, force);
2080 libxl_device_pci_destroy(&pcidev);
2083 int main_pcidetach(int argc, char **argv)
2085 int opt;
2086 int force = 0;
2087 const char *domname = NULL, *bdf = NULL;
2089 while ((opt = getopt(argc, argv, "hf")) != -1) {
2090 switch (opt) {
2091 case 'h':
2092 help("pci-detach");
2093 return 0;
2094 case 'f':
2095 force = 1;
2096 break;
2097 default:
2098 fprintf(stderr, "option not supported\n");
2099 break;
2102 if (optind >= argc - 1) {
2103 help("pci-detach");
2104 return 2;
2107 domname = argv[optind];
2108 bdf = argv[optind + 1];
2110 pcidetach(domname, bdf, force);
2111 return 0;
2113 static void pciattach(const char *dom, const char *bdf, const char *vs)
2115 libxl_device_pci pcidev;
2117 find_domain(dom);
2119 memset(&pcidev, 0x00, sizeof(pcidev));
2120 if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
2121 fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
2122 exit(2);
2124 libxl_device_pci_add(&ctx, domid, &pcidev);
2125 libxl_device_pci_destroy(&pcidev);
2128 int main_pciattach(int argc, char **argv)
2130 int opt;
2131 const char *domname = NULL, *bdf = NULL, *vs = NULL;
2133 while ((opt = getopt(argc, argv, "h")) != -1) {
2134 switch (opt) {
2135 case 'h':
2136 help("pci-attach");
2137 return 0;
2138 default:
2139 fprintf(stderr, "option not supported\n");
2140 break;
2143 if (optind >= argc - 1) {
2144 help("pci-attach");
2145 return 2;
2148 domname = argv[optind];
2149 bdf = argv[optind + 1];
2151 if (optind + 1 < argc)
2152 vs = argv[optind + 2];
2154 pciattach(domname, bdf, vs);
2155 return 0;
2158 static void pause_domain(const char *p)
2160 find_domain(p);
2161 libxl_domain_pause(&ctx, domid);
2164 static void unpause_domain(const char *p)
2166 find_domain(p);
2167 libxl_domain_unpause(&ctx, domid);
2170 static void destroy_domain(const char *p)
2172 int rc;
2173 find_domain(p);
2174 if (domid == 0) {
2175 fprintf(stderr, "Cannot destroy privileged domain 0.\n\n");
2176 exit(-1);
2178 rc = libxl_domain_destroy(&ctx, domid, 0);
2179 if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n.",rc); exit(-1); }
2182 static void shutdown_domain(const char *p, int wait)
2184 int rc;
2186 find_domain(p);
2187 rc=libxl_domain_shutdown(&ctx, domid, 0);
2188 if (rc) { fprintf(stderr,"shutdown failed (rc=%d)\n.",rc);exit(-1); }
2190 if (wait) {
2191 libxl_waiter waiter;
2192 int fd;
2194 libxl_wait_for_domain_death(&ctx, domid, &waiter);
2196 libxl_get_wait_fd(&ctx, &fd);
2198 while (wait) {
2199 fd_set rfds;
2200 libxl_event event;
2201 libxl_dominfo info;
2203 FD_ZERO(&rfds);
2204 FD_SET(fd, &rfds);
2206 if (!select(fd + 1, &rfds, NULL, NULL, NULL))
2207 continue;
2209 libxl_get_event(&ctx, &event);
2211 if (event.type == LIBXL_EVENT_DOMAIN_DEATH) {
2212 if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info) < 0)
2213 continue;
2215 LOG("Domain %d is dead", domid);
2216 wait = 0;
2219 libxl_free_event(&event);
2221 libxl_free_waiter(&waiter);
2225 static void reboot_domain(const char *p)
2227 int rc;
2228 find_domain(p);
2229 rc=libxl_domain_shutdown(&ctx, domid, 1);
2230 if (rc) { fprintf(stderr,"reboot failed (rc=%d)\n.",rc);exit(-1); }
2233 static void list_domains_details(const libxl_dominfo *info, int nb_domain)
2235 libxl_domain_config d_config;
2237 char *config_file;
2238 uint8_t *data;
2239 int i, len, rc;
2240 libxl_device_model_info dm_info;
2242 for (i = 0; i < nb_domain; i++) {
2243 /* no detailed info available on dom0 */
2244 if (info[i].domid == 0)
2245 continue;
2246 rc = libxl_userdata_retrieve(&ctx, info[i].domid, "xl", &data, &len);
2247 if (rc)
2248 continue;
2249 CHK_ERRNO(asprintf(&config_file, "<domid %d data>", info[i].domid));
2250 memset(&d_config, 0x00, sizeof(d_config));
2251 parse_config_data(config_file, (char *)data, len, &d_config, &dm_info);
2252 printf_info(info[i].domid, &d_config, &dm_info);
2253 libxl_domain_config_destroy(&d_config);
2254 free(data);
2255 free(config_file);
2259 static void list_domains(int verbose, const libxl_dominfo *info, int nb_domain)
2261 int i;
2262 static const char shutdown_reason_letters[]= "-rscw";
2264 printf("Name ID Mem VCPUs\tState\tTime(s)");
2265 if (verbose) printf(" UUID Reason-Code");
2266 printf("\n");
2267 for (i = 0; i < nb_domain; i++) {
2268 char *domname;
2269 unsigned shutdown_reason;
2270 domname = libxl_domid_to_name(&ctx, info[i].domid);
2271 shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
2272 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f",
2273 domname,
2274 info[i].domid,
2275 (unsigned long) (info[i].current_memkb / 1024),
2276 info[i].vcpu_online,
2277 info[i].running ? 'r' : '-',
2278 info[i].blocked ? 'b' : '-',
2279 info[i].paused ? 'p' : '-',
2280 info[i].shutdown ? 's' : '-',
2281 (shutdown_reason >= 0 &&
2282 shutdown_reason < sizeof(shutdown_reason_letters)-1
2283 ? shutdown_reason_letters[shutdown_reason] : '?'),
2284 info[i].dying ? 'd' : '-',
2285 ((float)info[i].cpu_time / 1e9));
2286 free(domname);
2287 if (verbose) {
2288 printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
2289 if (info[i].shutdown) printf(" %8x", shutdown_reason);
2290 else printf(" %8s", "-");
2292 putchar('\n');
2296 static void list_vm(void)
2298 libxl_vminfo *info;
2299 char *domname;
2300 int nb_vm, i;
2302 info = libxl_list_vm(&ctx, &nb_vm);
2304 if (info < 0) {
2305 fprintf(stderr, "libxl_domain_infolist failed.\n");
2306 exit(1);
2308 printf("UUID ID name\n");
2309 for (i = 0; i < nb_vm; i++) {
2310 domname = libxl_domid_to_name(&ctx, info[i].domid);
2311 printf(LIBXL_UUID_FMT " %d %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
2312 info[i].domid, domname);
2313 free(domname);
2315 free(info);
2318 static void save_domain_core_begin(const char *domain_spec,
2319 const char *override_config_file,
2320 uint8_t **config_data_r,
2321 int *config_len_r)
2323 int rc;
2325 find_domain(domain_spec);
2327 /* configuration file in optional data: */
2329 if (override_config_file) {
2330 void *config_v = 0;
2331 rc = libxl_read_file_contents(&ctx, override_config_file,
2332 &config_v, config_len_r);
2333 *config_data_r = config_v;
2334 } else {
2335 rc = libxl_userdata_retrieve(&ctx, domid, "xl",
2336 config_data_r, config_len_r);
2338 if (rc) {
2339 fputs("Unable to get config file\n",stderr);
2340 exit(2);
2344 static void save_domain_core_writeconfig(int fd, const char *filename,
2345 const uint8_t *config_data, int config_len)
2347 struct save_file_header hdr;
2348 uint8_t *optdata_begin;
2349 union { uint32_t u32; char b[4]; } u32buf;
2351 memset(&hdr, 0, sizeof(hdr));
2352 memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
2353 hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
2355 optdata_begin= 0;
2357 #define ADD_OPTDATA(ptr, len) ({ \
2358 if ((len)) { \
2359 hdr.optional_data_len += (len); \
2360 optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
2361 memcpy(optdata_begin + hdr.optional_data_len - (len), \
2362 (ptr), (len)); \
2363 } \
2364 })
2366 u32buf.u32 = config_len;
2367 ADD_OPTDATA(u32buf.b, 4);
2368 ADD_OPTDATA(config_data, config_len);
2370 /* that's the optional data */
2372 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2373 &hdr, sizeof(hdr), filename, "header") );
2374 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2375 optdata_begin, hdr.optional_data_len, filename, "header") );
2377 fprintf(stderr, "Saving to %s new xl format (info"
2378 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
2379 filename, hdr.mandatory_flags, hdr.optional_flags,
2380 hdr.optional_data_len);
2383 static int save_domain(const char *p, const char *filename, int checkpoint,
2384 const char *override_config_file)
2386 int fd;
2387 uint8_t *config_data;
2388 int config_len;
2390 save_domain_core_begin(p, override_config_file, &config_data, &config_len);
2392 if (!config_len) {
2393 fputs(" Savefile will not contain xl domain config\n", stderr);
2396 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
2397 if (fd < 0) {
2398 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
2399 exit(2);
2402 save_domain_core_writeconfig(fd, filename, config_data, config_len);
2404 CHK_ERRNO(libxl_domain_suspend(&ctx, NULL, domid, fd));
2405 close(fd);
2407 if (checkpoint)
2408 libxl_domain_unpause(&ctx, domid);
2409 else
2410 libxl_domain_destroy(&ctx, domid, 0);
2412 exit(0);
2415 static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
2416 const char *what, const char *rune) {
2417 char buf[msgsz];
2418 const char *stream;
2419 int rc;
2421 stream = rune ? "migration receiver stream" : "migration stream";
2422 rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
2423 if (rc) return ERROR_FAIL;
2425 if (memcmp(buf, msg, msgsz)) {
2426 fprintf(stderr, "%s contained unexpected data instead of %s\n",
2427 stream, what);
2428 if (rune)
2429 fprintf(stderr, "(command run was: %s )\n", rune);
2430 return ERROR_FAIL;
2432 return 0;
2435 static void migration_child_report(pid_t migration_child, int recv_fd) {
2436 pid_t child;
2437 int status, sr;
2438 struct timeval now, waituntil, timeout;
2439 static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
2441 if (!migration_child) return;
2443 CHK_ERRNO( gettimeofday(&waituntil, 0) );
2444 waituntil.tv_sec += 2;
2446 for (;;) {
2447 child = waitpid(migration_child, &status, WNOHANG);
2449 if (child == migration_child) {
2450 if (status)
2451 libxl_report_child_exitstatus(&ctx, XTL_INFO,
2452 "migration target process",
2453 migration_child, status);
2454 break;
2456 if (child == -1) {
2457 if (errno == EINTR) continue;
2458 fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
2459 (long)migration_child, strerror(errno));
2460 break;
2462 assert(child == 0);
2464 CHK_ERRNO( gettimeofday(&now, 0) );
2465 if (timercmp(&now, &waituntil, >)) {
2466 fprintf(stderr, "migration child [%ld] not exiting, no longer"
2467 " waiting (exit status will be unreported)\n",
2468 (long)migration_child);
2469 break;
2471 timersub(&waituntil, &now, &timeout);
2473 if (recv_fd >= 0) {
2474 fd_set readfds, exceptfds;
2475 FD_ZERO(&readfds);
2476 FD_ZERO(&exceptfds);
2477 FD_SET(recv_fd, &readfds);
2478 FD_SET(recv_fd, &exceptfds);
2479 sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
2480 } else {
2481 if (timercmp(&timeout, &pollinterval, >))
2482 timeout = pollinterval;
2483 sr = select(0,0,0,0, &timeout);
2485 if (sr > 0) {
2486 recv_fd = -1;
2487 } else if (sr == 0) {
2488 } else if (sr == -1) {
2489 if (errno != EINTR) {
2490 fprintf(stderr, "migration child [%ld] exit wait select"
2491 " failed unexpectedly: %s\n",
2492 (long)migration_child, strerror(errno));
2493 break;
2497 migration_child = 0;
2500 static void migrate_domain(const char *domain_spec, const char *rune,
2501 const char *override_config_file)
2503 pid_t child = -1;
2504 int rc;
2505 int sendpipe[2], recvpipe[2];
2506 int send_fd, recv_fd;
2507 libxl_domain_suspend_info suspinfo;
2508 char *away_domname;
2509 char rc_buf;
2510 uint8_t *config_data;
2511 int config_len;
2513 save_domain_core_begin(domain_spec, override_config_file,
2514 &config_data, &config_len);
2516 if (!config_len) {
2517 fprintf(stderr, "No config file stored for running domain and "
2518 "none supplied - cannot migrate.\n");
2519 exit(1);
2522 MUST( libxl_pipe(&ctx, sendpipe) );
2523 MUST( libxl_pipe(&ctx, recvpipe) );
2525 child = libxl_fork(&ctx);
2526 if (child==-1) exit(1);
2528 if (!child) {
2529 dup2(sendpipe[0], 0);
2530 dup2(recvpipe[1], 1);
2531 close(sendpipe[0]); close(sendpipe[1]);
2532 close(recvpipe[0]); close(recvpipe[1]);
2533 execlp("sh","sh","-c",rune,(char*)0);
2534 perror("failed to exec sh");
2535 exit(-1);
2538 close(sendpipe[0]);
2539 close(recvpipe[1]);
2540 send_fd = sendpipe[1];
2541 recv_fd = recvpipe[0];
2543 signal(SIGPIPE, SIG_IGN);
2544 /* if receiver dies, we get an error and can clean up
2545 rather than just dying */
2547 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
2548 sizeof(migrate_receiver_banner)-1,
2549 "banner", rune);
2550 if (rc) {
2551 close(send_fd);
2552 migration_child_report(child, recv_fd);
2553 exit(-rc);
2556 save_domain_core_writeconfig(send_fd, "migration stream",
2557 config_data, config_len);
2559 xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
2561 memset(&suspinfo, 0, sizeof(suspinfo));
2562 suspinfo.flags |= XL_SUSPEND_LIVE;
2563 rc = libxl_domain_suspend(&ctx, &suspinfo, domid, send_fd);
2564 if (rc) {
2565 fprintf(stderr, "migration sender: libxl_domain_suspend failed"
2566 " (rc=%d)\n", rc);
2567 goto failed_resume;
2570 //fprintf(stderr, "migration sender: Transfer complete.\n");
2571 // Should only be printed when debugging as it's a bit messy with
2572 // progress indication.
2574 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
2575 sizeof(migrate_receiver_ready),
2576 "ready message", rune);
2577 if (rc) goto failed_resume;
2579 xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
2581 /* right, at this point we are about give the destination
2582 * permission to rename and resume, so we must first rename the
2583 * domain away ourselves */
2585 fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
2587 if (common_domname) {
2588 if (asprintf(&away_domname, "%s--migratedaway", common_domname) < 0)
2589 goto failed_resume;
2590 rc = libxl_domain_rename(&ctx, domid,
2591 common_domname, away_domname, 0);
2592 if (rc) goto failed_resume;
2595 /* point of no return - as soon as we have tried to say
2596 * "go" to the receiver, it's not safe to carry on. We leave
2597 * the domain renamed to %s--migratedaway in case that's helpful.
2598 */
2600 fprintf(stderr, "migration sender: Giving target permission to start.\n");
2602 rc = libxl_write_exactly(&ctx, send_fd,
2603 migrate_permission_to_go,
2604 sizeof(migrate_permission_to_go),
2605 "migration stream", "GO message");
2606 if (rc) goto failed_badly;
2608 rc = migrate_read_fixedmessage(recv_fd, migrate_report,
2609 sizeof(migrate_report),
2610 "success/failure report message", rune);
2611 if (rc) goto failed_badly;
2613 rc = libxl_read_exactly(&ctx, recv_fd,
2614 &rc_buf, 1,
2615 "migration ack stream", "success/failure status");
2616 if (rc) goto failed_badly;
2618 if (rc_buf) {
2619 fprintf(stderr, "migration sender: Target reports startup failure"
2620 " (status code %d).\n", rc_buf);
2622 rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
2623 sizeof(migrate_permission_to_go),
2624 "permission for sender to resume",
2625 rune);
2626 if (rc) goto failed_badly;
2628 fprintf(stderr, "migration sender: Trying to resume at our end.\n");
2630 if (common_domname) {
2631 libxl_domain_rename(&ctx, domid,
2632 away_domname, common_domname, 0);
2634 rc = libxl_domain_resume(&ctx, domid);
2635 if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
2637 fprintf(stderr, "Migration failed due to problems at target.\n");
2638 exit(-ERROR_FAIL);
2641 fprintf(stderr, "migration sender: Target reports successful startup.\n");
2642 libxl_domain_destroy(&ctx, domid, 1); /* bang! */
2643 fprintf(stderr, "Migration successful.\n");
2644 exit(0);
2646 failed_resume:
2647 close(send_fd);
2648 migration_child_report(child, recv_fd);
2649 fprintf(stderr, "Migration failed, resuming at sender.\n");
2650 libxl_domain_resume(&ctx, domid);
2651 exit(-ERROR_FAIL);
2653 failed_badly:
2654 fprintf(stderr,
2655 "** Migration failed during final handshake **\n"
2656 "Domain state is now undefined !\n"
2657 "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
2658 " resuming at most one instance. Two simultaneous instances of the domain\n"
2659 " would probably result in SEVERE DATA LOSS and it is now your\n"
2660 " responsibility to avoid that. Sorry.\n");
2662 close(send_fd);
2663 migration_child_report(child, recv_fd);
2664 exit(-ERROR_BADFAIL);
2667 static void core_dump_domain(const char *domain_spec, const char *filename)
2669 int rc;
2670 find_domain(domain_spec);
2671 rc=libxl_domain_core_dump(&ctx, domid, filename);
2672 if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n.",rc);exit(-1); }
2675 static void migrate_receive(int debug, int daemonize)
2677 int rc, rc2;
2678 char rc_buf;
2679 char *migration_domname;
2680 struct domain_create dom_info;
2682 signal(SIGPIPE, SIG_IGN);
2683 /* if we get SIGPIPE we'd rather just have it as an error */
2685 fprintf(stderr, "migration target: Ready to receive domain.\n");
2687 CHK_ERRNO( libxl_write_exactly(&ctx, 1,
2688 migrate_receiver_banner,
2689 sizeof(migrate_receiver_banner)-1,
2690 "migration ack stream",
2691 "banner") );
2693 memset(&dom_info, 0, sizeof(dom_info));
2694 dom_info.debug = debug;
2695 dom_info.daemonize = daemonize;
2696 dom_info.paused = 1;
2697 dom_info.restore_file = "incoming migration stream";
2698 dom_info.migrate_fd = 0; /* stdin */
2699 dom_info.migration_domname_r = &migration_domname;
2701 rc = create_domain(&dom_info);
2702 if (rc < 0) {
2703 fprintf(stderr, "migration target: Domain creation failed"
2704 " (code %d).\n", rc);
2705 exit(-rc);
2708 fprintf(stderr, "migration target: Transfer complete,"
2709 " requesting permission to start domain.\n");
2711 rc = libxl_write_exactly(&ctx, 1,
2712 migrate_receiver_ready,
2713 sizeof(migrate_receiver_ready),
2714 "migration ack stream", "ready message");
2715 if (rc) exit(-rc);
2717 rc = migrate_read_fixedmessage(0, migrate_permission_to_go,
2718 sizeof(migrate_permission_to_go),
2719 "GO message", 0);
2720 if (rc) goto perhaps_destroy_notify_rc;
2722 fprintf(stderr, "migration target: Got permission, starting domain.\n");
2724 if (migration_domname) {
2725 rc = libxl_domain_rename(&ctx, domid,
2726 migration_domname, common_domname, 0);
2727 if (rc) goto perhaps_destroy_notify_rc;
2730 rc = libxl_domain_unpause(&ctx, domid);
2731 if (rc) goto perhaps_destroy_notify_rc;
2733 fprintf(stderr, "migration target: Domain started successsfully.\n");
2734 rc = 0;
2736 perhaps_destroy_notify_rc:
2737 rc2 = libxl_write_exactly(&ctx, 1,
2738 migrate_report, sizeof(migrate_report),
2739 "migration ack stream",
2740 "success/failure report");
2741 if (rc2) exit(-ERROR_BADFAIL);
2743 rc_buf = -rc;
2744 assert(!!rc_buf == !!rc);
2745 rc2 = libxl_write_exactly(&ctx, 1, &rc_buf, 1,
2746 "migration ack stream",
2747 "success/failure code");
2748 if (rc2) exit(-ERROR_BADFAIL);
2750 if (rc) {
2751 fprintf(stderr, "migration target: Failure, destroying our copy.\n");
2753 rc2 = libxl_domain_destroy(&ctx, domid, 1);
2754 if (rc2) {
2755 fprintf(stderr, "migration target: Failed to destroy our copy"
2756 " (code %d).\n", rc2);
2757 exit(-ERROR_BADFAIL);
2760 fprintf(stderr, "migration target: Cleanup OK, granting sender"
2761 " permission to resume.\n");
2763 rc2 = libxl_write_exactly(&ctx, 1,
2764 migrate_permission_to_go,
2765 sizeof(migrate_permission_to_go),
2766 "migration ack stream",
2767 "permission to sender to have domain back");
2768 if (rc2) exit(-ERROR_BADFAIL);
2771 exit(0);
2774 int main_restore(int argc, char **argv)
2776 const char *checkpoint_file = NULL;
2777 const char *config_file = NULL;
2778 struct domain_create dom_info;
2779 int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0;
2780 int opt, rc;
2782 while ((opt = getopt(argc, argv, "chpde")) != -1) {
2783 switch (opt) {
2784 case 'c':
2785 console_autoconnect = 1;
2786 break;
2787 case 'p':
2788 paused = 1;
2789 break;
2790 case 'd':
2791 debug = 1;
2792 break;
2793 case 'e':
2794 daemonize = 0;
2795 break;
2796 case 'h':
2797 help("restore");
2798 return 0;
2799 default:
2800 fprintf(stderr, "option not supported\n");
2801 break;
2805 if (argc-optind == 1) {
2806 checkpoint_file = argv[optind];
2807 } else if (argc-optind == 2) {
2808 config_file = argv[optind];
2809 checkpoint_file = argv[optind + 1];
2810 } else {
2811 help("restore");
2812 return 2;
2815 memset(&dom_info, 0, sizeof(dom_info));
2816 dom_info.debug = debug;
2817 dom_info.daemonize = daemonize;
2818 dom_info.paused = paused;
2819 dom_info.config_file = config_file;
2820 dom_info.restore_file = checkpoint_file;
2821 dom_info.migrate_fd = -1;
2822 dom_info.console_autoconnect = console_autoconnect;
2824 rc = create_domain(&dom_info);
2825 if (rc < 0)
2826 return -rc;
2828 return 0;
2831 int main_migrate_receive(int argc, char **argv)
2833 int debug = 0, daemonize = 1;
2834 int opt;
2836 while ((opt = getopt(argc, argv, "hed")) != -1) {
2837 switch (opt) {
2838 case 'h':
2839 help("migrate-receive");
2840 return 2;
2841 break;
2842 case 'e':
2843 daemonize = 0;
2844 break;
2845 case 'd':
2846 debug = 1;
2847 break;
2848 default:
2849 fprintf(stderr, "option not supported\n");
2850 break;
2854 if (argc-optind != 0) {
2855 help("migrate-receive");
2856 return 2;
2858 migrate_receive(debug, daemonize);
2859 return 0;
2862 int main_save(int argc, char **argv)
2864 const char *filename = NULL, *p = NULL;
2865 const char *config_filename;
2866 int checkpoint = 0;
2867 int opt;
2869 while ((opt = getopt(argc, argv, "hc")) != -1) {
2870 switch (opt) {
2871 case 'c':
2872 checkpoint = 1;
2873 break;
2874 case 'h':
2875 help("save");
2876 return 0;
2877 default:
2878 fprintf(stderr, "option not supported\n");
2879 break;
2883 if (argc-optind < 1 || argc-optind > 3) {
2884 help("save");
2885 return 2;
2888 p = argv[optind];
2889 filename = argv[optind + 1];
2890 config_filename = argv[optind + 2];
2891 save_domain(p, filename, checkpoint, config_filename);
2892 return 0;
2895 int main_migrate(int argc, char **argv)
2897 const char *p = NULL;
2898 const char *config_filename = NULL;
2899 const char *ssh_command = "ssh";
2900 char *rune = NULL;
2901 char *host;
2902 int opt, daemonize = 1, debug = 0;
2904 while ((opt = getopt(argc, argv, "hC:s:ed")) != -1) {
2905 switch (opt) {
2906 case 'h':
2907 help("migrate");
2908 return 0;
2909 case 'C':
2910 config_filename = optarg;
2911 break;
2912 case 's':
2913 ssh_command = optarg;
2914 break;
2915 case 'e':
2916 daemonize = 0;
2917 break;
2918 case 'd':
2919 debug = 1;
2920 break;
2921 default:
2922 fprintf(stderr, "option not supported\n");
2923 break;
2927 if (argc-optind < 2 || argc-optind > 2) {
2928 help("migrate");
2929 return 2;
2932 p = argv[optind];
2933 host = argv[optind + 1];
2935 if (!ssh_command[0]) {
2936 rune= host;
2937 } else {
2938 if (asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
2939 ssh_command, host,
2940 daemonize ? "" : " -e",
2941 debug ? " -d" : "") < 0)
2942 return 1;
2945 migrate_domain(p, rune, config_filename);
2946 return 0;
2949 int main_dump_core(int argc, char **argv)
2951 int opt;
2952 while ((opt = getopt(argc, argv, "h")) != -1) {
2953 switch (opt) {
2954 case 'h':
2955 help("dump-core");
2956 return 0;
2957 default:
2958 fprintf(stderr, "option `%c' not supported.\n", opt);
2959 break;
2962 if ( argc-optind < 2 ) {
2963 help("dump-core");
2964 return 2;
2966 core_dump_domain(argv[optind], argv[optind + 1]);
2967 return 0;
2970 int main_pause(int argc, char **argv)
2972 int opt;
2973 const char *p;
2976 while ((opt = getopt(argc, argv, "h")) != -1) {
2977 switch (opt) {
2978 case 'h':
2979 help("pause");
2980 return 0;
2981 default:
2982 fprintf(stderr, "option not supported\n");
2983 break;
2986 if (optind >= argc) {
2987 help("pause");
2988 return 2;
2991 p = argv[optind];
2993 pause_domain(p);
2994 return 0;
2997 int main_unpause(int argc, char **argv)
2999 int opt;
3000 const char *p;
3003 while ((opt = getopt(argc, argv, "h")) != -1) {
3004 switch (opt) {
3005 case 'h':
3006 help("unpause");
3007 return 0;
3008 default:
3009 fprintf(stderr, "option not supported\n");
3010 break;
3013 if (optind >= argc) {
3014 help("unpause");
3015 return 2;
3018 p = argv[optind];
3020 unpause_domain(p);
3021 return 0;
3024 int main_destroy(int argc, char **argv)
3026 int opt;
3027 const char *p;
3029 while ((opt = getopt(argc, argv, "h")) != -1) {
3030 switch (opt) {
3031 case 'h':
3032 help("destroy");
3033 return 0;
3034 default:
3035 fprintf(stderr, "option not supported\n");
3036 break;
3039 if (optind >= argc) {
3040 help("destroy");
3041 return 2;
3044 p = argv[optind];
3046 destroy_domain(p);
3047 return 0;
3050 int main_shutdown(int argc, char **argv)
3052 int opt;
3053 int wait = 0;
3054 const char *p;
3056 while ((opt = getopt(argc, argv, "hw")) != -1) {
3057 switch (opt) {
3058 case 'h':
3059 help("shutdown");
3060 return 0;
3061 case 'w':
3062 wait = 1;
3063 break;
3064 default:
3065 fprintf(stderr, "option not supported\n");
3066 break;
3069 if (optind >= argc) {
3070 help("shutdown");
3071 return 2;
3074 p = argv[optind];
3076 shutdown_domain(p, wait);
3077 return 0;
3080 int main_reboot(int argc, char **argv)
3082 int opt;
3083 const char *p;
3085 while ((opt = getopt(argc, argv, "h")) != -1) {
3086 switch (opt) {
3087 case 'h':
3088 help("reboot");
3089 return 0;
3090 default:
3091 fprintf(stderr, "option not supported\n");
3092 break;
3095 if (optind >= argc) {
3096 help("reboot");
3097 return 2;
3100 p = argv[optind];
3102 reboot_domain(p);
3103 return 0;
3105 int main_list(int argc, char **argv)
3107 int opt, verbose = 0;
3108 int details = 0;
3109 int option_index = 0;
3110 static struct option long_options[] = {
3111 {"long", 0, 0, 'l'},
3112 {"help", 0, 0, 'h'},
3113 {"verbose", 0, 0, 'v'},
3114 {0, 0, 0, 0}
3115 };
3117 libxl_dominfo info_buf;
3118 libxl_dominfo *info, *info_free=0;
3119 int nb_domain, rc;
3121 while (1) {
3122 opt = getopt_long(argc, argv, "lvh", long_options, &option_index);
3123 if (opt == -1)
3124 break;
3126 switch (opt) {
3127 case 'l':
3128 details = 1;
3129 break;
3130 case 'h':
3131 help("list");
3132 return 0;
3133 case 'v':
3134 verbose = 1;
3135 break;
3136 default:
3137 fprintf(stderr, "option not supported\n");
3138 break;
3142 if (optind >= argc) {
3143 info = libxl_list_domain(&ctx, &nb_domain);
3144 if (!info) {
3145 fprintf(stderr, "libxl_domain_infolist failed.\n");
3146 return 1;
3148 info_free = info;
3149 } else if (optind == argc-1) {
3150 find_domain(argv[optind]);
3151 rc = libxl_domain_info(&ctx, &info_buf, domid);
3152 if (rc == ERROR_INVAL) {
3153 fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
3154 argv[optind]);
3155 return -rc;
3157 if (rc) {
3158 fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
3159 return -rc;
3161 info = &info_buf;
3162 nb_domain = 1;
3163 } else {
3164 help("list");
3165 return 2;
3168 if (details)
3169 list_domains_details(info, nb_domain);
3170 else
3171 list_domains(verbose, info, nb_domain);
3173 free(info_free);
3175 return 0;
3178 int main_list_vm(int argc, char **argv)
3180 int opt;
3182 while ((opt = getopt(argc, argv, "h")) != -1) {
3183 switch (opt) {
3184 case 'h':
3185 help("list-vm");
3186 return 0;
3187 default:
3188 fprintf(stderr, "option not supported\n");
3189 break;
3193 list_vm();
3194 return 0;
3197 int main_create(int argc, char **argv)
3199 const char *filename = NULL;
3200 char *p;
3201 char extra_config[1024];
3202 struct domain_create dom_info;
3203 int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
3204 dryrun = 0, quiet = 0;
3205 int opt, rc;
3206 int option_index = 0;
3207 static struct option long_options[] = {
3208 {"dryrun", 0, 0, 'n'},
3209 {"quiet", 0, 0, 'q'},
3210 {"help", 0, 0, 'h'},
3211 {"defconfig", 1, 0, 'f'},
3212 {0, 0, 0, 0}
3213 };
3215 while (1) {
3216 opt = getopt_long(argc, argv, "hnqf:pcde", long_options, &option_index);
3217 if (opt == -1)
3218 break;
3220 switch (opt) {
3221 case 'f':
3222 filename = optarg;
3223 break;
3224 case 'p':
3225 paused = 1;
3226 break;
3227 case 'c':
3228 console_autoconnect = 1;
3229 break;
3230 case 'd':
3231 debug = 1;
3232 break;
3233 case 'e':
3234 daemonize = 0;
3235 break;
3236 case 'h':
3237 help("create");
3238 return 0;
3239 case 'n':
3240 dryrun = 1;
3241 break;
3242 case 'q':
3243 quiet = 1;
3244 break;
3245 default:
3246 fprintf(stderr, "option not supported\n");
3247 break;
3251 extra_config[0] = '\0';
3252 for (p = extra_config; optind < argc; optind++) {
3253 if (strchr(argv[optind], '=') != NULL) {
3254 p += snprintf(p, sizeof(extra_config) - (p - extra_config),
3255 "%s\n", argv[optind]);
3256 } else if (!filename) {
3257 filename = argv[optind];
3258 } else {
3259 help("create");
3260 return 2;
3264 memset(&dom_info, 0, sizeof(dom_info));
3265 dom_info.debug = debug;
3266 dom_info.daemonize = daemonize;
3267 dom_info.paused = paused;
3268 dom_info.dryrun = dryrun;
3269 dom_info.quiet = quiet;
3270 dom_info.config_file = filename;
3271 dom_info.extra_config = extra_config;
3272 dom_info.migrate_fd = -1;
3273 dom_info.console_autoconnect = console_autoconnect;
3275 rc = create_domain(&dom_info);
3276 if (rc < 0)
3277 return -rc;
3279 return 0;
3282 static void button_press(const char *p, const char *b)
3284 libxl_button button;
3286 find_domain(p);
3288 if (!strcmp(b, "power")) {
3289 button = POWER_BUTTON;
3290 } else if (!strcmp(b, "sleep")) {
3291 button = SLEEP_BUTTON;
3292 } else {
3293 fprintf(stderr, "%s is an invalid button identifier\n", b);
3294 exit(2);
3297 libxl_button_press(&ctx, domid, button);
3300 int main_button_press(int argc, char **argv)
3302 int opt;
3303 const char *p;
3304 const char *b;
3306 while ((opt = getopt(argc, argv, "h")) != -1) {
3307 switch (opt) {
3308 case 'h':
3309 help("button-press");
3310 return 0;
3311 default:
3312 fprintf(stderr, "option not supported\n");
3313 break;
3316 if (optind >= argc - 1) {
3317 help("button-press");
3318 return 2;
3321 p = argv[optind];
3322 b = argv[optind + 1];
3324 button_press(p, b);
3325 return 0;
3328 static void print_vcpuinfo(uint32_t tdomid,
3329 const libxl_vcpuinfo *vcpuinfo,
3330 uint32_t nr_cpus)
3332 int i, l;
3333 uint8_t *cpumap;
3334 uint8_t pcpumap;
3335 char *domname;
3337 /* NAME ID VCPU */
3338 domname = libxl_domid_to_name(&ctx, tdomid);
3339 printf("%-32s %5u %5u",
3340 domname, tdomid, vcpuinfo->vcpuid);
3341 free(domname);
3342 if (!vcpuinfo->online) {
3343 /* CPU STA */
3344 printf("%5c %3c%cp ", '-', '-', '-');
3345 } else {
3346 /* CPU STA */
3347 printf("%5u %3c%c- ", vcpuinfo->cpu,
3348 vcpuinfo->running ? 'r' : '-',
3349 vcpuinfo->blocked ? 'b' : '-');
3351 /* TIM */
3352 printf("%9.1f ", ((float)vcpuinfo->vcpu_time / 1e9));
3353 /* CPU AFFINITY */
3354 pcpumap = nr_cpus > 8 ? (uint8_t)-1 : ((1 << nr_cpus) - 1);
3355 for (cpumap = vcpuinfo->cpumap.map; nr_cpus; ++cpumap) {
3356 if (*cpumap < pcpumap) {
3357 break;
3359 if (nr_cpus > 8) {
3360 pcpumap = -1;
3361 nr_cpus -= 8;
3362 } else {
3363 pcpumap = ((1 << nr_cpus) - 1);
3364 nr_cpus = 0;
3367 if (!nr_cpus) {
3368 printf("any cpu\n");
3369 } else {
3370 for (cpumap = vcpuinfo->cpumap.map; nr_cpus; ++cpumap) {
3371 pcpumap = *cpumap;
3372 for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1)
3374 printf("%u", i);
3375 for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
3377 if (l < i) {
3378 printf("-%u", i);
3380 for (++i; pcpumap; ++i, pcpumap >>= 1) {
3381 if (pcpumap & 1) {
3382 printf(",%u", i);
3383 for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
3385 if (l < i) {
3386 printf("-%u", i);
3388 ++i;
3391 printf("\n");
3392 nr_cpus = nr_cpus > 8 ? nr_cpus - 8 : 0;
3397 static void print_domain_vcpuinfo(uint32_t domid, uint32_t nr_cpus)
3399 libxl_vcpuinfo *vcpuinfo;
3400 int i, nb_vcpu, nrcpus;
3402 vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &nrcpus);
3404 if (!vcpuinfo) {
3405 fprintf(stderr, "libxl_list_vcpu failed.\n");
3406 return;
3409 for (i = 0; i < nb_vcpu; i++) {
3410 print_vcpuinfo(domid, &vcpuinfo[i], nr_cpus);
3411 libxl_vcpuinfo_destroy(&vcpuinfo[i]);
3414 free(vcpuinfo);
3417 static void vcpulist(int argc, char **argv)
3419 libxl_dominfo *dominfo;
3420 libxl_physinfo physinfo;
3421 int i, nb_domain;
3423 if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
3424 fprintf(stderr, "libxl_physinfo failed.\n");
3425 goto vcpulist_out;
3428 printf("%-32s %5s %5s %5s %5s %9s %s\n",
3429 "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
3430 if (!argc) {
3431 if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
3432 fprintf(stderr, "libxl_list_domain failed.\n");
3433 goto vcpulist_out;
3436 for (i = 0; i<nb_domain; i++)
3437 print_domain_vcpuinfo(dominfo[i].domid, physinfo.nr_cpus);
3439 free(dominfo);
3441 } else {
3442 for (; argc > 0; ++argv, --argc) {
3443 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
3444 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
3445 goto vcpulist_out;
3448 print_domain_vcpuinfo(domid, physinfo.nr_cpus);
3451 vcpulist_out:
3455 int main_vcpulist(int argc, char **argv)
3457 int opt;
3459 while ((opt = getopt(argc, argv, "h")) != -1) {
3460 switch (opt) {
3461 case 'h':
3462 help("vcpu-list");
3463 return 0;
3464 default:
3465 fprintf(stderr, "option `%c' not supported.\n", opt);
3466 break;
3470 vcpulist(argc - optind, argv + optind);
3471 return 0;
3474 static void vcpupin(const char *d, const char *vcpu, char *cpu)
3476 libxl_vcpuinfo *vcpuinfo;
3477 libxl_cpumap cpumap;
3479 uint32_t vcpuid, cpuida, cpuidb;
3480 char *endptr, *toka, *tokb;
3481 int i, nb_vcpu;
3483 vcpuid = strtoul(vcpu, &endptr, 10);
3484 if (vcpu == endptr) {
3485 if (strcmp(vcpu, "all")) {
3486 fprintf(stderr, "Error: Invalid argument.\n");
3487 return;
3489 vcpuid = -1;
3492 find_domain(d);
3494 if (libxl_cpumap_alloc(&ctx, &cpumap)) {
3495 goto vcpupin_out;
3497 if (strcmp(cpu, "all")) {
3498 for (toka = strtok(cpu, ","), i = 0; toka; toka = strtok(NULL, ","), ++i) {
3499 cpuida = strtoul(toka, &endptr, 10);
3500 if (toka == endptr) {
3501 fprintf(stderr, "Error: Invalid argument.\n");
3502 goto vcpupin_out1;
3504 if (*endptr == '-') {
3505 tokb = endptr + 1;
3506 cpuidb = strtoul(tokb, &endptr, 10);
3507 if ((tokb == endptr) || (cpuida > cpuidb)) {
3508 fprintf(stderr, "Error: Invalid argument.\n");
3509 goto vcpupin_out1;
3511 while (cpuida <= cpuidb) {
3512 libxl_cpumap_set(&cpumap, cpuida);
3513 ++cpuida;
3515 } else {
3516 libxl_cpumap_set(&cpumap, cpuida);
3520 else {
3521 memset(cpumap.map, -1, cpumap.size);
3524 if (vcpuid != -1) {
3525 if (libxl_set_vcpuaffinity(&ctx, domid, vcpuid, &cpumap) == -1) {
3526 fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
3529 else {
3530 if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &i))) {
3531 fprintf(stderr, "libxl_list_vcpu failed.\n");
3532 goto vcpupin_out1;
3534 for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
3535 if (libxl_set_vcpuaffinity(&ctx, domid, vcpuinfo->vcpuid, &cpumap) == -1) {
3536 fprintf(stderr, "libxl_set_vcpuaffinity failed on vcpu `%u'.\n", vcpuinfo->vcpuid);
3540 vcpupin_out1:
3541 libxl_cpumap_destroy(&cpumap);
3542 vcpupin_out:
3546 int main_vcpupin(int argc, char **argv)
3548 int opt;
3550 while ((opt = getopt(argc, argv, "h")) != -1) {
3551 switch (opt) {
3552 case 'h':
3553 help("vcpu-pin");
3554 return 0;
3555 default:
3556 fprintf(stderr, "option `%c' not supported.\n", opt);
3557 break;
3561 if (optind != argc - 3) {
3562 help("vcpu-pin");
3563 return 2;
3566 vcpupin(argv[optind], argv[optind+1] , argv[optind+2]);
3567 return 0;
3570 static void vcpuset(const char *d, const char* nr_vcpus)
3572 char *endptr;
3573 unsigned int max_vcpus, i;
3574 uint32_t bitmask = 0;
3576 max_vcpus = strtoul(nr_vcpus, &endptr, 10);
3577 if (nr_vcpus == endptr) {
3578 fprintf(stderr, "Error: Invalid argument.\n");
3579 return;
3582 find_domain(d);
3584 for (i = 0; i < max_vcpus; i++)
3585 bitmask |= 1 << i;
3587 if (libxl_set_vcpuonline(&ctx, domid, bitmask) < 0)
3588 fprintf(stderr, "libxl_set_vcpuonline failed domid=%d bitmask=%x\n", domid, bitmask);
3591 int main_vcpuset(int argc, char **argv)
3593 int opt;
3595 while ((opt = getopt(argc, argv, "h")) != -1) {
3596 switch (opt) {
3597 case 'h':
3598 help("vcpu-set");
3599 return 0;
3600 default:
3601 fprintf(stderr, "option `%c' not supported.\n", opt);
3602 break;
3606 if (optind >= argc - 1) {
3607 help("vcpu-set");
3608 return 2;
3610 vcpuset(argv[optind], argv[optind+1]);
3611 return 0;
3614 static void output_xeninfo(void)
3616 const libxl_version_info *info;
3617 int sched_id;
3619 if (!(info = libxl_get_version_info(&ctx))) {
3620 fprintf(stderr, "libxl_get_version_info failed.\n");
3621 return;
3624 if ((sched_id = libxl_get_sched_id(&ctx)) < 0) {
3625 fprintf(stderr, "get_sched_id sysctl failed.\n");
3626 return;
3629 printf("xen_major : %d\n", info->xen_version_major);
3630 printf("xen_minor : %d\n", info->xen_version_minor);
3631 printf("xen_extra : %s\n", info->xen_version_extra);
3632 printf("xen_caps : %s\n", info->capabilities);
3633 printf("xen_scheduler : %s\n", libxl_schedid_to_name(&ctx, sched_id));
3634 printf("xen_pagesize : %lu\n", info->pagesize);
3635 printf("platform_params : virt_start=0x%lx\n", info->virt_start);
3636 printf("xen_changeset : %s\n", info->changeset);
3637 printf("xen_commandline : %s\n", info->commandline);
3638 printf("cc_compiler : %s\n", info->compiler);
3639 printf("cc_compile_by : %s\n", info->compile_by);
3640 printf("cc_compile_domain : %s\n", info->compile_domain);
3641 printf("cc_compile_date : %s\n", info->compile_date);
3643 return;
3646 static void output_nodeinfo(void)
3648 struct utsname utsbuf;
3650 if (uname(&utsbuf) < 0)
3651 return;
3653 printf("host : %s\n", utsbuf.nodename);
3654 printf("release : %s\n", utsbuf.release);
3655 printf("version : %s\n", utsbuf.version);
3656 printf("machine : %s\n", utsbuf.machine);
3659 static void output_physinfo(void)
3661 libxl_physinfo info;
3662 const libxl_version_info *vinfo;
3663 unsigned int i;
3664 libxl_cpumap cpumap;
3665 int n = 0;
3667 if (libxl_get_physinfo(&ctx, &info) != 0) {
3668 fprintf(stderr, "libxl_physinfo failed.\n");
3669 return;
3672 printf("nr_cpus : %d\n", info.nr_cpus);
3673 printf("nr_nodes : %d\n", info.nr_nodes);
3674 printf("cores_per_socket : %d\n", info.cores_per_socket);
3675 printf("threads_per_core : %d\n", info.threads_per_core);
3676 printf("cpu_mhz : %d\n", info.cpu_khz / 1000);
3677 printf("hw_caps : ");
3678 for (i = 0; i < 8; i++)
3679 printf("%08x%c", info.hw_cap[i], i < 7 ? ':' : '\n');
3680 printf("virt_caps :");
3681 if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm)
3682 printf(" hvm");
3683 if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm_directio)
3684 printf(" hvm_directio");
3685 printf("\n");
3686 vinfo = libxl_get_version_info(&ctx);
3687 if (vinfo) {
3688 i = (1 << 20) / vinfo->pagesize;
3689 printf("total_memory : %"PRIu64"\n", info.total_pages / i);
3690 printf("free_memory : %"PRIu64"\n", info.free_pages / i);
3692 if (!libxl_get_freecpus(&ctx, &cpumap)) {
3693 libxl_for_each_cpu(i, cpumap)
3694 if (libxl_cpumap_test(&cpumap, i))
3695 n++;
3696 printf("free_cpus : %d\n", n);
3697 free(cpumap.map);
3700 return;
3703 static void output_topologyinfo(void)
3705 libxl_topologyinfo info;
3706 int i;
3708 if (libxl_get_topologyinfo(&ctx, &info)) {
3709 fprintf(stderr, "libxl_get_topologyinfo failed.\n");
3710 return;
3713 printf("cpu_topology :\n");
3714 printf("cpu: core socket node\n");
3716 for (i = 0; i < info.coremap.entries; i++) {
3717 if (info.coremap.array[i] != LIBXL_CPUARRAY_INVALID_ENTRY)
3718 printf("%3d: %4d %4d %4d\n", i, info.coremap.array[i],
3719 info.socketmap.array[i], info.nodemap.array[i]);
3722 printf("numa_info : none\n");
3724 libxl_topologyinfo_destroy(&info);
3726 return;
3729 static void info(int numa)
3731 output_nodeinfo();
3733 output_physinfo();
3735 if (numa)
3736 output_topologyinfo();
3738 output_xeninfo();
3740 printf("xend_config_format : 4\n");
3742 return;
3745 int main_info(int argc, char **argv)
3747 int opt;
3748 int option_index = 0;
3749 static struct option long_options[] = {
3750 {"help", 0, 0, 'h'},
3751 {"numa", 0, 0, 'n'},
3752 {0, 0, 0, 0}
3753 };
3754 int numa = 0;
3756 while ((opt = getopt_long(argc, argv, "hn", long_options, &option_index)) != -1) {
3757 switch (opt) {
3758 case 'h':
3759 help("info");
3760 return 0;
3761 case 'n':
3762 numa = 1;
3763 break;
3764 default:
3765 fprintf(stderr, "option `%c' not supported.\n", opt);
3766 break;
3770 info(numa);
3771 return 0;
3774 static int sched_credit_domain_get(
3775 int domid, libxl_sched_credit *scinfo)
3777 int rc;
3779 rc = libxl_sched_credit_domain_get(&ctx, domid, scinfo);
3780 if (rc)
3781 fprintf(stderr, "libxl_sched_credit_domain_get failed.\n");
3783 return rc;
3786 static int sched_credit_domain_set(
3787 int domid, libxl_sched_credit *scinfo)
3789 int rc;
3791 rc = libxl_sched_credit_domain_set(&ctx, domid, scinfo);
3792 if (rc)
3793 fprintf(stderr, "libxl_sched_credit_domain_set failed.\n");
3795 return rc;
3798 static void sched_credit_domain_output(
3799 int domid, libxl_sched_credit *scinfo)
3801 char *domname;
3802 domname = libxl_domid_to_name(&ctx, domid);
3803 printf("%-33s %4d %6d %4d\n",
3804 domname,
3805 domid,
3806 scinfo->weight,
3807 scinfo->cap);
3808 free(domname);
3811 int main_sched_credit(int argc, char **argv)
3813 libxl_dominfo *info;
3814 libxl_sched_credit scinfo;
3815 int nb_domain, i;
3816 const char *dom = NULL;
3817 int weight = 256, cap = 0, opt_w = 0, opt_c = 0;
3818 int opt, rc;
3820 while ((opt = getopt(argc, argv, "hd:w:c:")) != -1) {
3821 switch (opt) {
3822 case 'd':
3823 dom = optarg;
3824 break;
3825 case 'w':
3826 weight = strtol(optarg, NULL, 10);
3827 opt_w = 1;
3828 break;
3829 case 'c':
3830 cap = strtol(optarg, NULL, 10);
3831 opt_c = 1;
3832 break;
3833 case 'h':
3834 help("sched-credit");
3835 return 0;
3836 default:
3837 fprintf(stderr, "option `%c' not supported.\n", opt);
3838 break;
3842 if (!dom && (opt_w || opt_c)) {
3843 fprintf(stderr, "Must specify a domain.\n");
3844 return 1;
3847 if (!dom) { /* list all domain's credit scheduler info */
3848 info = libxl_list_domain(&ctx, &nb_domain);
3849 if (!info) {
3850 fprintf(stderr, "libxl_domain_infolist failed.\n");
3851 return 1;
3854 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
3855 for (i = 0; i < nb_domain; i++) {
3856 rc = sched_credit_domain_get(info[i].domid, &scinfo);
3857 if (rc)
3858 return -rc;
3859 sched_credit_domain_output(info[i].domid, &scinfo);
3861 } else {
3862 find_domain(dom);
3864 rc = sched_credit_domain_get(domid, &scinfo);
3865 if (rc)
3866 return -rc;
3868 if (!opt_w && !opt_c) { /* output credit scheduler info */
3869 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
3870 sched_credit_domain_output(domid, &scinfo);
3871 } else { /* set credit scheduler paramaters */
3872 if (opt_w)
3873 scinfo.weight = weight;
3874 if (opt_c)
3875 scinfo.cap = cap;
3876 rc = sched_credit_domain_set(domid, &scinfo);
3877 if (rc)
3878 return -rc;
3882 return 0;
3885 int main_domid(int argc, char **argv)
3887 int opt;
3888 const char *domname = NULL;
3890 while ((opt = getopt(argc, argv, "h")) != -1) {
3891 switch (opt) {
3892 case 'h':
3893 help("domid");
3894 return 0;
3895 default:
3896 fprintf(stderr, "option `%c' not supported.\n", opt);
3897 break;
3901 domname = argv[optind];
3902 if (!domname) {
3903 fprintf(stderr, "Must specify a domain name.\n\n");
3904 help("domid");
3905 return 1;
3908 if (libxl_name_to_domid(&ctx, domname, &domid)) {
3909 fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
3910 return 1;
3913 printf("%d\n", domid);
3915 return 0;
3918 int main_domname(int argc, char **argv)
3920 int opt;
3921 char *domname = NULL;
3922 char *endptr = NULL;
3924 while ((opt = getopt(argc, argv, "h")) != -1) {
3925 switch (opt) {
3926 case 'h':
3927 help("domname");
3928 return 0;
3929 default:
3930 fprintf(stderr, "option `%c' not supported.\n", opt);
3931 break;
3935 if (!argv[optind]) {
3936 fprintf(stderr, "Must specify a domain id.\n\n");
3937 help("domname");
3938 return 1;
3940 domid = strtol(argv[optind], &endptr, 10);
3941 if (domid == 0 && !strcmp(endptr, argv[optind])) {
3942 /*no digits at all*/
3943 fprintf(stderr, "Invalid domain id.\n\n");
3944 return 1;
3947 domname = libxl_domid_to_name(&ctx, domid);
3948 if (!domname) {
3949 fprintf(stderr, "Can't get domain name of domain id '%d', maybe this domain does not exist.\n", domid);
3950 return 1;
3953 printf("%s\n", domname);
3954 free(domname);
3956 return 0;
3959 int main_rename(int argc, char **argv)
3961 int opt;
3962 const char *dom;
3963 const char *new_name;
3965 while ((opt = getopt(argc, argv, "h")) != -1) {
3966 switch (opt) {
3967 case 'h':
3968 help("rename");
3969 return 0;
3970 default:
3971 fprintf(stderr, "option `%c' not supported.\n", opt);
3972 break;
3976 dom = argv[optind++];
3977 if (!dom || !argv[optind]) {
3978 fprintf(stderr, "'xl rename' requires 2 arguments.\n\n");
3979 help("rename");
3980 return 1;
3983 find_domain(dom);
3984 new_name = argv[optind];
3986 if (libxl_domain_rename(&ctx, domid, common_domname, new_name, 0)) {
3987 fprintf(stderr, "Can't rename domain '%s'.\n", dom);
3988 return 1;
3991 return 0;
3994 int main_trigger(int argc, char **argv)
3996 int opt;
3997 char *trigger_name = NULL;
3998 char *endptr = NULL;
3999 const char *dom = NULL;
4000 int vcpuid = 0;
4002 while ((opt = getopt(argc, argv, "h")) != -1) {
4003 switch (opt) {
4004 case 'h':
4005 help("trigger");
4006 return 0;
4007 default:
4008 fprintf(stderr, "option `%c' not supported.\n", opt);
4009 break;
4013 dom = argv[optind++];
4014 if (!dom || !argv[optind]) {
4015 fprintf(stderr, "'xl trigger' requires between 2 and 3 arguments.\n\n");
4016 help("trigger");
4017 return 1;
4020 find_domain(dom);
4022 trigger_name = argv[optind++];
4024 if (argv[optind]) {
4025 vcpuid = strtol(argv[optind], &endptr, 10);
4026 if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
4027 fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
4031 libxl_send_trigger(&ctx, domid, trigger_name, vcpuid);
4033 return 0;
4037 int main_sysrq(int argc, char **argv)
4039 int opt;
4040 const char *sysrq = NULL;
4041 const char *dom = NULL;
4043 while ((opt = getopt(argc, argv, "h")) != -1) {
4044 switch (opt) {
4045 case 'h':
4046 help("sysrq");
4047 return 0;
4048 default:
4049 fprintf(stderr, "option `%c' not supported.\n", opt);
4050 break;
4054 dom = argv[optind++];
4055 if (!dom || !argv[optind]) {
4056 fprintf(stderr, "'xl sysrq' requires 2 arguments.\n\n");
4057 help("sysrq");
4058 return 1;
4061 find_domain(dom);
4063 sysrq = argv[optind];
4065 if (sysrq[1] != '\0') {
4066 fprintf(stderr, "Invalid sysrq.\n\n");
4067 help("sysrq");
4068 return 1;
4071 libxl_send_sysrq(&ctx, domid, sysrq[0]);
4073 return 0;
4076 int main_debug_keys(int argc, char **argv)
4078 int opt;
4079 char *keys;
4081 while ((opt = getopt(argc, argv, "h")) != -1) {
4082 switch (opt) {
4083 case 'h':
4084 help("debug-keys");
4085 return 0;
4086 default:
4087 fprintf(stderr, "option not supported\n");
4088 break;
4091 if (optind >= argc) {
4092 help("debug-keys");
4093 return 2;
4096 keys = argv[optind];
4098 if (libxl_send_debug_keys(&ctx, keys)) {
4099 fprintf(stderr, "cannot send debug keys: %s\n", keys);
4100 return 1;
4103 return 0;
4106 int main_dmesg(int argc, char **argv)
4108 unsigned int clear = 0;
4109 libxl_xen_console_reader *cr;
4110 char *line;
4111 int opt, ret = 1;
4113 while ((opt = getopt(argc, argv, "hc")) != -1) {
4114 switch (opt) {
4115 case 'c':
4116 clear = 1;
4117 break;
4118 case 'h':
4119 help("dmesg");
4120 return 0;
4121 default:
4122 fprintf(stderr, "option not supported\n");
4123 break;
4127 cr = libxl_xen_console_read_start(&ctx, clear);
4128 if (!cr)
4129 goto finish;
4131 while ((ret = libxl_xen_console_read_line(&ctx, cr, &line)) > 0)
4132 printf("%s", line);
4134 finish:
4135 libxl_xen_console_read_finish(&ctx, cr);
4136 return ret;
4139 int main_top(int argc, char **argv)
4141 int opt;
4143 while ((opt = getopt(argc, argv, "h")) != -1) {
4144 switch (opt) {
4145 case 'h':
4146 help("top");
4147 return 0;
4148 default:
4149 fprintf(stderr, "option `%c' not supported.\n", opt);
4150 break;
4154 return system("xentop");
4157 int main_networkattach(int argc, char **argv)
4159 int opt;
4160 libxl_device_nic nic;
4161 char *endptr;
4162 const char *tok;
4163 int i;
4164 unsigned int val;
4166 while ((opt = getopt(argc, argv, "h")) != -1) {
4167 switch (opt) {
4168 case 'h':
4169 help("network-attach");
4170 return 0;
4171 default:
4172 fprintf(stderr, "option `%c' not supported.\n", opt);
4173 break;
4176 if ((argc-optind < 2) || (argc-optind > 11)) {
4177 help("network-attach");
4178 return 0;
4181 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4182 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4183 return 1;
4185 libxl_device_nic_init(&nic, -1);
4186 for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
4187 if (!strncmp("type=", *argv, 5)) {
4188 if (!strncmp("vif", (*argv) + 5, 4)) {
4189 nic.nictype = NICTYPE_VIF;
4190 } else if (!strncmp("ioemu", (*argv) + 5, 5)) {
4191 nic.nictype = NICTYPE_IOEMU;
4192 } else {
4193 fprintf(stderr, "Invalid parameter `type'.\n");
4194 return 1;
4196 } else if (!strncmp("mac=", *argv, 4)) {
4197 tok = strtok((*argv) + 4, ":");
4198 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4199 val = strtoul(tok, &endptr, 16);
4200 if ((tok == endptr) || (val > 255)) {
4201 fprintf(stderr, "Invalid parameter `mac'.\n");
4202 return 1;
4204 nic.mac[i] = val;
4206 } else if (!strncmp("bridge=", *argv, 7)) {
4207 nic.bridge = (*argv) + 7;
4208 } else if (!strncmp("ip=", *argv, 3)) {
4209 if (!inet_aton((*argv) + 3, &(nic.ip))) {
4210 fprintf(stderr, "Invalid parameter `ip'.\n");
4211 return 1;
4213 } else if (!strncmp("script=", *argv, 6)) {
4214 nic.script = (*argv) + 6;
4215 } else if (!strncmp("backend=", *argv, 8)) {
4216 if(libxl_name_to_domid(&ctx, ((*argv) + 8), &val)) {
4217 fprintf(stderr, "Specified backend domain does not exist, defaulting to Dom0\n");
4218 val = 0;
4220 nic.backend_domid = val;
4221 } else if (!strncmp("vifname=", *argv, 8)) {
4222 nic.ifname = (*argv) + 8;
4223 } else if (!strncmp("model=", *argv, 6)) {
4224 nic.model = (*argv) + 6;
4225 } else if (!strncmp("rate=", *argv, 5)) {
4226 } else if (!strncmp("accel=", *argv, 6)) {
4227 } else {
4228 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4229 return 1;
4232 nic.domid = domid;
4233 if (libxl_device_nic_add(&ctx, domid, &nic)) {
4234 fprintf(stderr, "libxl_device_nic_add failed.\n");
4235 return 1;
4237 libxl_device_nic_destroy(&nic);
4238 return 0;
4241 int main_networklist(int argc, char **argv)
4243 int opt;
4244 libxl_nicinfo *nics;
4245 unsigned int nb, i;
4247 while ((opt = getopt(argc, argv, "h")) != -1) {
4248 switch (opt) {
4249 case 'h':
4250 help("network-list");
4251 return 0;
4252 default:
4253 fprintf(stderr, "option `%c' not supported.\n", opt);
4254 break;
4257 if (argc-optind < 1) {
4258 help("network-list");
4259 return 1;
4262 /* Idx BE MAC Hdl Sta evch txr/rxr BE-path */
4263 printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
4264 "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
4265 for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
4266 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4267 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4268 continue;
4270 if (!(nics = libxl_list_nics(&ctx, domid, &nb))) {
4271 continue;
4273 for (i = 0; i < nb; ++i) {
4274 /* Idx BE */
4275 printf("%-3d %-2d ", nics[i].devid, nics[i].backend_id);
4276 /* MAC */
4277 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4278 nics[i].mac[0], nics[i].mac[1], nics[i].mac[2],
4279 nics[i].mac[3], nics[i].mac[4], nics[i].mac[5]);
4280 /* Hdl Sta evch txr/rxr BE-path */
4281 printf("%6d %5d %6d %5d/%-11d %-30s\n",
4282 nics[i].devid, nics[i].state, nics[i].evtch,
4283 nics[i].rref_tx, nics[i].rref_rx, nics[i].backend);
4284 libxl_nicinfo_destroy(&nics[i]);
4286 free(nics);
4288 return 0;
4291 int main_networkdetach(int argc, char **argv)
4293 int opt;
4294 libxl_device_nic nic;
4296 while ((opt = getopt(argc, argv, "h")) != -1) {
4297 switch (opt) {
4298 case 'h':
4299 help("network-detach");
4300 return 0;
4301 default:
4302 fprintf(stderr, "option `%c' not supported.\n", opt);
4303 break;
4306 if (argc-optind != 2) {
4307 help("network-detach");
4308 return 0;
4311 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4312 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4313 return 1;
4316 if (!strchr(argv[optind+1], ':')) {
4317 if (libxl_devid_to_device_nic(&ctx, domid, argv[optind+1], &nic)) {
4318 fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
4319 return 1;
4321 } else {
4322 if (libxl_mac_to_device_nic(&ctx, domid, argv[optind+1], &nic)) {
4323 fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
4324 return 1;
4327 if (libxl_device_nic_del(&ctx, &nic, 1)) {
4328 fprintf(stderr, "libxl_device_nic_del failed.\n");
4329 return 1;
4331 libxl_device_nic_destroy(&nic);
4332 return 0;
4335 int main_blockattach(int argc, char **argv)
4337 int opt;
4338 const char *tok;
4339 uint32_t fe_domid, be_domid = 0;
4340 libxl_device_disk disk = { 0 };
4342 while ((opt = getopt(argc, argv, "h")) != -1) {
4343 switch (opt) {
4344 case 'h':
4345 help("block-attach");
4346 return 0;
4347 default:
4348 fprintf(stderr, "option `%c' not supported.\n", opt);
4349 break;
4352 if ((argc-optind < 3) || (argc-optind > 5)) {
4353 help("block-attach");
4354 return 0;
4357 tok = strtok(argv[optind+1], ":");
4358 if (!strcmp(tok, "phy")) {
4359 disk.phystype = PHYSTYPE_PHY;
4360 } else if (!strcmp(tok, "file")) {
4361 disk.phystype = PHYSTYPE_FILE;
4362 } else if (!strcmp(tok, "tap")) {
4363 tok = strtok(NULL, ":");
4364 if (!strcmp(tok, "aio")) {
4365 disk.phystype = PHYSTYPE_AIO;
4366 } else if (!strcmp(tok, "vhd")) {
4367 disk.phystype = PHYSTYPE_VHD;
4368 } else if (!strcmp(tok, "qcow")) {
4369 disk.phystype = PHYSTYPE_QCOW;
4370 } else if (!strcmp(tok, "qcow2")) {
4371 disk.phystype = PHYSTYPE_QCOW2;
4372 } else {
4373 fprintf(stderr, "Error: `%s' is not a valid disk image.\n", tok);
4374 return 1;
4376 } else {
4377 fprintf(stderr, "Error: `%s' is not a valid block device.\n", tok);
4378 return 1;
4380 disk.physpath = strtok(NULL, "\0");
4381 if (!disk.physpath) {
4382 fprintf(stderr, "Error: missing path to disk image.\n");
4383 return 1;
4385 disk.virtpath = argv[optind+2];
4386 disk.unpluggable = 1;
4387 disk.readwrite = ((argc-optind <= 3) || (argv[optind+3][0] == 'w'));
4389 if (domain_qualifier_to_domid(argv[optind], &fe_domid, 0) < 0) {
4390 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4391 return 1;
4393 if (argc-optind == 5) {
4394 if (domain_qualifier_to_domid(argv[optind+4], &be_domid, 0) < 0) {
4395 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind+4]);
4396 return 1;
4399 disk.domid = fe_domid;
4400 disk.backend_domid = be_domid;
4402 if (libxl_device_disk_add(&ctx, fe_domid, &disk)) {
4403 fprintf(stderr, "libxl_device_disk_add failed.\n");
4405 return 0;
4408 int main_blocklist(int argc, char **argv)
4410 int opt;
4411 int i, nb;
4412 libxl_device_disk *disks;
4413 libxl_diskinfo diskinfo;
4415 while ((opt = getopt(argc, argv, "h")) != -1) {
4416 switch (opt) {
4417 case 'h':
4418 help("block-list");
4419 return 0;
4420 default:
4421 fprintf(stderr, "option `%c' not supported.\n", opt);
4422 break;
4425 if (argc-optind < 1) {
4426 help("block-list");
4427 return 0;
4430 printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
4431 "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
4432 for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
4433 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4434 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4435 continue;
4437 disks = libxl_device_disk_list(&ctx, domid, &nb);
4438 if (!disks) {
4439 continue;
4441 for (i=0; i<nb; i++) {
4442 if (!libxl_device_disk_getinfo(&ctx, domid, &disks[i], &diskinfo)) {
4443 /* Vdev BE hdl st evch rref BE-path*/
4444 printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
4445 diskinfo.devid, diskinfo.backend_id, diskinfo.frontend_id,
4446 diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
4447 libxl_diskinfo_destroy(&diskinfo);
4449 libxl_device_disk_destroy(&disks[i]);
4451 free(disks);
4453 return 0;
4456 int main_blockdetach(int argc, char **argv)
4458 int opt;
4459 libxl_device_disk disk;
4461 while ((opt = getopt(argc, argv, "h")) != -1) {
4462 switch (opt) {
4463 case 'h':
4464 help("block-detach");
4465 return 0;
4466 default:
4467 fprintf(stderr, "option `%c' not supported.\n", opt);
4468 break;
4471 if (argc-optind != 2) {
4472 help("block-detach");
4473 return 0;
4476 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4477 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4478 return 1;
4480 if (libxl_devid_to_device_disk(&ctx, domid, argv[optind+1], &disk)) {
4481 fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
4482 return 1;
4484 if (libxl_device_disk_del(&ctx, &disk, 1)) {
4485 fprintf(stderr, "libxl_device_disk_del failed.\n");
4487 return 0;
4490 int main_network2attach(int argc, char **argv)
4492 int opt;
4493 const char *tok;
4494 char *endptr;
4495 const char *back_dom = NULL;
4496 uint32_t domid, back_domid;
4497 unsigned int val, i;
4498 libxl_device_net2 net2;
4500 while ((opt = getopt(argc, argv, "h")) != -1) {
4501 switch (opt) {
4502 case 'h':
4503 help("network2-attach");
4504 return 0;
4505 default:
4506 fprintf(stderr, "option `%c' not supported.\n", opt);
4507 break;
4510 if ((argc-optind < 1) || (argc-optind > 10)) {
4511 help("network2-attach");
4512 return 0;
4515 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4516 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4517 return 1;
4519 libxl_device_net2_init(&net2, -1);
4520 for (argv += optind+1, argc -= optind+1; argc > 0; --argc, ++argv) {
4521 if (!strncmp("front_mac=", *argv, 10)) {
4522 tok = strtok((*argv) + 10, ":");
4523 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4524 val = strtoul(tok, &endptr, 16);
4525 if ((tok == endptr) || (val > 255)) {
4526 fprintf(stderr, "Invalid parameter `front_mac'.\n");
4527 return 1;
4529 net2.front_mac[i] = val;
4531 } else if (!strncmp("back_mac=", *argv, 9)) {
4532 tok = strtok((*argv) + 10, ":");
4533 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4534 val = strtoul(tok, &endptr, 16);
4535 if ((tok == endptr) || (val > 255)) {
4536 fprintf(stderr, "Invalid parameter back_mac=%s.\n", *argv + 9);
4537 return 1;
4539 net2.back_mac[i] = val;
4541 } else if (!strncmp("backend=", *argv, 8)) {
4542 back_dom = *argv;
4543 } else if (!strncmp("trusted=", *argv, 8)) {
4544 net2.trusted = (*((*argv) + 8) == '1');
4545 } else if (!strncmp("back_trusted=", *argv, 13)) {
4546 net2.back_trusted = (*((*argv) + 13) == '1');
4547 } else if (!strncmp("bridge=", *argv, 7)) {
4548 net2.bridge = *argv + 13;
4549 } else if (!strncmp("filter_mac=", *argv, 11)) {
4550 net2.filter_mac = (*((*argv) + 11) == '1');
4551 } else if (!strncmp("front_filter_mac=", *argv, 17)) {
4552 net2.front_filter_mac = (*((*argv) + 17) == '1');
4553 } else if (!strncmp("pdev=", *argv, 5)) {
4554 val = strtoul(*argv + 5, &endptr, 10);
4555 if (endptr == (*argv + 5)) {
4556 fprintf(stderr, "Invalid parameter pdev=%s.\n", *argv + 5);
4557 return 1;
4559 net2.pdev = val;
4560 } else if (!strncmp("max_bypasses=", *argv, 13)) {
4561 val = strtoul(*argv + 13, &endptr, 10);
4562 if (endptr == (*argv + 13)) {
4563 fprintf(stderr, "Invalid parameter max_bypasses=%s.\n", *argv + 13);
4564 return 1;
4566 net2.max_bypasses = val;
4567 } else {
4568 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4569 return 1;
4573 if (back_dom) {
4574 if (domain_qualifier_to_domid(back_dom, &back_domid, 0) < 0) {
4575 fprintf(stderr, "%s is an invalid domain identifier\n", back_dom);
4576 return 1;
4579 net2.domid = domid;
4580 net2.backend_domid = back_domid;
4581 if (libxl_device_net2_add(&ctx, domid, &net2)) {
4582 fprintf(stderr, "libxl_device_net2_add failed.\n");
4584 return 0;
4587 int main_network2list(int argc, char **argv)
4589 int opt;
4590 unsigned int nb;
4591 libxl_net2info *net2s;
4593 while ((opt = getopt(argc, argv, "h")) != -1) {
4594 switch (opt) {
4595 case 'h':
4596 help("network2-list");
4597 return 0;
4598 default:
4599 fprintf(stderr, "option `%c' not supported.\n", opt);
4600 break;
4603 if (argc - optind < 1) {
4604 help("network2-list");
4605 return 0;
4608 printf("%-3s %-2s %-5s %-17s %-17s %-7s %-6s %-30s\n",
4609 "Idx", "BE", "state", "Mac Addr.", "Remote Mac Addr.",
4610 "trusted", "filter", "backend");
4611 for (argv += optind, argc -=optind; argc > 0; --argc, ++argv) {
4612 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4613 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4614 continue;
4616 if ((net2s = libxl_device_net2_list(&ctx, domid, &nb))) {
4617 for (; nb > 0; --nb, ++net2s) {
4618 printf("%3d %2d %5d ", net2s->devid, net2s->backend_id, net2s->state);
4619 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4620 net2s->mac[0], net2s->mac[1], net2s->mac[2],
4621 net2s->mac[3], net2s->mac[4], net2s->mac[5]);
4622 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4623 net2s->back_mac[0], net2s->back_mac[1], net2s->back_mac[2],
4624 net2s->back_mac[3], net2s->back_mac[4], net2s->back_mac[5]);
4625 printf("%-7d %-6d %-30s\n", net2s->trusted, net2s->filter_mac, net2s->backend);
4629 return 0;
4632 int main_network2detach(int argc, char **argv)
4634 int opt;
4635 libxl_device_net2 net2;
4637 while ((opt = getopt(argc, argv, "h")) != -1) {
4638 switch (opt) {
4639 case 'h':
4640 help("network2-detach");
4641 return 0;
4642 default:
4643 fprintf(stderr, "option `%c' not supported.\n", opt);
4644 break;
4647 if (argc-optind != 2) {
4648 help("network2-detach");
4649 return 0;
4652 if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
4653 fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
4654 return 1;
4656 if (libxl_devid_to_device_net2(&ctx, domid, argv[optind+1], &net2)) {
4657 fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
4658 return 1;
4660 if (libxl_device_net2_del(&ctx, &net2, 1)) {
4661 fprintf(stderr, "libxl_device_net2_del failed.\n");
4662 return 1;
4664 return 0;
4667 static char *uptime_to_string(unsigned long time, int short_mode)
4669 int sec, min, hour, day;
4670 char *time_string;
4671 int ret;
4673 day = (int)(time / 86400);
4674 time -= (day * 86400);
4675 hour = (int)(time / 3600);
4676 time -= (hour * 3600);
4677 min = (int)(time / 60);
4678 time -= (min * 60);
4679 sec = time;
4681 if (short_mode)
4682 if (day > 1)
4683 ret = asprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
4684 else if (day == 1)
4685 ret = asprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
4686 else
4687 ret = asprintf(&time_string, "%2d:%02d", hour, min);
4688 else
4689 if (day > 1)
4690 ret = asprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
4691 else if (day == 1)
4692 ret = asprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
4693 else
4694 ret = asprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
4696 if (ret < 0)
4697 return NULL;
4698 return time_string;
4701 static char *current_time_to_string(time_t now)
4703 char now_str[100];
4704 struct tm *tmp;
4706 tmp = localtime(&now);
4707 if (tmp == NULL) {
4708 fprintf(stderr, "Get localtime error");
4709 exit(-1);
4711 if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
4712 fprintf(stderr, "strftime returned 0");
4713 exit(-1);
4715 return strdup(now_str);
4718 static void print_dom0_uptime(int short_mode, time_t now)
4720 int fd;
4721 char buf[512];
4722 uint32_t uptime = 0;
4723 char *uptime_str = NULL;
4724 char *now_str = NULL;
4725 char *domname;
4727 fd = open("/proc/uptime", O_RDONLY);
4728 if (fd == -1)
4729 goto err;
4731 if (read(fd, buf, sizeof(buf)) == -1) {
4732 close(fd);
4733 goto err;
4735 close(fd);
4737 strtok(buf, " ");
4738 uptime = strtoul(buf, NULL, 10);
4740 domname = libxl_domid_to_name(&ctx, 0);
4741 if (short_mode)
4743 now_str = current_time_to_string(now);
4744 uptime_str = uptime_to_string(uptime, 1);
4745 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
4746 domname, 0);
4748 else
4750 now_str = NULL;
4751 uptime_str = uptime_to_string(uptime, 0);
4752 printf("%-33s %4d %s\n", domname,
4753 0, uptime_str);
4756 free(now_str);
4757 free(uptime_str);
4758 free(domname);
4759 return;
4760 err:
4761 fprintf(stderr, "Can not get Dom0 uptime.\n");
4762 exit(-1);
4765 static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
4767 uint32_t s_time = 0;
4768 uint32_t uptime = 0;
4769 char *uptime_str = NULL;
4770 char *now_str = NULL;
4771 char *domname;
4773 s_time = libxl_vm_get_start_time(&ctx, domuid);
4774 if (s_time == -1)
4775 return;
4776 uptime = now - s_time;
4777 domname = libxl_domid_to_name(&ctx, domuid);
4778 if (short_mode)
4780 now_str = current_time_to_string(now);
4781 uptime_str = uptime_to_string(uptime, 1);
4782 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
4783 domname, domuid);
4785 else
4787 now_str = NULL;
4788 uptime_str = uptime_to_string(uptime, 0);
4789 printf("%-33s %4d %s\n", domname,
4790 domuid, uptime_str);
4793 free(domname);
4794 free(now_str);
4795 free(uptime_str);
4796 return;
4799 static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
4801 libxl_vminfo *info;
4802 time_t now;
4803 int nb_vm, i;
4805 now = time(NULL);
4807 if (!short_mode)
4808 printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
4810 if (nb_doms == 0) {
4811 print_dom0_uptime(short_mode, now);
4812 info = libxl_list_vm(&ctx, &nb_vm);
4813 for (i = 0; i < nb_vm; i++)
4814 print_domU_uptime(info[i].domid, short_mode, now);
4815 } else {
4816 for (i = 0; i < nb_doms; i++) {
4817 if (doms[i] == 0)
4818 print_dom0_uptime(short_mode, now);
4819 else
4820 print_domU_uptime(doms[i], short_mode, now);
4825 int main_uptime(int argc, char **argv)
4827 const char *dom = NULL;
4828 int short_mode = 0;
4829 uint32_t domains[100];
4830 int nb_doms = 0;
4831 int opt;
4833 while ((opt = getopt(argc, argv, "hs")) != -1) {
4834 switch (opt) {
4835 case 's':
4836 short_mode = 1;
4837 break;
4838 case 'h':
4839 help("uptime");
4840 return 0;
4841 default:
4842 fprintf(stderr, "option `%c' not supported.\n", opt);
4843 break;
4847 for (;(dom = argv[optind]) != NULL; nb_doms++,optind++) {
4848 find_domain(dom);
4849 domains[nb_doms] = domid;
4852 print_uptime(short_mode, domains, nb_doms);
4854 return 0;
4857 int main_tmem_list(int argc, char **argv)
4859 const char *dom = NULL;
4860 char *buf = NULL;
4861 int use_long = 0;
4862 int all = 0;
4863 int opt;
4865 while ((opt = getopt(argc, argv, "alh")) != -1) {
4866 switch (opt) {
4867 case 'l':
4868 use_long = 1;
4869 break;
4870 case 'a':
4871 all = 1;
4872 break;
4873 case 'h':
4874 help("tmem-list");
4875 return 0;
4876 default:
4877 fprintf(stderr, "option `%c' not supported.\n", opt);
4878 break;
4882 dom = argv[optind];
4883 if (!dom && all == 0) {
4884 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4885 help("tmem-list");
4886 return 1;
4889 if (all)
4890 domid = -1;
4891 else
4892 find_domain(dom);
4894 buf = libxl_tmem_list(&ctx, domid, use_long);
4895 if (buf == NULL)
4896 return -1;
4898 printf("%s\n", buf);
4899 free(buf);
4900 return 0;
4903 int main_tmem_freeze(int argc, char **argv)
4905 const char *dom = NULL;
4906 int all = 0;
4907 int opt;
4909 while ((opt = getopt(argc, argv, "ah")) != -1) {
4910 switch (opt) {
4911 case 'a':
4912 all = 1;
4913 break;
4914 case 'h':
4915 help("tmem-freeze");
4916 return 0;
4917 default:
4918 fprintf(stderr, "option `%c' not supported.\n", opt);
4919 break;
4923 dom = argv[optind];
4924 if (!dom && all == 0) {
4925 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4926 help("tmem-freeze");
4927 return 1;
4930 if (all)
4931 domid = -1;
4932 else
4933 find_domain(dom);
4935 libxl_tmem_freeze(&ctx, domid);
4936 return 0;
4939 int main_tmem_destroy(int argc, char **argv)
4941 const char *dom = NULL;
4942 int all = 0;
4943 int opt;
4945 while ((opt = getopt(argc, argv, "ah")) != -1) {
4946 switch (opt) {
4947 case 'a':
4948 all = 1;
4949 break;
4950 case 'h':
4951 help("tmem-destroy");
4952 return 0;
4953 default:
4954 fprintf(stderr, "option `%c' not supported.\n", opt);
4955 break;
4959 dom = argv[optind];
4960 if (!dom && all == 0) {
4961 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4962 help("tmem-destroy");
4963 return 1;
4966 if (all)
4967 domid = -1;
4968 else
4969 find_domain(dom);
4971 libxl_tmem_destroy(&ctx, domid);
4972 return 0;
4975 int main_tmem_thaw(int argc, char **argv)
4977 const char *dom = NULL;
4978 int all = 0;
4979 int opt;
4981 while ((opt = getopt(argc, argv, "ah")) != -1) {
4982 switch (opt) {
4983 case 'a':
4984 all = 1;
4985 break;
4986 case 'h':
4987 help("tmem-thaw");
4988 return 0;
4989 default:
4990 fprintf(stderr, "option `%c' not supported.\n", opt);
4991 break;
4995 dom = argv[optind];
4996 if (!dom && all == 0) {
4997 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4998 help("tmem-thaw");
4999 return 1;
5002 if (all)
5003 domid = -1;
5004 else
5005 find_domain(dom);
5007 libxl_tmem_thaw(&ctx, domid);
5008 return 0;
5011 int main_tmem_set(int argc, char **argv)
5013 const char *dom = NULL;
5014 uint32_t weight = 0, cap = 0, compress = 0;
5015 int opt_w = 0, opt_c = 0, opt_p = 0;
5016 int all = 0;
5017 int opt;
5019 while ((opt = getopt(argc, argv, "aw:c:p:h")) != -1) {
5020 switch (opt) {
5021 case 'a':
5022 all = 1;
5023 break;
5024 case 'w':
5025 weight = strtol(optarg, NULL, 10);
5026 opt_w = 1;
5027 break;
5028 case 'c':
5029 cap = strtol(optarg, NULL, 10);
5030 opt_c = 1;
5031 break;
5032 case 'p':
5033 compress = strtol(optarg, NULL, 10);
5034 opt_p = 1;
5035 break;
5036 case 'h':
5037 help("tmem-set");
5038 return 0;
5039 default:
5040 fprintf(stderr, "option `%c' not supported.\n", opt);
5041 break;
5045 dom = argv[optind];
5046 if (!dom && all == 0) {
5047 fprintf(stderr, "You must specify -a or a domain id.\n\n");
5048 help("tmem-set");
5049 return 1;
5052 if (all)
5053 domid = -1;
5054 else
5055 find_domain(dom);
5057 if (!opt_w && !opt_c && !opt_p) {
5058 fprintf(stderr, "No set value specified.\n\n");
5059 help("tmem-set");
5060 return 1;
5063 if (opt_w)
5064 libxl_tmem_set(&ctx, domid, "weight", weight);
5065 if (opt_c)
5066 libxl_tmem_set(&ctx, domid, "cap", cap);
5067 if (opt_p)
5068 libxl_tmem_set(&ctx, domid, "compress", compress);
5070 return 0;
5073 int main_tmem_shared_auth(int argc, char **argv)
5075 const char *autharg = NULL;
5076 char *endptr = NULL;
5077 const char *dom = NULL;
5078 char *uuid = NULL;
5079 int auth = -1;
5080 int all = 0;
5081 int opt;
5083 while ((opt = getopt(argc, argv, "au:A:h")) != -1) {
5084 switch (opt) {
5085 case 'a':
5086 all = 1;
5087 break;
5088 case 'u':
5089 uuid = optarg;
5090 break;
5091 case 'A':
5092 autharg = optarg;
5093 break;
5094 case 'h':
5095 help("tmem-shared-auth");
5096 return 0;
5097 default:
5098 fprintf(stderr, "option `%c' not supported.\n", opt);
5099 break;
5103 dom = argv[optind];
5104 if (!dom && all == 0) {
5105 fprintf(stderr, "You must specify -a or a domain id.\n\n");
5106 help("tmem-shared-auth");
5107 return 1;
5110 if (all)
5111 domid = -1;
5112 else
5113 find_domain(dom);
5115 if (uuid == NULL || autharg == NULL) {
5116 fprintf(stderr, "No uuid or auth specified.\n\n");
5117 help("tmem-shared-auth");
5118 return 1;
5121 auth = strtol(autharg, &endptr, 10);
5122 if (*endptr != '\0') {
5123 fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
5124 return 1;
5127 libxl_tmem_shared_auth(&ctx, domid, uuid, auth);
5129 return 0;
5132 int main_tmem_freeable(int argc, char **argv)
5134 int opt;
5135 int mb;
5137 while ((opt = getopt(argc, argv, "h")) != -1) {
5138 switch (opt) {
5139 case 'h':
5140 help("tmem-freeable");
5141 return 0;
5142 default:
5143 fprintf(stderr, "option `%c' not supported.\n", opt);
5144 break;
5148 mb = libxl_tmem_freeable(&ctx);
5149 if (mb == -1)
5150 return -1;
5152 printf("%d\n", mb);
5153 return 0;
5156 int main_cpupoolcreate(int argc, char **argv)
5158 const char *filename = NULL;
5159 const char *p;
5160 char extra_config[1024];
5161 int dryrun = 0;
5162 int opt;
5163 int option_index = 0;
5164 static struct option long_options[] = {
5165 {"help", 0, 0, 'h'},
5166 {"defconfig", 1, 0, 'f'},
5167 {"dryrun", 0, 0, 'n'},
5168 {0, 0, 0, 0}
5169 };
5170 int ret;
5171 void *config_data = 0;
5172 int config_len = 0;
5173 XLU_Config *config;
5174 const char *buf;
5175 const char *name;
5176 const char *sched;
5177 uint32_t poolid;
5178 int schedid = -1;
5179 XLU_ConfigList *cpus;
5180 XLU_ConfigList *nodes;
5181 int n_cpus, n_nodes, i, n;
5182 libxl_cpumap freemap;
5183 libxl_cpumap cpumap;
5184 libxl_uuid uuid;
5185 libxl_topologyinfo topology;
5187 while (1) {
5188 opt = getopt_long(argc, argv, "hnf:", long_options, &option_index);
5189 if (opt == -1)
5190 break;
5192 switch (opt) {
5193 case 'f':
5194 filename = optarg;
5195 break;
5196 case 'h':
5197 help("cpupool-create");
5198 return 0;
5199 case 'n':
5200 dryrun = 1;
5201 break;
5202 default:
5203 fprintf(stderr, "option not supported\n");
5204 break;
5208 memset(extra_config, 0, sizeof(extra_config));
5209 while (optind < argc) {
5210 if ((p = strchr(argv[optind], '='))) {
5211 if (strlen(extra_config) + 1 < sizeof(extra_config)) {
5212 if (strlen(extra_config))
5213 strcat(extra_config, "\n");
5214 strcat(extra_config, argv[optind]);
5216 } else if (!filename) {
5217 filename = argv[optind];
5218 } else {
5219 help("cpupool-create");
5220 return -ERROR_FAIL;
5222 optind++;
5225 if (!filename) {
5226 help("cpupool-create");
5227 return -ERROR_FAIL;
5230 if (libxl_read_file_contents(&ctx, filename, &config_data, &config_len)) {
5231 fprintf(stderr, "Failed to read config file: %s: %s\n",
5232 filename, strerror(errno));
5233 return -ERROR_FAIL;
5235 if (strlen(extra_config)) {
5236 if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
5237 fprintf(stderr, "Failed to attach extra configration\n");
5238 return -ERROR_FAIL;
5240 config_data = xrealloc(config_data,
5241 config_len + strlen(extra_config) + 2);
5242 if (!config_data) {
5243 fprintf(stderr, "Failed to realloc config_data\n");
5244 return -ERROR_FAIL;
5246 strcat(config_data, "\n");
5247 strcat(config_data, extra_config);
5248 strcat(config_data, "\n");
5249 config_len += (strlen(extra_config) + 2);
5252 config = xlu_cfg_init(stderr, filename);
5253 if (!config) {
5254 fprintf(stderr, "Failed to allocate for configuration\n");
5255 return -ERROR_FAIL;
5258 ret = xlu_cfg_readdata(config, config_data, config_len);
5259 if (ret) {
5260 fprintf(stderr, "Failed to parse config file: %s\n", strerror(ret));
5261 return -ERROR_FAIL;
5264 if (!xlu_cfg_get_string (config, "name", &buf))
5265 name = strdup(buf);
5266 else
5267 name = libxl_basename(filename);
5268 if (!libxl_name_to_cpupoolid(&ctx, name, &poolid)) {
5269 fprintf(stderr, "Pool name \"%s\" already exists\n", name);
5270 return -ERROR_FAIL;
5273 if (!xlu_cfg_get_string (config, "sched", &buf)) {
5274 if ((schedid = libxl_name_to_schedid(&ctx, buf)) < 0) {
5275 fprintf(stderr, "Unknown scheduler\n");
5276 return -ERROR_FAIL;
5278 } else {
5279 if ((schedid = libxl_get_sched_id(&ctx)) < 0) {
5280 fprintf(stderr, "get_sched_id sysctl failed.\n");
5281 return -ERROR_FAIL;
5284 sched = libxl_schedid_to_name(&ctx, schedid);
5286 if (libxl_get_freecpus(&ctx, &freemap)) {
5287 fprintf(stderr, "libxl_get_freecpus failed\n");
5288 return -ERROR_FAIL;
5290 if (libxl_cpumap_alloc(&ctx, &cpumap)) {
5291 fprintf(stderr, "Failed to allocate cpumap\n");
5292 return -ERROR_FAIL;
5294 if (!xlu_cfg_get_list(config, "nodes", &nodes, 0, 0)) {
5295 n_cpus = 0;
5296 n_nodes = 0;
5297 if (libxl_get_topologyinfo(&ctx, &topology)) {
5298 fprintf(stderr, "libxl_get_topologyinfo failed\n");
5299 return -ERROR_FAIL;
5301 while ((buf = xlu_cfg_get_listitem(nodes, n_nodes)) != NULL) {
5302 n = atoi(buf);
5303 for (i = 0; i < topology.nodemap.entries; i++) {
5304 if ((topology.nodemap.array[i] == n) &&
5305 libxl_cpumap_test(&freemap, i)) {
5306 libxl_cpumap_set(&cpumap, i);
5307 n_cpus++;
5310 n_nodes++;
5313 libxl_topologyinfo_destroy(&topology);
5315 if (n_cpus == 0) {
5316 fprintf(stderr, "no free cpu found\n");
5317 return -ERROR_FAIL;
5319 } else if (!xlu_cfg_get_list(config, "cpus", &cpus, 0, 0)) {
5320 n_cpus = 0;
5321 while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) {
5322 i = atoi(buf);
5323 if ((i < 0) || (i >= freemap.size * 8) ||
5324 !libxl_cpumap_test(&freemap, i)) {
5325 fprintf(stderr, "cpu %d illegal or not free\n", i);
5326 return -ERROR_FAIL;
5328 libxl_cpumap_set(&cpumap, i);
5329 n_cpus++;
5331 } else {
5332 n_cpus = 1;
5333 n = 0;
5334 libxl_for_each_cpu(i, freemap)
5335 if (libxl_cpumap_test(&freemap, i)) {
5336 n++;
5337 libxl_cpumap_set(&cpumap, i);
5338 break;
5340 if (n < n_cpus) {
5341 fprintf(stderr, "no free cpu found\n");
5342 return -ERROR_FAIL;
5346 libxl_uuid_generate(&uuid);
5348 printf("Using config file \"%s\"\n", filename);
5349 printf("cpupool name: %s\n", name);
5350 printf("scheduler: %s\n", sched);
5351 printf("number of cpus: %d\n", n_cpus);
5353 if (dryrun)
5354 return 0;
5356 poolid = 0;
5357 if (libxl_create_cpupool(&ctx, name, schedid, cpumap, &uuid, &poolid)) {
5358 fprintf(stderr, "error on creating cpupool\n");
5359 return -ERROR_FAIL;
5362 return 0;
5365 int main_cpupoollist(int argc, char **argv)
5367 int opt;
5368 int option_index = 0;
5369 static struct option long_options[] = {
5370 {"help", 0, 0, 'h'},
5371 {"long", 0, 0, 'l'},
5372 {"cpus", 0, 0, 'c'},
5373 {0, 0, 0, 0}
5374 };
5375 int opt_long = 0;
5376 int opt_cpus = 0;
5377 const char *pool = NULL;
5378 libxl_cpupoolinfo *poolinfo;
5379 int n_pools, p, c, n;
5380 uint32_t poolid;
5381 char *name;
5382 int ret = 0;
5384 while (1) {
5385 opt = getopt_long(argc, argv, "hlc", long_options, &option_index);
5386 if (opt == -1)
5387 break;
5389 switch (opt) {
5390 case 'h':
5391 help("cpupool-list");
5392 return 0;
5393 case 'l':
5394 opt_long = 1;
5395 break;
5396 case 'c':
5397 opt_cpus = 1;
5398 break;
5399 default:
5400 fprintf(stderr, "option not supported\n");
5401 break;
5405 if ((optind + 1) < argc) {
5406 help("cpupool-list");
5407 return -ERROR_FAIL;
5409 if (optind < argc) {
5410 pool = argv[optind];
5411 if (libxl_name_to_cpupoolid(&ctx, pool, &poolid)) {
5412 fprintf(stderr, "Pool \'%s\' does not exist\n", pool);
5413 return -ERROR_FAIL;
5417 poolinfo = libxl_list_cpupool(&ctx, &n_pools);
5418 if (!poolinfo) {
5419 fprintf(stderr, "error getting cpupool info\n");
5420 return -ERROR_NOMEM;
5423 if (!opt_long) {
5424 printf("%-19s", "Name");
5425 if (opt_cpus)
5426 printf("CPU list\n");
5427 else
5428 printf("CPUs Sched Active Domain count\n");
5431 for (p = 0; p < n_pools; p++) {
5432 if (!ret && (!pool || (poolinfo[p].poolid != poolid))) {
5433 name = libxl_cpupoolid_to_name(&ctx, poolinfo[p].poolid);
5434 if (!name) {
5435 fprintf(stderr, "error getting cpupool info\n");
5436 ret = -ERROR_NOMEM;
5438 else if (opt_long) {
5439 ret = -ERROR_NI;
5440 } else {
5441 printf("%-19s", name);
5442 free(name);
5443 n = 0;
5444 libxl_for_each_cpu(c, poolinfo[p].cpumap)
5445 if (libxl_cpumap_test(&poolinfo[p].cpumap, c)) {
5446 if (n && opt_cpus) printf(",");
5447 if (opt_cpus) printf("%d", c);
5448 n++;
5450 if (!opt_cpus) {
5451 printf("%3d %9s y %4d", n,
5452 libxl_schedid_to_name(&ctx, poolinfo[p].sched_id),
5453 poolinfo[p].n_dom);
5455 printf("\n");
5458 libxl_cpupoolinfo_destroy(poolinfo + p);
5461 return ret;
5464 int main_cpupooldestroy(int argc, char **argv)
5466 int opt;
5467 const char *pool;
5468 uint32_t poolid;
5470 while ((opt = getopt(argc, argv, "h")) != -1) {
5471 switch (opt) {
5472 case 'h':
5473 help("cpupool-destroy");
5474 return 0;
5475 default:
5476 fprintf(stderr, "option `%c' not supported.\n", opt);
5477 break;
5481 pool = argv[optind];
5482 if (!pool) {
5483 fprintf(stderr, "no cpupool specified\n");
5484 help("cpupool-destroy");
5485 return -ERROR_FAIL;
5488 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5489 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5490 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5491 return -ERROR_FAIL;
5494 return -libxl_destroy_cpupool(&ctx, poolid);
5497 int main_cpupoolrename(int argc, char **argv)
5499 int opt;
5500 const char *pool;
5501 const char *new_name;
5502 uint32_t poolid;
5504 while ((opt = getopt(argc, argv, "h")) != -1) {
5505 switch (opt) {
5506 case 'h':
5507 help("cpupool-rename");
5508 return 0;
5509 default:
5510 fprintf(stderr, "option `%c' not supported.\n", opt);
5511 break;
5515 pool = argv[optind++];
5516 if (!pool || !argv[optind]) {
5517 fprintf(stderr, "'xl cpupool-rename' requires 2 arguments.\n\n");
5518 help("cpupool-rename");
5519 return 1;
5522 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5523 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5524 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5525 return -ERROR_FAIL;
5528 new_name = argv[optind];
5530 if (libxl_cpupool_rename(&ctx, new_name, poolid)) {
5531 fprintf(stderr, "Can't rename cpupool '%s'.\n", pool);
5532 return 1;
5535 return 0;
5538 int main_cpupoolcpuadd(int argc, char **argv)
5540 int opt;
5541 const char *pool;
5542 uint32_t poolid;
5543 int cpu;
5544 int node;
5545 int n;
5547 while ((opt = getopt(argc, argv, "h")) != -1) {
5548 switch (opt) {
5549 case 'h':
5550 help("cpupool-cpu-add");
5551 return 0;
5552 default:
5553 fprintf(stderr, "option `%c' not supported.\n", opt);
5554 break;
5558 pool = argv[optind++];
5559 if (!pool) {
5560 fprintf(stderr, "no cpupool specified\n");
5561 help("cpupool-cpu-add");
5562 return -ERROR_FAIL;
5565 if (!argv[optind]) {
5566 fprintf(stderr, "no cpu specified\n");
5567 help("cpupool-cpu-add");
5568 return -ERROR_FAIL;
5570 node = -1;
5571 cpu = -1;
5572 if (strncmp(argv[optind], "node:", 5) == 0) {
5573 node = atoi(argv[optind] + 5);
5574 } else {
5575 cpu = atoi(argv[optind]);
5578 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5579 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5580 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5581 return -ERROR_FAIL;
5584 if (cpu >= 0) {
5585 return -libxl_cpupool_cpuadd(&ctx, poolid, cpu);
5588 if (libxl_cpupool_cpuadd_node(&ctx, poolid, node, &n)) {
5589 fprintf(stderr, "libxl_cpupool_cpuadd_node failed\n");
5590 return -ERROR_FAIL;
5593 if (n > 0) {
5594 return 0;
5597 fprintf(stderr, "no free cpu found\n");
5598 return -ERROR_FAIL;
5601 int main_cpupoolcpuremove(int argc, char **argv)
5603 int opt;
5604 const char *pool;
5605 uint32_t poolid;
5606 int cpu;
5607 int node;
5608 int n;
5610 while ((opt = getopt(argc, argv, "h")) != -1) {
5611 switch (opt) {
5612 case 'h':
5613 help("cpupool-cpu-remove");
5614 return 0;
5615 default:
5616 fprintf(stderr, "option `%c' not supported.\n", opt);
5617 break;
5621 pool = argv[optind++];
5622 if (!pool) {
5623 fprintf(stderr, "no cpupool specified\n");
5624 help("cpupool-cpu-remove");
5625 return -ERROR_FAIL;
5628 if (!argv[optind]) {
5629 fprintf(stderr, "no cpu specified\n");
5630 help("cpupool-cpu-remove");
5631 return -ERROR_FAIL;
5633 node = -1;
5634 cpu = -1;
5635 if (strncmp(argv[optind], "node:", 5) == 0) {
5636 node = atoi(argv[optind] + 5);
5637 } else {
5638 cpu = atoi(argv[optind]);
5641 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5642 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5643 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5644 return -ERROR_FAIL;
5647 if (cpu >= 0) {
5648 return -libxl_cpupool_cpuremove(&ctx, poolid, cpu);
5651 if (libxl_cpupool_cpuremove_node(&ctx, poolid, node, &n)) {
5652 fprintf(stderr, "libxl_cpupool_cpuremove_node failed\n");
5653 return -ERROR_FAIL;
5656 if (n == 0) {
5657 fprintf(stderr, "no cpu of node found in cpupool\n");
5658 return -ERROR_FAIL;
5661 return 0;
5664 int main_cpupoolmigrate(int argc, char **argv)
5666 int opt;
5667 const char *pool;
5668 uint32_t poolid;
5669 const char *dom;
5670 uint32_t domid;
5672 while ((opt = getopt(argc, argv, "h")) != -1) {
5673 switch (opt) {
5674 case 'h':
5675 help("cpupool-migrate");
5676 return 0;
5677 default:
5678 fprintf(stderr, "option `%c' not supported.\n", opt);
5679 break;
5683 dom = argv[optind++];
5684 if (!dom) {
5685 fprintf(stderr, "no domain specified\n");
5686 help("cpupool-migrate");
5687 return -ERROR_FAIL;
5690 pool = argv[optind++];
5691 if (!pool) {
5692 fprintf(stderr, "no cpupool specified\n");
5693 help("cpupool-migrate");
5694 return -ERROR_FAIL;
5697 if (domain_qualifier_to_domid(dom, &domid, NULL) ||
5698 !libxl_domid_to_name(&ctx, domid)) {
5699 fprintf(stderr, "unknown domain \'%s\'\n", dom);
5700 return -ERROR_FAIL;
5703 if (cpupool_qualifier_to_cpupoolid(pool, &poolid, NULL) ||
5704 !libxl_cpupoolid_to_name(&ctx, poolid)) {
5705 fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
5706 return -ERROR_FAIL;
5709 return -libxl_cpupool_movedomain(&ctx, poolid, domid);
5712 int main_cpupoolnumasplit(int argc, char **argv)
5714 int ret;
5715 int opt;
5716 int p;
5717 int c;
5718 int n;
5719 uint32_t poolid;
5720 int schedid;
5721 int n_pools;
5722 int node;
5723 char name[16];
5724 libxl_uuid uuid;
5725 libxl_cpumap cpumap;
5726 libxl_cpupoolinfo *poolinfo;
5727 libxl_topologyinfo topology;
5729 while ((opt = getopt(argc, argv, "h")) != -1) {
5730 switch (opt) {
5731 case 'h':
5732 help("cpupool-numa-split");
5733 return 0;
5734 default:
5735 fprintf(stderr, "option `%c' not supported.\n", opt);
5736 break;
5739 ret = 0;
5741 poolinfo = libxl_list_cpupool(&ctx, &n_pools);
5742 if (!poolinfo) {
5743 fprintf(stderr, "error getting cpupool info\n");
5744 return -ERROR_NOMEM;
5746 poolid = poolinfo[0].poolid;
5747 schedid = poolinfo[0].sched_id;
5748 for (p = 0; p < n_pools; p++) {
5749 libxl_cpupoolinfo_destroy(poolinfo + p);
5751 if (n_pools > 1) {
5752 fprintf(stderr, "splitting not possible, already cpupools in use\n");
5753 return -ERROR_FAIL;
5756 if (libxl_get_topologyinfo(&ctx, &topology)) {
5757 fprintf(stderr, "libxl_get_topologyinfo failed\n");
5758 return -ERROR_FAIL;
5761 if (libxl_cpumap_alloc(&ctx, &cpumap)) {
5762 fprintf(stderr, "Failed to allocate cpumap\n");
5763 libxl_topologyinfo_destroy(&topology);
5764 return -ERROR_FAIL;
5767 /* Reset Pool-0 to 1st node: first add cpus, then remove cpus to avoid
5768 a cpupool without cpus in between */
5770 node = topology.nodemap.array[0];
5771 if (libxl_cpupool_cpuadd_node(&ctx, 0, node, &n)) {
5772 fprintf(stderr, "error on adding cpu to Pool 0\n");
5773 return -ERROR_FAIL;
5776 snprintf(name, 15, "Pool-node%d", node);
5777 ret = -libxl_cpupool_rename(&ctx, name, 0);
5778 if (ret) {
5779 fprintf(stderr, "error on renaming Pool 0\n");
5780 goto out;
5783 for (c = 0; c < topology.nodemap.entries; c++) {
5784 if (topology.nodemap.array[c] == node) {
5785 topology.nodemap.array[c] = LIBXL_CPUARRAY_INVALID_ENTRY;
5789 for (c = 0; c < topology.nodemap.entries; c++) {
5790 if (topology.nodemap.array[c] == LIBXL_CPUARRAY_INVALID_ENTRY) {
5791 continue;
5794 node = topology.nodemap.array[c];
5795 ret = -libxl_cpupool_cpuremove_node(&ctx, 0, node, &n);
5796 if (ret) {
5797 fprintf(stderr, "error on removing cpu from Pool 0\n");
5798 goto out;
5801 snprintf(name, 15, "Pool-node%d", node);
5802 libxl_uuid_generate(&uuid);
5803 ret = -libxl_create_cpupool(&ctx, name, schedid, cpumap, &uuid, &poolid);
5804 if (ret) {
5805 fprintf(stderr, "error on creating cpupool\n");
5806 goto out;
5809 ret = -libxl_cpupool_cpuadd_node(&ctx, 0, node, &n);
5810 if (ret) {
5811 fprintf(stderr, "error on adding cpus to cpupool\n");
5812 goto out;
5815 for (p = c; p < topology.nodemap.entries; p++) {
5816 if (topology.nodemap.array[p] == node) {
5817 topology.nodemap.array[p] = LIBXL_CPUARRAY_INVALID_ENTRY;
5822 out:
5823 libxl_topologyinfo_destroy(&topology);
5824 libxl_cpumap_destroy(&cpumap);
5826 return ret;