The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3673
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Move helper functions for tests to separate files that can be included. Also add a few additional helpers. This allows reusing those functions in other test scripts (for instance for performance tests).
From 9db33d031fdf350c62030d26ee019c37f2d98b5a Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Thu, 17 Aug 2017 11:48:29 +0200 Subject: [PATCH 1/8] tests: split out storage-related helper functions Signed-off-by: Alberto Donato <[email protected]> --- test/includes/storage.sh | 41 +++++++++++++++++++++++++++++++++++++++++ test/main.sh | 45 +++++---------------------------------------- 2 files changed, 46 insertions(+), 40 deletions(-) create mode 100644 test/includes/storage.sh diff --git a/test/includes/storage.sh b/test/includes/storage.sh new file mode 100644 index 000000000..63e4802d8 --- /dev/null +++ b/test/includes/storage.sh @@ -0,0 +1,41 @@ +# Helper functions related to storage backends. + +# Whether a storage backend is available +storage_backend_available() { + # shellcheck disable=2039 + local backends + backends="$(available_storage_backends)" + [ "${backends#*$1}" != "$backends" ] +} + +# Choose a random available backend, excluding LXD_BACKEND +random_storage_backend() { + # shellcheck disable=2046 + shuf -e $(available_storage_backends) | head -n 1 +} + +# Return the storage backend being used by a LXD instance +storage_backend() { + cat "$1/lxd.backend" +} + +# Return a list of available storage backends +available_storage_backends() { + # shellcheck disable=2039 + local backend backends storage_backends + + backends="dir" # always available + + storage_backends="btrfs lvm zfs" + if [ -n "${LXD_CEPH_CLUSTER:-}" ]; then + storage_backends="${storage_backends} ceph" + fi + + for backend in $storage_backends; do + if which "$backend" >/dev/null 2>&1; then + backends="$backends $backend" + fi + done + + echo "$backends" +} diff --git a/test/main.sh b/test/main.sh index 5667a75b9..6b0ad1553 100755 --- a/test/main.sh +++ b/test/main.sh @@ -36,6 +36,11 @@ if [ -n "${LXD_LOGS:-}" ] && [ ! -d "${LXD_LOGS}" ]; then fi # Helper functions +for include in includes/*.sh; do + # shellcheck disable=SC1090 + . "$include" +done + local_tcp_port() { while :; do port=$(shuf -i 10000-32768 -n 1) @@ -48,46 +53,6 @@ local_tcp_port() { done } -# return a list of available storage backends -available_storage_backends() { - # shellcheck disable=2039 - local backend backends - - backends="dir" - - storage_backends="btrfs lvm zfs" - if [ -n "${LXD_CEPH_CLUSTER:-}" ]; then - storage_backends="${storage_backends} ceph" - fi - - for backend in $storage_backends; do - if which "$backend" >/dev/null 2>&1; then - backends="$backends $backend" - fi - done - - echo "$backends" -} - -# whether a storage backend is available -storage_backend_available() { - # shellcheck disable=2039 - local backends - backends="$(available_storage_backends)" - [ "${backends#*$1}" != "$backends" ] -} - -# choose a random available backend, excluding LXD_BACKEND -random_storage_backend() { - # shellcheck disable=2046 - shuf -e $(available_storage_backends) | head -n 1 -} - -# return the storage backend being used by a LXD instance -storage_backend() { - cat "$1/lxd.backend" -} - if [ -z "${LXD_BACKEND:-}" ]; then LXD_BACKEND=dir From e9add472478bc33f405f2ba8193b9bdfa048df4a Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Thu, 17 Aug 2017 11:58:27 +0200 Subject: [PATCH 2/8] tests: split out network-related helper functions Signed-off-by: Alberto Donato <[email protected]> --- test/includes/net.sh | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/main.sh | 70 -------------------------------------------- 2 files changed, 83 insertions(+), 70 deletions(-) create mode 100644 test/includes/net.sh diff --git a/test/includes/net.sh b/test/includes/net.sh new file mode 100644 index 000000000..47a9aa330 --- /dev/null +++ b/test/includes/net.sh @@ -0,0 +1,83 @@ +# Network-related helper functions. + +# Return an available random local port +local_tcp_port() { + # shellcheck disable=SC2039 + local port pid + + while true; do + port=$(shuf -i 10000-32768 -n 1) + nc -l 127.0.0.1 "${port}" >/dev/null 2>&1 & + pid=$! + kill "${pid}" >/dev/null 2>&1 || continue + wait "${pid}" || true + echo "${port}" + return + done +} + +# Certificate-aware curl wrapper +my_curl() { + curl -k -s --cert "${LXD_CONF}/client.crt" --key "${LXD_CONF}/client.key" "$@" +} + + +# set up a loopback device +configure_loop_device() { + # shellcheck disable=SC2039 + local lv_loop_file pvloopdev + + lv_loop_file=$(mktemp -p "${TEST_DIR}" XXXX.img) + truncate -s 10G "${lv_loop_file}" + pvloopdev=$(losetup --show -f "${lv_loop_file}") + if [ ! -e "${pvloopdev}" ]; then + echo "failed to setup loop" + false + fi + echo "${pvloopdev}" >> "${TEST_DIR}/loops" + + # The following code enables to return a value from a shell function by + # calling the function as: fun VAR1 + + # shellcheck disable=2039 + local __tmp1="${1}" + # shellcheck disable=2039 + local res1="${lv_loop_file}" + if [ "${__tmp1}" ]; then + eval "${__tmp1}='${res1}'" + fi + + # shellcheck disable=2039 + local __tmp2="${2}" + # shellcheck disable=2039 + local res2="${pvloopdev}" + if [ "${__tmp2}" ]; then + eval "${__tmp2}='${res2}'" + fi +} + +deconfigure_loop_device() { + # shellcheck disable=SC2039 + local lv_loop_file loopdev success + + lv_loop_file="${1}" + loopdev="${2}" + success=0 + # shellcheck disable=SC2034 + for i in $(seq 10); do + if losetup -d "${loopdev}"; then + success=1 + break + fi + + sleep 0.5 + done + + if [ "$success" = "0" ]; then + echo "Failed to tear down loop device" + false + fi + + rm -f "${lv_loop_file}" + sed -i "\|^${loopdev}|d" "${TEST_DIR}/loops" +} diff --git a/test/main.sh b/test/main.sh index 6b0ad1553..c127cbd2d 100755 --- a/test/main.sh +++ b/test/main.sh @@ -41,19 +41,6 @@ for include in includes/*.sh; do . "$include" done -local_tcp_port() { - while :; do - port=$(shuf -i 10000-32768 -n 1) - nc -l 127.0.0.1 "${port}" >/dev/null 2>&1 & - pid=$! - kill "${pid}" >/dev/null 2>&1 || continue - wait "${pid}" || true - echo "${port}" - return - done -} - - if [ -z "${LXD_BACKEND:-}" ]; then LXD_BACKEND=dir fi @@ -219,10 +206,6 @@ gen_cert() { mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key" } -my_curl() { - curl -k -s --cert "${LXD_CONF}/client.crt" --key "${LXD_CONF}/client.key" "$@" -} - wait_for() { addr=${1} shift @@ -474,59 +457,6 @@ wipe() { rm -Rf "${1}" } -configure_loop_device() { - lv_loop_file=$(mktemp -p "${TEST_DIR}" XXXX.img) - truncate -s 10G "${lv_loop_file}" - pvloopdev=$(losetup --show -f "${lv_loop_file}") - if [ ! -e "${pvloopdev}" ]; then - echo "failed to setup loop" - false - fi - echo "${pvloopdev}" >> "${TEST_DIR}/loops" - - # The following code enables to return a value from a shell function by - # calling the function as: fun VAR1 - - # shellcheck disable=2039 - local __tmp1="${1}" - # shellcheck disable=2039 - local res1="${lv_loop_file}" - if [ "${__tmp1}" ]; then - eval "${__tmp1}='${res1}'" - fi - - # shellcheck disable=2039 - local __tmp2="${2}" - # shellcheck disable=2039 - local res2="${pvloopdev}" - if [ "${__tmp2}" ]; then - eval "${__tmp2}='${res2}'" - fi -} - -deconfigure_loop_device() { - lv_loop_file="${1}" - loopdev="${2}" - - SUCCESS=0 - # shellcheck disable=SC2034 - for i in $(seq 10); do - if losetup -d "${loopdev}"; then - SUCCESS=1 - break - fi - - sleep 0.5 - done - - if [ "${SUCCESS}" = "0" ]; then - echo "Failed to tear down loop device" - false - fi - - rm -f "${lv_loop_file}" - sed -i "\|^${loopdev}|d" "${TEST_DIR}/loops" -} # Must be set before cleanup() TEST_CURRENT=setup From 12381381069fcfc426868f8cd4193fd0040d3532 Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Thu, 17 Aug 2017 12:40:39 +0200 Subject: [PATCH 3/8] tests: split out lxc and lxd related helper functions Signed-off-by: Alberto Donato <[email protected]> --- test/includes/lxc.sh | 52 ++++++++ test/includes/lxd.sh | 307 ++++++++++++++++++++++++++++++++++++++++++++ test/main.sh | 352 --------------------------------------------------- 3 files changed, 359 insertions(+), 352 deletions(-) create mode 100644 test/includes/lxc.sh create mode 100644 test/includes/lxd.sh diff --git a/test/includes/lxc.sh b/test/includes/lxc.sh new file mode 100644 index 000000000..74b45cde6 --- /dev/null +++ b/test/includes/lxc.sh @@ -0,0 +1,52 @@ +# lxc CLI related test helpers. + +lxc() { + LXC_LOCAL=1 lxc_remote "$@" +} + +lxc_remote() { + set +x + # shellcheck disable=SC2039 + local injected cmd arg + + injected=0 + cmd=$(which lxc) + + # shellcheck disable=SC2048,SC2068 + for arg in $@; do + if [ "${arg}" = "--" ]; then + injected=1 + cmd="${cmd} ${DEBUG:-}" + [ -n "${LXC_LOCAL}" ] && cmd="${cmd} --force-local" + cmd="${cmd} --" + elif [ "${arg}" = "--force-local" ]; then + continue + else + cmd="${cmd} \"${arg}\"" + fi + done + + if [ "${injected}" = "0" ]; then + cmd="${cmd} ${DEBUG-}" + fi + if [ -n "${DEBUG:-}" ]; then + set -x + fi + eval "${cmd}" +} + +gen_cert() { + # Temporarily move the existing cert to trick LXC into generating a + # second cert. LXC will only generate a cert when adding a remote + # server with a HTTPS scheme. The remote server URL just needs to + # be syntactically correct to get past initial checks; in fact, we + # don't want it to succeed, that way we don't have to delete it later. + [ -f "${LXD_CONF}/${1}.crt" ] && return + mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client.crt.bak" + mv "${LXD_CONF}/client.key" "${LXD_CONF}/client.key.bak" + echo y | lxc_remote remote add "$(uuidgen)" https://0.0.0.0 || true + mv "${LXD_CONF}/client.crt" "${LXD_CONF}/${1}.crt" + mv "${LXD_CONF}/client.key" "${LXD_CONF}/${1}.key" + mv "${LXD_CONF}/client.crt.bak" "${LXD_CONF}/client.crt" + mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key" +} diff --git a/test/includes/lxd.sh b/test/includes/lxd.sh new file mode 100644 index 000000000..a8e2f561b --- /dev/null +++ b/test/includes/lxd.sh @@ -0,0 +1,307 @@ +# LXD-related test helpers. + +spawn_lxd() { + set +x + # LXD_DIR is local here because since $(lxc) is actually a function, it + # overwrites the environment and we would lose LXD_DIR's value otherwise. + + # shellcheck disable=2039 + local LXD_DIR lxddir lxd_backend + + lxddir=${1} + shift + + storage=${1} + shift + + if [ "$LXD_BACKEND" = "random" ]; then + lxd_backend="$(random_storage_backend)" + else + lxd_backend="$LXD_BACKEND" + fi + + if [ "${LXD_BACKEND}" = "ceph" ] && [ -z "${LXD_CEPH_CLUSTER:-}" ]; then + echo "A cluster name must be specified when using the CEPH driver." >&2 + exit 1 + fi + + # Copy pre generated Certs + cp deps/server.crt "${lxddir}" + cp deps/server.key "${lxddir}" + + # setup storage + "$lxd_backend"_setup "${lxddir}" + echo "$lxd_backend" > "${lxddir}/lxd.backend" + + echo "==> Spawning lxd in ${lxddir}" + # shellcheck disable=SC2086 + LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 & + LXD_PID=$! + echo "${LXD_PID}" > "${lxddir}/lxd.pid" + echo "${lxddir}" >> "${TEST_DIR}/daemons" + echo "==> Spawned LXD (PID is ${LXD_PID})" + + echo "==> Confirming lxd is responsive" + LXD_DIR="${lxddir}" lxd waitready --timeout=300 + + echo "==> Binding to network" + # shellcheck disable=SC2034 + for i in $(seq 10); do + addr="127.0.0.1:$(local_tcp_port)" + LXD_DIR="${lxddir}" lxc config set core.https_address "${addr}" || continue + echo "${addr}" > "${lxddir}/lxd.addr" + echo "==> Bound to ${addr}" + break + done + + echo "==> Setting trust password" + LXD_DIR="${lxddir}" lxc config set core.trust_password foo + if [ -n "${DEBUG:-}" ]; then + set -x + fi + + echo "==> Setting up networking" + LXD_DIR="${lxddir}" lxc profile device add default eth0 nic nictype=p2p name=eth0 + + if [ "${storage}" = true ]; then + echo "==> Configuring storage backend" + "$lxd_backend"_configure "${lxddir}" + fi +} + +respawn_lxd() { + set +x + # LXD_DIR is local here because since $(lxc) is actually a function, it + # overwrites the environment and we would lose LXD_DIR's value otherwise. + + # shellcheck disable=2039 + local LXD_DIR + + lxddir=${1} + shift + + echo "==> Spawning lxd in ${lxddir}" + # shellcheck disable=SC2086 + LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 & + LXD_PID=$! + echo "${LXD_PID}" > "${lxddir}/lxd.pid" + echo "==> Spawned LXD (PID is ${LXD_PID})" + + echo "==> Confirming lxd is responsive" + LXD_DIR="${lxddir}" lxd waitready --timeout=300 +} + +kill_lxd() { + # LXD_DIR is local here because since $(lxc) is actually a function, it + # overwrites the environment and we would lose LXD_DIR's value otherwise. + + # shellcheck disable=2039 + local LXD_DIR daemon_dir daemon_pid check_leftovers lxd_backend + + daemon_dir=${1} + LXD_DIR=${daemon_dir} + daemon_pid=$(cat "${daemon_dir}/lxd.pid") + check_leftovers="false" + lxd_backend=$(storage_backend "$daemon_dir") + echo "==> Killing LXD at ${daemon_dir}" + + if [ -e "${daemon_dir}/unix.socket" ]; then + # Delete all containers + echo "==> Deleting all containers" + for container in $(lxc list --fast --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do + lxc delete "${container}" --force-local -f || true + done + + # Delete all images + echo "==> Deleting all images" + for image in $(lxc image list --force-local | tail -n+3 | grep "^| " | cut -d'|' -f3 | sed "s/^ //g"); do + lxc image delete "${image}" --force-local || true + done + + # Delete all networks + echo "==> Deleting all networks" + for network in $(lxc network list --force-local | grep YES | grep "^| " | cut -d' ' -f2); do + lxc network delete "${network}" --force-local || true + done + + # Delete all profiles + echo "==> Deleting all profiles" + for profile in $(lxc profile list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do + lxc profile delete "${profile}" --force-local || true + done + + echo "==> Deleting all storage pools" + for storage in $(lxc storage list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do + lxc storage delete "${storage}" --force-local || true + done + + echo "==> Checking for locked DB tables" + for table in $(echo .tables | sqlite3 "${daemon_dir}/lxd.db"); do + echo "SELECT * FROM ${table};" | sqlite3 "${daemon_dir}/lxd.db" >/dev/null + done + + # Kill the daemon + lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true + + # Cleanup shmounts (needed due to the forceful kill) + find "${daemon_dir}" -name shmounts -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true + find "${daemon_dir}" -name devlxd -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true + + check_leftovers="true" + fi + + if [ -n "${LXD_LOGS:-}" ]; then + echo "==> Copying the logs" + mkdir -p "${LXD_LOGS}/${daemon_pid}" + cp -R "${daemon_dir}/logs/" "${LXD_LOGS}/${daemon_pid}/" + cp "${daemon_dir}/lxd.log" "${LXD_LOGS}/${daemon_pid}/" + fi + + if [ "${check_leftovers}" = "true" ]; then + echo "==> Checking for leftover files" + rm -f "${daemon_dir}/containers/lxc-monitord.log" + rm -f "${daemon_dir}/security/apparmor/cache/.features" + check_empty "${daemon_dir}/containers/" + check_empty "${daemon_dir}/devices/" + check_empty "${daemon_dir}/images/" + # FIXME: Once container logging rework is done, uncomment + # check_empty "${daemon_dir}/logs/" + check_empty "${daemon_dir}/security/apparmor/cache/" + check_empty "${daemon_dir}/security/apparmor/profiles/" + check_empty "${daemon_dir}/security/seccomp/" + check_empty "${daemon_dir}/shmounts/" + check_empty "${daemon_dir}/snapshots/" + + echo "==> Checking for leftover DB entries" + check_empty_table "${daemon_dir}/lxd.db" "containers" + check_empty_table "${daemon_dir}/lxd.db" "containers_config" + check_empty_table "${daemon_dir}/lxd.db" "containers_devices" + check_empty_table "${daemon_dir}/lxd.db" "containers_devices_config" + check_empty_table "${daemon_dir}/lxd.db" "containers_profiles" + check_empty_table "${daemon_dir}/lxd.db" "networks" + check_empty_table "${daemon_dir}/lxd.db" "networks_config" + check_empty_table "${daemon_dir}/lxd.db" "images" + check_empty_table "${daemon_dir}/lxd.db" "images_aliases" + check_empty_table "${daemon_dir}/lxd.db" "images_properties" + check_empty_table "${daemon_dir}/lxd.db" "images_source" + check_empty_table "${daemon_dir}/lxd.db" "profiles" + check_empty_table "${daemon_dir}/lxd.db" "profiles_config" + check_empty_table "${daemon_dir}/lxd.db" "profiles_devices" + check_empty_table "${daemon_dir}/lxd.db" "profiles_devices_config" + check_empty_table "${daemon_dir}/lxd.db" "storage_pools" + check_empty_table "${daemon_dir}/lxd.db" "storage_pools_config" + check_empty_table "${daemon_dir}/lxd.db" "storage_volumes" + check_empty_table "${daemon_dir}/lxd.db" "storage_volumes_config" + fi + + # teardown storage + "$lxd_backend"_teardown "${daemon_dir}" + + # Wipe the daemon directory + wipe "${daemon_dir}" + + # Remove the daemon from the list + sed "\|^${daemon_dir}|d" -i "${TEST_DIR}/daemons" +} + +shutdown_lxd() { + # LXD_DIR is local here because since $(lxc) is actually a function, it + # overwrites the environment and we would lose LXD_DIR's value otherwise. + + # shellcheck disable=2039 + local LXD_DIR + + daemon_dir=${1} + LXD_DIR=${daemon_dir} + daemon_pid=$(cat "${daemon_dir}/lxd.pid") + echo "==> Killing LXD at ${daemon_dir}" + + # Kill the daemon + lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true +} + +cleanup() { + # Allow for failures and stop tracing everything + set +ex + DEBUG= + + # Allow for inspection + if [ -n "${LXD_INSPECT:-}" ]; then + if [ "${TEST_RESULT}" != "success" ]; then + echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}" + fi + echo "==> Test result: ${TEST_RESULT}" + + # shellcheck disable=SC2086 + printf "To poke around, use:\n LXD_DIR=%s LXD_CONF=%s sudo -E %s/bin/lxc COMMAND\n" "${LXD_DIR}" "${LXD_CONF}" ${GOPATH:-} + echo "Tests Completed (${TEST_RESULT}): hit enter to continue" + + # shellcheck disable=SC2034 + read -r nothing + fi + + echo "==> Cleaning up" + + # Kill all the LXD instances + # shellcheck disable=SC2039 + local daemon_dir + while read -r daemon_dir; do + kill_lxd "${daemon_dir}" + done < "${TEST_DIR}/daemons" + + # Cleanup leftover networks + # shellcheck disable=SC2009 + ps aux | grep "interface=lxdt$$ " | grep -v grep | awk '{print $2}' | while read -r line; do + kill -9 "${line}" + done + if [ -e "/sys/class/net/lxdt$$" ]; then + ip link del lxdt$$ + fi + + # Wipe the test environment + wipe "${TEST_DIR}" + + echo "" + echo "" + if [ "${TEST_RESULT}" != "success" ]; then + echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}" + fi + echo "==> Test result: ${TEST_RESULT}" +} + +wait_for() { + # shellcheck disable=SC2039 + local addr op + + addr=${1} + shift + op=$("$@" | jq -r .operation) + my_curl "https://${addr}${op}/wait" +} + +wipe() { + if which btrfs >/dev/null 2>&1; then + rm -Rf "${1}" 2>/dev/null || true + if [ -d "${1}" ]; then + find "${1}" | tac | xargs btrfs subvolume delete >/dev/null 2>&1 || true + fi + fi + + # shellcheck disable=SC2039 + local pid + # shellcheck disable=SC2009 + ps aux | grep lxc-monitord | grep "${1}" | awk '{print $2}' | while read -r pid; do + kill -9 "${pid}" || true + done + + if [ -f "${TEST_DIR}/loops" ]; then + while read -r line; do + losetup -d "${line}" || true + done < "${TEST_DIR}/loops" + fi + if mountpoint -q "${1}"; then + umount "${1}" + fi + + rm -Rf "${1}" +} diff --git a/test/main.sh b/test/main.sh index c127cbd2d..7d060ae5a 100755 --- a/test/main.sh +++ b/test/main.sh @@ -62,157 +62,6 @@ for backend in $(available_storage_backends); do . "backends/${backend}.sh" done - -spawn_lxd() { - set +x - # LXD_DIR is local here because since $(lxc) is actually a function, it - # overwrites the environment and we would lose LXD_DIR's value otherwise. - - # shellcheck disable=2039 - local LXD_DIR lxddir lxd_backend - - lxddir=${1} - shift - - storage=${1} - shift - - if [ "$LXD_BACKEND" = "random" ]; then - lxd_backend="$(random_storage_backend)" - else - lxd_backend="$LXD_BACKEND" - fi - - if [ "${LXD_BACKEND}" = "ceph" ] && [ -z "${LXD_CEPH_CLUSTER:-}" ]; then - echo "A cluster name must be specified when using the CEPH driver." >&2 - exit 1 - fi - - # Copy pre generated Certs - cp deps/server.crt "${lxddir}" - cp deps/server.key "${lxddir}" - - # setup storage - "$lxd_backend"_setup "${lxddir}" - echo "$lxd_backend" > "${lxddir}/lxd.backend" - - echo "==> Spawning lxd in ${lxddir}" - # shellcheck disable=SC2086 - LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 & - LXD_PID=$! - echo "${LXD_PID}" > "${lxddir}/lxd.pid" - echo "${lxddir}" >> "${TEST_DIR}/daemons" - echo "==> Spawned LXD (PID is ${LXD_PID})" - - echo "==> Confirming lxd is responsive" - LXD_DIR="${lxddir}" lxd waitready --timeout=300 - - echo "==> Binding to network" - # shellcheck disable=SC2034 - for i in $(seq 10); do - addr="127.0.0.1:$(local_tcp_port)" - LXD_DIR="${lxddir}" lxc config set core.https_address "${addr}" || continue - echo "${addr}" > "${lxddir}/lxd.addr" - echo "==> Bound to ${addr}" - break - done - - echo "==> Setting trust password" - LXD_DIR="${lxddir}" lxc config set core.trust_password foo - if [ -n "${DEBUG:-}" ]; then - set -x - fi - - echo "==> Setting up networking" - LXD_DIR="${lxddir}" lxc profile device add default eth0 nic nictype=p2p name=eth0 - - if [ "${storage}" = true ]; then - echo "==> Configuring storage backend" - "$lxd_backend"_configure "${lxddir}" - fi -} - -respawn_lxd() { - set +x - # LXD_DIR is local here because since $(lxc) is actually a function, it - # overwrites the environment and we would lose LXD_DIR's value otherwise. - - # shellcheck disable=2039 - local LXD_DIR - - lxddir=${1} - shift - - echo "==> Spawning lxd in ${lxddir}" - # shellcheck disable=SC2086 - LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 & - LXD_PID=$! - echo "${LXD_PID}" > "${lxddir}/lxd.pid" - echo "==> Spawned LXD (PID is ${LXD_PID})" - - echo "==> Confirming lxd is responsive" - LXD_DIR="${lxddir}" lxd waitready --timeout=300 -} - -lxc() { - LXC_LOCAL=1 - lxc_remote "$@" - RET=$? - unset LXC_LOCAL - return ${RET} -} - -lxc_remote() { - set +x - injected=0 - cmd=$(which lxc) - - # shellcheck disable=SC2048,SC2068 - for arg in $@; do - if [ "${arg}" = "--" ]; then - injected=1 - cmd="${cmd} ${DEBUG:-}" - [ -n "${LXC_LOCAL}" ] && cmd="${cmd} --force-local" - cmd="${cmd} --" - elif [ "${arg}" = "--force-local" ]; then - continue - else - cmd="${cmd} \"${arg}\"" - fi - done - - if [ "${injected}" = "0" ]; then - cmd="${cmd} ${DEBUG-}" - fi - if [ -n "${DEBUG:-}" ]; then - set -x - fi - eval "${cmd}" -} - -gen_cert() { - # Temporarily move the existing cert to trick LXC into generating a - # second cert. LXC will only generate a cert when adding a remote - # server with a HTTPS scheme. The remote server URL just needs to - # be syntactically correct to get past initial checks; in fact, we - # don't want it to succeed, that way we don't have to delete it later. - [ -f "${LXD_CONF}/${1}.crt" ] && return - mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client.crt.bak" - mv "${LXD_CONF}/client.key" "${LXD_CONF}/client.key.bak" - echo y | lxc_remote remote add "$(uuidgen)" https://0.0.0.0 || true - mv "${LXD_CONF}/client.crt" "${LXD_CONF}/${1}.crt" - mv "${LXD_CONF}/client.key" "${LXD_CONF}/${1}.key" - mv "${LXD_CONF}/client.crt.bak" "${LXD_CONF}/client.crt" - mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key" -} - -wait_for() { - addr=${1} - shift - op=$("$@" | jq -r .operation) - my_curl "https://${addr}${op}/wait" -} - ensure_has_localhost_remote() { addr=${1} if ! lxc remote list | grep -q "localhost"; then @@ -256,207 +105,6 @@ check_empty_table() { fi } -kill_lxd() { - # LXD_DIR is local here because since $(lxc) is actually a function, it - # overwrites the environment and we would lose LXD_DIR's value otherwise. - - # shellcheck disable=2039 - local LXD_DIR daemon_dir daemon_pid check_leftovers lxd_backend - - daemon_dir=${1} - LXD_DIR=${daemon_dir} - daemon_pid=$(cat "${daemon_dir}/lxd.pid") - check_leftovers="false" - lxd_backend=$(storage_backend "$daemon_dir") - echo "==> Killing LXD at ${daemon_dir}" - - if [ -e "${daemon_dir}/unix.socket" ]; then - # Delete all containers - echo "==> Deleting all containers" - for container in $(lxc list --fast --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do - lxc delete "${container}" --force-local -f || true - done - - # Delete all images - echo "==> Deleting all images" - for image in $(lxc image list --force-local | tail -n+3 | grep "^| " | cut -d'|' -f3 | sed "s/^ //g"); do - lxc image delete "${image}" --force-local || true - done - - # Delete all networks - echo "==> Deleting all networks" - for network in $(lxc network list --force-local | grep YES | grep "^| " | cut -d' ' -f2); do - lxc network delete "${network}" --force-local || true - done - - # Delete all profiles - echo "==> Deleting all profiles" - for profile in $(lxc profile list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do - lxc profile delete "${profile}" --force-local || true - done - - echo "==> Deleting all storage pools" - for storage in $(lxc storage list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do - lxc storage delete "${storage}" --force-local || true - done - - echo "==> Checking for locked DB tables" - for table in $(echo .tables | sqlite3 "${daemon_dir}/lxd.db"); do - echo "SELECT * FROM ${table};" | sqlite3 "${daemon_dir}/lxd.db" >/dev/null - done - - # Kill the daemon - lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true - - # Cleanup shmounts (needed due to the forceful kill) - find "${daemon_dir}" -name shmounts -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true - find "${daemon_dir}" -name devlxd -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true - - check_leftovers="true" - fi - - if [ -n "${LXD_LOGS:-}" ]; then - echo "==> Copying the logs" - mkdir -p "${LXD_LOGS}/${daemon_pid}" - cp -R "${daemon_dir}/logs/" "${LXD_LOGS}/${daemon_pid}/" - cp "${daemon_dir}/lxd.log" "${LXD_LOGS}/${daemon_pid}/" - fi - - if [ "${check_leftovers}" = "true" ]; then - echo "==> Checking for leftover files" - rm -f "${daemon_dir}/containers/lxc-monitord.log" - rm -f "${daemon_dir}/security/apparmor/cache/.features" - check_empty "${daemon_dir}/containers/" - check_empty "${daemon_dir}/devices/" - check_empty "${daemon_dir}/images/" - # FIXME: Once container logging rework is done, uncomment - # check_empty "${daemon_dir}/logs/" - check_empty "${daemon_dir}/security/apparmor/cache/" - check_empty "${daemon_dir}/security/apparmor/profiles/" - check_empty "${daemon_dir}/security/seccomp/" - check_empty "${daemon_dir}/shmounts/" - check_empty "${daemon_dir}/snapshots/" - - echo "==> Checking for leftover DB entries" - check_empty_table "${daemon_dir}/lxd.db" "containers" - check_empty_table "${daemon_dir}/lxd.db" "containers_config" - check_empty_table "${daemon_dir}/lxd.db" "containers_devices" - check_empty_table "${daemon_dir}/lxd.db" "containers_devices_config" - check_empty_table "${daemon_dir}/lxd.db" "containers_profiles" - check_empty_table "${daemon_dir}/lxd.db" "networks" - check_empty_table "${daemon_dir}/lxd.db" "networks_config" - check_empty_table "${daemon_dir}/lxd.db" "images" - check_empty_table "${daemon_dir}/lxd.db" "images_aliases" - check_empty_table "${daemon_dir}/lxd.db" "images_properties" - check_empty_table "${daemon_dir}/lxd.db" "images_source" - check_empty_table "${daemon_dir}/lxd.db" "profiles" - check_empty_table "${daemon_dir}/lxd.db" "profiles_config" - check_empty_table "${daemon_dir}/lxd.db" "profiles_devices" - check_empty_table "${daemon_dir}/lxd.db" "profiles_devices_config" - check_empty_table "${daemon_dir}/lxd.db" "storage_pools" - check_empty_table "${daemon_dir}/lxd.db" "storage_pools_config" - check_empty_table "${daemon_dir}/lxd.db" "storage_volumes" - check_empty_table "${daemon_dir}/lxd.db" "storage_volumes_config" - fi - - # teardown storage - "$lxd_backend"_teardown "${daemon_dir}" - - # Wipe the daemon directory - wipe "${daemon_dir}" - - # Remove the daemon from the list - sed "\|^${daemon_dir}|d" -i "${TEST_DIR}/daemons" -} - -shutdown_lxd() { - # LXD_DIR is local here because since $(lxc) is actually a function, it - # overwrites the environment and we would lose LXD_DIR's value otherwise. - - # shellcheck disable=2039 - local LXD_DIR - - daemon_dir=${1} - LXD_DIR=${daemon_dir} - daemon_pid=$(cat "${daemon_dir}/lxd.pid") - echo "==> Killing LXD at ${daemon_dir}" - - # Kill the daemon - lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true -} - -cleanup() { - # Allow for failures and stop tracing everything - set +ex - DEBUG= - - # Allow for inspection - if [ -n "${LXD_INSPECT:-}" ]; then - if [ "${TEST_RESULT}" != "success" ]; then - echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}" - fi - echo "==> Test result: ${TEST_RESULT}" - - # shellcheck disable=SC2086 - printf "To poke around, use:\n LXD_DIR=%s LXD_CONF=%s sudo -E %s/bin/lxc COMMAND\n" "${LXD_DIR}" "${LXD_CONF}" ${GOPATH:-} - echo "Tests Completed (${TEST_RESULT}): hit enter to continue" - - # shellcheck disable=SC2034 - read -r nothing - fi - - echo "==> Cleaning up" - - # Kill all the LXD instances - while read -r daemon_dir; do - kill_lxd "${daemon_dir}" - done < "${TEST_DIR}/daemons" - - # Cleanup leftover networks - # shellcheck disable=SC2009 - ps aux | grep "interface=lxdt$$ " | grep -v grep | awk '{print $2}' | while read -r line; do - kill -9 "${line}" - done - if [ -e "/sys/class/net/lxdt$$" ]; then - ip link del lxdt$$ - fi - - # Wipe the test environment - wipe "${TEST_DIR}" - - echo "" - echo "" - if [ "${TEST_RESULT}" != "success" ]; then - echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}" - fi - echo "==> Test result: ${TEST_RESULT}" -} - -wipe() { - if which btrfs >/dev/null 2>&1; then - rm -Rf "${1}" 2>/dev/null || true - if [ -d "${1}" ]; then - find "${1}" | tac | xargs btrfs subvolume delete >/dev/null 2>&1 || true - fi - fi - - # shellcheck disable=SC2009 - ps aux | grep lxc-monitord | grep "${1}" | awk '{print $2}' | while read -r pid; do - kill -9 "${pid}" || true - done - - if [ -f "${TEST_DIR}/loops" ]; then - while read -r line; do - losetup -d "${line}" || true - done < "${TEST_DIR}/loops" - fi - if mountpoint -q "${1}"; then - umount "${1}" - fi - - rm -Rf "${1}" -} - # Must be set before cleanup() TEST_CURRENT=setup From 076103ad539aec71e12df6bfcda66eefb93f8888 Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Thu, 17 Aug 2017 13:50:40 +0200 Subject: [PATCH 4/8] tests: split out test setup related helper functions Signed-off-by: Alberto Donato <[email protected]> --- test/includes/setup.sh | 29 +++++++++++++++++++++++++++++ test/main.sh | 26 -------------------------- 2 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 test/includes/setup.sh diff --git a/test/includes/setup.sh b/test/includes/setup.sh new file mode 100644 index 000000000..1ecbc5cbe --- /dev/null +++ b/test/includes/setup.sh @@ -0,0 +1,29 @@ +# Test setup helper functions. + +ensure_has_localhost_remote() { + # shellcheck disable=SC2039 + local addr=${1} + if ! lxc remote list | grep -q "localhost"; then + lxc remote add localhost "https://${addr}" --accept-certificate --password foo + fi +} + +ensure_import_testimage() { + if ! lxc image alias list | grep -q "^| testimage\s*|.*$"; then + if [ -e "${LXD_TEST_IMAGE:-}" ]; then + lxc image import "${LXD_TEST_IMAGE}" --alias testimage + else + if [ ! -e "/bin/busybox" ]; then + echo "Please install busybox (busybox-static) or set LXD_TEST_IMAGE" + exit 1 + fi + + if ldd /bin/busybox >/dev/null 2>&1; then + echo "The testsuite requires /bin/busybox to be a static binary" + exit 1 + fi + + deps/import-busybox --alias testimage + fi + fi +} diff --git a/test/main.sh b/test/main.sh index 7d060ae5a..8797c10b1 100755 --- a/test/main.sh +++ b/test/main.sh @@ -62,32 +62,6 @@ for backend in $(available_storage_backends); do . "backends/${backend}.sh" done -ensure_has_localhost_remote() { - addr=${1} - if ! lxc remote list | grep -q "localhost"; then - lxc remote add localhost "https://${addr}" --accept-certificate --password foo - fi -} - -ensure_import_testimage() { - if ! lxc image alias list | grep -q "^| testimage\s*|.*$"; then - if [ -e "${LXD_TEST_IMAGE:-}" ]; then - lxc image import "${LXD_TEST_IMAGE}" --alias testimage - else - if [ ! -e "/bin/busybox" ]; then - echo "Please install busybox (busybox-static) or set LXD_TEST_IMAGE" - exit 1 - fi - - if ldd /bin/busybox >/dev/null 2>&1; then - echo "The testsuite requires /bin/busybox to be a static binary" - exit 1 - fi - - deps/import-busybox --alias testimage - fi - fi -} check_empty() { if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then From 152691cac7f987fe5736352a9e852db0faea0bdf Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Thu, 17 Aug 2017 15:20:11 +0200 Subject: [PATCH 5/8] tests: split out checks helper functions Signed-off-by: Alberto Donato <[email protected]> --- test/includes/check.sh | 17 +++++++++++++++++ test/main.sh | 17 ----------------- 2 files changed, 17 insertions(+), 17 deletions(-) create mode 100644 test/includes/check.sh diff --git a/test/includes/check.sh b/test/includes/check.sh new file mode 100644 index 000000000..0447402c5 --- /dev/null +++ b/test/includes/check.sh @@ -0,0 +1,17 @@ +# Miscellanous test checks. + +check_empty() { + if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then + echo "${1} is not empty, content:" + find "${1}" + false + fi +} + +check_empty_table() { + if [ -n "$(sqlite3 "${1}" "SELECT * FROM ${2};")" ]; then + echo "DB table ${2} is not empty, content:" + sqlite3 "${1}" "SELECT * FROM ${2};" + false + fi +} diff --git a/test/main.sh b/test/main.sh index 8797c10b1..8075861e2 100755 --- a/test/main.sh +++ b/test/main.sh @@ -63,23 +63,6 @@ for backend in $(available_storage_backends); do done -check_empty() { - if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then - echo "${1} is not empty, content:" - find "${1}" - false - fi -} - -check_empty_table() { - if [ -n "$(sqlite3 "${1}" "SELECT * FROM ${2};")" ]; then - echo "DB table ${2} is not empty, content:" - sqlite3 "${1}" "SELECT * FROM ${2};" - false - fi -} - - # Must be set before cleanup() TEST_CURRENT=setup TEST_RESULT=failure From d818291e4ac6ae171d9ee714bce9de0e7885a3f0 Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Thu, 17 Aug 2017 12:57:12 +0200 Subject: [PATCH 6/8] tests: add helper for importing shell files Signed-off-by: Alberto Donato <[email protected]> --- test/main.sh | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/test/main.sh b/test/main.sh index 8075861e2..5a2402350 100755 --- a/test/main.sh +++ b/test/main.sh @@ -36,10 +36,17 @@ if [ -n "${LXD_LOGS:-}" ] && [ ! -d "${LXD_LOGS}" ]; then fi # Helper functions -for include in includes/*.sh; do - # shellcheck disable=SC1090 - . "$include" -done +import_subdir_files() { + test "$1" + # shellcheck disable=SC2039 + local file + for file in "$1"/*.sh; do + # shellcheck disable=SC1090 + . "$file" + done +} + +import_subdir_files includes if [ -z "${LXD_BACKEND:-}" ]; then LXD_BACKEND=dir @@ -70,10 +77,7 @@ TEST_RESULT=failure trap cleanup EXIT HUP INT TERM # Import all the testsuites -for suite in suites/*.sh; do - # shellcheck disable=SC1090 - . "${suite}" -done +import_subdir_files suites # Setup test directory TEST_DIR=$(mktemp -d -p "$(pwd)" tmp.XXX) From 74a471ffd391d56815f6b8830ffd864485db8654 Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Thu, 17 Aug 2017 13:28:37 +0200 Subject: [PATCH 7/8] tests: lints Signed-off-by: Alberto Donato <[email protected]> --- test/includes/lxd.sh | 1 + test/main.sh | 3 ++- test/suites/static_analysis.sh | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/includes/lxd.sh b/test/includes/lxd.sh index a8e2f561b..baa64cbe3 100644 --- a/test/includes/lxd.sh +++ b/test/includes/lxd.sh @@ -14,6 +14,7 @@ spawn_lxd() { storage=${1} shift + # shellcheck disable=SC2153 if [ "$LXD_BACKEND" = "random" ]; then lxd_backend="$(random_storage_backend)" else diff --git a/test/main.sh b/test/main.sh index 5a2402350..ec4ce774c 100755 --- a/test/main.sh +++ b/test/main.sh @@ -11,6 +11,7 @@ if [ -n "${LXD_VERBOSE:-}" ] || [ -n "${LXD_DEBUG:-}" ]; then set -x fi +export DEBUG if [ -n "${LXD_VERBOSE:-}" ]; then DEBUG="--verbose" fi @@ -72,7 +73,7 @@ done # Must be set before cleanup() TEST_CURRENT=setup -TEST_RESULT=failure +export TEST_RESULT=failure trap cleanup EXIT HUP INT TERM diff --git a/test/suites/static_analysis.sh b/test/suites/static_analysis.sh index a87ef9cc6..f831d22aa 100644 --- a/test/suites/static_analysis.sh +++ b/test/suites/static_analysis.sh @@ -16,7 +16,7 @@ test_static_analysis() { # Shell static analysis if which shellcheck >/dev/null 2>&1; then - shellcheck --shell sh test/main.sh test/suites/* test/backends/* + shellcheck --shell sh test/*.sh test/includes/*.sh test/suites/*.sh test/backends/*.sh else echo "shellcheck not found, shell static analysis disabled" fi From 6e915ed3c14323a8a2685e81c51d3a3816c3e388 Mon Sep 17 00:00:00 2001 From: Alberto Donato <[email protected]> Date: Thu, 17 Aug 2017 15:51:57 +0200 Subject: [PATCH 8/8] Add dependencies check helper. Signed-off-by: Alberto Donato <[email protected]> --- test/includes/check.sh | 17 +++++++++++++++++ test/main.sh | 13 +++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/test/includes/check.sh b/test/includes/check.sh index 0447402c5..421225083 100644 --- a/test/includes/check.sh +++ b/test/includes/check.sh @@ -1,5 +1,22 @@ # Miscellanous test checks. + +check_dependencies() { + # shellcheck disable=SC2039 + local dep missing + + for dep in "$@"; do + if ! which "$dep" >/dev/null 2>&1; then + [ "$missing" ] && missing="$missing $dep" || missing="$dep" + fi + done + + if [ "$missing" ]; then + echo "Missing dependencies: $missing" >&2 + exit 1 + fi +} + check_empty() { if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then echo "${1} is not empty, content:" diff --git a/test/main.sh b/test/main.sh index ec4ce774c..69630b074 100755 --- a/test/main.sh +++ b/test/main.sh @@ -20,11 +20,12 @@ if [ -n "${LXD_DEBUG:-}" ]; then DEBUG="--debug" fi +if [ -z "${LXD_BACKEND:-}" ]; then + LXD_BACKEND="dir" +fi + echo "==> Checking for dependencies" -deps="lxd lxc curl jq git xgettext sqlite3 msgmerge msgfmt shuf setfacl uuidgen" -for dep in $deps; do - which "${dep}" >/dev/null 2>&1 || (echo "Missing dependency: ${dep}" >&2 && exit 1) -done +check_dependencies lxd lxc curl jq git xgettext sqlite3 msgmerge msgfmt shuf setfacl uuidgen if [ "${USER:-'root'}" != "root" ]; then echo "The testsuite must be run as root." >&2 @@ -49,10 +50,6 @@ import_subdir_files() { import_subdir_files includes -if [ -z "${LXD_BACKEND:-}" ]; then - LXD_BACKEND=dir -fi - echo "==> Available storage backends: $(available_storage_backends | sort)" if [ "$LXD_BACKEND" != "random" ] && ! storage_backend_available "$LXD_BACKEND"; then if [ "${LXD_BACKEND}" = "ceph" ] && [ -z "${LXD_CEPH_CLUSTER:-}" ]; then
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
