Commit Graph

22 Commits

Author SHA1 Message Date
Anders Kaseorg c4ed4bc021 test-install: Fix shellcheck warnings.
In tools/test-install/destroy-all line 31:
  | while read c
          ^-- SC2162: read without -r will mangle backslashes.

In tools/test-install/install line 57:
    installer_dir="$(readlink -f $INSTALLER)"
                                 ^-- SC2086: Double quote to prevent globbing and word splitting.

In tools/test-install/lxc-wait line 30:
for i in {1..60}; do
^-- SC2034: i appears unused. Verify use (or export if used externally).

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2018-08-03 09:15:27 -07:00
Greg Price 8111848ac4 test-install: Do a dist-upgrade in prepare-base.
This keeps the base tree up to date, saving the time we'd spend
doing the same upgrades in each test install.
2018-03-06 19:43:02 -08:00
Aditya Bansal 35969edd66 deps: Replace libz-dev with zlib1g-dev since the former was renamed. 2018-02-12 14:40:26 -08:00
Greg Price 86590dfdbe test-install: Add command destroy-all to clean up test containers.
This is just the one-liner I've been keeping in my shell history,
cleaned up a bit (newlines!) and with 28 lines of CLI boilerplate
added in front.
2018-02-08 17:29:41 -08:00
Greg Price 6e633f8e2f install: Use readlink -f rather than realpath.
It does exactly the same thing, though the name is less transparent; and
it simplifies the script by avoiding an extra, early `apt-get install`.
2018-02-08 17:22:02 -08:00
Greg Price 4c5326ce85 test-install: Factor out booted-yet-p polling loop, use in prepare-base.
Otherwise prepare-base is likely to fail when first run (but then
succeed when rerun, because the container is left running), because
the container isn't up yet when we try to operate in it.

Also clean up the placement of `set -e` vs `set -x`.
2018-02-08 16:34:49 -08:00
Greg Price fc9970e561 test-install: Add xenial support. 2018-02-08 16:34:49 -08:00
Greg Price 9476a3a334 test-install: Give the host a direct view of the guest's /tmp/src/.
(This is a small fixup to the main change, which was accidentally
included in a previous commit:
  08bbd7e61 "settings: Slightly simplify EMAIL_BACKEND logic."
Oops.  See there for most of the changes described here.)

The installer works out of a release-tarball tree.  We typically want
to share this tree between successive test-install runs (with an rsync
or similar command to update source files of interest) because
rebuilding a release tree from scratch is slow.  But the installer
will munge the tree; so instead of directly bind-mounting the tree
into the container, we need to give it an overlay over the tree, as a
sandbox to play in.

Previously we used lxc-copy's `-m overlay=...` feature to do this,
mounting an overlay in the container.  But then sometimes in
development we want to reach in and edit some code in the tree,
e.g. before rerunning the installer after something failed.  Reaching
inside the container for this is a pain (`ssh` would add latency, and
I haven't installed sshd in the containers; and getting rsync to work
with `lxc-attach` was beyond what I could figure out in a few minutes
of fiddling); and editing the base tree often doesn't work.

So, create the overlay with our own `mount -t overlay`, and have
`lxc-copy` just bind-mount that in.  Now the host has direct access to
the same overlay which the guest is working from.

Also this makes it past time to help the user out in finding the fresh
names we've created: first the container, now this shared tree.  Print
those at the end, rather than make the user scroll to the top and find
the right `set -x` line to copy-paste from.
2018-01-29 10:27:11 -08:00
Greg Price 08bbd7e61d settings: Slightly simplify EMAIL_BACKEND logic.
DEVELOPMENT is defined as just `not PRODUCTION`, but this code made
it look like things might be more complicated than that.
2018-01-24 14:34:30 -08:00
Greg Price 841a5f3152 install: Say --self-signed-cert instead of --snakeoil-cert.
Less evocative, but requires less explanation to document because
it's a well-known term on the Internet.
2018-01-23 18:08:52 -08:00
Greg Price 2a59b2d2ac install: Work around a bug in the (our) Debian package for camo.
Before this fix, the installer has an extremely annoying bug where
when run inside a container with `lxc-attach`, when the installer
finishes, the `lxc-attach` just hangs and doesn't respond even to
C-c or C-z.  The only way to get the terminal back is to root around
from some other terminal to find the PID and kill it; then run
something like `stty sane` to fix the messed-up terminal settings
left behind.

After bisecting pieces of the install script to locate which step
was causing the issue, it comes down to the `service camo restart`.
The comment here indicates that we knew about an annoying bug here
years ago, and just swept it under the rug by skipping this step
when in Travis. >_<

The issue can be reproduced by running simply `service camo restart`
under `lxc-attach` instead of the installer; or `service camo start`,
following a `service camo stop`.  If `lxc-attach` is used to get an
interactive shell, these commands appear to work fine; but then when
that shell exits, the same hang appears.  So, when we start camo
we're evidently leaving some kind of mess that entangles the daemon
with our shell.

Looking at the camo initscript where it starts the daemon, there's
not much code, and one flag jumps out as suspicious:

  start-stop-daemon --start --quiet --pidfile $PIDFILE -bm \
    --exec $DAEMON --no-close -c nobody --test > /dev/null 2>&1 \
    || return 1
  start-stop-daemon --start --quiet --pidfile $PIDFILE -bm \
    --no-close -c nobody --exec $DAEMON -- \
    $DAEMON_ARGS >> /var/log/camo/camo.log 2>&1 \
    || return 2

What does `--no-close` do?

 -C, --no-close
     Do not close any file descriptor when forcing the daemon
     into  the  background  (since version 1.16.5).  Used for
     debugging purposes to see  the  process  output,  or  to
     redirect  file  descriptors  to  log the process output.

