mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
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:
3
TODO
3
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:
|
||||
|
||||
@@ -140,7 +140,6 @@ if ($uri) {
|
||||
}
|
||||
|
||||
$g->launch ();
|
||||
$g->wait_ready ();
|
||||
|
||||
# List of possible filesystems.
|
||||
my @partitions = get_partitions ($g);
|
||||
|
||||
@@ -183,7 +183,6 @@ sub do_df
|
||||
}
|
||||
|
||||
$g->launch ();
|
||||
$g->wait_ready ();
|
||||
|
||||
my @partitions = get_partitions ($g);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
24
guestfs.pod
24
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
|
||||
|
||||
|
||||
@@ -28,5 +28,4 @@ main = do
|
||||
hClose fd
|
||||
Guestfs.add_drive g "test.img"
|
||||
Guestfs.launch g
|
||||
Guestfs.wait_ready g
|
||||
removeLink "test.img"
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -219,7 +219,6 @@ if ($uri) {
|
||||
}
|
||||
|
||||
$g->launch ();
|
||||
$g->wait_ready ();
|
||||
|
||||
=head1 OUTPUT FORMAT
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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"});
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -27,6 +27,5 @@ let () =
|
||||
|
||||
Guestfs.add_drive g "test.img";
|
||||
Guestfs.launch g;
|
||||
Guestfs.wait_ready g;
|
||||
|
||||
unlink "test.img"
|
||||
|
||||
@@ -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"|];
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"]);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user