2
# Run all tests in various versions of Ubuntu via lxc.
3
# Use of a local apt-cacher-ng instance and setting MIRROR in /etc/default/lxc
4
# is strongly recommended, to speed up creation of pristine images:
5
# MIRROR="http://localhost:3142/archive.ubuntu.com/ubuntu"
6
# lxc commands depend heavily on sudo. Edit your sudo configuration and give
7
# the user that will run these tests the ability to run lxc commands without
8
# password. Something like this works:
9
# Cmnd_Alias LXC_COMMANDS = /usr/bin/lxc-create, /usr/bin/lxc-start, \
10
# /usr/bin/lxc-destroy, /usr/bin/lxc-attach, /usr/bin/lxc-start-ephemeral, \
11
# /usr/bin/lxc-stop, /usr/bin/lxc-ls, /usr/bin/lxc-info, /usr/bin/lxc-wait
12
# your-user ALL=NOPASSWD: LXC_COMMANDS
16
TIMING=$LOG_DIR/timing.dat
19
/usr/bin/python /usr/bin/pastebinit "$@";
22
# User-tunable options.
23
# KEEP_DATA is actually a set of options to lxc-start-ephemeral, notably it
24
# can contain "--keep-data", in which case it will use a directory-backed
25
# overlayfs to create the ephemeral VM. Setting KEEP_DATA to an empty string
26
# will put the overlayfs in ramdisk (tmpfs), which is much faster but
27
# requires more RAM (don't run this on a system with less than 3GB total RAM),
28
# so the default is to --keep-data.
29
KEEP_DATA=${KEEP_DATA:-"--keep-data"}
30
# The name of the user we will create inside the container, we will also
31
# run commands inside the container as this user, using sudo.
34
# Location of LXC executables.
35
LXC_CREATE=`which lxc-create`
36
LXC_START=`which lxc-start`
37
LXC_STOP=`which lxc-stop`
38
LXC_DESTROY=`which lxc-destroy`
39
LXC_START_EPHEMERAL=`which lxc-start-ephemeral`
40
LXC_ATTACH=`which lxc-attach`
42
LXC_WAIT=`which lxc-wait`
43
LXC_INFO=`which lxc-info`
47
for tool in "$LXC_CREATE" "$LXC_START" "$LXC_STOP" "$LXC_DESTROY" \
48
"$LXC_ATTACH" "$LXC_WAIT" "$LXC_INFO"; do
49
if [ -z "$tool" ]; then
50
echo "lxc commands not found, maybe you need to install lxc"
53
if ! sudo -n $tool --version >/dev/null 2>&1; then
55
echo "I can't run $tool, maybe you need to give me sudo permissions"
65
pristine_container=${1}-pristine
66
target_container=${1}-testing
67
[ "$target" != "" ] || return 1
69
# Ensure we have a pristine container, create it otherwise.
70
if ! sudo $LXC_LS |grep -q $pristine_container; then
71
step="[$target] creating pristine container"
73
if ! /usr/bin/time -o $TIMING sudo $LXC_CREATE -n $pristine_container -t ubuntu -- -r $target --user=$CONTAINER_USER --packages=python-software-properties,software-properties-common,python3-dev >$LOG_DIR/$target.pristine.log 2>$LOG_DIR/$target.pristine.err; then
75
echo "[$target] Unable to create pristine container!"
76
echo "[$target] stdout: $(pastebinit $LOG_DIR/$target.pristine.log)"
77
echo "[$target] NOTE: unable to execute tests, marked as failed"
78
echo "[$target] Trying to destroy to reclaim possible resources"
79
sudo $LXC_DESTROY -f -n $pristine_container
82
cat $TIMING | sed -e "s/^/[$target] (timing) /"
83
# TODO: Add --provision-pristine to do exactly that, that way it will be faster
84
# at the expense of not updating dependencies for every run. It'll be useful
85
# for testing. It's a bit hard because we can't do the bind mount (-b), an alternative
86
# is to use -s to mimic bindmount (problem: target dir not created by default
88
step="[$target] starting container"
90
if ! /usr/bin/time -o $TIMING sudo $LXC_START_EPHEMERAL $KEEP_DATA -d -o $pristine_container -n $target_container -b $PWD >$LOG_DIR/$target.startup.log 2>$LOG_DIR/$target.startup.err; then
92
echo "[$target] Unable to start ephemeral container!"
93
echo "[$target] stdout: $(pastebinit $LOG_DIR/$target.startup.log)"
94
echo "[$target] stderr: $(pastebinit $LOG_DIR/$target.startup.err)"
95
echo "[$target] NOTE: unable to execute tests, marked as failed"
96
echo "[$target] Destroying failed container to reclaim resources"
97
sudo $LXC_DESTROY -f -n $target_container
100
cat $TIMING | sed -e "s/^/[$target] (timing) /"
102
# Before provisioning, try to detect and configure apt-cacher-ng
103
if [ -n "$VAGRANT_APT_CACHE" ]; then
105
sudo $LXC_ATTACH --keep-env -n $target_container -- bash -c "echo 'Acquire::http { Proxy \"$VAGRANT_APT_CACHE\"; };' > /etc/apt/apt.conf"
106
elif [ -e /etc/apt-cacher-ng ]; then
107
# Autodetected local apt-cacher-ng, find out the host IP address to
108
# pass into the container
109
APT_CACHER_IP=$(ip route get 8.8.8.8 | awk 'NR==1 {print $NF}')
110
[ -n "$APT_CACHER_IP" ] && sudo $LXC_ATTACH --keep-env -n $target_container -- bash -c "echo 'Acquire::http { Proxy \"http://$APT_CACHER_IP:3142\"; };' > /etc/apt/apt.conf"
113
# Unlike with Vagrant, we have to provision the VM "manually" here.
114
# However we can leverage the same script :D
115
step="[$target] provisioning container"
117
if ! /usr/bin/time -o $TIMING sudo $LXC_ATTACH --keep-env -n $target_container >$LOG_DIR/$target.provision.log 2>$LOG_DIR/$target.provision.err -- bash -c "support/provision-testing-environment $PWD"; then
118
echo "[$target] Unable to provision requirements in container!"
119
echo "[$target] stdout: $(pastebinit $LOG_DIR/$target.provision.log)"
120
echo "[$target] stderr: $(pastebinit $LOG_DIR/$target.provision.err)"
122
echo "[$target] Destroying failed container to reclaim resources"
123
sudo $LXC_DESTROY -f -n $target_container
126
cat $TIMING | sed -e "s/^/[$target] (timing) /"
131
# provision-testing-environment runs as root and creates a series of
132
# root-owned files in the branch directory. Later, tarmac will want
133
# to delete these files, so after provisioning we change everything
134
# under the branch directory to be owned by the unprivileged user,
135
# so stuff can be deleted correctly later.
136
echo "[$target] Fixing file permissions in source directory"
137
if ! sudo $LXC_ATTACH --keep-env -n $target_container -- bash -c "chown -R --reference=test-in-lxc.sh $PWD" >$LOG_DIR/$target.fix-perms.log 2>$LOG_DIR/$target.fix-perms.err; then
138
echo "[$target] Unable to fix permissions!"
139
echo "[$target] stdout: $(pastebinit $LOG_DIR/$target.fix-perms.log)"
140
echo "[$target] stderr: $(pastebinit $LOG_DIR/$target.fix-perms.err)"
141
echo "[$target] Some files owned by root may have been left around, fix them manually with chown."
145
if [ "$1" = "" ]; then
146
# Releases we actually want to test should be included in target_list below.
147
target_list="precise trusty"
152
PASS="$(printf "\33[32;1mPASS\33[39;0m")"
153
FAIL="$(printf "\33[31;1mFAIL\33[39;0m")"
157
test_lxc_can_run || exit 1
159
for target_release in $target_list; do
160
if ! start_lxc_for $target_release; then
164
# Our actual container has "-testing" appended.
165
target=${target_release}-testing
166
# Display something before the first test output
167
echo "[$target] Starting tests..."
169
# Run test suite commands here.
170
# Tests are found in each component's requirements/ dir and are named *container-tests-*
171
# Numbers can be used at the beginning to control running order within each component.
172
# Tests scripts are expected to:
173
# - Be run from the *component's* top-level directory. This is a convenience to avoid
174
# a boilerplate "cd .." on every test script. So for 'plainbox' we do the equivalent of
175
# $ cd $BLAH/plainbox
177
# - Exit 0 for success, other codes for failure
178
# - Write logs/debugging data to stdout and stderr.
179
for test_script in $(find ./ -path '*/requirements/*container-tests-*' | sort); do
180
echo "Found a test script: $test_script"
181
test_name=$(basename $test_script)
182
# Two dirnames strips the requirements/ component
183
component_dir=$(dirname $(dirname $test_script))
184
# Inside the LXC container, tests are relative to $HOME/src
185
script_md5sum=$(echo $test_script | md5sum |cut -d " " -f 1)
186
logfile=$LOG_DIR/${target}.${test_name}.${script_md5sum}.log
187
errfile=$LOG_DIR/${target}.${test_name}.${script_md5sum}.err
188
if /usr/bin/time -o $TIMING sudo $LXC_ATTACH --keep-env -n $target -- bash -c 'cd $HOME/src/'"$component_dir && ./requirements/$test_name" >$logfile 2>$errfile
190
echo "[$target] ${test_name}: $PASS"
193
echo "[$target] ${test_name}: $FAIL"
194
echo "[$target] stdout: $(pastebinit $logfile)"
195
echo "[$target] stderr: $(pastebinit $errfile)"
197
cat $TIMING | sed -e "s/^/[$target] (timing) /"
202
echo "[$target] Destroying container"
203
# Stop the container first
204
if ! sudo $LXC_STOP -n $target >$LOG_DIR/$target.stop.log 2>$LOG_DIR/$target.stop.err; then
205
echo "[$target] Unable to stop container!"
206
echo "[$target] stdout: $(pastebinit $LOG_DIR/$target.stop.log)"
207
echo "[$target] stderr: $(pastebinit $LOG_DIR/$target.stop.err)"
208
echo "[$target] You may need to manually 'sudo lxc-stop -n $target' to fix this"
210
# Wait for container to actually stop
211
sudo $LXC_WAIT -n $target -s 'STOPPED'
212
# If still present, then destroy it
213
if sudo $LXC_INFO -n $target; then
214
if ! sudo $LXC_DESTROY -n $target -f >$LOG_DIR/$target.destroy.log 2>$LOG_DIR/$target.destroy.err; then
215
echo "[$target] Unable to destroy container!"
216
echo "[$target] stdout: $(pastebinit $LOG_DIR/$target.destroy.log)"
217
echo "[$target] stderr: $(pastebinit $LOG_DIR/$target.destroy.err)"
218
echo "[$target] You may need to manually 'sudo lxc-destroy -f -n $target' to fix this"
222
# Propagate failure code outside