<<< Back to the libguestfs home page
guestfish -i? Why does virt-cat only work on a real VM image, but virt-df works on any disk image? What does "no root device found in this operating system image" mean? Note: these are the links to the very latest / bleeding edge builds.
| Distro | Location |
|---|---|
| Fedora ≥ 11, EPEL 5, RHEL ≥ 5.3, CentOS ≥ 5.3 | Latest Koji builds |
| Debian | Debian pkg-libvirt team wiki page and packages. |
| Ubuntu 9.10 | Richard Jones builds unofficial and unsupported Ubuntu packages of recent versions of libguestfs here. |
| Fedora ≤ 10, RHEL ≤ 5.2 | We don't support this, but you may be able to build it from source. |
| Other Linux distro | See How do I package ... on this page. |
| Other non-Linux OS | You'll have to port it. |
First of all, make sure you're using KVM. The usual problem is that
you need to grant KVM privs to ordinary users. Put this in a
boot-time script (like /etc/rc.local):
chmod o+rw /dev/kvm
libguestfs works by booting
an appliance
(like a mini-operating system), and this does take some time. Usually
around 8-15 seconds on a modern machine with KVM enabled. (The long
term target is 4-5 seconds).
If you find yourself restarting guestfish over and over again, you may
find it better to use
the remote
control
feature of guestfish to avoid the start-up costs.
If your distro packager enabled the
so-called supermin
appliance
variant of libguestfs, then libguestfs will use
quite a lot of disk space from /tmp for each libguestfs
handle. Probably around 70MB-100MB per handle. (It's only
used temporarily).
This is unavoidable, but you can place the temporary files somewhere
else by setting the TMPDIR environment variable. (Since
libguestfs 1.0.63,
see this
bug).
libguestfs runs qemu and gives it quite a lot of memory by default. However this memory is fully swappable, and if it's not needed for the operations you are performing, then it will be swapped out (or never even allocated if you have overcommit).
Nevertheless you can change the amount of memory allocated to the
appliance by setting
the LIBGUESTFS_MEMSIZE
environment variable. Be careful about setting this too small.
Set the LIBGUESTFS_DEBUG environment variable
to 1, like this:
export LIBGUESTFS_DEBUG=1
If using guestfish, add the -v option:
$ guestfish -v
If you're still not sure, use the test tool:
$ libguestfs-test-tool
and post the complete output into a bug report.
Usually these problems are caused by the combination of host, qemu and
appliance kernel, and are nothing to do with libguestfs. There are
various ways you can try to work around these problems, which come
down to trying different host, qemu and appliance combinations.
Use LIBGUESTFS_QEMU
to select other versions of qemu.
See also How do I debug libguestfs problems?
To understand the answer, you need to read about the architecture of libguestfs.
Specifically we include
an appliance
(like a mini-operating system) with libguestfs when it is packaged for
Fedora and Debian. And on Fedora and Debian, this appliance gets
built on the fly when the libguestfs package itself is built. The two
tools we use for this
are febootstrap
(for Fedora builds)
and debootstrap
(for Debian builds).
It may not be obvious, but the Fedora libguestfs package ships with a Fedora-based appliance. And the Debian libguestfs package ships with a Debian-based appliance. (For the Ubuntu case, just subtitute "Ubuntu" for "Debian" in the preceeding discussion).
To build for another distro, you need to solve the problem of building the appliance. There are three choices:
As of 2010-02-08, we use both the virtio network and block [disk] drivers.
If you see a serious performance regression (only for certain operations) when using the virtio block driver then you can try switching to using the IDE (libata) driver for:
./configure --with-drive-if=ide
Note that you will still be able to use names like /dev/sda
even with the virtio driver enabled. See
the
section on block device naming in the manpage.
We recommend you start with the API overview.
Now although this overview covers the C API, it's still worth reading, because all the other languages use the same API, with simple logical changes to the names of the calls:
| C | guestfs_ln_sf (g, target, linkname); |
|---|---|
| Python | g.ln_sf (target, linkname); |
| OCaml | Guestfs.ln_sf g target linkname; |
| Perl | $g->ln_sf (target, linkname); |
| Shell (guestfish) | ln-sf target linkname |
Once you're familiar with the API overview, you should look at this list of starting points for other language bindings.
We offer a command called guestmount which lets you mount guest filesystems on the host. This is implemented as a FUSE module. Why don't we just implement the whole of libguestfs using this mechanism, instead of having the large and rather complicated API?
The reasons are twofold. Firstly, libguestfs offers API calls for
doing things like creating and deleting partitions and logical
volumes, which don't fit into a filesystem model very easily. Or
rather, you could fit them in: for example, creating a partition could
be mapped to mkdir /fs/hda1 but then you'd have to
specify some method to choose the size of the partition
(maybe echo 100M > /fs/hda1/.size), and
the partition type, start and end sectors etc., but once you've done
that the filesystem-based API starts to look as complicated or more
than the
straightforward
call-based API we currently have.
The second reason is for efficiency. FUSE itself is reasonably efficient, but it does make lots of small, independent calls into the FUSE module. In guestmount these have to be translated into messages to the libguestfs appliance which has a big overhead (in time and round trips). For example, listing a directory can involve hundreds of round trips (although we try to be as clever as possible by prefetching anticipated data). Making a single libguestfs API call is always more efficient.
We have language bindings for many common programming languages. A full list is on the front page and this link describes how to get started in each language.
One thing you should note about libguestfs is that we prefer to autogenerate as much boilerplate code as possible, and that includes language bindings. Therefore if you wish to add a new programming language to the mix (which is something we welcome) it's best to get that language added to the generator.
Which language did we use to write the generator? OCaml, which is a modern take on ML, a language which has been around since 1974 and was originally designed in order to write compilers, and therefore is very suitable for writing code generation. So you'll need to learn a very little bit of OCaml in order to add your code to the generator.
A lot of people are confused by the two superficially similar tools we provide:
$ guestfish --ro -a guest.img ><fs> run ><fs> fsck /dev/sda1
$ virt-rescue --ro guest.img ><rescue> /sbin/fsck /dev/sda1
And the related question which then arises is why you can't type in full shell commands with all the --options in guestfish (but you can in virt-rescue).
guestfish is a program providing structured access to the guestfs API. It happens to be a nice interactive shell too, but its primary purpose is structured access from shell scripts. Think of it more like a language binding, like Python and other bindings, but for shell. The key differentiating factor of guestfish (and the libguestfs API in general) is the ability to automate changes.
virt-rescue is a free-for-all freeform way to boot the libguestfs appliance and make arbitrary changes to your VM. It's not structured, you can't automate it, but for making quick ad-hoc fixes to your guests, it can be quite useful.
See the question above.
But, if libguestfs was configured (at build time) with:
./configure --enable-debug-command
(which is true for all Fedora builds) then there is a "backdoor" into the appliance allowing you to send arbitrary shell commands. It's not as flexible as virt-rescue, because you can't interact with the shell commands, but here it is anyway:
><fs> debug sh "cmd arg1 arg2 ..."
Note that you should not rely on this. It could be removed or changed in future. If your program needs some operation, please add it to the libguestfs API instead.
guestfish -i?These questions are all related at a fundamental level which may not be immediately obvious.
At the libguestfs API and guestfish level, a "disk image" is just a pile of partitions and filesystems.
In contrast, when the virtual machine boots, it mounts those filesystems into a consistent hierarchy such as:
/ (/dev/sda2) | +-- /boot (/dev/sda1) | +-- /home (/dev/vg_external/Homes) | +-- /usr (/dev/vg_os/lv_usr) | +-- /var (/dev/vg_os/lv_var)
(or drive letters on Windows).
The libguestfs API however knows nothing about how filesystems are mounted. In general, a disk image that we just made up might not contain an operating system or "mountpoints" at all.
Nevertheless, users expect some tools (like virt-cat) to work with VM paths:
virt-cat fedora.img /var/log/messages
How does virt-cat know that /var is a separate
partition?
The trick is a large external program called virt-inspector. Virt-inspector contains all sorts of tests and heuristics, so it can take a disk image about which nothing is known beforehand and work out both what it is, and how filesystems would be mounted.
Some tools, such as virt-cat, virt-edit, virt-ls and virt-tar use the same virt-inspector code to map VM paths. Other tools, such as virt-df and virt-list-filesystems operate entirely at the raw "big pile of filesystems" level of the libguestfs API, and don't use virt-inspector code.
guestfish is in an
interesting middle ground. If you use the -a
and -m command line options, then you have
to tell guestfish exactly how to add disk images and where
to mount partitions. This is the raw API level.
However there
is also a guestfish -i (for inspector
) mode.
In this mode, guestfish runs virt-inspector, and then (if successful)
virt-inspector runs guestfish a second time with the correct
-a and -m options. This is much slower,
but usually simpler for the user.
The error no root device found in this operating system
image is related to this. It means virt-inspector was unable
to locate an operating system within the disk image you gave it. You
might see this from programs like virt-cat if you try to run them on
something which is just a disk image, not an actual VM disk image.
Yes it does. That's because it does a lot of things.
If you're on Fedora and want to build libguestfs from source, a good
place to start is to look at all of the BuildRequires
lines
in the
libguestfs spec file. Once you've installed all of those
packages, you should be good.
By far the most important thing you can do is to install and properly configure Squid. Note that the default configuration that ships with Squid is rubbish, so configuring it is not optional.
A very good place to start with Squid configuration is here: Using Squid to Speed Up Mock package downloads.
Make sure Squid is running, and that the environment
variables $http_proxy and $ftp_proxy
are pointing to it.
I have a file /etc/profile.d/local.sh that
contains:
export http_proxy=http://192.168.2.1:3128/ export ftp_proxy=$http_proxy
where 192.168.2.1:3128 is the address and port
number of my Squid proxy.
With that, the appliance building step should be reduced to a few minutes.
There are two LIBGUESTFS_* environment variables you can set in order to get more information out from libguestfs.
LIBGUESTFS_TRACE — Set this to 1 and libguestfs will
print out each command / API call in a format which is similar
to guestfish commands. (In theory at least you could copy and paste
the output into guestfish in order to get the same effect).
LIBGUESTFS_DEBUG — Set this to 1 in order to
enable massive amounts of debug messages. If you think there is some
problem inside the libguestfs appliance, then you should use this
option.
To set these from the shell, do this before running the program:
export LIBGUESTFS_DEBUG=1
For csh/tcsh the equivalent command would be:
setenv LIBGUESTFS_DEBUG 1
You can use the same environment variables above. Alternatively use
the guestfish
options -x (to trace commands) or
-v (to get the full debug output), or both.
Call guestfs_set_trace to enable command traces, and/or guestfs_set_verbose to enable debug messages. For best results, call these functions as early as possible, just after creating the guestfs handle if you can, and definitely before calling launch.
rjones AT redhat DOT com$Id: FAQ.html,v 1.15 2010/07/16 09:28:32 rjones Exp $