From: Richard Jones <rjones(a)trick.home.annexia.org>
This commit changes guestfs_launch so that it both launches
the appliance and waits until it is ready (ie. the daemon communicates
back to us).
Since we removed the pretence that we could implement a low-level
asynchronous API, the need to call launch() followed by wait_ready()
has looked a bit silly.
Now guestfs_wait_ready() is basically a no-op. It is left in the
API for backwards compatibility. Any calls to guestfs_wait_ready()
can be removed from client code.
---
TODO | 3 +-
cat/virt-cat.pl | 1 -
df/virt-df.pl | 1 -
examples/hello.c | 1 -
examples/to-xml.c | 1 -
fish/fish.c | 2 -
guestfs.pod | 24 +++++----------
haskell/Guestfs010Launch.hs | 1 -
haskell/Guestfs050LVCreate.hs | 1 -
inspector/virt-inspector.pl | 1 -
java/t/GuestFS010Launch.java | 1 -
java/t/GuestFS050LVCreate.java | 1 -
ocaml/examples/lvs.ml | 1 -
ocaml/t/guestfs_010_launch.ml | 1 -
ocaml/t/guestfs_050_lvcreate.ml | 1 -
ocaml/t/guestfs_060_readdir.ml | 1 -
perl/examples/lvs.pl | 1 -
perl/lib/Sys/Guestfs/Lib.pm | 2 +-
perl/t/050-lvcreate.t | 4 +--
perl/t/060-readdir.t | 4 +--
perl/t/510-lib-file-arch.t | 4 +--
python/t/010-launch.py | 1 -
python/t/050-lvcreate.py | 1 -
ruby/tests/tc_050_lvcreate.rb | 1 -
ruby/tests/tc_rhbz507346.rb | 1 -
src/generator.ml | 28 +++++++----------
src/guestfs.c | 62 +++++++++++++++++++--------------------
test-tool/test-tool.c | 10 +-----
28 files changed, 56 insertions(+), 105 deletions(-)
diff --git a/TODO b/TODO
index bfcc477..12b1ce6 100644
--- a/TODO
+++ b/TODO
@@ -214,7 +214,7 @@ Quick Perl scripts
Currently we can't do Perl "one-liners". ie. The current syntax for
any short Perl one-liner would be:
- perl -MSys::Guestfs -e '$g = Sys::Guestfs->new(); $g->add_drive
("foo"); $g->launch; $g->wait_ready; $g->mount ("/dev/sda1",
"/"); ....'
+ perl -MSys::Guestfs -e '$g = Sys::Guestfs->new(); $g->add_drive
("foo"); $g->launch; $g->mount ("/dev/sda1", "/");
....'
You can see we're well beyond a single line just getting to the point
of adding drives and mounting.
@@ -235,7 +235,6 @@ which is equivalent to the following sequence of calls:
$h->set_autosync (1);
$h->add_drive_ro ($filename);
$h->launch ();
- $h->wait_ready ();
$h->mount_ro (\"/dev/sda1\", \"/\");
Command-line form would be:
diff --git a/cat/virt-cat.pl b/cat/virt-cat.pl
index 1017876..8db5348 100755
--- a/cat/virt-cat.pl
+++ b/cat/virt-cat.pl
@@ -140,7 +140,6 @@ if ($uri) {
}
$g->launch ();
-$g->wait_ready ();
# List of possible filesystems.
my @partitions = get_partitions ($g);
diff --git a/df/virt-df.pl b/df/virt-df.pl
index a1b2228..21ba791 100755
--- a/df/virt-df.pl
+++ b/df/virt-df.pl
@@ -183,7 +183,6 @@ sub do_df
}
$g->launch ();
- $g->wait_ready ();
my @partitions = get_partitions ($g);
diff --git a/examples/hello.c b/examples/hello.c
index 1c12f8e..8b36ed4 100644
--- a/examples/hello.c
+++ b/examples/hello.c
@@ -27,7 +27,6 @@ main (int argc, char *argv[])
if (guestfs_add_drive (g, argv[1]) == -1) exit (1);
if (guestfs_launch (g) == -1) exit (1);
- if (guestfs_wait_ready (g) == -1) exit (1);
if (guestfs_mount (g, argv[2], "/") == -1) exit (1);
diff --git a/examples/to-xml.c b/examples/to-xml.c
index 2cf3de8..6d0a1df 100644
--- a/examples/to-xml.c
+++ b/examples/to-xml.c
@@ -51,7 +51,6 @@ main (int argc, char *argv[])
CALL (guestfs_add_drive (g, argv[i]), -1);
CALL (guestfs_launch (g), -1);
- CALL (guestfs_wait_ready (g), -1);
printf ("<guestfs-system>\n");
diff --git a/fish/fish.c b/fish/fish.c
index 9215f4e..f8c0483 100644
--- a/fish/fish.c
+++ b/fish/fish.c
@@ -81,8 +81,6 @@ launch (guestfs_h *_g)
if (guestfs_is_config (g)) {
if (guestfs_launch (g) == -1)
return -1;
- if (guestfs_wait_ready (g) == -1)
- return -1;
}
return 0;
}
diff --git a/guestfs.pod b/guestfs.pod
index c5b756e..33b84d7 100644
--- a/guestfs.pod
+++ b/guestfs.pod
@@ -11,7 +11,6 @@ guestfs - Library for accessing and modifying virtual machine images
guestfs_h *handle = guestfs_create ();
guestfs_add_drive (handle, "guest.img");
guestfs_launch (handle);
- guestfs_wait_ready (handle);
guestfs_mount (handle, "/dev/sda1", "/");
guestfs_touch (handle, "/hello");
guestfs_sync (handle);
@@ -56,7 +55,6 @@ functions in the following order:
*/
guestfs_launch (handle);
- guestfs_wait_ready (handle);
/* now you can examine what partitions, LVs etc are available
* you have to mount / at least
@@ -73,7 +71,7 @@ functions in the following order:
guestfs_close (handle);
-C<guestfs_wait_ready> and all of the actions including C<guestfs_sync>
+C<guestfs_launch> and all of the actions including C<guestfs_sync>
are blocking calls. You can use the low-level event API to do
non-blocking operations instead.
@@ -100,8 +98,7 @@ You have to call C<guestfs_add_drive> on the handle at least
once.
This function returns a non-NULL pointer to a handle on success or
NULL on error.
-After configuring the handle, you have to call C<guestfs_launch> and
-C<guestfs_wait_ready>.
+After configuring the handle, you have to call C<guestfs_launch>.
You may also want to configure error handling for the handle. See
L</ERROR HANDLING> section below.
@@ -443,7 +440,7 @@ libguestfs uses a state machine to model the child process:
/ | | LAUNCHING |
/ | \___________/
/ | /
- / | guestfs_wait_ready
+ / | guestfs_launch
/ | /
______ / __|____V
/ \ ------> / \
@@ -463,12 +460,10 @@ Configuration commands for qemu such as C<guestfs_add_drive>
can only
be issued when in the CONFIG state.
The high-level API offers two calls that go from CONFIG through
-LAUNCHING to READY. C<guestfs_launch> is a non-blocking call that
-starts up the child process, immediately moving from CONFIG to
-LAUNCHING. C<guestfs_wait_ready> blocks until the child process is
-READY to accept commands (or until some failure or timeout). The
-low-level event API described below provides a non-blocking way to
-replace C<guestfs_wait_ready>.
+LAUNCHING to READY. C<guestfs_launch> blocks until the child process
+is READY to accept commands (or until some failure or timeout).
+C<guestfs_launch> internally moves the state from CONFIG to LAUNCHING
+while it is running.
High-level API actions such as C<guestfs_mount> can only be issued
when in the READY state. These high-level API calls block waiting for
@@ -535,9 +530,6 @@ The callback function C<cb> will be called when the child
process
becomes ready first time after it has been launched. (This
corresponds to a transition from LAUNCHING to the READY state).
-You can use this instead of C<guestfs_wait_ready> to implement a
-non-blocking wait for the child process to finish booting up.
-
=head1 BLOCK DEVICE NAMING
In the kernel there is now quite a profusion of schemata for naming
@@ -780,7 +772,7 @@ parameters, but with the roles of daemon and library reversed.
Because the underlying channel (QEmu -net channel) doesn't have any
sort of connection control, when the daemon launches it sends an
initial word (C<GUESTFS_LAUNCH_FLAG>) which indicates that the guest
-and daemon is alive. This is what C<guestfs_wait_ready> waits for.
+and daemon is alive. This is what C<guestfs_launch> waits for.
=head1 QEMU WRAPPERS
diff --git a/haskell/Guestfs010Launch.hs b/haskell/Guestfs010Launch.hs
index 27e49f7..930d666 100644
--- a/haskell/Guestfs010Launch.hs
+++ b/haskell/Guestfs010Launch.hs
@@ -28,5 +28,4 @@ main = do
hClose fd
Guestfs.add_drive g "test.img"
Guestfs.launch g
- Guestfs.wait_ready g
removeLink "test.img"
diff --git a/haskell/Guestfs050LVCreate.hs b/haskell/Guestfs050LVCreate.hs
index b82bf0d..502f6b2 100644
--- a/haskell/Guestfs050LVCreate.hs
+++ b/haskell/Guestfs050LVCreate.hs
@@ -28,7 +28,6 @@ main = do
hClose fd
Guestfs.add_drive g "test.img"
Guestfs.launch g
- Guestfs.wait_ready g
Guestfs.pvcreate g "/dev/sda"
Guestfs.vgcreate g "VG" ["/dev/sda"]
diff --git a/inspector/virt-inspector.pl b/inspector/virt-inspector.pl
index 943f32e..86b1795 100755
--- a/inspector/virt-inspector.pl
+++ b/inspector/virt-inspector.pl
@@ -219,7 +219,6 @@ if ($uri) {
}
$g->launch ();
-$g->wait_ready ();
=head1 OUTPUT FORMAT
diff --git a/java/t/GuestFS010Launch.java b/java/t/GuestFS010Launch.java
index 198ea85..ad0665b 100644
--- a/java/t/GuestFS010Launch.java
+++ b/java/t/GuestFS010Launch.java
@@ -29,7 +29,6 @@ public class GuestFS010Launch {
f.close ();
g.add_drive ("test.img");
g.launch ();
- g.wait_ready ();
g.close ();
File f2 = new File ("test.img");
f2.delete ();
diff --git a/java/t/GuestFS050LVCreate.java b/java/t/GuestFS050LVCreate.java
index 012d68b..940239a 100644
--- a/java/t/GuestFS050LVCreate.java
+++ b/java/t/GuestFS050LVCreate.java
@@ -31,7 +31,6 @@ public class GuestFS050LVCreate {
g.add_drive ("test.img");
g.launch ();
- g.wait_ready ();
g.pvcreate ("/dev/sda");
g.vgcreate ("VG", new String[] {"/dev/sda"});
diff --git a/ocaml/examples/lvs.ml b/ocaml/examples/lvs.ml
index 12c7c15..74998b9 100644
--- a/ocaml/examples/lvs.ml
+++ b/ocaml/examples/lvs.ml
@@ -11,7 +11,6 @@ let () =
let h = Guestfs.create () in
Guestfs.add_drive h Sys.argv.(1);
Guestfs.launch h;
- Guestfs.wait_ready h;
let pvs = Guestfs.pvs h in
printf "PVs found: [ %s ]\n" (String.concat "; " (Array.to_list
pvs));
diff --git a/ocaml/t/guestfs_010_launch.ml b/ocaml/t/guestfs_010_launch.ml
index b253e0c..ae0f9f1 100644
--- a/ocaml/t/guestfs_010_launch.ml
+++ b/ocaml/t/guestfs_010_launch.ml
@@ -27,6 +27,5 @@ let () =
Guestfs.add_drive g "test.img";
Guestfs.launch g;
- Guestfs.wait_ready g;
unlink "test.img"
diff --git a/ocaml/t/guestfs_050_lvcreate.ml b/ocaml/t/guestfs_050_lvcreate.ml
index 2d5bb1f..ad98c06 100644
--- a/ocaml/t/guestfs_050_lvcreate.ml
+++ b/ocaml/t/guestfs_050_lvcreate.ml
@@ -27,7 +27,6 @@ let () =
Guestfs.add_drive g "test.img";
Guestfs.launch g;
- Guestfs.wait_ready g;
Guestfs.pvcreate g "/dev/sda";
Guestfs.vgcreate g "VG" [|"/dev/sda"|];
diff --git a/ocaml/t/guestfs_060_readdir.ml b/ocaml/t/guestfs_060_readdir.ml
index e9368a8..8035a09 100644
--- a/ocaml/t/guestfs_060_readdir.ml
+++ b/ocaml/t/guestfs_060_readdir.ml
@@ -27,7 +27,6 @@ let () =
Guestfs.add_drive g "test.img";
Guestfs.launch g;
- Guestfs.wait_ready g;
Guestfs.sfdisk g "/dev/sda" 0 0 0 [|","|];
Guestfs.mkfs g "ext2" "/dev/sda1";
diff --git a/perl/examples/lvs.pl b/perl/examples/lvs.pl
index 152db08..1a84017 100755
--- a/perl/examples/lvs.pl
+++ b/perl/examples/lvs.pl
@@ -14,7 +14,6 @@ $h->add_drive ($ARGV[0]);
print "Launching, this can take a few seconds\n";
$h->launch ();
-$h->wait_ready ();
print "Looking for PVs on the disk image\n";
my @pvs = $h->pvs ();
diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm
index 96ada0d..a9868e2 100644
--- a/perl/lib/Sys/Guestfs/Lib.pm
+++ b/perl/lib/Sys/Guestfs/Lib.pm
@@ -100,7 +100,7 @@ read-write handle, this function will refuse to use active libvirt
domains.
The handle is still in the config state when it is returned, so you
-have to call C<$g-E<gt>launch ()> and C<$g-E<gt>wait_ready>.
+have to call C<$g-E<gt>launch ()>.
The optional C<address> parameter can be added to specify the libvirt
URI. In addition, L<Sys::Virt(3)> lists other parameters which are
diff --git a/perl/t/050-lvcreate.t b/perl/t/050-lvcreate.t
index 1b3e313..a8f3e7b 100644
--- a/perl/t/050-lvcreate.t
+++ b/perl/t/050-lvcreate.t
@@ -17,7 +17,7 @@
use strict;
use warnings;
-use Test::More tests => 12;
+use Test::More tests => 11;
use Sys::Guestfs;
@@ -33,8 +33,6 @@ ok (1);
$h->launch ();
ok (1);
-$h->wait_ready ();
-ok (1);
$h->pvcreate ("/dev/sda");
ok (1);
diff --git a/perl/t/060-readdir.t b/perl/t/060-readdir.t
index 17dfd24..898b44f 100644
--- a/perl/t/060-readdir.t
+++ b/perl/t/060-readdir.t
@@ -17,7 +17,7 @@
use strict;
use warnings;
-use Test::More tests => 13;
+use Test::More tests => 12;
use Sys::Guestfs;
@@ -33,8 +33,6 @@ ok (1);
$h->launch ();
ok (1);
-$h->wait_ready ();
-ok (1);
$h->sfdisk ("/dev/sda", 0, 0, 0, [","]);
ok (1);
diff --git a/perl/t/510-lib-file-arch.t b/perl/t/510-lib-file-arch.t
index 5c70449..dfe32bc 100644
--- a/perl/t/510-lib-file-arch.t
+++ b/perl/t/510-lib-file-arch.t
@@ -22,7 +22,7 @@ BEGIN {
use Test::More;
eval "use Locale::TextDomain";;
if (exists $INC{"Locale/TextDomain.pm"}) {
- plan tests => 17;
+ plan tests => 16;
} else {
plan skip_all => "no perl-libintl module";
exit 0;
@@ -40,8 +40,6 @@ ok (1);
$h->launch ();
ok (1);
-$h->wait_ready ();
-ok (1);
$h->mount_ro ("/dev/sda", "/");
ok (1);
diff --git a/python/t/010-launch.py b/python/t/010-launch.py
index c1316d2..93a8154 100644
--- a/python/t/010-launch.py
+++ b/python/t/010-launch.py
@@ -24,6 +24,5 @@ f.truncate (500 * 1024 * 1024)
f.close ()
g.add_drive ("test.img")
g.launch ()
-g.wait_ready ()
os.unlink ("test.img")
diff --git a/python/t/050-lvcreate.py b/python/t/050-lvcreate.py
index 8503023..f98fe29 100644
--- a/python/t/050-lvcreate.py
+++ b/python/t/050-lvcreate.py
@@ -24,7 +24,6 @@ f.truncate (500 * 1024 * 1024)
f.close ()
g.add_drive ("test.img")
g.launch ()
-g.wait_ready ()
g.pvcreate ("/dev/sda")
g.vgcreate ("VG", ["/dev/sda"])
g.lvcreate ("LV1", "VG", 200)
diff --git a/ruby/tests/tc_050_lvcreate.rb b/ruby/tests/tc_050_lvcreate.rb
index ea87e39..37ae94d 100644
--- a/ruby/tests/tc_050_lvcreate.rb
+++ b/ruby/tests/tc_050_lvcreate.rb
@@ -30,7 +30,6 @@ class TestLoad < Test::Unit::TestCase
g.add_drive("test.img")
g.launch()
- g.wait_ready()
g.pvcreate("/dev/sda")
g.vgcreate("VG", ["/dev/sda"]);
diff --git a/ruby/tests/tc_rhbz507346.rb b/ruby/tests/tc_rhbz507346.rb
index 3bd4bb6..8c5b34f 100644
--- a/ruby/tests/tc_rhbz507346.rb
+++ b/ruby/tests/tc_rhbz507346.rb
@@ -30,7 +30,6 @@ class TestLoad < Test::Unit::TestCase
g.add_drive("test.img")
g.launch()
- g.wait_ready()
exception = assert_raise TypeError do
g.command(1)
diff --git a/src/generator.ml b/src/generator.ml
index 179665b..e5e2681 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -440,13 +440,18 @@ You should call this after configuring the handle
("wait_ready", (RErr, []), -1, [NotInFish],
[],
- "wait until the qemu subprocess launches",
+ "wait until the qemu subprocess launches (no op)",
"\
-Internally libguestfs is implemented by running a virtual machine
-using L<qemu(1)>.
+This function is a no op.
-You should call this after C<guestfs_launch> to wait for the launch
-to complete.");
+In versions of the API E<lt> 1.0.71 you had to call this function
+just after calling C<guestfs_launch> to wait for the launch
+to complete. However this is no longer necessary because
+C<guestfs_launch> now does the waiting.
+
+If you see any calls to this function in code then you can just
+remove them, unless you want to retain compatibility with older
+versions of the API.");
("kill_subprocess", (RErr, []), -1, [],
[],
@@ -4625,12 +4630,9 @@ static int
check_state (guestfs_h *g, const char *caller)
{
if (!guestfs__is_ready (g)) {
- if (guestfs__is_config (g))
+ if (guestfs__is_config (g) || guestfs__is_launching (g))
error (g, \"%%s: call launch before using this function\\n(in guestfish,
don't forget to use the 'run' command)\",
caller);
- else if (guestfs__is_launching (g))
- error (g, \"%%s: call wait_ready() before using this function\",
- caller);
else
error (g, \"%%s called from the wrong state, %%d != READY\",
caller, guestfs__get_state (g));
@@ -5522,11 +5524,6 @@ int main (int argc, char *argv[])
/* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
alarm (600);
- if (guestfs_wait_ready (g) == -1) {
- printf (\"guestfs_wait_ready FAILED\\n\");
- exit (1);
- }
-
/* Cancel previous alarm. */
alarm (0);
@@ -7390,7 +7387,6 @@ Sys::Guestfs - Perl bindings for libguestfs
my $h = Sys::Guestfs->new ();
$h->add_drive ('guest.img');
$h->launch ();
- $h->wait_ready ();
$h->mount ('/dev/sda1', '/');
$h->touch ('/hello');
$h->sync ();
@@ -7928,7 +7924,6 @@ import guestfs
g = guestfs.GuestFS ()
g.add_drive (\"guest.img\")
g.launch ()
-g.wait_ready ()
parts = g.list_partitions ()
The guestfs module provides a Python binding to the libguestfs API
@@ -7963,7 +7958,6 @@ g.add_drive (\"guest.img\")
# Launch the qemu subprocess and wait for it to become ready:
g.launch ()
-g.wait_ready ()
# Now you can issue commands, for example:
logvols = g.lvs ()
diff --git a/src/guestfs.c b/src/guestfs.c
index 17d812a..417d17f 100644
--- a/src/guestfs.c
+++ b/src/guestfs.c
@@ -1208,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:
@@ -1381,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;
}
diff --git a/test-tool/test-tool.c b/test-tool/test-tool.c
index 508c31a..c1a3de7 100644
--- a/test-tool/test-tool.c
+++ b/test-tool/test-tool.c
@@ -186,20 +186,14 @@ main (int argc, char *argv[])
printf ("guestfs_get_verbose: %d\n", guestfs_get_verbose (g));
/* Launch the guest handle. */
- if (guestfs_launch (g) == -1) {
- fprintf (stderr,
- _("libguestfs-test-tool: failed to launch appliance\n"));
- exit (1);
- }
-
printf ("Launching appliance, timeout set to %d seconds.\n", timeout);
fflush (stdout);
alarm (timeout);
- if (guestfs_wait_ready (g) == -1) {
+ if (guestfs_launch (g) == -1) {
fprintf (stderr,
- _("libguestfs-test-tool: failed or timed out in
'wait_ready'\n"));
+ _("libguestfs-test-tool: failed to launch appliance\n"));
exit (1);
}
--
1.6.2.5