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.
$h->set_autosync (1);
$h->add_drive_ro ($filename);
$h->launch ();
- $h->wait_ready ();
$h->mount_ro (\"/dev/sda1\", \"/\");
Command-line form would be:
}
$g->launch ();
-$g->wait_ready ();
# List of possible filesystems.
my @partitions = get_partitions ($g);
}
$g->launch ();
- $g->wait_ready ();
my @partitions = get_partitions ($g);
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);
CALL (guestfs_add_drive (g, argv[i]), -1);
CALL (guestfs_launch (g), -1);
- CALL (guestfs_wait_ready (g), -1);
printf ("<guestfs-system>\n");
if (guestfs_is_config (g)) {
if (guestfs_launch (g) == -1)
return -1;
- if (guestfs_wait_ready (g) == -1)
- return -1;
}
return 0;
}
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);
*/
guestfs_launch (handle);
- guestfs_wait_ready (handle);
/* now you can examine what partitions, LVs etc are available
* you have to mount / at least
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.
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.
/ | | LAUNCHING |
/ | \___________/
/ | /
- / | guestfs_wait_ready
+ / | guestfs_launch
/ | /
______ / __|____V
/ \ ------> / \
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
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
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
hClose fd
Guestfs.add_drive g "test.img"
Guestfs.launch g
- Guestfs.wait_ready g
removeLink "test.img"
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"]
}
$g->launch ();
-$g->wait_ready ();
=head1 OUTPUT FORMAT
f.close ();
g.add_drive ("test.img");
g.launch ();
- g.wait_ready ();
g.close ();
File f2 = new File ("test.img");
f2.delete ();
g.add_drive ("test.img");
g.launch ();
- g.wait_ready ();
g.pvcreate ("/dev/sda");
g.vgcreate ("VG", new String[] {"/dev/sda"});
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));
Guestfs.add_drive g "test.img";
Guestfs.launch g;
- Guestfs.wait_ready g;
unlink "test.img"
Guestfs.add_drive g "test.img";
Guestfs.launch g;
- Guestfs.wait_ready g;
Guestfs.pvcreate g "/dev/sda";
Guestfs.vgcreate g "VG" [|"/dev/sda"|];
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";
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 ();
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
use strict;
use warnings;
-use Test::More tests => 12;
+use Test::More tests => 11;
use Sys::Guestfs;
$h->launch ();
ok (1);
-$h->wait_ready ();
-ok (1);
$h->pvcreate ("/dev/sda");
ok (1);
use strict;
use warnings;
-use Test::More tests => 13;
+use Test::More tests => 12;
use Sys::Guestfs;
$h->launch ();
ok (1);
-$h->wait_ready ();
-ok (1);
$h->sfdisk ("/dev/sda", 0, 0, 0, [","]);
ok (1);
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;
$h->launch ();
ok (1);
-$h->wait_ready ();
-ok (1);
$h->mount_ro ("/dev/sda", "/");
ok (1);
f.close ()
g.add_drive ("test.img")
g.launch ()
-g.wait_ready ()
os.unlink ("test.img")
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)
g.add_drive("test.img")
g.launch()
- g.wait_ready()
g.pvcreate("/dev/sda")
g.vgcreate("VG", ["/dev/sda"]);
g.add_drive("test.img")
g.launch()
- g.wait_ready()
exception = assert_raise TypeError do
g.command(1)
("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, [],
[],
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));
/* 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);
my $h = Sys::Guestfs->new ();
$h->add_drive ('guest.img');
$h->launch ();
- $h->wait_ready ();
$h->mount ('/dev/sda1', '/');
$h->touch ('/hello');
$h->sync ();
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
# 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 ()
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:
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;
}
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);
}