X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fguestfs.c;h=55732f91ed028c7da062b23eab63e28c6e209eb8;hp=8c05c40a9ea3e6486e6fbef8ca9248169090a82c;hb=0740d45d28435015365b21213263249321d83878;hpb=bb02f0fbe80ef093731bc9a6a407f1edaccf991d diff --git a/src/guestfs.c b/src/guestfs.c index 8c05c40..55732f9 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_ADDR "10.0.2.4" +#define GUESTFWD_PORT "6666" /* 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:" GUESTFWD_ADDR ":" GUESTFWD_PORT + "-chardev:guestfsvmc"); 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," GUESTFWD_PORT ":unix:%s,server,nowait", 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; }