1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2025-04-01 23:57:05 +00:00

change from vagrant to lxd as the virtualization system

This commit is contained in:
downtownallday 2024-09-02 17:09:59 -04:00
parent a79a6c00eb
commit a1d6f67135
23 changed files with 1591 additions and 19 deletions

View File

@ -1 +1,3 @@
.emacs
backup/
vm_keys/

234
tests/bin/lx_functions.sh Normal file
View File

@ -0,0 +1,234 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
# source this file
lx_project_root_dir() {
local d="$PWD"
while [ ${#d} -gt 1 ]; do
if [ -e "$d/setup" ]; then
echo "$d"
return 0
fi
d="$(dirname "$d")"
done
return 1
}
lx_guess_project_name() {
local d
d="$(lx_project_root_dir)"
[ $? -ne 0 ] && return 1
if [ -e "$d/setup/redis.sh" ]; then
echo "ciab"
else
echo "miab"
fi
}
# get the interface with the default route (first one)
get_system_default_network_interface() {
ip route | awk '/^default/ {printf "%s", $5; exit 0}'
}
isa_bridge_interface() {
local interface="$1"
if ip --oneline link show type bridge | awk -F: '{print $2}' | grep -q "^ *$interface *\$"; then
echo "yes"
else
echo "no"
fi
}
isa_wifi_device() {
local interface="$1"
local type
type="$(nmcli d show "$interface" | awk '$1=="GENERAL.TYPE:" {print $2}')"
if [ "$type" = "wifi" ]; then
echo "yes"
else
echo "no"
fi
}
# delete an instance
lx_delete() {
local project="${1:-default}"
local inst="$2"
local interactive="${3:-interactive}"
local xargs=""
if [ "$interactive" = "interactive" ]; then
xargs="-i"
fi
# only delete instance if the instance exists
if [ "$(lxc --project "$project" list name="$inst" -c n -f csv)" = "$inst" ]; then
lxc --project "$project" delete "$inst" -f $xargs
fi
}
# create a virtual-machine instance and start it
lx_launch_vm() {
local project="${1:-default}"
local inst_name="$2"
lx_init_vm "$@" || return 1
lxc --project "$project" start "$inst_name" || return 1
}
# create a virtual-machine instance (stopped)
lx_init_vm() {
local project="${1:-default}"
local inst_name="$2"
local image="$3"
local mount_host="$4" # path that you want available in guest
local mount_guest="$5" # mountpoint in guest
shift; shift; shift; shift; shift;
# 1. this assumes that a bridge profile has been created called "bridgenet"
# 2. this assumes that storage named the same as project exists,
# e.g. "lxc storage create $project dir" was executed prior.
case "${@}" in
*bridgenet* )
echo "Using network 'bridgenet'"
lxc --project "$project" profile show bridgenet | sed 's/^/ /' || return 1
;;
esac
lxc --project "$project" init "$image" "$inst_name" --vm --storage "$project" "$@" || return 1
if [ ! -z "$mount_host" -a ! -z "$mount_guest" ]; then
echo "adding $mount_guest on $inst_name to refer to $mount_host on host as device '${project}root'"
if [ $EUID -ne 0 ]; then
# so that files created by root on the mount inside the
# guest have the permissions of the current host user and
# not root:root
# see: https://documentation.ubuntu.com/lxd/en/latest/userns-idmap/
local egid="$(id --group)"
local idmap="uid $EUID 0
gid $egid 0"
lxc --project "$project" config set "$inst_name" raw.idmap="$idmap"
fi
lxc --project "$project" config device add "$inst_name" "${project}root" disk source="$(realpath "$mount_host")" path="$mount_guest" || return 1
fi
}
lx_launch_vm_and_wait() {
local project="$1"
local inst="$2"
local base_image="$3"
local mount_project_root_to="$4"
shift; shift; shift; shift;
# Delete existing instance, if it exists
lx_delete "$project" "$inst" interactive || return 1
# Create the instance (started)
lx_launch_vm "$project" "$inst" "$base_image" "$(lx_project_root_dir)" "$mount_project_root_to" "$@" || return 1
lx_wait_for_boot "$project" "$inst" || return 1
}
lx_output_inst_list() {
# Pre-defined column shorthand chars:
# 4 - IPv4 address
# 6 - IPv6 address
# a - Architecture
# b - Storage pool
# c - Creation date
# d - Description
# D - disk usage
# e - Project name
# l - Last used date
# m - Memory usage
# M - Memory usage (%)
# n - Name
# N - Number of Processes
# p - PID of the instance's init process
# P - Profiles
# s - State
# S - Number of snapshots
# t - Type (persistent or ephemeral)
# u - CPU usage (in seconds)
# L - Location of the instance (e.g. its cluster member)
# f - Base Image Fingerprint (short)
# F - Base Image Fingerprint (long)
local project="$1"
local columns="${2:-ns46tSL}"
local format="${3:-table}" # csv|json|table|yaml|compact
lxc --project "$project" list -c "$columns" -f "$format"
}
lx_output_image_list() {
# Column shorthand chars:
# l - Shortest image alias (and optionally number of other aliases)
# L - Newline-separated list of all image aliases
# f - Fingerprint (short)
# F - Fingerprint (long)
# p - Whether image is public
# d - Description
# a - Architecture
# s - Size
# u - Upload date
# t - Type
local project="$1"
local columns="${2:-lfpdatsu}"
local format="${3:-table}" # csv|json|table|yaml|compact
lxc --project "$project" image list -c "$columns" -f "$format"
}
lx_wait_for_boot() {
local project="$1"
local inst="$2"
echo -n "Wait for boot "
while ! lxc --project "$project" exec "$inst" -- ls >/dev/null 2>&1; do
echo -n "."
sleep 1
done
echo ""
echo -n "Wait for cloud-init "
lxc --project "$project" exec "$inst" -- cloud-init status --wait
echo ""
}
lx_get_ssh_identity() {
local keydir="tests/assets/vm_keys"
if [ "$1" != "relative" ]; then
keydir="$(lx_project_root_dir)/$keydir"
fi
echo "$keydir/id_ed25519"
}
lx_get_ssh_known_hosts() {
local id="$(lx_get_ssh_identity)"
local known_hosts="$(dirname "$id")/known_hosts"
echo "$known_hosts"
}
lx_remove_known_host() {
local hostname="$1"
local known_hosts="$(lx_get_ssh_known_hosts)"
ssh-keygen -f "$known_hosts" -R "$hostname"
}
lx_create_ssh_identity() {
local id="$(lx_get_ssh_identity)"
if [ ! -e "$id" ]; then
mkdir -p "$(dirname "$id")"
ssh-keygen -f "$id" -C "vm key" -N "" -t ed25519
fi
}

209
tests/bin/lx_setup.sh Executable file
View File

@ -0,0 +1,209 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
#
# This script configures the system for virtulization by installing
# lxd, adding a host bridge, and configuring some firewall
# rules. Beware that the user running the script will be added to the
# 'sudo' group!
#
# The script can be run anytime, but usually only needs to be run
# once. Once successful, the lxd-based test vms can be run locally.
#
# Limitations:
#
# The host bridge only works with an ethernet interface. Wifi does not
# work, so you must be plugged in to run the vm tests.
#
# Docker cannot be installed alongside as LXD due to conflicts with
# Docker's iptables entries. More on this issue can be found here:
#
# https://github.com/docker/for-linux/issues/103
#
# https://documentation.ubuntu.com/lxd/en/latest/howto/network_bridge_firewalld/#prevent-connectivity-issues-with-lxd-and-docker
#
# Removal:
#
# Run the script with a single "-d" argument to back out the changes.
#
# Helpful tools:
#
# NetworkManager UI: nm-connection-editor
# NetworkManager cli: nmcli
#
D=$(dirname "$BASH_SOURCE")
. "$D/lx_functions.sh" || exit 1
project="$(lx_guess_project_name)"
bridge_yaml="/etc/netplan/51-lxd-bridge.yaml"
install_packages() {
sudo snap install lxd --channel=latest/stable
if [ $EUID -ne 0 ]; then
echo "Add $USER to the 'sudo' group (!!)"
sudo usermod -aG sudo $USER || exit 1
fi
}
remove_packages() {
# note: run 'snap remove --purge lxd' to nuke lxd images,
# otherwise they stay on the system
snap remove lxd
}
create_network_bridge() {
# Create network bridge (we'll bridge vms to the local network)
# On return, sets these variables:
# vm_bridge: to name of bridge interface
# get the interface with the default route (first one)
local default_network_interface="$(get_system_default_network_interface)"
local isa_bridge="$(isa_bridge_interface "$default_network_interface")"
local isa_wifi_device="$(isa_wifi_device "$default_network_interface")"
if [ "$isa_bridge" = "yes" ]; then
vm_bridge="$default_network_interface"
#out_iface="$(ip --oneline link show type bridge_slave | grep -F " $default_network_interface " | awk -F: '{print $2}')"
#out_iface="$default_network_interface"
else
echo "NO HOST BRIDGE FOUND!!! CREATING ONE."
if [ "$isa_wifi_device" = "yes" ]; then
echo "*********************************************************"
echo "UNSUPPORTED: Host bridging is not available with WIFI ! (interface $default_network_interface)"
echo "*********************************************************"
return 1
fi
echo "YOU WILL LOSE NETWORK CONNECTIVITY BRIEFLY"
echo "To remove the host bridge, delete $bridge_yaml, then run netplan apply, or run this script with '-u'"
vm_bridge="br-lxd0"
#out_iface="br-lxd0"
tmp="$(mktemp)"
sudo cat <<EOF > "$tmp"
network:
ethernets:
myeths:
match:
name: $default_network_interface
dhcp4: no
bridges:
$vm_bridge:
dhcp4: yes
interfaces: [ myeths ]
EOF
if [ -e "$bridge_yaml" ]; then
echo "Overwriting netplan $bridge_yaml"
else
echo "Adding netplan $bridge_yaml"
fi
sudo mv "$tmp" "$bridge_yaml" || return 1
sudo chown root:root "$bridge_yaml"
sudo chmod 600 "$bridge_yaml"
sudo netplan apply || return 1
fi
}
remove_network_bridge() {
if [ -e "$bridge_yaml" ]; then
sudo rm -f "$bridge_yaml" || return 1
sudo netplan apply || return 1
else
echo "OK: Bridge configuration does not exist ($bridge_yaml)"
fi
}
install_ufw_rules() {
local bridge="$1"
# per: https://documentation.ubuntu.com/lxd/en/latest/howto/network_bridge_firewalld/
sudo ufw allow in on "$bridge" comment 'for lxd'
sudo ufw route allow in on "$bridge" comment 'for lxd'
sudo ufw route allow out on "$bridge" comment 'for lxd'
if which docker >/dev/null; then
echo "WARNING: docker appears to be installed. Guest VM networking probably won't work as the docker iptables conflict with LXD (guest DHCP broadcasts are dropped)"
fi
}
remove_ufw_rules() {
# 2. Remove all old ufw rules
sudo ufw status numbered | grep -E '(for lxd|for multipass)' | cut -c2-3 | sort -nr |
while read n; do
echo 'y' | sudo ufw delete $n
done
}
create_lxd_project_and_pool() {
local bridge="$1"
# Create project and networking bridge profile. When an instance
# is initialized, include the 'bridgenet' profile (see
# lx_init_vm() in lx_functions.sh)
echo "Create lxd project '$project' with profile 'bridgenet'"
echo " bridge: $bridge"
lxc project create "$project" 2>/dev/null
lxc --project "$project" profile create bridgenet 2>/dev/null
cat <<EOF | lxc --project "$project" profile edit bridgenet
description: Bridged networking LXD profile
devices:
eth0:
name: eth0
nictype: bridged
parent: $bridge
type: nic
EOF
[ $? -ne 0 ] && return 1
# create lxd storage pool for project (our convention is that
# project and storage must have the same name)
if ! lxc storage list -f csv | grep -q "^$project,"; then
echo "Create storage pool for $project project"
lxc storage create "$project" dir || return 1
fi
}
if [ "$1" = "-u" ]; then
# uninstall
echo "Revert ufw rules"
remove_ufw_rules
echo "Remove packages"
remove_packages
echo "Remove network bridge"
remove_network_bridge
else
echo "Install packages"
install_packages || exit 1
echo "Revert ufw rules"
remove_ufw_rules || exit 1
echo "Create network bridge"
create_network_bridge || exit 1 # sets vm_bridge
echo "Install ufw rules"
install_ufw_rules "$vm_bridge" || exit 1
create_lxd_project_and_pool "$vm_bridge" || exit 1
lx_create_ssh_identity || exit 1
fi

58
tests/bin/lx_status.sh Executable file
View File

@ -0,0 +1,58 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
show() {
local project="$1"
local which=$2
if [ -z "$which" -o "$which" = "instances" ]; then
lxc --project "$project" list -c enfsd -f csv | sed "s/^/ /"
fi
if [ -z "$which" -o "$which" = "images" ]; then
lxc --project "$project" image list -c lfsd -f csv | sed "s/^/ $project,/"
fi
}
global="no"
if [ $# -gt 0 ]; then
projects=( "$@" )
else
global="yes"
projects=( $(lxc project list -f csv | awk -F, '{print $1}' | sed 's/ .*$//') )
fi
if [ "$global" = "yes" ]; then
echo "** projects"
idx=0
while [ $idx -lt ${#projects[*]} ]; do
echo " ${projects[$idx]}"
let idx+=1
done
else
echo "Project: ${projects[*]}"
fi
echo "** images"
idx=0
while [ $idx -lt ${#projects[*]} ]; do
project="${projects[$idx]}"
let idx+=1
show "$project" images $verbose
done
echo "** instances"
idx=0
while [ $idx -lt ${#projects[*]} ]; do
project="${projects[$idx]}"
let idx+=1
show "$project" instances $verbose
done

View File

@ -0,0 +1,91 @@
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
# source this file
#
# requires: lx_functions.sh
#
. "$(dirname "$BASH_SOURCE")/../lib/misc.sh"
load_provision_defaults() {
#
# search from the current directory up for a file named
# ".provision_defaults"
#
if [ -z "$PROVISION_DEFAULTS_FILE" ]; then
PROVISION_DEFAULTS_FILE="$(pwd)/.provision_defaults"
while [ "$PROVISION_DEFAULTS_FILE" != "/.provision_defaults" ]; do
[ -e "$PROVISION_DEFAULTS_FILE" ] && break
PROVISION_DEFAULTS_FILE="$(realpath -m "$PROVISION_DEFAULTS_FILE/../..")/.provision_defaults"
done
source "$PROVISION_DEFAULTS_FILE" || return 1
fi
if [ ! -e "$PROVISION_DEFAULTS_FILE" ]; then
return 1
fi
}
provision_start() {
load_provision_defaults || return 1
local base_image="${1:-$DEFAULT_LXD_IMAGE}"
local guest_mount_path="$2"
shift; shift
local opts=( "$@" )
if [ ${#opts[@]} -eq 0 ]; then
opts=( "${DEFAULT_LXD_INST_OPTS[@]}" )
fi
# set these globals
project="$(lx_guess_project_name)"
inst="$(basename "$PWD")"
provision_start_s="$(date +%s)"
echo "Creating instance '$inst' from image $base_image (${opts[@]})"
lx_launch_vm_and_wait \
"$project" "$inst" "$base_image" "$guest_mount_path" \
"${opts[@]}" \
|| return 1
}
provision_shell() {
# provision_start must have been called first!
local remote_path="/tmp/provision.sh"
local lxc_flags="--uid 0 --gid 0 --mode 755 --create-dirs"
if [ ! -z "$1" ]; then
lxc --project "$project" file push "$1" "${inst}${remote_path}" $lxc_flags || return 1
else
local tmp=$(mktemp)
echo "#!/bin/sh" >"$tmp"
cat >>"$tmp"
lxc --project "$project" file push "$tmp" "${inst}${remote_path}" $lxc_flags || return 1
rm -f "$tmp"
fi
lxc --project "$project" exec "$inst" --cwd / --env PROVISION=true \
-- "$remote_path"
}
provision_done() {
local rc="${1:-0}"
echo "Elapsed: $(elapsed_pretty "$provision_start_s" "$(date +%s)")"
if [ $rc -ne 0 ]; then
echo "Failed with code $rc"
return 1
else
echo "Success!"
return 0
fi
}

258
tests/bin/vlx Executable file
View File

@ -0,0 +1,258 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
# This is a helper script to make it easier to interact with lxd by
# calling lxc with arguments derived from conventions we've developed
# in this project.
#
# Those conventions are:
#
# 1. the project name is derived from the working directory. You
# must be anywhere in the source tree. "ciab" for cloudinabox and
# "miab" for mailinabox
#
# 2. the instance name is derived from the base name of the current
# working directory. this means that each instance must have it's
# own directory and have a script within it called "provision.sh"
# that creates the instance.
#
# Run the script with no arguments to see a list of commands.
#
# It's helpful to create a command alias. eg. in bash:
#
# alias vlx="/path/to/tests/bin/vlx"
#
# Add it to your ~/bash_aliases file to make it available for new
# terminal windows.
#
D=$(dirname "$BASH_SOURCE")
. "$D/lx_functions.sh" || exit 1
vlx_guess() {
if [ $# -eq 2 ]; then
LX_PROJECT="$1"
LX_INST="$2"
elif [ $# -eq 1 ]; then
LX_PROJECT="$(lx_guess_project_name)"
LX_INST="$1"
elif [ $# -eq 0 ]; then
LX_PROJECT="$(lx_guess_project_name)"
LX_INST="$(basename "$PWD")"
else
echo "Invalid number of arguments"
return 1
fi
}
vlx_exec_usage() {
echo "Usage: vlx exec <project> <inst> [<cwd>] -- cmd ..."
echo " or: vlx exec <inst> [<cwd>] -- cmd ..."
echo " or: vlx exec <cwd> -- cmd ..."
echo " or: vlx exec cmd ..."
}
vlx_exec() {
# args
# format 1: project inst [cwd] -- cmd ...
# format 2: inst [cwd] -- cmd ...
# format 3: <cwd> -- cmd ...
# format 4: cmd ...
if [ $# -eq 0 ]; then
vlx_exec_usage
return 1
fi
local args=( "$@" )
local idx=0
while [ $idx -le 3 -a $idx -lt ${#args[*]} ]; do
[ "${args[$idx]}" = "--" ] && break
let idx+=1
done
local wd=""
if [ "${args[$idx]}" = "--" ]; then
if [ $idx -eq 3 ]; then
# format 1 with cwd
echo "f1"
wd="$3"
vlx_guess "$1" "$2" || return 1
shift; shift; shift; shift;
elif [ $idx -eq 2 ]; then
# format 1 w/o cwd or 2
if [ "${2#/}" != "$2" ]; then
# wd starts with /, so it's a path
# format 2
echo "f2"
wd="$2"
vlx_guess "" "$1" || return 1
else
# format 1 w/o cwd
echo "f1 w/o cwd"
vlx_guess "$1" "$2" || return 1
fi
shift; shift; shift;
elif [ $idx -eq 1 ]; then
# format 2 w/o cwd or 3
if [ "${1#/}" != "$1" ]; then
# wd starts with /, so it's a path
# format 3
echo "f3"
wd="$1"
vlx_guess || return 1
else
# format 2 w/o cwd
echo "f2 w/o cwd"
vlx_guess "$1" || return 1
fi
shift; shift;
elif [ $idx -eq 0 ]; then
# command line "-- cmd ...", just ignore the leading --
shift;
fi
else
# format 4
echo "f4"
vlx_guess || return 1
fi
local xargs=""
if [ ! -z "$wd" ]; then
xargs="--cwd $wd"
fi
echo lxc --project "$LX_PROJECT" exec "$LX_INST" $xargs -- "$@"
lxc --project "$LX_PROJECT" exec "$LX_INST" $xargs -- "$@"
}
vlx_shell() {
vlx_guess "$@" || return 1
echo lxc --project "$LX_PROJECT" exec "$LX_INST" -- bash
lxc --project "$LX_PROJECT" exec "$LX_INST" -- bash
}
vlx_hostname() {
vlx_guess "$@" || return 1
local host
lxc --project "$LX_PROJECT" exec "$LX_INST" -- /usr/bin/hostname --fqdn || return 1
}
vlx_ssh() {
local host="$1"
if [ -z "$host" ]; then
host="$(vlx_hostname)"
if [ $? -ne 0 ]; then
echo "Could not determine hostname, please specify"
host=""
fi
if [ -z "$host" ]; then
echo "usage: vlx ssh <vm-hostname>"
return 1
fi
fi
local id="$(lx_get_ssh_identity)"
local known_hosts="$(lx_get_ssh_known_hosts)"
local vmuser="vmuser"
#echo ssh -i "$id" -o UserKnownHostsFile="$known_hosts" -o StrictHostKeyChecking=no "$vmuser@$host"
echo "Connecting to $vmuser@$host ..."
ssh -i "$id" -o UserKnownHostsFile="$known_hosts" -o StrictHostKeyChecking=no "$vmuser@$host"
}
vlx_list() {
vlx_guess "$1" || return 1
echo lxc --project "$LX_PROJECT" list
lxc --project "$LX_PROJECT" list
}
vlx_images() {
vlx_guess "$1" || return 1
echo lxc --project "$LX_PROJECT" image list
lxc --project "$LX_PROJECT" image list
}
vlx_up() {
if [ -x "./provision.sh" ] ; then
echo "Provision"
./provision.sh "$@" || return 1
else
echo "UP failed: ./provision.sh does not exist or is not executable"
return 1
fi
}
vlx_start() {
vlx_guess "$@" || return 1
echo lxc --project "$LX_PROJECT" start "$LX_INST"
lxc --project "$LX_PROJECT" start "$LX_INST"
}
vlx_stop() {
vlx_guess "$@" || return 1
echo lxc --project "$LX_PROJECT" stop "$LX_INST"
lxc --project "$LX_PROJECT" stop "$LX_INST"
}
vlx_delete() {
vlx_guess "$@" || return 1
echo lxc --project "$LX_PROJECT" delete --force --interactive "$LX_INST"
lxc --project "$LX_PROJECT" delete --force --interactive "$LX_INST"
}
vlx_destroy() {
vlx_delete "$@"
}
vlx_status() {
if [ $# -eq 0 ]; then
vlx_guess || return 1
"$D/lx_status.sh" "$LX_PROJECT"
elif [ "$1" = "-g" ]; then
"$D/lx_status.sh"
else
"$D/lx_status.sh" "$@"
fi
}
usage() {
echo "Usage:"
echo "vlx <command> [<arg> ...]"
echo "commands:"
echo " exec <working-directoy> -- command [arg ...]"
echo " exec command [arg ...]"
echo " shell"
echo " ssh"
echo " hostname"
echo " list"
echo " images"
echo " up"
echo " start"
echo " stop"
echo " delete|destroy"
echo " status"
}
if [ $# -eq 0 ]; then
usage
exit 1
fi
cmd="$1"
handler="vlx_$1"
shift
if [ ! "$(type -t $handler)" = "function" ]; then
echo "Unknown command: $cmd"
exit 1
fi
$handler "$@"

1
tests/lxd/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
out/

View File

@ -0,0 +1,10 @@
# defaults for lxd image creation using
# tests/bin/provision_functions.sh::provision_start()
DEFAULT_LXD_IMAGE="preloaded-ubuntu-jammy"
DEFAULT_LXD_INST_OPTS=(
"-p" "default"
"-p" "bridgenet"
"-c" "limits.cpu=1"
"-c" "limits.memory=2GiB"
)

18
tests/lxd/README.md Normal file
View File

@ -0,0 +1,18 @@
### To use lxd vm's:
1. run `tests/bin/lx_setup.sh`. This only needs to be run once.
2. run `tests/lxd/preloaded/create_preloaded.sh`. Run this anytime a new base image is updated (usually when ubuntu updates would require a system reboot).
### To bring up a vm:
1. It's helpful to have `vlx` in your path. vlx is a tool that makes `lxc` act a little like vagrant. In bash, create an alias for it: `alias vlx="$(pwd)/tests/bin/vlx"
2. set your working directory to the vm directory you'd like to start (eg. `cd "tests/lxd/vanilla"`), then run `vlx up`
3. to access the vm: `vlx shell` or `vlx ssh`. all vm's have the source root mounted at /cloudinabox or /mailinabox, so you can change files locally and they'll be available on the vm for testing
4. to destroy/delete the vm: `vlx destroy`

View File

@ -0,0 +1,8 @@
# jammy does not include the dm_crypt kernel module, which is needed
# for luks/encryption-at-rest
# remote-nextcloud-docker-ehdd
remote-nextcloud-docker
upgrade-from-upstream
upgrade
unsetvars

View File

@ -0,0 +1,3 @@
remote-nextcloud-docker
upgrade-from-upstream
upgrade

119
tests/lxd/parallel.sh Executable file
View File

@ -0,0 +1,119 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
#
# Parallel provisioning for test vms
#
. "$(dirname "$0")/../bin/lx_functions.sh"
. "$(dirname "$0")/../lib/color-output.sh"
. "$(dirname "$0")/../lib/misc.sh"
boxlist="" # the name of the boxlist or a path to the boxlist file
boxes=() # the contents of the boxlist file
project="$(lx_guess_project_name)"
load_boxlist() {
# sets global variable 'boxlist' and array 'boxes'
boxlist="${1:-default}"
local fn="$boxlist"
if [ ! -f "$fn" ]; then
fn="parallel-boxlist.$boxlist"
fi
if [ ! -f "$fn" ]; then
echo "Could not load boxlist from '${boxlist}'! Failed to find '$fn'."
exit 1
fi
boxes=( $(grep -v '^#' $fn) )
if [ $? -ne 0 ]; then
echo "Could not load boxlist from file '$fn'!"
exit 1
fi
}
# destroy running boxes
if [ "$1" = "-d" ]; then
shift
load_boxlist "$1"
for inst in $(lx_output_inst_list "$project" "n" "csv"); do
if array_contains $inst ${boxes[*]}; then
echo lxc --project "$project" delete $inst --force
lxc --project "$project" delete $inst --force
fi
done
exit 0
elif [ "$1" = "-h" -o "$1" = "--help" ]; then
echo "usage: $0 [-d] [boxlist]"
echo " -d delete/destroy running boxes"
echo " boxlist an file or named boxlist containing a list of instance names. defaults to 'default'"
exit 0
fi
load_boxlist "$1"
# set total parallel vms to (#cores minus 1)
MAX_PROCS=$(cat /proc/cpuinfo | grep processor | wc -l)
let MAX_PROCS-=1
[ $MAX_PROCS -eq 0 ] && MAX_PROCS=1
OUTPUT_DIR=out
#rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
echo "MAX_PROCS=$MAX_PROCS"
echo "OUTPUT_DIR=$OUTPUT_DIR"
start_time="$(date +%s)"
# bring up in parallel
for inst in ${boxes[*]}; do
outfile="$OUTPUT_DIR/$inst.out.txt"
rm -f "$outfile"
echo "Bringing up '$inst'. Output will be in: $outfile" 1>&2
echo $inst
done | xargs -P $MAX_PROCS -I"INSTNAME" \
sh -c '
cd "INSTNAME" &&
./provision.sh >'"../$OUTPUT_DIR/"'INSTNAME.out.txt 2>&1 &&
echo "EXITCODE: 0" >> '"../$OUTPUT_DIR/"'INSTNAME.out.txt ||
echo "EXITCODE: $?" >>'"../$OUTPUT_DIR/"'INSTNAME.out.txt
'
# output overall result"
H1 "Results"
rc=0
for inst in ${boxes[*]}; do
file="$OUTPUT_DIR"/$inst.out.txt
exitcode="$(tail "$file" | grep EXITCODE: | awk '{print $NF}')"
echo -n "$inst: "
if [ -z "$exitcode" ]; then
danger "NO EXITCODE!"
[ $rc -eq 0 ] && rc=2
elif [ "$exitcode" == "0" ]; then
elapsed="$(tail "$file" | grep ^Elapsed | awk -F: '{print $2}')"
success "SUCCESS (${elapsed# })"
else
danger "FAILURE ($exitcode)"
rc=1
fi
done
# output elapsed time
end_time="$(date +%s)"
echo ""
echo "Elapsed time: $(elapsed_pretty $start_time $end_time)"
# exit
echo ""
echo "Guest VMs are running! Destroy them with:"
echo " $0 -d $boxlist"
exit $rc

View File

@ -0,0 +1,97 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
# this script creates a new lxd image preloaded with software to speed
# up installation.
#
# prerequisites:
#
# tests/bin/lx_setup.sh must be run before running this script. it
# only needs to be run once, or any time the networking setup
# changes (eg. adding a new ethernet card).
#
D="$(dirname "$BASH_SOURCE")"
. "$D/../../bin/lx_functions.sh" || exit 1
project="$(lx_guess_project_name)"
inst_mountpoint=/mailinabox
[ "$project" = "ciab" ] && inst_mountpoint=/cloudinabox
if [ -z "$1" ]; then
imagelist=( $(<./imagelist) )
else
imagelist=( "$@" )
fi
for base_image in "${imagelist[@]}"
do
new_image="preloaded-${base_image/:/-}"
inst_name="preloaded"
echo ""
echo "START: create $new_image using base image $base_image"
echo "Delete existing instance: $inst_name"
lx_delete "$project" "$inst_name" "no-interactive" || exit 1
echo "Create instance '$inst_name' from '$base_image'"
# cloud init configuration creates user 'vmuser' instead of 'ubuntu'
cloud_config_users="#cloud-config
users:
- default
- name: vmuser
gecos: VM user for ssh
primary_group: vmuser
groups: adm, sudo, lxd
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
lock_passwd: true
ssh_authorized_keys:
- $(< $(lx_get_ssh_identity).pub)
"
lx_launch_vm "$project" "$inst_name" "$base_image" "$(lx_project_root_dir)" "$inst_mountpoint" -c cloud-init.user-data="$cloud_config_users" -c limits.cpu=2 -c limits.memory=2GiB -d root,size=30GiB || exit 1
lx_wait_for_boot "$project" "$inst_name"
echo ""
echo "================================================="
echo "Prep the VM instance"
echo "================================================="
lxc --project "$project" exec "$inst_name" --cwd "$inst_mountpoint" -- sudo tests/lxd/preloaded/prepvm.sh --no-dry-run || exit 1
echo ""
echo "================================================="
echo "Create an image from the instance"
echo "================================================="
echo "Stopping instance '$inst_name'"
lxc --project "$project" stop "$inst_name" || exit 1
echo "Create image '$new_image' from instance '$inst_name'"
lxc --project "$project" publish "$inst_name" "local:" --reuse --compression gzip --alias "$new_image" || exit 1 # --compression xz
echo ""
echo "================================================="
echo "Image list ($project)"
echo "================================================="
lx_output_image_list "$project" "ld"
echo ""
echo "================================================="
echo "Delete instance '$inst_name'"
echo "================================================="
lx_delete "$project" "$inst_name" "no-interactive"
echo "Success"
done

View File

@ -0,0 +1 @@
ubuntu:jammy

230
tests/lxd/preloaded/prepvm.sh Executable file
View File

@ -0,0 +1,230 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
# Run this on a VM to pre-install all the packages, then
# take a snapshot - it will greatly speed up subsequent
# test installs
#
# What won't be installed:
#
# Nextcloud and Roundcube are downloaded with wget by the setup
# scripts, so they are not included
#
# slapd - we want to test installation with setup/ldap.sh
#
if [ ! -d "setup" ]; then
echo "Run from the miab root directory"
exit 1
fi
source tests/lib/misc.sh
source tests/lib/system.sh
source tests/lib/color-output.sh
dry_run=true
start=$(date +%s)
if [ "$1" == "--no-dry-run" ]; then
dry_run=false
fi
if $dry_run; then
echo "WARNING: dry run is TRUE, no changes will be made"
fi
# prevent apt from running needrestart(1)
export NEEDRESTART_SUSPEND=true
# prevent interaction during package install
export DEBIAN_FRONTEND=noninteractive
# what major version of ubuntu are we installing on?
OS_MAJOR=$(. /etc/os-release; echo $VERSION_ID | awk -F. '{print $1}')
remove_line_continuation() {
local file="$1"
awk '
BEGIN { C=0 }
C==1 && /[^\\]$/ { C=0; print $0; next }
C==1 { printf("%s",substr($0,0,length($0)-1)); next }
/\\$/ { C=1; printf("%s",substr($0,0,length($0)-1)); next }
{ print $0 }' \
"$file"
}
install_packages() {
local return_code=0
while read line; do
pkgs=""
case "$line" in
apt_install* )
pkgs="$(cut -c12- <<<"$line")"
;;
"apt-get install"* )
pkgs="$(cut -c16- <<<"$line")"
;;
"apt install"* )
pkgs="$(cut -c12- <<<"$line")"
;;
esac
# don't install slapd
pkgs="$(sed 's/slapd//g' <<< "$pkgs")"
# manually set PHP_VER if necessary
if grep "PHP_VER" <<<"$pkgs" >/dev/null; then
pkgs="$(sed "s/\"\?\${*PHP_VER}*\"\?/$PHP_VER/g" <<< "$pkgs")"
fi
if [ ! -z "$pkgs" ]; then
H2 "install: $pkgs"
if ! $dry_run; then
exec_no_output apt-get install -y $pkgs
let return_code+=$?
fi
fi
done
return $return_code
}
install_ppas() {
H1 "Add apt repositories"
grep 'hide_output add-apt-repository' setup/system.sh |
while read line; do
line=$(sed 's/^hide_output //' <<< "$line")
H2 "$line"
if ! $dry_run; then
exec_no_output $line
fi
done
}
add_swap() {
H1 "Add a swap file to the system"
if ! $dry_run; then
dd if=/dev/zero of=/swapfile bs=1024 count=$[1024*1024] status=none
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo "/swapfile none swap sw 0 0" >> /etc/fstab
fi
}
# install PPAs from sources
install_ppas
# add swap file
add_swap
# obtain PHP_VER variable from sources
PHP_VER=$(source setup/functions.sh; echo $PHP_VER)
if ! $dry_run; then
H1 "Upgrade system"
H2 "apt update"
exec_no_output apt-get update -y || exit 1
H2 "apt upgrade"
exec_no_output apt-get upgrade -y --with-new-pkgs || exit 1
H2 "apt autoremove"
exec_no_output apt-get autoremove -y
fi
# without using the same installation order as setup/start.sh, we end
# up with the system's php getting installed in addition to the
# non-system php that may also installed by setup (don't know why,
# probably one of the packages has a dependency). create an ordered
# list of files to process so we get a similar system setup.
setup_files=( $(ls setup/*.sh) )
desired_order=(
setup/functions.sh
setup/preflight.sh
setup/questions.sh
setup/network-checks.sh
setup/system.sh
setup/ssl.sh
setup/dns.sh
setup/ldap.sh
setup/mail-postfix.sh
setup/mail-dovecot.sh
setup/mail-users.sh
setup/dkim.sh
setup/spamassassin.sh
setup/web.sh
setup/webmail.sh
setup/nextcloud.sh
setup/zpush.sh
setup/management.sh
setup/management-capture.sh
setup/munin.sh
setup/firstuser.sh
)
ordered_files=()
for file in "${desired_order[@]}" "${setup_files[@]}"; do
if [ -e "$file" ] && ! array_contains "$file" "${ordered_files[@]}"; then
ordered_files+=( "$file" )
fi
done
failed=0
for file in ${ordered_files[@]}; do
H1 "$file"
remove_line_continuation "$file" | install_packages
[ $? -ne 0 ] && let failed+=1
done
if ! $dry_run; then
# bonus
H1 "install extras"
H2 "openssh, emacs, ntpdate, net-tools, jq"
exec_no_output apt-get install -y openssh-server emacs-nox ntpdate net-tools jq || let failed+=1
# these are added by system-setup scripts and needed for test runner
H2 "python3-dnspython"
exec_no_output apt-get install -y python3-dnspython || let failed+=1
H2 "pyotp(pip)"
exec_no_output python3 -m pip install pyotp --quiet || let failed+=1
# ...and for browser-based tests
#H2 "x11" # needed for chromium w/head (not --headless)
#exec_no_output apt-get install -y xorg openbox xvfb gtk2-engines-pixbuf dbus-x11 xfonts-base xfonts-100dpi xfonts-75dpi xfonts-cyrillic xfonts-scalable x11-apps imagemagick || let failed+=1
H2 "chromium"
#exec_no_output apt-get install -y chromium-browser || let failed+=1
exec_no_output snap install chromium || let failed+=1
H2 "selenium(pip)"
exec_no_output python3 -m pip install selenium --quiet || let failed+=1
# remove apache, which is what setup will do
H2 "remove apache2"
exec_no_output apt-get -y purge apache2 apache2-\*
fi
end=$(date +%s)
echo ""
echo ""
if [ $failed -gt 0 ]; then
echo "$failed failures! ($(elapsed_pretty $start $end))"
echo ""
exit 1
else
echo "Successfully prepped in $(elapsed_pretty $start $end). Take a snapshot...."
echo ""
exit 0
fi

View File

@ -0,0 +1,35 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
#
# provision a miab-ldap that has a remote nextcloud (using Nextcloud
# from Docker) and an encrypted user-data
#
D=$(dirname "$BASH_SOURCE")
. "$D/../../bin/lx_functions.sh" || exit 1
. "$D/../../bin/provision_functions.sh" || exit 1
# Create the instance (started)
provision_start "" "/mailinabox" || exit 1
# Setup system
provision_shell <<<"
cd /mailinabox
export PRIMARY_HOSTNAME=qa1.abc.com
export FEATURE_MUNIN=false
export EHDD_KEYFILE=\$HOME/keyfile
echo -n 'boo' >\$EHDD_KEYFILE
tests/system-setup/remote-nextcloud-docker.sh || exit 1
tests/runner.sh -no-smtp-remote remote-nextcloud ehdd default || exit 2
"
provision_done $?

View File

@ -0,0 +1,33 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
#
# provision a miab-ldap that has a remote nextcloud (using Nextcloud
# from Docker)
#
D=$(dirname "$BASH_SOURCE")
. "$D/../../bin/lx_functions.sh" || exit 1
. "$D/../../bin/provision_functions.sh" || exit 1
# Create the instance (started)
provision_start "" "/mailinabox" || exit 1
# Setup system
provision_shell <<<"
cd /mailinabox
export PRIMARY_HOSTNAME=qa2.abc.com
export FEATURE_MUNIN=false
tests/system-setup/remote-nextcloud-docker.sh upgrade --populate=basic || exit 1
tests/runner.sh -no-smtp-remote remote-nextcloud upgrade-basic default || exit 2
"
provision_done $?

View File

@ -0,0 +1,35 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
#
# provision a miab-ldap that has a remote nextcloud (using Nextcloud
# from Docker)
#
D=$(dirname "$BASH_SOURCE")
. "$D/../../bin/lx_functions.sh" || exit 1
. "$D/../../bin/provision_functions.sh" || exit 1
# Create the instance (started)
provision_start "" "/mailinabox" || exit 1
# Setup system
provision_shell <<<"
export NONINTERACTIVE=1
export PUBLIC_IP=auto
export PUBLIC_IPV6=auto
export PRIMARY_HOSTNAME=mailinabox.lan # auto
export SKIP_NETWORK_CHECKS=1
cd /mailinabox
setup/start.sh
"
provision_done $?

View File

@ -0,0 +1,33 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
#
# provision a miab-ldap that has a remote nextcloud (using Nextcloud
# from Docker)
#
D=$(dirname "$BASH_SOURCE")
. "$D/../../bin/lx_functions.sh" || exit 1
. "$D/../../bin/provision_functions.sh" || exit 1
# Create the instance (started)
provision_start "" "/mailinabox" || exit 1
# Setup system
provision_shell <<<"
cd /mailinabox
export PRIMARY_HOSTNAME=qa3.abc.com
export UPSTREAM_TAG=main
tests/system-setup/upgrade-from-upstream.sh --populate=basic --populate=totpuser || exit 1
tests/runner.sh -no-smtp-remote upgrade-basic upgrade-totpuser default || exit 2
"
provision_done $?

32
tests/lxd/upgrade/provision.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
#
# provision a miab-ldap that has a remote nextcloud (using Nextcloud
# from Docker)
#
D=$(dirname "$BASH_SOURCE")
. "$D/../../bin/lx_functions.sh" || exit 1
. "$D/../../bin/provision_functions.sh" || exit 1
# Create the instance (started)
provision_start "" "/mailinabox" || exit 1
# Setup system
provision_shell <<<"
cd /mailinabox
export PRIMARY_HOSTNAME=upgrade.abc.com
tests/system-setup/upgrade.sh --populate=basic --populate=totpuser || exit 1
tests/runner.sh -no-smtp-remote upgrade-basic upgrade-totpuser default || exit 2
"
provision_done $?

65
tests/lxd/vanilla/provision.sh Executable file
View File

@ -0,0 +1,65 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
D=$(dirname "$BASH_SOURCE")
. "$D/../../bin/lx_functions.sh" || exit 1
. "$D/../../bin/provision_functions.sh" || exit 1
# Create the instance (started)
provision_start "" "/mailinabox" || exit 1
# Setup system
if [ "$1" = "ciab" ]; then
# use a remote cloudinabox (does not have to be running)
provision_shell <<<"
cd /mailinabox
export PRIMARY_HOSTNAME='${inst}.local'
export NC_PROTO=https
export NC_HOST=vanilla-ciab.local
export NC_PORT=443
export NC_PREFIX=/
export SKIP_SYSTEM_UPDATE=0
tests/system-setup/vanilla.sh --qa-ca --enable-mod=remote-nextcloud
rc=$?
if ! ufw status | grep remote_nextcloud >/dev/null; then
# firewall rules aren't added when ciab is down
echo 'For testing, allow ldaps from anywhere'
ufw allow ldaps
fi
echo 'Add smart host alias - so \$NC_HOST can send mail to/via this host'
(
source tests/lib/all.sh
rest_urlencoded POST /admin/mail/aliases/add qa@abc.com Test_1234 \"address=@\$NC_HOST\" 'description=smart-host' 'permitted_senders=qa@abc.com' 2>/dev/null
echo \"\$REST_HTTP_CODE: \$REST_OUTPUT\"
)
exit $rc
"
provision_done $?
else
# vanilla (default - no miab integration)
provision_shell <<<"
cd /mailinabox
export PRIMARY_HOSTNAME='${inst}.local'
#export FEATURE_MUNIN=false
#export FEATURE_NEXTCLOUD=false
export SKIP_SYSTEM_UPDATE=0
tests/system-setup/vanilla.sh
rc=$?
# --enable-mod=move-postfix-queue-to-user-data
# --enable-mod=roundcube-master
# --enable-mod=roundcube-debug
# --enable-mod=rcmcarddav-composer
exit $rc
"
provision_done $?
fi

View File

@ -22,11 +22,11 @@ export STORAGE_ROOT="${STORAGE_ROOT:-/home/$STORAGE_USER}"
export EMAIL_ADDR="${EMAIL_ADDR:-qa@abc.com}"
export EMAIL_PW="${EMAIL_PW:-Test_1234}"
export PUBLIC_IP="${PUBLIC_IP:-$(source ${MIAB_DIR:-.}/setup/functions.sh; get_default_privateip 4)}"
if lsmod | grep "^vboxguest[\t ]" >/dev/null; then
if lsmod | grep -q "^vboxguest[\t ]" || df | grep -q "^lxd_"; then
# The local mods directory defaults to 'local' (relative to the
# source tree, which is a mounted filesystem of the host). This
# will keep mods directory out of the source tree when running
# under virtualbox / vagrant.
# under virtualbox / vagrant / lxd.
export LOCAL_MODS_DIR="${LOCAL_MODS_DIR:-/local}"
else
export LOCAL_MODS_DIR="${LOCAL_MODS_DIR:-$(pwd)/local}"

View File

@ -86,7 +86,7 @@ init_test_system() {
# update system time
H2 "Set system time"
update_system_time || echo "Ignoring error..."
# update package lists before installing anything
H2 "apt-get update"
wait_for_apt
@ -115,7 +115,7 @@ init_test_system() {
| awk '/^(Upgrade|Install): / { print $0 }'
rm -f /tmp/history.log
fi
# install avahi if the system dns domain is .local - note that
# /bin/dnsdomainname returns empty string at this point
case "$PRIMARY_HOSTNAME" in
@ -149,7 +149,7 @@ init_miab_testing() {
else
echo "Not configured for encryption-at-rest"
fi
H2 "QA prerequisites"
local rc=0
@ -186,7 +186,7 @@ init_miab_testing() {
echo "Copy failed ($?)"
rc=1
fi
# create miab_ldap.conf to specify what the Nextcloud LDAP service
# account password will be to avoid a random one created by start.sh
if [ ! -z "$LDAP_NEXTCLOUD_PASSWORD" ]; then
@ -228,13 +228,13 @@ init_miab_testing() {
# ignore unknown option - may be interpreted elsewhere
shift
;;
esac
esac
done
# now that we've copied our files, unmount STORAGE_ROOT if
# encryption-at-rest was enabled
ehdd/umount.sh
return $rc
}
@ -303,7 +303,7 @@ clone_repo_and_pushd() {
;;
esac
done
if [ -z "$repo" -o -z "$treeish" -o -z "$targetdir" ]; then
return 1
fi
@ -329,7 +329,7 @@ upstream_install() {
if clone_repo_and_pushd "$@"; then
need_pop="yes"
fi
H1 "MIAB UPSTEAM INSTALL [$(git describe 2>/dev/null)]"
# ensure we're in a MiaB working directory
@ -351,24 +351,24 @@ upstream_install() {
exec_no_output apt-get remove -y nsd
#systemctl reset-failed nsd
fi
if ! setup/start.sh; then
echo "$F_WARN"
dump_file /var/log/syslog 100
echo "$F_RESET"
die "Upstream setup failed!"
fi
H2 "Post-setup actions"
workaround_dovecot_sieve_bug
# set actual STORAGE_ROOT, STORAGE_USER, PRIVATE_IP, etc
. /etc/mailinabox.conf || die "Could not source /etc/mailinabox.conf"
H2 "miab install success"
if [ "$need_pop" = "yes" ]; then
if [ ! -e tests/vagrant ]; then
if [ ! -e tests/lxd ]; then
# if this is an upstream install, then populate using
# miabldap's populate scripts (upstream doesn't have any)
local d
@ -397,7 +397,7 @@ miab_ldap_install() {
if clone_repo_and_pushd "$@"; then
need_pop="yes"
fi
H1 "MIAB-LDAP INSTALL [$(pwd)] [$(git describe 2>/dev/null)]"
# ensure we're in a MiaB-LDAP working directory
if [ ! -e setup/ldap.sh ]; then
@ -423,7 +423,7 @@ miab_ldap_install() {
else
setup/start.sh
fi
if [ $? -ne 0 ]; then
H1 "OUTPUT OF SELECT FILES"
dump_file "/var/log/syslog" 100
@ -444,11 +444,11 @@ miab_ldap_install() {
fi
H2 "miab-ldap install success"
# populate if specified on command line
populate_by_cli_argument "$@"
capture_state_by_cli_argument "$@"
if [ "$need_pop" = "yes" ]; then
popd >/dev/null
fi
@ -457,7 +457,7 @@ miab_ldap_install() {
capture_state_by_cli_argument() {
# this must be run with the working directory set to the source
# tree corresponding to the the installed state
# ...ignore unknown options they may be interpreted elsewhere
local state_dir=""
for arg; do