## open-iscsi boot test
The purpose of this test (`CloudImageTest`) is to test the boot of a system
using an iscsi root target.  In order to accomplish that, the tests does

  1. Download Ubuntu cloud image
  2. installs the open-iscsi deb inside
  3. collect kernel and initramfs from inside
  4. register the image as a read-only iscsi target served by tgt
  5. boot kernel and initramfs with a command line to use the image as root.
     And additionally attach a local disk for collecting output.
  6. provide user-data that executes commands, colects files and writes them
     to the output disk and then shuts the system down.
  7. extract the collected files from the output disk and inspect them.

The `CloudImageTest` uses qemu user networking.


## Caveats

  1. It depends on a cloud-image being present.

     Cloud-images are often not available for the first few weeks of a cycle.
     If no cloud-image of 'REL' is available, then boot-test will skip.
     If 'REL' is not known in distro-info-data, then test will fail.

     This means that uploads of open-iscsi (or its dependencies) will not
     be properly tested until a cloud-image is available, and will fail
     until distro-info-data is uploaded.

  2. Installation of large packages via patch-image may fail.
     An ubuntu image downloaded has only a small amount of extra space.
     Installation of a new kernel into the target would probably fail.

     If this becomes a problem, we could grow the disk like done at
       https://gist.github.com/smoser/6a048a0e2795b48221fc44962202fa14


### testing manually ###
The test case in `debian/tests/test-open-iscsi.py` uses some helper tools.

  * **patch-image**: this is used to install packages into the pristine image
     and collect the kernel and initramfs out of the image.  This allows us to
     test the portions of open-iscsi that update the initramfs.  Without
     using the updated initramfs we wouldn't really be testing the new
     open-iscsi.

     It will upgrade any packages inside that are mentioned in
     ADT_TEST_TRIGGERS environment.  It will also install open-iscsi if
     it is not in that list.

     It installs packages into the target by copying the host system's
     /etc/apt content in, and also includes copying local (file://) apt
     repos into the target.  This is necessary for the autopackage test
     environment that adds local package repositories to sources.list.d.

     It may also make other changes to the image to workaround bugs.
     See --help output for list of bugs.

  * **get-image**: This downloads an image from cloud-images.ubuntu.com.  See
     its Usage for more information.  it downloads via stream data and verifies
     download.  One thing to note is that it does not overwrite existing files.

  * **tgt-boot-test**: this registers an image in tgt locally, and then boots
     kernel and initramfs to mount that.  It knows how to build iscsi kernel
     command lines.

     By default, the xkvm process that is started will be allowed `60m` to
     complete.  This can be adjusted by setting `BOOT_TIMEOUT` in the
     environment.

  * **xkvm**: this is a helper/wrapper around qemu.  It is taken from the curtin
     projects tools/ directory.  It allows some simplified command lines, and
     most usefully, the '--netdev=<bridge>' argument will create a tun/tap
     device and attach it to the bridge.

     If the host system is not bare metal, kvm will not be
     enabled in the guest that is lauched.  To force use of kvm, set
     _USE_KVM=1 in the environment.  See 'should_try_kvm' in xkvm for details.

Testing manually looks like this:

    ## set up path to include debian/tests directory.
    $ PATH=$PWD/debian/tests:$PATH

    ## Get the image you want.  This creates out.d/disk.img and disk.img.dist
    $ get-image xenial.d xenial

    ## patch the image with an open-iscsi, which creates xenial.d/kernel
    ## and xenial.d/initrd from the kernel and initramfs inside the image.
    $ apt-get download open-iscsi
    $ deb=$(ls open-iscsi_*.deb | tail -n 1)
    $ sudo ./debian/tests/patch-image \
         --kernel=xenial.d/kernel --initrd=xenial.d/initrd
         xenial.d/disk.img "$deb"

    ## Boot the system, log in, look around.
    $ tgt-boot-test -v xenial.d/disk.img xenial.d/kernel xenial.d/initrd


### Features of tgt-boot-test ###

tgt-boot-test does a number of useful things.

 * determines the host address that the guest will use.
   This should support ipv6 and ipv4 addresses on bridges, and
   knows values that qemu's user networking uses.  Flags passed to `--netdev`
   are read intelligently.  This can be overriden with `--host-addr`, but
   it does a good job of determining what the right values are.

 * provides a nocloud metadata service with a python web server that
   supports ipv4 and ipv6.

 * provides the ability to provide additional kernel command line options
   or to provide a 'template' that references variables it knows such as
   {iserver} (iscsi server) or {seed_url}.

 * Sets ubuntu (passw0rd) and root password (root) and imports users
   ssh keys to the ubuntu user.

One thing to note is that yakkety's version of qemu does not run an ipv6
dhcp server on its user-network, so a stateful dhclient request will not
work.

In order to create a bridge easily with a ipv6 dhcp server, you can use
lxd at sufficent version (https://github.com/lxc/lxd/issues/2481).
Assuming that bug is fixed, to create an ipv6 only bridge:

    $ netname="ipv6-only"
    $ lxc network create $netname
    $ lxc network unset $netname ipv4.address
    $ lxc network unset $netname ipv4.nat
    $ lxc network set $netname ipv6.dhcp.stateful true

Then, you can use tgt-boot-test with that:

    $ PATH=$PWD/debian/tests:$PATH
    $ ./debian/tests/tgt-boot-test -vv --netdev=ipv6-only \
       --cmdline-ip="ip=off ip6=dhcp" \
       disk.img kernel initramfs
