=head1 NAME

p2v-hacking - extending and contributing to virt-p2v

=head1 DESCRIPTION

This manual page is for hackers who want to extend virt-p2v itself.

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

=head1 THE SOURCE CODE

Virt-p2v source is located in the github repository
L<https://github.com/libguestfs/virt-p2v>

Virt-p2v uses an autotools-based build system, with the main files
being F<configure.ac> and F<Makefile.am>.  See L</THE BUILD SYSTEM>.

To build from source, first read the L<p2v-building(1)>.

=head2 SOURCE CODE SUBDIRECTORIES

The majority of the source code is directly in the top level directory
of the sources.  There are also some subdirectories that contain some
specific sub-parts of virt-p2v.

=over 4

=item F<bash>

Bash tab-completion scripts.

=item F<build-aux>

Various build scripts used by autotools.

=item F<miniexpect>

A copy of the miniexpect library from
L<http://git.annexia.org/?p=miniexpect.git;a=summary>.

=item F<contrib>

Outside contributions, experimental parts.

=item F<docs>

Miscellaneous manual pages.

=item F<gnulib>

Gnulib is used as a portability library.  A copy of gnulib is included
under here.

=item F<libguestfs>

Some sources (mostly with utilities) copied from libguestfs.  Changes
to the sources there ought to be forwarded to libguestfs as well.

=item F<m4>

M4 macros used by autoconf.  See L</THE BUILD SYSTEM>.

=item F<website>

The virt-p2v files of the L<http://libguestfs.org> website.

=back

=head2 THE BUILD SYSTEM

Virt-p2v uses the GNU autotools build system (autoconf, automake).

The F<./configure> script is generated from F<configure.ac> and
F<m4/p2v-*.m4>.  Most of the configure script is split over many
m4 macro files by topic, for example F<m4/p2v-libraries.m4> deals
with the libraries required by virt-p2v.

F<subdir-rules.mk> is included in every F<Makefile.am> (top level and
subdirectories).

=head2 UNDERSTANDING THE 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 RUNNING VIRT-P2V

You can run the F<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 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 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 run-virt-p2v-non-gui-conversion

=head1 EXTENDING VIRT-P2V

=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 your start-up files
(e.g., ~/.emacs), to help ensure that you get indentation right:

 ;;; In virt-p2v, indent with spaces everywhere (not TABs).
 ;;; Exceptions: Makefile and ChangeLog modes.
 (add-hook 'find-file-hook
     '(lambda () (if (and buffer-file-name
                          (string-match "/virt-p2v\\>"
                              (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 virt-p2v, use this style.
 (defun virt-p2v-c-mode ()
   "C mode with adjusted defaults for use with virt-p2v."
   (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 "/virt-p2v\\>"
                               (buffer-file-name))
                           (virt-p2v-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.

=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

=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<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.

=head1 SEE ALSO

L<p2v-building(1)>,
L<p2v-release-notes(1)>,
L<http://libguestfs.org/>.

=head1 AUTHORS

Richard W.M. Jones (C<rjones at redhat dot com>)

=head1 COPYRIGHT

Copyright (C) 2009-2019 Red Hat Inc.
