diff --git a/.travis.yml b/.travis.yml index 3079e44..f3ae313 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,49 +1,70 @@ +dist: bionic sudo: required language: c os: - linux - - linux-ppc64le + +arch: + - amd64 + - ppc64le + - s390x + - arm64 env: global: - PACKAGE=sbd - - BUILD_OS_TYPE=fedora BUILD_OS_DIST= BUILD_OS_VERSION=29 + # appealing idea to go with centos 8 as build-host but unfortunately that isn't available for all platforms + # and the docker-image isn't there for anything else but x86_64 + # - BUILD_OS_TYPE="centos:" BUILD_OS_DIST=centos BUILD_OS_VERSION=8 + # - BUILD_OS_PREPARE="yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && yum install -y mock yum-utils &&" + - BUILD_OS_TYPE="fedora:" BUILD_OS_DIST= BUILD_OS_VERSION=30 + - BUILD_OS_PREPARE="dnf install -y mock dnf-utils findutils patch &&" matrix: exclude: - - os: linux - - os: linux-ppc64le + - arch: amd64 + - arch: ppc64le + - arch: s390x + - arch: arm64 include: - - os: linux - env: OS_ARCH=x86_64 OS_TYPE=centos OS_MOCK=epel OS_DIST=centos OS_VERSION=7 - - os: linux - env: OS_ARCH=x86_64 OS_TYPE=centos OS_MOCK=epel OS_DIST=centos OS_VERSION=6 - - os: linux - env: OS_ARCH=x86_64 OS_TYPE=fedora OS_MOCK=fedora OS_DIST= OS_VERSION=29 - - os: linux - env: OS_ARCH=x86_64 OS_TYPE=fedora OS_MOCK=fedora OS_DIST= OS_VERSION=30 - - os: linux - env: OS_ARCH=x86_64 OS_TYPE=fedora OS_MOCK=fedora OS_DIST= OS_VERSION=rawhide - - os: linux-ppc64le - env: OS_ARCH=ppc64le OS_TYPE=fedora OS_MOCK=fedora OS_DIST= OS_VERSION=30 + - arch: amd64 + env: OS_ARCH=x86_64 OS_TYPE="centos:" OS_MOCK=epel OS_DIST=centos OS_VERSION=7 OS_INSTALL="yum install -y" DOCKER_OPTS="--privileged" TEST_ENV="SBD_USE_DM=yes" + - arch: amd64 + env: OS_ARCH=x86_64 OS_TYPE="centos:" OS_MOCK=epel OS_DIST=centos OS_VERSION=6 OS_INSTALL="yum install -y" DOCKER_OPTS="--privileged" TEST_ENV="SBD_USE_DM=yes" + - arch: amd64 + env: OS_ARCH=x86_64 OS_TYPE="fedora:" OS_MOCK=fedora OS_DIST= OS_VERSION=30 OS_INSTALL="dnf install -y" DOCKER_OPTS="--privileged" TEST_ENV="SBD_USE_DM=yes" + - arch: amd64 + env: OS_ARCH=x86_64 OS_TYPE="fedora:" OS_MOCK=fedora OS_DIST= OS_VERSION=rawhide OS_INSTALL="dnf install -y" DOCKER_OPTS="--privileged" TEST_ENV="SBD_USE_DM=yes" + - arch: ppc64le + env: OS_ARCH=ppc64le OS_TYPE="fedora:" OS_MOCK=fedora OS_DIST= OS_VERSION=30 OS_INSTALL="dnf install -y" DOCKER_OPTS="--cap-add=sys_admin" TEST_ENV="SBD_USE_DM=no" MOCK_OPTS="--config-opts=internal_dev_setup=False" + - arch: s390x + env: OS_ARCH=s390x OS_TYPE="fedora:" OS_MOCK=fedora OS_DIST= OS_VERSION=30 OS_INSTALL="dnf install -y" DOCKER_OPTS="--cap-add=sys_admin" TEST_ENV="SBD_USE_DM=no" MOCK_OPTS="--config-opts=internal_dev_setup=False" + - arch: arm64 + env: OS_ARCH=aarch64 OS_TYPE="fedora:" OS_MOCK=fedora OS_DIST= OS_VERSION=30 OS_INSTALL="dnf install -y" DOCKER_OPTS="--cap-add=sys_admin" TEST_ENV="SBD_USE_DM=no" MOCK_OPTS="--config-opts=internal_dev_setup=False" + - arch: amd64 + env: OS_ARCH=x86_64 OS_TYPE="opensuse/" OS_MOCK=opensuse-leap OS_DIST="leap:" OS_VERSION=15.1 OS_INSTALL="zypper --no-gpg-checks --non-interactive install" DOCKER_OPTS="--privileged" TEST_ENV="SBD_USE_DM=yes" + - arch: amd64 + env: OS_ARCH=x86_64 OS_TYPE="opensuse/" OS_MOCK=opensuse OS_DIST= OS_VERSION=tumbleweed OS_INSTALL="zypper --no-gpg-checks --non-interactive install" DOCKER_OPTS="--privileged" TEST_ENV="SBD_USE_DM=yes" services: - docker install: true script: + - BUILD_SUCCESS=false - make -f Makefile.am srpm PACKAGE=${PACKAGE} - - docker pull ${BUILD_OS_TYPE}:${BUILD_OS_DIST}${BUILD_OS_VERSION} - - docker run --privileged -v ${PWD}:/rpms ${BUILD_OS_TYPE}:${BUILD_OS_DIST}${BUILD_OS_VERSION} /bin/bash -c "dnf install -y mock dnf-utils && if test $OS_VERSION = rawhide; then sed -i /etc/mock/${OS_MOCK}-${OS_VERSION}-${OS_ARCH}.cfg -e s/gpgcheck.*/gpgcheck=0/g; fi && mock --no-clean -r ${OS_MOCK}-${OS_VERSION}-${OS_ARCH} --resultdir=/rpms --disable-plugin=yum_cache --disable-plugin=selinux --no-bootstrap-chroot --old-chroot /rpms/sbd*.src.rpm" - - ls ${PWD}/${PACKAGE}*.${OS_ARCH}.rpm - - docker pull ${OS_TYPE}:${OS_DIST}${OS_VERSION} - - docker run --privileged -v ${PWD}:/rpms ${OS_TYPE}:${OS_DIST}${OS_VERSION} /bin/bash -c "if test $OS_VERSION = rawhide; then yum update -y --nogpgcheck; fi && yum install -y device-mapper /rpms/${PACKAGE}*.${OS_ARCH}.rpm && /usr/share/sbd/regressions.sh && touch /rpms/regressions.sh.SUCCESS" + - docker pull ${BUILD_OS_TYPE}${BUILD_OS_DIST}${BUILD_OS_VERSION} + - docker run --cap-add=sys_admin -v ${PWD}:/rpms -v /proc:/var/lib/mock/${OS_MOCK}-${OS_VERSION}-${OS_ARCH}/root/proc -v ${PWD}:/rpms -v /sys:/var/lib/mock/${OS_MOCK}-${OS_VERSION}-${OS_ARCH}/root/sys ${BUILD_OS_TYPE}${BUILD_OS_DIST}${BUILD_OS_VERSION} /bin/bash -c "${BUILD_OS_PREPARE} if test $OS_VERSION = rawhide; then sed -i /etc/mock/${OS_MOCK}-${OS_VERSION}-${OS_ARCH}.cfg -e s/gpgcheck.*/gpgcheck=0/g; fi && rpm -ql mock|grep "/mounts.py\$"|xargs -n1 sed -e "/USE_NSPAWN/d" -e "/self.mountall_essential/d" -i && mock --no-clean -r ${OS_MOCK}-${OS_VERSION}-${OS_ARCH} --resultdir=/rpms ${MOCK_OPTS} --disable-plugin=root_cache --disable-plugin=tmpfs --disable-plugin=yum_cache --disable-plugin=selinux --no-bootstrap-chroot --old-chroot /rpms/sbd*.src.rpm" + - ls ${PWD}/${PACKAGE}*.${OS_ARCH}.rpm && BUILD_SUCCESS=true + - ${BUILD_SUCCESS} && docker pull ${OS_TYPE}${OS_DIST}${OS_VERSION} + - ${BUILD_SUCCESS} && docker run ${DOCKER_OPTS} -v ${PWD}:/rpms ${OS_TYPE}${OS_DIST}${OS_VERSION} /bin/bash -c "if test $OS_VERSION = rawhide; then dnf update -y --nogpgcheck; fi && ${OS_INSTALL} device-mapper /rpms/${PACKAGE}*.${OS_ARCH}.rpm && ${TEST_ENV} /usr/share/sbd/regressions.sh && touch /rpms/regressions.sh.SUCCESS" - ls ${PWD}/regressions.sh.SUCCESS addons: apt: packages: - rpm + diff --git a/tests/regressions.sh b/tests/regressions.sh index b06166d..6cfb303 100755 --- a/tests/regressions.sh +++ b/tests/regressions.sh @@ -1,332 +1,332 @@ #!/bin/bash # # Copyright (C) 2013 Lars Marowsky-Bree # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # TODO: # - More tests # - Handle optional, long-running tests better # - Support for explicitly running a single test # - Verify output from commands # - Normalize uuids and device names so they are diffable # - Log to file, instead of syslog is needed # - How to test watch mode? # - Can the unit/service file be tested? or at least the wrapper? : ${SBD_BINARY:="/usr/sbin/sbd"} : ${SBD_PRELOAD="libsbdtestbed.so"} : ${SBD_USE_DM:="yes"} sbd() { LD_PRELOAD=${SBD_PRELOAD} SBD_WATCHDOG_TIMEOUT=5 SBD_DEVICE="${SBD_DEVICE}" SBD_PRELOAD_LOG=${SBD_PRELOAD_LOG} SBD_WATCHDOG_DEV=/dev/watchdog setsid ${SBD_BINARY} -p ${SBD_PIDFILE} $* } sbd_wipe_disk() { dd if=/dev/zero of=$1 count=2048 2>/dev/null } sbd_setup() { trap sbd_teardown EXIT for N in $(seq 3) ; do F[$N]=$(mktemp /tmp/sbd.device.$N.XXXXXX) sbd_wipe_disk ${F[$N]} if [[ "${SBD_USE_DM}" == "yes" ]]; then R[$N]=$(echo ${F[$N]}|cut -f4 -d.) L[$N]=$(losetup -f) losetup ${L[$N]} ${F[$N]} D[$N]="/dev/mapper/sbd_${N}_${R[$N]}" dmsetup create sbd_${N}_${R[$N]} --table "0 2048 linear ${L[$N]} 0" dmsetup mknodes sbd_${N}_${R[$N]} else D[$N]=${F[$N]} fi done if [[ "${SBD_USE_DM}" != "yes" ]]; then SBD_DEVICE="${F[1]};${F[2]};${F[3]}" fi SBD_PIDFILE=$(mktemp /tmp/sbd.pidfile.XXXXXX) SBD_PRELOAD_LOG=$(mktemp /tmp/sbd.logfile.XXXXXX) } sbd_teardown() { for N in $(seq 3) ; do if [[ "${SBD_USE_DM}" == "yes" ]]; then dmsetup remove sbd_${N}_${R[$N]} losetup -d ${L[$N]} fi rm -f ${F[$N]} sbd_daemon_cleanup rm -f ${SBD_PIDFILE} rm -f ${SBD_PRELOAD_LOG} done } sbd_dev_fail() { if [[ "${SBD_USE_DM}" == "yes" ]]; then dmsetup wipe_table sbd_${1}_${R[$1]} else D[$1]=/tmp/fail123456789 fi } sbd_dev_resume() { if [[ "${SBD_USE_DM}" == "yes" ]]; then dmsetup suspend sbd_${1}_${R[$1]} dmsetup load sbd_${1}_${R[$1]} --table "0 2048 linear ${L[$1]} 0" dmsetup resume sbd_${1}_${R[$1]} else D[$1]=${F[$1]} fi } sbd_daemon_cleanup() { echo > ${SBD_PRELOAD_LOG} pkill -TERM --pidfile ${SBD_PIDFILE} 2>/dev/null sleep 5 pkill -KILL --pidfile ${SBD_PIDFILE} 2>/dev/null pkill -KILL --parent $(cat ${SBD_PIDFILE} 2>/dev/null) 2>/dev/null echo > ${SBD_PIDFILE} } _ok() { echo -- $@ $@ rc=$? if [ $rc -ne 0 ]; then echo "$@ failed with $rc" exit $rc fi } _no() { echo -- $@ $@ rc=$? if [ $rc -eq 0 ]; then echo "$@ did NOT fail ($rc)" exit $rc fi return 0 } _in_log() { grep "$@" ${SBD_PRELOAD_LOG} >/dev/null if [ $? -ne 0 ]; then echo "didn't find '$@' in log:" cat ${SBD_PRELOAD_LOG} sbd_daemon_cleanup exit 1 fi } test_1() { echo "Creating three devices" _ok sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} create _ok sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} dump } test_2() { echo "Basic functionality" for S in `seq 2` ; do _ok sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} allocate "test-$S" done _ok sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} -n test-1 message test-2 reset _ok sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} list } test_3() { echo "Start mode (expected not to start, because reset was written in test_2)" _no sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} -n test-2 -Z -Z -Z -S 1 watch } test_4() { echo "Deliver message with 1 failure" sbd_dev_fail 1 _no sbd -d ${D[1]} -n test-1 message test-2 exit _no sbd -d ${D[1]} -d ${D[2]} -n test-1 message test-2 exit _ok sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} -n test-1 message test-2 exit sbd_dev_resume 1 } test_5() { echo "Deliver message with 2 failures" sbd_dev_fail 1 sbd_dev_fail 2 _no sbd -d ${D[1]} -d ${D[2]} -n test-1 message test-2 exit _no sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} -n test-1 message test-2 exit sbd_dev_resume 1 sbd_dev_resume 2 } test_6() { echo "Deliver message with 3 failures" sbd_dev_fail 1 sbd_dev_fail 2 sbd_dev_fail 3 _no sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} -n test-1 message test-2 exit sbd_dev_resume 1 sbd_dev_resume 2 sbd_dev_resume 3 } test_101() { echo "Creating one device" _ok sbd -d ${D[1]} create } test_102() { echo "Creating two devices" _ok sbd -d ${D[1]} -d ${D[2]} create } test_7() { echo "Allocate all slots plus 1" _ok sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} -2 0 create for S in `seq 255` ; do _ok sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} allocate "test-$S" done _no sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} allocate "test-256" } test_8() { echo "Non-existent device path" _no sbd -d /dev/kfdifdifdfdlfd -create 2>/dev/null } test_9() { echo "Basic sbd invocation" _no sbd _ok sbd -h } test_watchdog() { echo "Basic watchdog test" echo > ${SBD_PRELOAD_LOG} sbd test-watchdog < /dev/null _in_log "watchdog fired" } test_stall_inquisitor() { echo "Stall inquisitor test" sbd_daemon_cleanup sbd -d ${D[1]} -d ${D[2]} -d ${D[3]} -n test-1 watch sleep 10 _ok kill -0 $(cat ${SBD_PIDFILE}) kill -STOP $(cat ${SBD_PIDFILE}) sleep 10 kill -CONT $(cat ${SBD_PIDFILE}) 2>/dev/null _in_log "watchdog fired" } test_wipe_slots1() { echo "Wipe slots test (with watchdog)" sbd_daemon_cleanup sbd -d ${D[1]} -n test-1 watch sleep 2 sbd_wipe_disk ${D[1]} sleep 15 _in_log "watchdog fired" } test_wipe_slots2() { echo "Wipe slots test (without watchdog)" sbd_daemon_cleanup sbd -d ${D[1]} create sbd -d ${D[1]} -w /dev/null -n test-1 watch sleep 2 sbd_wipe_disk ${D[1]} sleep 15 _in_log "sysrq-trigger ('b')" _in_log "reboot (reboot)" } test_message1() { echo "Message test (reset)" sbd_daemon_cleanup sbd -d ${D[1]} create sbd -d ${D[1]} -w /dev/null -n test-1 watch sleep 2 sbd -d ${D[1]} message test-1 reset sleep 2 _in_log "sysrq-trigger ('b')" _in_log "reboot (reboot)" } test_message2() { echo "Message test (off)" sbd_daemon_cleanup sbd -d ${D[1]} create sbd -d ${D[1]} -w /dev/null -n test-1 watch sleep 2 sbd -d ${D[1]} message test-1 off sleep 2 _in_log "sysrq-trigger ('o')" _in_log "reboot (poweroff)" } test_message3() { echo "Message test (crashdump)" sbd_daemon_cleanup sbd -d ${D[1]} create sbd -d ${D[1]} -w /dev/null -n test-1 watch sleep 2 sbd -d ${D[1]} message test-1 crashdump sleep 2 _in_log "sysrq-trigger ('c')" } test_timeout_action1() { echo "Timeout action test (off)" sbd_daemon_cleanup sbd -d ${D[1]} create SBD_TIMEOUT_ACTION=off sbd -d ${D[1]} -w /dev/null -n test-1 watch sleep 2 sbd_wipe_disk ${D[1]} - sleep 10 + sleep 15 _in_log "sysrq-trigger ('o')" _in_log "reboot (poweroff)" } test_timeout_action2() { echo "Timeout action test (crashdump)" sbd_daemon_cleanup sbd -d ${D[1]} create SBD_TIMEOUT_ACTION=crashdump sbd -d ${D[1]} -w /dev/null -n test-1 watch sleep 2 sbd_wipe_disk ${D[1]} - sleep 10 + sleep 15 _in_log "sysrq-trigger ('c')" } sbd_setup if [[ "${SBD_PRELOAD}" != "" ]]; then SBD_DAEMON_TESTS="watchdog stall_inquisitor wipe_slots1 wipe_slots2 message1 message2 message3 timeout_action1 timeout_action2" fi for T in $(seq 9) ${SBD_DAEMON_TESTS}; do if ! test_$T ; then echo "FAILURE: Test $T" break fi echo "SUCCESS: Test $T" done echo "SUCCESS: All tests completed"