#!/bin/bash # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License, Version 1.0 only # (the "License"). You may not use this file except in compliance # with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # basedir=$(dirname "$0") SCRIPT_COMMON=common.sh if [ -f "${basedir}/${SCRIPT_COMMON}" ]; then . "${basedir}/${SCRIPT_COMMON}" else echo "Missing helper script ${SCRIPT_COMMON}" && exit 1 fi . "$STF_SUITE/include/default.cfg" PROG=zfs-tests.sh SUDO=/usr/bin/sudo SETENFORCE=/usr/sbin/setenforce VERBOSE= QUIET= CLEANUP=1 CLEANUPALL=0 LOOPBACK=1 FILESIZE="4G" RUNFILE=${RUNFILE:-"linux.run"} FILEDIR=${FILEDIR:-/var/tmp} DISKS=${DISKS:-""} SINGLETEST=() SINGLETESTUSER="root" # # Attempt to remove loopback devices and files which where created earlier # by this script to run the test framework. The '-k' option may be passed # to the script to suppress cleanup for debugging purposes. # cleanup() { if [ $CLEANUP -eq 0 ]; then return 0 fi if [ $LOOPBACK -eq 1 ]; then for TEST_LOOPBACK in ${LOOPBACKS}; do LOOP_DEV=$(basename "$TEST_LOOPBACK") DM_DEV=$(${SUDO} "${DMSETUP}" ls 2>/dev/null | \ grep "${LOOP_DEV}" | cut -f1) if [ -n "$DM_DEV" ]; then ${SUDO} "${DMSETUP}" remove "${DM_DEV}" || echo "Failed to remove: ${DM_DEV}" fi if [ -n "${TEST_LOOPBACK}" ]; then ${SUDO} "${LOSETUP}" -d "${TEST_LOOPBACK}" || echo "Failed to remove: ${TEST_LOOPBACK}" fi done fi for TEST_FILE in ${FILES}; do rm -f "${TEST_FILE}" &>/dev/null done } trap cleanup EXIT # # Attempt to remove all testpools (testpool.XXX), unopened dm devices, # loopback devices, and files. This is a useful way to cleanup a previous # test run failure which has left the system in an unknown state. This can # be dangerous and should only be used in a dedicated test environment. # cleanup_all() { local TEST_POOLS TEST_POOLS=$(${SUDO} "${ZPOOL}" list -H -o name | grep testpool) local TEST_LOOPBACKS TEST_LOOPBACKS=$(${SUDO} "${LOSETUP}" -a|grep file-vdev|cut -f1 -d:) local TEST_FILES TEST_FILES=$(ls /var/tmp/file-vdev* 2>/dev/null) msg msg "--- Cleanup ---" msg "Removing pool(s): $(echo "${TEST_POOLS}" | tr '\n' ' ')" for TEST_POOL in $TEST_POOLS; do ${SUDO} "${ZPOOL}" destroy "${TEST_POOL}" done msg "Removing dm(s): $(${SUDO} "${DMSETUP}" ls | grep loop | tr '\n' ' ')" ${SUDO} "${DMSETUP}" remove_all msg "Removing loopback(s): $(echo "${TEST_LOOPBACKS}" | tr '\n' ' ')" for TEST_LOOPBACK in $TEST_LOOPBACKS; do ${SUDO} "${LOSETUP}" -d "${TEST_LOOPBACK}" done msg "Removing files(s): $(echo "${TEST_FILES}" | tr '\n' ' ')" for TEST_FILE in $TEST_FILES; do ${SUDO} rm -f "${TEST_FILE}" done } # # Log a failure message, cleanup, and return an error. # fail() { echo -e "${PROG}: $1" >&2 cleanup exit 1 } # # Takes a name as the only arguments and looks for the following variations # on that name. If one is found it is returned. # # $RUNFILEDIR/ # $RUNFILEDIR/.run # # .run # find_runfile() { local NAME=$1 local RESULT="" if [ -f "$RUNFILEDIR/$NAME" ]; then RESULT="$RUNFILEDIR/$NAME" elif [ -f "$RUNFILEDIR/$NAME.run" ]; then RESULT="$RUNFILEDIR/$NAME.run" elif [ -f "$NAME" ]; then RESULT="$NAME" elif [ -f "$NAME.run" ]; then RESULT="$NAME.run" fi echo "$RESULT" } # # Output a useful usage message. # usage() { cat << EOF USAGE: $0 [hvqxkf] [-s SIZE] [-r RUNFILE] [-t PATH] [-u USER] DESCRIPTION: ZFS Test Suite launch script OPTIONS: -h Show this message -v Verbose zfs-tests.sh output -q Quiet test-runner output -x Remove all testpools, dm, lo, and files (unsafe) -k Disable cleanup after test failure -f Use files only, disables block device tests -d DIR Use DIR for files and loopback devices -s SIZE Use vdevs of SIZE (default: 4G) -r RUNFILE Run tests in RUNFILE (default: linux.run) -t PATH Run single test at PATH relative to test suite -u USER Run single test as USER (default: root) EXAMPLES: # Run the default (linux) suite of tests and output the configuration used. $0 -v # Run a smaller suite of tests designed to run more quickly. $0 -r linux-fast # Cleanup a previous run of the test suite prior to testing, run the # default (linux) suite of tests and perform no cleanup on exit. $0 -x EOF } while getopts 'hvqxkfd:s:r:?t:u:' OPTION; do case $OPTION in h) usage exit 1 ;; v) # shellcheck disable=SC2034 VERBOSE=1 ;; q) QUIET="-q" ;; x) CLEANUPALL=1 ;; k) CLEANUP=0 ;; f) LOOPBACK=0 ;; d) FILEDIR="$OPTARG" ;; s) FILESIZE="$OPTARG" ;; r) RUNFILE="$OPTARG" ;; t) if [ ${#SINGLETEST[@]} -ne 0 ]; then fail "-t can only be provided once." fi SINGLETEST+=("$OPTARG") ;; u) SINGLETESTUSER="$OPTARG" ;; ?) usage exit ;; esac done shift $((OPTIND-1)) FILES=${FILES:-"$FILEDIR/file-vdev0 $FILEDIR/file-vdev1 $FILEDIR/file-vdev2"} LOOPBACKS=${LOOPBACKS:-""} if [ ${#SINGLETEST[@]} -ne 0 ]; then RUNFILEDIR="/var/tmp" RUNFILE="zfs-tests.$$.run" SINGLEQUIET="False" if [ -n "$QUIET" ]; then SINGLEQUIET="True" fi cat >$RUNFILEDIR/$RUNFILE << EOF [DEFAULT] pre = quiet = $SINGLEQUIET pre_user = root user = $SINGLETESTUSER timeout = 600 post_user = root post = outputdir = /var/tmp/test_results EOF for t in "${SINGLETEST[@]}" do SINGLETESTDIR=$(dirname "$t") SINGLETESTFILE=$(basename "$t") SETUPSCRIPT= CLEANUPSCRIPT= if [ -f "$STF_SUITE/$SINGLETESTDIR/setup.ksh" ]; then SETUPSCRIPT="setup" fi if [ -f "$STF_SUITE/$SINGLETESTDIR/cleanup.ksh" ]; then CLEANUPSCRIPT="cleanup" fi cat >>$RUNFILEDIR/$RUNFILE << EOF [$SINGLETESTDIR] tests = ['$SINGLETESTFILE'] pre = $SETUPSCRIPT post = $CLEANUPSCRIPT EOF done fi # # Attempt to locate the runfile describing the test workload. # if [ -n "$RUNFILE" ]; then SAVED_RUNFILE="$RUNFILE" RUNFILE=$(find_runfile "$RUNFILE") [ -z "$RUNFILE" ] && fail "Cannot find runfile: $SAVED_RUNFILE" fi if [ ! -r "$RUNFILE" ]; then fail "Cannot read runfile: $RUNFILE" fi # # This script should not be run as root. Instead the test user, which may # be a normal user account, needs to be configured such that it can # run commands via sudo passwordlessly. # if [ "$(id -u)" = "0" ]; then fail "This script must not be run as root." fi if [ "$(sudo whoami)" != "root" ]; then fail "Passwordless sudo access required." fi # # Check if ksh exists # if [ -z "$(which ksh 2>/dev/null)" ]; then fail "This test suite requires ksh." fi # # Verify the ZFS module stack if loaded. # ${SUDO} "${ZFS_SH}" &>/dev/null # # Attempt to cleanup all previous state for a new test run. # if [ $CLEANUPALL -ne 0 ]; then cleanup_all fi # # By default preserve any existing pools # if [ -z "${KEEP}" ]; then KEEP=$(${SUDO} "${ZPOOL}" list -H -o name) if [ -z "${KEEP}" ]; then KEEP="rpool" fi fi __ZFS_POOL_EXCLUDE="$(echo $KEEP | sed ':a;N;s/\n/ /g;ba')" msg msg "--- Configuration ---" msg "Runfile: $RUNFILE" msg "STF_TOOLS: $STF_TOOLS" msg "STF_SUITE: $STF_SUITE" # # No DISKS have been provided so a basic file or loopback based devices # must be created for the test suite to use. # if [ -z "${DISKS}" ]; then # # Create sparse files for the test suite. These may be used # directory or have loopback devices layered on them. # for TEST_FILE in ${FILES}; do [ -f "$TEST_FILE" ] && fail "Failed file exists: ${TEST_FILE}" truncate -s "${FILESIZE}" "${TEST_FILE}" || fail "Failed creating: ${TEST_FILE} ($?)" DISKS="$DISKS$TEST_FILE " done # # If requested setup loopback devices backed by the sparse files. # if [ $LOOPBACK -eq 1 ]; then DISKS="" check_loop_utils for TEST_FILE in ${FILES}; do TEST_LOOPBACK=$(${SUDO} "${LOSETUP}" -f) ${SUDO} "${LOSETUP}" "${TEST_LOOPBACK}" "${TEST_FILE}" || fail "Failed: ${TEST_FILE} -> ${TEST_LOOPBACK}" LOOPBACKS="${LOOPBACKS}${TEST_LOOPBACK} " BASELOOPBACKS=$(basename "$TEST_LOOPBACK") DISKS="$DISKS$BASELOOPBACKS " done fi fi NUM_DISKS=$(echo "${DISKS}" | $AWK '{print NF}') [ "$NUM_DISKS" -lt 3 ] && fail "Not enough disks ($NUM_DISKS/3 minimum)" # # Disable SELinux until the ZFS Test Suite has been updated accordingly. # if [ -x ${SETENFORCE} ]; then ${SUDO} ${SETENFORCE} permissive &>/dev/null fi msg "FILEDIR: $FILEDIR" msg "FILES: $FILES" msg "LOOPBACKS: $LOOPBACKS" msg "DISKS: $DISKS" msg "NUM_DISKS: $NUM_DISKS" msg "FILESIZE: $FILESIZE" msg "Keep pool(s): $KEEP" msg "" export STF_TOOLS export STF_SUITE export DISKS export KEEP export __ZFS_POOL_EXCLUDE msg "${TEST_RUNNER} ${QUIET} -c ${RUNFILE} -i ${STF_SUITE}" ${TEST_RUNNER} ${QUIET} -c "${RUNFILE}" -i "${STF_SUITE}" RESULT=$? echo if [ ${#SINGLETEST[@]} -ne 0 ]; then rm -f "$RUNFILE" &>/dev/null fi exit ${RESULT}