debuggers.hg

view tools/libxl/xl_cmdimpl.c @ 21996:36c9f6ea9782

xl: support backend domid in config file for vifs

Allow specification of backend domains for vifs, either in the config
file or via network-attach.

Signed-off-by: Mihir Nanavati <mihirn@cs.ubc.ca>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Stefano Stabellini <sstabellini@xensource.com>
date Mon Aug 09 17:44:01 2010 +0100 (2010-08-09)
parents fdf12cb3e2d1
children 1644b4efef8a
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, "backend")) {
837 if(libxl_name_to_domid(&ctx, (p2 + 1), &(nic->backend_domid))) {
838 fprintf(stderr, "Specified backend domain does not exist, defaulting to Dom0\n");
839 nic->backend_domid = 0;
840 }
841 } else if (!strcmp(p, "rate")) {
842 fprintf(stderr, "the rate parameter for vifs is currently not supported\n");
843 } else if (!strcmp(p, "accel")) {
844 fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
845 }
846 } while ((p = strtok(NULL, ",")) != NULL);
847 skip:
848 free(buf2);
849 d_config->num_vifs++;
850 }
851 }
853 if (!xlu_cfg_get_list(config, "vif2", &net2s, 0)) {
854 d_config->num_vif2s = 0;
855 d_config->vif2s = NULL;
856 while ((buf = xlu_cfg_get_listitem(net2s, d_config->num_vif2s))) {
857 libxl_device_net2 *net2;
858 char *buf2 = strdup(buf);
859 char *p;
861 d_config->vif2s = realloc(d_config->vif2s, sizeof (libxl_device_net2) * (d_config->num_vif2s + 1));
862 net2 = d_config->vif2s + d_config->num_vif2s;
864 init_net2_info(net2, d_config->num_vif2s);
866 for (p = strtok(buf2, ","); p; p = strtok(buf2, ",")) {
867 while (isblank(*p))
868 p++;
869 if (!strncmp("front_mac=", p, 10)) {
870 libxl_strtomac(p + 10, net2->front_mac);
871 } else if (!strncmp("back_mac=", p, 9)) {
872 libxl_strtomac(p + 9, net2->back_mac);
873 } else if (!strncmp("backend=", p, 8)) {
874 domain_qualifier_to_domid(p + 8, &net2->backend_domid, 0);
875 } else if (!strncmp("trusted=", p, 8)) {
876 net2->trusted = (*(p + 8) == '1');
877 } else if (!strncmp("back_trusted=", p, 13)) {
878 net2->back_trusted = (*(p + 13) == '1');
879 } else if (!strncmp("bridge=", p, 7)) {
880 net2->bridge = strdup(p + 13);
881 } else if (!strncmp("filter_mac=", p, 11)) {
882 net2->filter_mac = (*(p + 11) == '1');
883 } else if (!strncmp("front_filter_mac=", p, 17)) {
884 net2->front_filter_mac = (*(p + 17) == '1');
885 } else if (!strncmp("pdev=", p, 5)) {
886 net2->pdev = strtoul(p + 5, NULL, 10);
887 } else if (!strncmp("max_bypasses=", p, 13)) {
888 net2->max_bypasses = strtoul(p + 13, NULL, 10);
889 }
890 }
891 free(buf2);
892 d_config->num_vif2s++;
893 }
894 }
896 if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
897 d_config->num_vfbs = 0;
898 d_config->num_vkbs = 0;
899 d_config->vfbs = NULL;
900 d_config->vkbs = NULL;
901 while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
902 libxl_device_vfb *vfb;
903 libxl_device_vkb *vkb;
905 char *buf2 = strdup(buf);
906 char *p, *p2;
908 d_config->vfbs = (libxl_device_vfb *) realloc(d_config->vfbs, sizeof(libxl_device_vfb) * (d_config->num_vfbs + 1));
909 vfb = d_config->vfbs + d_config->num_vfbs;
910 init_vfb_info(vfb, d_config->num_vfbs);
912 d_config->vkbs = (libxl_device_vkb *) realloc(d_config->vkbs, sizeof(libxl_device_vkb) * (d_config->num_vkbs + 1));
913 vkb = d_config->vkbs + d_config->num_vkbs;
914 init_vkb_info(vkb, d_config->num_vkbs);
916 p = strtok(buf2, ",");
917 if (!p)
918 goto skip_vfb;
919 do {
920 while (*p == ' ')
921 p++;
922 if ((p2 = strchr(p, '=')) == NULL)
923 break;
924 *p2 = '\0';
925 if (!strcmp(p, "vnc")) {
926 vfb->vnc = atoi(p2 + 1);
927 } else if (!strcmp(p, "vnclisten")) {
928 vfb->vnclisten = strdup(p2 + 1);
929 } else if (!strcmp(p, "vncpasswd")) {
930 vfb->vncpasswd = strdup(p2 + 1);
931 } else if (!strcmp(p, "vncdisplay")) {
932 vfb->vncdisplay = atoi(p2 + 1);
933 } else if (!strcmp(p, "vncunused")) {
934 vfb->vncunused = atoi(p2 + 1);
935 } else if (!strcmp(p, "keymap")) {
936 vfb->keymap = strdup(p2 + 1);
937 } else if (!strcmp(p, "sdl")) {
938 vfb->sdl = atoi(p2 + 1);
939 } else if (!strcmp(p, "opengl")) {
940 vfb->opengl = atoi(p2 + 1);
941 } else if (!strcmp(p, "display")) {
942 vfb->display = strdup(p2 + 1);
943 } else if (!strcmp(p, "xauthority")) {
944 vfb->xauthority = strdup(p2 + 1);
945 }
946 } while ((p = strtok(NULL, ",")) != NULL);
947 skip_vfb:
948 free(buf2);
949 d_config->num_vfbs++;
950 d_config->num_vkbs++;
951 }
952 }
954 if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
955 pci_msitranslate = l;
957 if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
958 pci_power_mgmt = l;
960 if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
961 int i;
962 d_config->num_pcidevs = 0;
963 d_config->pcidevs = NULL;
964 for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
965 libxl_device_pci *pcidev;
967 d_config->pcidevs = (libxl_device_pci *) realloc(d_config->pcidevs, sizeof (libxl_device_pci) * (d_config->num_pcidevs + 1));
968 pcidev = d_config->pcidevs + d_config->num_pcidevs;
969 memset(pcidev, 0x00, sizeof(libxl_device_pci));
971 pcidev->msitranslate = pci_msitranslate;
972 pcidev->power_mgmt = pci_power_mgmt;
973 if (!libxl_device_pci_parse_bdf(&ctx, pcidev, buf))
974 d_config->num_pcidevs++;
975 }
976 }
978 if (c_info->hvm == 1) {
979 /* init dm from c and b */
980 init_dm_info(dm_info, c_info, b_info);
982 /* then process config related to dm */
983 if (!xlu_cfg_get_string (config, "device_model", &buf))
984 dm_info->device_model = strdup(buf);
985 if (!xlu_cfg_get_long (config, "stdvga", &l))
986 dm_info->stdvga = l;
987 if (!xlu_cfg_get_long (config, "vnc", &l))
988 dm_info->vnc = l;
989 if (!xlu_cfg_get_string (config, "vnclisten", &buf))
990 dm_info->vnclisten = strdup(buf);
991 if (!xlu_cfg_get_string (config, "vncpasswd", &buf))
992 dm_info->vncpasswd = strdup(buf);
993 if (!xlu_cfg_get_long (config, "vncdisplay", &l))
994 dm_info->vncdisplay = l;
995 if (!xlu_cfg_get_long (config, "vncunused", &l))
996 dm_info->vncunused = l;
997 if (!xlu_cfg_get_string (config, "keymap", &buf))
998 dm_info->keymap = strdup(buf);
999 if (!xlu_cfg_get_long (config, "sdl", &l))
1000 dm_info->sdl = l;
1001 if (!xlu_cfg_get_long (config, "opengl", &l))
1002 dm_info->opengl = l;
1003 if (!xlu_cfg_get_long (config, "nographic", &l))
1004 dm_info->nographic = l;
1005 if (!xlu_cfg_get_string (config, "serial", &buf))
1006 dm_info->serial = strdup(buf);
1007 if (!xlu_cfg_get_string (config, "boot", &buf))
1008 dm_info->boot = strdup(buf);
1009 if (!xlu_cfg_get_long (config, "usb", &l))
1010 dm_info->usb = l;
1011 if (!xlu_cfg_get_string (config, "usbdevice", &buf))
1012 dm_info->usbdevice = strdup(buf);
1013 if (!xlu_cfg_get_string (config, "soundhw", &buf))
1014 dm_info->soundhw = strdup(buf);
1015 if (!xlu_cfg_get_long (config, "xen_platform_pci", &l))
1016 dm_info->xen_platform_pci = l;
1019 dm_info->type = c_info->hvm ? XENFV : XENPV;
1021 xlu_cfg_destroy(config);
1024 static void *xmalloc(size_t sz) {
1025 void *r;
1026 r = malloc(sz);
1027 if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
1028 (unsigned long)sz); exit(-ERROR_FAIL); }
1029 return r;
1032 static void *xrealloc(void *ptr, size_t sz) {
1033 void *r;
1034 if (!sz) { free(ptr); return 0; }
1035 /* realloc(non-0, 0) has a useless return value;
1036 * but xrealloc(anything, 0) is like free
1037 */
1038 r = realloc(ptr, sz);
1039 if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
1040 (unsigned long)sz); exit(-ERROR_FAIL); }
1041 return r;
1044 int autoconnect_console(int hvm)
1046 int status, options;
1047 pid_t pid, r;
1049 /*
1050 * Fork for xenconsole. We exec xenconsole in the foreground
1051 * process allowing it to retain the tty. xl continues in the
1052 * child. The xenconsole client uses a xenstore watch to wait for
1053 * the console to be setup so there is no race.
1054 */
1055 pid = fork();
1056 if (pid < 0) {
1057 perror("unable to fork xenconsole");
1058 return ERROR_FAIL;
1059 } else if (pid == 0)
1060 return 0;
1062 /*
1063 * In the PV case we only catch failure of the create process, in
1064 * the HVM case we also wait for the creation process to be
1065 * completed so that the stubdom is already up and running and we
1066 * can connect to it.
1067 */
1068 if (hvm)
1069 options = 0;
1070 else
1071 options = WNOHANG;
1072 sleep(1);
1073 r = waitpid(pid, &status, options);
1074 if (r > 0 && WIFEXITED(status) && WEXITSTATUS(status) != 0)
1075 _exit(WEXITSTATUS(status));
1077 libxl_primary_console_exec(&ctx, domid);
1078 /* Do not return. xl continued in child process */
1079 fprintf(stderr, "Unable to attach console\n");
1080 _exit(1);
1083 /* Returns 1 if domain should be restarted, 2 if domain should be renamed then restarted */
1084 static int handle_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1085 struct domain_config *d_config, libxl_dominfo *info)
1087 int restart = 0;
1088 enum action_on_shutdown action;
1090 switch (info->shutdown_reason) {
1091 case SHUTDOWN_poweroff:
1092 action = d_config->on_poweroff;
1093 break;
1094 case SHUTDOWN_reboot:
1095 action = d_config->on_reboot;
1096 break;
1097 case SHUTDOWN_suspend:
1098 return 0;
1099 case SHUTDOWN_crash:
1100 action = d_config->on_crash;
1101 break;
1102 case SHUTDOWN_watchdog:
1103 action = d_config->on_watchdog;
1104 break;
1105 default:
1106 LOG("Unknown shutdown reason code %s. Destroying domain.", info->shutdown_reason);
1107 action = ACTION_DESTROY;
1110 LOG("Action for shutdown reason code %d is %s", info->shutdown_reason, action_on_shutdown_names[action]);
1112 if (action == ACTION_COREDUMP_DESTROY || action == ACTION_COREDUMP_RESTART) {
1113 char *corefile;
1114 int rc;
1116 if (asprintf(&corefile, "/var/xen/dump/%s", d_config->c_info.name) < 0) {
1117 LOG("failed to construct core dump path");
1118 } else {
1119 LOG("dumping core to %s", corefile);
1120 rc=libxl_domain_core_dump(ctx, domid, corefile);
1121 if (rc) LOG("core dump failed (rc=%d).", rc);
1123 /* No point crying over spilled milk, continue on failure. */
1125 if (action == ACTION_COREDUMP_DESTROY)
1126 action = ACTION_DESTROY;
1127 else
1128 action = ACTION_RESTART;
1131 switch (action) {
1132 case ACTION_PRESERVE:
1133 break;
1135 case ACTION_RESTART_RENAME:
1136 restart = 2;
1137 break;
1139 case ACTION_RESTART:
1140 restart = 1;
1141 /* fall-through */
1142 case ACTION_DESTROY:
1143 LOG("Domain %d needs to be cleaned up: destroying the domain", domid);
1144 libxl_domain_destroy(ctx, domid, 0);
1145 break;
1147 case ACTION_COREDUMP_DESTROY:
1148 case ACTION_COREDUMP_RESTART:
1149 /* Already handled these above. */
1150 abort();
1153 return restart;
1156 static int preserve_domain(libxl_ctx *ctx, uint32_t domid, libxl_event *event,
1157 struct domain_config *d_config, libxl_dominfo *info)
1159 time_t now;
1160 struct tm tm;
1161 char stime[24];
1163 libxl_uuid new_uuid;
1165 int rc;
1167 now = time(NULL);
1168 if (now == ((time_t) -1)) {
1169 LOG("Failed to get current time for domain rename");
1170 return 0;
1173 tzset();
1174 if (gmtime_r(&now, &tm) == NULL) {
1175 LOG("Failed to convert time to UTC");
1176 return 0;
1179 if (!strftime(&stime[0], sizeof(stime), "-%Y%m%dT%H%MZ", &tm)) {
1180 LOG("Failed to format time as a string");
1181 return 0;
1184 random_uuid(&new_uuid);
1186 LOG("Preserving domain %d %s with suffix%s", domid, d_config->c_info.name, stime);
1187 rc = libxl_domain_preserve(ctx, domid, &d_config->c_info, stime, new_uuid);
1189 return rc == 0 ? 1 : 0;
1192 struct domain_create {
1193 int debug;
1194 int daemonize;
1195 int paused;
1196 int dryrun;
1197 int quiet;
1198 int console_autoconnect;
1199 const char *config_file;
1200 const char *extra_config; /* extra config string */
1201 const char *restore_file;
1202 int migrate_fd; /* -1 means none */
1203 char **migration_domname_r;
1204 };
1206 static int create_domain(struct domain_create *dom_info)
1208 struct domain_config d_config;
1210 libxl_domain_build_state state;
1211 libxl_device_model_info dm_info;
1212 libxl_device_console console;
1214 int debug = dom_info->debug;
1215 int daemonize = dom_info->daemonize;
1216 int paused = dom_info->paused;
1217 const char *config_file = dom_info->config_file;
1218 const char *extra_config = dom_info->extra_config;
1219 const char *restore_file = dom_info->restore_file;
1220 int migrate_fd = dom_info->migrate_fd;
1221 char **migration_domname_r = dom_info->migration_domname_r;
1223 int i, fd;
1224 int need_daemon = 1;
1225 int ret, rc;
1226 libxl_device_model_starting *dm_starting = 0;
1227 libxl_waiter *w1 = NULL, *w2 = NULL;
1228 void *config_data = 0;
1229 int config_len = 0;
1230 int restore_fd = -1;
1231 struct save_file_header hdr;
1233 memset(&d_config, 0x00, sizeof(d_config));
1234 memset(&dm_info, 0x00, sizeof(dm_info));
1236 if (restore_file) {
1237 uint8_t *optdata_begin = 0;
1238 const uint8_t *optdata_here = 0;
1239 union { uint32_t u32; char b[4]; } u32buf;
1240 uint32_t badflags;
1242 restore_fd = migrate_fd >= 0 ? migrate_fd :
1243 open(restore_file, O_RDONLY);
1245 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
1246 sizeof(hdr), restore_file, "header") );
1247 if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
1248 fprintf(stderr, "File has wrong magic number -"
1249 " corrupt or for a different tool?\n");
1250 return ERROR_INVAL;
1252 if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
1253 fprintf(stderr, "File has wrong byte order\n");
1254 return ERROR_INVAL;
1256 fprintf(stderr, "Loading new save file %s"
1257 " (new xl fmt info"
1258 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
1259 restore_file, hdr.mandatory_flags, hdr.optional_flags,
1260 hdr.optional_data_len);
1262 badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
1263 if (badflags) {
1264 fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
1265 "which are not supported; need newer xl\n",
1266 badflags);
1267 return ERROR_INVAL;
1269 if (hdr.optional_data_len) {
1270 optdata_begin = xmalloc(hdr.optional_data_len);
1271 CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
1272 hdr.optional_data_len, restore_file, "optdata") );
1275 #define OPTDATA_LEFT (hdr.optional_data_len - (optdata_here - optdata_begin))
1276 #define WITH_OPTDATA(amt, body) \
1277 if (OPTDATA_LEFT < (amt)) { \
1278 fprintf(stderr, "Savefile truncated.\n"); \
1279 return ERROR_INVAL; \
1280 } else { \
1281 body; \
1282 optdata_here += (amt); \
1285 optdata_here = optdata_begin;
1287 if (OPTDATA_LEFT) {
1288 fprintf(stderr, " Savefile contains xl domain config\n");
1289 WITH_OPTDATA(4, {
1290 memcpy(u32buf.b, optdata_here, 4);
1291 config_len = u32buf.u32;
1292 });
1293 WITH_OPTDATA(config_len, {
1294 config_data = xmalloc(config_len);
1295 memcpy(config_data, optdata_here, config_len);
1296 });
1301 if (config_file) {
1302 free(config_data); config_data = 0;
1303 ret = libxl_read_file_contents(&ctx, config_file,
1304 &config_data, &config_len);
1305 if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
1306 config_file, strerror(errno)); return ERROR_FAIL; }
1307 if (!restore_file && extra_config
1308 && strlen(extra_config)) {
1309 if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
1310 fprintf(stderr, "Failed to attach extra configration\n");
1311 return ERROR_FAIL;
1313 config_data = realloc(config_data, config_len
1314 + strlen(extra_config) + 2);
1315 if (!config_data) {
1316 fprintf(stderr, "Failed to realloc config_data\n");
1317 return ERROR_FAIL;
1319 strcat(config_data, "\n");
1320 strcat(config_data, extra_config);
1321 strcat(config_data, "\n");
1322 config_len += (strlen(extra_config) + 2);
1324 } else {
1325 if (!config_data) {
1326 fprintf(stderr, "Config file not specified and"
1327 " none in save file\n");
1328 return ERROR_INVAL;
1330 config_file = "<saved>";
1333 if (!dom_info->quiet)
1334 printf("Parsing config file %s\n", config_file);
1336 parse_config_data(config_file, config_data, config_len, &d_config, &dm_info);
1338 ret = 0;
1339 if (dom_info->dryrun)
1340 goto out;
1342 if (migrate_fd >= 0) {
1343 if (d_config.c_info.name) {
1344 /* when we receive a domain we get its name from the config
1345 * file; and we receive it to a temporary name */
1346 assert(!common_domname);
1347 common_domname = d_config.c_info.name;
1348 if (asprintf(migration_domname_r, "%s--incoming", d_config.c_info.name) < 0) {
1349 fprintf(stderr, "Failed to allocate memory in asprintf\n");
1350 exit(1);
1352 d_config.c_info.name = *migration_domname_r;
1356 if (debug)
1357 printf_info(-1, &d_config, &dm_info);
1359 start:
1360 domid = 0;
1362 ret = libxl_domain_make(&ctx, &d_config.c_info, &domid);
1363 if (ret) {
1364 fprintf(stderr, "cannot make domain: %d\n", ret);
1365 ret = ERROR_FAIL;
1366 goto error_out;
1369 ret = libxl_userdata_store(&ctx, domid, "xl",
1370 config_data, config_len);
1371 if (ret) {
1372 perror("cannot save config file");
1373 ret = ERROR_FAIL;
1374 goto error_out;
1377 if (dom_info->console_autoconnect) {
1378 ret = autoconnect_console(d_config.c_info.hvm);
1379 if (ret)
1380 goto error_out;
1383 /*
1384 * Do not attempt to reconnect if we come round again due to a
1385 * guest reboot -- the stdin/out will be disconnected by then.
1386 */
1387 dom_info->console_autoconnect = 0;
1389 ret = libxl_run_bootloader(&ctx, &d_config.b_info, d_config.num_disks > 0 ? &d_config.disks[0] : NULL, domid);
1390 if (ret) {
1391 fprintf(stderr, "failed to run bootloader: %d\n", ret);
1392 goto error_out;
1395 if (!restore_file || !need_daemon) {
1396 if (dm_info.saved_state) {
1397 free(dm_info.saved_state);
1398 dm_info.saved_state = NULL;
1400 ret = libxl_domain_build(&ctx, &d_config.b_info, domid, &state);
1401 } else {
1402 ret = libxl_domain_restore(&ctx, &d_config.b_info, domid, restore_fd, &state, &dm_info);
1405 if (ret) {
1406 fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
1407 ret = ERROR_FAIL;
1408 goto error_out;
1411 for (i = 0; i < d_config.num_disks; i++) {
1412 d_config.disks[i].domid = domid;
1413 ret = libxl_device_disk_add(&ctx, domid, &d_config.disks[i]);
1414 if (ret) {
1415 fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
1416 ret = ERROR_FAIL;
1417 goto error_out;
1420 for (i = 0; i < d_config.num_vifs; i++) {
1421 d_config.vifs[i].domid = domid;
1422 ret = libxl_device_nic_add(&ctx, domid, &d_config.vifs[i]);
1423 if (ret) {
1424 fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
1425 ret = ERROR_FAIL;
1426 goto error_out;
1429 if (!d_config.c_info.hvm) {
1430 for (i = 0; i < d_config.num_vif2s; i++) {
1431 d_config.vif2s[i].domid = domid;
1432 ret = libxl_device_net2_add(&ctx, domid, &d_config.vif2s[i]);
1433 if (ret) {
1434 fprintf(stderr, "cannot add net2 %d to domain: %d\n", i, ret);
1435 ret = ERROR_FAIL;
1436 goto error_out;
1440 if (d_config.c_info.hvm) {
1441 init_console_info(&console, 0, &state);
1442 console.domid = domid;
1443 libxl_device_console_add(&ctx, domid, &console);
1444 dm_info.domid = domid;
1445 MUST( libxl_create_device_model(&ctx, &dm_info,
1446 d_config.disks, d_config.num_disks,
1447 d_config.vifs, d_config.num_vifs,
1448 &dm_starting) );
1449 } else {
1450 for (i = 0; i < d_config.num_vfbs; i++) {
1451 d_config.vfbs[i].domid = domid;
1452 libxl_device_vfb_add(&ctx, domid, &d_config.vfbs[i]);
1453 d_config.vkbs[i].domid = domid;
1454 libxl_device_vkb_add(&ctx, domid, &d_config.vkbs[i]);
1456 init_console_info(&console, 0, &state);
1457 console.domid = domid;
1458 if (d_config.num_vfbs)
1459 console.constype = CONSTYPE_IOEMU;
1460 libxl_device_console_add(&ctx, domid, &console);
1461 if (d_config.num_vfbs)
1462 libxl_create_xenpv_qemu(&ctx, d_config.vfbs, 1, &console, &dm_starting);
1465 if (dm_starting)
1466 MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
1467 for (i = 0; i < d_config.num_pcidevs; i++)
1468 libxl_device_pci_add(&ctx, domid, &d_config.pcidevs[i]);
1470 if (!paused)
1471 libxl_domain_unpause(&ctx, domid);
1473 ret = domid; /* caller gets success in parent */
1474 if (!daemonize)
1475 goto out;
1477 if (need_daemon) {
1478 char *fullname, *name;
1479 pid_t child1, got_child;
1480 int nullfd;
1482 child1 = libxl_fork(&ctx);
1483 if (child1) {
1484 int status;
1485 for (;;) {
1486 got_child = waitpid(child1, &status, 0);
1487 if (got_child == child1) break;
1488 assert(got_child == -1);
1489 if (errno != EINTR) {
1490 perror("failed to wait for daemonizing child");
1491 ret = ERROR_FAIL;
1492 goto error_out;
1495 if (status) {
1496 libxl_report_child_exitstatus(&ctx, XTL_ERROR,
1497 "daemonizing child", child1, status);
1498 ret = ERROR_FAIL;
1499 goto error_out;
1501 return domid; /* caller gets success in parent */
1504 rc = libxl_ctx_postfork(&ctx);
1505 if (rc) {
1506 LOG("failed to reinitialise context after fork");
1507 exit(-1);
1510 if (asprintf(&name, "xl-%s", d_config.c_info.name) < 0) {
1511 LOG("Failed to allocate memory in asprintf");
1512 exit(1);
1514 rc = libxl_create_logfile(&ctx, name, &fullname);
1515 if (rc) {
1516 LOG("failed to open logfile %s",fullname,strerror(errno));
1517 exit(-1);
1520 CHK_ERRNO(( logfile = open(fullname, O_WRONLY|O_CREAT, 0644) )<0);
1521 free(fullname);
1522 free(name);
1524 CHK_ERRNO(( nullfd = open("/dev/null", O_RDONLY) )<0);
1525 dup2(nullfd, 0);
1526 dup2(logfile, 1);
1527 dup2(logfile, 2);
1529 CHK_ERRNO(daemon(0, 1) < 0);
1530 need_daemon = 0;
1532 LOG("Waiting for domain %s (domid %d) to die [pid %ld]",
1533 d_config.c_info.name, domid, (long)getpid());
1534 w1 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter) * d_config.num_disks);
1535 w2 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter));
1536 libxl_wait_for_disk_ejects(&ctx, domid, d_config.disks, d_config.num_disks, w1);
1537 libxl_wait_for_domain_death(&ctx, domid, w2);
1538 libxl_get_wait_fd(&ctx, &fd);
1539 while (1) {
1540 int ret;
1541 fd_set rfds;
1542 libxl_dominfo info;
1543 libxl_event event;
1544 libxl_device_disk disk;
1546 FD_ZERO(&rfds);
1547 FD_SET(fd, &rfds);
1549 ret = select(fd + 1, &rfds, NULL, NULL, NULL);
1550 if (!ret)
1551 continue;
1552 libxl_get_event(&ctx, &event);
1553 switch (event.type) {
1554 case LIBXL_EVENT_DOMAIN_DEATH:
1555 ret = libxl_event_get_domain_death_info(&ctx, domid, &event, &info);
1557 if (ret < 0) continue;
1559 LOG("Domain %d is dead", domid);
1561 if (ret) {
1562 switch (handle_domain_death(&ctx, domid, &event, &d_config, &info)) {
1563 case 2:
1564 if (!preserve_domain(&ctx, domid, &event, &d_config, &info))
1565 /* If we fail then exit leaving the old domain in place. */
1566 exit(-1);
1568 /* Otherwise fall through and restart. */
1569 case 1:
1571 libxl_free_waiter(w1);
1572 libxl_free_waiter(w2);
1573 free(w1);
1574 free(w2);
1575 /*
1576 * XXX FIXME: If this sleep is not there then domain
1577 * re-creation fails sometimes.
1578 */
1579 LOG("Done. Rebooting now");
1580 sleep(2);
1581 goto start;
1582 case 0:
1583 LOG("Done. Exiting now");
1584 exit(0);
1587 break;
1588 case LIBXL_EVENT_DISK_EJECT:
1589 if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
1590 libxl_cdrom_insert(&ctx, domid, &disk);
1591 break;
1593 libxl_free_event(&event);
1596 close(logfile);
1597 exit(0);
1599 error_out:
1600 if (domid)
1601 libxl_domain_destroy(&ctx, domid, 0);
1602 out:
1604 free_domain_config(&d_config);
1606 free(config_data);
1608 return ret;
1611 void help(char *command)
1613 int i;
1614 struct cmd_spec *cmd;
1616 if (!command || !strcmp(command, "help")) {
1617 printf("Usage xl [-v] <subcommand> [args]\n\n");
1618 printf("xl full list of subcommands:\n\n");
1619 for (i = 0; i < cmdtable_len; i++)
1620 printf(" %-20s%s\n",
1621 cmd_table[i].cmd_name, cmd_table[i].cmd_desc);
1622 } else {
1623 cmd = cmdtable_lookup(command);
1624 if (cmd) {
1625 printf("Usage: xl [-v] %s %s\n\n%s.\n\n",
1626 cmd->cmd_name,
1627 cmd->cmd_usage,
1628 cmd->cmd_desc);
1629 if (cmd->cmd_option)
1630 printf("Options:\n\n%s\n", cmd->cmd_option);
1632 else {
1633 printf("command \"%s\" not implemented\n", command);
1638 static int64_t parse_mem_size_kb(char *mem)
1640 char *endptr;
1641 int64_t kbytes;
1643 kbytes = strtoll(mem, &endptr, 10);
1645 if (strlen(endptr) > 1)
1646 return -1;
1648 switch (tolower((uint8_t)*endptr)) {
1649 case 't':
1650 kbytes <<= 10;
1651 case 'g':
1652 kbytes <<= 10;
1653 case '\0':
1654 case 'm':
1655 kbytes <<= 10;
1656 case 'k':
1657 break;
1658 case 'b':
1659 kbytes >>= 10;
1660 break;
1661 default:
1662 return -1;
1665 return kbytes;
1668 int set_memory_max(char *p, char *mem)
1670 int64_t memorykb;
1671 int rc;
1673 find_domain(p);
1675 memorykb = parse_mem_size_kb(mem);
1676 if (memorykb == -1) {
1677 fprintf(stderr, "invalid memory size: %s\n", mem);
1678 exit(3);
1681 rc = libxl_domain_setmaxmem(&ctx, domid, memorykb);
1683 return rc;
1686 int main_memmax(int argc, char **argv)
1688 int opt = 0;
1689 char *p = NULL, *mem;
1690 int rc;
1692 while ((opt = getopt(argc, argv, "h")) != -1) {
1693 switch (opt) {
1694 case 'h':
1695 help("mem-max");
1696 exit(0);
1697 default:
1698 fprintf(stderr, "option not supported\n");
1699 break;
1702 if (optind >= argc - 1) {
1703 help("mem-max");
1704 return 2;
1707 p = argv[optind];
1708 mem = argv[optind + 1];
1710 rc = set_memory_max(p, mem);
1711 if (rc) {
1712 fprintf(stderr, "cannot set domid %d static max memory to : %s\n", domid, mem);
1713 return 1;
1716 return 0;
1719 void set_memory_target(char *p, char *mem)
1721 long long int memorykb;
1723 find_domain(p);
1725 memorykb = parse_mem_size_kb(mem);
1726 if (memorykb == -1) {
1727 fprintf(stderr, "invalid memory size: %s\n", mem);
1728 exit(3);
1731 libxl_set_memory_target(&ctx, domid, memorykb, /* enforce */ 1);
1734 int main_memset(int argc, char **argv)
1736 int opt = 0;
1737 char *p = NULL, *mem;
1739 while ((opt = getopt(argc, argv, "h:")) != -1) {
1740 switch (opt) {
1741 case 'h':
1742 help("mem-set");
1743 return 0;
1744 default:
1745 fprintf(stderr, "option not supported\n");
1746 break;
1749 if (optind >= argc - 1) {
1750 help("mem-set");
1751 return 2;
1754 p = argv[optind];
1755 mem = argv[optind + 1];
1757 set_memory_target(p, mem);
1758 return 0;
1761 void cd_insert(char *dom, char *virtdev, char *phys)
1763 libxl_device_disk disk;
1764 char *p;
1766 find_domain(dom);
1768 disk.backend_domid = 0;
1769 disk.domid = domid;
1770 if (phys) {
1771 p = strchr(phys, ':');
1772 if (!p) {
1773 fprintf(stderr, "No type specified, ");
1774 disk.physpath = phys;
1775 if (!strncmp(phys, "/dev", 4)) {
1776 fprintf(stderr, "assuming phy:\n");
1777 disk.phystype = PHYSTYPE_PHY;
1778 } else {
1779 fprintf(stderr, "assuming file:\n");
1780 disk.phystype = PHYSTYPE_FILE;
1782 } else {
1783 *p = '\0';
1784 p++;
1785 disk.physpath = p;
1786 libxl_string_to_phystype(&ctx, phys, &disk.phystype);
1788 } else {
1789 disk.physpath = NULL;
1790 disk.phystype = 0;
1792 disk.virtpath = virtdev;
1793 disk.unpluggable = 1;
1794 disk.readwrite = 0;
1795 disk.is_cdrom = 1;
1797 libxl_cdrom_insert(&ctx, domid, &disk);
1800 int main_cd_eject(int argc, char **argv)
1802 int opt = 0;
1803 char *p = NULL, *virtdev;
1805 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1806 switch (opt) {
1807 case 'h':
1808 help("cd-eject");
1809 return 0;
1810 default:
1811 fprintf(stderr, "option not supported\n");
1812 break;
1815 if (optind >= argc - 1) {
1816 help("cd-eject");
1817 return 2;
1820 p = argv[optind];
1821 virtdev = argv[optind + 1];
1823 cd_insert(p, virtdev, NULL);
1824 return 0;
1827 int main_cd_insert(int argc, char **argv)
1829 int opt = 0;
1830 char *p = NULL, *file = NULL, *virtdev;
1832 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1833 switch (opt) {
1834 case 'h':
1835 help("cd-insert");
1836 return 0;
1837 default:
1838 fprintf(stderr, "option not supported\n");
1839 break;
1842 if (optind >= argc - 2) {
1843 help("cd-insert");
1844 return 2;
1847 p = argv[optind];
1848 virtdev = argv[optind + 1];
1849 file = argv[optind + 2];
1851 cd_insert(p, virtdev, file);
1852 return 0;
1855 int main_console(int argc, char **argv)
1857 int opt = 0;
1859 while ((opt = getopt(argc, argv, "hn:")) != -1) {
1860 switch (opt) {
1861 case 'h':
1862 help("console");
1863 return 0;
1864 default:
1865 fprintf(stderr, "option not supported\n");
1866 break;
1869 if (optind >= argc) {
1870 help("console");
1871 return 2;
1874 find_domain(argv[optind]);
1875 libxl_primary_console_exec(&ctx, domid);
1876 fprintf(stderr, "Unable to attach console\n");
1877 return 1;
1880 static int vncviewer(const char *domain_spec, int autopass)
1882 find_domain(domain_spec);
1883 libxl_vncviewer_exec(&ctx, domid, autopass);
1884 fprintf(stderr, "Unable to execute vncviewer\n");
1885 return 1;
1888 int main_vncviewer(int argc, char **argv)
1890 static const struct option long_options[] = {
1891 {"autopass", 0, 0, 'a'},
1892 {"vncviewer-autopass", 0, 0, 'a'},
1893 {"help", 0, 0, 'h'},
1894 {0, 0, 0, 0}
1895 };
1896 int opt, autopass = 0;
1898 while (1) {
1899 opt = getopt_long(argc, argv, "ah", long_options, NULL);
1900 if (opt == -1)
1901 break;
1903 switch (opt) {
1904 case 'a':
1905 autopass = 1;
1906 break;
1907 case 'h':
1908 help("vncviewer");
1909 return 0;
1910 default:
1911 fprintf(stderr, "option not supported\n");
1912 break;
1916 if (argc - optind != 1) {
1917 help("vncviewer");
1918 return 2;
1921 if (vncviewer(argv[optind], autopass))
1922 return 1;
1923 return 0;
1926 void pcilist_assignable(void)
1928 libxl_device_pci *pcidevs;
1929 int num, i;
1931 if ( libxl_device_pci_list_assignable(&ctx, &pcidevs, &num) )
1932 return;
1933 for (i = 0; i < num; i++) {
1934 printf("%04x:%02x:%02x:%01x\n",
1935 pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
1937 free(pcidevs);
1940 int main_pcilist_assignable(int argc, char **argv)
1942 int opt;
1944 while ((opt = getopt(argc, argv, "h")) != -1) {
1945 switch (opt) {
1946 case 'h':
1947 help("pci-list-assignable-devices");
1948 return 0;
1949 default:
1950 fprintf(stderr, "option not supported\n");
1951 break;
1955 pcilist_assignable();
1956 return 0;
1959 void pcilist(char *dom)
1961 libxl_device_pci *pcidevs;
1962 int num, i;
1964 find_domain(dom);
1966 if (libxl_device_pci_list_assigned(&ctx, &pcidevs, domid, &num))
1967 return;
1968 printf("VFn domain bus slot func\n");
1969 for (i = 0; i < num; i++) {
1970 printf("0x%02x 0x%04x 0x%02x 0x%02x 0x%01x\n", pcidevs[i].vdevfn, pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
1972 free(pcidevs);
1975 int main_pcilist(int argc, char **argv)
1977 int opt;
1978 char *domname = NULL;
1980 while ((opt = getopt(argc, argv, "h")) != -1) {
1981 switch (opt) {
1982 case 'h':
1983 help("pci-list");
1984 return 0;
1985 default:
1986 fprintf(stderr, "option not supported\n");
1987 break;
1990 if (optind >= argc) {
1991 help("pci-list");
1992 return 2;
1995 domname = argv[optind];
1997 pcilist(domname);
1998 return 0;
2001 void pcidetach(char *dom, char *bdf)
2003 libxl_device_pci pcidev;
2005 find_domain(dom);
2007 memset(&pcidev, 0x00, sizeof(pcidev));
2008 if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
2009 fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
2010 exit(2);
2012 libxl_device_pci_remove(&ctx, domid, &pcidev);
2015 int main_pcidetach(int argc, char **argv)
2017 int opt;
2018 char *domname = NULL, *bdf = NULL;
2020 while ((opt = getopt(argc, argv, "h")) != -1) {
2021 switch (opt) {
2022 case 'h':
2023 help("pci-detach");
2024 return 0;
2025 default:
2026 fprintf(stderr, "option not supported\n");
2027 break;
2030 if (optind >= argc - 1) {
2031 help("pci-detach");
2032 return 2;
2035 domname = argv[optind];
2036 bdf = argv[optind + 1];
2038 pcidetach(domname, bdf);
2039 return 0;
2041 void pciattach(char *dom, char *bdf, char *vs)
2043 libxl_device_pci pcidev;
2045 find_domain(dom);
2047 memset(&pcidev, 0x00, sizeof(pcidev));
2048 if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
2049 fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
2050 exit(2);
2052 libxl_device_pci_add(&ctx, domid, &pcidev);
2055 int main_pciattach(int argc, char **argv)
2057 int opt;
2058 char *domname = NULL, *bdf = NULL, *vs = NULL;
2060 while ((opt = getopt(argc, argv, "h")) != -1) {
2061 switch (opt) {
2062 case 'h':
2063 help("pci-attach");
2064 return 0;
2065 default:
2066 fprintf(stderr, "option not supported\n");
2067 break;
2070 if (optind >= argc - 1) {
2071 help("pci-attach");
2072 return 2;
2075 domname = argv[optind];
2076 bdf = argv[optind + 1];
2078 if (optind + 1 < argc)
2079 vs = argv[optind + 2];
2081 pciattach(domname, bdf, vs);
2082 return 0;
2085 void pause_domain(char *p)
2087 find_domain(p);
2088 libxl_domain_pause(&ctx, domid);
2091 void unpause_domain(char *p)
2093 find_domain(p);
2094 libxl_domain_unpause(&ctx, domid);
2097 void destroy_domain(char *p)
2099 int rc;
2100 find_domain(p);
2101 if (domid == 0) {
2102 fprintf(stderr, "Cannot destroy privileged domain 0.\n\n");
2103 exit(-1);
2105 rc = libxl_domain_destroy(&ctx, domid, 0);
2106 if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n.",rc); exit(-1); }
2109 void shutdown_domain(char *p)
2111 int rc;
2112 find_domain(p);
2113 rc=libxl_domain_shutdown(&ctx, domid, 0);
2114 if (rc) { fprintf(stderr,"shutdown failed (rc=%d)\n.",rc);exit(-1); }
2117 void reboot_domain(char *p)
2119 int rc;
2120 find_domain(p);
2121 rc=libxl_domain_shutdown(&ctx, domid, 1);
2122 if (rc) { fprintf(stderr,"reboot failed (rc=%d)\n.",rc);exit(-1); }
2125 void list_domains_details(const libxl_dominfo *info, int nb_domain)
2127 struct domain_config d_config;
2129 char *config_file;
2130 uint8_t *data;
2131 int i, len, rc;
2132 libxl_device_model_info dm_info;
2134 for (i = 0; i < nb_domain; i++) {
2135 /* no detailed info available on dom0 */
2136 if (info[i].domid == 0)
2137 continue;
2138 rc = libxl_userdata_retrieve(&ctx, info[i].domid, "xl", &data, &len);
2139 if (rc)
2140 continue;
2141 CHK_ERRNO(asprintf(&config_file, "<domid %d data>", info[i].domid));
2142 memset(&d_config, 0x00, sizeof(d_config));
2143 parse_config_data(config_file, (char *)data, len, &d_config, &dm_info);
2144 printf_info(info[i].domid, &d_config, &dm_info);
2145 free_domain_config(&d_config);
2146 free(data);
2147 free(config_file);
2151 void list_domains(int verbose, const libxl_dominfo *info, int nb_domain)
2153 int i;
2155 printf("Name ID Mem VCPUs\tState\tTime(s)\n");
2156 for (i = 0; i < nb_domain; i++) {
2157 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f",
2158 libxl_domid_to_name(&ctx, info[i].domid),
2159 info[i].domid,
2160 (unsigned long) (info[i].max_memkb / 1024),
2161 info[i].vcpu_online,
2162 info[i].running ? 'r' : '-',
2163 info[i].blocked ? 'b' : '-',
2164 info[i].paused ? 'p' : '-',
2165 info[i].shutdown ? 's' : '-',
2166 info[i].shutdown_reason == SHUTDOWN_crash ? 'c' : '-',
2167 info[i].dying ? 'd' : '-',
2168 ((float)info[i].cpu_time / 1e9));
2169 if (verbose) {
2170 char *uuid = libxl_uuid2string(&ctx, info[i].uuid);
2171 printf(" %s", uuid);
2173 putchar('\n');
2177 void list_vm(void)
2179 libxl_vminfo *info;
2180 int nb_vm, i;
2182 info = libxl_list_vm(&ctx, &nb_vm);
2184 if (info < 0) {
2185 fprintf(stderr, "libxl_domain_infolist failed.\n");
2186 exit(1);
2188 printf("UUID ID name\n");
2189 for (i = 0; i < nb_vm; i++) {
2190 printf(UUID_FMT " %d %-30s\n",
2191 info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
2192 info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
2193 info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], info[i].uuid[11],
2194 info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], info[i].uuid[15],
2195 info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
2197 free(info);
2200 static void save_domain_core_begin(char *domain_spec,
2201 const char *override_config_file,
2202 uint8_t **config_data_r,
2203 int *config_len_r)
2205 int rc;
2207 find_domain(domain_spec);
2209 /* configuration file in optional data: */
2211 if (override_config_file) {
2212 void *config_v = 0;
2213 rc = libxl_read_file_contents(&ctx, override_config_file,
2214 &config_v, config_len_r);
2215 *config_data_r = config_v;
2216 } else {
2217 rc = libxl_userdata_retrieve(&ctx, domid, "xl",
2218 config_data_r, config_len_r);
2220 if (rc) {
2221 fputs("Unable to get config file\n",stderr);
2222 exit(2);
2226 void save_domain_core_writeconfig(int fd, const char *filename,
2227 const uint8_t *config_data, int config_len)
2229 struct save_file_header hdr;
2230 uint8_t *optdata_begin;
2231 union { uint32_t u32; char b[4]; } u32buf;
2233 memset(&hdr, 0, sizeof(hdr));
2234 memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
2235 hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
2237 optdata_begin= 0;
2239 #define ADD_OPTDATA(ptr, len) ({ \
2240 if ((len)) { \
2241 hdr.optional_data_len += (len); \
2242 optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
2243 memcpy(optdata_begin + hdr.optional_data_len - (len), \
2244 (ptr), (len)); \
2245 } \
2246 })
2248 u32buf.u32 = config_len;
2249 ADD_OPTDATA(u32buf.b, 4);
2250 ADD_OPTDATA(config_data, config_len);
2252 /* that's the optional data */
2254 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2255 &hdr, sizeof(hdr), filename, "header") );
2256 CHK_ERRNO( libxl_write_exactly(&ctx, fd,
2257 optdata_begin, hdr.optional_data_len, filename, "header") );
2259 fprintf(stderr, "Saving to %s new xl format (info"
2260 " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
2261 filename, hdr.mandatory_flags, hdr.optional_flags,
2262 hdr.optional_data_len);
2265 int save_domain(char *p, char *filename, int checkpoint,
2266 const char *override_config_file)
2268 int fd;
2269 uint8_t *config_data;
2270 int config_len;
2272 save_domain_core_begin(p, override_config_file, &config_data, &config_len);
2274 if (!config_len) {
2275 fputs(" Savefile will not contain xl domain config\n", stderr);
2278 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
2279 if (fd < 0) {
2280 fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
2281 exit(2);
2284 save_domain_core_writeconfig(fd, filename, config_data, config_len);
2286 CHK_ERRNO(libxl_domain_suspend(&ctx, NULL, domid, fd));
2287 close(fd);
2289 if (checkpoint)
2290 libxl_domain_unpause(&ctx, domid);
2291 else
2292 libxl_domain_destroy(&ctx, domid, 0);
2294 exit(0);
2297 static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
2298 const char *what, const char *rune) {
2299 char buf[msgsz];
2300 const char *stream;
2301 int rc;
2303 stream = rune ? "migration receiver stream" : "migration stream";
2304 rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
2305 if (rc) return ERROR_FAIL;
2307 if (memcmp(buf, msg, msgsz)) {
2308 fprintf(stderr, "%s contained unexpected data instead of %s\n",
2309 stream, what);
2310 if (rune)
2311 fprintf(stderr, "(command run was: %s )\n", rune);
2312 return ERROR_FAIL;
2314 return 0;
2317 static void migration_child_report(pid_t migration_child, int recv_fd) {
2318 pid_t child;
2319 int status, sr;
2320 struct timeval now, waituntil, timeout;
2321 static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
2323 if (!migration_child) return;
2325 CHK_ERRNO( gettimeofday(&waituntil, 0) );
2326 waituntil.tv_sec += 2;
2328 for (;;) {
2329 child = waitpid(migration_child, &status, WNOHANG);
2331 if (child == migration_child) {
2332 if (status)
2333 libxl_report_child_exitstatus(&ctx, XTL_INFO,
2334 "migration target process",
2335 migration_child, status);
2336 break;
2338 if (child == -1) {
2339 if (errno == EINTR) continue;
2340 fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
2341 (long)migration_child, strerror(errno));
2342 break;
2344 assert(child == 0);
2346 CHK_ERRNO( gettimeofday(&now, 0) );
2347 if (timercmp(&now, &waituntil, >)) {
2348 fprintf(stderr, "migration child [%ld] not exiting, no longer"
2349 " waiting (exit status will be unreported)\n",
2350 (long)migration_child);
2351 break;
2353 timersub(&waituntil, &now, &timeout);
2355 if (recv_fd >= 0) {
2356 fd_set readfds, exceptfds;
2357 FD_ZERO(&readfds);
2358 FD_ZERO(&exceptfds);
2359 FD_SET(recv_fd, &readfds);
2360 FD_SET(recv_fd, &exceptfds);
2361 sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
2362 } else {
2363 if (timercmp(&timeout, &pollinterval, >))
2364 timeout = pollinterval;
2365 sr = select(0,0,0,0, &timeout);
2367 if (sr > 0) {
2368 recv_fd = -1;
2369 } else if (sr == 0) {
2370 } else if (sr == -1) {
2371 if (errno != EINTR) {
2372 fprintf(stderr, "migration child [%ld] exit wait select"
2373 " failed unexpectedly: %s\n",
2374 (long)migration_child, strerror(errno));
2375 break;
2379 migration_child = 0;
2382 static void migrate_domain(char *domain_spec, const char *rune,
2383 const char *override_config_file)
2385 pid_t child = -1;
2386 int rc;
2387 int sendpipe[2], recvpipe[2];
2388 int send_fd, recv_fd;
2389 libxl_domain_suspend_info suspinfo;
2390 char *away_domname;
2391 char rc_buf;
2392 uint8_t *config_data;
2393 int config_len;
2395 save_domain_core_begin(domain_spec, override_config_file,
2396 &config_data, &config_len);
2398 if (!config_len) {
2399 fprintf(stderr, "No config file stored for running domain and "
2400 "none supplied - cannot migrate.\n");
2401 exit(1);
2404 MUST( libxl_pipe(&ctx, sendpipe) );
2405 MUST( libxl_pipe(&ctx, recvpipe) );
2407 child = libxl_fork(&ctx);
2408 if (child==-1) exit(1);
2410 if (!child) {
2411 dup2(sendpipe[0], 0);
2412 dup2(recvpipe[1], 1);
2413 close(sendpipe[0]); close(sendpipe[1]);
2414 close(recvpipe[0]); close(recvpipe[1]);
2415 execlp("sh","sh","-c",rune,(char*)0);
2416 perror("failed to exec sh");
2417 exit(-1);
2420 close(sendpipe[0]);
2421 close(recvpipe[1]);
2422 send_fd = sendpipe[1];
2423 recv_fd = recvpipe[0];
2425 signal(SIGPIPE, SIG_IGN);
2426 /* if receiver dies, we get an error and can clean up
2427 rather than just dying */
2429 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
2430 sizeof(migrate_receiver_banner)-1,
2431 "banner", rune);
2432 if (rc) {
2433 close(send_fd);
2434 migration_child_report(child, recv_fd);
2435 exit(-rc);
2438 save_domain_core_writeconfig(send_fd, "migration stream",
2439 config_data, config_len);
2441 xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
2443 memset(&suspinfo, 0, sizeof(suspinfo));
2444 suspinfo.flags |= XL_SUSPEND_LIVE;
2445 rc = libxl_domain_suspend(&ctx, &suspinfo, domid, send_fd);
2446 if (rc) {
2447 fprintf(stderr, "migration sender: libxl_domain_suspend failed"
2448 " (rc=%d)\n", rc);
2449 goto failed_resume;
2452 //fprintf(stderr, "migration sender: Transfer complete.\n");
2453 // Should only be printed when debugging as it's a bit messy with
2454 // progress indication.
2456 rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
2457 sizeof(migrate_receiver_ready),
2458 "ready message", rune);
2459 if (rc) goto failed_resume;
2461 xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
2463 /* right, at this point we are about give the destination
2464 * permission to rename and resume, so we must first rename the
2465 * domain away ourselves */
2467 fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
2469 if (common_domname) {
2470 if (asprintf(&away_domname, "%s--migratedaway", common_domname) < 0)
2471 goto failed_resume;
2472 rc = libxl_domain_rename(&ctx, domid,
2473 common_domname, away_domname, 0);
2474 if (rc) goto failed_resume;
2477 /* point of no return - as soon as we have tried to say
2478 * "go" to the receiver, it's not safe to carry on. We leave
2479 * the domain renamed to %s--migratedaway in case that's helpful.
2480 */
2482 fprintf(stderr, "migration sender: Giving target permission to start.\n");
2484 rc = libxl_write_exactly(&ctx, send_fd,
2485 migrate_permission_to_go,
2486 sizeof(migrate_permission_to_go),
2487 "migration stream", "GO message");
2488 if (rc) goto failed_badly;
2490 rc = migrate_read_fixedmessage(recv_fd, migrate_report,
2491 sizeof(migrate_report),
2492 "success/failure report message", rune);
2493 if (rc) goto failed_badly;
2495 rc = libxl_read_exactly(&ctx, recv_fd,
2496 &rc_buf, 1,
2497 "migration ack stream", "success/failure status");
2498 if (rc) goto failed_badly;
2500 if (rc_buf) {
2501 fprintf(stderr, "migration sender: Target reports startup failure"
2502 " (status code %d).\n", rc_buf);
2504 rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
2505 sizeof(migrate_permission_to_go),
2506 "permission for sender to resume",
2507 rune);
2508 if (rc) goto failed_badly;
2510 fprintf(stderr, "migration sender: Trying to resume at our end.\n");
2512 if (common_domname) {
2513 libxl_domain_rename(&ctx, domid,
2514 away_domname, common_domname, 0);
2516 rc = libxl_domain_resume(&ctx, domid);
2517 if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
2519 fprintf(stderr, "Migration failed due to problems at target.\n");
2520 exit(-ERROR_FAIL);
2523 fprintf(stderr, "migration sender: Target reports successful startup.\n");
2524 libxl_domain_destroy(&ctx, domid, 1); /* bang! */
2525 fprintf(stderr, "Migration successful.\n");
2526 exit(0);
2528 failed_resume:
2529 close(send_fd);
2530 migration_child_report(child, recv_fd);
2531 fprintf(stderr, "Migration failed, resuming at sender.\n");
2532 libxl_domain_resume(&ctx, domid);
2533 exit(-ERROR_FAIL);
2535 failed_badly:
2536 fprintf(stderr,
2537 "** Migration failed during final handshake **\n"
2538 "Domain state is now undefined !\n"
2539 "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
2540 " resuming at most one instance. Two simultaneous instances of the domain\n"
2541 " would probably result in SEVERE DATA LOSS and it is now your\n"
2542 " responsibility to avoid that. Sorry.\n");
2544 close(send_fd);
2545 migration_child_report(child, recv_fd);
2546 exit(-ERROR_BADFAIL);
2549 static void core_dump_domain(const char *domain_spec, const char *filename)
2551 int rc;
2552 find_domain(domain_spec);
2553 rc=libxl_domain_core_dump(&ctx, domid, filename);
2554 if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n.",rc);exit(-1); }
2557 static void migrate_receive(int debug, int daemonize)
2559 int rc, rc2;
2560 char rc_buf;
2561 char *migration_domname;
2562 struct domain_create dom_info;
2564 signal(SIGPIPE, SIG_IGN);
2565 /* if we get SIGPIPE we'd rather just have it as an error */
2567 fprintf(stderr, "migration target: Ready to receive domain.\n");
2569 CHK_ERRNO( libxl_write_exactly(&ctx, 1,
2570 migrate_receiver_banner,
2571 sizeof(migrate_receiver_banner)-1,
2572 "migration ack stream",
2573 "banner") );
2575 memset(&dom_info, 0, sizeof(dom_info));
2576 dom_info.debug = debug;
2577 dom_info.daemonize = daemonize;
2578 dom_info.paused = 1;
2579 dom_info.restore_file = "incoming migration stream";
2580 dom_info.migration_domname_r = &migration_domname;
2582 rc = create_domain(&dom_info);
2583 if (rc < 0) {
2584 fprintf(stderr, "migration target: Domain creation failed"
2585 " (code %d).\n", rc);
2586 exit(-rc);
2589 fprintf(stderr, "migration target: Transfer complete,"
2590 " requesting permission to start domain.\n");
2592 rc = libxl_write_exactly(&ctx, 1,
2593 migrate_receiver_ready,
2594 sizeof(migrate_receiver_ready),
2595 "migration ack stream", "ready message");
2596 if (rc) exit(-rc);
2598 rc = migrate_read_fixedmessage(0, migrate_permission_to_go,
2599 sizeof(migrate_permission_to_go),
2600 "GO message", 0);
2601 if (rc) goto perhaps_destroy_notify_rc;
2603 fprintf(stderr, "migration target: Got permission, starting domain.\n");
2605 if (migration_domname) {
2606 rc = libxl_domain_rename(&ctx, domid,
2607 migration_domname, common_domname, 0);
2608 if (rc) goto perhaps_destroy_notify_rc;
2611 rc = libxl_domain_unpause(&ctx, domid);
2612 if (rc) goto perhaps_destroy_notify_rc;
2614 fprintf(stderr, "migration target: Domain started successsfully.\n");
2615 rc = 0;
2617 perhaps_destroy_notify_rc:
2618 rc2 = libxl_write_exactly(&ctx, 1,
2619 migrate_report, sizeof(migrate_report),
2620 "migration ack stream",
2621 "success/failure report");
2622 if (rc2) exit(-ERROR_BADFAIL);
2624 rc_buf = -rc;
2625 assert(!!rc_buf == !!rc);
2626 rc2 = libxl_write_exactly(&ctx, 1, &rc_buf, 1,
2627 "migration ack stream",
2628 "success/failure code");
2629 if (rc2) exit(-ERROR_BADFAIL);
2631 if (rc) {
2632 fprintf(stderr, "migration target: Failure, destroying our copy.\n");
2634 rc2 = libxl_domain_destroy(&ctx, domid, 1);
2635 if (rc2) {
2636 fprintf(stderr, "migration target: Failed to destroy our copy"
2637 " (code %d).\n", rc2);
2638 exit(-ERROR_BADFAIL);
2641 fprintf(stderr, "migration target: Cleanup OK, granting sender"
2642 " permission to resume.\n");
2644 rc2 = libxl_write_exactly(&ctx, 1,
2645 migrate_permission_to_go,
2646 sizeof(migrate_permission_to_go),
2647 "migration ack stream",
2648 "permission to sender to have domain back");
2649 if (rc2) exit(-ERROR_BADFAIL);
2652 exit(0);
2655 int main_restore(int argc, char **argv)
2657 char *checkpoint_file = NULL;
2658 char *config_file = NULL;
2659 struct domain_create dom_info;
2660 int paused = 0, debug = 0, daemonize = 1;
2661 int opt, rc;
2663 while ((opt = getopt(argc, argv, "hpde")) != -1) {
2664 switch (opt) {
2665 case 'p':
2666 paused = 1;
2667 break;
2668 case 'd':
2669 debug = 1;
2670 break;
2671 case 'e':
2672 daemonize = 0;
2673 break;
2674 case 'h':
2675 help("restore");
2676 return 0;
2677 default:
2678 fprintf(stderr, "option not supported\n");
2679 break;
2683 if (argc-optind == 1) {
2684 checkpoint_file = argv[optind];
2685 } else if (argc-optind == 2) {
2686 config_file = argv[optind];
2687 checkpoint_file = argv[optind + 1];
2688 } else {
2689 help("restore");
2690 return 2;
2693 memset(&dom_info, 0, sizeof(dom_info));
2694 dom_info.debug = debug;
2695 dom_info.daemonize = daemonize;
2696 dom_info.paused = paused;
2697 dom_info.config_file = config_file;
2698 dom_info.restore_file = checkpoint_file;
2699 dom_info.migrate_fd = -1;
2701 rc = create_domain(&dom_info);
2702 if (rc < 0)
2703 return -rc;
2705 return 0;
2708 int main_migrate_receive(int argc, char **argv)
2710 int debug = 0, daemonize = 1;
2711 int opt;
2713 while ((opt = getopt(argc, argv, "hed")) != -1) {
2714 switch (opt) {
2715 case 'h':
2716 help("migrate-receive");
2717 return 2;
2718 break;
2719 case 'e':
2720 daemonize = 0;
2721 break;
2722 case 'd':
2723 debug = 1;
2724 break;
2725 default:
2726 fprintf(stderr, "option not supported\n");
2727 break;
2731 if (argc-optind != 0) {
2732 help("migrate-receive");
2733 return 2;
2735 migrate_receive(debug, daemonize);
2736 return 0;
2739 int main_save(int argc, char **argv)
2741 char *filename = NULL, *p = NULL;
2742 const char *config_filename;
2743 int checkpoint = 0;
2744 int opt;
2746 while ((opt = getopt(argc, argv, "hc")) != -1) {
2747 switch (opt) {
2748 case 'c':
2749 checkpoint = 1;
2750 break;
2751 case 'h':
2752 help("save");
2753 return 0;
2754 default:
2755 fprintf(stderr, "option not supported\n");
2756 break;
2760 if (argc-optind < 1 || argc-optind > 3) {
2761 help("save");
2762 return 2;
2765 p = argv[optind];
2766 filename = argv[optind + 1];
2767 config_filename = argv[optind + 2];
2768 save_domain(p, filename, checkpoint, config_filename);
2769 return 0;
2772 int main_migrate(int argc, char **argv)
2774 char *p = NULL;
2775 const char *config_filename = NULL;
2776 const char *ssh_command = "ssh";
2777 char *rune = NULL;
2778 char *host;
2779 int opt, daemonize = 1, debug = 0;
2781 while ((opt = getopt(argc, argv, "hC:s:ed")) != -1) {
2782 switch (opt) {
2783 case 'h':
2784 help("migrate");
2785 return 0;
2786 case 'C':
2787 config_filename = optarg;
2788 break;
2789 case 's':
2790 ssh_command = optarg;
2791 break;
2792 case 'e':
2793 daemonize = 0;
2794 break;
2795 case 'd':
2796 debug = 1;
2797 break;
2798 default:
2799 fprintf(stderr, "option not supported\n");
2800 break;
2804 if (argc-optind < 2 || argc-optind > 2) {
2805 help("migrate");
2806 return 2;
2809 p = argv[optind];
2810 host = argv[optind + 1];
2812 if (!ssh_command[0]) {
2813 rune= host;
2814 } else {
2815 if (asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
2816 ssh_command, host,
2817 daemonize ? "" : " -e",
2818 debug ? " -d" : "") < 0)
2819 return 1;
2822 migrate_domain(p, rune, config_filename);
2823 return 0;
2826 int main_dump_core(int argc, char **argv)
2828 if ( argc-optind < 2 ) {
2829 help("dump-core");
2830 return 2;
2832 core_dump_domain(argv[optind], argv[optind + 1]);
2833 return 0;
2836 int main_pause(int argc, char **argv)
2838 int opt;
2839 char *p;
2842 while ((opt = getopt(argc, argv, "h")) != -1) {
2843 switch (opt) {
2844 case 'h':
2845 help("pause");
2846 return 0;
2847 default:
2848 fprintf(stderr, "option not supported\n");
2849 break;
2852 if (optind >= argc) {
2853 help("pause");
2854 return 2;
2857 p = argv[optind];
2859 pause_domain(p);
2860 return 0;
2863 int main_unpause(int argc, char **argv)
2865 int opt;
2866 char *p;
2869 while ((opt = getopt(argc, argv, "h")) != -1) {
2870 switch (opt) {
2871 case 'h':
2872 help("unpause");
2873 return 0;
2874 default:
2875 fprintf(stderr, "option not supported\n");
2876 break;
2879 if (optind >= argc) {
2880 help("unpause");
2881 return 2;
2884 p = argv[optind];
2886 unpause_domain(p);
2887 return 0;
2890 int main_destroy(int argc, char **argv)
2892 int opt;
2893 char *p;
2895 while ((opt = getopt(argc, argv, "h")) != -1) {
2896 switch (opt) {
2897 case 'h':
2898 help("destroy");
2899 return 0;
2900 default:
2901 fprintf(stderr, "option not supported\n");
2902 break;
2905 if (optind >= argc) {
2906 help("destroy");
2907 return 2;
2910 p = argv[optind];
2912 destroy_domain(p);
2913 return 0;
2916 int main_shutdown(int argc, char **argv)
2918 int opt;
2919 char *p;
2921 while ((opt = getopt(argc, argv, "h")) != -1) {
2922 switch (opt) {
2923 case 'h':
2924 help("shutdown");
2925 return 0;
2926 default:
2927 fprintf(stderr, "option not supported\n");
2928 break;
2931 if (optind >= argc) {
2932 help("shutdown");
2933 return 2;
2936 p = argv[optind];
2938 shutdown_domain(p);
2939 return 0;
2942 int main_reboot(int argc, char **argv)
2944 int opt;
2945 char *p;
2947 while ((opt = getopt(argc, argv, "h")) != -1) {
2948 switch (opt) {
2949 case 'h':
2950 help("reboot");
2951 return 0;
2952 default:
2953 fprintf(stderr, "option not supported\n");
2954 break;
2957 if (optind >= argc) {
2958 help("reboot");
2959 return 2;
2962 p = argv[optind];
2964 reboot_domain(p);
2965 return 0;
2967 int main_list(int argc, char **argv)
2969 int opt, verbose = 0;
2970 int details = 0;
2971 int option_index = 0;
2972 static struct option long_options[] = {
2973 {"long", 0, 0, 'l'},
2974 {"help", 0, 0, 'h'},
2975 {"verbose", 0, 0, 'v'},
2976 {0, 0, 0, 0}
2977 };
2979 libxl_dominfo info_buf;
2980 libxl_dominfo *info, *info_free=0;
2981 int nb_domain, rc;
2983 while (1) {
2984 opt = getopt_long(argc, argv, "lvh", long_options, &option_index);
2985 if (opt == -1)
2986 break;
2988 switch (opt) {
2989 case 'l':
2990 details = 1;
2991 break;
2992 case 'h':
2993 help("list");
2994 return 0;
2995 case 'v':
2996 verbose = 1;
2997 break;
2998 default:
2999 fprintf(stderr, "option not supported\n");
3000 break;
3004 if (optind >= argc) {
3005 info = libxl_list_domain(&ctx, &nb_domain);
3006 if (!info) {
3007 fprintf(stderr, "libxl_domain_infolist failed.\n");
3008 return 1;
3010 info_free = info;
3011 } else if (optind == argc-1) {
3012 find_domain(argv[optind]);
3013 rc = libxl_domain_info(&ctx, &info_buf, domid);
3014 if (rc == ERROR_INVAL) {
3015 fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
3016 argv[optind]);
3017 return -rc;
3019 if (rc) {
3020 fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
3021 return -rc;
3023 info = &info_buf;
3024 nb_domain = 1;
3025 } else {
3026 help("list");
3027 return 2;
3030 if (details)
3031 list_domains_details(info, nb_domain);
3032 else
3033 list_domains(verbose, info, nb_domain);
3035 free(info_free);
3037 return 0;
3040 int main_list_vm(int argc, char **argv)
3042 int opt;
3044 while ((opt = getopt(argc, argv, "h")) != -1) {
3045 switch (opt) {
3046 case 'h':
3047 help("list-vm");
3048 return 0;
3049 default:
3050 fprintf(stderr, "option not supported\n");
3051 break;
3055 list_vm();
3056 return 0;
3059 int main_create(int argc, char **argv)
3061 char *filename = NULL;
3062 char *p, extra_config[1024];
3063 struct domain_create dom_info;
3064 int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
3065 dryrun = 0, quiet = 0;
3066 int opt, rc;
3067 int option_index = 0;
3068 static struct option long_options[] = {
3069 {"dryrun", 0, 0, 'n'},
3070 {"quiet", 0, 0, 'q'},
3071 {"help", 0, 0, 'h'},
3072 {"defconfig", 1, 0, 'f'},
3073 {0, 0, 0, 0}
3074 };
3076 while (1) {
3077 opt = getopt_long(argc, argv, "hnqf:pcde", long_options, &option_index);
3078 if (opt == -1)
3079 break;
3081 switch (opt) {
3082 case 'f':
3083 filename = optarg;
3084 break;
3085 case 'p':
3086 paused = 1;
3087 break;
3088 case 'c':
3089 console_autoconnect = 1;
3090 break;
3091 case 'd':
3092 debug = 1;
3093 break;
3094 case 'e':
3095 daemonize = 0;
3096 break;
3097 case 'h':
3098 help("create");
3099 return 0;
3100 case 'n':
3101 dryrun = 1;
3102 break;
3103 case 'q':
3104 quiet = 1;
3105 break;
3106 default:
3107 fprintf(stderr, "option not supported\n");
3108 break;
3112 memset(extra_config, 0, sizeof(extra_config));
3113 while (optind < argc) {
3114 if ((p = strchr(argv[optind], '='))) {
3115 if (strlen(extra_config) + 1 < sizeof(extra_config)) {
3116 if (strlen(extra_config))
3117 strcat(extra_config, "\n");
3118 strcat(extra_config, argv[optind]);
3120 } else if (!filename) {
3121 filename = argv[optind];
3122 } else {
3123 help("create");
3124 return 2;
3126 optind++;
3129 memset(&dom_info, 0, sizeof(dom_info));
3130 dom_info.debug = debug;
3131 dom_info.daemonize = daemonize;
3132 dom_info.paused = paused;
3133 dom_info.dryrun = dryrun;
3134 dom_info.quiet = quiet;
3135 dom_info.config_file = filename;
3136 dom_info.extra_config = extra_config;
3137 dom_info.migrate_fd = -1;
3138 dom_info.console_autoconnect = console_autoconnect;
3140 rc = create_domain(&dom_info);
3141 if (rc < 0)
3142 return -rc;
3144 return 0;
3147 void button_press(char *p, char *b)
3149 libxl_button button;
3151 find_domain(p);
3153 if (!strcmp(b, "power")) {
3154 button = POWER_BUTTON;
3155 } else if (!strcmp(b, "sleep")) {
3156 button = SLEEP_BUTTON;
3157 } else {
3158 fprintf(stderr, "%s is an invalid button identifier\n", b);
3159 exit(2);
3162 libxl_button_press(&ctx, domid, button);
3165 int main_button_press(int argc, char **argv)
3167 int opt;
3168 char *p;
3169 char *b;
3171 while ((opt = getopt(argc, argv, "h")) != -1) {
3172 switch (opt) {
3173 case 'h':
3174 help("button-press");
3175 return 0;
3176 default:
3177 fprintf(stderr, "option not supported\n");
3178 break;
3181 if (optind >= argc - 1) {
3182 help("button-press");
3183 return 2;
3186 p = argv[optind];
3187 b = argv[optind + 1];
3189 button_press(p, b);
3190 return 0;
3193 static void print_vcpuinfo(uint32_t tdomid,
3194 const libxl_vcpuinfo *vcpuinfo,
3195 uint32_t nr_cpus)
3197 int i, l;
3198 uint64_t *cpumap;
3199 uint64_t pcpumap;
3201 /* NAME ID VCPU */
3202 printf("%-32s %5u %5u",
3203 libxl_domid_to_name(&ctx, tdomid), tdomid, vcpuinfo->vcpuid);
3204 if (!vcpuinfo->online) {
3205 /* CPU STA */
3206 printf("%5c %3c%cp ", '-', '-', '-');
3207 } else {
3208 /* CPU STA */
3209 printf("%5u %3c%c- ", vcpuinfo->cpu,
3210 vcpuinfo->running ? 'r' : '-',
3211 vcpuinfo->blocked ? 'b' : '-');
3213 /* TIM */
3214 printf("%9.1f ", ((float)vcpuinfo->vcpu_time / 1e9));
3215 /* CPU AFFINITY */
3216 pcpumap = nr_cpus > 64 ? -1 : ((1 << nr_cpus) - 1);
3217 for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
3218 if (*cpumap < pcpumap) {
3219 break;
3221 if (nr_cpus > 64) {
3222 pcpumap = -1;
3223 nr_cpus -= 64;
3224 } else {
3225 pcpumap = ((1 << nr_cpus) - 1);
3226 nr_cpus = 0;
3229 if (!nr_cpus) {
3230 printf("any cpu\n");
3231 } else {
3232 for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
3233 pcpumap = *cpumap;
3234 for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1)
3236 printf("%u", i);
3237 for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
3239 if (l < i) {
3240 printf("-%u", i);
3242 for (++i; pcpumap; ++i, pcpumap >>= 1) {
3243 if (pcpumap & 1) {
3244 printf(",%u", i);
3245 for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
3247 if (l < i) {
3248 printf("-%u", i);
3250 ++i;
3253 printf("\n");
3254 nr_cpus = nr_cpus > 64 ? nr_cpus - 64 : 0;
3259 void vcpulist(int argc, char **argv)
3261 libxl_dominfo *dominfo;
3262 libxl_vcpuinfo *vcpuinfo;
3263 libxl_physinfo physinfo;
3264 int nb_vcpu, nb_domain, cpusize;
3266 if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
3267 fprintf(stderr, "libxl_physinfo failed.\n");
3268 goto vcpulist_out;
3270 printf("%-32s %5s %5s %5s %5s %9s %s\n",
3271 "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
3272 if (!argc) {
3273 if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
3274 fprintf(stderr, "libxl_list_domain failed.\n");
3275 goto vcpulist_out;
3277 for (; nb_domain > 0; --nb_domain, ++dominfo) {
3278 if (!(vcpuinfo = libxl_list_vcpu(&ctx, dominfo->domid, &nb_vcpu, &cpusize))) {
3279 fprintf(stderr, "libxl_list_vcpu failed.\n");
3280 goto vcpulist_out;
3282 for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
3283 print_vcpuinfo(dominfo->domid, vcpuinfo, physinfo.nr_cpus);
3286 } else {
3287 for (; argc > 0; ++argv, --argc) {
3288 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
3289 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
3291 if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &cpusize))) {
3292 fprintf(stderr, "libxl_list_vcpu failed.\n");
3293 goto vcpulist_out;
3295 for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
3296 print_vcpuinfo(domid, vcpuinfo, physinfo.nr_cpus);
3300 vcpulist_out:
3304 int main_vcpulist(int argc, char **argv)
3306 int opt;
3308 while ((opt = getopt(argc, argv, "h")) != -1) {
3309 switch (opt) {
3310 case 'h':
3311 help("vcpu-list");
3312 return 0;
3313 default:
3314 fprintf(stderr, "option `%c' not supported.\n", opt);
3315 break;
3319 vcpulist(argc - 2, argv + 2);
3320 return 0;
3323 void vcpupin(char *d, const char *vcpu, char *cpu)
3325 libxl_vcpuinfo *vcpuinfo;
3326 libxl_physinfo physinfo;
3327 uint64_t *cpumap = NULL;
3329 uint32_t vcpuid, cpuida, cpuidb;
3330 char *endptr, *toka, *tokb;
3331 int i, nb_vcpu, cpusize;
3333 vcpuid = strtoul(vcpu, &endptr, 10);
3334 if (vcpu == endptr) {
3335 if (strcmp(vcpu, "all")) {
3336 fprintf(stderr, "Error: Invalid argument.\n");
3337 return;
3339 vcpuid = -1;
3342 find_domain(d);
3344 if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
3345 fprintf(stderr, "libxl_get_physinfo failed.\n");
3346 goto vcpupin_out1;
3349 cpumap = calloc(physinfo.max_cpu_id + 1, sizeof (uint64_t));
3350 if (!cpumap) {
3351 goto vcpupin_out1;
3353 if (strcmp(cpu, "all")) {
3354 for (toka = strtok(cpu, ","), i = 0; toka; toka = strtok(NULL, ","), ++i) {
3355 cpuida = strtoul(toka, &endptr, 10);
3356 if (toka == endptr) {
3357 fprintf(stderr, "Error: Invalid argument.\n");
3358 goto vcpupin_out;
3360 if (*endptr == '-') {
3361 tokb = endptr + 1;
3362 cpuidb = strtoul(tokb, &endptr, 10);
3363 if ((tokb == endptr) || (cpuida > cpuidb)) {
3364 fprintf(stderr, "Error: Invalid argument.\n");
3365 goto vcpupin_out;
3367 while (cpuida <= cpuidb) {
3368 cpumap[cpuida / 64] |= (1 << (cpuida % 64));
3369 ++cpuida;
3371 } else {
3372 cpumap[cpuida / 64] |= (1 << (cpuida % 64));
3376 else {
3377 memset(cpumap, -1, sizeof (uint64_t) * (physinfo.max_cpu_id + 1));
3380 if (vcpuid != -1) {
3381 if (libxl_set_vcpuaffinity(&ctx, domid, vcpuid,
3382 cpumap, physinfo.max_cpu_id + 1) == -1) {
3383 fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
3386 else {
3387 if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &cpusize))) {
3388 fprintf(stderr, "libxl_list_vcpu failed.\n");
3389 goto vcpupin_out;
3391 for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
3392 if (libxl_set_vcpuaffinity(&ctx, domid, vcpuinfo->vcpuid,
3393 cpumap, physinfo.max_cpu_id + 1) == -1) {
3394 fprintf(stderr, "libxl_list_vcpu failed on vcpu `%u'.\n", vcpuinfo->vcpuid);
3398 vcpupin_out1:
3399 free(cpumap);
3400 vcpupin_out:
3404 int main_vcpupin(int argc, char **argv)
3406 int opt;
3408 if (argc != 5) {
3409 help("vcpu-pin");
3410 return 0;
3412 while ((opt = getopt(argc, argv, "h")) != -1) {
3413 switch (opt) {
3414 case 'h':
3415 help("vcpu-pin");
3416 return 0;
3417 default:
3418 fprintf(stderr, "option `%c' not supported.\n", opt);
3419 break;
3423 vcpupin(argv[2], argv[3] , argv[4]);
3424 return 0;
3427 void vcpuset(char *d, char* nr_vcpus)
3429 char *endptr;
3430 unsigned int max_vcpus;
3432 max_vcpus = strtoul(nr_vcpus, &endptr, 10);
3433 if (nr_vcpus == endptr) {
3434 fprintf(stderr, "Error: Invalid argument.\n");
3435 return;
3438 find_domain(d);
3440 if (libxl_set_vcpucount(&ctx, domid, max_vcpus) == ERROR_INVAL) {
3441 fprintf(stderr, "Error: Cannot set vcpus greater than max vcpus on running domain or lesser than 1.\n");
3445 int main_vcpuset(int argc, char **argv)
3447 int opt;
3449 if (argc != 4) {
3450 help("vcpu-set");
3451 return 0;
3453 while ((opt = getopt(argc, argv, "h")) != -1) {
3454 switch (opt) {
3455 case 'h':
3456 help("vcpu-set");
3457 return 0;
3458 default:
3459 fprintf(stderr, "option `%c' not supported.\n", opt);
3460 break;
3464 vcpuset(argv[2], argv[3]);
3465 return 0;
3468 static void output_xeninfo(void)
3470 const libxl_version_info *info;
3471 int sched_id;
3473 if (!(info = libxl_get_version_info(&ctx))) {
3474 fprintf(stderr, "libxl_get_version_info failed.\n");
3475 return;
3478 if ((sched_id = libxl_get_sched_id(&ctx)) < 0) {
3479 fprintf(stderr, "get_sched_id sysctl failed.\n");
3480 return;
3483 printf("xen_major : %d\n", info->xen_version_major);
3484 printf("xen_minor : %d\n", info->xen_version_minor);
3485 printf("xen_extra : %s\n", info->xen_version_extra);
3486 printf("xen_caps : %s\n", info->capabilities);
3487 printf("xen_scheduler : %s\n",
3488 sched_id == XEN_SCHEDULER_SEDF ? "sedf" :
3489 sched_id == XEN_SCHEDULER_CREDIT ? "credit" :
3490 sched_id == XEN_SCHEDULER_CREDIT2 ? "credit2" : "unknown");
3491 printf("xen_pagesize : %lu\n", info->pagesize);
3492 printf("platform_params : virt_start=0x%lx\n", info->virt_start);
3493 printf("xen_changeset : %s\n", info->changeset);
3494 printf("xen_commandline : %s\n", info->commandline);
3495 printf("cc_compiler : %s\n", info->compiler);
3496 printf("cc_compile_by : %s\n", info->compile_by);
3497 printf("cc_compile_domain : %s\n", info->compile_domain);
3498 printf("cc_compile_date : %s\n", info->compile_date);
3500 return;
3503 static void output_nodeinfo(void)
3505 struct utsname utsbuf;
3507 if (uname(&utsbuf) < 0)
3508 return;
3510 printf("host : %s\n", utsbuf.nodename);
3511 printf("release : %s\n", utsbuf.release);
3512 printf("version : %s\n", utsbuf.version);
3513 printf("machine : %s\n", utsbuf.machine);
3516 static void output_physinfo(void)
3518 libxl_physinfo info;
3519 const libxl_version_info *vinfo;
3520 unsigned int i;
3522 if (libxl_get_physinfo(&ctx, &info) != 0) {
3523 fprintf(stderr, "libxl_physinfo failed.\n");
3524 return;
3527 printf("nr_cpus : %d\n", info.nr_cpus);
3528 printf("nr_nodes : %d\n", info.nr_nodes);
3529 printf("cores_per_socket : %d\n", info.cores_per_socket);
3530 printf("threads_per_core : %d\n", info.threads_per_core);
3531 printf("cpu_mhz : %d\n", info.cpu_khz / 1000);
3532 printf("hw_caps : ");
3533 for (i = 0; i < 8; i++)
3534 printf("%08x%c", info.hw_cap[i], i < 7 ? ':' : '\n');
3535 printf("virt_caps :");
3536 if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm)
3537 printf(" hvm");
3538 if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm_directio)
3539 printf(" hvm_directio");
3540 printf("\n");
3541 vinfo = libxl_get_version_info(&ctx);
3542 if (vinfo) {
3543 i = (1 << 20) / vinfo->pagesize;
3544 printf("total_memory : %"PRIu64"\n", info.total_pages / i);
3545 printf("free_memory : %"PRIu64"\n", info.free_pages / i);
3548 return;
3551 static void info(void)
3553 output_nodeinfo();
3555 output_physinfo();
3557 output_xeninfo();
3559 printf("xend_config_format : 4\n");
3561 return;
3564 int main_info(int argc, char **argv)
3566 int opt;
3568 while ((opt = getopt(argc, argv, "h")) != -1) {
3569 switch (opt) {
3570 case 'h':
3571 help("info");
3572 return 0;
3573 default:
3574 fprintf(stderr, "option `%c' not supported.\n", opt);
3575 break;
3579 info();
3580 return 0;
3583 static int sched_credit_domain_get(
3584 int domid, libxl_sched_credit *scinfo)
3586 int rc;
3588 rc = libxl_sched_credit_domain_get(&ctx, domid, scinfo);
3589 if (rc)
3590 fprintf(stderr, "libxl_sched_credit_domain_get failed.\n");
3592 return rc;
3595 static int sched_credit_domain_set(
3596 int domid, libxl_sched_credit *scinfo)
3598 int rc;
3600 rc = libxl_sched_credit_domain_set(&ctx, domid, scinfo);
3601 if (rc)
3602 fprintf(stderr, "libxl_sched_credit_domain_set failed.\n");
3604 return rc;
3607 static void sched_credit_domain_output(
3608 int domid, libxl_sched_credit *scinfo)
3610 printf("%-33s %4d %6d %4d\n",
3611 libxl_domid_to_name(&ctx, domid),
3612 domid,
3613 scinfo->weight,
3614 scinfo->cap);
3617 int main_sched_credit(int argc, char **argv)
3619 libxl_dominfo *info;
3620 libxl_sched_credit scinfo;
3621 int nb_domain, i;
3622 char *dom = NULL;
3623 int weight = 256, cap = 0, opt_w = 0, opt_c = 0;
3624 int opt, rc;
3626 while ((opt = getopt(argc, argv, "hd:w:c:")) != -1) {
3627 switch (opt) {
3628 case 'd':
3629 dom = optarg;
3630 break;
3631 case 'w':
3632 weight = strtol(optarg, NULL, 10);
3633 opt_w = 1;
3634 break;
3635 case 'c':
3636 cap = strtol(optarg, NULL, 10);
3637 opt_c = 1;
3638 break;
3639 case 'h':
3640 help("sched-credit");
3641 return 0;
3642 default:
3643 fprintf(stderr, "option `%c' not supported.\n", opt);
3644 break;
3648 if (!dom && (opt_w || opt_c)) {
3649 fprintf(stderr, "Must specify a domain.\n");
3650 return 1;
3653 if (!dom) { /* list all domain's credit scheduler info */
3654 info = libxl_list_domain(&ctx, &nb_domain);
3655 if (!info) {
3656 fprintf(stderr, "libxl_domain_infolist failed.\n");
3657 return 1;
3660 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
3661 for (i = 0; i < nb_domain; i++) {
3662 rc = sched_credit_domain_get(info[i].domid, &scinfo);
3663 if (rc)
3664 return -rc;
3665 sched_credit_domain_output(info[i].domid, &scinfo);
3667 } else {
3668 find_domain(dom);
3670 rc = sched_credit_domain_get(domid, &scinfo);
3671 if (rc)
3672 return -rc;
3674 if (!opt_w && !opt_c) { /* output credit scheduler info */
3675 printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
3676 sched_credit_domain_output(domid, &scinfo);
3677 } else { /* set credit scheduler paramaters */
3678 if (opt_w)
3679 scinfo.weight = weight;
3680 if (opt_c)
3681 scinfo.cap = cap;
3682 rc = sched_credit_domain_set(domid, &scinfo);
3683 if (rc)
3684 return -rc;
3688 return 0;
3691 int main_domid(int argc, char **argv)
3693 int opt;
3694 char *domname = NULL;
3696 while ((opt = getopt(argc, argv, "h")) != -1) {
3697 switch (opt) {
3698 case 'h':
3699 help("domid");
3700 return 0;
3701 default:
3702 fprintf(stderr, "option `%c' not supported.\n", opt);
3703 break;
3707 domname = argv[optind];
3708 if (!domname) {
3709 fprintf(stderr, "Must specify a domain name.\n\n");
3710 help("domid");
3711 return 1;
3714 if (libxl_name_to_domid(&ctx, domname, &domid)) {
3715 fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
3716 return 1;
3719 printf("%d\n", domid);
3721 return 0;
3724 int main_domname(int argc, char **argv)
3726 int opt;
3727 char *domname = NULL;
3728 char *endptr = NULL;
3730 while ((opt = getopt(argc, argv, "h")) != -1) {
3731 switch (opt) {
3732 case 'h':
3733 help("domname");
3734 return 0;
3735 default:
3736 fprintf(stderr, "option `%c' not supported.\n", opt);
3737 break;
3741 if (!argv[optind]) {
3742 fprintf(stderr, "Must specify a domain id.\n\n");
3743 help("domname");
3744 return 1;
3746 domid = strtol(argv[optind], &endptr, 10);
3747 if (domid == 0 && !strcmp(endptr, argv[optind])) {
3748 /*no digits at all*/
3749 fprintf(stderr, "Invalid domain id.\n\n");
3750 return 1;
3753 domname = libxl_domid_to_name(&ctx, domid);
3754 if (!domname) {
3755 fprintf(stderr, "Can't get domain name of domain id '%d', maybe this domain does not exist.\n", domid);
3756 return 1;
3759 printf("%s\n", domname);
3761 return 0;
3764 int main_rename(int argc, char **argv)
3766 int opt;
3767 char *dom;
3768 char *new_name;
3770 while ((opt = getopt(argc, argv, "h")) != -1) {
3771 switch (opt) {
3772 case 'h':
3773 help("rename");
3774 return 0;
3775 default:
3776 fprintf(stderr, "option `%c' not supported.\n", opt);
3777 break;
3781 dom = argv[optind++];
3782 if (!dom || !argv[optind]) {
3783 fprintf(stderr, "'xl rename' requires 2 arguments.\n\n");
3784 help("rename");
3785 return 1;
3788 find_domain(dom);
3789 new_name = argv[optind];
3791 if (libxl_domain_rename(&ctx, domid, common_domname, new_name, 0)) {
3792 fprintf(stderr, "Can't rename domain '%s'.\n", dom);
3793 return 1;
3796 return 0;
3799 int main_trigger(int argc, char **argv)
3801 int opt;
3802 char *trigger_name = NULL;
3803 char *endptr = NULL;
3804 char *dom = NULL;
3805 int vcpuid = 0;
3807 while ((opt = getopt(argc, argv, "h")) != -1) {
3808 switch (opt) {
3809 case 'h':
3810 help("trigger");
3811 return 0;
3812 default:
3813 fprintf(stderr, "option `%c' not supported.\n", opt);
3814 break;
3818 dom = argv[optind++];
3819 if (!dom || !argv[optind]) {
3820 fprintf(stderr, "'xl trigger' requires between 2 and 3 arguments.\n\n");
3821 help("trigger");
3822 return 1;
3825 find_domain(dom);
3827 trigger_name = argv[optind++];
3829 if (argv[optind]) {
3830 vcpuid = strtol(argv[optind], &endptr, 10);
3831 if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
3832 fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
3836 libxl_send_trigger(&ctx, domid, trigger_name, vcpuid);
3838 return 0;
3842 int main_sysrq(int argc, char **argv)
3844 int opt;
3845 char *sysrq = NULL;
3846 char *dom = NULL;
3848 while ((opt = getopt(argc, argv, "h")) != -1) {
3849 switch (opt) {
3850 case 'h':
3851 help("sysrq");
3852 return 0;
3853 default:
3854 fprintf(stderr, "option `%c' not supported.\n", opt);
3855 break;
3859 dom = argv[optind++];
3860 if (!dom || !argv[optind]) {
3861 fprintf(stderr, "'xl sysrq' requires 2 arguments.\n\n");
3862 help("sysrq");
3863 return 1;
3866 find_domain(dom);
3868 sysrq = argv[optind];
3870 if (sysrq[1] != '\0') {
3871 fprintf(stderr, "Invalid sysrq.\n\n");
3872 help("sysrq");
3873 return 1;
3876 libxl_send_sysrq(&ctx, domid, sysrq[0]);
3878 return 0;
3881 int main_debug_keys(int argc, char **argv)
3883 int opt;
3884 char *keys;
3886 while ((opt = getopt(argc, argv, "h")) != -1) {
3887 switch (opt) {
3888 case 'h':
3889 help("debug-keys");
3890 return 0;
3891 default:
3892 fprintf(stderr, "option not supported\n");
3893 break;
3896 if (optind >= argc) {
3897 help("debug-keys");
3898 return 2;
3901 keys = argv[optind];
3903 if (libxl_send_debug_keys(&ctx, keys)) {
3904 fprintf(stderr, "cannot send debug keys: %s\n", keys);
3905 return 1;
3908 return 0;
3911 int main_dmesg(int argc, char **argv)
3913 unsigned int clear = 0;
3914 libxl_xen_console_reader *cr;
3915 char *line;
3916 int opt, ret = 1;
3918 while ((opt = getopt(argc, argv, "hc")) != -1) {
3919 switch (opt) {
3920 case 'c':
3921 clear = 1;
3922 break;
3923 case 'h':
3924 help("dmesg");
3925 return 0;
3926 default:
3927 fprintf(stderr, "option not supported\n");
3928 break;
3932 cr = libxl_xen_console_read_start(&ctx, clear);
3933 if (!cr)
3934 goto finish;
3936 while ((ret = libxl_xen_console_read_line(&ctx, cr, &line)) > 0)
3937 printf("%s", line);
3939 finish:
3940 libxl_xen_console_read_finish(&ctx, cr);
3941 return ret;
3944 int main_top(int argc, char **argv)
3946 int opt;
3948 while ((opt = getopt(argc, argv, "h")) != -1) {
3949 switch (opt) {
3950 case 'h':
3951 help("top");
3952 return 0;
3953 default:
3954 fprintf(stderr, "option `%c' not supported.\n", opt);
3955 break;
3959 return system("xentop");
3962 int main_networkattach(int argc, char **argv)
3964 int opt;
3965 libxl_device_nic nic;
3966 char *endptr, *tok;
3967 int i;
3968 unsigned int val;
3970 if ((argc < 3) || (argc > 11)) {
3971 help("network-attach");
3972 return 0;
3974 while ((opt = getopt(argc, argv, "h")) != -1) {
3975 switch (opt) {
3976 case 'h':
3977 help("network-attach");
3978 return 0;
3979 default:
3980 fprintf(stderr, "option `%c' not supported.\n", opt);
3981 break;
3985 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
3986 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
3987 return 1;
3989 init_nic_info(&nic, -1);
3990 for (argv += 3, argc -= 3; argc > 0; ++argv, --argc) {
3991 if (!strncmp("type=", *argv, 5)) {
3992 if (!strncmp("vif", (*argv) + 5, 4)) {
3993 nic.nictype = NICTYPE_VIF;
3994 } else if (!strncmp("ioemu", (*argv) + 5, 5)) {
3995 nic.nictype = NICTYPE_IOEMU;
3996 } else {
3997 fprintf(stderr, "Invalid parameter `type'.\n");
3998 return 1;
4000 } else if (!strncmp("mac=", *argv, 4)) {
4001 tok = strtok((*argv) + 4, ":");
4002 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4003 val = strtoul(tok, &endptr, 16);
4004 if ((tok == endptr) || (val > 255)) {
4005 fprintf(stderr, "Invalid parameter `mac'.\n");
4006 return 1;
4008 nic.mac[i] = val;
4010 } else if (!strncmp("bridge=", *argv, 7)) {
4011 nic.bridge = (*argv) + 7;
4012 } else if (!strncmp("ip=", *argv, 3)) {
4013 if (!inet_aton((*argv) + 3, &(nic.ip))) {
4014 fprintf(stderr, "Invalid parameter `ip'.\n");
4015 return 1;
4017 } else if (!strncmp("script=", *argv, 6)) {
4018 nic.script = (*argv) + 6;
4019 } else if (!strncmp("backend=", *argv, 8)) {
4020 if(libxl_name_to_domid(&ctx, ((*argv) + 8), &val)) {
4021 fprintf(stderr, "Specified backend domain does not exist, defaulting to Dom0\n");
4022 val = 0;
4024 nic.backend_domid = val;
4025 } else if (!strncmp("vifname=", *argv, 8)) {
4026 nic.ifname = (*argv) + 8;
4027 } else if (!strncmp("model=", *argv, 6)) {
4028 nic.model = (*argv) + 6;
4029 } else if (!strncmp("rate=", *argv, 5)) {
4030 } else if (!strncmp("accel=", *argv, 6)) {
4031 } else {
4032 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4033 return 1;
4036 nic.domid = domid;
4037 if (libxl_device_nic_add(&ctx, domid, &nic)) {
4038 fprintf(stderr, "libxl_device_nic_add failed.\n");
4039 return 1;
4041 return 0;
4044 int main_networklist(int argc, char **argv)
4046 int opt;
4047 libxl_nicinfo *nics;
4048 unsigned int nb;
4050 if (argc < 3) {
4051 help("network-list");
4052 return 1;
4054 while ((opt = getopt(argc, argv, "h")) != -1) {
4055 switch (opt) {
4056 case 'h':
4057 help("network-list");
4058 return 0;
4059 default:
4060 fprintf(stderr, "option `%c' not supported.\n", opt);
4061 break;
4065 /* Idx BE MAC Hdl Sta evch txr/rxr BE-path */
4066 printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
4067 "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
4068 for (argv += 2, argc -= 2; argc > 0; --argc, ++argv) {
4069 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4070 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4071 continue;
4073 if (!(nics = libxl_list_nics(&ctx, domid, &nb))) {
4074 continue;
4076 for (; nb > 0; --nb, ++nics) {
4077 /* Idx BE */
4078 printf("%-3d %-2d ", nics->devid, nics->backend_id);
4079 /* MAC */
4080 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4081 nics->mac[0], nics->mac[1], nics->mac[2],
4082 nics->mac[3], nics->mac[4], nics->mac[5]);
4083 /* Hdl Sta evch txr/rxr BE-path */
4084 printf("%6d %5d %6d %5d/%-11d %-30s\n",
4085 nics->devid, nics->state, nics->evtch,
4086 nics->rref_tx, nics->rref_rx, nics->backend);
4089 return 0;
4092 int main_networkdetach(int argc, char **argv)
4094 int opt;
4095 libxl_device_nic nic;
4097 if (argc != 4) {
4098 help("network-detach");
4099 return 0;
4101 while ((opt = getopt(argc, argv, "h")) != -1) {
4102 switch (opt) {
4103 case 'h':
4104 help("network-detach");
4105 return 0;
4106 default:
4107 fprintf(stderr, "option `%c' not supported.\n", opt);
4108 break;
4112 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
4113 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
4114 return 1;
4117 if (!strchr(argv[3], ':')) {
4118 if (libxl_devid_to_device_nic(&ctx, domid, argv[3], &nic)) {
4119 fprintf(stderr, "Unknown device %s.\n", argv[3]);
4120 return 1;
4122 } else {
4123 if (libxl_mac_to_device_nic(&ctx, domid, argv[3], &nic)) {
4124 fprintf(stderr, "Unknown device %s.\n", argv[3]);
4125 return 1;
4128 if (libxl_device_nic_del(&ctx, &nic, 1)) {
4129 fprintf(stderr, "libxl_device_nic_del failed.\n");
4130 return 1;
4132 return 0;
4135 int main_blockattach(int argc, char **argv)
4137 int opt;
4138 char *tok;
4139 uint32_t fe_domid, be_domid = 0;
4140 libxl_device_disk disk = { 0 };
4142 if ((argc < 5) || (argc > 7)) {
4143 help("block-attach");
4144 return 0;
4146 while ((opt = getopt(argc, argv, "h")) != -1) {
4147 switch (opt) {
4148 case 'h':
4149 help("block-attach");
4150 return 0;
4151 default:
4152 fprintf(stderr, "option `%c' not supported.\n", opt);
4153 break;
4157 tok = strtok(argv[3], ":");
4158 if (!strcmp(tok, "phy")) {
4159 disk.phystype = PHYSTYPE_PHY;
4160 } else if (!strcmp(tok, "file")) {
4161 disk.phystype = PHYSTYPE_FILE;
4162 } else if (!strcmp(tok, "tap")) {
4163 tok = strtok(NULL, ":");
4164 if (!strcmp(tok, "aio")) {
4165 disk.phystype = PHYSTYPE_AIO;
4166 } else if (!strcmp(tok, "vhd")) {
4167 disk.phystype = PHYSTYPE_VHD;
4168 } else if (!strcmp(tok, "qcow")) {
4169 disk.phystype = PHYSTYPE_QCOW;
4170 } else if (!strcmp(tok, "qcow2")) {
4171 disk.phystype = PHYSTYPE_QCOW2;
4172 } else {
4173 fprintf(stderr, "Error: `%s' is not a valid disk image.\n", tok);
4174 return 1;
4176 } else {
4177 fprintf(stderr, "Error: `%s' is not a valid block device.\n", tok);
4178 return 1;
4180 disk.physpath = strtok(NULL, "\0");
4181 if (!disk.physpath) {
4182 fprintf(stderr, "Error: missing path to disk image.\n");
4183 return 1;
4185 disk.virtpath = argv[4];
4186 disk.unpluggable = 1;
4187 disk.readwrite = ((argc <= 4) || (argv[5][0] == 'w'));
4189 if (domain_qualifier_to_domid(argv[2], &fe_domid, 0) < 0) {
4190 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
4191 return 1;
4193 if (argc == 7) {
4194 if (domain_qualifier_to_domid(argv[6], &be_domid, 0) < 0) {
4195 fprintf(stderr, "%s is an invalid domain identifier\n", argv[6]);
4196 return 1;
4199 disk.domid = fe_domid;
4200 disk.backend_domid = be_domid;
4201 if (libxl_device_disk_add(&ctx, fe_domid, &disk)) {
4202 fprintf(stderr, "libxl_device_disk_add failed.\n");
4204 return 0;
4207 int main_blocklist(int argc, char **argv)
4209 int opt;
4210 int nb;
4211 libxl_device_disk *disks;
4212 libxl_diskinfo diskinfo;
4214 if (argc < 3) {
4215 help("block-list");
4216 return 0;
4218 while ((opt = getopt(argc, argv, "h")) != -1) {
4219 switch (opt) {
4220 case 'h':
4221 help("block-list");
4222 return 0;
4223 default:
4224 fprintf(stderr, "option `%c' not supported.\n", opt);
4225 break;
4229 printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
4230 "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
4231 for (argv += 2, argc -= 2; argc > 0; --argc, ++argv) {
4232 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4233 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4234 continue;
4236 disks = libxl_device_disk_list(&ctx, domid, &nb);
4237 if (!disks) {
4238 continue;
4240 for (; nb > 0; --nb, ++disks) {
4241 if (!libxl_device_disk_getinfo(&ctx, domid, disks, &diskinfo)) {
4242 /* Vdev BE hdl st evch rref BE-path*/
4243 printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
4244 diskinfo.devid, diskinfo.backend_id, diskinfo.frontend_id,
4245 diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
4249 return 0;
4252 int main_blockdetach(int argc, char **argv)
4254 int opt;
4255 libxl_device_disk disk;
4257 if (argc != 4) {
4258 help("block-detach");
4259 return 0;
4261 while ((opt = getopt(argc, argv, "h")) != -1) {
4262 switch (opt) {
4263 case 'h':
4264 help("block-detach");
4265 return 0;
4266 default:
4267 fprintf(stderr, "option `%c' not supported.\n", opt);
4268 break;
4272 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
4273 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
4274 return 1;
4276 if (libxl_devid_to_device_disk(&ctx, domid, argv[3], &disk)) {
4277 fprintf(stderr, "Error: Device %s not connected.\n", argv[3]);
4278 return 1;
4280 if (libxl_device_disk_del(&ctx, &disk, 1)) {
4281 fprintf(stderr, "libxl_device_del failed.\n");
4283 return 0;
4286 int main_network2attach(int argc, char **argv)
4288 int opt;
4289 char *tok, *endptr;
4290 char *back_dom = NULL;
4291 uint32_t domid, back_domid;
4292 unsigned int val, i;
4293 libxl_device_net2 net2;
4295 if ((argc < 3) || (argc > 12)) {
4296 help("network2-attach");
4297 return 0;
4299 while ((opt = getopt(argc, argv, "h")) != -1) {
4300 switch (opt) {
4301 case 'h':
4302 help("network2-attach");
4303 return 0;
4304 default:
4305 fprintf(stderr, "option `%c' not supported.\n", opt);
4306 break;
4310 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
4311 fprintf(stderr, "%s is an invalid domain identifier\n", argv[1]);
4312 return 1;
4314 init_net2_info(&net2, -1);
4315 for (argv += 3, argc -= 3; argc > 0; --argc, ++argv) {
4316 if (!strncmp("front_mac=", *argv, 10)) {
4317 tok = strtok((*argv) + 10, ":");
4318 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4319 val = strtoul(tok, &endptr, 16);
4320 if ((tok == endptr) || (val > 255)) {
4321 fprintf(stderr, "Invalid parameter `front_mac'.\n");
4322 return 1;
4324 net2.front_mac[i] = val;
4326 } else if (!strncmp("back_mac=", *argv, 9)) {
4327 tok = strtok((*argv) + 10, ":");
4328 for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
4329 val = strtoul(tok, &endptr, 16);
4330 if ((tok == endptr) || (val > 255)) {
4331 fprintf(stderr, "Invalid parameter back_mac=%s.\n", *argv + 9);
4332 return 1;
4334 net2.back_mac[i] = val;
4336 } else if (!strncmp("backend=", *argv, 8)) {
4337 back_dom = *argv;
4338 } else if (!strncmp("trusted=", *argv, 8)) {
4339 net2.trusted = (*((*argv) + 8) == '1');
4340 } else if (!strncmp("back_trusted=", *argv, 13)) {
4341 net2.back_trusted = (*((*argv) + 13) == '1');
4342 } else if (!strncmp("bridge=", *argv, 7)) {
4343 net2.bridge = *argv + 13;
4344 } else if (!strncmp("filter_mac=", *argv, 11)) {
4345 net2.filter_mac = (*((*argv) + 11) == '1');
4346 } else if (!strncmp("front_filter_mac=", *argv, 17)) {
4347 net2.front_filter_mac = (*((*argv) + 17) == '1');
4348 } else if (!strncmp("pdev=", *argv, 5)) {
4349 val = strtoul(*argv + 5, &endptr, 10);
4350 if (endptr == (*argv + 5)) {
4351 fprintf(stderr, "Invalid parameter pdev=%s.\n", *argv + 5);
4352 return 1;
4354 net2.pdev = val;
4355 } else if (!strncmp("max_bypasses=", *argv, 13)) {
4356 val = strtoul(*argv + 13, &endptr, 10);
4357 if (endptr == (*argv + 13)) {
4358 fprintf(stderr, "Invalid parameter max_bypasses=%s.\n", *argv + 13);
4359 return 1;
4361 net2.max_bypasses = val;
4362 } else {
4363 fprintf(stderr, "unrecognized argument `%s'\n", *argv);
4364 return 1;
4368 if (back_dom) {
4369 if (domain_qualifier_to_domid(back_dom, &back_domid, 0) < 0) {
4370 fprintf(stderr, "%s is an invalid domain identifier\n", back_dom);
4371 return 1;
4374 net2.domid = domid;
4375 net2.backend_domid = back_domid;
4376 if (libxl_device_net2_add(&ctx, domid, &net2)) {
4377 fprintf(stderr, "libxl_device_net2_add failed.\n");
4379 return 0;
4382 int main_network2list(int argc, char **argv)
4384 int opt;
4385 unsigned int nb;
4386 libxl_net2info *net2s;
4388 if (argc < 3) {
4389 help("network2-list");
4390 return 0;
4392 while ((opt = getopt(argc, argv, "h")) != -1) {
4393 switch (opt) {
4394 case 'h':
4395 help("network2-list");
4396 return 0;
4397 default:
4398 fprintf(stderr, "option `%c' not supported.\n", opt);
4399 break;
4403 printf("%-3s %-2s %-5s %-17s %-17s %-7s %-6s %-30s\n",
4404 "Idx", "BE", "state", "Mac Addr.", "Remote Mac Addr.",
4405 "trusted", "filter", "backend");
4406 for (argv += 2, argc -=2; argc > 0; --argc, ++argv) {
4407 if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
4408 fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
4409 continue;
4411 if ((net2s = libxl_device_net2_list(&ctx, domid, &nb))) {
4412 for (; nb > 0; --nb, ++net2s) {
4413 printf("%3d %2d %5d ", net2s->devid, net2s->backend_id, net2s->state);
4414 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4415 net2s->mac[0], net2s->mac[1], net2s->mac[2],
4416 net2s->mac[3], net2s->mac[4], net2s->mac[5]);
4417 printf("%02x:%02x:%02x:%02x:%02x:%02x ",
4418 net2s->back_mac[0], net2s->back_mac[1], net2s->back_mac[2],
4419 net2s->back_mac[3], net2s->back_mac[4], net2s->back_mac[5]);
4420 printf("%-7d %-6d %-30s\n", net2s->trusted, net2s->filter_mac, net2s->backend);
4424 return 0;
4427 int main_network2detach(int argc, char **argv)
4429 int opt;
4430 libxl_device_net2 net2;
4432 if (argc != 4) {
4433 help("network2-detach");
4434 return 0;
4436 while ((opt = getopt(argc, argv, "h")) != -1) {
4437 switch (opt) {
4438 case 'h':
4439 help("network2-detach");
4440 return 0;
4441 default:
4442 fprintf(stderr, "option `%c' not supported.\n", opt);
4443 break;
4447 if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
4448 fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
4449 return 1;
4451 if (libxl_devid_to_device_net2(&ctx, domid, argv[3], &net2)) {
4452 fprintf(stderr, "Error: Device %s not connected.\n", argv[3]);
4453 return 1;
4455 if (libxl_device_net2_del(&ctx, &net2, 1)) {
4456 fprintf(stderr, "libxl_device_net2_del failed.\n");
4457 return 1;
4459 return 0;
4462 static char *uptime_to_string(unsigned long time, int short_mode)
4464 int sec, min, hour, day;
4465 char *time_string;
4466 int ret;
4468 day = (int)(time / 86400);
4469 time -= (day * 86400);
4470 hour = (int)(time / 3600);
4471 time -= (hour * 3600);
4472 min = (int)(time / 60);
4473 time -= (min * 60);
4474 sec = time;
4476 if (short_mode)
4477 if (day > 1)
4478 ret = asprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
4479 else if (day == 1)
4480 ret = asprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
4481 else
4482 ret = asprintf(&time_string, "%2d:%02d", hour, min);
4483 else
4484 if (day > 1)
4485 ret = asprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
4486 else if (day == 1)
4487 ret = asprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
4488 else
4489 ret = asprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
4491 if (ret < 0)
4492 return NULL;
4493 return time_string;
4496 static char *current_time_to_string(time_t now)
4498 char now_str[100];
4499 struct tm *tmp;
4501 tmp = localtime(&now);
4502 if (tmp == NULL) {
4503 fprintf(stderr, "Get localtime error");
4504 exit(-1);
4506 if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
4507 fprintf(stderr, "strftime returned 0");
4508 exit(-1);
4510 return strdup(now_str);
4513 static void print_dom0_uptime(int short_mode, time_t now)
4515 int fd;
4516 char buf[512];
4517 uint32_t uptime = 0;
4518 char *uptime_str = NULL;
4519 char *now_str = NULL;
4521 fd = open("/proc/uptime", O_RDONLY);
4522 if (fd == -1)
4523 goto err;
4525 if (read(fd, buf, sizeof(buf)) == -1) {
4526 close(fd);
4527 goto err;
4529 close(fd);
4531 strtok(buf, " ");
4532 uptime = strtoul(buf, NULL, 10);
4534 if (short_mode)
4536 now_str = current_time_to_string(now);
4537 uptime_str = uptime_to_string(uptime, 1);
4538 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
4539 libxl_domid_to_name(&ctx, 0), 0);
4541 else
4543 uptime_str = uptime_to_string(uptime, 0);
4544 printf("%-33s %4d %s\n", libxl_domid_to_name(&ctx, 0),
4545 0, uptime_str);
4548 if (now_str)
4549 free(now_str);
4550 if (uptime_str)
4551 free(uptime_str);
4552 return;
4553 err:
4554 fprintf(stderr, "Can not get Dom0 uptime.\n");
4555 exit(-1);
4558 static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
4560 uint32_t s_time = 0;
4561 uint32_t uptime = 0;
4562 char *uptime_str = NULL;
4563 char *now_str = NULL;
4565 s_time = libxl_vm_get_start_time(&ctx, domuid);
4566 if (s_time == -1)
4567 return;
4568 uptime = now - s_time;
4569 if (short_mode)
4571 now_str = current_time_to_string(now);
4572 uptime_str = uptime_to_string(uptime, 1);
4573 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
4574 libxl_domid_to_name(&ctx, domuid), domuid);
4576 else
4578 uptime_str = uptime_to_string(uptime, 0);
4579 printf("%-33s %4d %s\n", libxl_domid_to_name(&ctx, domuid),
4580 domuid, uptime_str);
4583 if (now_str)
4584 free(now_str);
4585 if (uptime_str)
4586 free(uptime_str);
4587 return;
4590 static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
4592 libxl_vminfo *info;
4593 time_t now;
4594 int nb_vm, i;
4596 now = time(NULL);
4598 if (!short_mode)
4599 printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
4601 if (nb_doms == 0) {
4602 print_dom0_uptime(short_mode, now);
4603 info = libxl_list_vm(&ctx, &nb_vm);
4604 for (i = 0; i < nb_vm; i++)
4605 print_domU_uptime(info[i].domid, short_mode, now);
4606 } else {
4607 for (i = 0; i < nb_doms; i++) {
4608 if (doms[i] == 0)
4609 print_dom0_uptime(short_mode, now);
4610 else
4611 print_domU_uptime(doms[i], short_mode, now);
4616 int main_uptime(int argc, char **argv)
4618 char *dom = NULL;
4619 int short_mode = 0;
4620 uint32_t domains[100];
4621 int nb_doms = 0;
4622 int opt;
4624 while ((opt = getopt(argc, argv, "hs")) != -1) {
4625 switch (opt) {
4626 case 's':
4627 short_mode = 1;
4628 break;
4629 case 'h':
4630 help("uptime");
4631 return 0;
4632 default:
4633 fprintf(stderr, "option `%c' not supported.\n", opt);
4634 break;
4638 for (;(dom = argv[optind]) != NULL; nb_doms++,optind++) {
4639 find_domain(dom);
4640 domains[nb_doms] = domid;
4643 print_uptime(short_mode, domains, nb_doms);
4645 return 0;
4648 int main_tmem_list(int argc, char **argv)
4650 char *dom = NULL;
4651 char *buf = NULL;
4652 int use_long = 0;
4653 int all = 0;
4654 int opt;
4656 while ((opt = getopt(argc, argv, "alh")) != -1) {
4657 switch (opt) {
4658 case 'l':
4659 use_long = 1;
4660 break;
4661 case 'a':
4662 all = 1;
4663 break;
4664 case 'h':
4665 help("tmem-list");
4666 return 0;
4667 default:
4668 fprintf(stderr, "option `%c' not supported.\n", opt);
4669 break;
4673 dom = argv[optind];
4674 if (!dom && all == 0) {
4675 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4676 help("tmem-list");
4677 return 1;
4680 if (all)
4681 domid = -1;
4682 else
4683 find_domain(dom);
4685 buf = libxl_tmem_list(&ctx, domid, use_long);
4686 if (buf == NULL)
4687 return -1;
4689 printf("%s\n", buf);
4690 free(buf);
4691 return 0;
4694 int main_tmem_freeze(int argc, char **argv)
4696 char *dom = NULL;
4697 int all = 0;
4698 int opt;
4700 while ((opt = getopt(argc, argv, "ah")) != -1) {
4701 switch (opt) {
4702 case 'a':
4703 all = 1;
4704 break;
4705 case 'h':
4706 help("tmem-freeze");
4707 return 0;
4708 default:
4709 fprintf(stderr, "option `%c' not supported.\n", opt);
4710 break;
4714 dom = argv[optind];
4715 if (!dom && all == 0) {
4716 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4717 help("tmem-freeze");
4718 return 1;
4721 if (all)
4722 domid = -1;
4723 else
4724 find_domain(dom);
4726 libxl_tmem_freeze(&ctx, domid);
4727 return 0;
4730 int main_tmem_destroy(int argc, char **argv)
4732 char *dom = NULL;
4733 int all = 0;
4734 int opt;
4736 while ((opt = getopt(argc, argv, "ah")) != -1) {
4737 switch (opt) {
4738 case 'a':
4739 all = 1;
4740 break;
4741 case 'h':
4742 help("tmem-destroy");
4743 return 0;
4744 default:
4745 fprintf(stderr, "option `%c' not supported.\n", opt);
4746 break;
4750 dom = argv[optind];
4751 if (!dom && all == 0) {
4752 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4753 help("tmem-destroy");
4754 return 1;
4757 if (all)
4758 domid = -1;
4759 else
4760 find_domain(dom);
4762 libxl_tmem_destroy(&ctx, domid);
4763 return 0;
4766 int main_tmem_thaw(int argc, char **argv)
4768 char *dom = NULL;
4769 int all = 0;
4770 int opt;
4772 while ((opt = getopt(argc, argv, "ah")) != -1) {
4773 switch (opt) {
4774 case 'a':
4775 all = 1;
4776 break;
4777 case 'h':
4778 help("tmem-thaw");
4779 return 0;
4780 default:
4781 fprintf(stderr, "option `%c' not supported.\n", opt);
4782 break;
4786 dom = argv[optind];
4787 if (!dom && all == 0) {
4788 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4789 help("tmem-thaw");
4790 return 1;
4793 if (all)
4794 domid = -1;
4795 else
4796 find_domain(dom);
4798 libxl_tmem_thaw(&ctx, domid);
4799 return 0;
4802 int main_tmem_set(int argc, char **argv)
4804 char *dom = NULL;
4805 uint32_t weight = 0, cap = 0, compress = 0;
4806 int opt_w = 0, opt_c = 0, opt_p = 0;
4807 int all = 0;
4808 int opt;
4810 while ((opt = getopt(argc, argv, "aw:c:p:h")) != -1) {
4811 switch (opt) {
4812 case 'a':
4813 all = 1;
4814 break;
4815 case 'w':
4816 weight = strtol(optarg, NULL, 10);
4817 opt_w = 1;
4818 break;
4819 case 'c':
4820 cap = strtol(optarg, NULL, 10);
4821 opt_c = 1;
4822 break;
4823 case 'p':
4824 compress = strtol(optarg, NULL, 10);
4825 opt_p = 1;
4826 break;
4827 case 'h':
4828 help("tmem-set");
4829 return 0;
4830 default:
4831 fprintf(stderr, "option `%c' not supported.\n", opt);
4832 break;
4836 dom = argv[optind];
4837 if (!dom && all == 0) {
4838 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4839 help("tmem-set");
4840 return 1;
4843 if (all)
4844 domid = -1;
4845 else
4846 find_domain(dom);
4848 if (!opt_w && !opt_c && !opt_p) {
4849 fprintf(stderr, "No set value specified.\n\n");
4850 help("tmem-set");
4851 return 1;
4854 if (opt_w)
4855 libxl_tmem_set(&ctx, domid, "weight", weight);
4856 if (opt_c)
4857 libxl_tmem_set(&ctx, domid, "cap", cap);
4858 if (opt_p)
4859 libxl_tmem_set(&ctx, domid, "compress", compress);
4861 return 0;
4864 int main_tmem_shared_auth(int argc, char **argv)
4866 char *autharg = NULL;
4867 char *endptr = NULL;
4868 char *dom = NULL;
4869 char *uuid = NULL;
4870 int auth = -1;
4871 int all = 0;
4872 int opt;
4874 while ((opt = getopt(argc, argv, "au:A:h")) != -1) {
4875 switch (opt) {
4876 case 'a':
4877 all = 1;
4878 break;
4879 case 'u':
4880 uuid = optarg;
4881 break;
4882 case 'A':
4883 autharg = optarg;
4884 break;
4885 case 'h':
4886 help("tmem-shared-auth");
4887 return 0;
4888 default:
4889 fprintf(stderr, "option `%c' not supported.\n", opt);
4890 break;
4894 dom = argv[optind];
4895 if (!dom && all == 0) {
4896 fprintf(stderr, "You must specify -a or a domain id.\n\n");
4897 help("tmem-shared-auth");
4898 return 1;
4901 if (all)
4902 domid = -1;
4903 else
4904 find_domain(dom);
4906 if (uuid == NULL || autharg == NULL) {
4907 fprintf(stderr, "No uuid or auth specified.\n\n");
4908 help("tmem-shared-auth");
4909 return 1;
4912 auth = strtol(autharg, &endptr, 10);
4913 if (*endptr != '\0') {
4914 fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
4915 return 1;
4918 libxl_tmem_shared_auth(&ctx, domid, uuid, auth);
4920 return 0;
4923 int main_tmem_freeable(int argc, char **argv)
4925 int opt;
4926 int mb;
4928 while ((opt = getopt(argc, argv, "h")) != -1) {
4929 switch (opt) {
4930 case 'h':
4931 help("tmem-freeable");
4932 return 0;
4933 default:
4934 fprintf(stderr, "option `%c' not supported.\n", opt);
4935 break;
4939 mb = libxl_tmem_freeable(&ctx);
4940 if (mb == -1)
4941 return -1;
4943 printf("%d\n", mb);
4944 return 0;