debuggers.hg

view tools/libxl/xl_cmdimpl.c @ 21994:fdf12cb3e2d1

Do not try to retrieve userdata for dom0

There is no userdata available regarding dom0, do not try to retrieve it

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Stefano Stabellini <sstabellini@xensource.com>
date Mon Aug 09 17:20:39 2010 +0100 (2010-08-09)
parents 493d70234c97
children 36c9f6ea9782
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 static void free_domain_config(struct domain_config *d_config)
147 {
148 free(d_config->disks);
149 free(d_config->vifs);
150 free(d_config->vif2s);
151 free(d_config->pcidevs);
152 free(d_config->vfbs);
153 free(d_config->vkbs);
154 }
156 /* Optional data, in order:
157 * 4 bytes uint32_t config file size
158 * n bytes config file in Unix text file format
159 */
161 #define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
163 static int qualifier_to_id(const char *p, uint32_t *id_r)
164 {
165 int i, alldigit;
167 alldigit = 1;
168 for (i = 0; p[i]; i++) {
169 if (!isdigit((uint8_t)p[i])) {
170 alldigit = 0;
171 break;
172 }
173 }
175 if (i > 0 && alldigit) {
176 *id_r = strtoul(p, NULL, 10);
177 return 0;
178 } else {
179 /* check here if it's a uuid and do proper conversion */
180 }
181 return 1;
182 }
184 static int domain_qualifier_to_domid(const char *p, uint32_t *domid_r,
185 int *was_name_r)
186 {
187 int was_name;
189 was_name = qualifier_to_id(p, domid_r);
190 if (was_name_r) *was_name_r = was_name;
191 return was_name ? libxl_name_to_domid(&ctx, p, domid_r) : 0;
192 }
194 static int pool_qualifier_to_poolid(const char *p, uint32_t *poolid_r,
195 int *was_name_r)
196 {
197 int was_name;
199 was_name = qualifier_to_id(p, poolid_r);
200 if (was_name_r) *was_name_r = was_name;
201 return was_name ? libxl_name_to_poolid(&ctx, p, poolid_r) : 0;
202 }
204 static void find_domain(const char *p)
205 {
206 int rc, was_name;
208 rc = domain_qualifier_to_domid(p, &domid, &was_name);
209 if (rc) {
210 fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
211 exit(2);
212 }
213 common_domname = was_name ? p : libxl_domid_to_name(&ctx, domid);
214 }
216 #define LOG(_f, _a...) dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
218 void dolog(const char *file, int line, const char *func, char *fmt, ...)
219 {
220 va_list ap;
221 char *s;
222 int rc;
224 va_start(ap, fmt);
225 rc = vasprintf(&s, fmt, ap);
226 va_end(ap);
227 if (rc >= 0)
228 libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
229 }
231 static void init_create_info(libxl_domain_create_info *c_info)
232 {
233 memset(c_info, '\0', sizeof(*c_info));
234 c_info->xsdata = NULL;
235 c_info->platformdata = NULL;
236 c_info->hap = 1;
237 c_info->hvm = 1;
238 c_info->oos = 1;
239 c_info->ssidref = 0;
240 c_info->poolid = 0;
241 }
243 static void init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info *c_info)
244 {
245 memset(b_info, '\0', sizeof(*b_info));
246 b_info->max_vcpus = 1;
247 b_info->max_memkb = 32 * 1024;
248 b_info->target_memkb = b_info->max_memkb;
249 b_info->disable_migrate = 0;
250 if (c_info->hvm) {
251 b_info->shadow_memkb = 0; /* Set later */
252 b_info->video_memkb = 8 * 1024;
253 b_info->kernel.path = "hvmloader";
254 b_info->hvm = 1;
255 b_info->u.hvm.pae = 1;
256 b_info->u.hvm.apic = 1;
257 b_info->u.hvm.acpi = 1;
258 b_info->u.hvm.nx = 1;
259 b_info->u.hvm.viridian = 0;
260 b_info->u.hvm.hpet = 1;
261 b_info->u.hvm.vpt_align = 1;
262 b_info->u.hvm.timer_mode = 1;
263 } else {
264 b_info->u.pv.slack_memkb = 8 * 1024;
265 }
266 }
268 static void random_uuid(libxl_uuid *uuid)
269 {
270 int i;
271 for (i = 0; i < 16; i++)
272 (*uuid)[i] = rand();
273 }
275 static void init_dm_info(libxl_device_model_info *dm_info,
276 libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
277 {
278 memset(dm_info, '\0', sizeof(*dm_info));
280 random_uuid(&dm_info->uuid);
282 dm_info->dom_name = c_info->name;
283 dm_info->device_model = "qemu-dm";
284 dm_info->videoram = b_info->video_memkb / 1024;
285 dm_info->apic = b_info->u.hvm.apic;
286 dm_info->vcpus = b_info->max_vcpus;
287 dm_info->vcpu_avail = b_info->cur_vcpus;
289 dm_info->stdvga = 0;
290 dm_info->vnc = 1;
291 dm_info->vnclisten = "127.0.0.1";
292 dm_info->vncdisplay = 0;
293 dm_info->vncunused = 1;
294 dm_info->keymap = NULL;
295 dm_info->sdl = 0;
296 dm_info->opengl = 0;
297 dm_info->nographic = 0;
298 dm_info->serial = NULL;
299 dm_info->boot = "cda";
300 dm_info->usb = 0;
301 dm_info->usbdevice = NULL;
302 dm_info->xen_platform_pci = 1;
303 }
305 static void init_nic_info(libxl_device_nic *nic_info, int devnum)
306 {
307 memset(nic_info, '\0', sizeof(*nic_info));
309 nic_info->backend_domid = 0;
310 nic_info->domid = 0;
311 nic_info->devid = devnum;
312 nic_info->mtu = 1492;
313 nic_info->model = "e1000";
314 nic_info->mac[0] = 0x00;
315 nic_info->mac[1] = 0x16;
316 nic_info->mac[2] = 0x3e;
317 nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
318 nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
319 nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
320 nic_info->ifname = NULL;
321 nic_info->bridge = "xenbr0";
322 CHK_ERRNO( asprintf(&nic_info->script, "%s/vif-bridge",
323 libxl_xen_script_dir_path()) );
324 nic_info->nictype = NICTYPE_IOEMU;
325 }
327 static void init_net2_info(libxl_device_net2 *net2_info, int devnum)
328 {
329 memset(net2_info, '\0', sizeof(*net2_info));
331 net2_info->devid = devnum;
332 net2_info->front_mac[0] = 0x00;
333 net2_info->front_mac[1] = 0x16;
334 net2_info->front_mac[2] = 0x3e;;
335 net2_info->front_mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
336 net2_info->front_mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
337 net2_info->front_mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
338 net2_info->back_mac[0] = 0x00;
339 net2_info->back_mac[1] = 0x16;
340 net2_info->back_mac[2] = 0x3e;
341 net2_info->back_mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
342 net2_info->back_mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
343 net2_info->back_mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
344 net2_info->back_trusted = 1;
345 net2_info->filter_mac = 1;
346 net2_info->max_bypasses = 5;
347 net2_info->bridge = "xenbr0";
348 }
350 static void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
351 {
352 memset(vfb, 0x00, sizeof(libxl_device_vfb));
353 vfb->devid = dev_num;
354 vfb->vnc = 1;
355 vfb->vnclisten = "127.0.0.1";
356 vfb->vncdisplay = 0;
357 vfb->vncunused = 1;
358 vfb->keymap = NULL;
359 vfb->sdl = 0;
360 vfb->opengl = 0;
361 }
363 static void init_vkb_info(libxl_device_vkb *vkb, int dev_num)
364 {
365 memset(vkb, 0x00, sizeof(libxl_device_vkb));
366 vkb->devid = dev_num;
367 }
369 static void init_console_info(libxl_device_console *console, int dev_num, libxl_domain_build_state *state)
370 {
371 memset(console, 0x00, sizeof(libxl_device_console));
372 console->devid = dev_num;
373 console->constype = CONSTYPE_XENCONSOLED;
374 if (state)
375 console->build_state = state;
376 }
378 static void printf_info(int domid,
379 struct domain_config *d_config,
380 libxl_device_model_info *dm_info)
381 {
382 int i;
384 libxl_domain_create_info *c_info = &d_config->c_info;
385 libxl_domain_build_info *b_info = &d_config->b_info;
387 printf("(domain\n\t(domid %d)\n", domid);
388 printf("\t(domain_create_info)\n");
389 printf("\t(hvm %d)\n", c_info->hvm);
390 printf("\t(hap %d)\n", c_info->hap);
391 printf("\t(oos %d)\n", c_info->oos);
392 printf("\t(ssidref %d)\n", c_info->ssidref);
393 printf("\t(name %s)\n", c_info->name);
394 printf("\t(uuid " UUID_FMT ")\n",
395 (c_info->uuid)[0], (c_info->uuid)[1], (c_info->uuid)[2], (c_info->uuid)[3],
396 (c_info->uuid)[4], (c_info->uuid)[5], (c_info->uuid)[6], (c_info->uuid)[7],
397 (c_info->uuid)[8], (c_info->uuid)[9], (c_info->uuid)[10], (c_info->uuid)[11],
398 (c_info->uuid)[12], (c_info->uuid)[13], (c_info->uuid)[14], (c_info->uuid)[15]);
399 printf("\t(cpupool %s (%d))\n", c_info->poolname, c_info->poolid);
400 if (c_info->xsdata)
401 printf("\t(xsdata contains data)\n");
402 else
403 printf("\t(xsdata (null))\n");
404 if (c_info->platformdata)
405 printf("\t(platformdata contains data)\n");
406 else
407 printf("\t(platformdata (null))\n");
410 printf("\t(domain_build_info)\n");
411 printf("\t(max_vcpus %d)\n", b_info->max_vcpus);
412 printf("\t(tsc_mode %d)\n", b_info->tsc_mode);
413 printf("\t(max_memkb %d)\n", b_info->max_memkb);
414 printf("\t(target_memkb %d)\n", b_info->target_memkb);
415 printf("\t(nomigrate %d)\n", b_info->disable_migrate);
417 if (!c_info->hvm && b_info->u.pv.bootloader) {
418 printf("\t(bootloader %s)\n", b_info->u.pv.bootloader);
419 if (b_info->u.pv.bootloader_args)
420 printf("\t(bootloader_args %s)\n", b_info->u.pv.bootloader_args);
421 }
423 printf("\t(image\n");
424 if (c_info->hvm) {
425 printf("\t\t(hvm\n");
426 printf("\t\t\t(loader %s)\n", b_info->kernel.path);
427 printf("\t\t\t(video_memkb %d)\n", b_info->video_memkb);
428 printf("\t\t\t(shadow_memkb %d)\n", b_info->shadow_memkb);
429 printf("\t\t\t(pae %d)\n", b_info->u.hvm.pae);
430 printf("\t\t\t(apic %d)\n", b_info->u.hvm.apic);
431 printf("\t\t\t(acpi %d)\n", b_info->u.hvm.acpi);
432 printf("\t\t\t(nx %d)\n", b_info->u.hvm.nx);
433 printf("\t\t\t(viridian %d)\n", b_info->u.hvm.viridian);
434 printf("\t\t\t(hpet %d)\n", b_info->u.hvm.hpet);
435 printf("\t\t\t(vpt_align %d)\n", b_info->u.hvm.vpt_align);
436 printf("\t\t\t(timer_mode %d)\n", b_info->u.hvm.timer_mode);
438 printf("\t\t\t(device_model %s)\n", dm_info->device_model);
439 printf("\t\t\t(videoram %d)\n", dm_info->videoram);
440 printf("\t\t\t(stdvga %d)\n", dm_info->stdvga);
441 printf("\t\t\t(vnc %d)\n", dm_info->vnc);
442 printf("\t\t\t(vnclisten %s)\n", dm_info->vnclisten);
443 printf("\t\t\t(vncdisplay %d)\n", dm_info->vncdisplay);
444 printf("\t\t\t(vncunused %d)\n", dm_info->vncunused);
445 printf("\t\t\t(keymap %s)\n", dm_info->keymap);
446 printf("\t\t\t(sdl %d)\n", dm_info->sdl);
447 printf("\t\t\t(opengl %d)\n", dm_info->opengl);
448 printf("\t\t\t(nographic %d)\n", dm_info->nographic);
449 printf("\t\t\t(serial %s)\n", dm_info->serial);
450 printf("\t\t\t(boot %s)\n", dm_info->boot);
451 printf("\t\t\t(usb %d)\n", dm_info->usb);
452 printf("\t\t\t(usbdevice %s)\n", dm_info->usbdevice);
453 printf("\t\t\t(apic %d)\n", dm_info->apic);
454 printf("\t\t)\n");
455 } else {
456 printf("\t\t(linux %d)\n", b_info->hvm);
457 printf("\t\t\t(kernel %s)\n", b_info->kernel.path);
458 printf("\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
459 printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk.path);
460 printf("\t\t)\n");
461 }
462 printf("\t)\n");
464 for (i = 0; i < d_config->num_disks; i++) {
465 printf("\t(device\n");
466 printf("\t\t(tap\n");
467 printf("\t\t\t(backend_domid %d)\n", d_config->disks[i].backend_domid);
468 printf("\t\t\t(domid %d)\n", d_config->disks[i].domid);
469 printf("\t\t\t(physpath %s)\n", d_config->disks[i].physpath);
470 printf("\t\t\t(phystype %d)\n", d_config->disks[i].phystype);
471 printf("\t\t\t(virtpath %s)\n", d_config->disks[i].virtpath);
472 printf("\t\t\t(unpluggable %d)\n", d_config->disks[i].unpluggable);
473 printf("\t\t\t(readwrite %d)\n", d_config->disks[i].readwrite);
474 printf("\t\t\t(is_cdrom %d)\n", d_config->disks[i].is_cdrom);
475 printf("\t\t)\n");
476 printf("\t)\n");
477 }
479 for (i = 0; i < d_config->num_vifs; i++) {
480 printf("\t(device\n");
481 printf("\t\t(vif\n");
482 printf("\t\t\t(backend_domid %d)\n", d_config->vifs[i].backend_domid);
483 printf("\t\t\t(domid %d)\n", d_config->vifs[i].domid);
484 printf("\t\t\t(devid %d)\n", d_config->vifs[i].devid);
485 printf("\t\t\t(mtu %d)\n", d_config->vifs[i].mtu);
486 printf("\t\t\t(model %s)\n", d_config->vifs[i].model);
487 printf("\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n",
488 d_config->vifs[i].mac[0], d_config->vifs[i].mac[1],
489 d_config->vifs[i].mac[2], d_config->vifs[i].mac[3],
490 d_config->vifs[i].mac[4], d_config->vifs[i].mac[5]);
491 printf("\t\t)\n");
492 printf("\t)\n");
493 }
495 for (i = 0; i < d_config->num_pcidevs; i++) {
496 printf("\t(device\n");
497 printf("\t\t(pci\n");
498 printf("\t\t\t(pci dev %04x:%02x:%02x.%01x@%02x)\n",
499 d_config->pcidevs[i].domain, d_config->pcidevs[i].bus,
500 d_config->pcidevs[i].dev, d_config->pcidevs[i].func,
501 d_config->pcidevs[i].vdevfn);
502 printf("\t\t\t(opts msitranslate %d power_mgmt %d)\n",
503 d_config->pcidevs[i].msitranslate,
504 d_config->pcidevs[i].power_mgmt);
505 printf("\t\t)\n");
506 printf("\t)\n");
507 }
509 for (i = 0; i < d_config->num_vfbs; i++) {
510 printf("\t(device\n");
511 printf("\t\t(vfb\n");
512 printf("\t\t\t(backend_domid %d)\n", d_config->vfbs[i].backend_domid);
513 printf("\t\t\t(domid %d)\n", d_config->vfbs[i].domid);
514 printf("\t\t\t(devid %d)\n", d_config->vfbs[i].devid);
515 printf("\t\t\t(vnc %d)\n", d_config->vfbs[i].vnc);
516 printf("\t\t\t(vnclisten %s)\n", d_config->vfbs[i].vnclisten);
517 printf("\t\t\t(vncdisplay %d)\n", d_config->vfbs[i].vncdisplay);
518 printf("\t\t\t(vncunused %d)\n", d_config->vfbs[i].vncunused);
519 printf("\t\t\t(keymap %s)\n", d_config->vfbs[i].keymap);
520 printf("\t\t\t(sdl %d)\n", d_config->vfbs[i].sdl);
521 printf("\t\t\t(opengl %d)\n", d_config->vfbs[i].opengl);
522 printf("\t\t\t(display %s)\n", d_config->vfbs[i].display);
523 printf("\t\t\t(xauthority %s)\n", d_config->vfbs[i].xauthority);
524 printf("\t\t)\n");
525 printf("\t)\n");
526 }
527 printf(")\n");
528 }
530 static int parse_action_on_shutdown(const char *buf, enum action_on_shutdown *a)
531 {
532 int i;
533 const char *n;
535 for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
536 n = action_on_shutdown_names[i];
538 if (strcmp(buf, n) == 0) {
539 *a = i;
540 return 1;
541 }
542 }
543 return 0;
544 }
546 static void parse_config_data(const char *configfile_filename_report,
547 const char *configfile_data,
548 int configfile_len,
549 struct domain_config *d_config,
550 libxl_device_model_info *dm_info)
551 {
552 const char *buf;
553 long l;
554 XLU_Config *config;
555 XLU_ConfigList *vbds, *nics, *pcis, *cvfbs, *net2s;
556 int pci_power_mgmt = 0;
557 int pci_msitranslate = 1;
558 int e;
560 libxl_domain_create_info *c_info = &d_config->c_info;
561 libxl_domain_build_info *b_info = &d_config->b_info;
563 config= xlu_cfg_init(stderr, configfile_filename_report);
564 if (!config) {
565 fprintf(stderr, "Failed to allocate for configuration\n");
566 exit(1);
567 }
569 e= xlu_cfg_readdata(config, configfile_data, configfile_len);
570 if (e) {
571 fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
572 exit(1);
573 }
575 init_create_info(c_info);
577 c_info->hvm = 0;
578 if (!xlu_cfg_get_string (config, "builder", &buf) &&
579 !strncmp(buf, "hvm", strlen(buf)))
580 c_info->hvm = 1;
582 if (!xlu_cfg_get_long (config, "hap", &l))
583 c_info->hap = l;
585 if (!xlu_cfg_get_string (config, "name", &buf))
586 c_info->name = strdup(buf);
587 else
588 c_info->name = "test";
589 random_uuid(&c_info->uuid);
591 if (!xlu_cfg_get_long(config, "oos", &l))
592 c_info->oos = l;
594 if (!xlu_cfg_get_string (config, "pool", &buf)) {
595 c_info->poolid = -1;
596 pool_qualifier_to_poolid(buf, &c_info->poolid, NULL);
597 }
598 c_info->poolname = libxl_poolid_to_name(&ctx, c_info->poolid);
599 if (!c_info->poolname) {
600 fprintf(stderr, "Illegal pool specified\n");
601 exit(1);
602 }
604 init_build_info(b_info, c_info);
606 /* the following is the actual config parsing with overriding values in the structures */
607 if (!xlu_cfg_get_long (config, "vcpus", &l)) {
608 b_info->max_vcpus = l;
609 b_info->cur_vcpus = (1 << l) - 1;
610 }
612 if (!xlu_cfg_get_long (config, "memory", &l)) {
613 b_info->max_memkb = l * 1024;
614 b_info->target_memkb = b_info->max_memkb;
615 }
617 if (xlu_cfg_get_string (config, "on_poweroff", &buf))
618 buf = "destroy";
619 if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
620 fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
621 exit(1);
622 }
624 if (xlu_cfg_get_string (config, "on_reboot", &buf))
625 buf = "restart";
626 if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
627 fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
628 exit(1);
629 }
631 if (xlu_cfg_get_string (config, "on_watchdog", &buf))
632 buf = "destroy";
633 if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
634 fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
635 exit(1);
636 }
639 if (xlu_cfg_get_string (config, "on_crash", &buf))
640 buf = "destroy";
641 if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
642 fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
643 exit(1);
644 }
646 /* libxl_get_required_shadow_memory() must be called after final values
647 * (default or specified) for vcpus and memory are set, because the
648 * calculation depends on those values. */
649 b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l)
650 ? l * 1024
651 : libxl_get_required_shadow_memory(b_info->max_memkb,
652 b_info->max_vcpus);
654 if (!xlu_cfg_get_long (config, "nomigrate", &l))
655 b_info->disable_migrate = l;
657 if (!xlu_cfg_get_long(config, "tsc_mode", &l))
658 b_info->tsc_mode = l;
660 if (!xlu_cfg_get_long (config, "videoram", &l))
661 b_info->video_memkb = l * 1024;
663 if (!xlu_cfg_get_string (config, "kernel", &buf))
664 b_info->kernel.path = strdup(buf);
666 if (c_info->hvm == 1) {
667 if (!xlu_cfg_get_long (config, "pae", &l))
668 b_info->u.hvm.pae = l;
669 if (!xlu_cfg_get_long (config, "apic", &l))
670 b_info->u.hvm.apic = l;
671 if (!xlu_cfg_get_long (config, "acpi", &l))
672 b_info->u.hvm.acpi = l;
673 if (!xlu_cfg_get_long (config, "nx", &l))
674 b_info->u.hvm.nx = l;
675 if (!xlu_cfg_get_long (config, "viridian", &l))
676 b_info->u.hvm.viridian = l;
677 if (!xlu_cfg_get_long (config, "hpet", &l))
678 b_info->u.hvm.hpet = l;
679 if (!xlu_cfg_get_long (config, "vpt_align", &l))
680 b_info->u.hvm.vpt_align = l;
681 if (!xlu_cfg_get_long (config, "timer_mode", &l))
682 b_info->u.hvm.timer_mode = l;
683 } else {
684 char *cmdline = NULL;
685 const char *root = NULL, *extra = "";
687 xlu_cfg_get_string (config, "root", &root);
688 xlu_cfg_get_string (config, "extra", &extra);
690 if (root) {
691 if (asprintf(&cmdline, "root=%s %s", root, extra) == -1)
692 cmdline = NULL;
693 } else {
694 cmdline = strdup(extra);
695 }
697 if ((root || extra) && !cmdline) {
698 fprintf(stderr, "Failed to allocate memory for cmdline\n");
699 exit(1);
700 }
702 if (!xlu_cfg_get_string (config, "bootloader", &buf))
703 b_info->u.pv.bootloader = strdup(buf);
704 if (!xlu_cfg_get_string (config, "bootloader_args", &buf))
705 b_info->u.pv.bootloader_args = strdup(buf);
707 if (!b_info->u.pv.bootloader && !b_info->kernel.path) {
708 fprintf(stderr, "Neither kernel nor bootloader specified\n");
709 exit(1);
710 }
712 b_info->u.pv.cmdline = cmdline;
713 if (!xlu_cfg_get_string (config, "ramdisk", &buf))
714 b_info->u.pv.ramdisk.path = strdup(buf);
715 }
717 if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
718 d_config->num_disks = 0;
719 d_config->disks = NULL;
720 while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
721 libxl_device_disk *disk;
722 char *buf2 = strdup(buf);
723 char *p, *p2;
725 d_config->disks = (libxl_device_disk *) realloc(d_config->disks, sizeof (libxl_device_disk) * (d_config->num_disks + 1));
726 disk = d_config->disks + d_config->num_disks;
728 disk->backend_domid = 0;
729 disk->domid = 0;
730 disk->unpluggable = 0;
732 p = strtok(buf2, ",:");
733 while (*p == ' ')
734 p++;
735 if (!strcmp(p, "phy")) {
736 disk->phystype = PHYSTYPE_PHY;
737 } else if (!strcmp(p, "file")) {
738 disk->phystype = PHYSTYPE_FILE;
739 } else if (!strcmp(p, "tap")) {
740 p = strtok(NULL, ":");
741 if (!strcmp(p, "aio")) {
742 disk->phystype = PHYSTYPE_AIO;
743 } else if (!strcmp(p, "vhd")) {
744 disk->phystype = PHYSTYPE_VHD;
745 } else if (!strcmp(p, "qcow")) {
746 disk->phystype = PHYSTYPE_QCOW;
747 } else if (!strcmp(p, "qcow2")) {
748 disk->phystype = PHYSTYPE_QCOW2;
749 }
750 }
751 p = strtok(NULL, ",");
752 while (*p == ' ')
753 p++;
754 disk->physpath= strdup(p);
755 p = strtok(NULL, ",");
756 while (*p == ' ')
757 p++;
758 p2 = strchr(p, ':');
759 if (p2 == NULL) {
760 disk->virtpath = strdup(p);
761 disk->is_cdrom = 0;
762 disk->unpluggable = 1;
763 } else {
764 *p2 = '\0';
765 disk->virtpath = strdup(p);
766 if (!strcmp(p2 + 1, "cdrom")) {
767 disk->is_cdrom = 1;
768 disk->unpluggable = 1;
769 } else
770 disk->is_cdrom = 0;
771 }
772 p = strtok(NULL, ",");
773 while (*p == ' ')
774 p++;
775 disk->readwrite = (p[0] == 'w') ? 1 : 0;
776 free(buf2);
777 d_config->num_disks++;
778 }
779 }
781 if (!xlu_cfg_get_list (config, "vif", &nics, 0)) {
782 d_config->num_vifs = 0;
783 d_config->vifs = NULL;
784 while ((buf = xlu_cfg_get_listitem (nics, d_config->num_vifs)) != NULL) {
785 libxl_device_nic *nic;
786 char *buf2 = strdup(buf);
787 char *p, *p2;
789 d_config->vifs = (libxl_device_nic *) realloc(d_config->vifs, sizeof (libxl_device_nic) * (d_config->num_vifs+1));
790 nic = d_config->vifs + d_config->num_vifs;
791 init_nic_info(nic, d_config->num_vifs);
793 p = strtok(buf2, ",");
794 if (!p)
795 goto skip;
796 do {
797 while (*p == ' ')
798 p++;
799 if ((p2 = strchr(p, '=')) == NULL)
800 break;
801 *p2 = '\0';
802 if (!strcmp(p, "model")) {
803 nic->model = strdup(p2 + 1);
804 } else if (!strcmp(p, "mac")) {
805 char *p3 = p2 + 1;
806 *(p3 + 2) = '\0';
807 nic->mac[0] = strtol(p3, NULL, 16);
808 p3 = p3 + 3;
809 *(p3 + 2) = '\0';
810 nic->mac[1] = strtol(p3, NULL, 16);
811 p3 = p3 + 3;
812 *(p3 + 2) = '\0';
813 nic->mac[2] = strtol(p3, NULL, 16);
814 p3 = p3 + 3;
815 *(p3 + 2) = '\0';
816 nic->mac[3] = strtol(p3, NULL, 16);
817 p3 = p3 + 3;
818 *(p3 + 2) = '\0';
819 nic->mac[4] = strtol(p3, NULL, 16);
820 p3 = p3 + 3;
821 *(p3 + 2) = '\0';
822 nic->mac[5] = strtol(p3, NULL, 16);
823 } else if (!strcmp(p, "bridge")) {
824 nic->bridge = strdup(p2 + 1);
825 } else if (!strcmp(p, "type")) {
826 if (!strcmp(p2 + 1, "ioemu"))
827 nic->nictype = NICTYPE_IOEMU;
828 else
829 nic->nictype = NICTYPE_VIF;
830 } else if (!strcmp(p, "ip")) {
831 inet_pton(AF_INET, p2 + 1, &nic->ip);
832 } else if (!strcmp(p, "script")) {
833 nic->script = strdup(p2 + 1);
834 } else if (!strcmp(p, "vifname")) {
835 nic->ifname = strdup(p2 + 1);
836 } else if (!strcmp(p, "rate")) {
837 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
838 } else if (!strcmp(p, "accel")) {
839 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
840 }
841 } while ((p = strtok(NULL, ",")) != NULL);
842 skip:
843 free(buf2);
844 d_config->num_vifs++;
845 }
846 }
848 if (!xlu_cfg_get_list(config, "vif2", &net2s, 0)) {
849 d_config->num_vif2s = 0;
850 d_config->vif2s = NULL;
851 while ((buf = xlu_cfg_get_listitem(net2s, d_config->num_vif2s))) {
852 libxl_device_net2 *net2;
853 char *buf2 = strdup(buf);
854 char *p;
856 d_config->vif2s = realloc(d_config->vif2s, sizeof (libxl_device_net2) * (d_config->num_vif2s + 1));
857 net2 = d_config->vif2s + d_config->num_vif2s;
859 init_net2_info(net2, d_config->num_vif2s);
861 for (p = strtok(buf2, ","); p; p = strtok(buf2, ",")) {
862 while (isblank(*p))
863 p++;
864 if (!strncmp("front_mac=", p, 10)) {
865 libxl_strtomac(p + 10, net2->front_mac);
866 } else if (!strncmp("back_mac=", p, 9)) {
867 libxl_strtomac(p + 9, net2->back_mac);
868 } else if (!strncmp("backend=", p, 8)) {
869 domain_qualifier_to_domid(p + 8, &net2->backend_domid, 0);
870 } else if (!strncmp("trusted=", p, 8)) {
871 net2->trusted = (*(p + 8) == '1');
872 } else if (!strncmp("back_trusted=", p, 13)) {
873 net2->back_trusted = (*(p + 13) == '1');
874 } else if (!strncmp("bridge=", p, 7)) {
875 net2->bridge = strdup(p + 13);
876 } else if (!strncmp("filter_mac=", p, 11)) {
877 net2->filter_mac = (*(p + 11) == '1');
878 } else if (!strncmp("front_filter_mac=", p, 17)) {
879 net2->front_filter_mac = (*(p + 17) == '1');
880 } else if (!strncmp("pdev=", p, 5)) {
881 net2->pdev = strtoul(p + 5, NULL, 10);
882 } else if (!strncmp("max_bypasses=", p, 13)) {
883 net2->max_bypasses = strtoul(p + 13, NULL, 10);
884 }
885 }
886 free(buf2);
887 d_config->num_vif2s++;
888 }
889 }
891 if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
892 d_config->num_vfbs = 0;
893 d_config->num_vkbs = 0;
894 d_config->vfbs = NULL;
895 d_config->vkbs = NULL;
896 while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
897 libxl_device_vfb *vfb;
898 libxl_device_vkb *vkb;
900 char *buf2 = strdup(buf);
901 char *p, *p2;
903 d_config->vfbs = (libxl_device_vfb *) realloc(d_config->vfbs, sizeof(libxl_device_vfb) * (d_config->num_vfbs + 1));
904 vfb = d_config->vfbs + d_config->num_vfbs;
905 init_vfb_info(vfb, d_config->num_vfbs);
907 d_config->vkbs = (libxl_device_vkb *) realloc(d_config->vkbs, sizeof(libxl_device_vkb) * (d_config->num_vkbs + 1));
908 vkb = d_config->vkbs + d_config->num_vkbs;
909 init_vkb_info(vkb, d_config->num_vkbs);
911 p = strtok(buf2, ",");
912 if (!p)
913 goto skip_vfb;
914 do {
915 while (*p == ' ')
916 p++;
917 if ((p2 = strchr(p, '=')) == NULL)
918 break;
919 *p2 = '\0';
920 if (!strcmp(p, "vnc")) {
921 vfb->vnc = atoi(p2 + 1);
922 } else if (!strcmp(p, "vnclisten")) {
923 vfb->vnclisten = strdup(p2 + 1);
924 } else if (!strcmp(p, "vncpasswd")) {
925 vfb->vncpasswd = strdup(p2 + 1);
926 } else if (!strcmp(p, "vncdisplay")) {
927 vfb->vncdisplay = atoi(p2 + 1);
928 } else if (!strcmp(p, "vncunused")) {
929 vfb->vncunused = atoi(p2 + 1);
930 } else if (!strcmp(p, "keymap")) {
931 vfb->keymap = strdup(p2 + 1);
932 } else if (!strcmp(p, "sdl")) {
933 vfb->sdl = atoi(p2 + 1);
934 } else if (!strcmp(p, "opengl")) {
935 vfb->opengl = atoi(p2 + 1);
936 } else if (!strcmp(p, "display")) {
937 vfb->display = strdup(p2 + 1);
938 } else if (!strcmp(p, "xauthority")) {
939 vfb->xauthority = strdup(p2 + 1);
940 }
941 } while ((p = strtok(NULL, ",")) != NULL);
942 skip_vfb:
943 free(buf2);
944 d_config->num_vfbs++;
945 d_config->num_vkbs++;
946 }
947 }
949 if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
950 pci_msitranslate = l;
952 if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
953 pci_power_mgmt = l;
955 if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
956 int i;
957 d_config->num_pcidevs = 0;
958 d_config->pcidevs = NULL;
959 for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
960 libxl_device_pci *pcidev;
962 d_config->pcidevs = (libxl_device_pci *) realloc(d_config->pcidevs, sizeof (libxl_device_pci) * (d_config->num_pcidevs + 1));
963 pcidev = d_config->pcidevs + d_config->num_pcidevs;
964 memset(pcidev, 0x00, sizeof(libxl_device_pci));
966 pcidev->msitranslate = pci_msitranslate;
967 pcidev->power_mgmt = pci_power_mgmt;
968 if (!libxl_device_pci_parse_bdf(&ctx, pcidev, buf))
969 d_config->num_pcidevs++;
970 }
971 }
973 if (c_info->hvm == 1) {
974 /* init dm from c and b */
975 init_dm_info(dm_info, c_info, b_info);
977 /* then process config related to dm */
978 if (!xlu_cfg_get_string (config, "device_model", &buf))
979 dm_info->device_model = strdup(buf);
980 if (!xlu_cfg_get_long (config, "stdvga", &l))
981 dm_info->stdvga = l;
982 if (!xlu_cfg_get_long (config, "vnc", &l))
983 dm_info->vnc = l;
984 if (!xlu_cfg_get_string (config, "vnclisten", &buf))
985 dm_info->vnclisten = strdup(buf);
986 if (!xlu_cfg_get_string (config, "vncpasswd", &buf))
987 dm_info->vncpasswd = strdup(buf);
988 if (!xlu_cfg_get_long (config, "vncdisplay", &l))
989 dm_info->vncdisplay = l;
990 if (!xlu_cfg_get_long (config, "vncunused", &l))
991 dm_info->vncunused = l;
992 if (!xlu_cfg_get_string (config, "keymap", &buf))
993 dm_info->keymap = strdup(buf);
994 if (!xlu_cfg_get_long (config, "sdl", &l))
995 dm_info->sdl = l;
996 if (!xlu_cfg_get_long (config, "opengl", &l))
997 dm_info->opengl = l;
998 if (!xlu_cfg_get_long (config, "nographic", &l))
999 dm_info->nographic = l;
1000 if (!xlu_cfg_get_string (config, "serial", &buf))
1001 dm_info->serial = strdup(buf);
1002 if (!xlu_cfg_get_string (config, "boot", &buf))
1003 dm_info->boot = strdup(buf);
1004 if (!xlu_cfg_get_long (config, "usb", &l))
1005 dm_info->usb = l;
1006 if (!xlu_cfg_get_string (config, "usbdevice", &buf))
1007 dm_info->usbdevice = strdup(buf);
1008 if (!xlu_cfg_get_string (config, "soundhw", &buf))
1009 dm_info->soundhw = strdup(buf);
1010 if (!xlu_cfg_get_long (config, "xen_platform_pci", &l))
1011 dm_info->xen_platform_pci = l;
1014 dm_info->type = c_info->hvm ? XENFV : XENPV;
1016 xlu_cfg_destroy(config);
1019 static void *xmalloc(size_t sz) {
1020 void *r;
1021 r = malloc(sz);
1022 if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
1023 (unsigned long)sz); exit(-ERROR_FAIL); }
1024 return r;
1027 static void *xrealloc(void *ptr, size_t sz) {
1028 void *r;
1029 if (!sz) { free(ptr); return 0; }
1030 /* realloc(non-0, 0) has a useless return value;
1031 * but xrealloc(anything, 0) is like free
1032 */
1033 r = realloc(ptr, sz);
1034 if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
1035 (unsigned long)sz); exit(-ERROR_FAIL); }
1036 return r;
1039 int autoconnect_console(int hvm)
1041 int status, options;
1042 pid_t pid, r;
1044 /*
1045 * Fork for xenconsole. We exec xenconsole in the foreground
1046 * process allowing it to retain the tty. xl continues in the
1047 * child. The xenconsole client uses a xenstore watch to wait for
1048 * the console to be setup so there is no race.
1049 */
1050 pid = fork();
1051 if (pid < 0) {
1052 perror("unable to fork xenconsole");
1053 return ERROR_FAIL;
1054 } else if (pid == 0)
1055 return 0;
1057 /*
1058 * In the PV case we only catch failure of the create process, in
1059 * the HVM case we also wait for the creation process to be
1060 * completed so that the stubdom is already up and running and we
1061 * can connect to it.
1062 */
1063 if (hvm)
1064 options = 0;
1065 else
1066 options = WNOHANG;
1067 sleep(1);
1068 r = waitpid(pid, &status, options);
1069 if (r > 0 && WIFEXITED(status) && WEXITSTATUS(status) != 0)
1070 _exit(WEXITSTATUS(status));
1072 libxl_primary_console_exec(&ctx, domid);
1073 /* Do not return. xl continued in child process */
1074 fprintf(stderr, "Unable to attach console\n");
1075 _exit(1);
1078 /* Returns 1 if domain should be restarted, 2 if domain should be renamed then restarted */
1079 static int handle_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1080 struct domain_config *d_config, libxl_dominfo *info)
1082 int restart = 0;
1083 enum action_on_shutdown action;
1085 switch (info->shutdown_reason) {
1086 case SHUTDOWN_poweroff:
1087 action = d_config->on_poweroff;
1088 break;
1089 case SHUTDOWN_reboot:
1090 action = d_config->on_reboot;
1091 break;
1092 case SHUTDOWN_suspend:
1093 return 0;
1094 case SHUTDOWN_crash:
1095 action = d_config->on_crash;
1096 break;
1097 case SHUTDOWN_watchdog:
1098 action = d_config->on_watchdog;
1099 break;
1100 default:
1101 LOG("Unknown shutdown reason code %s. Destroying domain.", info->shutdown_reason);
1102 action = ACTION_DESTROY;
1105 LOG("Action for shutdown reason code %d is %s", info->shutdown_reason, action_on_shutdown_names[action]);
1107 if (action == ACTION_COREDUMP_DESTROY || action == ACTION_COREDUMP_RESTART) {
1108 char *corefile;
1109 int rc;
1111 if (asprintf(&corefile, "/var/xen/dump/%s", d_config->c_info.name) < 0) {
1112 LOG("failed to construct core dump path");
1113 } else {
1114 LOG("dumping core to %s", corefile);
1115 rc=libxl_domain_core_dump(ctx, domid, corefile);
1116 if (rc) LOG("core dump failed (rc=%d).", rc);
1118 /* No point crying over spilled milk, continue on failure. */
1120 if (action == ACTION_COREDUMP_DESTROY)
1121 action = ACTION_DESTROY;
1122 else
1123 action = ACTION_RESTART;
1126 switch (action) {
1127 case ACTION_PRESERVE:
1128 break;
1130 case ACTION_RESTART_RENAME:
1131 restart = 2;
1132 break;
1134 case ACTION_RESTART:
1135 restart = 1;
1136 /* fall-through */
1137 case ACTION_DESTROY:
1138 LOG("Domain %d needs to be cleaned up: destroying the domain", domid);
1139 libxl_domain_destroy(ctx, domid, 0);
1140 break;
1142 case ACTION_COREDUMP_DESTROY:
1143 case ACTION_COREDUMP_RESTART:
1144 /* Already handled these above. */
1145 abort();
1148 return restart;
1151 static int preserve_domain(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1152 struct domain_config *d_config, libxl_dominfo *info)
1154 time_t now;
1155 struct tm tm;
1156 char stime[24];
1158 libxl_uuid new_uuid;
1160 int rc;
1162 now = time(NULL);
1163 if (now == ((time_t) -1)) {
1164 LOG("Failed to get current time for domain rename");
1165 return 0;
1168 tzset();
1169 if (gmtime_r(&now, &tm) == NULL) {
1170 LOG("Failed to convert time to UTC");
1171 return 0;
1174 if (!strftime(&stime[0], sizeof(stime), "-%Y%m%dT%H%MZ", &tm)) {
1175 LOG("Failed to format time as a string");
1176 return 0;
1179 random_uuid(&new_uuid);
1181 LOG("Preserving domain %d %s with suffix%s", domid, d_config->c_info.name, stime);
1182 rc = libxl_domain_preserve(ctx, domid, &d_config->c_info, stime, new_uuid);
1184 return rc == 0 ? 1 : 0;
1187 struct domain_create {
1188 int debug;
1189 int daemonize;
1190 int paused;
1191 int dryrun;
1192 int quiet;
1193 int console_autoconnect;
1194 const char *config_file;
1195 const char *extra_config; /* extra config string */
1196 const char *restore_file;
1197 int migrate_fd; /* -1 means none */
1198 char **migration_domname_r;
1199 };
1201 static int create_domain(struct domain_create *dom_info)
1203 struct domain_config d_config;
1205 libxl_domain_build_state state;
1206 libxl_device_model_info dm_info;
1207 libxl_device_console console;
1209 int debug = dom_info->debug;
1210 int daemonize = dom_info->daemonize;
1211 int paused = dom_info->paused;
1212 const char *config_file = dom_info->config_file;
1213 const char *extra_config = dom_info->extra_config;
1214 const char *restore_file = dom_info->restore_file;
1215 int migrate_fd = dom_info->migrate_fd;
1216 char **migration_domname_r = dom_info->migration_domname_r;
1218 int i, fd;
1219 int need_daemon = 1;
1220 int ret, rc;
1221 libxl_device_model_starting *dm_starting = 0;
1222 libxl_waiter *w1 = NULL, *w2 = NULL;
1223 void *config_data = 0;
1224 int config_len = 0;
1225 int restore_fd = -1;
1226 struct save_file_header hdr;
1228 memset(&d_config, 0x00, sizeof(d_config));
1229 memset(&dm_info, 0x00, sizeof(dm_info));
1231 if (restore_file) {
1232 uint8_t *optdata_begin = 0;
1233 const uint8_t *optdata_here = 0;
1234 union { uint32_t u32; char b[4]; } u32buf;
1235 uint32_t badflags;
1237 restore_fd = migrate_fd >= 0 ? migrate_fd :
1238 open(restore_file, O_RDONLY);
1240 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
1241 sizeof(hdr), restore_file, "header") );
1242 if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
1243 fprintf(stderr, "File has wrong magic number -"
1244 " corrupt or for a different tool?\n");
1245 return ERROR_INVAL;
1247 if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
1248 fprintf(stderr, "File has wrong byte order\n");
1249 return ERROR_INVAL;
1251 fprintf(stderr, "Loading new save file %s"
1252 " (new xl fmt info"
1253 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
1254 restore_file, hdr.mandatory_flags, hdr.optional_flags,
1255 hdr.optional_data_len);
1257 badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
1258 if (badflags) {
1259 fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
1260 "which are not supported; need newer xl\n",
1261 badflags);
1262 return ERROR_INVAL;
1264 if (hdr.optional_data_len) {
1265 optdata_begin = xmalloc(hdr.optional_data_len);
1266 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
1267 hdr.optional_data_len, restore_file, "optdata") );
1270 #define OPTDATA_LEFT (hdr.optional_data_len - (optdata_here - optdata_begin))
1271 #define WITH_OPTDATA(amt, body) \
1272 if (OPTDATA_LEFT < (amt)) { \
1273 fprintf(stderr, "Savefile truncated.\n"); \
1274 return ERROR_INVAL; \
1275 } else { \
1276 body; \
1277 optdata_here += (amt); \
1280 optdata_here = optdata_begin;
1282 if (OPTDATA_LEFT) {
1283 fprintf(stderr, " Savefile contains xl domain config\n");
1284 WITH_OPTDATA(4, {
1285 memcpy(u32buf.b, optdata_here, 4);
1286 config_len = u32buf.u32;
1287 });
1288 WITH_OPTDATA(config_len, {
1289 config_data = xmalloc(config_len);
1290 memcpy(config_data, optdata_here, config_len);
1291 });
1296 if (config_file) {
1297 free(config_data); config_data = 0;
1298 ret = libxl_read_file_contents(&ctx, config_file,
1299 &config_data, &config_len);
1300 if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
1301 config_file, strerror(errno)); return ERROR_FAIL; }
1302 if (!restore_file && extra_config
1303 && strlen(extra_config)) {
1304 if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
1305 fprintf(stderr, "Failed to attach extra configration\n");
1306 return ERROR_FAIL;
1308 config_data = realloc(config_data, config_len
1309 + strlen(extra_config) + 2);
1310 if (!config_data) {
1311 fprintf(stderr, "Failed to realloc config_data\n");
1312 return ERROR_FAIL;
1314 strcat(config_data, "\n");
1315 strcat(config_data, extra_config);
1316 strcat(config_data, "\n");
1317 config_len += (strlen(extra_config) + 2);
1319 } else {
1320 if (!config_data) {
1321 fprintf(stderr, "Config file not specified and"
1322 " none in save file\n");
1323 return ERROR_INVAL;
1325 config_file = "<saved>";
1328 if (!dom_info->quiet)
1329 printf("Parsing config file %s\n", config_file);
1331 parse_config_data(config_file, config_data, config_len, &d_config, &dm_info);
1333 ret = 0;
1334 if (dom_info->dryrun)
1335 goto out;
1337 if (migrate_fd >= 0) {
1338 if (d_config.c_info.name) {
1339 /* when we receive a domain we get its name from the config
1340 * file; and we receive it to a temporary name */
1341 assert(!common_domname);
1342 common_domname = d_config.c_info.name;
1343 if (asprintf(migration_domname_r, "%s--incoming", d_config.c_info.name) < 0) {
1344 fprintf(stderr, "Failed to allocate memory in asprintf\n");
1345 exit(1);
1347 d_config.c_info.name = *migration_domname_r;
1351 if (debug)
1352 printf_info(-1, &d_config, &dm_info);
1354 start:
1355 domid = 0;
1357 ret = libxl_domain_make(&ctx, &d_config.c_info, &domid);
1358 if (ret) {
1359 fprintf(stderr, "cannot make domain: %d\n", ret);
1360 ret = ERROR_FAIL;
1361 goto error_out;
1364 ret = libxl_userdata_store(&ctx, domid, "xl",
1365 config_data, config_len);
1366 if (ret) {
1367 perror("cannot save config file");
1368 ret = ERROR_FAIL;
1369 goto error_out;
1372 if (dom_info->console_autoconnect) {
1373 ret = autoconnect_console(d_config.c_info.hvm);
1374 if (ret)
1375 goto error_out;
1378 /*
1379 * Do not attempt to reconnect if we come round again due to a
1380 * guest reboot -- the stdin/out will be disconnected by then.
1381 */
1382 dom_info->console_autoconnect = 0;
1384 ret = libxl_run_bootloader(&ctx, &d_config.b_info, d_config.num_disks > 0 ? &d_config.disks[0] : NULL, domid);
1385 if (ret) {
1386 fprintf(stderr, "failed to run bootloader: %d\n", ret);
1387 goto error_out;
1390 if (!restore_file || !need_daemon) {
1391 if (dm_info.saved_state) {
1392 free(dm_info.saved_state);
1393 dm_info.saved_state = NULL;
1395 ret = libxl_domain_build(&ctx, &d_config.b_info, domid, &state);
1396 } else {
1397 ret = libxl_domain_restore(&ctx, &d_config.b_info, domid, restore_fd, &state, &dm_info);
1400 if (ret) {
1401 fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
1402 ret = ERROR_FAIL;
1403 goto error_out;
1406 for (i = 0; i < d_config.num_disks; i++) {
1407 d_config.disks[i].domid = domid;
1408 ret = libxl_device_disk_add(&ctx, domid, &d_config.disks[i]);
1409 if (ret) {
1410 fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
1411 ret = ERROR_FAIL;
1412 goto error_out;
1415 for (i = 0; i < d_config.num_vifs; i++) {
1416 d_config.vifs[i].domid = domid;
1417 ret = libxl_device_nic_add(&ctx, domid, &d_config.vifs[i]);
1418 if (ret) {
1419 fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
1420 ret = ERROR_FAIL;
1421 goto error_out;
1424 if (!d_config.c_info.hvm) {
1425 for (i = 0; i < d_config.num_vif2s; i++) {
1426 d_config.vif2s[i].domid = domid;
1427 ret = libxl_device_net2_add(&ctx, domid, &d_config.vif2s[i]);
1428 if (ret) {
1429 fprintf(stderr, "cannot add net2 %d to domain: %d\n", i, ret);
1430 ret = ERROR_FAIL;
1431 goto error_out;
1435 if (d_config.c_info.hvm) {
1436 init_console_info(&console, 0, &state);
1437 console.domid = domid;
1438 libxl_device_console_add(&ctx, domid, &console);
1439 dm_info.domid = domid;
1440 MUST( libxl_create_device_model(&ctx, &dm_info,
1441 d_config.disks, d_config.num_disks,
1442 d_config.vifs, d_config.num_vifs,
1443 &dm_starting) );
1444 } else {
1445 for (i = 0; i < d_config.num_vfbs; i++) {
1446 d_config.vfbs[i].domid = domid;
1447 libxl_device_vfb_add(&ctx, domid, &d_config.vfbs[i]);
1448 d_config.vkbs[i].domid = domid;
1449 libxl_device_vkb_add(&ctx, domid, &d_config.vkbs[i]);
1451 init_console_info(&console, 0, &state);
1452 console.domid = domid;
1453 if (d_config.num_vfbs)
1454 console.constype = CONSTYPE_IOEMU;
1455 libxl_device_console_add(&ctx, domid, &console);
1456 if (d_config.num_vfbs)
1457 libxl_create_xenpv_qemu(&ctx, d_config.vfbs, 1, &console, &dm_starting);
1460 if (dm_starting)
1461 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
1462 for (i = 0; i < d_config.num_pcidevs; i++)
1463 libxl_device_pci_add(&ctx, domid, &d_config.pcidevs[i]);
1465 if (!paused)
1466 libxl_domain_unpause(&ctx, domid);
1468 ret = domid; /* caller gets success in parent */
1469 if (!daemonize)
1470 goto out;
1472 if (need_daemon) {
1473 char *fullname, *name;
1474 pid_t child1, got_child;
1475 int nullfd;
1477 child1 = libxl_fork(&ctx);
1478 if (child1) {
1479 int status;
1480 for (;;) {
1481 got_child = waitpid(child1, &status, 0);
1482 if (got_child == child1) break;
1483 assert(got_child == -1);
1484 if (errno != EINTR) {
1485 perror("failed to wait for daemonizing child");
1486 ret = ERROR_FAIL;
1487 goto error_out;
1490 if (status) {
1491 libxl_report_child_exitstatus(&ctx, XTL_ERROR,
1492 "daemonizing child", child1, status);
1493 ret = ERROR_FAIL;
1494 goto error_out;
1496 return domid; /* caller gets success in parent */
1499 rc = libxl_ctx_postfork(&ctx);
1500 if (rc) {
1501 LOG("failed to reinitialise context after fork");
1502 exit(-1);
1505 if (asprintf(&name, "xl-%s", d_config.c_info.name) < 0) {
1506 LOG("Failed to allocate memory in asprintf");
1507 exit(1);
1509 rc = libxl_create_logfile(&ctx, name, &fullname);
1510 if (rc) {
1511 LOG("failed to open logfile %s",fullname,strerror(errno));
1512 exit(-1);
1515 CHK_ERRNO(( logfile = open(fullname, O_WRONLY|O_CREAT, 0644) )<0);
1516 free(fullname);
1517 free(name);
1519 CHK_ERRNO(( nullfd = open("/dev/null", O_RDONLY) )<0);
1520 dup2(nullfd, 0);
1521 dup2(logfile, 1);
1522 dup2(logfile, 2);
1524 CHK_ERRNO(daemon(0, 1) < 0);
1525 need_daemon = 0;
1527 LOG("Waiting for domain %s (domid %d) to die [pid %ld]",
1528 d_config.c_info.name, domid, (long)getpid());
1529 w1 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter) * d_config.num_disks);
1530 w2 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter));
1531 libxl_wait_for_disk_ejects(&ctx, domid, d_config.disks, d_config.num_disks, w1);
1532 libxl_wait_for_domain_death(&ctx, domid, w2);
1533 libxl_get_wait_fd(&ctx, &fd);
1534 while (1) {
1535 int ret;
1536 fd_set rfds;
1537 libxl_dominfo info;
1538 libxl_event event;
1539 libxl_device_disk disk;
1541 FD_ZERO(&rfds);
1542 FD_SET(fd, &rfds);
1544 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
1545 if (!ret)
1546 continue;
1547 libxl_get_event(&ctx, &event);
1548 switch (event.type) {
1549 case LIBXL_EVENT_DOMAIN_DEATH:
1550 ret = libxl_event_get_domain_death_info(&ctx, domid, &event, &info);
1552 if (ret < 0) continue;
1554 LOG("Domain %d is dead", domid);
1556 if (ret) {
1557 switch (handle_domain_death(&ctx, domid, &event, &d_config, &info)) {
1558 case 2:
1559 if (!preserve_domain(&ctx, domid, &event, &d_config, &info))
1560 /* If we fail then exit leaving the old domain in place. */
1561 exit(-1);
1563 /* Otherwise fall through and restart. */
1564 case 1:
1566 libxl_free_waiter(w1);
1567 libxl_free_waiter(w2);
1568 free(w1);
1569 free(w2);
1570 /*
1571 * XXX FIXME: If this sleep is not there then domain
1572 * re-creation fails sometimes.
1573 */
1574 LOG("Done. Rebooting now");
1575 sleep(2);
1576 goto start;
1577 case 0:
1578 LOG("Done. Exiting now");
1579 exit(0);
1582 break;
1583 case LIBXL_EVENT_DISK_EJECT:
1584 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
1585 libxl_cdrom_insert(&ctx, domid, &disk);
1586 break;
1588 libxl_free_event(&event);
1591 close(logfile);
1592 exit(0);
1594 error_out:
1595 if (domid)
1596 libxl_domain_destroy(&ctx, domid, 0);
1597 out:
1599 free_domain_config(&d_config);
1601 free(config_data);
1603 return ret;
1606 void help(char *command)
1608 int i;
1609 struct cmd_spec *cmd;
1611 if (!command || !strcmp(command, "help")) {
1612 printf("Usage xl [-v] <subcommand> [args]\n\n");
1613 printf("xl full list of subcommands:\n\n");
1614 for (i = 0; i < cmdtable_len; i++)
1615 printf(" %-20s%s\n",
1616 cmd_table[i].cmd_name, cmd_table[i].cmd_desc);
1617 } else {
1618 cmd = cmdtable_lookup(command);
1619 if (cmd) {
1620 printf("Usage: xl [-v] %s %s\n\n%s.\n\n",
1621 cmd->cmd_name,
1622 cmd->cmd_usage,
1623 cmd->cmd_desc);
1624 if (cmd->cmd_option)
1625 printf("Options:\n\n%s\n", cmd->cmd_option);
1627 else {
1628 printf("command \"%s\" not implemented\n", command);
1633 static int64_t parse_mem_size_kb(char *mem)
1635 char *endptr;
1636 int64_t kbytes;
1638 kbytes = strtoll(mem, &endptr, 10);
1640 if (strlen(endptr) > 1)
1641 return -1;
1643 switch (tolower((uint8_t)*endptr)) {
1644 case 't':
1645 kbytes <<= 10;
1646 case 'g':
1647 kbytes <<= 10;
1648 case '\0':
1649 case 'm':
1650 kbytes <<= 10;
1651 case 'k':
1652 break;
1653 case 'b':
1654 kbytes >>= 10;
1655 break;
1656 default:
1657 return -1;
1660 return kbytes;
1663 int set_memory_max(char *p, char *mem)
1665 int64_t memorykb;
1666 int rc;
1668 find_domain(p);
1670 memorykb = parse_mem_size_kb(mem);
1671 if (memorykb == -1) {
1672 fprintf(stderr, "invalid memory size: %s\n", mem);
1673 exit(3);
1676 rc = libxl_domain_setmaxmem(&ctx, domid, memorykb);
1678 return rc;
1681 int main_memmax(int argc, char **argv)
1683 int opt = 0;
1684 char *p = NULL, *mem;
1685 int rc;
1687 while ((opt = getopt(argc, argv, "h")) != -1) {
1688 switch (opt) {
1689 case 'h':
1690 help("mem-max");
1691 exit(0);
1692 default:
1693 fprintf(stderr, "option not supported\n");
1694 break;
1697 if (optind >= argc - 1) {
1698 help("mem-max");
1699 return 2;
1702 p = argv[optind];
1703 mem = argv[optind + 1];
1705 rc = set_memory_max(p, mem);
1706 if (rc) {
1707 fprintf(stderr, "cannot set domid %d static max memory to : %s\n", domid, mem);
1708 return 1;
1711 return 0;
1714 void set_memory_target(char *p, char *mem)
1716 long long int memorykb;
1718 find_domain(p);
1720 memorykb = parse_mem_size_kb(mem);
1721 if (memorykb == -1) {
1722 fprintf(stderr, "invalid memory size: %s\n", mem);
1723 exit(3);
1726 libxl_set_memory_target(&ctx, domid, memorykb, /* enforce */ 1);
1729 int main_memset(int argc, char **argv)
1731 int opt = 0;
1732 char *p = NULL, *mem;
1734 while ((opt = getopt(argc, argv, "h:")) != -1) {
1735 switch (opt) {
1736 case 'h':
1737 help("mem-set");
1738 return 0;
1739 default:
1740 fprintf(stderr, "option not supported\n");
1741 break;
1744 if (optind >= argc - 1) {
1745 help("mem-set");
1746 return 2;
1749 p = argv[optind];
1750 mem = argv[optind + 1];
1752 set_memory_target(p, mem);
1753 return 0;
1756 void cd_insert(char *dom, char *virtdev, char *phys)
1758 libxl_device_disk disk;
1759 char *p;
1761 find_domain(dom);
1763 disk.backend_domid = 0;
1764 disk.domid = domid;
1765 if (phys) {
1766 p = strchr(phys, ':');
1767 if (!p) {
1768 fprintf(stderr, "No type specified, ");
1769 disk.physpath = phys;
1770 if (!strncmp(phys, "/dev", 4)) {
1771 fprintf(stderr, "assuming phy:\n");
1772 disk.phystype = PHYSTYPE_PHY;
1773 } else {
1774 fprintf(stderr, "assuming file:\n");
1775 disk.phystype = PHYSTYPE_FILE;
1777 } else {
1778 *p = '\0';
1779 p++;
1780 disk.physpath = p;
1781 libxl_string_to_phystype(&ctx, phys, &disk.phystype);
1783 } else {
1784 disk.physpath = NULL;
1785 disk.phystype = 0;
1787 disk.virtpath = virtdev;
1788 disk.unpluggable = 1;
1789 disk.readwrite = 0;
1790 disk.is_cdrom = 1;
1792 libxl_cdrom_insert(&ctx, domid, &disk);
1795 int main_cd_eject(int argc, char **argv)
1797 int opt = 0;
1798 char *p = NULL, *virtdev;
1800 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1801 switch (opt) {
1802 case 'h':
1803 help("cd-eject");
1804 return 0;
1805 default:
1806 fprintf(stderr, "option not supported\n");
1807 break;
1810 if (optind >= argc - 1) {
1811 help("cd-eject");
1812 return 2;
1815 p = argv[optind];
1816 virtdev = argv[optind + 1];
1818 cd_insert(p, virtdev, NULL);
1819 return 0;
1822 int main_cd_insert(int argc, char **argv)
1824 int opt = 0;
1825 char *p = NULL, *file = NULL, *virtdev;
1827 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1828 switch (opt) {
1829 case 'h':
1830 help("cd-insert");
1831 return 0;
1832 default:
1833 fprintf(stderr, "option not supported\n");
1834 break;
1837 if (optind >= argc - 2) {
1838 help("cd-insert");
1839 return 2;
1842 p = argv[optind];
1843 virtdev = argv[optind + 1];
1844 file = argv[optind + 2];
1846 cd_insert(p, virtdev, file);
1847 return 0;
1850 int main_console(int argc, char **argv)
1852 int opt = 0;
1854 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1855 switch (opt) {
1856 case 'h':
1857 help("console");
1858 return 0;
1859 default:
1860 fprintf(stderr, "option not supported\n");
1861 break;
1864 if (optind >= argc) {
1865 help("console");
1866 return 2;
1869 find_domain(argv[optind]);
1870 libxl_primary_console_exec(&ctx, domid);
1871 fprintf(stderr, "Unable to attach console\n");
1872 return 1;
1875 static int vncviewer(const char *domain_spec, int autopass)
1877 find_domain(domain_spec);
1878 libxl_vncviewer_exec(&ctx, domid, autopass);
1879 fprintf(stderr, "Unable to execute vncviewer\n");
1880 return 1;
1883 int main_vncviewer(int argc, char **argv)
1885 static const struct option long_options[] = {
1886 {"autopass", 0, 0, 'a'},
1887 {"vncviewer-autopass", 0, 0, 'a'},
1888 {"help", 0, 0, 'h'},
1889 {0, 0, 0, 0}
1890 };
1891 int opt, autopass = 0;
1893 while (1) {
1894 opt = getopt_long(argc, argv, "ah", long_options, NULL);
1895 if (opt == -1)
1896 break;
1898 switch (opt) {
1899 case 'a':
1900 autopass = 1;
1901 break;
1902 case 'h':
1903 help("vncviewer");
1904 return 0;
1905 default:
1906 fprintf(stderr, "option not supported\n");
1907 break;
1911 if (argc - optind != 1) {
1912 help("vncviewer");
1913 return 2;
1916 if (vncviewer(argv[optind], autopass))
1917 return 1;
1918 return 0;
1921 void pcilist_assignable(void)
1923 libxl_device_pci *pcidevs;
1924 int num, i;
1926 if ( libxl_device_pci_list_assignable(&ctx, &pcidevs, &num) )
1927 return;
1928 for (i = 0; i < num; i++) {
1929 printf("%04x:%02x:%02x:%01x\n",
1930 pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
1932 free(pcidevs);
1935 int main_pcilist_assignable(int argc, char **argv)
1937 int opt;
1939 while ((opt = getopt(argc, argv, "h")) != -1) {
1940 switch (opt) {
1941 case 'h':
1942 help("pci-list-assignable-devices");
1943 return 0;
1944 default:
1945 fprintf(stderr, "option not supported\n");
1946 break;
1950 pcilist_assignable();
1951 return 0;
1954 void pcilist(char *dom)
1956 libxl_device_pci *pcidevs;
1957 int num, i;
1959 find_domain(dom);
1961 if (libxl_device_pci_list_assigned(&ctx, &pcidevs, domid, &num))
1962 return;
1963 printf("VFn domain bus slot func\n");
1964 for (i = 0; i < num; i++) {
1965 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);
1967 free(pcidevs);
1970 int main_pcilist(int argc, char **argv)
1972 int opt;
1973 char *domname = NULL;
1975 while ((opt = getopt(argc, argv, "h")) != -1) {
1976 switch (opt) {
1977 case 'h':
1978 help("pci-list");
1979 return 0;
1980 default:
1981 fprintf(stderr, "option not supported\n");
1982 break;
1985 if (optind >= argc) {
1986 help("pci-list");
1987 return 2;
1990 domname = argv[optind];
1992 pcilist(domname);
1993 return 0;
1996 void pcidetach(char *dom, char *bdf)
1998 libxl_device_pci pcidev;
2000 find_domain(dom);
2002 memset(&pcidev, 0x00, sizeof(pcidev));
2003 if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
2004 fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
2005 exit(2);
2007 libxl_device_pci_remove(&ctx, domid, &pcidev);
2010 int main_pcidetach(int argc, char **argv)
2012 int opt;
2013 char *domname = NULL, *bdf = NULL;
2015 while ((opt = getopt(argc, argv, "h")) != -1) {
2016 switch (opt) {
2017 case 'h':
2018 help("pci-detach");
2019 return 0;
2020 default:
2021 fprintf(stderr, "option not supported\n");
2022 break;
2025 if (optind >= argc - 1) {
2026 help("pci-detach");
2027 return 2;
2030 domname = argv[optind];
2031 bdf = argv[optind + 1];
2033 pcidetach(domname, bdf);
2034 return 0;
2036 void pciattach(char *dom, char *bdf, char *vs)
2038 libxl_device_pci pcidev;
2040 find_domain(dom);
2042 memset(&pcidev, 0x00, sizeof(pcidev));
2043 if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
2044 fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
2045 exit(2);
2047 libxl_device_pci_add(&ctx, domid, &pcidev);
2050 int main_pciattach(int argc, char **argv)
2052 int opt;
2053 char *domname = NULL, *bdf = NULL, *vs = NULL;
2055 while ((opt = getopt(argc, argv, "h")) != -1) {
2056 switch (opt) {
2057 case 'h':
2058 help("pci-attach");
2059 return 0;
2060 default:
2061 fprintf(stderr, "option not supported\n");
2062 break;
2065 if (optind >= argc - 1) {
2066 help("pci-attach");
2067 return 2;
2070 domname = argv[optind];
2071 bdf = argv[optind + 1];
2073 if (optind + 1 < argc)
2074 vs = argv[optind + 2];
2076 pciattach(domname, bdf, vs);
2077 return 0;
2080 void pause_domain(char *p)
2082 find_domain(p);
2083 libxl_domain_pause(&ctx, domid);
2086 void unpause_domain(char *p)
2088 find_domain(p);
2089 libxl_domain_unpause(&ctx, domid);
2092 void destroy_domain(char *p)
2094 int rc;
2095 find_domain(p);
2096 if (domid == 0) {
2097 fprintf(stderr, "Cannot destroy privileged domain 0.\n\n");
2098 exit(-1);
2100 rc = libxl_domain_destroy(&ctx, domid, 0);
2101 if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n.",rc); exit(-1); }
2104 void shutdown_domain(char *p)
2106 int rc;
2107 find_domain(p);
2108 rc=libxl_domain_shutdown(&ctx, domid, 0);
2109 if (rc) { fprintf(stderr,"shutdown failed (rc=%d)\n.",rc);exit(-1); }
2112 void reboot_domain(char *p)
2114 int rc;
2115 find_domain(p);
2116 rc=libxl_domain_shutdown(&ctx, domid, 1);
2117 if (rc) { fprintf(stderr,"reboot failed (rc=%d)\n.",rc);exit(-1); }
2120 void list_domains_details(const libxl_dominfo *info, int nb_domain)
2122 struct domain_config d_config;
2124 char *config_file;
2125 uint8_t *data;
2126 int i, len, rc;
2127 libxl_device_model_info dm_info;
2129 for (i = 0; i < nb_domain; i++) {
2130 /* no detailed info available on dom0 */
2131 if (info[i].domid == 0)
2132 continue;
2133 rc = libxl_userdata_retrieve(&ctx, info[i].domid, "xl", &data, &len);
2134 if (rc)
2135 continue;
2136 CHK_ERRNO(asprintf(&config_file, "<domid %d data>", info[i].domid));
2137 memset(&d_config, 0x00, sizeof(d_config));
2138 parse_config_data(config_file, (char *)data, len, &d_config, &dm_info);
2139 printf_info(info[i].domid, &d_config, &dm_info);
2140 free_domain_config(&d_config);
2141 free(data);
2142 free(config_file);
2146 void list_domains(int verbose, const libxl_dominfo *info, int nb_domain)
2148 int i;
2150 printf("Name ID Mem VCPUs\tState\tTime(s)\n");
2151 for (i = 0; i < nb_domain; i++) {
2152 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f",
2153 libxl_domid_to_name(&ctx, info[i].domid),
2154 info[i].domid,
2155 (unsigned long) (info[i].max_memkb / 1024),
2156 info[i].vcpu_online,
2157 info[i].running ? 'r' : '-',
2158 info[i].blocked ? 'b' : '-',
2159 info[i].paused ? 'p' : '-',
2160 info[i].shutdown ? 's' : '-',
2161 info[i].shutdown_reason == SHUTDOWN_crash ? 'c' : '-',
2162 info[i].dying ? 'd' : '-',
2163 ((float)info[i].cpu_time / 1e9));
2164 if (verbose) {
2165 char *uuid = libxl_uuid2string(&ctx, info[i].uuid);
2166 printf(" %s", uuid);
2168 putchar('\n');
2172 void list_vm(void)
2174 libxl_vminfo *info;
2175 int nb_vm, i;
2177 info = libxl_list_vm(&ctx, &nb_vm);
2179 if (info < 0) {
2180 fprintf(stderr, "libxl_domain_infolist failed.\n");
2181 exit(1);
2183 printf("UUID ID name\n");
2184 for (i = 0; i < nb_vm; i++) {
2185 printf(UUID_FMT " %d %-30s\n",
2186 info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
2187 info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
2188 info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], info[i].uuid[11],
2189 info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], info[i].uuid[15],
2190 info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
2192 free(info);
2195 static void save_domain_core_begin(char *domain_spec,
2196 const char *override_config_file,
2197 uint8_t **config_data_r,
2198 int *config_len_r)
2200 int rc;
2202 find_domain(domain_spec);
2204 /* configuration file in optional data: */
2206 if (override_config_file) {
2207 void *config_v = 0;
2208 rc = libxl_read_file_contents(&ctx, override_config_file,
2209 &config_v, config_len_r);
2210 *config_data_r = config_v;
2211 } else {
2212 rc = libxl_userdata_retrieve(&ctx, domid, "xl",
2213 config_data_r, config_len_r);
2215 if (rc) {
2216 fputs("Unable to get config file\n",stderr);
2217 exit(2);
2221 void save_domain_core_writeconfig(int fd, const char *filename,
2222 const uint8_t *config_data, int config_len)
2224 struct save_file_header hdr;
2225 uint8_t *optdata_begin;
2226 union { uint32_t u32; char b[4]; } u32buf;
2228 memset(&hdr, 0, sizeof(hdr));
2229 memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
2230 hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
2232 optdata_begin= 0;
2234 #define ADD_OPTDATA(ptr, len) ({ \
2235 if ((len)) { \
2236 hdr.optional_data_len += (len); \
2237 optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
2238 memcpy(optdata_begin + hdr.optional_data_len - (len), \
2239 (ptr), (len)); \
2240 } \
2241 })
2243 u32buf.u32 = config_len;
2244 ADD_OPTDATA(u32buf.b, 4);
2245 ADD_OPTDATA(config_data, config_len);
2247 /* that's the optional data */
2249 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2250 &hdr, sizeof(hdr), filename, "header") );
2251 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2252 optdata_begin, hdr.optional_data_len, filename, "header") );
2254 fprintf(stderr, "Saving to %s new xl format (info"
2255 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
2256 filename, hdr.mandatory_flags, hdr.optional_flags,
2257 hdr.optional_data_len);
2260 int save_domain(char *p, char *filename, int checkpoint,
2261 const char *override_config_file)
2263 int fd;
2264 uint8_t *config_data;
2265 int config_len;
2267 save_domain_core_begin(p, override_config_file, &config_data, &config_len);
2269 if (!config_len) {
2270 fputs(" Savefile will not contain xl domain config\n", stderr);
2273 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
2274 if (fd < 0) {
2275 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
2276 exit(2);
2279 save_domain_core_writeconfig(fd, filename, config_data, config_len);
2281 CHK_ERRNO(libxl_domain_suspend(&ctx, NULL, domid, fd));
2282 close(fd);
2284 if (checkpoint)
2285 libxl_domain_unpause(&ctx, domid);
2286 else
2287 libxl_domain_destroy(&ctx, domid, 0);
2289 exit(0);
2292 static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
2293 const char *what, const char *rune) {
2294 char buf[msgsz];
2295 const char *stream;
2296 int rc;
2298 stream = rune ? "migration receiver stream" : "migration stream";
2299 rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
2300 if (rc) return ERROR_FAIL;
2302 if (memcmp(buf, msg, msgsz)) {
2303 fprintf(stderr, "%s contained unexpected data instead of %s\n",
2304 stream, what);
2305 if (rune)
2306 fprintf(stderr, "(command run was: %s )\n", rune);
2307 return ERROR_FAIL;
2309 return 0;
2312 static void migration_child_report(pid_t migration_child, int recv_fd) {
2313 pid_t child;
2314 int status, sr;
2315 struct timeval now, waituntil, timeout;
2316 static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
2318 if (!migration_child) return;
2320 CHK_ERRNO( gettimeofday(&waituntil, 0) );
2321 waituntil.tv_sec += 2;
2323 for (;;) {
2324 child = waitpid(migration_child, &status, WNOHANG);
2326 if (child == migration_child) {
2327 if (status)
2328 libxl_report_child_exitstatus(&ctx, XTL_INFO,
2329 "migration target process",
2330 migration_child, status);
2331 break;
2333 if (child == -1) {
2334 if (errno == EINTR) continue;
2335 fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
2336 (long)migration_child, strerror(errno));
2337 break;
2339 assert(child == 0);
2341 CHK_ERRNO( gettimeofday(&now, 0) );
2342 if (timercmp(&now, &waituntil, >)) {
2343 fprintf(stderr, "migration child [%ld] not exiting, no longer"
2344 " waiting (exit status will be unreported)\n",
2345 (long)migration_child);
2346 break;
2348 timersub(&waituntil, &now, &timeout);
2350 if (recv_fd >= 0) {
2351 fd_set readfds, exceptfds;
2352 FD_ZERO(&readfds);
2353 FD_ZERO(&exceptfds);
2354 FD_SET(recv_fd, &readfds);
2355 FD_SET(recv_fd, &exceptfds);
2356 sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
2357 } else {
2358 if (timercmp(&timeout, &pollinterval, >))
2359 timeout = pollinterval;
2360 sr = select(0,0,0,0, &timeout);
2362 if (sr > 0) {
2363 recv_fd = -1;
2364 } else if (sr == 0) {
2365 } else if (sr == -1) {
2366 if (errno != EINTR) {
2367 fprintf(stderr, "migration child [%ld] exit wait select"
2368 " failed unexpectedly: %s\n",
2369 (long)migration_child, strerror(errno));
2370 break;
2374 migration_child = 0;
2377 static void migrate_domain(char *domain_spec, const char *rune,
2378 const char *override_config_file)
2380 pid_t child = -1;
2381 int rc;
2382 int sendpipe[2], recvpipe[2];
2383 int send_fd, recv_fd;
2384 libxl_domain_suspend_info suspinfo;
2385 char *away_domname;
2386 char rc_buf;
2387 uint8_t *config_data;
2388 int config_len;
2390 save_domain_core_begin(domain_spec, override_config_file,
2391 &config_data, &config_len);
2393 if (!config_len) {
2394 fprintf(stderr, "No config file stored for running domain and "
2395 "none supplied - cannot migrate.\n");
2396 exit(1);
2399 MUST( libxl_pipe(&ctx, sendpipe) );
2400 MUST( libxl_pipe(&ctx, recvpipe) );
2402 child = libxl_fork(&ctx);
2403 if (child==-1) exit(1);
2405 if (!child) {
2406 dup2(sendpipe[0], 0);
2407 dup2(recvpipe[1], 1);
2408 close(sendpipe[0]); close(sendpipe[1]);
2409 close(recvpipe[0]); close(recvpipe[1]);
2410 execlp("sh","sh","-c",rune,(char*)0);
2411 perror("failed to exec sh");
2412 exit(-1);
2415 close(sendpipe[0]);
2416 close(recvpipe[1]);
2417 send_fd = sendpipe[1];
2418 recv_fd = recvpipe[0];
2420 signal(SIGPIPE, SIG_IGN);
2421 /* if receiver dies, we get an error and can clean up
2422 rather than just dying */
2424 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
2425 sizeof(migrate_receiver_banner)-1,
2426 "banner", rune);
2427 if (rc) {
2428 close(send_fd);
2429 migration_child_report(child, recv_fd);
2430 exit(-rc);
2433 save_domain_core_writeconfig(send_fd, "migration stream",
2434 config_data, config_len);
2436 xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
2438 memset(&suspinfo, 0, sizeof(suspinfo));
2439 suspinfo.flags |= XL_SUSPEND_LIVE;
2440 rc = libxl_domain_suspend(&ctx, &suspinfo, domid, send_fd);
2441 if (rc) {
2442 fprintf(stderr, "migration sender: libxl_domain_suspend failed"
2443 " (rc=%d)\n", rc);
2444 goto failed_resume;
2447 //fprintf(stderr, "migration sender: Transfer complete.\n");
2448 // Should only be printed when debugging as it's a bit messy with
2449 // progress indication.
2451 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
2452 sizeof(migrate_receiver_ready),
2453 "ready message", rune);
2454 if (rc) goto failed_resume;
2456 xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
2458 /* right, at this point we are about give the destination
2459 * permission to rename and resume, so we must first rename the
2460 * domain away ourselves */
2462 fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
2464 if (common_domname) {
2465 if (asprintf(&away_domname, "%s--migratedaway", common_domname) < 0)
2466 goto failed_resume;
2467 rc = libxl_domain_rename(&ctx, domid,
2468 common_domname, away_domname, 0);
2469 if (rc) goto failed_resume;
2472 /* point of no return - as soon as we have tried to say
2473 * "go" to the receiver, it's not safe to carry on. We leave
2474 * the domain renamed to %s--migratedaway in case that's helpful.
2475 */
2477 fprintf(stderr, "migration sender: Giving target permission to start.\n");
2479 rc = libxl_write_exactly(&ctx, send_fd,
2480 migrate_permission_to_go,
2481 sizeof(migrate_permission_to_go),
2482 "migration stream", "GO message");
2483 if (rc) goto failed_badly;
2485 rc = migrate_read_fixedmessage(recv_fd, migrate_report,
2486 sizeof(migrate_report),
2487 "success/failure report message", rune);
2488 if (rc) goto failed_badly;
2490 rc = libxl_read_exactly(&ctx, recv_fd,
2491 &rc_buf, 1,
2492 "migration ack stream", "success/failure status");
2493 if (rc) goto failed_badly;
2495 if (rc_buf) {
2496 fprintf(stderr, "migration sender: Target reports startup failure"
2497 " (status code %d).\n", rc_buf);
2499 rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
2500 sizeof(migrate_permission_to_go),
2501 "permission for sender to resume",
2502 rune);
2503 if (rc) goto failed_badly;
2505 fprintf(stderr, "migration sender: Trying to resume at our end.\n");
2507 if (common_domname) {
2508 libxl_domain_rename(&ctx, domid,
2509 away_domname, common_domname, 0);
2511 rc = libxl_domain_resume(&ctx, domid);
2512 if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
2514 fprintf(stderr, "Migration failed due to problems at target.\n");
2515 exit(-ERROR_FAIL);
2518 fprintf(stderr, "migration sender: Target reports successful startup.\n");
2519 libxl_domain_destroy(&ctx, domid, 1); /* bang! */
2520 fprintf(stderr, "Migration successful.\n");
2521 exit(0);
2523 failed_resume:
2524 close(send_fd);
2525 migration_child_report(child, recv_fd);
2526 fprintf(stderr, "Migration failed, resuming at sender.\n");
2527 libxl_domain_resume(&ctx, domid);
2528 exit(-ERROR_FAIL);
2530 failed_badly:
2531 fprintf(stderr,
2532 "** Migration failed during final handshake **\n"
2533 "Domain state is now undefined !\n"
2534 "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
2535 " resuming at most one instance. Two simultaneous instances of the domain\n"
2536 " would probably result in SEVERE DATA LOSS and it is now your\n"
2537 " responsibility to avoid that. Sorry.\n");
2539 close(send_fd);
2540 migration_child_report(child, recv_fd);
2541 exit(-ERROR_BADFAIL);
2544 static void core_dump_domain(const char *domain_spec, const char *filename)
2546 int rc;
2547 find_domain(domain_spec);
2548 rc=libxl_domain_core_dump(&ctx, domid, filename);
2549 if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n.",rc);exit(-1); }
2552 static void migrate_receive(int debug, int daemonize)
2554 int rc, rc2;
2555 char rc_buf;
2556 char *migration_domname;
2557 struct domain_create dom_info;
2559 signal(SIGPIPE, SIG_IGN);
2560 /* if we get SIGPIPE we'd rather just have it as an error */
2562 fprintf(stderr, "migration target: Ready to receive domain.\n");
2564 CHK_ERRNO( libxl_write_exactly(&ctx, 1,
2565 migrate_receiver_banner,
2566 sizeof(migrate_receiver_banner)-1,
2567 "migration ack stream",
2568 "banner") );
2570 memset(&dom_info, 0, sizeof(dom_info));
2571 dom_info.debug = debug;
2572 dom_info.daemonize = daemonize;
2573 dom_info.paused = 1;
2574 dom_info.restore_file = "incoming migration stream";
2575 dom_info.migration_domname_r = &migration_domname;
2577 rc = create_domain(&dom_info);
2578 if (rc < 0) {
2579 fprintf(stderr, "migration target: Domain creation failed"
2580 " (code %d).\n", rc);
2581 exit(-rc);
2584 fprintf(stderr, "migration target: Transfer complete,"
2585 " requesting permission to start domain.\n");
2587 rc = libxl_write_exactly(&ctx, 1,
2588 migrate_receiver_ready,
2589 sizeof(migrate_receiver_ready),
2590 "migration ack stream", "ready message");
2591 if (rc) exit(-rc);
2593 rc = migrate_read_fixedmessage(0, migrate_permission_to_go,
2594 sizeof(migrate_permission_to_go),
2595 "GO message", 0);
2596 if (rc) goto perhaps_destroy_notify_rc;
2598 fprintf(stderr, "migration target: Got permission, starting domain.\n");
2600 if (migration_domname) {
2601 rc = libxl_domain_rename(&ctx, domid,
2602 migration_domname, common_domname, 0);
2603 if (rc) goto perhaps_destroy_notify_rc;
2606 rc = libxl_domain_unpause(&ctx, domid);
2607 if (rc) goto perhaps_destroy_notify_rc;
2609 fprintf(stderr, "migration target: Domain started successsfully.\n");
2610 rc = 0;
2612 perhaps_destroy_notify_rc:
2613 rc2 = libxl_write_exactly(&ctx, 1,
2614 migrate_report, sizeof(migrate_report),
2615 "migration ack stream",
2616 "success/failure report");
2617 if (rc2) exit(-ERROR_BADFAIL);
2619 rc_buf = -rc;
2620 assert(!!rc_buf == !!rc);
2621 rc2 = libxl_write_exactly(&ctx, 1, &rc_buf, 1,
2622 "migration ack stream",
2623 "success/failure code");
2624 if (rc2) exit(-ERROR_BADFAIL);
2626 if (rc) {
2627 fprintf(stderr, "migration target: Failure, destroying our copy.\n");
2629 rc2 = libxl_domain_destroy(&ctx, domid, 1);
2630 if (rc2) {
2631 fprintf(stderr, "migration target: Failed to destroy our copy"
2632 " (code %d).\n", rc2);
2633 exit(-ERROR_BADFAIL);
2636 fprintf(stderr, "migration target: Cleanup OK, granting sender"
2637 " permission to resume.\n");
2639 rc2 = libxl_write_exactly(&ctx, 1,
2640 migrate_permission_to_go,
2641 sizeof(migrate_permission_to_go),
2642 "migration ack stream",
2643 "permission to sender to have domain back");
2644 if (rc2) exit(-ERROR_BADFAIL);
2647 exit(0);
2650 int main_restore(int argc, char **argv)
2652 char *checkpoint_file = NULL;
2653 char *config_file = NULL;
2654 struct domain_create dom_info;
2655 int paused = 0, debug = 0, daemonize = 1;
2656 int opt, rc;
2658 while ((opt = getopt(argc, argv, "hpde")) != -1) {
2659 switch (opt) {
2660 case 'p':
2661 paused = 1;
2662 break;
2663 case 'd':
2664 debug = 1;
2665 break;
2666 case 'e':
2667 daemonize = 0;
2668 break;
2669 case 'h':
2670 help("restore");
2671 return 0;
2672 default:
2673 fprintf(stderr, "option not supported\n");
2674 break;
2678 if (argc-optind == 1) {
2679 checkpoint_file = argv[optind];
2680 } else if (argc-optind == 2) {
2681 config_file = argv[optind];
2682 checkpoint_file = argv[optind + 1];
2683 } else {
2684 help("restore");
2685 return 2;
2688 memset(&dom_info, 0, sizeof(dom_info));
2689 dom_info.debug = debug;
2690 dom_info.daemonize = daemonize;
2691 dom_info.paused = paused;
2692 dom_info.config_file = config_file;
2693 dom_info.restore_file = checkpoint_file;
2694 dom_info.migrate_fd = -1;
2696 rc = create_domain(&dom_info);
2697 if (rc < 0)
2698 return -rc;
2700 return 0;
2703 int main_migrate_receive(int argc, char **argv)
2705 int debug = 0, daemonize = 1;
2706 int opt;
2708 while ((opt = getopt(argc, argv, "hed")) != -1) {
2709 switch (opt) {
2710 case 'h':
2711 help("migrate-receive");
2712 return 2;
2713 break;
2714 case 'e':
2715 daemonize = 0;
2716 break;
2717 case 'd':
2718 debug = 1;
2719 break;
2720 default:
2721 fprintf(stderr, "option not supported\n");
2722 break;
2726 if (argc-optind != 0) {
2727 help("migrate-receive");
2728 return 2;
2730 migrate_receive(debug, daemonize);
2731 return 0;
2734 int main_save(int argc, char **argv)
2736 char *filename = NULL, *p = NULL;
2737 const char *config_filename;
2738 int checkpoint = 0;
2739 int opt;
2741 while ((opt = getopt(argc, argv, "hc")) != -1) {
2742 switch (opt) {
2743 case 'c':
2744 checkpoint = 1;
2745 break;
2746 case 'h':
2747 help("save");
2748 return 0;
2749 default:
2750 fprintf(stderr, "option not supported\n");
2751 break;
2755 if (argc-optind < 1 || argc-optind > 3) {
2756 help("save");
2757 return 2;
2760 p = argv[optind];
2761 filename = argv[optind + 1];
2762 config_filename = argv[optind + 2];
2763 save_domain(p, filename, checkpoint, config_filename);
2764 return 0;
2767 int main_migrate(int argc, char **argv)
2769 char *p = NULL;
2770 const char *config_filename = NULL;
2771 const char *ssh_command = "ssh";
2772 char *rune = NULL;
2773 char *host;
2774 int opt, daemonize = 1, debug = 0;
2776 while ((opt = getopt(argc, argv, "hC:s:ed")) != -1) {
2777 switch (opt) {
2778 case 'h':
2779 help("migrate");
2780 return 0;
2781 case 'C':
2782 config_filename = optarg;
2783 break;
2784 case 's':
2785 ssh_command = optarg;
2786 break;
2787 case 'e':
2788 daemonize = 0;
2789 break;
2790 case 'd':
2791 debug = 1;
2792 break;
2793 default:
2794 fprintf(stderr, "option not supported\n");
2795 break;
2799 if (argc-optind < 2 || argc-optind > 2) {
2800 help("migrate");
2801 return 2;
2804 p = argv[optind];
2805 host = argv[optind + 1];
2807 if (!ssh_command[0]) {
2808 rune= host;
2809 } else {
2810 if (asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
2811 ssh_command, host,
2812 daemonize ? "" : " -e",
2813 debug ? " -d" : "") < 0)
2814 return 1;
2817 migrate_domain(p, rune, config_filename);
2818 return 0;
2821 int main_dump_core(int argc, char **argv)
2823 if ( argc-optind < 2 ) {
2824 help("dump-core");
2825 return 2;
2827 core_dump_domain(argv[optind], argv[optind + 1]);
2828 return 0;
2831 int main_pause(int argc, char **argv)
2833 int opt;
2834 char *p;
2837 while ((opt = getopt(argc, argv, "h")) != -1) {
2838 switch (opt) {
2839 case 'h':
2840 help("pause");
2841 return 0;
2842 default:
2843 fprintf(stderr, "option not supported\n");
2844 break;
2847 if (optind >= argc) {
2848 help("pause");
2849 return 2;
2852 p = argv[optind];
2854 pause_domain(p);
2855 return 0;
2858 int main_unpause(int argc, char **argv)
2860 int opt;
2861 char *p;
2864 while ((opt = getopt(argc, argv, "h")) != -1) {
2865 switch (opt) {
2866 case 'h':
2867 help("unpause");
2868 return 0;
2869 default:
2870 fprintf(stderr, "option not supported\n");
2871 break;
2874 if (optind >= argc) {
2875 help("unpause");
2876 return 2;
2879 p = argv[optind];
2881 unpause_domain(p);
2882 return 0;
2885 int main_destroy(int argc, char **argv)
2887 int opt;
2888 char *p;
2890 while ((opt = getopt(argc, argv, "h")) != -1) {
2891 switch (opt) {
2892 case 'h':
2893 help("destroy");
2894 return 0;
2895 default:
2896 fprintf(stderr, "option not supported\n");
2897 break;
2900 if (optind >= argc) {
2901 help("destroy");
2902 return 2;
2905 p = argv[optind];
2907 destroy_domain(p);
2908 return 0;
2911 int main_shutdown(int argc, char **argv)
2913 int opt;
2914 char *p;
2916 while ((opt = getopt(argc, argv, "h")) != -1) {
2917 switch (opt) {
2918 case 'h':
2919 help("shutdown");
2920 return 0;
2921 default:
2922 fprintf(stderr, "option not supported\n");
2923 break;
2926 if (optind >= argc) {
2927 help("shutdown");
2928 return 2;
2931 p = argv[optind];
2933 shutdown_domain(p);
2934 return 0;
2937 int main_reboot(int argc, char **argv)
2939 int opt;
2940 char *p;
2942 while ((opt = getopt(argc, argv, "h")) != -1) {
2943 switch (opt) {
2944 case 'h':
2945 help("reboot");
2946 return 0;
2947 default:
2948 fprintf(stderr, "option not supported\n");
2949 break;
2952 if (optind >= argc) {
2953 help("reboot");
2954 return 2;
2957 p = argv[optind];
2959 reboot_domain(p);
2960 return 0;
2962 int main_list(int argc, char **argv)
2964 int opt, verbose = 0;
2965 int details = 0;
2966 int option_index = 0;
2967 static struct option long_options[] = {
2968 {"long", 0, 0, 'l'},
2969 {"help", 0, 0, 'h'},
2970 {"verbose", 0, 0, 'v'},
2971 {0, 0, 0, 0}
2972 };
2974 libxl_dominfo info_buf;
2975 libxl_dominfo *info, *info_free=0;
2976 int nb_domain, rc;
2978 while (1) {
2979 opt = getopt_long(argc, argv, "lvh", long_options, &option_index);
2980 if (opt == -1)
2981 break;
2983 switch (opt) {
2984 case 'l':
2985 details = 1;
2986 break;
2987 case 'h':
2988 help("list");
2989 return 0;
2990 case 'v':
2991 verbose = 1;
2992 break;
2993 default:
2994 fprintf(stderr, "option not supported\n");
2995 break;
2999 if (optind >= argc) {
3000 info = libxl_list_domain(&ctx, &nb_domain);
3001 if (!info) {
3002 fprintf(stderr, "libxl_domain_infolist failed.\n");
3003 return 1;
3005 info_free = info;
3006 } else if (optind == argc-1) {
3007 find_domain(argv[optind]);
3008 rc = libxl_domain_info(&ctx, &info_buf, domid);
3009 if (rc == ERROR_INVAL) {
3010 fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
3011 argv[optind]);
3012 return -rc;
3014 if (rc) {
3015 fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
3016 return -rc;
3018 info = &info_buf;
3019 nb_domain = 1;
3020 } else {
3021 help("list");
3022 return 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 return 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 return 0;
3044 default:
3045 fprintf(stderr, "option not supported\n");
3046 break;
3050 list_vm();
3051 return 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 return 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 return 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 return -rc;
3139 return 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 return 0;
3171 default:
3172 fprintf(stderr, "option not supported\n");
3173 break;
3176 if (optind >= argc - 1) {
3177 help("button-press");
3178 return 2;
3181 p = argv[optind];
3182 b = argv[optind + 1];
3184 button_press(p, b);
3185 return 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 return 0;
3308 default:
3309 fprintf(stderr, "option `%c' not supported.\n", opt);
3310 break;
3314 vcpulist(argc - 2, argv + 2);
3315 return 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 return 0;
3407 while ((opt = getopt(argc, argv, "h")) != -1) {
3408 switch (opt) {
3409 case 'h':
3410 help("vcpu-pin");
3411 return 0;
3412 default:
3413 fprintf(stderr, "option `%c' not supported.\n", opt);
3414 break;
3418 vcpupin(argv[2], argv[3] , argv[4]);
3419 return 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 return 0;
3448 while ((opt = getopt(argc, argv, "h")) != -1) {
3449 switch (opt) {
3450 case 'h':
3451 help("vcpu-set");
3452 return 0;
3453 default:
3454 fprintf(stderr, "option `%c' not supported.\n", opt);
3455 break;
3459 vcpuset(argv[2], argv[3]);
3460 return 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 return 0;
3568 default:
3569 fprintf(stderr, "option `%c' not supported.\n", opt);
3570 break;
3574 info();
3575 return 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 return 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 return 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 return 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 return -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 return -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 return -rc;
3683 return 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 return 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 return 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 return 1;
3714 printf("%d\n", domid);
3716 return 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 return 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 return 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 return 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 return 1;
3754 printf("%s\n", domname);
3756 return 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 return 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 return 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 return 1;
3791 return 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 return 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 return 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 return 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 return 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 return 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 return 1;
3871 libxl_send_sysrq(&ctx, domid, sysrq[0]);
3873 return 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 return 0;
3886 default:
3887 fprintf(stderr, "option not supported\n");
3888 break;
3891 if (optind >= argc) {
3892 help("debug-keys");
3893 return 2;
3896 keys = argv[optind];
3898 if (libxl_send_debug_keys(&ctx, keys)) {
3899 fprintf(stderr, "cannot send debug keys: %s\n", keys);
3900 return 1;
3903 return 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 return 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 return 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 return 0;
3948 default:
3949 fprintf(stderr, "option `%c' not supported.\n", opt);
3950 break;
3954 return 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 return 0;
3969 while ((opt = getopt(argc, argv, "h")) != -1) {
3970 switch (opt) {
3971 case 'h':
3972 help("network-attach");
3973 return 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 return 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 return 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 return 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 return 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 return 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 return 1;
4032 nic.domid = domid;
4033 if (libxl_device_nic_add(&ctx, domid, &nic)) {
4034 fprintf(stderr, "libxl_device_nic_add failed.\n");
4035 return 1;
4037 return 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 return 1;
4050 while ((opt = getopt(argc, argv, "h")) != -1) {
4051 switch (opt) {
4052 case 'h':
4053 help("network-list");
4054 return 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 return 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 return 0;
4097 while ((opt = getopt(argc, argv, "h")) != -1) {
4098 switch (opt) {
4099 case 'h':
4100 help("network-detach");
4101 return 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 return 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 return 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 return 1;
4124 if (libxl_device_nic_del(&ctx, &nic, 1)) {
4125 fprintf(stderr, "libxl_device_nic_del failed.\n");
4126 return 1;
4128 return 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 return 0;
4142 while ((opt = getopt(argc, argv, "h")) != -1) {
4143 switch (opt) {
4144 case 'h':
4145 help("block-attach");
4146 return 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 return 1;
4172 } else {
4173 fprintf(stderr, "Error: `%s' is not a valid block device.\n", tok);
4174 return 1;
4176 disk.physpath = strtok(NULL, "\0");
4177 if (!disk.physpath) {
4178 fprintf(stderr, "Error: missing path to disk image.\n");
4179 return 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 return 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 return 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 return 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 return 0;
4214 while ((opt = getopt(argc, argv, "h")) != -1) {
4215 switch (opt) {
4216 case 'h':
4217 help("block-list");
4218 return 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 return 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 return 0;
4257 while ((opt = getopt(argc, argv, "h")) != -1) {
4258 switch (opt) {
4259 case 'h':
4260 help("block-detach");
4261 return 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 return 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 return 1;
4276 if (libxl_device_disk_del(&ctx, &disk, 1)) {
4277 fprintf(stderr, "libxl_device_del failed.\n");
4279 return 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 return 0;
4295 while ((opt = getopt(argc, argv, "h")) != -1) {
4296 switch (opt) {
4297 case 'h':
4298 help("network2-attach");
4299 return 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 return 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 return 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 return 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 return 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 return 1;
4357 net2.max_bypasses = val;
4358 } else {
4359 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4360 return 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 return 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 return 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 return 0;
4388 while ((opt = getopt(argc, argv, "h")) != -1) {
4389 switch (opt) {
4390 case 'h':
4391 help("network2-list");
4392 return 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 return 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 return 0;
4432 while ((opt = getopt(argc, argv, "h")) != -1) {
4433 switch (opt) {
4434 case 'h':
4435 help("network2-detach");
4436 return 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 return 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 return 1;
4451 if (libxl_device_net2_del(&ctx, &net2, 1)) {
4452 fprintf(stderr, "libxl_device_net2_del failed.\n");
4453 return 1;
4455 return 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 return 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 return 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 return 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 return 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 return -1;
4685 printf("%s\n", buf);
4686 free(buf);
4687 return 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 return 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 return 1;
4717 if (all)
4718 domid = -1;
4719 else
4720 find_domain(dom);
4722 libxl_tmem_freeze(&ctx, domid);
4723 return 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 return 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 return 1;
4753 if (all)
4754 domid = -1;
4755 else
4756 find_domain(dom);
4758 libxl_tmem_destroy(&ctx, domid);
4759 return 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 return 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 return 1;
4789 if (all)
4790 domid = -1;
4791 else
4792 find_domain(dom);
4794 libxl_tmem_thaw(&ctx, domid);
4795 return 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 return 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 return 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 return 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 return 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 return 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 return 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 return 1;
4908 auth = strtol(autharg, &endptr, 10);
4909 if (*endptr != '\0') {
4910 fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
4911 return 1;
4914 libxl_tmem_shared_auth(&ctx, domid, uuid, auth);
4916 return 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 return 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 return -1;
4939 printf("%d\n", mb);
4940 return 0;