mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
1230 lines
31 KiB
Plaintext
1230 lines
31 KiB
Plaintext
=head1 NAME
|
||
|
||
guestfs-hacking - extending and contributing to libguestfs
|
||
|
||
=head1 DESCRIPTION
|
||
|
||
This manual page is for hackers who want to extend libguestfs itself.
|
||
|
||
=head1 THE SOURCE CODE
|
||
|
||
Libguestfs source is located in the github repository
|
||
L<https://github.com/libguestfs/libguestfs>
|
||
|
||
Large amounts of boilerplate code in libguestfs (RPC, bindings,
|
||
documentation) are generated. This means that many source files will
|
||
appear to be missing from a straightforward git checkout. You have to
|
||
run the generator (C<./autogen.sh && make -C generator>) in order to
|
||
create those files.
|
||
|
||
Libguestfs uses an autotools-based build system, with the main files
|
||
being F<configure.ac> and F<Makefile.am>. See L</THE BUILD SYSTEM>.
|
||
|
||
The F<generator> subdirectory contains the generator, plus files
|
||
describing the API. The F<lib> subdirectory contains source for the
|
||
library. The F<appliance> and F<daemon> subdirectories contain the
|
||
source for the code that builds the appliance, and the code that runs
|
||
in the appliance respectively. Other directories are covered in the
|
||
section L<SOURCE CODE SUBDIRECTORIES> below.
|
||
|
||
Apart from the fact that all API entry points go via some generated
|
||
code, the library is straightforward. (In fact, even the generated
|
||
code is designed to be readable, and should be read as ordinary code).
|
||
Some actions run entirely in the library, and are written as C
|
||
functions in files under F<lib>. Others are forwarded to the daemon
|
||
where (after some generated RPC marshalling) they appear as C
|
||
functions in files under F<daemon>.
|
||
|
||
To build from source, first read the L<guestfs-building(1)>.
|
||
|
||
=head2 SOURCE CODE SUBDIRECTORIES
|
||
|
||
There are a lot of subdirectories in the source tree! Which ones
|
||
should you concentrate on first? F<lib> and F<daemon> which contain
|
||
the source code of the core library. F<generator> is the code
|
||
generator described above, so that is important. The F<Makefile.am>
|
||
in the root directory will tell you in which order the subdirectories
|
||
get built. And then if you are looking at a particular tool
|
||
(eg. F<v2v>) or language binding (eg. F<python>), go straight to that
|
||
subdirectory, but remember that if you didn't run the generator yet,
|
||
then you may find files which appear to be missing.
|
||
|
||
=over 4
|
||
|
||
=item F<align>
|
||
|
||
L<virt-alignment-scan(1)> command and documentation.
|
||
|
||
=item F<appliance>
|
||
|
||
The libguestfs appliance, build scripts and so on.
|
||
|
||
=item F<bash>
|
||
|
||
Bash tab-completion scripts.
|
||
|
||
=item F<build-aux>
|
||
|
||
Various build scripts used by autotools.
|
||
|
||
=item F<builder>
|
||
|
||
L<virt-builder(1)> command and documentation.
|
||
|
||
=item F<cat>
|
||
|
||
The L<virt-cat(1)>, L<virt-filesystems(1)>, L<virt-log(1)>,
|
||
L<virt-ls(1)> and L<virt-tail(1)> commands and documentation.
|
||
|
||
=item F<common>
|
||
|
||
Various libraries of internal code can be found in the F<common>
|
||
subdirectory:
|
||
|
||
=over 4
|
||
|
||
=item F<common/edit>
|
||
|
||
Common code for interactively and non-interactively editing files
|
||
within a libguestfs filesystem.
|
||
|
||
=item F<common/errnostring>
|
||
|
||
The communication protocol used between the library and the daemon
|
||
running inside the appliance has to encode errnos as strings, which is
|
||
handled by this library.
|
||
|
||
=item F<common/miniexpect>
|
||
|
||
A copy of the miniexpect library from
|
||
L<http://git.annexia.org/?p=miniexpect.git;a=summary>. This is used
|
||
in virt-p2v.
|
||
|
||
=item F<common/mlaugeas>
|
||
|
||
Bindings for the Augeas library. These come from the ocaml-augeas
|
||
library L<http://git.annexia.org/?p=ocaml-augeas.git>
|
||
|
||
=item F<common/mlgettext>
|
||
|
||
Small, generated wrapper which allows libguestfs to be compiled with
|
||
or without ocaml-gettext. This is generated by F<./configure>.
|
||
|
||
=item F<common/mlpcre>
|
||
|
||
Lightweight OCaml bindings for Perl Compatible Regular Expressions
|
||
(PCRE). Note this is not related in any way to Markus Mottl's
|
||
ocaml-pcre library.
|
||
|
||
=item F<common/mlprogress>
|
||
|
||
OCaml bindings for the progress bar functions (see F<common/progress>).
|
||
|
||
=item F<common/mlstdutils>
|
||
|
||
A library of pure OCaml utility functions used in many places.
|
||
|
||
=item F<common/mltools>
|
||
|
||
OCaml utility functions only used by the OCaml virt tools (like
|
||
C<virt-sysprep>, C<virt-v2v> etc.)
|
||
|
||
=item F<common/mlutils>
|
||
|
||
OCaml bindings for C functions in C<common/utils>, and some POSIX
|
||
bindings which are missing from the OCaml stdlib.
|
||
|
||
=item F<common/mlvisit>
|
||
|
||
OCaml bindings for the visit functions (see F<common/visit>).
|
||
|
||
=item F<common/mlxml>
|
||
|
||
OCaml bindings for the libxml2 library.
|
||
|
||
=item F<common/options>
|
||
|
||
Common options parsing for guestfish, guestmount and some virt tools.
|
||
|
||
=item F<common/parallel>
|
||
|
||
A framework used for processing multiple libvirt domains in parallel.
|
||
|
||
=item F<common/progress>
|
||
|
||
Common code for printing progress bars.
|
||
|
||
=item F<common/protocol>
|
||
|
||
The XDR-based communication protocol used between the library
|
||
and the daemon running inside the appliance is defined here.
|
||
|
||
=item F<common/qemuopts>
|
||
|
||
Mini-library for writing qemu command lines and qemu config files.
|
||
|
||
=item F<common/structs>
|
||
|
||
Common code for printing and freeing libguestfs structs, used by the
|
||
library and some tools.
|
||
|
||
=item F<common/utils>
|
||
|
||
Various utility functions used throughout the library and tools.
|
||
|
||
=item F<common/visit>
|
||
|
||
Recursively visit a guestfs filesystem hierarchy.
|
||
|
||
=item F<common/windows>
|
||
|
||
Utility functions for handling Windows drive letters.
|
||
|
||
=back
|
||
|
||
=item F<contrib>
|
||
|
||
Outside contributions, experimental parts.
|
||
|
||
=item F<customize>
|
||
|
||
L<virt-customize(1)> command and documentation.
|
||
|
||
=item F<daemon>
|
||
|
||
The daemon that runs inside the libguestfs appliance and carries out
|
||
actions.
|
||
|
||
=item F<df>
|
||
|
||
L<virt-df(1)> command and documentation.
|
||
|
||
=item F<dib>
|
||
|
||
L<virt-dib(1)> command and documentation.
|
||
|
||
=item F<diff>
|
||
|
||
L<virt-diff(1)> command and documentation.
|
||
|
||
=item F<docs>
|
||
|
||
Miscellaneous manual pages.
|
||
|
||
=item F<edit>
|
||
|
||
L<virt-edit(1)> command and documentation.
|
||
|
||
=item F<examples>
|
||
|
||
C API example code.
|
||
|
||
=item F<fish>
|
||
|
||
L<guestfish(1)>, the command-line shell, and various shell scripts
|
||
built on top such as L<virt-copy-in(1)>, L<virt-copy-out(1)>,
|
||
L<virt-tar-in(1)>, L<virt-tar-out(1)>.
|
||
|
||
=item F<format>
|
||
|
||
L<virt-format(1)> command and documentation.
|
||
|
||
=item F<fuse>
|
||
|
||
L<guestmount(1)>, FUSE (userspace filesystem) built on top of libguestfs.
|
||
|
||
=item F<generator>
|
||
|
||
The crucially important generator, used to automatically generate
|
||
large amounts of boilerplate C code for things like RPC and bindings.
|
||
|
||
=item F<get-kernel>
|
||
|
||
L<virt-get-kernel(1)> command and documentation.
|
||
|
||
=item F<gnulib>
|
||
|
||
Gnulib is used as a portability library. A copy of gnulib is included
|
||
under here.
|
||
|
||
=item F<inspector>
|
||
|
||
L<virt-inspector(1)>, the virtual machine image inspector.
|
||
|
||
=item F<lib>
|
||
|
||
Source code to the C library.
|
||
|
||
=item F<logo>
|
||
|
||
Logo used on the website. The fish is called Arthur by the way.
|
||
|
||
=item F<m4>
|
||
|
||
M4 macros used by autoconf. See L</THE BUILD SYSTEM>.
|
||
|
||
=item F<make-fs>
|
||
|
||
L<virt-make-fs(1)> command and documentation.
|
||
|
||
=item F<p2v>
|
||
|
||
L<virt-p2v(1)> command, documentation and scripts for building the
|
||
virt-p2v ISO or disk image.
|
||
|
||
=item F<po>
|
||
|
||
Translations of simple gettext strings.
|
||
|
||
=item F<po-docs>
|
||
|
||
The build infrastructure and PO files for translations of manpages and
|
||
POD files. Eventually this will be combined with the F<po> directory,
|
||
but that is rather complicated.
|
||
|
||
=item F<rescue>
|
||
|
||
L<virt-rescue(1)> command and documentation.
|
||
|
||
=item F<resize>
|
||
|
||
L<virt-resize(1)> command and documentation.
|
||
|
||
=item F<sparsify>
|
||
|
||
L<virt-sparsify(1)> command and documentation.
|
||
|
||
=item F<sysprep>
|
||
|
||
L<virt-sysprep(1)> command and documentation.
|
||
|
||
=item F<tests>
|
||
|
||
Tests.
|
||
|
||
=item F<test-data>
|
||
|
||
Files and other test data used by the tests.
|
||
|
||
=item F<test-tool>
|
||
|
||
Test tool for end users to test if their qemu/kernel combination
|
||
will work with libguestfs.
|
||
|
||
=item F<tmp>
|
||
|
||
Used for temporary files when running the tests (instead of F</tmp>
|
||
etc). The reason is so that you can run multiple parallel tests of
|
||
libguestfs without having one set of tests overwriting the appliance
|
||
created by another.
|
||
|
||
=item F<tools>
|
||
|
||
Command line tools written in Perl (L<virt-win-reg(1)> and many others).
|
||
|
||
=item F<utils>
|
||
|
||
Miscellaneous utilities, such as C<boot-benchmark>.
|
||
|
||
=item F<v2v>
|
||
|
||
L<virt-v2v(1)> command and documentation.
|
||
|
||
=item F<website>
|
||
|
||
The L<http://libguestfs.org> website files.
|
||
|
||
=item F<csharp>
|
||
|
||
=item F<erlang>
|
||
|
||
=item F<gobject>
|
||
|
||
=item F<golang>
|
||
|
||
=item F<haskell>
|
||
|
||
=item F<java>
|
||
|
||
=item F<lua>
|
||
|
||
=item F<ocaml>
|
||
|
||
=item F<php>
|
||
|
||
=item F<perl>
|
||
|
||
=item F<python>
|
||
|
||
=item F<ruby>
|
||
|
||
Language bindings.
|
||
|
||
=back
|
||
|
||
=head2 THE BUILD SYSTEM
|
||
|
||
Libguestfs uses the GNU autotools build system (autoconf, automake,
|
||
libtool).
|
||
|
||
The F<./configure> script is generated from F<configure.ac> and
|
||
F<m4/guestfs-*.m4>. Most of the configure script is split over many
|
||
m4 macro files by topic, for example F<m4/guestfs-daemon.m4> deals
|
||
with the dependencies of the daemon.
|
||
|
||
The job of the top level F<Makefile.am> is mainly to list the
|
||
subdirectories (C<SUBDIRS>) in the order they should be compiled.
|
||
|
||
F<common-rules.mk> is included in every F<Makefile.am> (top level and
|
||
subdirectories). F<subdir-rules.mk> is included only in subdirectory
|
||
F<Makefile.am> files.
|
||
|
||
There are many make targets. Use this command to list them all:
|
||
|
||
make help
|
||
|
||
=head1 EXTENDING LIBGUESTFS
|
||
|
||
=head2 ADDING A NEW API
|
||
|
||
Because large amounts of boilerplate code in libguestfs are generated,
|
||
this makes it easy to extend the libguestfs API.
|
||
|
||
To add a new API action there are two changes:
|
||
|
||
=over 4
|
||
|
||
=item 1.
|
||
|
||
You need to add a description of the call (name, parameters, return
|
||
type, tests, documentation) to F<generator/actions_*.ml> and
|
||
possibly F<generator/proc_nr.ml>.
|
||
|
||
There are two sorts of API action, depending on whether the call goes
|
||
through to the daemon in the appliance, or is serviced entirely by the
|
||
library (see L<guestfs-internals(1)/ARCHITECTURE>). L<guestfs(3)/guestfs_sync> is an example
|
||
of the former, since the sync is done in the appliance.
|
||
L<guestfs(3)/guestfs_set_trace> is an example of the latter, since a trace flag
|
||
is maintained in the handle and all tracing is done on the library
|
||
side.
|
||
|
||
Most new actions are of the first type, and get added to the
|
||
C<daemon_functions> list. Each function has a unique procedure number
|
||
used in the RPC protocol which is assigned to that action when we
|
||
publish libguestfs and cannot be reused. Take the latest procedure
|
||
number and increment it.
|
||
|
||
For library-only actions of the second type, add to the
|
||
C<non_daemon_functions> list. Since these functions are serviced by
|
||
the library and do not travel over the RPC mechanism to the daemon,
|
||
these functions do not need a procedure number, and so the procedure
|
||
number is set to C<-1>.
|
||
|
||
=item 2.
|
||
|
||
Implement the action (in C):
|
||
|
||
For daemon actions, implement the function C<do_E<lt>nameE<gt>> in the
|
||
C<daemon/> directory.
|
||
|
||
For library actions, implement the function C<guestfs_impl_E<lt>nameE<gt>>
|
||
in the C<lib/> directory.
|
||
|
||
In either case, use another function as an example of what to do.
|
||
|
||
=item 3.
|
||
|
||
As an alternative to step 2: Since libguestfs 1.38, daemon actions
|
||
can be implemented in OCaml. You have to set the C<impl = OCaml ...>
|
||
flag in the generator. Take a look at F<daemon/file.ml> for an
|
||
example.
|
||
|
||
=back
|
||
|
||
After making these changes, use C<make> to compile.
|
||
|
||
Note that you don’t need to implement the RPC, language bindings,
|
||
manual pages or anything else. It’s all automatically generated from
|
||
the OCaml description.
|
||
|
||
=head3 Adding tests for an API
|
||
|
||
You can supply zero or as many tests as you want per API call. The
|
||
tests can either be added as part of the API description
|
||
(F<generator/actions_*.ml>), or in some rarer cases you may want to drop
|
||
a script into C<tests/*/>. Note that adding a script to C<tests/*/>
|
||
is slower, so if possible use the first method.
|
||
|
||
The following describes the test environment used when you add an API
|
||
test in F<actions_*.ml>.
|
||
|
||
The test environment has 4 block devices:
|
||
|
||
=over 4
|
||
|
||
=item F</dev/sda> 2 GB
|
||
|
||
General block device for testing.
|
||
|
||
=item F</dev/sdb> 2 GB
|
||
|
||
F</dev/sdb1> is an ext2 filesystem used for testing
|
||
filesystem write operations.
|
||
|
||
=item F</dev/sdc> 10 MB
|
||
|
||
Used in a few tests where two block devices are needed.
|
||
|
||
=item F</dev/sdd>
|
||
|
||
ISO with fixed content (see F<images/test.iso>).
|
||
|
||
=back
|
||
|
||
To be able to run the tests in a reasonable amount of time, the
|
||
libguestfs appliance and block devices are reused between tests. So
|
||
don't try testing L<guestfs(3)/guestfs_kill_subprocess> :-x
|
||
|
||
Each test starts with an initial scenario, selected using one of the
|
||
C<Init*> expressions, described in F<generator/types.ml>. These
|
||
initialize the disks mentioned above in a particular way as documented
|
||
in F<types.ml>. You should not assume anything about the previous
|
||
contents of other disks that are not initialized.
|
||
|
||
You can add a prerequisite clause to any individual test. This is a
|
||
run-time check, which, if it fails, causes the test to be skipped.
|
||
Useful if testing a command which might not work on all variations of
|
||
libguestfs builds. A test that has prerequisite of C<Always> means to
|
||
run unconditionally.
|
||
|
||
In addition, packagers can skip individual tests by setting
|
||
environment variables before running C<make check>.
|
||
|
||
SKIP_TEST_<CMD>_<NUM>=1
|
||
|
||
eg: C<SKIP_TEST_COMMAND_3=1> skips test #3 of L<guestfs(3)/guestfs_command>.
|
||
|
||
or:
|
||
|
||
SKIP_TEST_<CMD>=1
|
||
|
||
eg: C<SKIP_TEST_ZEROFREE=1> skips all L<guestfs(3)/guestfs_zerofree> tests.
|
||
|
||
Packagers can run only certain tests by setting for example:
|
||
|
||
TEST_ONLY="vfs_type zerofree"
|
||
|
||
See F<tests/c-api/tests.c> for more details of how these environment
|
||
variables work.
|
||
|
||
=head3 Debugging new APIs
|
||
|
||
Test new actions work before submitting them.
|
||
|
||
You can use guestfish to try out new commands.
|
||
|
||
Debugging the daemon is a problem because it runs inside a minimal
|
||
environment. However you can fprintf messages in the daemon to
|
||
stderr, and they will show up if you use C<guestfish -v>.
|
||
|
||
=head2 ADDING A NEW LANGUAGE BINDING
|
||
|
||
All language bindings must be generated by the generator
|
||
(see the F<generator> subdirectory).
|
||
|
||
There is no documentation for this yet. We suggest you look
|
||
at an existing binding, eg. F<generator/ocaml.ml> or
|
||
F<generator/perl.ml>.
|
||
|
||
=head3 Adding tests for language bindings
|
||
|
||
Language bindings should come with tests. Previously testing of
|
||
language bindings was rather ad-hoc, but we have been trying to
|
||
formalize the set of tests that every language binding should use.
|
||
|
||
Currently only the OCaml and Perl bindings actually implement the full
|
||
set of tests, and the OCaml bindings are canonical, so you should
|
||
emulate what the OCaml tests do.
|
||
|
||
This is the numbering scheme used by the tests:
|
||
|
||
- 000+ basic tests:
|
||
|
||
010 load the library
|
||
020 create
|
||
030 create-flags
|
||
040 create multiple handles
|
||
050 test setting and getting config properties
|
||
060 explicit close
|
||
065 implicit close (in GC'd languages)
|
||
070 optargs
|
||
080 version
|
||
090 retvalues
|
||
|
||
- 100 launch, create partitions and LVs and filesystems
|
||
|
||
- 400+ events:
|
||
|
||
410 close event
|
||
420 log messages
|
||
430 progress messages
|
||
|
||
- 800+ regression tests (specific to the language)
|
||
|
||
- 900+ any other custom tests for the language
|
||
|
||
To save time when running the tests, only 100, 430, 800+, 900+ should
|
||
launch the handle.
|
||
|
||
=head2 FORMATTING CODE
|
||
|
||
Our C source code generally adheres to some basic code-formatting
|
||
conventions. The existing code base is not totally consistent on this
|
||
front, but we do prefer that contributed code be formatted similarly.
|
||
In short, use spaces-not-TABs for indentation, use 2 spaces for each
|
||
indentation level, and other than that, follow the K&R style.
|
||
|
||
If you use Emacs, add the following to one of one of your start-up files
|
||
(e.g., ~/.emacs), to help ensure that you get indentation right:
|
||
|
||
;;; In libguestfs, indent with spaces everywhere (not TABs).
|
||
;;; Exceptions: Makefile and ChangeLog modes.
|
||
(add-hook 'find-file-hook
|
||
'(lambda () (if (and buffer-file-name
|
||
(string-match "/libguestfs\\>"
|
||
(buffer-file-name))
|
||
(not (string-equal mode-name "Change Log"))
|
||
(not (string-equal mode-name "Makefile")))
|
||
(setq indent-tabs-mode nil))))
|
||
|
||
;;; When editing C sources in libguestfs, use this style.
|
||
(defun libguestfs-c-mode ()
|
||
"C mode with adjusted defaults for use with libguestfs."
|
||
(interactive)
|
||
(c-set-style "K&R")
|
||
(setq c-indent-level 2)
|
||
(setq c-basic-offset 2))
|
||
(add-hook 'c-mode-hook
|
||
'(lambda () (if (string-match "/libguestfs\\>"
|
||
(buffer-file-name))
|
||
(libguestfs-c-mode))))
|
||
|
||
=head2 TESTING YOUR CHANGES
|
||
|
||
Turn warnings into errors when developing to make warnings hard to
|
||
ignore:
|
||
|
||
./configure --enable-werror
|
||
|
||
Useful targets are:
|
||
|
||
=over 4
|
||
|
||
=item C<make check>
|
||
|
||
Runs the regular test suite.
|
||
|
||
This is implemented using the regular automake C<TESTS> target. See
|
||
the automake documentation for details.
|
||
|
||
=item C<make check-valgrind>
|
||
|
||
Runs a subset of the test suite under valgrind.
|
||
|
||
See L</VALGRIND> below.
|
||
|
||
=item C<make check-valgrind-local-guests>
|
||
|
||
Runs a subset of the test suite under valgrind
|
||
using locally installed libvirt guests (read-only).
|
||
|
||
=item C<make check-direct>
|
||
|
||
Runs all tests using default appliance back-end. This only
|
||
has any effect if a non-default backend was selected
|
||
using C<./configure --with-default-backend=...>
|
||
|
||
=item C<make check-valgrind-direct>
|
||
|
||
Run a subset of the test suite under valgrind using the
|
||
default appliance back-end.
|
||
|
||
=item C<make check-uml>
|
||
|
||
Runs all tests using the User-Mode Linux backend.
|
||
|
||
As there is no standard location for the User-Mode Linux kernel, you
|
||
I<have> to set C<LIBGUESTFS_HV> to point to the kernel image, eg:
|
||
|
||
make check-uml LIBGUESTFS_HV=~/d/linux-um/vmlinux
|
||
|
||
=item C<make check-valgrind-uml>
|
||
|
||
Runs all tests using the User-Mode Linux backend, under valgrind.
|
||
|
||
As above, you have to set C<LIBGUESTFS_HV> to point to the kernel.
|
||
|
||
=item C<make check-with-upstream-qemu>
|
||
|
||
Runs all tests using a local qemu binary. It looks for the qemu
|
||
binary in QEMUDIR (defaults to F<$HOME/d/qemu>), but you can set this
|
||
to another directory on the command line, eg:
|
||
|
||
make check-with-upstream-qemu QEMUDIR=/usr/src/qemu
|
||
|
||
=item C<make check-with-upstream-libvirt>
|
||
|
||
Runs all tests using a local libvirt. This only has any effect if the
|
||
libvirt backend was selected using
|
||
C<./configure --with-default-backend=libvirt>
|
||
|
||
It looks for libvirt in LIBVIRTDIR (defaults to F<$HOME/d/libvirt>),
|
||
but you can set this to another directory on the command line, eg:
|
||
|
||
make check-with-upstream-libvirt LIBVIRTDIR=/usr/src/libvirt
|
||
|
||
=item C<make check-slow>
|
||
|
||
Runs some slow/long-running tests which are not run by default.
|
||
|
||
To mark a test as slow/long-running:
|
||
|
||
=over 4
|
||
|
||
=item *
|
||
|
||
Add it to the list of C<TESTS> in the F<Makefile.am>, just like a
|
||
normal test.
|
||
|
||
=item *
|
||
|
||
Modify the test so it checks if the C<SLOW=1> environment variable is
|
||
set, and if I<not> set it skips (ie. returns with exit code 77). If
|
||
using C<$TEST_FUNCTIONS>, you can call the function C<slow_test> for
|
||
this.
|
||
|
||
=item *
|
||
|
||
Add a variable C<SLOW_TESTS> to the F<Makefile.am> listing the slow
|
||
tests.
|
||
|
||
=item *
|
||
|
||
Add a rule to the F<Makefile.am>:
|
||
|
||
check-slow:
|
||
$(MAKE) check TESTS="$(SLOW_TESTS)" SLOW=1
|
||
|
||
=back
|
||
|
||
=item C<sudo make check-root>
|
||
|
||
Runs some tests which require root privileges. These are supposed to
|
||
be safe, but take care. You have to run this as root (eg. using
|
||
L<sudo(8)> explicitly).
|
||
|
||
To mark a test as requiring root:
|
||
|
||
=over 4
|
||
|
||
=item *
|
||
|
||
Add it to the list of C<TESTS> in the F<Makefile.am>, just like a
|
||
normal test.
|
||
|
||
=item *
|
||
|
||
Modify the test so it checks if euid == 0, and if I<not> set it skips
|
||
(ie. returns with exit code 77). If using C<$TEST_FUNCTIONS>, you can
|
||
call the function C<root_test> for this.
|
||
|
||
=item *
|
||
|
||
Add a variable C<ROOT_TESTS> to the F<Makefile.am> listing the root
|
||
tests.
|
||
|
||
=item *
|
||
|
||
Add a rule to the F<Makefile.am>:
|
||
|
||
check-root:
|
||
$(MAKE) check TESTS="$(ROOT_TESTS)"
|
||
|
||
=back
|
||
|
||
=item C<make check-all>
|
||
|
||
Equivalent to running all C<make check*> rules except C<check-root>.
|
||
|
||
=item C<make check-release>
|
||
|
||
Runs a subset of C<make check*> rules that are required to pass
|
||
before a tarball can be released. Currently this is:
|
||
|
||
=over 4
|
||
|
||
=item *
|
||
|
||
check
|
||
|
||
=item *
|
||
|
||
check-valgrind
|
||
|
||
=item *
|
||
|
||
check-direct
|
||
|
||
=item *
|
||
|
||
check-valgrind-direct
|
||
|
||
=item *
|
||
|
||
check-slow
|
||
|
||
=back
|
||
|
||
=item C<make installcheck>
|
||
|
||
Run C<make check> on the installed copy of libguestfs.
|
||
|
||
The version of installed libguestfs being tested, and the version of
|
||
the libguestfs source tree must be the same.
|
||
|
||
Do:
|
||
|
||
./autogen.sh
|
||
make clean ||:
|
||
make
|
||
make installcheck
|
||
|
||
=back
|
||
|
||
=head2 VALGRIND
|
||
|
||
When you do C<make check-valgrind>, it searches for any F<Makefile.am>
|
||
in the tree that has a C<check-valgrind:> target and runs it.
|
||
|
||
Writing the F<Makefile.am> and tests correctly to use valgrind and
|
||
working with automake parallel tests is subtle.
|
||
|
||
If your tests are run via a shell script wrapper, then in the wrapper
|
||
use:
|
||
|
||
$VG virt-foo
|
||
|
||
and in the F<Makefile.am> use:
|
||
|
||
check-valgrind:
|
||
make VG="@VG@" check
|
||
|
||
However, if your binaries run directly from the C<TESTS> rule, you
|
||
have to modify the F<Makefile.am> like this:
|
||
|
||
LOG_COMPILER = $(VG)
|
||
|
||
check-valgrind:
|
||
make VG="@VG@" check
|
||
|
||
In either case, check that the right program is being tested by
|
||
examining the F<tmp/valgrind*> log files carefully.
|
||
|
||
=head2 SUBMITTING PATCHES
|
||
|
||
Submit patches to the mailing list:
|
||
L<http://www.redhat.com/mailman/listinfo/libguestfs>
|
||
and CC to L<rjones@redhat.com>.
|
||
|
||
You do not need to subscribe to the mailing list if you don’t want to.
|
||
There may be a short delay while your message is moderated.
|
||
|
||
=head2 DAEMON CUSTOM PRINTF FORMATTERS
|
||
|
||
In the daemon code we have created custom printf formatters C<%Q> and
|
||
C<%R>, which are used to do shell quoting.
|
||
|
||
=over 4
|
||
|
||
=item %Q
|
||
|
||
Simple shell quoted string. Any spaces or other shell characters are
|
||
escaped for you.
|
||
|
||
=item %R
|
||
|
||
Same as C<%Q> except the string is treated as a path which is prefixed
|
||
by the sysroot.
|
||
|
||
=back
|
||
|
||
For example:
|
||
|
||
asprintf (&cmd, "cat %R", path);
|
||
|
||
would produce C<cat /sysroot/some\ path\ with\ spaces>
|
||
|
||
I<Note:> Do I<not> use these when you are passing parameters to the
|
||
C<command{,r,v,rv}()> functions. These parameters do NOT need to be
|
||
quoted because they are not passed via the shell (instead, straight to
|
||
exec). You probably want to use the C<sysroot_path()> function
|
||
however.
|
||
|
||
=head2 INTERNATIONALIZATION (I18N) SUPPORT
|
||
|
||
We support i18n (gettext anyhow) in the library.
|
||
|
||
However many messages come from the daemon, and we don’t translate
|
||
those at the moment. One reason is that the appliance generally has
|
||
all locale files removed from it, because they take up a lot of space.
|
||
So we'd have to readd some of those, as well as copying our PO files
|
||
into the appliance.
|
||
|
||
Debugging messages are never translated, since they are intended for
|
||
the programmers.
|
||
|
||
=head1 MISCELLANEOUS TOPICS
|
||
|
||
=head2 HOW OCAML PROGRAMS ARE COMPILED AND LINKED
|
||
|
||
Mostly this section is "how we make automake & ocamlopt work together"
|
||
since OCaml programs themselves are easy to compile.
|
||
|
||
Automake has no native support for OCaml programs, ocamlc nor
|
||
ocamlopt. What we do instead is to treat OCaml programs as C programs
|
||
which happen to contain these "other objects" (C<"DEPENDENCIES"> in
|
||
automake-speak) that happen to be the OCaml objects. This works
|
||
because OCaml programs usually have C files for native bindings etc.
|
||
|
||
So a typical program is described as just its C sources:
|
||
|
||
virt_v2v_SOURCES = ... utils-c.c xml-c.c
|
||
|
||
For programs that have no explicit C sources, we create an empty
|
||
F<dummy.c> file, and list that instead:
|
||
|
||
virt_resize_SOURCES = dummy.c
|
||
|
||
The OCaml objects which contain most of the code are listed as
|
||
automake dependencies (other dependencies may also be listed):
|
||
|
||
virt_v2v_DEPENDENCIES = ... cmdline.cmx v2v.cmx
|
||
|
||
The only other special thing we need to do is to provide a custom link
|
||
command. This is needed because automake won't assemble the ocamlopt
|
||
command, the list of objects and the C<-cclib> libraries in the
|
||
correct order otherwise.
|
||
|
||
virt_v2v_LINK = \
|
||
$(top_srcdir)/ocaml-link.sh -cclib '-lutils -lgnu' -- ...
|
||
|
||
The actual rules, which you can examine in F<v2v/Makefile.am>, are a
|
||
little bit more complicated than this because they have to handle:
|
||
|
||
=over 4
|
||
|
||
=item *
|
||
|
||
Compiling for byte code or native code.
|
||
|
||
=item *
|
||
|
||
The pattern rules needed to compile the OCaml sources to objects.
|
||
|
||
These are now kept in F<subdir-rules.mk> at the top level, which is
|
||
included in every subdirectory F<Makefile.am>.
|
||
|
||
=item *
|
||
|
||
Adding OCaml sources files to C<EXTRA_DIST>.
|
||
|
||
Automake isn't aware of the complete list of sources for a binary, so
|
||
it will not add them all automatically.
|
||
|
||
=back
|
||
|
||
=head2 VIRT-V2V
|
||
|
||
First a little history. Virt-v2v has been through at least two
|
||
complete rewrites, so this is probably about the third version (but we
|
||
don't intend to rewrite it again). The previous version was written
|
||
in Perl and can be found here:
|
||
L<https://git.fedorahosted.org/git/virt-v2v.git>
|
||
|
||
The current version started out as almost a line-for-line rewrite of
|
||
the Perl code in OCaml + C, and it still has a fairly similar
|
||
structure. Therefore if there are details of this code that you don't
|
||
understand (especially in the details of guest conversion), checking
|
||
the Perl code may help.
|
||
|
||
The files to start with when reading this code are:
|
||
|
||
=over 4
|
||
|
||
=item *
|
||
|
||
F<types.mli>
|
||
|
||
=item *
|
||
|
||
F<v2v.ml>
|
||
|
||
=back
|
||
|
||
F<types.mli> defines all the structures used and passed around when
|
||
communicating between different bits of the program. F<v2v.ml>
|
||
controls how the program runs in stages.
|
||
|
||
After studying those files, you may want to branch out into the input
|
||
modules (F<input_*>), the output modules (F<output_*>) or the
|
||
conversion modules (F<convert_*>). The input and output modules
|
||
define I<-i> and I<-o> options (see the manual). The conversion
|
||
modules define what guest types we can handle and the detailed steps
|
||
involved in converting them.
|
||
|
||
Every other file in this directory is a support module / library of
|
||
some sort. Some code is written in C, especially where we want to use
|
||
an external C library such as libxml2.
|
||
|
||
=head2 VIRT-P2V
|
||
|
||
Virt-p2v is a front end on virt-v2v. ie. All it does is act as a GUI
|
||
front end, and it calls out to virt-v2v to perform the actual
|
||
conversion. Therefore most of the C code in the F<p2v/> subdirectory
|
||
is Gtk (GUI) code, or supporting code for talking to the remote
|
||
conversion server. There is no special support for physical machines
|
||
in virt-v2v. They are converted in the same way as foreign VMs.
|
||
|
||
=head3 Running virt-p2v
|
||
|
||
You can run the F<p2v/virt-p2v> binary directly, but it will try to
|
||
convert your machine’s real F</dev/sda> which is unlikely to work
|
||
well. However virt-p2v also has a test mode in which you can supply a
|
||
test disk:
|
||
|
||
make -C p2v run-virt-p2v-directly
|
||
|
||
This is a wrapper around the L<virt-p2v(1)> I<--test-disk> option.
|
||
You can control the "physical machine" disk by setting
|
||
C<PHYSICAL_MACHINE> to point to a disk image.
|
||
|
||
A more realistic test is to run virt-p2v inside a VM on the local
|
||
machine. To do that, do:
|
||
|
||
make -C p2v run-virt-p2v-in-a-vm
|
||
|
||
This also runs qemu with the "physical machine" disk (which you can
|
||
set by setting C<PHYSICAL_MACHINE>), a virtual CD, and a variety of
|
||
network cards for testing. You can change the qemu binary and add
|
||
extra qemu options by setting C<QEMU> and/or C<QEMU_OPTIONS> on the
|
||
make commandline.
|
||
|
||
A third way to run virt-p2v simulates fairly accurately the program
|
||
being downloaded over PXE and then doing an automatic conversion of
|
||
the source physical machine (the non-GUI path -- see next section
|
||
below):
|
||
|
||
make -C p2v run-virt-p2v-non-gui-conversion
|
||
|
||
=head3 Understanding the virt-p2v code
|
||
|
||
I<See also:> L<virt-p2v(1)/HOW VIRT-P2V WORKS>
|
||
|
||
There are two paths through the code, GUI or non-GUI (parsing the
|
||
kernel command line):
|
||
|
||
main.c ──────┬─────▶ gui.c ──────┬─────▶ conversion.c
|
||
│ │
|
||
│ │
|
||
└────▶ kernel.c ────┘
|
||
|
||
but both paths call back to the F<conversion.c> function
|
||
C<start_conversion> to run the remote virt-v2v.
|
||
|
||
The main task of F<gui.c>/F<kernel.c> is to populate the virt-v2v
|
||
configuration (F<config.c>).
|
||
|
||
During conversion, we need to establish ssh connections, and that is
|
||
done using two libraries:
|
||
|
||
conversion.c ──────▶ ssh.c ──────▶ miniexpect.c
|
||
|
||
where F<ssh.c> is responsible for managing ssh connections overall,
|
||
and F<miniexpect.c> implements "expect-like" functionality for talking
|
||
interactively to the remote virt-v2v conversion server.
|
||
|
||
(Note that miniexpect is a separate library with its own upstream, so
|
||
if you patch miniexpect.c, then please make sure the changes get
|
||
reflected in miniexpect’s upstream too:
|
||
F<http://git.annexia.org/?p=miniexpect.git;a=summary>)
|
||
|
||
=head1 MAINTAINER TASKS
|
||
|
||
=head2 MAINTAINER MAKEFILE TARGETS
|
||
|
||
These C<make> targets probably won’t work and aren't useful unless you
|
||
are a libguestfs maintainer.
|
||
|
||
=head3 make maintainer-commit
|
||
|
||
This commits everything in the working directory with the commit
|
||
message C<Version $(VERSION).>. You must update F<configure.ac>,
|
||
clean and rebuild first.
|
||
|
||
=head3 make maintainer-tag
|
||
|
||
This tags the current HEAD commit with the tag C<v$(VERSION)> and one
|
||
of the messages:
|
||
|
||
Version $(VERSION) stable
|
||
|
||
Version $(VERSION) development
|
||
|
||
(See L<guestfs(3)/LIBGUESTFS VERSION NUMBERS> for the difference
|
||
between a stable and development release.)
|
||
|
||
=head3 make maintainer-check-authors
|
||
|
||
Check that all authors (found in git commit messages) are included in
|
||
the F<generator/authors.ml> file.
|
||
|
||
=head3 make maintainer-check-extra-dist
|
||
|
||
This rule must be run after C<make dist> (so there is a tarball in the
|
||
working directory). It compares the contents of the tarball with the
|
||
contents of git to ensure that no files have been missed from
|
||
F<Makefile.am> C<EXTRA_DIST> rules.
|
||
|
||
=head3 make maintainer-upload-website
|
||
|
||
This is used by the software used to automate libguestfs releases to
|
||
copy the libguestfs website to another git repository before it is
|
||
uploaded to the web server.
|
||
|
||
=head2 MAKING A STABLE RELEASE
|
||
|
||
When we make a stable release, there are several steps documented
|
||
here. See L<guestfs(3)/LIBGUESTFS VERSION NUMBERS> for general information
|
||
about the stable branch policy.
|
||
|
||
=over 4
|
||
|
||
=item *
|
||
|
||
Check C<make && make check> works on at least:
|
||
|
||
=over 4
|
||
|
||
=item Fedora (x86-64)
|
||
|
||
=item Debian (x86-64)
|
||
|
||
=item Ubuntu (x86-64)
|
||
|
||
=item Fedora (aarch64)
|
||
|
||
=item Fedora (ppc64)
|
||
|
||
=item Fedora (ppc64le)
|
||
|
||
=back
|
||
|
||
=item *
|
||
|
||
Check C<./configure --without-libvirt> works.
|
||
|
||
=item *
|
||
|
||
Finalize F<guestfs-release-notes.pod>
|
||
|
||
=item *
|
||
|
||
Push and pull from Zanata.
|
||
|
||
Run:
|
||
|
||
zanata push
|
||
|
||
to push the latest POT files to Zanata. Then run:
|
||
|
||
./zanata-pull.sh
|
||
|
||
which is a wrapper to pull the latest translated F<*.po> files.
|
||
|
||
=item *
|
||
|
||
Consider updating gnulib to latest upstream version.
|
||
|
||
=item *
|
||
|
||
Create new stable and development directories under
|
||
L<http://libguestfs.org/download>.
|
||
|
||
=item *
|
||
|
||
Edit F<website/index.html.in>.
|
||
|
||
=item *
|
||
|
||
Set the version (in F<configure.ac>) to the new I<stable> version,
|
||
ie. 1.XX.0, and commit it:
|
||
|
||
./localconfigure
|
||
make distclean -k
|
||
./localconfigure
|
||
make && make dist
|
||
make maintainer-commit
|
||
make maintainer-tag
|
||
|
||
=item *
|
||
|
||
Create the stable branch in git:
|
||
|
||
git branch stable-1.XX
|
||
git push origin stable-1.XX
|
||
|
||
=item *
|
||
|
||
Do a full release of the stable branch.
|
||
|
||
=item *
|
||
|
||
Set the version to the next development version and commit that.
|
||
Optionally do a full release of the development branch.
|
||
|
||
=back
|
||
|
||
=head1 INTERNAL DOCUMENTATION
|
||
|
||
This section documents internal functions inside libguestfs and
|
||
various utilities. It is intended for libguestfs developers only.
|
||
|
||
This section is autogenerated from C</**> comments in source files,
|
||
which are marked up in POD format.
|
||
|
||
B<These functions are not publicly exported, and may change or be
|
||
removed at any time.>
|
||
|
||
__INTERNAL_DOCUMENTATION__
|
||
|
||
=head1 SEE ALSO
|
||
|
||
L<guestfs(3)>,
|
||
L<guestfs-building(1)>,
|
||
L<guestfs-examples(3)>,
|
||
L<guestfs-internals(1)>,
|
||
L<guestfs-performance(1)>,
|
||
L<guestfs-release-notes(1)>,
|
||
L<guestfs-testing(1)>,
|
||
L<libguestfs-test-tool(1)>,
|
||
L<libguestfs-make-fixed-appliance(1)>,
|
||
L<http://libguestfs.org/>.
|
||
|
||
=head1 AUTHORS
|
||
|
||
Richard W.M. Jones (C<rjones at redhat dot com>)
|
||
|
||
=head1 COPYRIGHT
|
||
|
||
Copyright (C) 2009-2017 Red Hat Inc.
|