And in fact, looking in /proc/PID/fd while a hang is happening finds
that fd 0 on the camo daemon process, aka stdin, is connected to our
terminal.

So, stop that by denying the initscript our stdin in the first place.
This fixes the problem.

The Debian maintainer turns out to be "Zulip Debian Packaging Team",
at debian@zulip.com; so this package and its bugs are basically ours.
2018-01-22 18:55:46 -08:00
Greg Price 6e7ae9a239 test-install: Run installer under eatmydata.
This is a tool that throws away `fsync` calls and other requests for
the system to sync files to disk.  It may make the install faster; for
example, if it has to install a number of system packages, `dpkg` is
known to make a lot of `fsync` calls which slow things down
significantly.  Conversely, if there's a power failure in the middle
of running a test install, we really don't mind if the test install's
data becomes corrupt.
2018-01-22 18:55:46 -08:00
Greg Price eb25928674 test-install: Allow the installer to move the install tree aside.
When the install script is successful, one of the final things it
wants to do is to move the tree that Zulip was installed from into the
deployments directory.  It can't do that, at least not in a naive way
with `mv`, if the tree is actually a mount point.  So, stick the tree
inside some other directory that we create just for the purpose of
being the mount point and containing the install tree.
2018-01-22 18:55:46 -08:00
Greg Price b0a9117e80 test-install: Pre-install a few more dependencies in base image. 2018-01-22 18:55:46 -08:00
Greg Price 0e3ab4d437 test-install: Share the pip cache across installs.
This saves several minutes off the install time.  Sadly pip still
clones Git repos for dependencies that point to them, but for many
others (not all? not sure) it just gets a wheel from the cache.
2018-01-22 18:55:46 -08:00
Greg Price 69ba6ad6d7 test-install: Let installer handle the snakeoil cert. 2018-01-22 18:55:46 -08:00
Greg Price 7b47cca67e test-install: Pre-install two more dependencies in base image. 2018-01-22 18:55:46 -08:00
Greg Price 525b136f10 install: Install curl.
The third-party `install-yarn.sh` script uses `curl`, and we invoke it
in `install-node`.  So we need to install it as a dependency.

We've mostly gotten away with this because it's common for `curl` to
already be installed; but it isn't always.
2018-01-22 18:55:46 -08:00
Greg Price 07969a2b0c test-install: Share the tarball directory between host and container.
This greatly simplifies iterating on changes to the installer and
associated code: just edit in the shared directory (or edit in your
worktree and rsync to the directory), and rerun.

With this change, the form with a directory is now really the main
way to run the script; the form accepting a tarball is really just
a convenience feature, unpacking the tarball and then proceeding with
that directory.
2018-01-22 18:55:46 -08:00
Greg Price d7e2190b85 test-install: Pass options through to the installer.
This will facilitate testing interesting installer features
using its own CLI.

On my laptop, with a recent base image (updated a few days ago with
`prepare-base`), it takes just 7 or 8 seconds to get to the installer
running, as timed by passing `--help` so that the installer promptly
exits.
2018-01-22 18:55:45 -08:00
Greg Price de7abd8f78 test-install: Upgrade CLI parsing, with getopt.
This will let us add more options without the CLI collapsing under
its own weight.
2018-01-22 18:55:45 -08:00
Greg Price bf5f1b5f20 install: Start on an LXC-based dev/test environment for the installer.
In order to do development on the installer itself in a sane way,
we need a reasonably fast and automatic way to get a fresh environment
to try to run it in.

This calls for some form of virtualization.  Choices include

 * A public cloud, like EC2 or Digital Ocean.  These could work, if we
   wrote some suitable scripts against their APIs, to manage
   appropriate base images (as AMIs or snapshots respectively) and to
   start fresh instances/droplets from a base image.  There'd be some
   latency on starting a new VM, and this would also require the user
   to have an account on the relevant cloud with API access to create
   images and VMs.

 * A local whole-machine VM system (hypervisor) like VirtualBox or
   VMware, perhaps managing the configuration through Vagrant.  These
   hypervisors can be unstable and painfully slow.  They're often the
   only way to get development work done on a Mac or Windows machine,
   which is why we use them there for the normal Zulip development
   environment; but I don't really want to find out how their
   instability scales when constantly spawning fresh VMs from an image.

 * Containers.  The new hotness, the name on everyone's lips, is Docker.
   But Docker is not designed for virtualizing a traditional Unix server,
   complete with its own init system and a fleet of processes with a
   shared filesystem -- in other words, the platform Zulip's installer
   and deployment system are for.  Docker brings its own quite
   different model of deployment, and someday we may port Zulip from
   the traditional Unix server to the Docker-style deployment model,
   but for testing our traditional-Unix-server deployment we need a
   (virtualized) traditional Unix server.

 * Containers, with LXC.  LXC provides containers that function as
   traditional Unix servers; because of the magic of containers, the
   overhead is quite low, and LXC offers handy snapshotting features
   so that we can quickly start up a fresh environment from a base
   image.  Running LXC does require a Linux base system.  For
   contributors whose local development machine isn't already Linux,
   the same solutions are available as for our normal development
   environment: the base system for running LXC could be e.g. a
   Vagrant-managed VirtualBox VM, or a machine in a public cloud.

This commit adds a first version of such a thing, using LXC to manage
a base image plus a fresh container for each test run.  The test
containers function as VMs: once installed, all the Zulip services run
normally in them and can be managed in the normal production ways.

This initial version has a shortage of usage messages or docs, and
likely has some sharp edges.  It also requires familiarity with the
basics of LXC commands in order to make good use of the resulting
containers: `lxc-ls -f`, `lxc-attach`, `lxc-stop`, and `lxc-start`,
in particular.
2018-01-19 17:27:04 -08:00