Remove guestfs_wait_ready (turn it into a no-op).

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.
This commit is contained in:
Richard Jones
2009-09-21 11:52:53 +01:00
parent 62b3228725
commit 8869adf1e8
28 changed files with 56 additions and 105 deletions

3
TODO
View File

@@ -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:

View File

@@ -140,7 +140,6 @@ if ($uri) {
}
$g->launch ();
$g->wait_ready ();
# List of possible filesystems.
my @partitions = get_partitions ($g);

View File

@@ -183,7 +183,6 @@ sub do_df
}
$g->launch ();
$g->wait_ready ();
my @partitions = get_partitions ($g);

View File

@@ -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);

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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

View File

@@ -28,5 +28,4 @@ main = do
hClose fd
Guestfs.add_drive g "test.img"
Guestfs.launch g
Guestfs.wait_ready g
removeLink "test.img"

View File

@@ -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"]

View File

@@ -219,7 +219,6 @@ if ($uri) {
}
$g->launch ();
$g->wait_ready ();
=head1 OUTPUT FORMAT

View File

@@ -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 ();

View File

@@ -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"});

View File

@@ -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));

View File

@@ -27,6 +27,5 @@ let () =
Guestfs.add_drive g "test.img";
Guestfs.launch g;
Guestfs.wait_ready g;
unlink "test.img"

View File

@@ -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"|];

View File

@@ -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";

View File

@@ -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 ();

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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")

View File

@@ -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)

View File

@@ -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"]);

View File

@@ -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)

View File

@@ -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 ()

View File

@@ -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;
}

View File

@@ -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);
}