X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fguestfs.c;h=bc34f60788a4aae00f072fe363d389343bbe323b;hp=17974fd37a1ffe0800e1a0f74e4f8d8f536a2719;hb=a1c8c3e1be70a821a5e4dfeeee6c78979e587b7a;hpb=bf2f52e9c6f787d3b040083909aa9c11c54873f6 diff --git a/src/guestfs.c b/src/guestfs.c index 17974fd..bc34f60 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -85,8 +85,8 @@ static void close_handles (void); #define UNIX_PATH_MAX 108 /* Also in guestfsd.c */ -#define VMCHANNEL_PORT 6666 -#define VMCHANNEL_ADDR "10.0.2.4" +#define GUESTFWD_PORT 6666 +#define GUESTFWD_ADDR "10.0.2.4" /* GuestFS handle and connection. */ enum state { CONFIG, LAUNCHING, READY, BUSY, NO_HANDLE }; @@ -983,90 +983,93 @@ guestfs__launch (guestfs_h *g) } if (r == 0) { /* Child (qemu). */ - char vmchannel[256]; - char append[256]; - char memsize_str[256]; + char buf[256]; /* Set up the full command line. Do this in the subprocess so we * don't need to worry about cleaning up. */ g->cmdline[0] = g->qemu; -#define LINUX_CMDLINE \ - "panic=1 " /* force kernel to panic if daemon exits */ \ - "console=ttyS0 " /* serial console */ \ - "udevtimeout=300 " /* good for very slow systems (RHBZ#480319) */ \ - "noapic " /* workaround for RHBZ#502058 - ok if not SMP */ \ - "acpi=off " /* we don't need ACPI, turn it off */ \ - "cgroup_disable=memory " /* saves us about 5 MB of RAM */ - - /* Linux kernel command line. */ - snprintf (append, sizeof append, - LINUX_CMDLINE - "guestfs=%s:%d " - "%s" /* (selinux) */ - "%s" /* (verbose) */ - "%s", /* (append) */ - VMCHANNEL_ADDR, VMCHANNEL_PORT, - g->selinux ? "selinux=1 enforcing=0 " : "selinux=0 ", - g->verbose ? "guestfs_verbose=1 " : " ", - g->append ? g->append : ""); - - snprintf (memsize_str, sizeof memsize_str, "%d", g->memsize); - + snprintf (buf, sizeof buf, "%d", g->memsize); add_cmdline (g, "-m"); - add_cmdline (g, memsize_str); + add_cmdline (g, buf); + add_cmdline (g, "-no-reboot"); /* Force exit instead of reboot on panic */ - add_cmdline (g, "-kernel"); - add_cmdline (g, (char *) kernel); - add_cmdline (g, "-initrd"); - add_cmdline (g, (char *) initrd); - add_cmdline (g, "-append"); - add_cmdline (g, append); add_cmdline (g, "-nographic"); add_cmdline (g, "-serial"); add_cmdline (g, "stdio"); -#if 0 - /* Doesn't work. See: - * http://lists.gnu.org/archive/html/qemu-devel/2009-07/threads.html - * Subject "guestfwd option doesn't allow supplementary ,server,nowait" - */ - if (qemu_supports (g, "guestfwd")) { - /* New-style -net user,guestfwd=... syntax for vmchannel. See: + /* These options recommended by KVM developers to improve reliability. */ + if (qemu_supports (g, "-no-hpet")) + add_cmdline (g, "-no-hpet"); + + if (qemu_supports (g, "-rtc-td-hack")) + add_cmdline (g, "-rtc-td-hack"); + + if (qemu_supports (g, "-chardev") && qemu_supports (g, "guestfwd")) { + /* New-style -net user,guestfwd=... syntax for guestfwd. See: + * * http://git.savannah.gnu.org/cgit/qemu.git/commit/?id=c92ef6a22d3c71538fcc48fb61ad353f7ba03b62 + * + * The original suggested format doesn't work, see: + * + * http://lists.gnu.org/archive/html/qemu-devel/2009-07/msg01654.html + * + * However Gerd Hoffman privately suggested to me using -chardev + * instead, which does work. */ - snprintf (vmchannel, sizeof vmchannel, - "user,vlan=0,net=10.0.2.0/8,guestfwd=tcp:%s:%d-unix:%s,server,nowait", - VMCHANNEL_ADDR, VMCHANNEL_PORT, unixsock); + snprintf (buf, sizeof buf, + "socket,id=guestfsvmc,path=%s,server,nowait", unixsock); + + add_cmdline (g, "-chardev"); + add_cmdline (g, buf); + + snprintf (buf, sizeof buf, + "user,vlan=0,net=10.0.2.0/8," + "guestfwd=tcp:%s:%d-chardev:guestfsvmc", + GUESTFWD_ADDR, GUESTFWD_PORT); add_cmdline (g, "-net"); - add_cmdline (g, vmchannel); + add_cmdline (g, buf); } else { -#endif /* Not guestfwd. HOPEFULLY this qemu uses the older -net channel * syntax, or if not then we'll get a quick failure. */ - snprintf (vmchannel, sizeof vmchannel, - "channel,%d:unix:%s,server,nowait", - VMCHANNEL_PORT, unixsock); + snprintf (buf, sizeof buf, + "channel,%d:unix:%s,server,nowait", GUESTFWD_PORT, unixsock); add_cmdline (g, "-net"); - add_cmdline (g, vmchannel); + add_cmdline (g, buf); add_cmdline (g, "-net"); add_cmdline (g, "user,vlan=0,net=10.0.2.0/8"); -#if 0 } -#endif add_cmdline (g, "-net"); add_cmdline (g, "nic,model=" NET_IF ",vlan=0"); - /* These options recommended by KVM developers to improve reliability. */ - if (qemu_supports (g, "-no-hpet")) - add_cmdline (g, "-no-hpet"); +#define LINUX_CMDLINE \ + "panic=1 " /* force kernel to panic if daemon exits */ \ + "console=ttyS0 " /* serial console */ \ + "udevtimeout=300 " /* good for very slow systems (RHBZ#480319) */ \ + "noapic " /* workaround for RHBZ#502058 - ok if not SMP */ \ + "acpi=off " /* we don't need ACPI, turn it off */ \ + "cgroup_disable=memory " /* saves us about 5 MB of RAM */ - if (qemu_supports (g, "-rtc-td-hack")) - add_cmdline (g, "-rtc-td-hack"); + /* Linux kernel command line. */ + snprintf (buf, sizeof buf, + LINUX_CMDLINE + "%s" /* (selinux) */ + "%s" /* (verbose) */ + "%s", /* (append) */ + g->selinux ? "selinux=1 enforcing=0 " : "selinux=0 ", + g->verbose ? "guestfs_verbose=1 " : "", + g->append ? g->append : ""); + + add_cmdline (g, "-kernel"); + add_cmdline (g, (char *) kernel); + add_cmdline (g, "-initrd"); + add_cmdline (g, (char *) initrd); + add_cmdline (g, "-append"); + add_cmdline (g, buf); /* Finish off the command line. */ incr_cmdline_size (g); @@ -1205,6 +1208,32 @@ guestfs__launch (guestfs_h *g) connected: g->state = LAUNCHING; + + /* Wait for qemu to start and to connect back to us via vmchannel and + * send the GUESTFS_LAUNCH_FLAG message. + */ + uint32_t size; + void *buf = NULL; + r = recv_from_daemon (g, &size, &buf); + free (buf); + + if (r == -1) return -1; + + if (size != GUESTFS_LAUNCH_FLAG) { + error (g, _("guestfs_launch failed, see earlier error messages")); + goto cleanup2; + } + + /* This is possible in some really strange situations, such as + * guestfsd starts up OK but then qemu immediately exits. Check for + * it because the caller is probably expecting to be able to send + * commands after this function returns. + */ + if (g->state != READY) { + error (g, _("qemu launched and contacted daemon, but state != READY")); + goto cleanup2; + } + return 0; cleanup2: @@ -1378,45 +1407,17 @@ qemu_supports (guestfs_h *g, const char *option) return g->qemu_help && strstr (g->qemu_help, option) != NULL; } +/* You had to call this function after launch in versions <= 1.0.70, + * but it is now a no-op. + */ int guestfs__wait_ready (guestfs_h *g) { - int r; - uint32_t size; - void *buf = NULL; - - if (g->state == READY) return 0; - - if (g->state == BUSY) { - error (g, _("qemu has finished launching already")); - return -1; - } - - if (g->state != LAUNCHING) { + if (g->state != READY) { error (g, _("qemu has not been launched yet")); return -1; } - r = recv_from_daemon (g, &size, &buf); - free (buf); - - if (r == -1) return -1; - - if (size != GUESTFS_LAUNCH_FLAG) { - error (g, _("guestfs_wait_ready failed, see earlier error messages")); - return -1; - } - - /* This is possible in some really strange situations, such as - * guestfsd starts up OK but then qemu immediately exits. Check for - * it because the caller is probably expecting to be able to send - * commands after this function returns. - */ - if (g->state != READY) { - error (g, _("qemu launched and contacted daemon, but state != READY")); - return -1; - } - return 0; } @@ -1900,20 +1901,20 @@ recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) } /* Got the full message, caller can start processing it. */ -#if 0 +#ifdef ENABLE_PACKET_DUMP if (g->verbose) { - size_t i, j; + ssize_t i, j; for (i = 0; i < nr; i += 16) { - printf ("%04x: ", i); + printf ("%04zx: ", i); for (j = i; j < MIN (i+16, nr); ++j) - printf ("%02x ", (unsigned char) (*buf_rtn)[j]); + printf ("%02x ", (*(unsigned char **)buf_rtn)[j]); for (; j < i+16; ++j) printf (" "); printf ("|"); - for (j = i; j < MIN (i+16, g->nr); ++j) - if (isprint ((*buf_rtn)[j])) - printf ("%c", (*buf_rtn)[j]); + for (j = i; j < MIN (i+16, nr); ++j) + if (isprint ((*(char **)buf_rtn)[j])) + printf ("%c", (*(char **)buf_rtn)[j]); else printf ("."); for (; j < i+16; ++j)