Stefano Stabellini
2010-Aug-13 18:52 UTC
[Xen-devel] [PATCH 2 of 4] multiconsole support in xenconsole, xenconsoled and libxl
multiple consoles support in xenconsole, xenconsoled and libxl This patch implements the new protocol for handling pv consoles and emulated serials as described in the document docs/misc/console.txt. The changes are: - xenconsoled: do not write the pty under serial in xenstore if xenconsoled is handling a consolepath; - xenconsole: implement support for an explicit console type parameter; the parameter can be "pv", to specify that the user wants to connect to a pv console, or "serial", to specify that the user wants to connect to an emulated serial. If the type parameter hasn''t been specified be the user, xenconsole tries to guess which type of console it has to connect to, defaulting to pv console for pv guests and emulated serial for hvm guests. - xenconsole: use the new xenstore paths; - libxl: rename libxl_console_constype to libxl_console_consback: constype is used to to specify whether qemu or xenconsoled provides the backend, so I renamed it to libxl_console_consback to make it more obvious that we are talking about backends; - libxl: add a new libxl_console_constype to specify if the console is an emulated serial or a pv console; - libxl: support the new xenconsole "type" command line parameter; - libxl: use the "output" node under console in xenstore to tell qemu where do we want the output of this pv console to go; Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- diff -r 5e922670db68 docs/misc/console.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/misc/console.txt Fri Aug 13 19:41:01 2010 +0100 @@ -0,0 +1,91 @@ +Xen PV Console notes +------------------------------------------------------------------------ + Stefano Stabellini + stefano.stabellini@eu.citrix.com + + +Xen traditionally provided a single pv console to pv guests, storing the +relevant information in xenstore under /local/domain/$DOMID/console. + +Now many years after the introduction of the pv console we have +multiple pv consoles support for pv and hvm guests; multiple pv +console backends (qemu and xenconsoled) and emulated serial cards too. + +This document tries to describe how the whole system works and how the +different components interact with each others. + +The first PV console path in xenstore remains: + +/local/domain/$DOMID/console + +the other PV consoles follow the conventional xenstore device path and +live in: + +/local/domain/$DOMID/device/console/$DEVID. + +The output of a PV console, whether it should be a file, a pty, a +socket, or something else, is specified by the toolstack in the xenstore +node "output", under the relevant console section. +For example: + +# xenstore-read /local/domain/26/device/console/1/output +pty + +The backend chosen for a particular console is specified by the +toolstack in the "type" node on xenstore, under the relevant console +section. +For example: + +# xenstore-read /local/domain/26/console/type +xenconsoled + +The supported values are only xenconsoled or ioemu; xenconsoled has +several limitations: it can only be used for the first PV console and it +can only have a pty as output. + +If the output is a pty, backends write the device name to the "tty" node +in xenstore under the relevant console path. + +Emulated serials are provided by qemu-dm only to hvm guests; the number +of emulated serials depends on how many "-serial" command line options +are given to qemu. The output of a serial is specified as argument to +the -serial command line option to qemu. Qemu writes the tty name to +xenstore in the following path: + +/local/domain/$DOMID/serial/$SERIAL_NUM/tty + + +xenconsole is the tool to connect to a PV console or an emulated serial +that has a pty as output. Xenconsole takes a domid as parameter plus an +optional console type (pv for PV consoles or serial for emulated +serials) and console number. Depending on the type and console +number, xenconsole will look for the tty node in different xenstore +paths, as described above. If the user doesn''t specify the console type +xenconsole will try to guess: if the guest is a pv guest it defaults to +PV console, if the guest is an hvm guest it defaults to emulated serial. + +By default xl creates a pv console for hvm guests, plus an emulated +serial if the user specified ''serial = "pty"'' in the VM config file. +Considering that xenconsole defaults to emulated serials for hvm guests, +executing xl create -c "domain" causes xenconsole to attach to the +emulated serial tty. This is most probably what the user wanted because +currently no bootloaders support xen pv consoles so the only way to +interact with a bootloader like grub over a console is to use the +emulated serial. +However the pv console is still easy to use with Linux PV on HVM guests: +the user just need to pass "console=hvc0" to the kernel command line and +then execute "xl console -t pv <domain>" to connect to it. + +When using stubdoms the serial cards are still emulated by qemu (this +time running in the stubdom), the number of serial cards and where the +output goes is still specified using qemu command line options. +The difference is that for each emulated serial card there must be a pv +console connection between the stubdom and dom0 to export the serial +output from the stubdom to dom0. The pv console backend for stubdom''s pv +consoles is always ioemu because multiple pv consoles support is a +requirement in this case, considering that minios has its own pv console +too. In order to simplify the setup when using stubdoms the hvm guest +can only have one pv console with xenstored as backend (the stubdom +could provide pv console backends to the hvm guest but then it would +need another pv console connection for each console backend to export +the pty to dom0). diff -r 5e922670db68 tools/console/client/main.c --- a/tools/console/client/main.c Fri Aug 13 19:29:44 2010 +0100 +++ b/tools/console/client/main.c Fri Aug 13 19:41:01 2010 +0100 @@ -40,6 +40,7 @@ #endif #include "xs.h" +#include "xenctrl.h" #define ESCAPE_CHARACTER 0x1d @@ -254,6 +255,12 @@ static int console_loop(int fd, struct x return 0; } +typedef enum { + CONSOLE_INVAL, + CONSOLE_PV, + CONSOLE_SERIAL, +} console_type; + int main(int argc, char **argv) { struct termios attr; @@ -263,6 +270,7 @@ int main(int argc, char **argv) unsigned int num = 0; int opt_ind=0; struct option lopt[] = { + { "type", 1, 0, ''t'' }, { "num", 1, 0, ''n'' }, { "help", 0, 0, ''h'' }, { 0 }, @@ -272,6 +280,7 @@ int main(int argc, char **argv) int spty, xsfd; struct xs_handle *xs; char *end; + console_type type = CONSOLE_INVAL; while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch(ch) { @@ -282,6 +291,17 @@ int main(int argc, char **argv) case ''n'': num = atoi(optarg); break; + case ''t'': + if (!strcmp(optarg, "serial")) + type = CONSOLE_SERIAL; + else if (!strcmp(optarg, "pv")) + type = CONSOLE_PV; + else { + fprintf(stderr, "Invalid type argument\n"); + fprintf(stderr, "Console types supported are: serial, pv\n"); + exit(EINVAL); + } + break; default: fprintf(stderr, "Invalid argument\n"); fprintf(stderr, "Try `%s --help'' for more information.\n", @@ -314,10 +334,30 @@ int main(int argc, char **argv) dom_path = xs_get_domain_path(xs, domid); if (dom_path == NULL) err(errno, "xs_get_domain_path()"); - path = malloc(strlen(dom_path) + strlen("/serial/0/tty") + 5); + if (type == CONSOLE_INVAL) { + xc_dominfo_t xcinfo; + xc_interface *xc_handle = xc_interface_open(0,0,0); + if (xc_handle == NULL) + err(errno, "Could not open xc interface"); + xc_domain_getinfo(xc_handle, domid, 1, &xcinfo); + /* default to pv console for pv guests and serial for hvm guests */ + if (xcinfo.hvm) + type = CONSOLE_SERIAL; + else + type = CONSOLE_PV; + xc_interface_close(xc_handle); + } + path = malloc(strlen(dom_path) + strlen("/device/console/0/tty") + 5); if (path == NULL) err(ENOMEM, "malloc"); - snprintf(path, strlen(dom_path) + strlen("/serial/0/tty") + 5, "%s/serial/%d/tty", dom_path, num); + if (type == CONSOLE_SERIAL) + snprintf(path, strlen(dom_path) + strlen("/serial/0/tty") + 5, "%s/serial/%d/tty", dom_path, num); + else { + if (num == 0) + snprintf(path, strlen(dom_path) + strlen("/console/tty") + 1, "%s/console/tty", dom_path); + else + snprintf(path, strlen(dom_path) + strlen("/device/console/%d/tty") + 5, "%s/device/console/%d/tty", dom_path, num); + } /* FIXME consoled currently does not assume domain-0 doesn''t have a console which is good when we break domain-0 up. To keep us diff -r 5e922670db68 tools/console/daemon/io.c --- a/tools/console/daemon/io.c Fri Aug 13 19:29:44 2010 +0100 +++ b/tools/console/daemon/io.c Fri Aug 13 19:41:01 2010 +0100 @@ -451,27 +451,6 @@ static int domain_create_tty(struct doma free(data); } free(path); - } - - success = asprintf(&path, "%s/limit", dom->serialpath) != -1; - if (!success) - goto out; - data = xs_read(xs, XBT_NULL, path, &len); - if (data) { - dom->buffer.max_capacity = strtoul(data, 0, 0); - free(data); - } - free(path); - - success = asprintf(&path, "%s/tty", dom->serialpath) != -1; - if (!success) - goto out; - success = xs_write(xs, XBT_NULL, path, slave, strlen(slave)); - free(path); - if (!success) - goto out; - - if (dom->use_consolepath) { success = (asprintf(&path, "%s/tty", dom->conspath) != -1); if (!success) goto out; @@ -479,6 +458,23 @@ static int domain_create_tty(struct doma free(path); if (!success) goto out; + } else { + success = asprintf(&path, "%s/limit", dom->serialpath) != -1; + if (!success) + goto out; + data = xs_read(xs, XBT_NULL, path, &len); + if (data) { + dom->buffer.max_capacity = strtoul(data, 0, 0); + free(data); + } + free(path); + success = asprintf(&path, "%s/tty", dom->serialpath) != -1; + if (!success) + goto out; + success = xs_write(xs, XBT_NULL, path, slave, strlen(slave)); + free(path); + if (!success) + goto out; } if (fcntl(dom->master_fd, F_SETFL, O_NONBLOCK) == -1) diff -r 5e922670db68 tools/libxl/libxl.c --- a/tools/libxl/libxl.c Fri Aug 13 19:29:44 2010 +0100 +++ b/tools/libxl/libxl.c Fri Aug 13 19:41:01 2010 +0100 @@ -951,13 +951,20 @@ out: return 0; } -int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num) +int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_constype type) { libxl_gc gc = LIBXL_INIT_GC(ctx); char *p = libxl_sprintf(&gc, "%s/xenconsole", libxl_private_bindir_path()); char *domid_s = libxl_sprintf(&gc, "%d", domid); char *cons_num_s = libxl_sprintf(&gc, "%d", cons_num); - execl(p, p, domid_s, "--num", cons_num_s, (void *)NULL); + char *cons_type_s; + + if (type == LIBXL_CONSTYPE_PV) + cons_type_s = "pv"; + else + cons_type_s = "serial"; + + execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s, (void *)NULL); libxl_free_all(&gc); return ERROR_FAIL; } @@ -966,9 +973,13 @@ int libxl_primary_console_exec(libxl_ctx { uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm); if (stubdomid) - return libxl_console_exec(ctx, stubdomid, 1); - else - return libxl_console_exec(ctx, domid_vm, 0); + return libxl_console_exec(ctx, stubdomid, 1, LIBXL_CONSTYPE_PV); + else { + if (is_hvm(ctx, domid_vm)) + return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_SERIAL); + else + return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_PV); + } } int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass) @@ -1539,15 +1550,22 @@ retry_transaction: for (i = 0; i < num_console; i++) { console[i].devid = i; - console[i].constype = CONSTYPE_IOEMU; + console[i].consback = LIBXL_CONSBACK_IOEMU; console[i].domid = domid; - if (!i) + if (!i) { + char *filename; + char *name = libxl_sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid)); + libxl_create_logfile(ctx, name, &filename); + console[i].output = libxl_sprintf(&gc, "file:%s", filename); console[i].build_state = &state; + free(filename); + } else + console[i].output = "pty"; ret = libxl_device_console_add(ctx, domid, &console[i]); if (ret) goto out_free; } - if (libxl_create_xenpv_qemu(ctx, vfb, num_console, console, &dm_starting) < 0) { + if (libxl_create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) { ret = ERROR_FAIL; goto out_free; } @@ -2289,7 +2307,7 @@ int libxl_device_console_add(libxl_ctx * if (console->build_state) { xs_transaction_t t; - char **ents = (char **) libxl_calloc(&gc, 9, sizeof(char *)); + char **ents = (char **) libxl_calloc(&gc, 11, sizeof(char *)); ents[0] = "console/port"; ents[1] = libxl_sprintf(&gc, "%"PRIu32, console->build_state->console_port); ents[2] = "console/ring-ref"; @@ -2297,10 +2315,12 @@ int libxl_device_console_add(libxl_ctx * ents[4] = "console/limit"; ents[5] = libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT); ents[6] = "console/type"; - if (console->constype == CONSTYPE_XENCONSOLED) + if (console->consback == LIBXL_CONSBACK_XENCONSOLED) ents[7] = "xenconsoled"; else ents[7] = "ioemu"; + ents[8] = "console/output"; + ents[9] = console->output; retry_transaction: t = xs_transaction_start(ctx->xsh); libxl_xs_writev(&gc, t, libxl_xs_get_dompath(&gc, console->domid), ents); @@ -2338,19 +2358,25 @@ retry_transaction: flexarray_set(back, boffset++, "protocol"); flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL); - flexarray_set(front, foffset++, "backend-id"); - flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", console->backend_domid)); - flexarray_set(front, foffset++, "state"); - flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1)); - flexarray_set(front, foffset++, "limit"); - flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT)); - flexarray_set(front, foffset++, "protocol"); - flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL); - flexarray_set(front, foffset++, "type"); - if (console->constype == CONSTYPE_XENCONSOLED) - flexarray_set(front, foffset++, "xenconsoled"); - else - flexarray_set(front, foffset++, "ioemu"); + /* if devid == 0 do not add the frontend to device/console/ because + * it has already been added to console/ */ + if (device.devid > 0) { + flexarray_set(front, foffset++, "backend-id"); + flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", console->backend_domid)); + flexarray_set(front, foffset++, "state"); + flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1)); + flexarray_set(front, foffset++, "limit"); + flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT)); + flexarray_set(front, foffset++, "protocol"); + flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL); + flexarray_set(front, foffset++, "type"); + if (console->consback == LIBXL_CONSBACK_XENCONSOLED) + flexarray_set(front, foffset++, "xenconsoled"); + else + flexarray_set(front, foffset++, "ioemu"); + flexarray_set(front, foffset++, "output"); + flexarray_set(front, foffset++, console->output); + } libxl_device_generic_add(ctx, &device, libxl_xs_kvs_of_flexarray(&gc, back, boffset), @@ -2558,13 +2584,11 @@ int libxl_cdrom_insert(libxl_ctx *ctx, u /******************************************************************************/ static int libxl_build_xenpv_qemu_args(libxl_gc *gc, + uint32_t domid, libxl_device_vfb *vfb, - int num_console, - libxl_device_console *console, libxl_device_model_info *info) { libxl_ctx *ctx = libxl_gc_owner(gc); - int i = 0, j = 0, num = 0; memset(info, 0x00, sizeof(libxl_device_model_info)); info->vnc = vfb->vnc; @@ -2578,46 +2602,20 @@ static int libxl_build_xenpv_qemu_args(l info->keymap = libxl_strdup(gc, vfb->keymap); info->sdl = vfb->sdl; info->opengl = vfb->opengl; - for (i = 0; i < num_console; i++) { - if (console->constype == CONSTYPE_IOEMU) - num++; - } - if (num > 0) { - uint32_t guest_domid; - if (libxl_is_stubdom(ctx, vfb->domid, &guest_domid)) { - char *filename; - char *name = libxl_sprintf(gc, "qemu-dm-%s", _libxl_domid_to_name(gc, guest_domid)); - libxl_create_logfile(ctx, name, &filename); - info->serial = libxl_sprintf(gc, "file:%s", filename); - free(filename); - } else { - info->serial = "pty"; - } - num--; - } - if (num > 0) { - info->extra = (char **) libxl_calloc(gc, num * 2 + 1, sizeof(char *)); - for (j = 0; j < num * 2; j = j + 2) { - info->extra[j] = "-serial"; - info->extra[j + 1] = "pty"; - } - info->extra[j] = NULL; - } - info->domid = vfb->domid; - info->dom_name = _libxl_domid_to_name(gc, vfb->domid); + info->domid = domid; + info->dom_name = libxl_domid_to_name(ctx, domid); info->device_model = libxl_abs_path(gc, "qemu-dm", libxl_libexec_path()); info->type = XENPV; return 0; } -int libxl_create_xenpv_qemu(libxl_ctx *ctx, libxl_device_vfb *vfb, - int num_console, libxl_device_console *console, +int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, libxl_device_model_starting **starting_r) { libxl_gc gc = LIBXL_INIT_GC(ctx); libxl_device_model_info info; - libxl_build_xenpv_qemu_args(&gc, vfb, num_console, console, &info); + libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info); libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r); libxl_free_all(&gc); return 0; diff -r 5e922670db68 tools/libxl/libxl.h --- a/tools/libxl/libxl.h Fri Aug 13 19:29:44 2010 +0100 +++ b/tools/libxl/libxl.h Fri Aug 13 19:41:01 2010 +0100 @@ -225,16 +225,22 @@ typedef struct { } libxl_device_vkb; typedef enum { - CONSTYPE_XENCONSOLED, - CONSTYPE_IOEMU, + LIBXL_CONSTYPE_SERIAL, + LIBXL_CONSTYPE_PV, } libxl_console_constype; +typedef enum { + LIBXL_CONSBACK_XENCONSOLED, + LIBXL_CONSBACK_IOEMU, +} libxl_console_consback; + typedef struct { uint32_t backend_domid; uint32_t domid; int devid; - libxl_console_constype constype; + libxl_console_consback consback; libxl_domain_build_state *build_state; + char *output; } libxl_device_console; typedef enum { @@ -432,7 +438,7 @@ int libxl_domain_setmaxmem(libxl_ctx *ct int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce); int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass); -int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num); +int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_constype type); /* libxl_primary_console_exec finds the domid and console number * corresponding to the primary console of the given vm, then calls * libxl_console_exec with the right arguments (domid might be different @@ -454,8 +460,7 @@ int libxl_create_device_model(libxl_ctx libxl_device_disk *disk, int num_disks, libxl_device_nic *vifs, int num_vifs, libxl_device_model_starting **starting_r); -int libxl_create_xenpv_qemu(libxl_ctx *ctx, libxl_device_vfb *vfb, - int num_console, libxl_device_console *console, +int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, libxl_device_model_starting **starting_r); /* Caller must either: pass starting_r==0, or on successful * return pass *starting_r (which will be non-0) to diff -r 5e922670db68 tools/libxl/xl_cmdimpl.c --- a/tools/libxl/xl_cmdimpl.c Fri Aug 13 19:29:44 2010 +0100 +++ b/tools/libxl/xl_cmdimpl.c Fri Aug 13 19:41:01 2010 +0100 @@ -370,7 +370,8 @@ static void init_console_info(libxl_devi { memset(console, 0x00, sizeof(libxl_device_console)); console->devid = dev_num; - console->constype = CONSTYPE_XENCONSOLED; + console->consback = LIBXL_CONSBACK_XENCONSOLED; + console->output = "pty"; if (state) console->build_state = state; } @@ -1456,10 +1457,10 @@ start: init_console_info(&console, 0, &state); console.domid = domid; if (d_config.num_vfbs) - console.constype = CONSTYPE_IOEMU; + console.consback = LIBXL_CONSBACK_IOEMU; libxl_device_console_add(&ctx, domid, &console); if (d_config.num_vfbs) - libxl_create_xenpv_qemu(&ctx, d_config.vfbs, 1, &console, &dm_starting); + libxl_create_xenpv_qemu(&ctx, domid, d_config.vfbs, &dm_starting); } if (dm_starting) @@ -1854,13 +1855,27 @@ int main_cd_insert(int argc, char **argv int main_console(int argc, char **argv) { - int opt = 0; - - while ((opt = getopt(argc, argv, "hn:")) != -1) { + int opt = 0, num = 0; + libxl_console_constype type = -1; + + while ((opt = getopt(argc, argv, "hn:t:")) != -1) { switch (opt) { case ''h'': help("console"); return 0; + case ''t'': + if (!strcmp(optarg, "pv")) + type = LIBXL_CONSTYPE_PV; + else if (!strcmp(optarg, "serial")) + type = LIBXL_CONSTYPE_SERIAL; + else { + fprintf(stderr, "console type supported are: pv, serial\n"); + return 2; + } + break; + case ''n'': + num = atoi(optarg); + break; default: fprintf(stderr, "option not supported\n"); break; @@ -1872,7 +1887,10 @@ int main_console(int argc, char **argv) } find_domain(argv[optind]); - libxl_primary_console_exec(&ctx, domid); + if (type <= 0 && num == 0) + libxl_primary_console_exec(&ctx, domid); + else + libxl_console_exec(&ctx, domid, num, type); fprintf(stderr, "Unable to attach console\n"); return 1; } diff -r 5e922670db68 tools/libxl/xl_cmdtable.c --- a/tools/libxl/xl_cmdtable.c Fri Aug 13 19:29:44 2010 +0100 +++ b/tools/libxl/xl_cmdtable.c Fri Aug 13 19:41:01 2010 +0100 @@ -86,7 +86,9 @@ struct cmd_spec cmd_table[] = { { "console", &main_console, "Attach to domain''s console", - "<Domain>", + "[options] <Domain>\n" + "-t <type> console type, pv or serial\n" + "-n <number> console number" }, { "vncviewer", &main_vncviewer, diff -r 5e922670db68 tools/ocaml/libs/xl/xl_stubs.c --- a/tools/ocaml/libs/xl/xl_stubs.c Fri Aug 13 19:29:44 2010 +0100 +++ b/tools/ocaml/libs/xl/xl_stubs.c Fri Aug 13 19:41:01 2010 +0100 @@ -232,7 +232,7 @@ static int device_console_val(caml_gc *g c_val->backend_domid = Int_val(Field(v, 0)); c_val->devid = Int_val(Field(v, 1)); - c_val->constype = (Int_val(Field(v, 2))) + CONSTYPE_XENCONSOLED; + c_val->consback = (Int_val(Field(v, 2))) + LIBXL_CONSBACK_XENCONSOLED; CAMLreturn(0); } _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Stefano Stabellini
2010-Aug-16 11:36 UTC
Re: [Xen-devel] [PATCH 2 of 4] multiconsole support in xenconsole, xenconsoled and libxl
On Fri, 13 Aug 2010, Stefano Stabellini wrote:> multiple consoles support in xenconsole, xenconsoled and libxl > > This patch implements the new protocol for handling pv consoles and > emulated serials as described in the document docs/misc/console.txt. > > The changes are: > > - xenconsoled: do not write the pty under serial in xenstore if > xenconsoled is handling a consolepath; > > - xenconsole: implement support for an explicit console type parameter; > the parameter can be "pv", to specify that the user wants to > connect to a pv console, or "serial", to specify that the user wants to > connect to an emulated serial. If the type parameter hasn''t been > specified be the user, xenconsole tries to guess which type of console > it has to connect to, defaulting to pv console for pv guests and > emulated serial for hvm guests. > > - xenconsole: use the new xenstore paths; > > - libxl: rename libxl_console_constype to libxl_console_consback: > constype is used to to specify whether qemu or xenconsoled provides the > backend, so I renamed it to libxl_console_consback to make it more > obvious that we are talking about backends; > > - libxl: add a new libxl_console_constype to specify if the console is > an emulated serial or a pv console; > > - libxl: support the new xenconsole "type" command line parameter; > > - libxl: use the "output" node under console in xenstore to tell qemu > where do we want the output of this pv console to go; > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >this patch didn''t apply cleanly to xen-unstable tip: I am appending a rebased version of the patch with one additional change: - remove the legacy "serialpath" from xenconsoled altogether Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- diff -r a55625b65336 docs/misc/console.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/misc/console.txt Mon Aug 16 12:32:58 2010 +0100 @@ -0,0 +1,91 @@ +Xen PV Console notes +------------------------------------------------------------------------ + Stefano Stabellini + stefano.stabellini@eu.citrix.com + + +Xen traditionally provided a single pv console to pv guests, storing the +relevant information in xenstore under /local/domain/$DOMID/console. + +Now many years after the introduction of the pv console we have +multiple pv consoles support for pv and hvm guests; multiple pv +console backends (qemu and xenconsoled) and emulated serial cards too. + +This document tries to describe how the whole system works and how the +different components interact with each others. + +The first PV console path in xenstore remains: + +/local/domain/$DOMID/console + +the other PV consoles follow the conventional xenstore device path and +live in: + +/local/domain/$DOMID/device/console/$DEVID. + +The output of a PV console, whether it should be a file, a pty, a +socket, or something else, is specified by the toolstack in the xenstore +node "output", under the relevant console section. +For example: + +# xenstore-read /local/domain/26/device/console/1/output +pty + +The backend chosen for a particular console is specified by the +toolstack in the "type" node on xenstore, under the relevant console +section. +For example: + +# xenstore-read /local/domain/26/console/type +xenconsoled + +The supported values are only xenconsoled or ioemu; xenconsoled has +several limitations: it can only be used for the first PV console and it +can only have a pty as output. + +If the output is a pty, backends write the device name to the "tty" node +in xenstore under the relevant console path. + +Emulated serials are provided by qemu-dm only to hvm guests; the number +of emulated serials depends on how many "-serial" command line options +are given to qemu. The output of a serial is specified as argument to +the -serial command line option to qemu. Qemu writes the tty name to +xenstore in the following path: + +/local/domain/$DOMID/serial/$SERIAL_NUM/tty + + +xenconsole is the tool to connect to a PV console or an emulated serial +that has a pty as output. Xenconsole takes a domid as parameter plus an +optional console type (pv for PV consoles or serial for emulated +serials) and console number. Depending on the type and console +number, xenconsole will look for the tty node in different xenstore +paths, as described above. If the user doesn''t specify the console type +xenconsole will try to guess: if the guest is a pv guest it defaults to +PV console, if the guest is an hvm guest it defaults to emulated serial. + +By default xl creates a pv console for hvm guests, plus an emulated +serial if the user specified ''serial = "pty"'' in the VM config file. +Considering that xenconsole defaults to emulated serials for hvm guests, +executing xl create -c "domain" causes xenconsole to attach to the +emulated serial tty. This is most probably what the user wanted because +currently no bootloaders support xen pv consoles so the only way to +interact with a bootloader like grub over a console is to use the +emulated serial. +However the pv console is still easy to use with Linux PV on HVM guests: +the user just need to pass "console=hvc0" to the kernel command line and +then execute "xl console -t pv <domain>" to connect to it. + +When using stubdoms the serial cards are still emulated by qemu (this +time running in the stubdom), the number of serial cards and where the +output goes is still specified using qemu command line options. +The difference is that for each emulated serial card there must be a pv +console connection between the stubdom and dom0 to export the serial +output from the stubdom to dom0. The pv console backend for stubdom''s pv +consoles is always ioemu because multiple pv consoles support is a +requirement in this case, considering that minios has its own pv console +too. In order to simplify the setup when using stubdoms the hvm guest +can only have one pv console with xenstored as backend (the stubdom +could provide pv console backends to the hvm guest but then it would +need another pv console connection for each console backend to export +the pty to dom0). diff -r a55625b65336 tools/console/client/main.c --- a/tools/console/client/main.c Mon Aug 16 09:54:02 2010 +0100 +++ b/tools/console/client/main.c Mon Aug 16 12:32:58 2010 +0100 @@ -40,6 +40,7 @@ #endif #include "xs.h" +#include "xenctrl.h" #define ESCAPE_CHARACTER 0x1d @@ -254,6 +255,12 @@ static int console_loop(int fd, struct x return 0; } +typedef enum { + CONSOLE_INVAL, + CONSOLE_PV, + CONSOLE_SERIAL, +} console_type; + int main(int argc, char **argv) { struct termios attr; @@ -263,6 +270,7 @@ int main(int argc, char **argv) unsigned int num = 0; int opt_ind=0; struct option lopt[] = { + { "type", 1, 0, ''t'' }, { "num", 1, 0, ''n'' }, { "help", 0, 0, ''h'' }, { 0 }, @@ -272,6 +280,7 @@ int main(int argc, char **argv) int spty, xsfd; struct xs_handle *xs; char *end; + console_type type = CONSOLE_INVAL; while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch(ch) { @@ -282,6 +291,17 @@ int main(int argc, char **argv) case ''n'': num = atoi(optarg); break; + case ''t'': + if (!strcmp(optarg, "serial")) + type = CONSOLE_SERIAL; + else if (!strcmp(optarg, "pv")) + type = CONSOLE_PV; + else { + fprintf(stderr, "Invalid type argument\n"); + fprintf(stderr, "Console types supported are: serial, pv\n"); + exit(EINVAL); + } + break; default: fprintf(stderr, "Invalid argument\n"); fprintf(stderr, "Try `%s --help'' for more information.\n", @@ -314,10 +334,30 @@ int main(int argc, char **argv) dom_path = xs_get_domain_path(xs, domid); if (dom_path == NULL) err(errno, "xs_get_domain_path()"); - path = malloc(strlen(dom_path) + strlen("/serial/0/tty") + 5); + if (type == CONSOLE_INVAL) { + xc_dominfo_t xcinfo; + xc_interface *xc_handle = xc_interface_open(0,0,0); + if (xc_handle == NULL) + err(errno, "Could not open xc interface"); + xc_domain_getinfo(xc_handle, domid, 1, &xcinfo); + /* default to pv console for pv guests and serial for hvm guests */ + if (xcinfo.hvm) + type = CONSOLE_SERIAL; + else + type = CONSOLE_PV; + xc_interface_close(xc_handle); + } + path = malloc(strlen(dom_path) + strlen("/device/console/0/tty") + 5); if (path == NULL) err(ENOMEM, "malloc"); - snprintf(path, strlen(dom_path) + strlen("/serial/0/tty") + 5, "%s/serial/%d/tty", dom_path, num); + if (type == CONSOLE_SERIAL) + snprintf(path, strlen(dom_path) + strlen("/serial/0/tty") + 5, "%s/serial/%d/tty", dom_path, num); + else { + if (num == 0) + snprintf(path, strlen(dom_path) + strlen("/console/tty") + 1, "%s/console/tty", dom_path); + else + snprintf(path, strlen(dom_path) + strlen("/device/console/%d/tty") + 5, "%s/device/console/%d/tty", dom_path, num); + } /* FIXME consoled currently does not assume domain-0 doesn''t have a console which is good when we break domain-0 up. To keep us diff -r a55625b65336 tools/console/daemon/io.c --- a/tools/console/daemon/io.c Mon Aug 16 09:54:02 2010 +0100 +++ b/tools/console/daemon/io.c Mon Aug 16 12:32:58 2010 +0100 @@ -87,8 +87,6 @@ struct domain { struct buffer buffer; struct domain *next; char *conspath; - char *serialpath; - int use_consolepath; int ring_ref; evtchn_port_or_error_t local_port; evtchn_port_or_error_t remote_port; @@ -440,20 +438,8 @@ static int domain_create_tty(struct doma goto out; } - if (dom->use_consolepath) { - success = asprintf(&path, "%s/limit", dom->conspath) !- -1; - if (!success) - goto out; - data = xs_read(xs, XBT_NULL, path, &len); - if (data) { - dom->buffer.max_capacity = strtoul(data, 0, 0); - free(data); - } - free(path); - } - - success = asprintf(&path, "%s/limit", dom->serialpath) != -1; + success = asprintf(&path, "%s/limit", dom->conspath) !+ -1; if (!success) goto out; data = xs_read(xs, XBT_NULL, path, &len); @@ -463,7 +449,7 @@ static int domain_create_tty(struct doma } free(path); - success = asprintf(&path, "%s/tty", dom->serialpath) != -1; + success = (asprintf(&path, "%s/tty", dom->conspath) != -1); if (!success) goto out; success = xs_write(xs, XBT_NULL, path, slave, strlen(slave)); @@ -471,16 +457,6 @@ static int domain_create_tty(struct doma if (!success) goto out; - if (dom->use_consolepath) { - success = (asprintf(&path, "%s/tty", dom->conspath) != -1); - if (!success) - goto out; - success = xs_write(xs, XBT_NULL, path, slave, strlen(slave)); - free(path); - if (!success) - goto out; - } - if (fcntl(dom->master_fd, F_SETFL, O_NONBLOCK) == -1) goto out; @@ -524,29 +500,20 @@ static int xs_gather(struct xs_handle *x va_end(ap); return ret; } - + static int domain_create_ring(struct domain *dom) { int err, remote_port, ring_ref, rc; char *type, path[PATH_MAX]; - err = xs_gather(xs, dom->serialpath, + err = xs_gather(xs, dom->conspath, "ring-ref", "%u", &ring_ref, "port", "%i", &remote_port, NULL); - if (err) { - err = xs_gather(xs, dom->conspath, - "ring-ref", "%u", &ring_ref, - "port", "%i", &remote_port, - NULL); - if (err) - goto out; - dom->use_consolepath = 1; - } else - dom->use_consolepath = 0; + if (err) + goto out; - snprintf(path, sizeof(path), "%s/type", - dom->use_consolepath ? dom->conspath: dom->serialpath); + snprintf(path, sizeof(path), "%s/type", dom->conspath); type = xs_read(xs, XBT_NULL, path, NULL); if (type && strcmp(type, "xenconsoled") != 0) { free(type); @@ -628,16 +595,12 @@ static bool watch_domain(struct domain * snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid); if (watch) { - success = xs_watch(xs, dom->serialpath, domid_str); - if (success) { - success = xs_watch(xs, dom->conspath, domid_str); - if (success) - domain_create_ring(dom); - else - xs_unwatch(xs, dom->serialpath, domid_str); - } + success = xs_watch(xs, dom->conspath, domid_str); + if (success) + domain_create_ring(dom); + else + xs_unwatch(xs, dom->conspath, domid_str); } else { - success = xs_unwatch(xs, dom->serialpath, domid_str); success = xs_unwatch(xs, dom->conspath, domid_str); } @@ -666,14 +629,6 @@ static struct domain *create_domain(int dom->domid = domid; - dom->serialpath = xs_get_domain_path(xs, dom->domid); - s = realloc(dom->serialpath, strlen(dom->serialpath) + - strlen("/serial/0") + 1); - if (s == NULL) - goto out; - dom->serialpath = s; - strcat(dom->serialpath, "/serial/0"); - dom->conspath = xs_get_domain_path(xs, dom->domid); s = realloc(dom->conspath, strlen(dom->conspath) + strlen("/console") + 1); @@ -712,7 +667,6 @@ static struct domain *create_domain(int return dom; out: - free(dom->serialpath); free(dom->conspath); free(dom); return NULL; @@ -755,9 +709,6 @@ static void cleanup_domain(struct domain free(d->buffer.data); d->buffer.data = NULL; - free(d->serialpath); - d->serialpath = NULL; - free(d->conspath); d->conspath = NULL; diff -r a55625b65336 tools/libxl/libxl.c --- a/tools/libxl/libxl.c Mon Aug 16 09:54:02 2010 +0100 +++ b/tools/libxl/libxl.c Mon Aug 16 12:32:58 2010 +0100 @@ -952,13 +952,20 @@ out: return 0; } -int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num) +int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_constype type) { libxl_gc gc = LIBXL_INIT_GC(ctx); char *p = libxl_sprintf(&gc, "%s/xenconsole", libxl_private_bindir_path()); char *domid_s = libxl_sprintf(&gc, "%d", domid); char *cons_num_s = libxl_sprintf(&gc, "%d", cons_num); - execl(p, p, domid_s, "--num", cons_num_s, (void *)NULL); + char *cons_type_s; + + if (type == LIBXL_CONSTYPE_PV) + cons_type_s = "pv"; + else + cons_type_s = "serial"; + + execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s, (void *)NULL); libxl_free_all(&gc); return ERROR_FAIL; } @@ -967,9 +974,13 @@ int libxl_primary_console_exec(libxl_ctx { uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm); if (stubdomid) - return libxl_console_exec(ctx, stubdomid, 1); - else - return libxl_console_exec(ctx, domid_vm, 0); + return libxl_console_exec(ctx, stubdomid, 1, LIBXL_CONSTYPE_PV); + else { + if (is_hvm(ctx, domid_vm)) + return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_SERIAL); + else + return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_PV); + } } int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass) @@ -1540,15 +1551,22 @@ retry_transaction: for (i = 0; i < num_console; i++) { console[i].devid = i; - console[i].constype = CONSTYPE_IOEMU; + console[i].consback = LIBXL_CONSBACK_IOEMU; console[i].domid = domid; - if (!i) + if (!i) { + char *filename; + char *name = libxl_sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid)); + libxl_create_logfile(ctx, name, &filename); + console[i].output = libxl_sprintf(&gc, "file:%s", filename); console[i].build_state = &state; + free(filename); + } else + console[i].output = "pty"; ret = libxl_device_console_add(ctx, domid, &console[i]); if (ret) goto out_free; } - if (libxl_create_xenpv_qemu(ctx, vfb, num_console, console, &dm_starting) < 0) { + if (libxl_create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) { ret = ERROR_FAIL; goto out_free; } @@ -2290,7 +2308,7 @@ int libxl_device_console_add(libxl_ctx * if (console->build_state) { xs_transaction_t t; - char **ents = (char **) libxl_calloc(&gc, 9, sizeof(char *)); + char **ents = (char **) libxl_calloc(&gc, 11, sizeof(char *)); ents[0] = "console/port"; ents[1] = libxl_sprintf(&gc, "%"PRIu32, console->build_state->console_port); ents[2] = "console/ring-ref"; @@ -2298,10 +2316,12 @@ int libxl_device_console_add(libxl_ctx * ents[4] = "console/limit"; ents[5] = libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT); ents[6] = "console/type"; - if (console->constype == CONSTYPE_XENCONSOLED) + if (console->consback == LIBXL_CONSBACK_XENCONSOLED) ents[7] = "xenconsoled"; else ents[7] = "ioemu"; + ents[8] = "console/output"; + ents[9] = console->output; retry_transaction: t = xs_transaction_start(ctx->xsh); libxl_xs_writev(&gc, t, libxl_xs_get_dompath(&gc, console->domid), ents); @@ -2339,19 +2359,25 @@ retry_transaction: flexarray_set(back, boffset++, "protocol"); flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL); - flexarray_set(front, foffset++, "backend-id"); - flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", console->backend_domid)); - flexarray_set(front, foffset++, "state"); - flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1)); - flexarray_set(front, foffset++, "limit"); - flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT)); - flexarray_set(front, foffset++, "protocol"); - flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL); - flexarray_set(front, foffset++, "type"); - if (console->constype == CONSTYPE_XENCONSOLED) - flexarray_set(front, foffset++, "xenconsoled"); - else - flexarray_set(front, foffset++, "ioemu"); + /* if devid == 0 do not add the frontend to device/console/ because + * it has already been added to console/ */ + if (device.devid > 0) { + flexarray_set(front, foffset++, "backend-id"); + flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", console->backend_domid)); + flexarray_set(front, foffset++, "state"); + flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1)); + flexarray_set(front, foffset++, "limit"); + flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT)); + flexarray_set(front, foffset++, "protocol"); + flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL); + flexarray_set(front, foffset++, "type"); + if (console->consback == LIBXL_CONSBACK_XENCONSOLED) + flexarray_set(front, foffset++, "xenconsoled"); + else + flexarray_set(front, foffset++, "ioemu"); + flexarray_set(front, foffset++, "output"); + flexarray_set(front, foffset++, console->output); + } libxl_device_generic_add(ctx, &device, libxl_xs_kvs_of_flexarray(&gc, back, boffset), @@ -2559,13 +2585,11 @@ int libxl_cdrom_insert(libxl_ctx *ctx, u /******************************************************************************/ static int libxl_build_xenpv_qemu_args(libxl_gc *gc, + uint32_t domid, libxl_device_vfb *vfb, - int num_console, - libxl_device_console *console, libxl_device_model_info *info) { libxl_ctx *ctx = libxl_gc_owner(gc); - int i = 0, j = 0, num = 0; memset(info, 0x00, sizeof(libxl_device_model_info)); info->vnc = vfb->vnc; @@ -2579,46 +2603,20 @@ static int libxl_build_xenpv_qemu_args(l info->keymap = libxl_strdup(gc, vfb->keymap); info->sdl = vfb->sdl; info->opengl = vfb->opengl; - for (i = 0; i < num_console; i++) { - if (console->constype == CONSTYPE_IOEMU) - num++; - } - if (num > 0) { - uint32_t guest_domid; - if (libxl_is_stubdom(ctx, vfb->domid, &guest_domid)) { - char *filename; - char *name = libxl_sprintf(gc, "qemu-dm-%s", _libxl_domid_to_name(gc, guest_domid)); - libxl_create_logfile(ctx, name, &filename); - info->serial = libxl_sprintf(gc, "file:%s", filename); - free(filename); - } else { - info->serial = "pty"; - } - num--; - } - if (num > 0) { - info->extra = (char **) libxl_calloc(gc, num * 2 + 1, sizeof(char *)); - for (j = 0; j < num * 2; j = j + 2) { - info->extra[j] = "-serial"; - info->extra[j + 1] = "pty"; - } - info->extra[j] = NULL; - } - info->domid = vfb->domid; - info->dom_name = _libxl_domid_to_name(gc, vfb->domid); + info->domid = domid; + info->dom_name = libxl_domid_to_name(ctx, domid); info->device_model = libxl_abs_path(gc, "qemu-dm", libxl_libexec_path()); info->type = XENPV; return 0; } -int libxl_create_xenpv_qemu(libxl_ctx *ctx, libxl_device_vfb *vfb, - int num_console, libxl_device_console *console, +int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, libxl_device_model_starting **starting_r) { libxl_gc gc = LIBXL_INIT_GC(ctx); libxl_device_model_info info; - libxl_build_xenpv_qemu_args(&gc, vfb, num_console, console, &info); + libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info); libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r); libxl_free_all(&gc); return 0; diff -r a55625b65336 tools/libxl/libxl.h --- a/tools/libxl/libxl.h Mon Aug 16 09:54:02 2010 +0100 +++ b/tools/libxl/libxl.h Mon Aug 16 12:32:58 2010 +0100 @@ -335,16 +335,22 @@ typedef struct { } libxl_device_vkb; typedef enum { - CONSTYPE_XENCONSOLED, - CONSTYPE_IOEMU, + LIBXL_CONSTYPE_SERIAL, + LIBXL_CONSTYPE_PV, } libxl_console_constype; +typedef enum { + LIBXL_CONSBACK_XENCONSOLED, + LIBXL_CONSBACK_IOEMU, +} libxl_console_consback; + typedef struct { uint32_t backend_domid; uint32_t domid; int devid; - libxl_console_constype constype; + libxl_console_consback consback; libxl_domain_build_state *build_state; + char *output; } libxl_device_console; typedef enum { @@ -542,7 +548,7 @@ int libxl_domain_setmaxmem(libxl_ctx *ct int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce); int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass); -int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num); +int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_constype type); /* libxl_primary_console_exec finds the domid and console number * corresponding to the primary console of the given vm, then calls * libxl_console_exec with the right arguments (domid might be different @@ -564,8 +570,7 @@ int libxl_create_device_model(libxl_ctx libxl_device_disk *disk, int num_disks, libxl_device_nic *vifs, int num_vifs, libxl_device_model_starting **starting_r); -int libxl_create_xenpv_qemu(libxl_ctx *ctx, libxl_device_vfb *vfb, - int num_console, libxl_device_console *console, +int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, libxl_device_model_starting **starting_r); /* Caller must either: pass starting_r==0, or on successful * return pass *starting_r (which will be non-0) to diff -r a55625b65336 tools/libxl/xl_cmdimpl.c --- a/tools/libxl/xl_cmdimpl.c Mon Aug 16 09:54:02 2010 +0100 +++ b/tools/libxl/xl_cmdimpl.c Mon Aug 16 12:32:58 2010 +0100 @@ -371,7 +371,8 @@ static void init_console_info(libxl_devi { memset(console, 0x00, sizeof(libxl_device_console)); console->devid = dev_num; - console->constype = CONSTYPE_XENCONSOLED; + console->consback = LIBXL_CONSBACK_XENCONSOLED; + console->output = "pty"; if (state) console->build_state = state; } @@ -1457,10 +1458,10 @@ start: init_console_info(&console, 0, &state); console.domid = domid; if (d_config.num_vfbs) - console.constype = CONSTYPE_IOEMU; + console.consback = LIBXL_CONSBACK_IOEMU; libxl_device_console_add(&ctx, domid, &console); if (d_config.num_vfbs) - libxl_create_xenpv_qemu(&ctx, d_config.vfbs, 1, &console, &dm_starting); + libxl_create_xenpv_qemu(&ctx, domid, d_config.vfbs, &dm_starting); } if (dm_starting) @@ -1855,13 +1856,27 @@ int main_cd_insert(int argc, char **argv int main_console(int argc, char **argv) { - int opt = 0; - - while ((opt = getopt(argc, argv, "hn:")) != -1) { + int opt = 0, num = 0; + libxl_console_constype type = -1; + + while ((opt = getopt(argc, argv, "hn:t:")) != -1) { switch (opt) { case ''h'': help("console"); return 0; + case ''t'': + if (!strcmp(optarg, "pv")) + type = LIBXL_CONSTYPE_PV; + else if (!strcmp(optarg, "serial")) + type = LIBXL_CONSTYPE_SERIAL; + else { + fprintf(stderr, "console type supported are: pv, serial\n"); + return 2; + } + break; + case ''n'': + num = atoi(optarg); + break; default: fprintf(stderr, "option not supported\n"); break; @@ -1873,7 +1888,10 @@ int main_console(int argc, char **argv) } find_domain(argv[optind]); - libxl_primary_console_exec(&ctx, domid); + if (type <= 0 && num == 0) + libxl_primary_console_exec(&ctx, domid); + else + libxl_console_exec(&ctx, domid, num, type); fprintf(stderr, "Unable to attach console\n"); return 1; } diff -r a55625b65336 tools/libxl/xl_cmdtable.c --- a/tools/libxl/xl_cmdtable.c Mon Aug 16 09:54:02 2010 +0100 +++ b/tools/libxl/xl_cmdtable.c Mon Aug 16 12:32:58 2010 +0100 @@ -86,7 +86,9 @@ struct cmd_spec cmd_table[] = { { "console", &main_console, "Attach to domain''s console", - "<Domain>", + "[options] <Domain>\n" + "-t <type> console type, pv or serial\n" + "-n <number> console number" }, { "vncviewer", &main_vncviewer, diff -r a55625b65336 tools/ocaml/libs/xl/xl_stubs.c --- a/tools/ocaml/libs/xl/xl_stubs.c Mon Aug 16 09:54:02 2010 +0100 +++ b/tools/ocaml/libs/xl/xl_stubs.c Mon Aug 16 12:32:58 2010 +0100 @@ -232,7 +232,7 @@ static int device_console_val(caml_gc *g c_val->backend_domid = Int_val(Field(v, 0)); c_val->devid = Int_val(Field(v, 1)); - c_val->constype = (Int_val(Field(v, 2))) + CONSTYPE_XENCONSOLED; + c_val->consback = (Int_val(Field(v, 2))) + LIBXL_CONSBACK_XENCONSOLED; CAMLreturn(0); } _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel