debuggers.hg

view tools/libxl/xl_cmdimpl.c @ 21943:84f8ad68bc58

xl: support "xl list <domain>"

xm list takes an optional domain argument; make xl list do likewise.
This also gets rid of a small amount of code which was duplicated
between list_domains and list_domains_details.

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Ian Jackson <Ian.Jackson@eu.citrix.com>
date Fri Jul 30 15:12:56 2010 +0100 (2010-07-30)
parents 9ced33b68bd8
children bb187c5a7fbc
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 <sys/time.h> /* for time */
25 #include <getopt.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <signal.h>
30 #include <sys/socket.h>
31 #include <sys/select.h>
32 #include <arpa/inet.h>
33 #include <sys/utsname.h> /* for utsname in xl info */
34 #include <xenctrl.h>
35 #include <ctype.h>
36 #include <inttypes.h>
38 #include "libxl.h"
39 #include "libxl_utils.h"
40 #include "libxlutil.h"
41 #include "xl.h"
43 #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
45 #define CHK_ERRNO( call ) ({ \
46 int chk_errno = (call); \
47 if (chk_errno < 0) { \
48 fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n", \
49 __FILE__,__LINE__, strerror(chk_errno), #call); \
50 exit(-ERROR_FAIL); \
51 } \
52 })
54 #define MUST( call ) ({ \
55 int must_rc = (call); \
56 if (must_rc < 0) { \
57 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \
58 __FILE__,__LINE__, must_rc, #call); \
59 exit(-must_rc); \
60 } \
61 })
64 int logfile = 2;
66 /* every libxl action in xl uses this same libxl context */
67 libxl_ctx ctx;
69 /* when we operate on a domain, it is this one: */
70 static uint32_t domid;
71 static const char *common_domname;
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 enum action_on_shutdown {
104 ACTION_DESTROY,
106 ACTION_RESTART,
107 ACTION_RESTART_RENAME,
109 ACTION_PRESERVE,
111 ACTION_COREDUMP_DESTROY,
112 ACTION_COREDUMP_RESTART,
113 };
115 static char *action_on_shutdown_names[] = {
116 [ACTION_DESTROY] = "destroy",
118 [ACTION_RESTART] = "restart",
119 [ACTION_RESTART_RENAME] = "rename-restart",
121 [ACTION_PRESERVE] = "preserve",
123 [ACTION_COREDUMP_DESTROY] = "coredump-destroy",
124 [ACTION_COREDUMP_RESTART] = "coredump-restart",
125 };
127 struct domain_config {
128 libxl_domain_create_info c_info;
129 libxl_domain_build_info b_info;
131 int num_disks, num_vifs, num_vif2s, num_pcidevs, num_vfbs, num_vkbs;
133 libxl_device_disk *disks;
134 libxl_device_nic *vifs;
135 libxl_device_net2 *vif2s;
136 libxl_device_pci *pcidevs;
137 libxl_device_vfb *vfbs;
138 libxl_device_vkb *vkbs;
140 enum action_on_shutdown on_poweroff;
141 enum action_on_shutdown on_reboot;
142 enum action_on_shutdown on_watchdog;
143 enum action_on_shutdown on_crash;
144 };
146 /* Optional data, in order:
147 * 4 bytes uint32_t config file size
148 * n bytes config file in Unix text file format
149 */
151 #define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
153 static int qualifier_to_id(const char *p, uint32_t *id_r)
154 {
155 int i, alldigit;
157 alldigit = 1;
158 for (i = 0; p[i]; i++) {
159 if (!isdigit((uint8_t)p[i])) {
160 alldigit = 0;
161 break;
162 }
163 }
165 if (i > 0 && alldigit) {
166 *id_r = strtoul(p, NULL, 10);
167 return 0;
168 } else {
169 /* check here if it's a uuid and do proper conversion */
170 }
171 return 1;
172 }
174 static int domain_qualifier_to_domid(const char *p, uint32_t *domid_r,
175 int *was_name_r)
176 {
177 int was_name;
179 was_name = qualifier_to_id(p, domid_r);
180 if (was_name_r) *was_name_r = was_name;
181 return was_name ? libxl_name_to_domid(&ctx, p, domid_r) : 0;
182 }
184 static int pool_qualifier_to_poolid(const char *p, uint32_t *poolid_r,
185 int *was_name_r)
186 {
187 int was_name;
189 was_name = qualifier_to_id(p, poolid_r);
190 if (was_name_r) *was_name_r = was_name;
191 return was_name ? libxl_name_to_poolid(&ctx, p, poolid_r) : 0;
192 }
194 static void find_domain(const char *p)
195 {
196 int rc, was_name;
198 rc = domain_qualifier_to_domid(p, &domid, &was_name);
199 if (rc) {
200 fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
201 exit(2);
202 }
203 common_domname = was_name ? p : libxl_domid_to_name(&ctx, domid);
204 }
206 #define LOG(_f, _a...) dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
208 void dolog(const char *file, int line, const char *func, char *fmt, ...)
209 {
210 va_list ap;
211 char *s;
212 int rc;
214 va_start(ap, fmt);
215 rc = vasprintf(&s, fmt, ap);
216 va_end(ap);
217 if (rc >= 0)
218 libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
219 }
221 static void init_create_info(libxl_domain_create_info *c_info)
222 {
223 memset(c_info, '\0', sizeof(*c_info));
224 c_info->xsdata = NULL;
225 c_info->platformdata = NULL;
226 c_info->hap = 1;
227 c_info->hvm = 1;
228 c_info->oos = 1;
229 c_info->ssidref = 0;
230 c_info->poolid = 0;
231 }
233 static void init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info *c_info)
234 {
235 memset(b_info, '\0', sizeof(*b_info));
236 b_info->max_vcpus = 1;
237 b_info->max_memkb = 32 * 1024;
238 b_info->target_memkb = b_info->max_memkb;
239 b_info->disable_migrate = 0;
240 if (c_info->hvm) {
241 b_info->shadow_memkb = 0; /* Set later */
242 b_info->video_memkb = 8 * 1024;
243 b_info->kernel.path = "hvmloader";
244 b_info->hvm = 1;
245 b_info->u.hvm.pae = 1;
246 b_info->u.hvm.apic = 1;
247 b_info->u.hvm.acpi = 1;
248 b_info->u.hvm.nx = 1;
249 b_info->u.hvm.viridian = 0;
250 b_info->u.hvm.hpet = 1;
251 b_info->u.hvm.vpt_align = 1;
252 b_info->u.hvm.timer_mode = 1;
253 } else {
254 b_info->u.pv.slack_memkb = 8 * 1024;
255 }
256 }
258 static void random_uuid(uint8_t *uuid)
259 {
260 int i;
261 for (i = 0; i < 16; i++)
262 uuid[i] = rand();
263 }
265 static void init_dm_info(libxl_device_model_info *dm_info,
266 libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
267 {
268 memset(dm_info, '\0', sizeof(*dm_info));
270 random_uuid(&dm_info->uuid[0]);
272 dm_info->dom_name = c_info->name;
273 dm_info->device_model = "qemu-dm";
274 dm_info->videoram = b_info->video_memkb / 1024;
275 dm_info->apic = b_info->u.hvm.apic;
276 dm_info->vcpus = b_info->max_vcpus;
277 dm_info->vcpu_avail = b_info->cur_vcpus;
279 dm_info->stdvga = 0;
280 dm_info->vnc = 1;
281 dm_info->vnclisten = "127.0.0.1";
282 dm_info->vncdisplay = 0;
283 dm_info->vncunused = 1;
284 dm_info->keymap = NULL;
285 dm_info->sdl = 0;
286 dm_info->opengl = 0;
287 dm_info->nographic = 0;
288 dm_info->serial = NULL;
289 dm_info->boot = "cda";
290 dm_info->usb = 0;
291 dm_info->usbdevice = NULL;
292 dm_info->xen_platform_pci = 1;
293 }
295 static void init_nic_info(libxl_device_nic *nic_info, int devnum)
296 {
297 memset(nic_info, '\0', sizeof(*nic_info));
299 nic_info->backend_domid = 0;
300 nic_info->domid = 0;
301 nic_info->devid = devnum;
302 nic_info->mtu = 1492;
303 nic_info->model = "e1000";
304 nic_info->mac[0] = 0x00;
305 nic_info->mac[1] = 0x16;
306 nic_info->mac[2] = 0x3e;
307 nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
308 nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
309 nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
310 nic_info->ifname = NULL;
311 nic_info->bridge = "xenbr0";
312 CHK_ERRNO( asprintf(&nic_info->script, "%s/vif-bridge",
313 libxl_xen_script_dir_path()) );
314 nic_info->nictype = NICTYPE_IOEMU;
315 }
317 static void init_net2_info(libxl_device_net2 *net2_info, int devnum)
318 {
319 memset(net2_info, '\0', sizeof(*net2_info));
321 net2_info->devid = devnum;
322 net2_info->front_mac[0] = 0x00;
323 net2_info->front_mac[1] = 0x16;
324 net2_info->front_mac[2] = 0x3e;;
325 net2_info->front_mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
326 net2_info->front_mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
327 net2_info->front_mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
328 net2_info->back_mac[0] = 0x00;
329 net2_info->back_mac[1] = 0x16;
330 net2_info->back_mac[2] = 0x3e;
331 net2_info->back_mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
332 net2_info->back_mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
333 net2_info->back_mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
334 net2_info->back_trusted = 1;
335 net2_info->filter_mac = 1;
336 net2_info->max_bypasses = 5;
337 net2_info->bridge = "xenbr0";
338 }
340 static void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
341 {
342 memset(vfb, 0x00, sizeof(libxl_device_vfb));
343 vfb->devid = dev_num;
344 vfb->vnc = 1;
345 vfb->vnclisten = "127.0.0.1";
346 vfb->vncdisplay = 0;
347 vfb->vncunused = 1;
348 vfb->keymap = NULL;
349 vfb->sdl = 0;
350 vfb->opengl = 0;
351 }
353 static void init_vkb_info(libxl_device_vkb *vkb, int dev_num)
354 {
355 memset(vkb, 0x00, sizeof(libxl_device_vkb));
356 vkb->devid = dev_num;
357 }
359 static void init_console_info(libxl_device_console *console, int dev_num, libxl_domain_build_state *state)
360 {
361 memset(console, 0x00, sizeof(libxl_device_console));
362 console->devid = dev_num;
363 console->constype = CONSTYPE_XENCONSOLED;
364 if (state)
365 console->build_state = state;
366 }
368 static void printf_info(int domid,
369 struct domain_config *d_config,
370 libxl_device_model_info *dm_info)
371 {
372 int i;
374 libxl_domain_create_info *c_info = &d_config->c_info;
375 libxl_domain_build_info *b_info = &d_config->b_info;
377 printf("(domain\n\t(domid %d)\n", domid);
378 printf("\t(domain_create_info)\n");
379 printf("\t(hvm %d)\n", c_info->hvm);
380 printf("\t(hap %d)\n", c_info->hap);
381 printf("\t(oos %d)\n", c_info->oos);
382 printf("\t(ssidref %d)\n", c_info->ssidref);
383 printf("\t(name %s)\n", c_info->name);
384 printf("\t(uuid " UUID_FMT ")\n",
385 (c_info->uuid)[0], (c_info->uuid)[1], (c_info->uuid)[2], (c_info->uuid)[3],
386 (c_info->uuid)[4], (c_info->uuid)[5], (c_info->uuid)[6], (c_info->uuid)[7],
387 (c_info->uuid)[8], (c_info->uuid)[9], (c_info->uuid)[10], (c_info->uuid)[11],
388 (c_info->uuid)[12], (c_info->uuid)[13], (c_info->uuid)[14], (c_info->uuid)[15]);
389 printf("\t(cpupool %s (%d))\n", c_info->poolname, c_info->poolid);
390 if (c_info->xsdata)
391 printf("\t(xsdata contains data)\n");
392 else
393 printf("\t(xsdata (null))\n");
394 if (c_info->platformdata)
395 printf("\t(platformdata contains data)\n");
396 else
397 printf("\t(platformdata (null))\n");
400 printf("\t(domain_build_info)\n");
401 printf("\t(max_vcpus %d)\n", b_info->max_vcpus);
402 printf("\t(tsc_mode %d)\n", b_info->tsc_mode);
403 printf("\t(max_memkb %d)\n", b_info->max_memkb);
404 printf("\t(target_memkb %d)\n", b_info->target_memkb);
405 printf("\t(nomigrate %d)\n", b_info->disable_migrate);
407 if (!c_info->hvm && b_info->u.pv.bootloader) {
408 printf("\t(bootloader %s)\n", b_info->u.pv.bootloader);
409 if (b_info->u.pv.bootloader_args)
410 printf("\t(bootloader_args %s)\n", b_info->u.pv.bootloader_args);
411 }
413 printf("\t(image\n");
414 if (c_info->hvm) {
415 printf("\t\t(hvm\n");
416 printf("\t\t\t(loader %s)\n", b_info->kernel.path);
417 printf("\t\t\t(video_memkb %d)\n", b_info->video_memkb);
418 printf("\t\t\t(shadow_memkb %d)\n", b_info->shadow_memkb);
419 printf("\t\t\t(pae %d)\n", b_info->u.hvm.pae);
420 printf("\t\t\t(apic %d)\n", b_info->u.hvm.apic);
421 printf("\t\t\t(acpi %d)\n", b_info->u.hvm.acpi);
422 printf("\t\t\t(nx %d)\n", b_info->u.hvm.nx);
423 printf("\t\t\t(viridian %d)\n", b_info->u.hvm.viridian);
424 printf("\t\t\t(hpet %d)\n", b_info->u.hvm.hpet);
425 printf("\t\t\t(vpt_align %d)\n", b_info->u.hvm.vpt_align);
426 printf("\t\t\t(timer_mode %d)\n", b_info->u.hvm.timer_mode);
428 printf("\t\t\t(device_model %s)\n", dm_info->device_model);
429 printf("\t\t\t(videoram %d)\n", dm_info->videoram);
430 printf("\t\t\t(stdvga %d)\n", dm_info->stdvga);
431 printf("\t\t\t(vnc %d)\n", dm_info->vnc);
432 printf("\t\t\t(vnclisten %s)\n", dm_info->vnclisten);
433 printf("\t\t\t(vncdisplay %d)\n", dm_info->vncdisplay);
434 printf("\t\t\t(vncunused %d)\n", dm_info->vncunused);
435 printf("\t\t\t(keymap %s)\n", dm_info->keymap);
436 printf("\t\t\t(sdl %d)\n", dm_info->sdl);
437 printf("\t\t\t(opengl %d)\n", dm_info->opengl);
438 printf("\t\t\t(nographic %d)\n", dm_info->nographic);
439 printf("\t\t\t(serial %s)\n", dm_info->serial);
440 printf("\t\t\t(boot %s)\n", dm_info->boot);
441 printf("\t\t\t(usb %d)\n", dm_info->usb);
442 printf("\t\t\t(usbdevice %s)\n", dm_info->usbdevice);
443 printf("\t\t\t(apic %d)\n", dm_info->apic);
444 printf("\t\t)\n");
445 } else {
446 printf("\t\t(linux %d)\n", b_info->hvm);
447 printf("\t\t\t(kernel %s)\n", b_info->kernel.path);
448 printf("\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
449 printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk.path);
450 printf("\t\t)\n");
451 }
452 printf("\t)\n");
454 for (i = 0; i < d_config->num_disks; i++) {
455 printf("\t(device\n");
456 printf("\t\t(tap\n");
457 printf("\t\t\t(backend_domid %d)\n", d_config->disks[i].backend_domid);
458 printf("\t\t\t(domid %d)\n", d_config->disks[i].domid);
459 printf("\t\t\t(physpath %s)\n", d_config->disks[i].physpath);
460 printf("\t\t\t(phystype %d)\n", d_config->disks[i].phystype);
461 printf("\t\t\t(virtpath %s)\n", d_config->disks[i].virtpath);
462 printf("\t\t\t(unpluggable %d)\n", d_config->disks[i].unpluggable);
463 printf("\t\t\t(readwrite %d)\n", d_config->disks[i].readwrite);
464 printf("\t\t\t(is_cdrom %d)\n", d_config->disks[i].is_cdrom);
465 printf("\t\t)\n");
466 printf("\t)\n");
467 }
469 for (i = 0; i < d_config->num_vifs; i++) {
470 printf("\t(device\n");
471 printf("\t\t(vif\n");
472 printf("\t\t\t(backend_domid %d)\n", d_config->vifs[i].backend_domid);
473 printf("\t\t\t(domid %d)\n", d_config->vifs[i].domid);
474 printf("\t\t\t(devid %d)\n", d_config->vifs[i].devid);
475 printf("\t\t\t(mtu %d)\n", d_config->vifs[i].mtu);
476 printf("\t\t\t(model %s)\n", d_config->vifs[i].model);
477 printf("\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n",
478 d_config->vifs[i].mac[0], d_config->vifs[i].mac[1],
479 d_config->vifs[i].mac[2], d_config->vifs[i].mac[3],
480 d_config->vifs[i].mac[4], d_config->vifs[i].mac[5]);
481 printf("\t\t)\n");
482 printf("\t)\n");
483 }
485 for (i = 0; i < d_config->num_pcidevs; i++) {
486 printf("\t(device\n");
487 printf("\t\t(pci\n");
488 printf("\t\t\t(pci dev "PCI_BDF_VDEVFN")\n",
489 d_config->pcidevs[i].domain, d_config->pcidevs[i].bus,
490 d_config->pcidevs[i].dev, d_config->pcidevs[i].func,
491 d_config->pcidevs[i].vdevfn);
492 printf("\t\t\t(opts msitranslate %d power_mgmt %d)\n",
493 d_config->pcidevs[i].msitranslate,
494 d_config->pcidevs[i].power_mgmt);
495 printf("\t\t)\n");
496 printf("\t)\n");
497 }
499 for (i = 0; i < d_config->num_vfbs; i++) {
500 printf("\t(device\n");
501 printf("\t\t(vfb\n");
502 printf("\t\t\t(backend_domid %d)\n", d_config->vfbs[i].backend_domid);
503 printf("\t\t\t(domid %d)\n", d_config->vfbs[i].domid);
504 printf("\t\t\t(devid %d)\n", d_config->vfbs[i].devid);
505 printf("\t\t\t(vnc %d)\n", d_config->vfbs[i].vnc);
506 printf("\t\t\t(vnclisten %s)\n", d_config->vfbs[i].vnclisten);
507 printf("\t\t\t(vncdisplay %d)\n", d_config->vfbs[i].vncdisplay);
508 printf("\t\t\t(vncunused %d)\n", d_config->vfbs[i].vncunused);
509 printf("\t\t\t(keymap %s)\n", d_config->vfbs[i].keymap);
510 printf("\t\t\t(sdl %d)\n", d_config->vfbs[i].sdl);
511 printf("\t\t\t(opengl %d)\n", d_config->vfbs[i].opengl);
512 printf("\t\t\t(display %s)\n", d_config->vfbs[i].display);
513 printf("\t\t\t(xauthority %s)\n", d_config->vfbs[i].xauthority);
514 printf("\t\t)\n");
515 printf("\t)\n");
516 }
517 printf(")\n");
518 }
520 static int parse_action_on_shutdown(const char *buf, enum action_on_shutdown *a)
521 {
522 int i;
523 const char *n;
525 for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
526 n = action_on_shutdown_names[i];
528 if (strcmp(buf, n) == 0) {
529 *a = i;
530 return 1;
531 }
532 }
533 return 0;
534 }
536 static void parse_config_data(const char *configfile_filename_report,
537 const char *configfile_data,
538 int configfile_len,
539 struct domain_config *d_config,
540 libxl_device_model_info *dm_info)
541 {
542 const char *buf;
543 long l;
544 XLU_Config *config;
545 XLU_ConfigList *vbds, *nics, *pcis, *cvfbs, *net2s;
546 int pci_power_mgmt = 0;
547 int pci_msitranslate = 1;
548 int e;
550 libxl_domain_create_info *c_info = &d_config->c_info;
551 libxl_domain_build_info *b_info = &d_config->b_info;
553 config= xlu_cfg_init(stderr, configfile_filename_report);
554 if (!config) {
555 fprintf(stderr, "Failed to allocate for configuration\n");
556 exit(1);
557 }
559 e= xlu_cfg_readdata(config, configfile_data, configfile_len);
560 if (e) {
561 fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
562 exit(1);
563 }
565 init_create_info(c_info);
567 c_info->hvm = 0;
568 if (!xlu_cfg_get_string (config, "builder", &buf) &&
569 !strncmp(buf, "hvm", strlen(buf)))
570 c_info->hvm = 1;
572 if (!xlu_cfg_get_long (config, "hap", &l))
573 c_info->hap = l;
575 if (!xlu_cfg_get_string (config, "name", &buf))
576 c_info->name = strdup(buf);
577 else
578 c_info->name = "test";
579 random_uuid(&c_info->uuid[0]);
581 if (!xlu_cfg_get_long(config, "oos", &l))
582 c_info->oos = l;
584 if (!xlu_cfg_get_string (config, "pool", &buf)) {
585 c_info->poolid = -1;
586 pool_qualifier_to_poolid(buf, &c_info->poolid, NULL);
587 }
588 c_info->poolname = libxl_poolid_to_name(&ctx, c_info->poolid);
589 if (!c_info->poolname) {
590 fprintf(stderr, "Illegal pool specified\n");
591 exit(1);
592 }
594 init_build_info(b_info, c_info);
596 /* the following is the actual config parsing with overriding values in the structures */
597 if (!xlu_cfg_get_long (config, "vcpus", &l)) {
598 b_info->max_vcpus = l;
599 b_info->cur_vcpus = (1 << l) - 1;
600 }
602 if (!xlu_cfg_get_long (config, "memory", &l)) {
603 b_info->max_memkb = l * 1024;
604 b_info->target_memkb = b_info->max_memkb;
605 }
607 if (xlu_cfg_get_string (config, "on_poweroff", &buf))
608 buf = "destroy";
609 if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
610 fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
611 exit(1);
612 }
614 if (xlu_cfg_get_string (config, "on_reboot", &buf))
615 buf = "restart";
616 if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
617 fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
618 exit(1);
619 }
621 if (xlu_cfg_get_string (config, "on_watchdog", &buf))
622 buf = "destroy";
623 if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
624 fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
625 exit(1);
626 }
629 if (xlu_cfg_get_string (config, "on_crash", &buf))
630 buf = "destroy";
631 if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
632 fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
633 exit(1);
634 }
636 /* libxl_get_required_shadow_memory() must be called after final values
637 * (default or specified) for vcpus and memory are set, because the
638 * calculation depends on those values. */
639 b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l)
640 ? l * 1024
641 : libxl_get_required_shadow_memory(b_info->max_memkb,
642 b_info->max_vcpus);
644 if (!xlu_cfg_get_long (config, "nomigrate", &l))
645 b_info->disable_migrate = l;
647 if (!xlu_cfg_get_long(config, "tsc_mode", &l))
648 b_info->tsc_mode = l;
650 if (!xlu_cfg_get_long (config, "videoram", &l))
651 b_info->video_memkb = l * 1024;
653 if (!xlu_cfg_get_string (config, "kernel", &buf))
654 b_info->kernel.path = strdup(buf);
656 if (c_info->hvm == 1) {
657 if (!xlu_cfg_get_long (config, "pae", &l))
658 b_info->u.hvm.pae = l;
659 if (!xlu_cfg_get_long (config, "apic", &l))
660 b_info->u.hvm.apic = l;
661 if (!xlu_cfg_get_long (config, "acpi", &l))
662 b_info->u.hvm.acpi = l;
663 if (!xlu_cfg_get_long (config, "nx", &l))
664 b_info->u.hvm.nx = l;
665 if (!xlu_cfg_get_long (config, "viridian", &l))
666 b_info->u.hvm.viridian = l;
667 if (!xlu_cfg_get_long (config, "hpet", &l))
668 b_info->u.hvm.hpet = l;
669 if (!xlu_cfg_get_long (config, "vpt_align", &l))
670 b_info->u.hvm.vpt_align = l;
671 if (!xlu_cfg_get_long (config, "timer_mode", &l))
672 b_info->u.hvm.timer_mode = l;
673 } else {
674 char *cmdline = NULL;
675 const char *root = NULL, *extra = "";
677 xlu_cfg_get_string (config, "root", &root);
678 xlu_cfg_get_string (config, "extra", &extra);
680 if (root) {
681 if (asprintf(&cmdline, "root=%s %s", root, extra) == -1)
682 cmdline = NULL;
683 } else {
684 cmdline = strdup(extra);
685 }
687 if ((root || extra) && !cmdline) {
688 fprintf(stderr, "Failed to allocate memory for cmdline\n");
689 exit(1);
690 }
692 if (!xlu_cfg_get_string (config, "bootloader", &buf))
693 b_info->u.pv.bootloader = strdup(buf);
694 if (!xlu_cfg_get_string (config, "bootloader_args", &buf))
695 b_info->u.pv.bootloader_args = strdup(buf);
697 if (!b_info->u.pv.bootloader && !b_info->kernel.path) {
698 fprintf(stderr, "Neither kernel nor bootloader specified\n");
699 exit(1);
700 }
702 b_info->u.pv.cmdline = cmdline;
703 if (!xlu_cfg_get_string (config, "ramdisk", &buf))
704 b_info->u.pv.ramdisk.path = strdup(buf);
705 }
707 if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
708 d_config->num_disks = 0;
709 d_config->disks = NULL;
710 while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
711 libxl_device_disk *disk;
712 char *buf2 = strdup(buf);
713 char *p, *p2;
715 d_config->disks = (libxl_device_disk *) realloc(d_config->disks, sizeof (libxl_device_disk) * (d_config->num_disks + 1));
716 disk = d_config->disks + d_config->num_disks;
718 disk->backend_domid = 0;
719 disk->domid = 0;
720 disk->unpluggable = 0;
722 p = strtok(buf2, ",:");
723 while (*p == ' ')
724 p++;
725 if (!strcmp(p, "phy")) {
726 disk->phystype = PHYSTYPE_PHY;
727 } else if (!strcmp(p, "file")) {
728 disk->phystype = PHYSTYPE_FILE;
729 } else if (!strcmp(p, "tap")) {
730 p = strtok(NULL, ":");
731 if (!strcmp(p, "aio")) {
732 disk->phystype = PHYSTYPE_AIO;
733 } else if (!strcmp(p, "vhd")) {
734 disk->phystype = PHYSTYPE_VHD;
735 } else if (!strcmp(p, "qcow")) {
736 disk->phystype = PHYSTYPE_QCOW;
737 } else if (!strcmp(p, "qcow2")) {
738 disk->phystype = PHYSTYPE_QCOW2;
739 }
740 }
741 p = strtok(NULL, ",");
742 while (*p == ' ')
743 p++;
744 disk->physpath= strdup(p);
745 p = strtok(NULL, ",");
746 while (*p == ' ')
747 p++;
748 p2 = strchr(p, ':');
749 if (p2 == NULL) {
750 disk->virtpath = strdup(p);
751 disk->is_cdrom = 0;
752 disk->unpluggable = 1;
753 } else {
754 *p2 = '\0';
755 disk->virtpath = strdup(p);
756 if (!strcmp(p2 + 1, "cdrom")) {
757 disk->is_cdrom = 1;
758 disk->unpluggable = 1;
759 } else
760 disk->is_cdrom = 0;
761 }
762 p = strtok(NULL, ",");
763 while (*p == ' ')
764 p++;
765 disk->readwrite = (p[0] == 'w') ? 1 : 0;
766 free(buf2);
767 d_config->num_disks++;
768 }
769 }
771 if (!xlu_cfg_get_list (config, "vif", &nics, 0)) {
772 d_config->num_vifs = 0;
773 d_config->vifs = NULL;
774 while ((buf = xlu_cfg_get_listitem (nics, d_config->num_vifs)) != NULL) {
775 libxl_device_nic *nic;
776 char *buf2 = strdup(buf);
777 char *p, *p2;
779 d_config->vifs = (libxl_device_nic *) realloc(d_config->vifs, sizeof (libxl_device_nic) * (d_config->num_vifs+1));
780 nic = d_config->vifs + d_config->num_vifs;
781 init_nic_info(nic, d_config->num_vifs);
783 p = strtok(buf2, ",");
784 if (!p)
785 goto skip;
786 do {
787 while (*p == ' ')
788 p++;
789 if ((p2 = strchr(p, '=')) == NULL)
790 break;
791 *p2 = '\0';
792 if (!strcmp(p, "model")) {
793 nic->model = strdup(p2 + 1);
794 } else if (!strcmp(p, "mac")) {
795 char *p3 = p2 + 1;
796 *(p3 + 2) = '\0';
797 nic->mac[0] = strtol(p3, NULL, 16);
798 p3 = p3 + 3;
799 *(p3 + 2) = '\0';
800 nic->mac[1] = strtol(p3, NULL, 16);
801 p3 = p3 + 3;
802 *(p3 + 2) = '\0';
803 nic->mac[2] = strtol(p3, NULL, 16);
804 p3 = p3 + 3;
805 *(p3 + 2) = '\0';
806 nic->mac[3] = strtol(p3, NULL, 16);
807 p3 = p3 + 3;
808 *(p3 + 2) = '\0';
809 nic->mac[4] = strtol(p3, NULL, 16);
810 p3 = p3 + 3;
811 *(p3 + 2) = '\0';
812 nic->mac[5] = strtol(p3, NULL, 16);
813 } else if (!strcmp(p, "bridge")) {
814 nic->bridge = strdup(p2 + 1);
815 } else if (!strcmp(p, "type")) {
816 if (!strcmp(p2 + 1, "ioemu"))
817 nic->nictype = NICTYPE_IOEMU;
818 else
819 nic->nictype = NICTYPE_VIF;
820 } else if (!strcmp(p, "ip")) {
821 inet_pton(AF_INET, p2 + 1, &nic->ip);
822 } else if (!strcmp(p, "script")) {
823 nic->script = strdup(p2 + 1);
824 } else if (!strcmp(p, "vifname")) {
825 nic->ifname = strdup(p2 + 1);
826 } else if (!strcmp(p, "rate")) {
827 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
828 } else if (!strcmp(p, "accel")) {
829 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
830 }
831 } while ((p = strtok(NULL, ",")) != NULL);
832 skip:
833 free(buf2);
834 d_config->num_vifs++;
835 }
836 }
838 if (!xlu_cfg_get_list(config, "vif2", &net2s, 0)) {
839 d_config->num_vif2s = 0;
840 d_config->vif2s = NULL;
841 while ((buf = xlu_cfg_get_listitem(net2s, d_config->num_vif2s))) {
842 libxl_device_net2 *net2;
843 char *buf2 = strdup(buf);
844 char *p;
846 d_config->vif2s = realloc(d_config->vif2s, sizeof (libxl_device_net2) * (d_config->num_vif2s + 1));
847 net2 = d_config->vif2s + d_config->num_vif2s;
849 init_net2_info(net2, d_config->num_vif2s);
851 for (p = strtok(buf2, ","); p; p = strtok(buf2, ",")) {
852 while (isblank(*p))
853 p++;
854 if (!strncmp("front_mac=", p, 10)) {
855 libxl_strtomac(p + 10, net2->front_mac);
856 } else if (!strncmp("back_mac=", p, 9)) {
857 libxl_strtomac(p + 9, net2->back_mac);
858 } else if (!strncmp("backend=", p, 8)) {
859 domain_qualifier_to_domid(p + 8, &net2->backend_domid, 0);
860 } else if (!strncmp("trusted=", p, 8)) {
861 net2->trusted = (*(p + 8) == '1');
862 } else if (!strncmp("back_trusted=", p, 13)) {
863 net2->back_trusted = (*(p + 13) == '1');
864 } else if (!strncmp("bridge=", p, 7)) {
865 net2->bridge = strdup(p + 13);
866 } else if (!strncmp("filter_mac=", p, 11)) {
867 net2->filter_mac = (*(p + 11) == '1');
868 } else if (!strncmp("front_filter_mac=", p, 17)) {
869 net2->front_filter_mac = (*(p + 17) == '1');
870 } else if (!strncmp("pdev=", p, 5)) {
871 net2->pdev = strtoul(p + 5, NULL, 10);
872 } else if (!strncmp("max_bypasses=", p, 13)) {
873 net2->max_bypasses = strtoul(p + 13, NULL, 10);
874 }
875 }
876 free(buf2);
877 d_config->num_vif2s++;
878 }
879 }
881 if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
882 d_config->num_vfbs = 0;
883 d_config->num_vkbs = 0;
884 d_config->vfbs = NULL;
885 d_config->vkbs = NULL;
886 while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
887 libxl_device_vfb *vfb;
888 libxl_device_vkb *vkb;
890 char *buf2 = strdup(buf);
891 char *p, *p2;
893 d_config->vfbs = (libxl_device_vfb *) realloc(d_config->vfbs, sizeof(libxl_device_vfb) * (d_config->num_vfbs + 1));
894 vfb = d_config->vfbs + d_config->num_vfbs;
895 init_vfb_info(vfb, d_config->num_vfbs);
897 d_config->vkbs = (libxl_device_vkb *) realloc(d_config->vkbs, sizeof(libxl_device_vkb) * (d_config->num_vkbs + 1));
898 vkb = d_config->vkbs + d_config->num_vkbs;
899 init_vkb_info(vkb, d_config->num_vkbs);
901 p = strtok(buf2, ",");
902 if (!p)
903 goto skip_vfb;
904 do {
905 while (*p == ' ')
906 p++;
907 if ((p2 = strchr(p, '=')) == NULL)
908 break;
909 *p2 = '\0';
910 if (!strcmp(p, "vnc")) {
911 vfb->vnc = atoi(p2 + 1);
912 } else if (!strcmp(p, "vnclisten")) {
913 vfb->vnclisten = strdup(p2 + 1);
914 } else if (!strcmp(p, "vncpasswd")) {
915 vfb->vncpasswd = strdup(p2 + 1);
916 } else if (!strcmp(p, "vncdisplay")) {
917 vfb->vncdisplay = atoi(p2 + 1);
918 } else if (!strcmp(p, "vncunused")) {
919 vfb->vncunused = atoi(p2 + 1);
920 } else if (!strcmp(p, "keymap")) {
921 vfb->keymap = strdup(p2 + 1);
922 } else if (!strcmp(p, "sdl")) {
923 vfb->sdl = atoi(p2 + 1);
924 } else if (!strcmp(p, "opengl")) {
925 vfb->opengl = atoi(p2 + 1);
926 } else if (!strcmp(p, "display")) {
927 vfb->display = strdup(p2 + 1);
928 } else if (!strcmp(p, "xauthority")) {
929 vfb->xauthority = strdup(p2 + 1);
930 }
931 } while ((p = strtok(NULL, ",")) != NULL);
932 skip_vfb:
933 free(buf2);
934 d_config->num_vfbs++;
935 d_config->num_vkbs++;
936 }
937 }
939 if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
940 pci_msitranslate = l;
942 if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
943 pci_power_mgmt = l;
945 if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
946 d_config->num_pcidevs = 0;
947 d_config->pcidevs = NULL;
948 while ((buf = xlu_cfg_get_listitem (pcis, d_config->num_pcidevs)) != NULL) {
949 libxl_device_pci *pcidev;
950 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
951 char *buf2 = strdup(buf);
952 char *p;
954 d_config->pcidevs = (libxl_device_pci *) realloc(d_config->pcidevs, sizeof (libxl_device_pci) * (d_config->num_pcidevs + 1));
955 pcidev = d_config->pcidevs + d_config->num_pcidevs;
956 memset(pcidev, 0x00, sizeof(libxl_device_pci));
958 p = strtok(buf2, ",");
959 if (!p)
960 goto skip_pci;
961 if (sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, &vdevfn) < 4) {
962 domain = 0;
963 if (sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn) < 3) {
964 fprintf(stderr,"xl: Unable to parse pci bdf (%s)\n", p);
965 goto skip_pci;
966 }
967 }
969 libxl_device_pci_init(pcidev, domain, bus, dev, func, vdevfn);
970 pcidev->msitranslate = pci_msitranslate;
971 pcidev->power_mgmt = pci_power_mgmt;
972 while ((p = strtok(NULL, ",=")) != NULL) {
973 while (*p == ' ')
974 p++;
975 if (!strcmp(p, "msitranslate")) {
976 p = strtok(NULL, ",=");
977 pcidev->msitranslate = atoi(p);
978 } else if (!strcmp(p, "power_mgmt")) {
979 p = strtok(NULL, ",=");
980 pcidev->power_mgmt = atoi(p);
981 }
982 }
983 d_config->num_pcidevs++;
984 skip_pci:
985 free(buf2);
986 }
987 }
989 if (c_info->hvm == 1) {
990 /* init dm from c and b */
991 init_dm_info(dm_info, c_info, b_info);
993 /* then process config related to dm */
994 if (!xlu_cfg_get_string (config, "device_model", &buf))
995 dm_info->device_model = strdup(buf);
996 if (!xlu_cfg_get_long (config, "stdvga", &l))
997 dm_info->stdvga = l;
998 if (!xlu_cfg_get_long (config, "vnc", &l))
999 dm_info->vnc = l;
1000 if (!xlu_cfg_get_string (config, "vnclisten", &buf))
1001 dm_info->vnclisten = strdup(buf);
1002 if (!xlu_cfg_get_string (config, "vncpasswd", &buf))
1003 dm_info->vncpasswd = strdup(buf);
1004 if (!xlu_cfg_get_long (config, "vncdisplay", &l))
1005 dm_info->vncdisplay = l;
1006 if (!xlu_cfg_get_long (config, "vncunused", &l))
1007 dm_info->vncunused = l;
1008 if (!xlu_cfg_get_string (config, "keymap", &buf))
1009 dm_info->keymap = strdup(buf);
1010 if (!xlu_cfg_get_long (config, "sdl", &l))
1011 dm_info->sdl = l;
1012 if (!xlu_cfg_get_long (config, "opengl", &l))
1013 dm_info->opengl = l;
1014 if (!xlu_cfg_get_long (config, "nographic", &l))
1015 dm_info->nographic = l;
1016 if (!xlu_cfg_get_string (config, "serial", &buf))
1017 dm_info->serial = strdup(buf);
1018 if (!xlu_cfg_get_string (config, "boot", &buf))
1019 dm_info->boot = strdup(buf);
1020 if (!xlu_cfg_get_long (config, "usb", &l))
1021 dm_info->usb = l;
1022 if (!xlu_cfg_get_string (config, "usbdevice", &buf))
1023 dm_info->usbdevice = strdup(buf);
1024 if (!xlu_cfg_get_string (config, "soundhw", &buf))
1025 dm_info->soundhw = strdup(buf);
1026 if (!xlu_cfg_get_long (config, "xen_platform_pci", &l))
1027 dm_info->xen_platform_pci = l;
1030 dm_info->type = c_info->hvm ? XENFV : XENPV;
1032 xlu_cfg_destroy(config);
1035 static void *xmalloc(size_t sz) {
1036 void *r;
1037 r = malloc(sz);
1038 if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
1039 (unsigned long)sz); exit(-ERROR_FAIL); }
1040 return r;
1043 static void *xrealloc(void *ptr, size_t sz) {
1044 void *r;
1045 if (!sz) { free(ptr); return 0; }
1046 /* realloc(non-0, 0) has a useless return value;
1047 * but xrealloc(anything, 0) is like free
1048 */
1049 r = realloc(ptr, sz);
1050 if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
1051 (unsigned long)sz); exit(-ERROR_FAIL); }
1052 return r;
1055 int autoconnect_console(int hvm)
1057 int status, options;
1058 pid_t pid, r;
1060 /*
1061 * Fork for xenconsole. We exec xenconsole in the foreground
1062 * process allowing it to retain the tty. xl continues in the
1063 * child. The xenconsole client uses a xenstore watch to wait for
1064 * the console to be setup so there is no race.
1065 */
1066 pid = fork();
1067 if (pid < 0) {
1068 perror("unable to fork xenconsole");
1069 return ERROR_FAIL;
1070 } else if (pid == 0)
1071 return 0;
1073 /*
1074 * In the PV case we only catch failure of the create process, in
1075 * the HVM case we also wait for the creation process to be
1076 * completed so that the stubdom is already up and running and we
1077 * can connect to it.
1078 */
1079 if (hvm)
1080 options = 0;
1081 else
1082 options = WNOHANG;
1083 sleep(1);
1084 r = waitpid(pid, &status, options);
1085 if (r > 0 && WIFEXITED(status) && WEXITSTATUS(status) != 0)
1086 _exit(WEXITSTATUS(status));
1088 libxl_primary_console_exec(&ctx, domid);
1089 /* Do not return. xl continued in child process */
1090 fprintf(stderr, "Unable to attach console\n");
1091 _exit(1);
1094 /* Returns 1 if domain should be restarted, 2 if domain should be renamed then restarted */
1095 static int handle_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1096 struct domain_config *d_config, libxl_dominfo *info)
1098 int restart = 0;
1099 enum action_on_shutdown action;
1101 switch (info->shutdown_reason) {
1102 case SHUTDOWN_poweroff:
1103 action = d_config->on_poweroff;
1104 break;
1105 case SHUTDOWN_reboot:
1106 action = d_config->on_reboot;
1107 break;
1108 case SHUTDOWN_suspend:
1109 return 0;
1110 case SHUTDOWN_crash:
1111 action = d_config->on_crash;
1112 break;
1113 case SHUTDOWN_watchdog:
1114 action = d_config->on_watchdog;
1115 break;
1116 default:
1117 LOG("Unknown shutdown reason code %s. Destroying domain.", info->shutdown_reason);
1118 action = ACTION_DESTROY;
1121 LOG("Action for shutdown reason code %d is %s", info->shutdown_reason, action_on_shutdown_names[action]);
1123 if (action == ACTION_COREDUMP_DESTROY || action == ACTION_COREDUMP_RESTART) {
1124 char *corefile;
1125 int rc;
1127 if (asprintf(&corefile, "/var/xen/dump/%s", d_config->c_info.name) < 0) {
1128 LOG("failed to construct core dump path");
1129 } else {
1130 LOG("dumping core to %s", corefile);
1131 rc=libxl_domain_core_dump(ctx, domid, corefile);
1132 if (rc) LOG("core dump failed (rc=%d).", rc);
1134 /* No point crying over spilled milk, continue on failure. */
1136 if (action == ACTION_COREDUMP_DESTROY)
1137 action = ACTION_DESTROY;
1138 else
1139 action = ACTION_RESTART;
1142 switch (action) {
1143 case ACTION_PRESERVE:
1144 break;
1146 case ACTION_RESTART_RENAME:
1147 restart = 2;
1148 break;
1150 case ACTION_RESTART:
1151 restart = 1;
1152 /* fall-through */
1153 case ACTION_DESTROY:
1154 LOG("Domain %d needs to be cleaned up: destroying the domain", domid);
1155 libxl_domain_destroy(ctx, domid, 0);
1156 break;
1158 case ACTION_COREDUMP_DESTROY:
1159 case ACTION_COREDUMP_RESTART:
1160 /* Already handled these above. */
1161 abort();
1164 return restart;
1167 static int preserve_domain(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1168 struct domain_config *d_config, libxl_dominfo *info)
1170 time_t now;
1171 struct tm tm;
1172 char stime[24];
1174 uint8_t new_uuid[16];
1176 int rc;
1178 now = time(NULL);
1179 if (now == ((time_t) -1)) {
1180 LOG("Failed to get current time for domain rename");
1181 return 0;
1184 tzset();
1185 if (gmtime_r(&now, &tm) == NULL) {
1186 LOG("Failed to convert time to UTC");
1187 return 0;
1190 if (!strftime(&stime[0], sizeof(stime), "-%Y%m%dT%H%MZ", &tm)) {
1191 LOG("Failed to format time as a string");
1192 return 0;
1195 random_uuid(&new_uuid[0]);
1197 LOG("Preserving domain %d %s with suffix%s", domid, d_config->c_info.name, stime);
1198 rc = libxl_domain_preserve(ctx, domid, &d_config->c_info, stime, new_uuid);
1200 return rc == 0 ? 1 : 0;
1203 struct domain_create {
1204 int debug;
1205 int daemonize;
1206 int paused;
1207 int dryrun;
1208 int quiet;
1209 int console_autoconnect;
1210 const char *config_file;
1211 const char *extra_config; /* extra config string */
1212 const char *restore_file;
1213 int migrate_fd; /* -1 means none */
1214 char **migration_domname_r;
1215 };
1217 static int create_domain(struct domain_create *dom_info)
1219 struct domain_config d_config;
1221 libxl_domain_build_state state;
1222 libxl_device_model_info dm_info;
1223 libxl_device_console console;
1225 int debug = dom_info->debug;
1226 int daemonize = dom_info->daemonize;
1227 int paused = dom_info->paused;
1228 const char *config_file = dom_info->config_file;
1229 const char *extra_config = dom_info->extra_config;
1230 const char *restore_file = dom_info->restore_file;
1231 int migrate_fd = dom_info->migrate_fd;
1232 char **migration_domname_r = dom_info->migration_domname_r;
1234 int i, fd;
1235 int need_daemon = 1;
1236 int ret, rc;
1237 libxl_device_model_starting *dm_starting = 0;
1238 libxl_waiter *w1 = NULL, *w2 = NULL;
1239 void *config_data = 0;
1240 int config_len = 0;
1241 int restore_fd = -1;
1242 struct save_file_header hdr;
1244 memset(&d_config, 0x00, sizeof(d_config));
1245 memset(&dm_info, 0x00, sizeof(dm_info));
1247 if (restore_file) {
1248 uint8_t *optdata_begin = 0;
1249 const uint8_t *optdata_here = 0;
1250 union { uint32_t u32; char b[4]; } u32buf;
1251 uint32_t badflags;
1253 restore_fd = migrate_fd >= 0 ? migrate_fd :
1254 open(restore_file, O_RDONLY);
1256 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
1257 sizeof(hdr), restore_file, "header") );
1258 if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
1259 fprintf(stderr, "File has wrong magic number -"
1260 " corrupt or for a different tool?\n");
1261 return ERROR_INVAL;
1263 if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
1264 fprintf(stderr, "File has wrong byte order\n");
1265 return ERROR_INVAL;
1267 fprintf(stderr, "Loading new save file %s"
1268 " (new xl fmt info"
1269 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
1270 restore_file, hdr.mandatory_flags, hdr.optional_flags,
1271 hdr.optional_data_len);
1273 badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
1274 if (badflags) {
1275 fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
1276 "which are not supported; need newer xl\n",
1277 badflags);
1278 return ERROR_INVAL;
1280 if (hdr.optional_data_len) {
1281 optdata_begin = xmalloc(hdr.optional_data_len);
1282 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
1283 hdr.optional_data_len, restore_file, "optdata") );
1286 #define OPTDATA_LEFT (hdr.optional_data_len - (optdata_here - optdata_begin))
1287 #define WITH_OPTDATA(amt, body) \
1288 if (OPTDATA_LEFT < (amt)) { \
1289 fprintf(stderr, "Savefile truncated.\n"); \
1290 return ERROR_INVAL; \
1291 } else { \
1292 body; \
1293 optdata_here += (amt); \
1296 optdata_here = optdata_begin;
1298 if (OPTDATA_LEFT) {
1299 fprintf(stderr, " Savefile contains xl domain config\n");
1300 WITH_OPTDATA(4, {
1301 memcpy(u32buf.b, optdata_here, 4);
1302 config_len = u32buf.u32;
1303 });
1304 WITH_OPTDATA(config_len, {
1305 config_data = xmalloc(config_len);
1306 memcpy(config_data, optdata_here, config_len);
1307 });
1312 if (config_file) {
1313 free(config_data); config_data = 0;
1314 ret = libxl_read_file_contents(&ctx, config_file,
1315 &config_data, &config_len);
1316 if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
1317 config_file, strerror(errno)); return ERROR_FAIL; }
1318 if (!restore_file && extra_config
1319 && strlen(extra_config)) {
1320 if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
1321 fprintf(stderr, "Failed to attach extra configration\n");
1322 return ERROR_FAIL;
1324 config_data = realloc(config_data, config_len
1325 + strlen(extra_config) + 2);
1326 if (!config_data) {
1327 fprintf(stderr, "Failed to realloc config_data\n");
1328 return ERROR_FAIL;
1330 strcat(config_data, "\n");
1331 strcat(config_data, extra_config);
1332 strcat(config_data, "\n");
1333 config_len += (strlen(extra_config) + 2);
1335 } else {
1336 if (!config_data) {
1337 fprintf(stderr, "Config file not specified and"
1338 " none in save file\n");
1339 return ERROR_INVAL;
1341 config_file = "<saved>";
1344 if (!dom_info->quiet)
1345 printf("Parsing config file %s\n", config_file);
1347 parse_config_data(config_file, config_data, config_len, &d_config, &dm_info);
1349 if (dom_info->dryrun)
1350 return 0;
1352 if (migrate_fd >= 0) {
1353 if (d_config.c_info.name) {
1354 /* when we receive a domain we get its name from the config
1355 * file; and we receive it to a temporary name */
1356 assert(!common_domname);
1357 common_domname = d_config.c_info.name;
1358 if (asprintf(migration_domname_r, "%s--incoming", d_config.c_info.name) < 0) {
1359 fprintf(stderr, "Failed to allocate memory in asprintf\n");
1360 exit(1);
1362 d_config.c_info.name = *migration_domname_r;
1366 if (debug)
1367 printf_info(-1, &d_config, &dm_info);
1369 start:
1370 domid = 0;
1372 ret = libxl_domain_make(&ctx, &d_config.c_info, &domid);
1373 if (ret) {
1374 fprintf(stderr, "cannot make domain: %d\n", ret);
1375 ret = ERROR_FAIL;
1376 goto error_out;
1379 ret = libxl_userdata_store(&ctx, domid, "xl",
1380 config_data, config_len);
1381 if (ret) {
1382 perror("cannot save config file");
1383 ret = ERROR_FAIL;
1384 goto error_out;
1387 if (dom_info->console_autoconnect) {
1388 ret = autoconnect_console(d_config.c_info.hvm);
1389 if (ret)
1390 goto error_out;
1393 /*
1394 * Do not attempt to reconnect if we come round again due to a
1395 * guest reboot -- the stdin/out will be disconnected by then.
1396 */
1397 dom_info->console_autoconnect = 0;
1399 ret = libxl_run_bootloader(&ctx, &d_config.b_info, d_config.num_disks > 0 ? &d_config.disks[0] : NULL, domid);
1400 if (ret) {
1401 fprintf(stderr, "failed to run bootloader: %d\n", ret);
1402 goto error_out;
1405 if (!restore_file || !need_daemon) {
1406 if (dm_info.saved_state) {
1407 free(dm_info.saved_state);
1408 dm_info.saved_state = NULL;
1410 ret = libxl_domain_build(&ctx, &d_config.b_info, domid, &state);
1411 } else {
1412 ret = libxl_domain_restore(&ctx, &d_config.b_info, domid, restore_fd, &state, &dm_info);
1415 if (ret) {
1416 fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
1417 ret = ERROR_FAIL;
1418 goto error_out;
1421 for (i = 0; i < d_config.num_disks; i++) {
1422 d_config.disks[i].domid = domid;
1423 ret = libxl_device_disk_add(&ctx, domid, &d_config.disks[i]);
1424 if (ret) {
1425 fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
1426 ret = ERROR_FAIL;
1427 goto error_out;
1430 for (i = 0; i < d_config.num_vifs; i++) {
1431 d_config.vifs[i].domid = domid;
1432 ret = libxl_device_nic_add(&ctx, domid, &d_config.vifs[i]);
1433 if (ret) {
1434 fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
1435 ret = ERROR_FAIL;
1436 goto error_out;
1439 if (!d_config.c_info.hvm) {
1440 for (i = 0; i < d_config.num_vif2s; i++) {
1441 d_config.vif2s[i].domid = domid;
1442 ret = libxl_device_net2_add(&ctx, domid, &d_config.vif2s[i]);
1443 if (ret) {
1444 fprintf(stderr, "cannot add net2 %d to domain: %d\n", i, ret);
1445 ret = ERROR_FAIL;
1446 goto error_out;
1450 if (d_config.c_info.hvm) {
1451 dm_info.domid = domid;
1452 MUST( libxl_create_device_model(&ctx, &dm_info,
1453 d_config.disks, d_config.num_disks,
1454 d_config.vifs, d_config.num_vifs,
1455 &dm_starting) );
1456 } else {
1457 for (i = 0; i < d_config.num_vfbs; i++) {
1458 d_config.vfbs[i].domid = domid;
1459 libxl_device_vfb_add(&ctx, domid, &d_config.vfbs[i]);
1460 d_config.vkbs[i].domid = domid;
1461 libxl_device_vkb_add(&ctx, domid, &d_config.vkbs[i]);
1463 init_console_info(&console, 0, &state);
1464 console.domid = domid;
1465 if (d_config.num_vfbs)
1466 console.constype = CONSTYPE_IOEMU;
1467 libxl_device_console_add(&ctx, domid, &console);
1468 if (d_config.num_vfbs)
1469 libxl_create_xenpv_qemu(&ctx, d_config.vfbs, 1, &console, &dm_starting);
1472 if (dm_starting)
1473 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
1474 for (i = 0; i < d_config.num_pcidevs; i++)
1475 libxl_device_pci_add(&ctx, domid, &d_config.pcidevs[i]);
1477 if (!paused)
1478 libxl_domain_unpause(&ctx, domid);
1480 if (!daemonize)
1481 return domid; /* caller gets success in parent */
1483 if (need_daemon) {
1484 char *fullname, *name;
1485 pid_t child1, got_child;
1486 int nullfd;
1488 child1 = libxl_fork(&ctx);
1489 if (child1) {
1490 int status;
1491 for (;;) {
1492 got_child = waitpid(child1, &status, 0);
1493 if (got_child == child1) break;
1494 assert(got_child == -1);
1495 if (errno != EINTR) {
1496 perror("failed to wait for daemonizing child");
1497 ret = ERROR_FAIL;
1498 goto error_out;
1501 if (status) {
1502 libxl_report_child_exitstatus(&ctx, XTL_ERROR,
1503 "daemonizing child", child1, status);
1504 ret = ERROR_FAIL;
1505 goto error_out;
1507 return domid; /* caller gets success in parent */
1510 rc = libxl_ctx_postfork(&ctx);
1511 if (rc) {
1512 LOG("failed to reinitialise context after fork");
1513 exit(-1);
1516 if (asprintf(&name, "xl-%s", d_config.c_info.name) < 0) {
1517 LOG("Failed to allocate memory in asprintf");
1518 exit(1);
1520 rc = libxl_create_logfile(&ctx, name, &fullname);
1521 if (rc) {
1522 LOG("failed to open logfile %s",fullname,strerror(errno));
1523 exit(-1);
1526 CHK_ERRNO(( logfile = open(fullname, O_WRONLY|O_CREAT, 0644) )<0);
1527 free(fullname);
1528 free(name);
1530 CHK_ERRNO(( nullfd = open("/dev/null", O_RDONLY) )<0);
1531 dup2(nullfd, 0);
1532 dup2(logfile, 1);
1533 dup2(logfile, 2);
1535 CHK_ERRNO(daemon(0, 1) < 0);
1536 need_daemon = 0;
1538 LOG("Waiting for domain %s (domid %d) to die [pid %ld]",
1539 d_config.c_info.name, domid, (long)getpid());
1540 w1 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter) * d_config.num_disks);
1541 w2 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter));
1542 libxl_wait_for_disk_ejects(&ctx, domid, d_config.disks, d_config.num_disks, w1);
1543 libxl_wait_for_domain_death(&ctx, domid, w2);
1544 libxl_get_wait_fd(&ctx, &fd);
1545 while (1) {
1546 int ret;
1547 fd_set rfds;
1548 libxl_dominfo info;
1549 libxl_event event;
1550 libxl_device_disk disk;
1552 FD_ZERO(&rfds);
1553 FD_SET(fd, &rfds);
1555 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
1556 if (!ret)
1557 continue;
1558 libxl_get_event(&ctx, &event);
1559 switch (event.type) {
1560 case LIBXL_EVENT_DOMAIN_DEATH:
1561 ret = libxl_event_get_domain_death_info(&ctx, domid, &event, &info);
1563 if (ret < 0) continue;
1565 LOG("Domain %d is dead", domid);
1567 if (ret) {
1568 switch (handle_domain_death(&ctx, domid, &event, &d_config, &info)) {
1569 case 2:
1570 if (!preserve_domain(&ctx, domid, &event, &d_config, &info))
1571 /* If we fail then exit leaving the old domain in place. */
1572 exit(-1);
1574 /* Otherwise fall through and restart. */
1575 case 1:
1577 libxl_free_waiter(w1);
1578 libxl_free_waiter(w2);
1579 free(w1);
1580 free(w2);
1581 /*
1582 * XXX FIXME: If this sleep is not there then domain
1583 * re-creation fails sometimes.
1584 */
1585 LOG("Done. Rebooting now");
1586 sleep(2);
1587 goto start;
1588 case 0:
1589 LOG("Done. Exiting now");
1590 exit(0);
1593 break;
1594 case LIBXL_EVENT_DISK_EJECT:
1595 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
1596 libxl_cdrom_insert(&ctx, domid, &disk);
1597 break;
1599 libxl_free_event(&event);
1602 close(logfile);
1603 exit(0);
1605 error_out:
1606 if (domid)
1607 libxl_domain_destroy(&ctx, domid, 0);
1608 return ret;
1611 void help(char *command)
1613 int i;
1614 struct cmd_spec *cmd;
1616 if (!command || !strcmp(command, "help")) {
1617 printf("Usage xl [-v] <subcommand> [args]\n\n");
1618 printf("xl full list of subcommands:\n\n");
1619 for (i = 0; i < cmdtable_len; i++)
1620 printf(" %-20s%s\n",
1621 cmd_table[i].cmd_name, cmd_table[i].cmd_desc);
1622 } else {
1623 cmd = cmdtable_lookup(command);
1624 if (cmd) {
1625 printf("Usage: xl [-v] %s %s\n\n%s.\n\n",
1626 cmd->cmd_name,
1627 cmd->cmd_usage,
1628 cmd->cmd_desc);
1629 if (cmd->cmd_option)
1630 printf("Options:\n\n%s\n", cmd->cmd_option);
1632 else {
1633 printf("command \"%s\" not implemented\n", command);
1638 static int64_t parse_mem_size_kb(char *mem)
1640 char *endptr;
1641 int64_t kbytes;
1643 kbytes = strtoll(mem, &endptr, 10);
1645 if (strlen(endptr) > 1)
1646 return -1;
1648 switch (tolower((uint8_t)*endptr)) {
1649 case 't':
1650 kbytes <<= 10;
1651 case 'g':
1652 kbytes <<= 10;
1653 case '\0':
1654 case 'm':
1655 kbytes <<= 10;
1656 case 'k':
1657 break;
1658 case 'b':
1659 kbytes >>= 10;
1660 break;
1661 default:
1662 return -1;
1665 return kbytes;
1668 int set_memory_max(char *p, char *mem)
1670 int64_t memorykb;
1671 int rc;
1673 find_domain(p);
1675 memorykb = parse_mem_size_kb(mem);
1676 if (memorykb == -1) {
1677 fprintf(stderr, "invalid memory size: %s\n", mem);
1678 exit(3);
1681 rc = libxl_domain_setmaxmem(&ctx, domid, memorykb);
1683 return rc;
1686 int main_memmax(int argc, char **argv)
1688 int opt = 0;
1689 char *p = NULL, *mem;
1690 int rc;
1692 while ((opt = getopt(argc, argv, "h")) != -1) {
1693 switch (opt) {
1694 case 'h':
1695 help("mem-max");
1696 exit(0);
1697 default:
1698 fprintf(stderr, "option not supported\n");
1699 break;
1702 if (optind >= argc - 1) {
1703 help("mem-max");
1704 exit(2);
1707 p = argv[optind];
1708 mem = argv[optind + 1];
1710 rc = set_memory_max(p, mem);
1711 if (rc) {
1712 fprintf(stderr, "cannot set domid %d static max memory to : %s\n", domid, mem);
1713 exit(1);
1716 exit(0);
1719 void set_memory_target(char *p, char *mem)
1721 long long int memorykb;
1723 find_domain(p);
1725 memorykb = parse_mem_size_kb(mem);
1726 if (memorykb == -1) {
1727 fprintf(stderr, "invalid memory size: %s\n", mem);
1728 exit(3);
1731 libxl_set_memory_target(&ctx, domid, memorykb, /* enforce */ 1);
1734 int main_memset(int argc, char **argv)
1736 int opt = 0;
1737 char *p = NULL, *mem;
1739 while ((opt = getopt(argc, argv, "h:")) != -1) {
1740 switch (opt) {
1741 case 'h':
1742 help("mem-set");
1743 exit(0);
1744 default:
1745 fprintf(stderr, "option not supported\n");
1746 break;
1749 if (optind >= argc - 1) {
1750 help("mem-set");
1751 exit(2);
1754 p = argv[optind];
1755 mem = argv[optind + 1];
1757 set_memory_target(p, mem);
1758 exit(0);
1761 void cd_insert(char *dom, char *virtdev, char *phys)
1763 libxl_device_disk disk;
1764 char *p;
1766 find_domain(dom);
1768 disk.backend_domid = 0;
1769 disk.domid = domid;
1770 if (phys) {
1771 p = strchr(phys, ':');
1772 if (!p) {
1773 fprintf(stderr, "No type specified, ");
1774 disk.physpath = phys;
1775 if (!strncmp(phys, "/dev", 4)) {
1776 fprintf(stderr, "assuming phy:\n");
1777 disk.phystype = PHYSTYPE_PHY;
1778 } else {
1779 fprintf(stderr, "assuming file:\n");
1780 disk.phystype = PHYSTYPE_FILE;
1782 } else {
1783 *p = '\0';
1784 p++;
1785 disk.physpath = p;
1786 libxl_string_to_phystype(&ctx, phys, &disk.phystype);
1788 } else {
1789 disk.physpath = NULL;
1790 disk.phystype = 0;
1792 disk.virtpath = virtdev;
1793 disk.unpluggable = 1;
1794 disk.readwrite = 0;
1795 disk.is_cdrom = 1;
1797 libxl_cdrom_insert(&ctx, domid, &disk);
1800 int main_cd_eject(int argc, char **argv)
1802 int opt = 0;
1803 char *p = NULL, *virtdev;
1805 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1806 switch (opt) {
1807 case 'h':
1808 help("cd-eject");
1809 exit(0);
1810 default:
1811 fprintf(stderr, "option not supported\n");
1812 break;
1815 if (optind >= argc - 1) {
1816 help("cd-eject");
1817 exit(2);
1820 p = argv[optind];
1821 virtdev = argv[optind + 1];
1823 cd_insert(p, virtdev, NULL);
1824 exit(0);
1827 int main_cd_insert(int argc, char **argv)
1829 int opt = 0;
1830 char *p = NULL, *file = NULL, *virtdev;
1832 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1833 switch (opt) {
1834 case 'h':
1835 help("cd-insert");
1836 exit(0);
1837 default:
1838 fprintf(stderr, "option not supported\n");
1839 break;
1842 if (optind >= argc - 2) {
1843 help("cd-insert");
1844 exit(2);
1847 p = argv[optind];
1848 virtdev = argv[optind + 1];
1849 file = argv[optind + 2];
1851 cd_insert(p, virtdev, file);
1852 exit(0);
1855 int main_console(int argc, char **argv)
1857 int opt = 0;
1859 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1860 switch (opt) {
1861 case 'h':
1862 help("console");
1863 exit(0);
1864 default:
1865 fprintf(stderr, "option not supported\n");
1866 break;
1869 if (optind >= argc) {
1870 help("console");
1871 exit(2);
1874 find_domain(argv[optind]);
1875 libxl_primary_console_exec(&ctx, domid);
1876 fprintf(stderr, "Unable to attach console\n");
1877 return 1;
1880 static int vncviewer(const char *domain_spec, int autopass)
1882 find_domain(domain_spec);
1883 libxl_vncviewer_exec(&ctx, domid, autopass);
1884 fprintf(stderr, "Unable to execute vncviewer\n");
1885 return 1;
1888 int main_vncviewer(int argc, char **argv)
1890 static const struct option long_options[] = {
1891 {"autopass", 0, 0, 'a'},
1892 {"vncviewer-autopass", 0, 0, 'a'},
1893 {"help", 0, 0, 'h'},
1894 {0, 0, 0, 0}
1895 };
1896 int opt, autopass = 0;
1898 while (1) {
1899 opt = getopt_long(argc, argv, "ah", long_options, NULL);
1900 if (opt == -1)
1901 break;
1903 switch (opt) {
1904 case 'a':
1905 autopass = 1;
1906 break;
1907 case 'h':
1908 help("vncviewer");
1909 exit(0);
1910 default:
1911 fprintf(stderr, "option not supported\n");
1912 break;
1916 if (argc - optind != 1) {
1917 help("vncviewer");
1918 exit(2);
1921 if (vncviewer(argv[optind], autopass))
1922 exit(1);
1923 exit(0);
1926 void pcilist_assignable(void)
1928 libxl_device_pci *pcidevs;
1929 int num, i;
1931 if ( libxl_device_pci_list_assignable(&ctx, &pcidevs, &num) )
1932 return;
1933 for (i = 0; i < num; i++) {
1934 printf("%04x:%02x:%02x:%01x\n",
1935 pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
1937 free(pcidevs);
1940 int main_pcilist_assignable(int argc, char **argv)
1942 int opt;
1944 while ((opt = getopt(argc, argv, "h")) != -1) {
1945 switch (opt) {
1946 case 'h':
1947 help("pci-list-assignable-devices");
1948 exit(0);
1949 default:
1950 fprintf(stderr, "option not supported\n");
1951 break;
1955 pcilist_assignable();
1956 exit(0);
1959 void pcilist(char *dom)
1961 libxl_device_pci *pcidevs;
1962 int num, i;
1964 find_domain(dom);
1966 if (libxl_device_pci_list_assigned(&ctx, &pcidevs, domid, &num))
1967 return;
1968 printf("VFn domain bus slot func\n");
1969 for (i = 0; i < num; i++) {
1970 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);
1972 free(pcidevs);
1975 int main_pcilist(int argc, char **argv)
1977 int opt;
1978 char *domname = NULL;
1980 while ((opt = getopt(argc, argv, "h")) != -1) {
1981 switch (opt) {
1982 case 'h':
1983 help("pci-list");
1984 exit(0);
1985 default:
1986 fprintf(stderr, "option not supported\n");
1987 break;
1990 if (optind >= argc) {
1991 help("pci-list");
1992 exit(2);
1995 domname = argv[optind];
1997 pcilist(domname);
1998 exit(0);
2001 void pcidetach(char *dom, char *bdf)
2003 libxl_device_pci pcidev;
2004 unsigned int domain, bus, dev, func;
2006 find_domain(dom);
2008 memset(&pcidev, 0x00, sizeof(pcidev));
2009 if (sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func) != 4) {
2010 fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
2011 exit(2);
2013 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
2014 libxl_device_pci_remove(&ctx, domid, &pcidev);
2017 int main_pcidetach(int argc, char **argv)
2019 int opt;
2020 char *domname = NULL, *bdf = NULL;
2022 while ((opt = getopt(argc, argv, "h")) != -1) {
2023 switch (opt) {
2024 case 'h':
2025 help("pci-detach");
2026 exit(0);
2027 default:
2028 fprintf(stderr, "option not supported\n");
2029 break;
2032 if (optind >= argc - 1) {
2033 help("pci-detach");
2034 exit(2);
2037 domname = argv[optind];
2038 bdf = argv[optind + 1];
2040 pcidetach(domname, bdf);
2041 exit(0);
2043 void pciattach(char *dom, char *bdf, char *vs)
2045 libxl_device_pci pcidev;
2046 unsigned int domain, bus, dev, func;
2048 find_domain(dom);
2050 memset(&pcidev, 0x00, sizeof(pcidev));
2051 if (sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func) != 4) {
2052 fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
2053 exit(2);
2055 libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
2056 libxl_device_pci_add(&ctx, domid, &pcidev);
2059 int main_pciattach(int argc, char **argv)
2061 int opt;
2062 char *domname = NULL, *bdf = NULL, *vs = NULL;
2064 while ((opt = getopt(argc, argv, "h")) != -1) {
2065 switch (opt) {
2066 case 'h':
2067 help("pci-attach");
2068 exit(0);
2069 default:
2070 fprintf(stderr, "option not supported\n");
2071 break;
2074 if (optind >= argc - 1) {
2075 help("pci-attach");
2076 exit(2);
2079 domname = argv[optind];
2080 bdf = argv[optind + 1];
2082 if (optind + 1 < argc)
2083 vs = argv[optind + 2];
2085 pciattach(domname, bdf, vs);
2086 exit(0);
2089 void pause_domain(char *p)
2091 find_domain(p);
2092 libxl_domain_pause(&ctx, domid);
2095 void unpause_domain(char *p)
2097 find_domain(p);
2098 libxl_domain_unpause(&ctx, domid);
2101 void destroy_domain(char *p)
2103 int rc;
2104 find_domain(p);
2105 if (domid == 0) {
2106 fprintf(stderr, "Cannot destroy privileged domain 0.\n\n");
2107 exit(-1);
2109 rc = libxl_domain_destroy(&ctx, domid, 0);
2110 if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n.",rc); exit(-1); }
2113 void shutdown_domain(char *p)
2115 int rc;
2116 find_domain(p);
2117 rc=libxl_domain_shutdown(&ctx, domid, 0);
2118 if (rc) { fprintf(stderr,"shutdown failed (rc=%d)\n.",rc);exit(-1); }
2121 void reboot_domain(char *p)
2123 int rc;
2124 find_domain(p);
2125 rc=libxl_domain_shutdown(&ctx, domid, 1);
2126 if (rc) { fprintf(stderr,"reboot failed (rc=%d)\n.",rc);exit(-1); }
2129 void list_domains_details(const libxl_dominfo *info, int nb_domain)
2131 struct domain_config d_config;
2133 char *config_file;
2134 uint8_t *data;
2135 int i, len, rc;
2136 libxl_device_model_info dm_info;
2138 for (i = 0; i < nb_domain; i++) {
2139 rc = libxl_userdata_retrieve(&ctx, info[i].domid, "xl", &data, &len);
2140 if (rc)
2141 continue;
2142 CHK_ERRNO(asprintf(&config_file, "<domid %d data>", info[i].domid));
2143 memset(&d_config, 0x00, sizeof(d_config));
2144 parse_config_data(config_file, (char *)data, len, &d_config, &dm_info);
2145 printf_info(info[i].domid, &d_config, &dm_info);
2146 free(data);
2147 free(config_file);
2151 void list_domains(int verbose, const libxl_dominfo *info, int nb_domain)
2153 int i;
2155 printf("Name ID Mem VCPUs\tState\tTime(s)\n");
2156 for (i = 0; i < nb_domain; i++) {
2157 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f",
2158 libxl_domid_to_name(&ctx, info[i].domid),
2159 info[i].domid,
2160 (unsigned long) (info[i].max_memkb / 1024),
2161 info[i].vcpu_online,
2162 info[i].running ? 'r' : '-',
2163 info[i].blocked ? 'b' : '-',
2164 info[i].paused ? 'p' : '-',
2165 info[i].shutdown ? 's' : '-',
2166 info[i].shutdown_reason == SHUTDOWN_crash ? 'c' : '-',
2167 info[i].dying ? 'd' : '-',
2168 ((float)info[i].cpu_time / 1e9));
2169 if (verbose) {
2170 char *uuid = libxl_uuid2string(&ctx, info[i].uuid);
2171 printf(" %s", uuid);
2173 putchar('\n');
2177 void list_vm(void)
2179 libxl_vminfo *info;
2180 int nb_vm, i;
2182 info = libxl_list_vm(&ctx, &nb_vm);
2184 if (info < 0) {
2185 fprintf(stderr, "libxl_domain_infolist failed.\n");
2186 exit(1);
2188 printf("UUID ID name\n");
2189 for (i = 0; i < nb_vm; i++) {
2190 printf(UUID_FMT " %d %-30s\n",
2191 info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
2192 info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
2193 info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], info[i].uuid[11],
2194 info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], info[i].uuid[15],
2195 info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
2197 free(info);
2200 static void save_domain_core_begin(char *domain_spec,
2201 const char *override_config_file,
2202 uint8_t **config_data_r,
2203 int *config_len_r)
2205 int rc;
2207 find_domain(domain_spec);
2209 /* configuration file in optional data: */
2211 if (override_config_file) {
2212 void *config_v = 0;
2213 rc = libxl_read_file_contents(&ctx, override_config_file,
2214 &config_v, config_len_r);
2215 *config_data_r = config_v;
2216 } else {
2217 rc = libxl_userdata_retrieve(&ctx, domid, "xl",
2218 config_data_r, config_len_r);
2220 if (rc) {
2221 fputs("Unable to get config file\n",stderr);
2222 exit(2);
2226 void save_domain_core_writeconfig(int fd, const char *filename,
2227 const uint8_t *config_data, int config_len)
2229 struct save_file_header hdr;
2230 uint8_t *optdata_begin;
2231 union { uint32_t u32; char b[4]; } u32buf;
2233 memset(&hdr, 0, sizeof(hdr));
2234 memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
2235 hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
2237 optdata_begin= 0;
2239 #define ADD_OPTDATA(ptr, len) ({ \
2240 if ((len)) { \
2241 hdr.optional_data_len += (len); \
2242 optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
2243 memcpy(optdata_begin + hdr.optional_data_len - (len), \
2244 (ptr), (len)); \
2245 } \
2246 })
2248 u32buf.u32 = config_len;
2249 ADD_OPTDATA(u32buf.b, 4);
2250 ADD_OPTDATA(config_data, config_len);
2252 /* that's the optional data */
2254 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2255 &hdr, sizeof(hdr), filename, "header") );
2256 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2257 optdata_begin, hdr.optional_data_len, filename, "header") );
2259 fprintf(stderr, "Saving to %s new xl format (info"
2260 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
2261 filename, hdr.mandatory_flags, hdr.optional_flags,
2262 hdr.optional_data_len);
2265 int save_domain(char *p, char *filename, int checkpoint,
2266 const char *override_config_file)
2268 int fd;
2269 uint8_t *config_data;
2270 int config_len;
2272 save_domain_core_begin(p, override_config_file, &config_data, &config_len);
2274 if (!config_len) {
2275 fputs(" Savefile will not contain xl domain config\n", stderr);
2278 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
2279 if (fd < 0) {
2280 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
2281 exit(2);
2284 save_domain_core_writeconfig(fd, filename, config_data, config_len);
2286 CHK_ERRNO(libxl_domain_suspend(&ctx, NULL, domid, fd));
2287 close(fd);
2289 if (checkpoint)
2290 libxl_domain_unpause(&ctx, domid);
2291 else
2292 libxl_domain_destroy(&ctx, domid, 0);
2294 exit(0);
2297 static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
2298 const char *what, const char *rune) {
2299 char buf[msgsz];
2300 const char *stream;
2301 int rc;
2303 stream = rune ? "migration receiver stream" : "migration stream";
2304 rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
2305 if (rc) return ERROR_FAIL;
2307 if (memcmp(buf, msg, msgsz)) {
2308 fprintf(stderr, "%s contained unexpected data instead of %s\n",
2309 stream, what);
2310 if (rune)
2311 fprintf(stderr, "(command run was: %s )\n", rune);
2312 return ERROR_FAIL;
2314 return 0;
2317 static void migration_child_report(pid_t migration_child, int recv_fd) {
2318 pid_t child;
2319 int status, sr;
2320 struct timeval now, waituntil, timeout;
2321 static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
2323 if (!migration_child) return;
2325 CHK_ERRNO( gettimeofday(&waituntil, 0) );
2326 waituntil.tv_sec += 2;
2328 for (;;) {
2329 child = waitpid(migration_child, &status, WNOHANG);
2331 if (child == migration_child) {
2332 if (status)
2333 libxl_report_child_exitstatus(&ctx, XTL_INFO,
2334 "migration target process",
2335 migration_child, status);
2336 break;
2338 if (child == -1) {
2339 if (errno == EINTR) continue;
2340 fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
2341 (long)migration_child, strerror(errno));
2342 break;
2344 assert(child == 0);
2346 CHK_ERRNO( gettimeofday(&now, 0) );
2347 if (timercmp(&now, &waituntil, >)) {
2348 fprintf(stderr, "migration child [%ld] not exiting, no longer"
2349 " waiting (exit status will be unreported)\n",
2350 (long)migration_child);
2351 break;
2353 timersub(&waituntil, &now, &timeout);
2355 if (recv_fd >= 0) {
2356 fd_set readfds, exceptfds;
2357 FD_ZERO(&readfds);
2358 FD_ZERO(&exceptfds);
2359 FD_SET(recv_fd, &readfds);
2360 FD_SET(recv_fd, &exceptfds);
2361 sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
2362 } else {
2363 if (timercmp(&timeout, &pollinterval, >))
2364 timeout = pollinterval;
2365 sr = select(0,0,0,0, &timeout);
2367 if (sr > 0) {
2368 recv_fd = -1;
2369 } else if (sr == 0) {
2370 } else if (sr == -1) {
2371 if (errno != EINTR) {
2372 fprintf(stderr, "migration child [%ld] exit wait select"
2373 " failed unexpectedly: %s\n",
2374 (long)migration_child, strerror(errno));
2375 break;
2379 migration_child = 0;
2382 static void migrate_domain(char *domain_spec, const char *rune,
2383 const char *override_config_file)
2385 pid_t child = -1;
2386 int rc;
2387 int sendpipe[2], recvpipe[2];
2388 int send_fd, recv_fd;
2389 libxl_domain_suspend_info suspinfo;
2390 char *away_domname;
2391 char rc_buf;
2392 uint8_t *config_data;
2393 int config_len;
2395 save_domain_core_begin(domain_spec, override_config_file,
2396 &config_data, &config_len);
2398 if (!config_len) {
2399 fprintf(stderr, "No config file stored for running domain and "
2400 "none supplied - cannot migrate.\n");
2401 exit(1);
2404 MUST( libxl_pipe(&ctx, sendpipe) );
2405 MUST( libxl_pipe(&ctx, recvpipe) );
2407 child = libxl_fork(&ctx);
2408 if (child==-1) exit(1);
2410 if (!child) {
2411 dup2(sendpipe[0], 0);
2412 dup2(recvpipe[1], 1);
2413 close(sendpipe[0]); close(sendpipe[1]);
2414 close(recvpipe[0]); close(recvpipe[1]);
2415 execlp("sh","sh","-c",rune,(char*)0);
2416 perror("failed to exec sh");
2417 exit(-1);
2420 close(sendpipe[0]);
2421 close(recvpipe[1]);
2422 send_fd = sendpipe[1];
2423 recv_fd = recvpipe[0];
2425 signal(SIGPIPE, SIG_IGN);
2426 /* if receiver dies, we get an error and can clean up
2427 rather than just dying */
2429 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
2430 sizeof(migrate_receiver_banner)-1,
2431 "banner", rune);
2432 if (rc) {
2433 close(send_fd);
2434 migration_child_report(child, recv_fd);
2435 exit(-rc);
2438 save_domain_core_writeconfig(send_fd, "migration stream",
2439 config_data, config_len);
2441 xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
2443 memset(&suspinfo, 0, sizeof(suspinfo));
2444 suspinfo.flags |= XL_SUSPEND_LIVE;
2445 rc = libxl_domain_suspend(&ctx, &suspinfo, domid, send_fd);
2446 if (rc) {
2447 fprintf(stderr, "migration sender: libxl_domain_suspend failed"
2448 " (rc=%d)\n", rc);
2449 goto failed_resume;
2452 //fprintf(stderr, "migration sender: Transfer complete.\n");
2453 // Should only be printed when debugging as it's a bit messy with
2454 // progress indication.
2456 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
2457 sizeof(migrate_receiver_ready),
2458 "ready message", rune);
2459 if (rc) goto failed_resume;
2461 xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
2463 /* right, at this point we are about give the destination
2464 * permission to rename and resume, so we must first rename the
2465 * domain away ourselves */
2467 fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
2469 if (common_domname) {
2470 if (asprintf(&away_domname, "%s--migratedaway", common_domname) < 0)
2471 goto failed_resume;
2472 rc = libxl_domain_rename(&ctx, domid,
2473 common_domname, away_domname, 0);
2474 if (rc) goto failed_resume;
2477 /* point of no return - as soon as we have tried to say
2478 * "go" to the receiver, it's not safe to carry on. We leave
2479 * the domain renamed to %s--migratedaway in case that's helpful.
2480 */
2482 fprintf(stderr, "migration sender: Giving target permission to start.\n");
2484 rc = libxl_write_exactly(&ctx, send_fd,
2485 migrate_permission_to_go,
2486 sizeof(migrate_permission_to_go),
2487 "migration stream", "GO message");
2488 if (rc) goto failed_badly;
2490 rc = migrate_read_fixedmessage(recv_fd, migrate_report,
2491 sizeof(migrate_report),
2492 "success/failure report message", rune);
2493 if (rc) goto failed_badly;
2495 rc = libxl_read_exactly(&ctx, recv_fd,
2496 &rc_buf, 1,
2497 "migration ack stream", "success/failure status");
2498 if (rc) goto failed_badly;
2500 if (rc_buf) {
2501 fprintf(stderr, "migration sender: Target reports startup failure"
2502 " (status code %d).\n", rc_buf);
2504 rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
2505 sizeof(migrate_permission_to_go),
2506 "permission for sender to resume",
2507 rune);
2508 if (rc) goto failed_badly;
2510 fprintf(stderr, "migration sender: Trying to resume at our end.\n");
2512 if (common_domname) {
2513 libxl_domain_rename(&ctx, domid,
2514 away_domname, common_domname, 0);
2516 rc = libxl_domain_resume(&ctx, domid);
2517 if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
2519 fprintf(stderr, "Migration failed due to problems at target.\n");
2520 exit(-ERROR_FAIL);
2523 fprintf(stderr, "migration sender: Target reports successful startup.\n");
2524 libxl_domain_destroy(&ctx, domid, 1); /* bang! */
2525 fprintf(stderr, "Migration successful.\n");
2526 exit(0);
2528 failed_resume:
2529 close(send_fd);
2530 migration_child_report(child, recv_fd);
2531 fprintf(stderr, "Migration failed, resuming at sender.\n");
2532 libxl_domain_resume(&ctx, domid);
2533 exit(-ERROR_FAIL);
2535 failed_badly:
2536 fprintf(stderr,
2537 "** Migration failed during final handshake **\n"
2538 "Domain state is now undefined !\n"
2539 "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
2540 " resuming at most one instance. Two simultaneous instances of the domain\n"
2541 " would probably result in SEVERE DATA LOSS and it is now your\n"
2542 " responsibility to avoid that. Sorry.\n");
2544 close(send_fd);
2545 migration_child_report(child, recv_fd);
2546 exit(-ERROR_BADFAIL);
2549 static void core_dump_domain(const char *domain_spec, const char *filename)
2551 int rc;
2552 find_domain(domain_spec);
2553 rc=libxl_domain_core_dump(&ctx, domid, filename);
2554 if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n.",rc);exit(-1); }
2557 static void migrate_receive(int debug, int daemonize)
2559 int rc, rc2;
2560 char rc_buf;
2561 char *migration_domname;
2562 struct domain_create dom_info;
2564 signal(SIGPIPE, SIG_IGN);
2565 /* if we get SIGPIPE we'd rather just have it as an error */
2567 fprintf(stderr, "migration target: Ready to receive domain.\n");
2569 CHK_ERRNO( libxl_write_exactly(&ctx, 1,
2570 migrate_receiver_banner,
2571 sizeof(migrate_receiver_banner)-1,
2572 "migration ack stream",
2573 "banner") );
2575 memset(&dom_info, 0, sizeof(dom_info));
2576 dom_info.debug = debug;
2577 dom_info.daemonize = daemonize;
2578 dom_info.paused = 1;
2579 dom_info.restore_file = "incoming migration stream";
2580 dom_info.migration_domname_r = &migration_domname;
2582 rc = create_domain(&dom_info);
2583 if (rc < 0) {
2584 fprintf(stderr, "migration target: Domain creation failed"
2585 " (code %d).\n", rc);
2586 exit(-rc);
2589 fprintf(stderr, "migration target: Transfer complete,"
2590 " requesting permission to start domain.\n");
2592 rc = libxl_write_exactly(&ctx, 1,
2593 migrate_receiver_ready,
2594 sizeof(migrate_receiver_ready),
2595 "migration ack stream", "ready message");
2596 if (rc) exit(-rc);
2598 rc = migrate_read_fixedmessage(0, migrate_permission_to_go,
2599 sizeof(migrate_permission_to_go),
2600 "GO message", 0);
2601 if (rc) goto perhaps_destroy_notify_rc;
2603 fprintf(stderr, "migration target: Got permission, starting domain.\n");
2605 if (migration_domname) {
2606 rc = libxl_domain_rename(&ctx, domid,
2607 migration_domname, common_domname, 0);
2608 if (rc) goto perhaps_destroy_notify_rc;
2611 rc = libxl_domain_unpause(&ctx, domid);
2612 if (rc) goto perhaps_destroy_notify_rc;
2614 fprintf(stderr, "migration target: Domain started successsfully.\n");
2615 rc = 0;
2617 perhaps_destroy_notify_rc:
2618 rc2 = libxl_write_exactly(&ctx, 1,
2619 migrate_report, sizeof(migrate_report),
2620 "migration ack stream",
2621 "success/failure report");
2622 if (rc2) exit(-ERROR_BADFAIL);
2624 rc_buf = -rc;
2625 assert(!!rc_buf == !!rc);
2626 rc2 = libxl_write_exactly(&ctx, 1, &rc_buf, 1,
2627 "migration ack stream",
2628 "success/failure code");
2629 if (rc2) exit(-ERROR_BADFAIL);
2631 if (rc) {
2632 fprintf(stderr, "migration target: Failure, destroying our copy.\n");
2634 rc2 = libxl_domain_destroy(&ctx, domid, 1);
2635 if (rc2) {
2636 fprintf(stderr, "migration target: Failed to destroy our copy"
2637 " (code %d).\n", rc2);
2638 exit(-ERROR_BADFAIL);
2641 fprintf(stderr, "migration target: Cleanup OK, granting sender"
2642 " permission to resume.\n");
2644 rc2 = libxl_write_exactly(&ctx, 1,
2645 migrate_permission_to_go,
2646 sizeof(migrate_permission_to_go),
2647 "migration ack stream",
2648 "permission to sender to have domain back");
2649 if (rc2) exit(-ERROR_BADFAIL);
2652 exit(0);
2655 int main_restore(int argc, char **argv)
2657 char *checkpoint_file = NULL;
2658 char *config_file = NULL;
2659 struct domain_create dom_info;
2660 int paused = 0, debug = 0, daemonize = 1;
2661 int opt, rc;
2663 while ((opt = getopt(argc, argv, "hpde")) != -1) {
2664 switch (opt) {
2665 case 'p':
2666 paused = 1;
2667 break;
2668 case 'd':
2669 debug = 1;
2670 break;
2671 case 'e':
2672 daemonize = 0;
2673 break;
2674 case 'h':
2675 help("restore");
2676 exit(0);
2677 default:
2678 fprintf(stderr, "option not supported\n");
2679 break;
2683 if (argc-optind == 1) {
2684 checkpoint_file = argv[optind];
2685 } else if (argc-optind == 2) {
2686 config_file = argv[optind];
2687 checkpoint_file = argv[optind + 1];
2688 } else {
2689 help("restore");
2690 exit(2);
2693 memset(&dom_info, 0, sizeof(dom_info));
2694 dom_info.debug = debug;
2695 dom_info.daemonize = daemonize;
2696 dom_info.paused = paused;
2697 dom_info.config_file = config_file;
2698 dom_info.restore_file = checkpoint_file;
2699 dom_info.migrate_fd = -1;
2701 rc = create_domain(&dom_info);
2702 if (rc < 0)
2703 exit(-rc);
2705 exit(0);
2708 int main_migrate_receive(int argc, char **argv)
2710 int debug = 0, daemonize = 1;
2711 int opt;
2713 while ((opt = getopt(argc, argv, "hed")) != -1) {
2714 switch (opt) {
2715 case 'h':
2716 help("migrate-receive");
2717 exit(2);
2718 break;
2719 case 'e':
2720 daemonize = 0;
2721 break;
2722 case 'd':
2723 debug = 1;
2724 break;
2725 default:
2726 fprintf(stderr, "option not supported\n");
2727 break;
2731 if (argc-optind != 0) {
2732 help("migrate-receive");
2733 exit(2);
2735 migrate_receive(debug, daemonize);
2736 exit(0);
2739 int main_save(int argc, char **argv)
2741 char *filename = NULL, *p = NULL;
2742 const char *config_filename;
2743 int checkpoint = 0;
2744 int opt;
2746 while ((opt = getopt(argc, argv, "hc")) != -1) {
2747 switch (opt) {
2748 case 'c':
2749 checkpoint = 1;
2750 break;
2751 case 'h':
2752 help("save");
2753 exit(0);
2754 default:
2755 fprintf(stderr, "option not supported\n");
2756 break;
2760 if (argc-optind < 1 || argc-optind > 3) {
2761 help("save");
2762 exit(2);
2765 p = argv[optind];
2766 filename = argv[optind + 1];
2767 config_filename = argv[optind + 2];
2768 save_domain(p, filename, checkpoint, config_filename);
2769 exit(0);
2772 int main_migrate(int argc, char **argv)
2774 char *p = NULL;
2775 const char *config_filename = NULL;
2776 const char *ssh_command = "ssh";
2777 char *rune = NULL;
2778 char *host;
2779 int opt, daemonize = 1, debug = 0;
2781 while ((opt = getopt(argc, argv, "hC:s:ed")) != -1) {
2782 switch (opt) {
2783 case 'h':
2784 help("migrate");
2785 exit(0);
2786 case 'C':
2787 config_filename = optarg;
2788 break;
2789 case 's':
2790 ssh_command = optarg;
2791 break;
2792 case 'e':
2793 daemonize = 0;
2794 break;
2795 case 'd':
2796 debug = 1;
2797 break;
2798 default:
2799 fprintf(stderr, "option not supported\n");
2800 break;
2804 if (argc-optind < 2 || argc-optind > 2) {
2805 help("migrate");
2806 exit(2);
2809 p = argv[optind];
2810 host = argv[optind + 1];
2812 if (!ssh_command[0]) {
2813 rune= host;
2814 } else {
2815 if (asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
2816 ssh_command, host,
2817 daemonize ? "" : " -e",
2818 debug ? " -d" : "") < 0)
2819 exit(1);
2822 migrate_domain(p, rune, config_filename);
2823 exit(0);
2826 int main_dump_core(int argc, char **argv)
2828 if ( argc-optind < 2 ) {
2829 help("dump-core");
2830 exit(2);
2832 core_dump_domain(argv[optind], argv[optind + 1]);
2833 exit(0);
2836 int main_pause(int argc, char **argv)
2838 int opt;
2839 char *p;
2842 while ((opt = getopt(argc, argv, "h")) != -1) {
2843 switch (opt) {
2844 case 'h':
2845 help("pause");
2846 exit(0);
2847 default:
2848 fprintf(stderr, "option not supported\n");
2849 break;
2852 if (optind >= argc) {
2853 help("pause");
2854 exit(2);
2857 p = argv[optind];
2859 pause_domain(p);
2860 exit(0);
2863 int main_unpause(int argc, char **argv)
2865 int opt;
2866 char *p;
2869 while ((opt = getopt(argc, argv, "h")) != -1) {
2870 switch (opt) {
2871 case 'h':
2872 help("unpause");
2873 exit(0);
2874 default:
2875 fprintf(stderr, "option not supported\n");
2876 break;
2879 if (optind >= argc) {
2880 help("unpause");
2881 exit(2);
2884 p = argv[optind];
2886 unpause_domain(p);
2887 exit(0);
2890 int main_destroy(int argc, char **argv)
2892 int opt;
2893 char *p;
2895 while ((opt = getopt(argc, argv, "h")) != -1) {
2896 switch (opt) {
2897 case 'h':
2898 help("destroy");
2899 exit(0);
2900 default:
2901 fprintf(stderr, "option not supported\n");
2902 break;
2905 if (optind >= argc) {
2906 help("destroy");
2907 exit(2);
2910 p = argv[optind];
2912 destroy_domain(p);
2913 exit(0);
2916 int main_shutdown(int argc, char **argv)
2918 int opt;
2919 char *p;
2921 while ((opt = getopt(argc, argv, "h")) != -1) {
2922 switch (opt) {
2923 case 'h':
2924 help("shutdown");
2925 exit(0);
2926 default:
2927 fprintf(stderr, "option not supported\n");
2928 break;
2931 if (optind >= argc) {
2932 help("shutdown");
2933 exit(2);
2936 p = argv[optind];
2938 shutdown_domain(p);
2939 exit(0);
2942 int main_reboot(int argc, char **argv)
2944 int opt;
2945 char *p;
2947 while ((opt = getopt(argc, argv, "h")) != -1) {
2948 switch (opt) {
2949 case 'h':
2950 help("reboot");
2951 exit(0);
2952 default:
2953 fprintf(stderr, "option not supported\n");
2954 break;
2957 if (optind >= argc) {
2958 help("reboot");
2959 exit(2);
2962 p = argv[optind];
2964 reboot_domain(p);
2965 exit(0);
2967 int main_list(int argc, char **argv)
2969 int opt, verbose = 0;
2970 int details = 0;
2971 int option_index = 0;
2972 static struct option long_options[] = {
2973 {"long", 0, 0, 'l'},
2974 {"help", 0, 0, 'h'},
2975 {"verbose", 0, 0, 'v'},
2976 {0, 0, 0, 0}
2977 };
2979 libxl_dominfo info_buf;
2980 libxl_dominfo *info, *info_free=0;
2981 int nb_domain, rc;
2983 while (1) {
2984 opt = getopt_long(argc, argv, "lvh", long_options, &option_index);
2985 if (opt == -1)
2986 break;
2988 switch (opt) {
2989 case 'l':
2990 details = 1;
2991 break;
2992 case 'h':
2993 help("list");
2994 exit(0);
2995 case 'v':
2996 verbose = 1;
2997 break;
2998 default:
2999 fprintf(stderr, "option not supported\n");
3000 break;
3004 if (optind >= argc) {
3005 info = libxl_list_domain(&ctx, &nb_domain);
3006 if (!info) {
3007 fprintf(stderr, "libxl_domain_infolist failed.\n");
3008 exit(1);
3010 info_free = info;
3011 } else if (optind == argc-1) {
3012 find_domain(argv[optind]);
3013 rc = libxl_domain_info(&ctx, &info_buf, domid);
3014 if (rc) {
3015 fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
3016 exit(-rc);
3018 info = &info_buf;
3019 nb_domain = 1;
3020 } else {
3021 help("list");
3022 exit(2);
3025 if (details)
3026 list_domains_details(info, nb_domain);
3027 else
3028 list_domains(verbose, info, nb_domain);
3030 free(info_free);
3032 exit(0);
3035 int main_list_vm(int argc, char **argv)
3037 int opt;
3039 while ((opt = getopt(argc, argv, "h")) != -1) {
3040 switch (opt) {
3041 case 'h':
3042 help("list-vm");
3043 exit(0);
3044 default:
3045 fprintf(stderr, "option not supported\n");
3046 break;
3050 list_vm();
3051 exit(0);
3054 int main_create(int argc, char **argv)
3056 char *filename = NULL;
3057 char *p, extra_config[1024];
3058 struct domain_create dom_info;
3059 int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
3060 dryrun = 0, quiet = 0;
3061 int opt, rc;
3062 int option_index = 0;
3063 static struct option long_options[] = {
3064 {"dryrun", 0, 0, 'n'},
3065 {"quiet", 0, 0, 'q'},
3066 {"help", 0, 0, 'h'},
3067 {"defconfig", 1, 0, 'f'},
3068 {0, 0, 0, 0}
3069 };
3071 while (1) {
3072 opt = getopt_long(argc, argv, "hnqf:pcde", long_options, &option_index);
3073 if (opt == -1)
3074 break;
3076 switch (opt) {
3077 case 'f':
3078 filename = optarg;
3079 break;
3080 case 'p':
3081 paused = 1;
3082 break;
3083 case 'c':
3084 console_autoconnect = 1;
3085 break;
3086 case 'd':
3087 debug = 1;
3088 break;
3089 case 'e':
3090 daemonize = 0;
3091 break;
3092 case 'h':
3093 help("create");
3094 exit(0);
3095 case 'n':
3096 dryrun = 1;
3097 break;
3098 case 'q':
3099 quiet = 1;
3100 break;
3101 default:
3102 fprintf(stderr, "option not supported\n");
3103 break;
3107 memset(extra_config, 0, sizeof(extra_config));
3108 while (optind < argc) {
3109 if ((p = strchr(argv[optind], '='))) {
3110 if (strlen(extra_config) + 1 < sizeof(extra_config)) {
3111 if (strlen(extra_config))
3112 strcat(extra_config, "\n");
3113 strcat(extra_config, argv[optind]);
3115 } else if (!filename) {
3116 filename = argv[optind];
3117 } else {
3118 help("create");
3119 exit(2);
3121 optind++;
3124 memset(&dom_info, 0, sizeof(dom_info));
3125 dom_info.debug = debug;
3126 dom_info.daemonize = daemonize;
3127 dom_info.paused = paused;
3128 dom_info.dryrun = dryrun;
3129 dom_info.quiet = quiet;
3130 dom_info.config_file = filename;
3131 dom_info.extra_config = extra_config;
3132 dom_info.migrate_fd = -1;
3133 dom_info.console_autoconnect = console_autoconnect;
3135 rc = create_domain(&dom_info);
3136 if (rc < 0)
3137 exit(-rc);
3139 exit(0);
3142 void button_press(char *p, char *b)
3144 libxl_button button;
3146 find_domain(p);
3148 if (!strcmp(b, "power")) {
3149 button = POWER_BUTTON;
3150 } else if (!strcmp(b, "sleep")) {
3151 button = SLEEP_BUTTON;
3152 } else {
3153 fprintf(stderr, "%s is an invalid button identifier\n", b);
3154 exit(2);
3157 libxl_button_press(&ctx, domid, button);
3160 int main_button_press(int argc, char **argv)
3162 int opt;
3163 char *p;
3164 char *b;
3166 while ((opt = getopt(argc, argv, "h")) != -1) {
3167 switch (opt) {
3168 case 'h':
3169 help("button-press");
3170 exit(0);
3171 default:
3172 fprintf(stderr, "option not supported\n");
3173 break;
3176 if (optind >= argc - 1) {
3177 help("button-press");
3178 exit(2);
3181 p = argv[optind];
3182 b = argv[optind + 1];
3184 button_press(p, b);
3185 exit(0);
3188 static void print_vcpuinfo(uint32_t tdomid,
3189 const libxl_vcpuinfo *vcpuinfo,
3190 uint32_t nr_cpus)
3192 int i, l;
3193 uint64_t *cpumap;
3194 uint64_t pcpumap;
3196 /* NAME ID VCPU */
3197 printf("%-32s %5u %5u",
3198 libxl_domid_to_name(&ctx, tdomid), tdomid, vcpuinfo->vcpuid);
3199 if (!vcpuinfo->online) {
3200 /* CPU STA */
3201 printf("%5c %3c%cp ", '-', '-', '-');
3202 } else {
3203 /* CPU STA */
3204 printf("%5u %3c%c- ", vcpuinfo->cpu,
3205 vcpuinfo->running ? 'r' : '-',
3206 vcpuinfo->blocked ? 'b' : '-');
3208 /* TIM */
3209 printf("%9.1f ", ((float)vcpuinfo->vcpu_time / 1e9));
3210 /* CPU AFFINITY */
3211 pcpumap = nr_cpus > 64 ? -1 : ((1 << nr_cpus) - 1);
3212 for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
3213 if (*cpumap < pcpumap) {
3214 break;
3216 if (nr_cpus > 64) {
3217 pcpumap = -1;
3218 nr_cpus -= 64;
3219 } else {
3220 pcpumap = ((1 << nr_cpus) - 1);
3221 nr_cpus = 0;
3224 if (!nr_cpus) {
3225 printf("any cpu\n");
3226 } else {
3227 for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
3228 pcpumap = *cpumap;
3229 for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1)
3231 printf("%u", i);
3232 for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
3234 if (l < i) {
3235 printf("-%u", i);
3237 for (++i; pcpumap; ++i, pcpumap >>= 1) {
3238 if (pcpumap & 1) {
3239 printf(",%u", i);
3240 for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
3242 if (l < i) {
3243 printf("-%u", i);
3245 ++i;
3248 printf("\n");
3249 nr_cpus = nr_cpus > 64 ? nr_cpus - 64 : 0;
3254 void vcpulist(int argc, char **argv)
3256 libxl_dominfo *dominfo;
3257 libxl_vcpuinfo *vcpuinfo;
3258 libxl_physinfo physinfo;
3259 int nb_vcpu, nb_domain, cpusize;
3261 if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
3262 fprintf(stderr, "libxl_physinfo failed.\n");
3263 goto vcpulist_out;
3265 printf("%-32s %5s %5s %5s %5s %9s %s\n",
3266 "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
3267 if (!argc) {
3268 if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
3269 fprintf(stderr, "libxl_list_domain failed.\n");
3270 goto vcpulist_out;
3272 for (; nb_domain > 0; --nb_domain, ++dominfo) {
3273 if (!(vcpuinfo = libxl_list_vcpu(&ctx, dominfo->domid, &nb_vcpu, &cpusize))) {
3274 fprintf(stderr, "libxl_list_vcpu failed.\n");
3275 goto vcpulist_out;
3277 for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
3278 print_vcpuinfo(dominfo->domid, vcpuinfo, physinfo.nr_cpus);
3281 } else {
3282 for (; argc > 0; ++argv, --argc) {
3283 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
3284 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
3286 if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &cpusize))) {
3287 fprintf(stderr, "libxl_list_vcpu failed.\n");
3288 goto vcpulist_out;
3290 for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
3291 print_vcpuinfo(domid, vcpuinfo, physinfo.nr_cpus);
3295 vcpulist_out:
3299 int main_vcpulist(int argc, char **argv)
3301 int opt;
3303 while ((opt = getopt(argc, argv, "h")) != -1) {
3304 switch (opt) {
3305 case 'h':
3306 help("vcpu-list");
3307 exit(0);
3308 default:
3309 fprintf(stderr, "option `%c' not supported.\n", opt);
3310 break;
3314 vcpulist(argc - 2, argv + 2);
3315 exit(0);
3318 void vcpupin(char *d, const char *vcpu, char *cpu)
3320 libxl_vcpuinfo *vcpuinfo;
3321 libxl_physinfo physinfo;
3322 uint64_t *cpumap = NULL;
3324 uint32_t vcpuid, cpuida, cpuidb;
3325 char *endptr, *toka, *tokb;
3326 int i, nb_vcpu, cpusize;
3328 vcpuid = strtoul(vcpu, &endptr, 10);
3329 if (vcpu == endptr) {
3330 if (strcmp(vcpu, "all")) {
3331 fprintf(stderr, "Error: Invalid argument.\n");
3332 return;
3334 vcpuid = -1;
3337 find_domain(d);
3339 if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
3340 fprintf(stderr, "libxl_get_physinfo failed.\n");
3341 goto vcpupin_out1;
3344 cpumap = calloc(physinfo.max_cpu_id + 1, sizeof (uint64_t));
3345 if (!cpumap) {
3346 goto vcpupin_out1;
3348 if (strcmp(cpu, "all")) {
3349 for (toka = strtok(cpu, ","), i = 0; toka; toka = strtok(NULL, ","), ++i) {
3350 cpuida = strtoul(toka, &endptr, 10);
3351 if (toka == endptr) {
3352 fprintf(stderr, "Error: Invalid argument.\n");
3353 goto vcpupin_out;
3355 if (*endptr == '-') {
3356 tokb = endptr + 1;
3357 cpuidb = strtoul(tokb, &endptr, 10);
3358 if ((tokb == endptr) || (cpuida > cpuidb)) {
3359 fprintf(stderr, "Error: Invalid argument.\n");
3360 goto vcpupin_out;
3362 while (cpuida <= cpuidb) {
3363 cpumap[cpuida / 64] |= (1 << (cpuida % 64));
3364 ++cpuida;
3366 } else {
3367 cpumap[cpuida / 64] |= (1 << (cpuida % 64));
3371 else {
3372 memset(cpumap, -1, sizeof (uint64_t) * (physinfo.max_cpu_id + 1));
3375 if (vcpuid != -1) {
3376 if (libxl_set_vcpuaffinity(&ctx, domid, vcpuid,
3377 cpumap, physinfo.max_cpu_id + 1) == -1) {
3378 fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
3381 else {
3382 if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &cpusize))) {
3383 fprintf(stderr, "libxl_list_vcpu failed.\n");
3384 goto vcpupin_out;
3386 for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
3387 if (libxl_set_vcpuaffinity(&ctx, domid, vcpuinfo->vcpuid,
3388 cpumap, physinfo.max_cpu_id + 1) == -1) {
3389 fprintf(stderr, "libxl_list_vcpu failed on vcpu `%u'.\n", vcpuinfo->vcpuid);
3393 vcpupin_out1:
3394 free(cpumap);
3395 vcpupin_out:
3399 int main_vcpupin(int argc, char **argv)
3401 int opt;
3403 if (argc != 5) {
3404 help("vcpu-pin");
3405 exit(0);
3407 while ((opt = getopt(argc, argv, "h")) != -1) {
3408 switch (opt) {
3409 case 'h':
3410 help("vcpu-pin");
3411 exit(0);
3412 default:
3413 fprintf(stderr, "option `%c' not supported.\n", opt);
3414 break;
3418 vcpupin(argv[2], argv[3] , argv[4]);
3419 exit(0);
3422 void vcpuset(char *d, char* nr_vcpus)
3424 char *endptr;
3425 unsigned int max_vcpus;
3427 max_vcpus = strtoul(nr_vcpus, &endptr, 10);
3428 if (nr_vcpus == endptr) {
3429 fprintf(stderr, "Error: Invalid argument.\n");
3430 return;
3433 find_domain(d);
3435 if (libxl_set_vcpucount(&ctx, domid, max_vcpus) == ERROR_INVAL) {
3436 fprintf(stderr, "Error: Cannot set vcpus greater than max vcpus on running domain or lesser than 1.\n");
3440 int main_vcpuset(int argc, char **argv)
3442 int opt;
3444 if (argc != 4) {
3445 help("vcpu-set");
3446 exit(0);
3448 while ((opt = getopt(argc, argv, "h")) != -1) {
3449 switch (opt) {
3450 case 'h':
3451 help("vcpu-set");
3452 exit(0);
3453 default:
3454 fprintf(stderr, "option `%c' not supported.\n", opt);
3455 break;
3459 vcpuset(argv[2], argv[3]);
3460 exit(0);
3463 static void output_xeninfo(void)
3465 const libxl_version_info *info;
3466 int sched_id;
3468 if (!(info = libxl_get_version_info(&ctx))) {
3469 fprintf(stderr, "libxl_get_version_info failed.\n");
3470 return;
3473 if ((sched_id = libxl_get_sched_id(&ctx)) < 0) {
3474 fprintf(stderr, "get_sched_id sysctl failed.\n");
3475 return;
3478 printf("xen_major : %d\n", info->xen_version_major);
3479 printf("xen_minor : %d\n", info->xen_version_minor);
3480 printf("xen_extra : %s\n", info->xen_version_extra);
3481 printf("xen_caps : %s\n", info->capabilities);
3482 printf("xen_scheduler : %s\n",
3483 sched_id == XEN_SCHEDULER_SEDF ? "sedf" :
3484 sched_id == XEN_SCHEDULER_CREDIT ? "credit" :
3485 sched_id == XEN_SCHEDULER_CREDIT2 ? "credit2" : "unknown");
3486 printf("xen_pagesize : %lu\n", info->pagesize);
3487 printf("platform_params : virt_start=0x%lx\n", info->virt_start);
3488 printf("xen_changeset : %s\n", info->changeset);
3489 printf("xen_commandline : %s\n", info->commandline);
3490 printf("cc_compiler : %s\n", info->compiler);
3491 printf("cc_compile_by : %s\n", info->compile_by);
3492 printf("cc_compile_domain : %s\n", info->compile_domain);
3493 printf("cc_compile_date : %s\n", info->compile_date);
3495 return;
3498 static void output_nodeinfo(void)
3500 struct utsname utsbuf;
3502 if (uname(&utsbuf) < 0)
3503 return;
3505 printf("host : %s\n", utsbuf.nodename);
3506 printf("release : %s\n", utsbuf.release);
3507 printf("version : %s\n", utsbuf.version);
3508 printf("machine : %s\n", utsbuf.machine);
3511 static void output_physinfo(void)
3513 libxl_physinfo info;
3514 const libxl_version_info *vinfo;
3515 unsigned int i;
3517 if (libxl_get_physinfo(&ctx, &info) != 0) {
3518 fprintf(stderr, "libxl_physinfo failed.\n");
3519 return;
3522 printf("nr_cpus : %d\n", info.nr_cpus);
3523 printf("nr_nodes : %d\n", info.nr_nodes);
3524 printf("cores_per_socket : %d\n", info.cores_per_socket);
3525 printf("threads_per_core : %d\n", info.threads_per_core);
3526 printf("cpu_mhz : %d\n", info.cpu_khz / 1000);
3527 printf("hw_caps : ");
3528 for (i = 0; i < 8; i++)
3529 printf("%08x%c", info.hw_cap[i], i < 7 ? ':' : '\n');
3530 printf("virt_caps :");
3531 if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm)
3532 printf(" hvm");
3533 if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm_directio)
3534 printf(" hvm_directio");
3535 printf("\n");
3536 vinfo = libxl_get_version_info(&ctx);
3537 if (vinfo) {
3538 i = (1 << 20) / vinfo->pagesize;
3539 printf("total_memory : %"PRIu64"\n", info.total_pages / i);
3540 printf("free_memory : %"PRIu64"\n", info.free_pages / i);
3543 return;
3546 static void info(void)
3548 output_nodeinfo();
3550 output_physinfo();
3552 output_xeninfo();
3554 printf("xend_config_format : 4\n");
3556 return;
3559 int main_info(int argc, char **argv)
3561 int opt;
3563 while ((opt = getopt(argc, argv, "h")) != -1) {
3564 switch (opt) {
3565 case 'h':
3566 help("info");
3567 exit(0);
3568 default:
3569 fprintf(stderr, "option `%c' not supported.\n", opt);
3570 break;
3574 info();
3575 exit(0);
3578 static int sched_credit_domain_get(
3579 int domid, libxl_sched_credit *scinfo)
3581 int rc;
3583 rc = libxl_sched_credit_domain_get(&ctx, domid, scinfo);
3584 if (rc)
3585 fprintf(stderr, "libxl_sched_credit_domain_get failed.\n");
3587 return rc;
3590 static int sched_credit_domain_set(
3591 int domid, libxl_sched_credit *scinfo)
3593 int rc;
3595 rc = libxl_sched_credit_domain_set(&ctx, domid, scinfo);
3596 if (rc)
3597 fprintf(stderr, "libxl_sched_credit_domain_set failed.\n");
3599 return rc;
3602 static void sched_credit_domain_output(
3603 int domid, libxl_sched_credit *scinfo)
3605 printf("%-33s %4d %6d %4d\n",
3606 libxl_domid_to_name(&ctx, domid),
3607 domid,
3608 scinfo->weight,
3609 scinfo->cap);
3612 int main_sched_credit(int argc, char **argv)
3614 libxl_dominfo *info;
3615 libxl_sched_credit scinfo;
3616 int nb_domain, i;
3617 char *dom = NULL;
3618 int weight = 256, cap = 0, opt_w = 0, opt_c = 0;
3619 int opt, rc;
3621 while ((opt = getopt(argc, argv, "hd:w:c:")) != -1) {
3622 switch (opt) {
3623 case 'd':
3624 dom = optarg;
3625 break;
3626 case 'w':
3627 weight = strtol(optarg, NULL, 10);
3628 opt_w = 1;
3629 break;
3630 case 'c':
3631 cap = strtol(optarg, NULL, 10);
3632 opt_c = 1;
3633 break;
3634 case 'h':
3635 help("sched-credit");
3636 exit(0);
3637 default:
3638 fprintf(stderr, "option `%c' not supported.\n", opt);
3639 break;
3643 if (!dom && (opt_w || opt_c)) {
3644 fprintf(stderr, "Must specify a domain.\n");
3645 exit(1);
3648 if (!dom) { /* list all domain's credit scheduler info */
3649 info = libxl_list_domain(&ctx, &nb_domain);
3650 if (!info) {
3651 fprintf(stderr, "libxl_domain_infolist failed.\n");
3652 exit(1);
3655 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
3656 for (i = 0; i < nb_domain; i++) {
3657 rc = sched_credit_domain_get(info[i].domid, &scinfo);
3658 if (rc)
3659 exit(-rc);
3660 sched_credit_domain_output(info[i].domid, &scinfo);
3662 } else {
3663 find_domain(dom);
3665 rc = sched_credit_domain_get(domid, &scinfo);
3666 if (rc)
3667 exit(-rc);
3669 if (!opt_w && !opt_c) { /* output credit scheduler info */
3670 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
3671 sched_credit_domain_output(domid, &scinfo);
3672 } else { /* set credit scheduler paramaters */
3673 if (opt_w)
3674 scinfo.weight = weight;
3675 if (opt_c)
3676 scinfo.cap = cap;
3677 rc = sched_credit_domain_set(domid, &scinfo);
3678 if (rc)
3679 exit(-rc);
3683 exit(0);
3686 int main_domid(int argc, char **argv)
3688 int opt;
3689 char *domname = NULL;
3691 while ((opt = getopt(argc, argv, "h")) != -1) {
3692 switch (opt) {
3693 case 'h':
3694 help("domid");
3695 exit(0);
3696 default:
3697 fprintf(stderr, "option `%c' not supported.\n", opt);
3698 break;
3702 domname = argv[optind];
3703 if (!domname) {
3704 fprintf(stderr, "Must specify a domain name.\n\n");
3705 help("domid");
3706 exit(1);
3709 if (libxl_name_to_domid(&ctx, domname, &domid)) {
3710 fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
3711 exit(1);
3714 printf("%d\n", domid);
3716 exit(0);
3719 int main_domname(int argc, char **argv)
3721 int opt;
3722 char *domname = NULL;
3723 char *endptr = NULL;
3725 while ((opt = getopt(argc, argv, "h")) != -1) {
3726 switch (opt) {
3727 case 'h':
3728 help("domname");
3729 exit(0);
3730 default:
3731 fprintf(stderr, "option `%c' not supported.\n", opt);
3732 break;
3736 if (!argv[optind]) {
3737 fprintf(stderr, "Must specify a domain id.\n\n");
3738 help("domname");
3739 exit(1);
3741 domid = strtol(argv[optind], &endptr, 10);
3742 if (domid == 0 && !strcmp(endptr, argv[optind])) {
3743 /*no digits at all*/
3744 fprintf(stderr, "Invalid domain id.\n\n");
3745 exit(1);
3748 domname = libxl_domid_to_name(&ctx, domid);
3749 if (!domname) {
3750 fprintf(stderr, "Can't get domain name of domain id '%d', maybe this domain does not exist.\n", domid);
3751 exit(1);
3754 printf("%s\n", domname);
3756 exit(0);
3759 int main_rename(int argc, char **argv)
3761 int opt;
3762 char *dom;
3763 char *new_name;
3765 while ((opt = getopt(argc, argv, "h")) != -1) {
3766 switch (opt) {
3767 case 'h':
3768 help("rename");
3769 exit(0);
3770 default:
3771 fprintf(stderr, "option `%c' not supported.\n", opt);
3772 break;
3776 dom = argv[optind++];
3777 if (!dom || !argv[optind]) {
3778 fprintf(stderr, "'xl rename' requires 2 arguments.\n\n");
3779 help("rename");
3780 exit(1);
3783 find_domain(dom);
3784 new_name = argv[optind];
3786 if (libxl_domain_rename(&ctx, domid, common_domname, new_name, 0)) {
3787 fprintf(stderr, "Can't rename domain '%s'.\n", dom);
3788 exit(1);
3791 exit(0);
3794 int main_trigger(int argc, char **argv)
3796 int opt;
3797 char *trigger_name = NULL;
3798 char *endptr = NULL;
3799 char *dom = NULL;
3800 int vcpuid = 0;
3802 while ((opt = getopt(argc, argv, "h")) != -1) {
3803 switch (opt) {
3804 case 'h':
3805 help("trigger");
3806 exit(0);
3807 default:
3808 fprintf(stderr, "option `%c' not supported.\n", opt);
3809 break;
3813 dom = argv[optind++];
3814 if (!dom || !argv[optind]) {
3815 fprintf(stderr, "'xl trigger' requires between 2 and 3 arguments.\n\n");
3816 help("trigger");
3817 exit(1);
3820 find_domain(dom);
3822 trigger_name = argv[optind++];
3824 if (argv[optind]) {
3825 vcpuid = strtol(argv[optind], &endptr, 10);
3826 if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
3827 fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
3831 libxl_send_trigger(&ctx, domid, trigger_name, vcpuid);
3833 exit(0);
3837 int main_sysrq(int argc, char **argv)
3839 int opt;
3840 char *sysrq = NULL;
3841 char *dom = NULL;
3843 while ((opt = getopt(argc, argv, "h")) != -1) {
3844 switch (opt) {
3845 case 'h':
3846 help("sysrq");
3847 exit(0);
3848 default:
3849 fprintf(stderr, "option `%c' not supported.\n", opt);
3850 break;
3854 dom = argv[optind++];
3855 if (!dom || !argv[optind]) {
3856 fprintf(stderr, "'xl sysrq' requires 2 arguments.\n\n");
3857 help("sysrq");
3858 exit(1);
3861 find_domain(dom);
3863 sysrq = argv[optind];
3865 if (sysrq[1] != '\0') {
3866 fprintf(stderr, "Invalid sysrq.\n\n");
3867 help("sysrq");
3868 exit(1);
3871 libxl_send_sysrq(&ctx, domid, sysrq[0]);
3873 exit(0);
3876 int main_debug_keys(int argc, char **argv)
3878 int opt;
3879 char *keys;
3881 while ((opt = getopt(argc, argv, "h")) != -1) {
3882 switch (opt) {
3883 case 'h':
3884 help("debug-keys");
3885 exit(0);
3886 default:
3887 fprintf(stderr, "option not supported\n");
3888 break;
3891 if (optind >= argc) {
3892 help("debug-keys");
3893 exit(2);
3896 keys = argv[optind];
3898 if (libxl_send_debug_keys(&ctx, keys)) {
3899 fprintf(stderr, "cannot send debug keys: %s\n", keys);
3900 exit(1);
3903 exit(0);
3906 int main_dmesg(int argc, char **argv)
3908 unsigned int clear = 0;
3909 libxl_xen_console_reader *cr;
3910 char *line;
3911 int opt, ret = 1;
3913 while ((opt = getopt(argc, argv, "hc")) != -1) {
3914 switch (opt) {
3915 case 'c':
3916 clear = 1;
3917 break;
3918 case 'h':
3919 help("dmesg");
3920 exit(0);
3921 default:
3922 fprintf(stderr, "option not supported\n");
3923 break;
3927 cr = libxl_xen_console_read_start(&ctx, clear);
3928 if (!cr)
3929 goto finish;
3931 while ((ret = libxl_xen_console_read_line(&ctx, cr, &line)) > 0)
3932 printf("%s", line);
3934 finish:
3935 libxl_xen_console_read_finish(&ctx, cr);
3936 exit(ret);
3939 int main_top(int argc, char **argv)
3941 int opt;
3943 while ((opt = getopt(argc, argv, "h")) != -1) {
3944 switch (opt) {
3945 case 'h':
3946 help("top");
3947 exit(0);
3948 default:
3949 fprintf(stderr, "option `%c' not supported.\n", opt);
3950 break;
3954 exit(system("xentop"));
3957 int main_networkattach(int argc, char **argv)
3959 int opt;
3960 libxl_device_nic nic;
3961 char *endptr, *tok;
3962 int i;
3963 unsigned int val;
3965 if ((argc < 3) || (argc > 11)) {
3966 help("network-attach");
3967 exit(0);
3969 while ((opt = getopt(argc, argv, "h")) != -1) {
3970 switch (opt) {
3971 case 'h':
3972 help("network-attach");
3973 exit(0);
3974 default:
3975 fprintf(stderr, "option `%c' not supported.\n", opt);
3976 break;
3980 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
3981 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
3982 exit(1);
3984 init_nic_info(&nic, -1);
3985 for (argv += 3, argc -= 3; argc > 0; ++argv, --argc) {
3986 if (!strncmp("type=", *argv, 5)) {
3987 if (!strncmp("vif", (*argv) + 5, 4)) {
3988 nic.nictype = NICTYPE_VIF;
3989 } else if (!strncmp("ioemu", (*argv) + 5, 5)) {
3990 nic.nictype = NICTYPE_IOEMU;
3991 } else {
3992 fprintf(stderr, "Invalid parameter `type'.\n");
3993 exit(1);
3995 } else if (!strncmp("mac=", *argv, 4)) {
3996 tok = strtok((*argv) + 4, ":");
3997 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
3998 val = strtoul(tok, &endptr, 16);
3999 if ((tok == endptr) || (val > 255)) {
4000 fprintf(stderr, "Invalid parameter `mac'.\n");
4001 exit(1);
4003 nic.mac[i] = val;
4005 } else if (!strncmp("bridge=", *argv, 7)) {
4006 nic.bridge = (*argv) + 7;
4007 } else if (!strncmp("ip=", *argv, 3)) {
4008 if (!inet_aton((*argv) + 3, &(nic.ip))) {
4009 fprintf(stderr, "Invalid parameter `ip'.\n");
4010 exit(1);
4012 } else if (!strncmp("script=", *argv, 6)) {
4013 nic.script = (*argv) + 6;
4014 } else if (!strncmp("backend=", *argv, 8)) {
4015 val = strtoul((*argv) + 8, &endptr, 10);
4016 if (((*argv) + 8) == endptr) {
4017 fprintf(stderr, "Invalid parameter `backend'.\n");
4018 exit(1);
4020 nic.backend_domid = val;
4021 } else if (!strncmp("vifname=", *argv, 8)) {
4022 nic.ifname = (*argv) + 8;
4023 } else if (!strncmp("model=", *argv, 6)) {
4024 nic.model = (*argv) + 6;
4025 } else if (!strncmp("rate=", *argv, 5)) {
4026 } else if (!strncmp("accel=", *argv, 6)) {
4027 } else {
4028 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4029 exit(1);
4032 nic.domid = domid;
4033 if (libxl_device_nic_add(&ctx, domid, &nic)) {
4034 fprintf(stderr, "libxl_device_nic_add failed.\n");
4035 exit(1);
4037 exit(0);
4040 int main_networklist(int argc, char **argv)
4042 int opt;
4043 libxl_nicinfo *nics;
4044 unsigned int nb;
4046 if (argc < 3) {
4047 help("network-list");
4048 exit(1);
4050 while ((opt = getopt(argc, argv, "h")) != -1) {
4051 switch (opt) {
4052 case 'h':
4053 help("network-list");
4054 exit(0);
4055 default:
4056 fprintf(stderr, "option `%c' not supported.\n", opt);
4057 break;
4061 /* Idx BE MAC Hdl Sta evch txr/rxr BE-path */
4062 printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
4063 "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
4064 for (argv += 2, argc -= 2; argc > 0; --argc, ++argv) {
4065 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4066 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4067 continue;
4069 if (!(nics = libxl_list_nics(&ctx, domid, &nb))) {
4070 continue;
4072 for (; nb > 0; --nb, ++nics) {
4073 /* Idx BE */
4074 printf("%-3d %-2d ", nics->devid, nics->backend_id);
4075 /* MAC */
4076 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4077 nics->mac[0], nics->mac[1], nics->mac[2],
4078 nics->mac[3], nics->mac[4], nics->mac[5]);
4079 /* Hdl Sta evch txr/rxr BE-path */
4080 printf("%6d %5d %6d %5d/%-11d %-30s\n",
4081 nics->devid, nics->state, nics->evtch,
4082 nics->rref_tx, nics->rref_rx, nics->backend);
4085 exit(0);
4088 int main_networkdetach(int argc, char **argv)
4090 int opt;
4091 libxl_device_nic nic;
4093 if (argc != 4) {
4094 help("network-detach");
4095 exit(0);
4097 while ((opt = getopt(argc, argv, "h")) != -1) {
4098 switch (opt) {
4099 case 'h':
4100 help("network-detach");
4101 exit(0);
4102 default:
4103 fprintf(stderr, "option `%c' not supported.\n", opt);
4104 break;
4108 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
4109 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
4110 exit(1);
4113 if (!strchr(argv[3], ':')) {
4114 if (libxl_devid_to_device_nic(&ctx, domid, argv[3], &nic)) {
4115 fprintf(stderr, "Unknown device %s.\n", argv[3]);
4116 exit(1);
4118 } else {
4119 if (libxl_mac_to_device_nic(&ctx, domid, argv[3], &nic)) {
4120 fprintf(stderr, "Unknown device %s.\n", argv[3]);
4121 exit(1);
4124 if (libxl_device_nic_del(&ctx, &nic, 1)) {
4125 fprintf(stderr, "libxl_device_nic_del failed.\n");
4126 exit(1);
4128 exit(0);
4131 int main_blockattach(int argc, char **argv)
4133 int opt;
4134 char *tok;
4135 uint32_t fe_domid, be_domid = 0;
4136 libxl_device_disk disk = { 0 };
4138 if ((argc < 5) || (argc > 7)) {
4139 help("block-attach");
4140 exit(0);
4142 while ((opt = getopt(argc, argv, "h")) != -1) {
4143 switch (opt) {
4144 case 'h':
4145 help("block-attach");
4146 exit(0);
4147 default:
4148 fprintf(stderr, "option `%c' not supported.\n", opt);
4149 break;
4153 tok = strtok(argv[3], ":");
4154 if (!strcmp(tok, "phy")) {
4155 disk.phystype = PHYSTYPE_PHY;
4156 } else if (!strcmp(tok, "file")) {
4157 disk.phystype = PHYSTYPE_FILE;
4158 } else if (!strcmp(tok, "tap")) {
4159 tok = strtok(NULL, ":");
4160 if (!strcmp(tok, "aio")) {
4161 disk.phystype = PHYSTYPE_AIO;
4162 } else if (!strcmp(tok, "vhd")) {
4163 disk.phystype = PHYSTYPE_VHD;
4164 } else if (!strcmp(tok, "qcow")) {
4165 disk.phystype = PHYSTYPE_QCOW;
4166 } else if (!strcmp(tok, "qcow2")) {
4167 disk.phystype = PHYSTYPE_QCOW2;
4168 } else {
4169 fprintf(stderr, "Error: `%s' is not a valid disk image.\n", tok);
4170 exit(1);
4172 } else {
4173 fprintf(stderr, "Error: `%s' is not a valid block device.\n", tok);
4174 exit(1);
4176 disk.physpath = strtok(NULL, "\0");
4177 if (!disk.physpath) {
4178 fprintf(stderr, "Error: missing path to disk image.\n");
4179 exit(1);
4181 disk.virtpath = argv[4];
4182 disk.unpluggable = 1;
4183 disk.readwrite = ((argc <= 4) || (argv[5][0] == 'w'));
4185 if (domain_qualifier_to_domid(argv[2], &fe_domid, 0) < 0) {
4186 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
4187 exit(1);
4189 if (argc == 7) {
4190 if (domain_qualifier_to_domid(argv[6], &be_domid, 0) < 0) {
4191 fprintf(stderr, "%s is an invalid domain identifier\n", argv[6]);
4192 exit(1);
4195 disk.domid = fe_domid;
4196 disk.backend_domid = be_domid;
4197 if (libxl_device_disk_add(&ctx, fe_domid, &disk)) {
4198 fprintf(stderr, "libxl_device_disk_add failed.\n");
4200 exit(0);
4203 int main_blocklist(int argc, char **argv)
4205 int opt;
4206 int nb;
4207 libxl_device_disk *disks;
4208 libxl_diskinfo diskinfo;
4210 if (argc < 3) {
4211 help("block-list");
4212 exit(0);
4214 while ((opt = getopt(argc, argv, "h")) != -1) {
4215 switch (opt) {
4216 case 'h':
4217 help("block-list");
4218 exit(0);
4219 default:
4220 fprintf(stderr, "option `%c' not supported.\n", opt);
4221 break;
4225 printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
4226 "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
4227 for (argv += 2, argc -= 2; argc > 0; --argc, ++argv) {
4228 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4229 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4230 continue;
4232 disks = libxl_device_disk_list(&ctx, domid, &nb);
4233 if (!disks) {
4234 continue;
4236 for (; nb > 0; --nb, ++disks) {
4237 if (!libxl_device_disk_getinfo(&ctx, domid, disks, &diskinfo)) {
4238 /* Vdev BE hdl st evch rref BE-path*/
4239 printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
4240 diskinfo.devid, diskinfo.backend_id, diskinfo.frontend_id,
4241 diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
4245 exit(0);
4248 int main_blockdetach(int argc, char **argv)
4250 int opt;
4251 libxl_device_disk disk;
4253 if (argc != 4) {
4254 help("block-detach");
4255 exit(0);
4257 while ((opt = getopt(argc, argv, "h")) != -1) {
4258 switch (opt) {
4259 case 'h':
4260 help("block-detach");
4261 exit(0);
4262 default:
4263 fprintf(stderr, "option `%c' not supported.\n", opt);
4264 break;
4268 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
4269 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
4270 exit(1);
4272 if (libxl_devid_to_device_disk(&ctx, domid, argv[3], &disk)) {
4273 fprintf(stderr, "Error: Device %s not connected.\n", argv[3]);
4274 exit(1);
4276 if (libxl_device_disk_del(&ctx, &disk, 1)) {
4277 fprintf(stderr, "libxl_device_del failed.\n");
4279 exit(0);
4282 int main_network2attach(int argc, char **argv)
4284 int opt;
4285 char *tok, *endptr;
4286 char *back_dom = NULL;
4287 uint32_t domid, back_domid;
4288 unsigned int val, i;
4289 libxl_device_net2 net2;
4291 if ((argc < 3) || (argc > 12)) {
4292 help("network2-attach");
4293 exit(0);
4295 while ((opt = getopt(argc, argv, "h")) != -1) {
4296 switch (opt) {
4297 case 'h':
4298 help("network2-attach");
4299 exit(0);
4300 default:
4301 fprintf(stderr, "option `%c' not supported.\n", opt);
4302 break;
4306 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
4307 fprintf(stderr, "%s is an invalid domain identifier\n", argv[1]);
4308 exit(1);
4310 init_net2_info(&net2, -1);
4311 for (argv += 3, argc -= 3; argc > 0; --argc, ++argv) {
4312 if (!strncmp("front_mac=", *argv, 10)) {
4313 tok = strtok((*argv) + 10, ":");
4314 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4315 val = strtoul(tok, &endptr, 16);
4316 if ((tok == endptr) || (val > 255)) {
4317 fprintf(stderr, "Invalid parameter `front_mac'.\n");
4318 exit(1);
4320 net2.front_mac[i] = val;
4322 } else if (!strncmp("back_mac=", *argv, 9)) {
4323 tok = strtok((*argv) + 10, ":");
4324 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4325 val = strtoul(tok, &endptr, 16);
4326 if ((tok == endptr) || (val > 255)) {
4327 fprintf(stderr, "Invalid parameter back_mac=%s.\n", *argv + 9);
4328 exit(1);
4330 net2.back_mac[i] = val;
4332 } else if (!strncmp("backend=", *argv, 8)) {
4333 back_dom = *argv;
4334 } else if (!strncmp("trusted=", *argv, 8)) {
4335 net2.trusted = (*((*argv) + 8) == '1');
4336 } else if (!strncmp("back_trusted=", *argv, 13)) {
4337 net2.back_trusted = (*((*argv) + 13) == '1');
4338 } else if (!strncmp("bridge=", *argv, 7)) {
4339 net2.bridge = *argv + 13;
4340 } else if (!strncmp("filter_mac=", *argv, 11)) {
4341 net2.filter_mac = (*((*argv) + 11) == '1');
4342 } else if (!strncmp("front_filter_mac=", *argv, 17)) {
4343 net2.front_filter_mac = (*((*argv) + 17) == '1');
4344 } else if (!strncmp("pdev=", *argv, 5)) {
4345 val = strtoul(*argv + 5, &endptr, 10);
4346 if (endptr == (*argv + 5)) {
4347 fprintf(stderr, "Invalid parameter pdev=%s.\n", *argv + 5);
4348 exit(1);
4350 net2.pdev = val;
4351 } else if (!strncmp("max_bypasses=", *argv, 13)) {
4352 val = strtoul(*argv + 13, &endptr, 10);
4353 if (endptr == (*argv + 13)) {
4354 fprintf(stderr, "Invalid parameter max_bypasses=%s.\n", *argv + 13);
4355 exit(1);
4357 net2.max_bypasses = val;
4358 } else {
4359 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4360 exit(1);
4364 if (back_dom) {
4365 if (domain_qualifier_to_domid(back_dom, &back_domid, 0) < 0) {
4366 fprintf(stderr, "%s is an invalid domain identifier\n", back_dom);
4367 exit(1);
4370 net2.domid = domid;
4371 net2.backend_domid = back_domid;
4372 if (libxl_device_net2_add(&ctx, domid, &net2)) {
4373 fprintf(stderr, "libxl_device_net2_add failed.\n");
4375 exit(0);
4378 int main_network2list(int argc, char **argv)
4380 int opt;
4381 unsigned int nb;
4382 libxl_net2info *net2s;
4384 if (argc < 3) {
4385 help("network2-list");
4386 exit(0);
4388 while ((opt = getopt(argc, argv, "h")) != -1) {
4389 switch (opt) {
4390 case 'h':
4391 help("network2-list");
4392 exit(0);
4393 default:
4394 fprintf(stderr, "option `%c' not supported.\n", opt);
4395 break;
4399 printf("%-3s %-2s %-5s %-17s %-17s %-7s %-6s %-30s\n",
4400 "Idx", "BE", "state", "Mac Addr.", "Remote Mac Addr.",
4401 "trusted", "filter", "backend");
4402 for (argv += 2, argc -=2; argc > 0; --argc, ++argv) {
4403 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4404 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4405 continue;
4407 if ((net2s = libxl_device_net2_list(&ctx, domid, &nb))) {
4408 for (; nb > 0; --nb, ++net2s) {
4409 printf("%3d %2d %5d ", net2s->devid, net2s->backend_id, net2s->state);
4410 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4411 net2s->mac[0], net2s->mac[1], net2s->mac[2],
4412 net2s->mac[3], net2s->mac[4], net2s->mac[5]);
4413 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4414 net2s->back_mac[0], net2s->back_mac[1], net2s->back_mac[2],
4415 net2s->back_mac[3], net2s->back_mac[4], net2s->back_mac[5]);
4416 printf("%-7d %-6d %-30s\n", net2s->trusted, net2s->filter_mac, net2s->backend);
4420 exit(0);
4423 int main_network2detach(int argc, char **argv)
4425 int opt;
4426 libxl_device_net2 net2;
4428 if (argc != 4) {
4429 help("network2-detach");
4430 exit(0);
4432 while ((opt = getopt(argc, argv, "h")) != -1) {
4433 switch (opt) {
4434 case 'h':
4435 help("network2-detach");
4436 exit(0);
4437 default:
4438 fprintf(stderr, "option `%c' not supported.\n", opt);
4439 break;
4443 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
4444 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
4445 exit(1);
4447 if (libxl_devid_to_device_net2(&ctx, domid, argv[3], &net2)) {
4448 fprintf(stderr, "Error: Device %s not connected.\n", argv[3]);
4449 exit(1);
4451 if (libxl_device_net2_del(&ctx, &net2, 1)) {
4452 fprintf(stderr, "libxl_device_net2_del failed.\n");
4453 exit(1);
4455 exit(0);
4458 static char *uptime_to_string(unsigned long time, int short_mode)
4460 int sec, min, hour, day;
4461 char *time_string;
4462 int ret;
4464 day = (int)(time / 86400);
4465 time -= (day * 86400);
4466 hour = (int)(time / 3600);
4467 time -= (hour * 3600);
4468 min = (int)(time / 60);
4469 time -= (min * 60);
4470 sec = time;
4472 if (short_mode)
4473 if (day > 1)
4474 ret = asprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
4475 else if (day == 1)
4476 ret = asprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
4477 else
4478 ret = asprintf(&time_string, "%2d:%02d", hour, min);
4479 else
4480 if (day > 1)
4481 ret = asprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
4482 else if (day == 1)
4483 ret = asprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
4484 else
4485 ret = asprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
4487 if (ret < 0)
4488 return NULL;
4489 return time_string;
4492 static char *current_time_to_string(time_t now)
4494 char now_str[100];
4495 struct tm *tmp;
4497 tmp = localtime(&now);
4498 if (tmp == NULL) {
4499 fprintf(stderr, "Get localtime error");
4500 exit(-1);
4502 if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
4503 fprintf(stderr, "strftime returned 0");
4504 exit(-1);
4506 return strdup(now_str);
4509 static void print_dom0_uptime(int short_mode, time_t now)
4511 int fd;
4512 char buf[512];
4513 uint32_t uptime = 0;
4514 char *uptime_str = NULL;
4515 char *now_str = NULL;
4517 fd = open("/proc/uptime", O_RDONLY);
4518 if (fd == -1)
4519 goto err;
4521 if (read(fd, buf, sizeof(buf)) == -1) {
4522 close(fd);
4523 goto err;
4525 close(fd);
4527 strtok(buf, " ");
4528 uptime = strtoul(buf, NULL, 10);
4530 if (short_mode)
4532 now_str = current_time_to_string(now);
4533 uptime_str = uptime_to_string(uptime, 1);
4534 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
4535 libxl_domid_to_name(&ctx, 0), 0);
4537 else
4539 uptime_str = uptime_to_string(uptime, 0);
4540 printf("%-33s %4d %s\n", libxl_domid_to_name(&ctx, 0),
4541 0, uptime_str);
4544 if (now_str)
4545 free(now_str);
4546 if (uptime_str)
4547 free(uptime_str);
4548 return;
4549 err:
4550 fprintf(stderr, "Can not get Dom0 uptime.\n");
4551 exit(-1);
4554 static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
4556 uint32_t s_time = 0;
4557 uint32_t uptime = 0;
4558 char *uptime_str = NULL;
4559 char *now_str = NULL;
4561 s_time = libxl_vm_get_start_time(&ctx, domuid);
4562 if (s_time == -1)
4563 return;
4564 uptime = now - s_time;
4565 if (short_mode)
4567 now_str = current_time_to_string(now);
4568 uptime_str = uptime_to_string(uptime, 1);
4569 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
4570 libxl_domid_to_name(&ctx, domuid), domuid);
4572 else
4574 uptime_str = uptime_to_string(uptime, 0);
4575 printf("%-33s %4d %s\n", libxl_domid_to_name(&ctx, domuid),
4576 domuid, uptime_str);
4579 if (now_str)
4580 free(now_str);
4581 if (uptime_str)
4582 free(uptime_str);
4583 return;
4586 static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
4588 libxl_vminfo *info;
4589 time_t now;
4590 int nb_vm, i;
4592 now = time(NULL);
4594 if (!short_mode)
4595 printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
4597 if (nb_doms == 0) {
4598 print_dom0_uptime(short_mode, now);
4599 info = libxl_list_vm(&ctx, &nb_vm);
4600 for (i = 0; i < nb_vm; i++)
4601 print_domU_uptime(info[i].domid, short_mode, now);
4602 } else {
4603 for (i = 0; i < nb_doms; i++) {
4604 if (doms[i] == 0)
4605 print_dom0_uptime(short_mode, now);
4606 else
4607 print_domU_uptime(doms[i], short_mode, now);
4612 int main_uptime(int argc, char **argv)
4614 char *dom = NULL;
4615 int short_mode = 0;
4616 uint32_t domains[100];
4617 int nb_doms = 0;
4618 int opt;
4620 while ((opt = getopt(argc, argv, "hs")) != -1) {
4621 switch (opt) {
4622 case 's':
4623 short_mode = 1;
4624 break;
4625 case 'h':
4626 help("uptime");
4627 exit(0);
4628 default:
4629 fprintf(stderr, "option `%c' not supported.\n", opt);
4630 break;
4634 for (;(dom = argv[optind]) != NULL; nb_doms++,optind++) {
4635 find_domain(dom);
4636 domains[nb_doms] = domid;
4639 print_uptime(short_mode, domains, nb_doms);
4641 exit(0);
4644 int main_tmem_list(int argc, char **argv)
4646 char *dom = NULL;
4647 char *buf = NULL;
4648 int use_long = 0;
4649 int all = 0;
4650 int opt;
4652 while ((opt = getopt(argc, argv, "alh")) != -1) {
4653 switch (opt) {
4654 case 'l':
4655 use_long = 1;
4656 break;
4657 case 'a':
4658 all = 1;
4659 break;
4660 case 'h':
4661 help("tmem-list");
4662 exit(0);
4663 default:
4664 fprintf(stderr, "option `%c' not supported.\n", opt);
4665 break;
4669 dom = argv[optind];
4670 if (!dom && all == 0) {
4671 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4672 help("tmem-list");
4673 exit(1);
4676 if (all)
4677 domid = -1;
4678 else
4679 find_domain(dom);
4681 buf = libxl_tmem_list(&ctx, domid, use_long);
4682 if (buf == NULL)
4683 exit(-1);
4685 printf("%s\n", buf);
4686 free(buf);
4687 exit(0);
4690 int main_tmem_freeze(int argc, char **argv)
4692 char *dom = NULL;
4693 int all = 0;
4694 int opt;
4696 while ((opt = getopt(argc, argv, "ah")) != -1) {
4697 switch (opt) {
4698 case 'a':
4699 all = 1;
4700 break;
4701 case 'h':
4702 help("tmem-freeze");
4703 exit(0);
4704 default:
4705 fprintf(stderr, "option `%c' not supported.\n", opt);
4706 break;
4710 dom = argv[optind];
4711 if (!dom && all == 0) {
4712 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4713 help("tmem-freeze");
4714 exit(1);
4717 if (all)
4718 domid = -1;
4719 else
4720 find_domain(dom);
4722 libxl_tmem_freeze(&ctx, domid);
4723 exit(0);
4726 int main_tmem_destroy(int argc, char **argv)
4728 char *dom = NULL;
4729 int all = 0;
4730 int opt;
4732 while ((opt = getopt(argc, argv, "ah")) != -1) {
4733 switch (opt) {
4734 case 'a':
4735 all = 1;
4736 break;
4737 case 'h':
4738 help("tmem-destroy");
4739 exit(0);
4740 default:
4741 fprintf(stderr, "option `%c' not supported.\n", opt);
4742 break;
4746 dom = argv[optind];
4747 if (!dom && all == 0) {
4748 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4749 help("tmem-destroy");
4750 exit(1);
4753 if (all)
4754 domid = -1;
4755 else
4756 find_domain(dom);
4758 libxl_tmem_destroy(&ctx, domid);
4759 exit(0);
4762 int main_tmem_thaw(int argc, char **argv)
4764 char *dom = NULL;
4765 int all = 0;
4766 int opt;
4768 while ((opt = getopt(argc, argv, "ah")) != -1) {
4769 switch (opt) {
4770 case 'a':
4771 all = 1;
4772 break;
4773 case 'h':
4774 help("tmem-thaw");
4775 exit(0);
4776 default:
4777 fprintf(stderr, "option `%c' not supported.\n", opt);
4778 break;
4782 dom = argv[optind];
4783 if (!dom && all == 0) {
4784 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4785 help("tmem-thaw");
4786 exit(1);
4789 if (all)
4790 domid = -1;
4791 else
4792 find_domain(dom);
4794 libxl_tmem_thaw(&ctx, domid);
4795 exit(0);
4798 int main_tmem_set(int argc, char **argv)
4800 char *dom = NULL;
4801 uint32_t weight = 0, cap = 0, compress = 0;
4802 int opt_w = 0, opt_c = 0, opt_p = 0;
4803 int all = 0;
4804 int opt;
4806 while ((opt = getopt(argc, argv, "aw:c:p:h")) != -1) {
4807 switch (opt) {
4808 case 'a':
4809 all = 1;
4810 break;
4811 case 'w':
4812 weight = strtol(optarg, NULL, 10);
4813 opt_w = 1;
4814 break;
4815 case 'c':
4816 cap = strtol(optarg, NULL, 10);
4817 opt_c = 1;
4818 break;
4819 case 'p':
4820 compress = strtol(optarg, NULL, 10);
4821 opt_p = 1;
4822 break;
4823 case 'h':
4824 help("tmem-set");
4825 exit(0);
4826 default:
4827 fprintf(stderr, "option `%c' not supported.\n", opt);
4828 break;
4832 dom = argv[optind];
4833 if (!dom && all == 0) {
4834 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4835 help("tmem-set");
4836 exit(1);
4839 if (all)
4840 domid = -1;
4841 else
4842 find_domain(dom);
4844 if (!opt_w && !opt_c && !opt_p) {
4845 fprintf(stderr, "No set value specified.\n\n");
4846 help("tmem-set");
4847 exit(1);
4850 if (opt_w)
4851 libxl_tmem_set(&ctx, domid, "weight", weight);
4852 if (opt_c)
4853 libxl_tmem_set(&ctx, domid, "cap", cap);
4854 if (opt_p)
4855 libxl_tmem_set(&ctx, domid, "compress", compress);
4857 exit(0);
4860 int main_tmem_shared_auth(int argc, char **argv)
4862 char *autharg = NULL;
4863 char *endptr = NULL;
4864 char *dom = NULL;
4865 char *uuid = NULL;
4866 int auth = -1;
4867 int all = 0;
4868 int opt;
4870 while ((opt = getopt(argc, argv, "au:A:h")) != -1) {
4871 switch (opt) {
4872 case 'a':
4873 all = 1;
4874 break;
4875 case 'u':
4876 uuid = optarg;
4877 break;
4878 case 'A':
4879 autharg = optarg;
4880 break;
4881 case 'h':
4882 help("tmem-shared-auth");
4883 exit(0);
4884 default:
4885 fprintf(stderr, "option `%c' not supported.\n", opt);
4886 break;
4890 dom = argv[optind];
4891 if (!dom && all == 0) {
4892 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4893 help("tmem-shared-auth");
4894 exit(1);
4897 if (all)
4898 domid = -1;
4899 else
4900 find_domain(dom);
4902 if (uuid == NULL || autharg == NULL) {
4903 fprintf(stderr, "No uuid or auth specified.\n\n");
4904 help("tmem-shared-auth");
4905 exit(1);
4908 auth = strtol(autharg, &endptr, 10);
4909 if (*endptr != '\0') {
4910 fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
4911 exit(1);
4914 libxl_tmem_shared_auth(&ctx, domid, uuid, auth);
4916 exit(0);
4919 int main_tmem_freeable(int argc, char **argv)
4921 int opt;
4922 int mb;
4924 while ((opt = getopt(argc, argv, "h")) != -1) {
4925 switch (opt) {
4926 case 'h':
4927 help("tmem-freeable");
4928 exit(0);
4929 default:
4930 fprintf(stderr, "option `%c' not supported.\n", opt);
4931 break;
4935 mb = libxl_tmem_freeable(&ctx);
4936 if (mb == -1)
4937 exit(-1);
4939 printf("%d\n", mb);
4940 exit(0);