ZTS: Use QEMU for tests on Linux and FreeBSD
This commit adds functional tests for these systems: - AlmaLinux 8, AlmaLinux 9, ArchLinux - CentOS Stream 9, Fedora 39, Fedora 40 - Debian 11, Debian 12 - FreeBSD 13, FreeBSD 14, FreeBSD 15 - Ubuntu 20.04, Ubuntu 22.04, Ubuntu 24.04 - enabled by default: - AlmaLinux 8, AlmaLinux 9 - Fedora 39, Fedora 40 - FreeBSD 13, FreeBSD 14, FreeBSD 15 Workflow for each operating system: - install qemu on the github runner - download current cloud image of operating system - start and init that image via cloud-init - install dependencies and poweroff system - start system and build openzfs and then poweroff again - clone build system and start 3 instances of it - the functional testings complete within times < 3h Signed-off-by: Tino Reichardt <milky-zfs@mcmilk.de> Signed-off-by: Tony Hutter <hutter2@llnl.gov>
This commit is contained in:
parent
bf132dbdb3
commit
e50b34f940
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
Workflow for each operating system:
|
||||||
|
- install qemu on the github runner
|
||||||
|
- download current cloud image of operating system
|
||||||
|
- start and init that image via cloud-init
|
||||||
|
- install dependencies and poweroff system
|
||||||
|
- start system and build openzfs and then poweroff again
|
||||||
|
- clone build system and start 3 instances of it
|
||||||
|
- the functional testings complete within times < 3h
|
|
@ -0,0 +1,109 @@
|
||||||
|
#!/bin/awk -f
|
||||||
|
#
|
||||||
|
# Merge multiple ZTS tests results summaries into a single summary. This is
|
||||||
|
# needed when you're running different parts of ZTS on different tests
|
||||||
|
# runners or VMs.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# ./merge_summary.awk summary1.txt [summary2.txt] [summary3.txt] ...
|
||||||
|
#
|
||||||
|
# or:
|
||||||
|
#
|
||||||
|
# cat summary*.txt | ./merge_summary.awk
|
||||||
|
#
|
||||||
|
BEGIN {
|
||||||
|
i=-1
|
||||||
|
pass=0
|
||||||
|
fail=0
|
||||||
|
skip=0
|
||||||
|
state=""
|
||||||
|
cl=0
|
||||||
|
el=0
|
||||||
|
upl=0
|
||||||
|
ul=0
|
||||||
|
|
||||||
|
# Total seconds of tests runtime
|
||||||
|
total=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Skip empty lines
|
||||||
|
/^\s*$/{next}
|
||||||
|
|
||||||
|
# Skip Configuration and Test lines
|
||||||
|
/^Test:/{state=""; next}
|
||||||
|
/Configuration/{state="";next}
|
||||||
|
|
||||||
|
# When we see "test-runner.py" stop saving config lines, and
|
||||||
|
# save test runner lines
|
||||||
|
/test-runner.py/{state="testrunner"; runner=runner$0"\n"; next}
|
||||||
|
|
||||||
|
# We need to differentiate the PASS counts from test result lines that start
|
||||||
|
# with PASS, like:
|
||||||
|
#
|
||||||
|
# PASS mv_files/setup
|
||||||
|
#
|
||||||
|
# Use state="pass_count" to differentiate
|
||||||
|
#
|
||||||
|
/Results Summary/{state="pass_count"; next}
|
||||||
|
/PASS/{ if (state=="pass_count") {pass += $2}}
|
||||||
|
/FAIL/{ if (state=="pass_count") {fail += $2}}
|
||||||
|
/SKIP/{ if (state=="pass_count") {skip += $2}}
|
||||||
|
/Running Time/{
|
||||||
|
state="";
|
||||||
|
running[i]=$3;
|
||||||
|
split($3, arr, ":")
|
||||||
|
total += arr[1] * 60 * 60;
|
||||||
|
total += arr[2] * 60;
|
||||||
|
total += arr[3]
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/Tests with results other than PASS that are expected/{state="expected_lines"; next}
|
||||||
|
/Tests with result of PASS that are unexpected/{state="unexpected_pass_lines"; next}
|
||||||
|
/Tests with results other than PASS that are unexpected/{state="unexpected_lines"; next}
|
||||||
|
{
|
||||||
|
if (state == "expected_lines") {
|
||||||
|
expected_lines[el] = $0
|
||||||
|
el++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == "unexpected_pass_lines") {
|
||||||
|
unexpected_pass_lines[upl] = $0
|
||||||
|
upl++
|
||||||
|
}
|
||||||
|
if (state == "unexpected_lines") {
|
||||||
|
unexpected_lines[ul] = $0
|
||||||
|
ul++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reproduce summary
|
||||||
|
END {
|
||||||
|
print runner;
|
||||||
|
print "\nResults Summary"
|
||||||
|
print "PASS\t"pass
|
||||||
|
print "FAIL\t"fail
|
||||||
|
print "SKIP\t"skip
|
||||||
|
print ""
|
||||||
|
print "Running Time:\t"strftime("%T", total, 1)
|
||||||
|
if (pass+fail+skip > 0) {
|
||||||
|
percent_passed=(pass/(pass+fail+skip) * 100)
|
||||||
|
}
|
||||||
|
printf "Percent passed:\t%3.2f%", percent_passed
|
||||||
|
|
||||||
|
print "\n\nTests with results other than PASS that are expected:"
|
||||||
|
asort(expected_lines, sorted)
|
||||||
|
for (j in sorted)
|
||||||
|
print sorted[j]
|
||||||
|
|
||||||
|
print "\n\nTests with result of PASS that are unexpected:"
|
||||||
|
asort(unexpected_pass_lines, sorted)
|
||||||
|
for (j in sorted)
|
||||||
|
print sorted[j]
|
||||||
|
|
||||||
|
print "\n\nTests with results other than PASS that are unexpected:"
|
||||||
|
asort(unexpected_lines, sorted)
|
||||||
|
for (j in sorted)
|
||||||
|
print sorted[j]
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 1) setup qemu instance on action runner
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# install needed packages
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install axel cloud-image-utils daemonize guestfs-tools \
|
||||||
|
ksmtuned virt-manager linux-modules-extra-`uname -r`
|
||||||
|
|
||||||
|
# generate ssh keys
|
||||||
|
rm -f ~/.ssh/id_ed25519
|
||||||
|
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -q -N ""
|
||||||
|
|
||||||
|
# no need for some scheduler
|
||||||
|
for i in /sys/block/s*/queue/scheduler; do
|
||||||
|
echo "none" | sudo tee $i > /dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
# this one is fast and mostly free
|
||||||
|
sudo mount -o remount,rw,noatime,barrier=0 /mnt
|
||||||
|
|
||||||
|
# we expect RAM shortage
|
||||||
|
cat << EOF | sudo tee /etc/ksmtuned.conf > /dev/null
|
||||||
|
KSM_MONITOR_INTERVAL=60
|
||||||
|
|
||||||
|
# Millisecond sleep between ksm scans for 16Gb server.
|
||||||
|
# Smaller servers sleep more, bigger sleep less.
|
||||||
|
KSM_SLEEP_MSEC=10
|
||||||
|
KSM_NPAGES_BOOST=300
|
||||||
|
KSM_NPAGES_DECAY=-50
|
||||||
|
KSM_NPAGES_MIN=64
|
||||||
|
KSM_NPAGES_MAX=2048
|
||||||
|
|
||||||
|
KSM_THRES_COEF=20
|
||||||
|
KSM_THRES_CONST=2048
|
||||||
|
|
||||||
|
LOGFILE=/var/log/ksmtuned.log
|
||||||
|
DEBUG=1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo systemctl restart ksm
|
||||||
|
sudo systemctl restart ksmtuned
|
|
@ -0,0 +1,200 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 2) start qemu with some operating system, init via cloud-init
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# short name used in zfs-qemu.yml
|
||||||
|
OS="$1"
|
||||||
|
|
||||||
|
# OS variant (virt-install --os-variant list)
|
||||||
|
OSv=$OS
|
||||||
|
|
||||||
|
# compressed with .zst extension
|
||||||
|
FREEBSD="https://github.com/mcmilk/openzfs-freebsd-images/releases/download/v2024-08-10"
|
||||||
|
URLzs=""
|
||||||
|
|
||||||
|
# Ubuntu mirrors
|
||||||
|
#UBMIRROR="https://cloud-images.ubuntu.com"
|
||||||
|
#UBMIRROR="https://mirrors.cloud.tencent.com/ubuntu-cloud-images"
|
||||||
|
UBMIRROR="https://mirror.citrahost.com/ubuntu-cloud-images"
|
||||||
|
|
||||||
|
case "$OS" in
|
||||||
|
almalinux8)
|
||||||
|
OSNAME="AlmaLinux 8"
|
||||||
|
URL="https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-latest.x86_64.qcow2"
|
||||||
|
;;
|
||||||
|
almalinux9)
|
||||||
|
OSNAME="AlmaLinux 9"
|
||||||
|
URL="https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2"
|
||||||
|
;;
|
||||||
|
archlinux)
|
||||||
|
OSNAME="Archlinux"
|
||||||
|
URL="https://geo.mirror.pkgbuild.com/images/latest/Arch-Linux-x86_64-cloudimg.qcow2"
|
||||||
|
;;
|
||||||
|
centos-stream9)
|
||||||
|
OSNAME="CentOS Stream 9"
|
||||||
|
URL="https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-9-latest.x86_64.qcow2"
|
||||||
|
;;
|
||||||
|
debian11)
|
||||||
|
OSNAME="Debian 11"
|
||||||
|
URL="https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.qcow2"
|
||||||
|
;;
|
||||||
|
debian12)
|
||||||
|
OSNAME="Debian 12"
|
||||||
|
URL="https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2"
|
||||||
|
;;
|
||||||
|
fedora39)
|
||||||
|
OSNAME="Fedora 39"
|
||||||
|
OSv="fedora39"
|
||||||
|
URL="https://download.fedoraproject.org/pub/fedora/linux/releases/39/Cloud/x86_64/images/Fedora-Cloud-Base-39-1.5.x86_64.qcow2"
|
||||||
|
;;
|
||||||
|
fedora40)
|
||||||
|
OSNAME="Fedora 40"
|
||||||
|
OSv="fedora39"
|
||||||
|
URL="https://download.fedoraproject.org/pub/fedora/linux/releases/40/Cloud/x86_64/images/Fedora-Cloud-Base-Generic.x86_64-40-1.14.qcow2"
|
||||||
|
;;
|
||||||
|
freebsd13r)
|
||||||
|
OSNAME="FreeBSD 13.3-RELEASE"
|
||||||
|
OSv="freebsd13.0"
|
||||||
|
URLzs="$FREEBSD/amd64-freebsd-13.3-RELEASE.qcow2.zst"
|
||||||
|
BASH="/usr/local/bin/bash"
|
||||||
|
;;
|
||||||
|
freebsd13)
|
||||||
|
OSNAME="FreeBSD 13.4-STABLE"
|
||||||
|
OSv="freebsd13.0"
|
||||||
|
URLzs="$FREEBSD/amd64-freebsd-13.4-STABLE.qcow2.zst"
|
||||||
|
BASH="/usr/local/bin/bash"
|
||||||
|
;;
|
||||||
|
freebsd14r)
|
||||||
|
OSNAME="FreeBSD 14.1-RELEASE"
|
||||||
|
OSv="freebsd14.0"
|
||||||
|
URLzs="$FREEBSD/amd64-freebsd-14.1-RELEASE.qcow2.zst"
|
||||||
|
BASH="/usr/local/bin/bash"
|
||||||
|
;;
|
||||||
|
freebsd14)
|
||||||
|
OSNAME="FreeBSD 14.1-STABLE"
|
||||||
|
OSv="freebsd14.0"
|
||||||
|
URLzs="$FREEBSD/amd64-freebsd-14.1-STABLE.qcow2.zst"
|
||||||
|
BASH="/usr/local/bin/bash"
|
||||||
|
;;
|
||||||
|
freebsd15)
|
||||||
|
OSNAME="FreeBSD 15.0-CURRENT"
|
||||||
|
OSv="freebsd14.0"
|
||||||
|
URLzs="$FREEBSD/amd64-freebsd-15.0-CURRENT.qcow2.zst"
|
||||||
|
BASH="/usr/local/bin/bash"
|
||||||
|
;;
|
||||||
|
tumbleweed)
|
||||||
|
OSNAME="openSUSE Tumbleweed"
|
||||||
|
OSv="opensusetumbleweed"
|
||||||
|
MIRROR="http://opensuse-mirror-gce-us.susecloud.net"
|
||||||
|
URL="$MIRROR/tumbleweed/appliances/openSUSE-MicroOS.x86_64-OpenStack-Cloud.qcow2"
|
||||||
|
;;
|
||||||
|
ubuntu20)
|
||||||
|
OSNAME="Ubuntu 20.04"
|
||||||
|
OSv="ubuntu20.04"
|
||||||
|
URL="$UBMIRROR/focal/current/focal-server-cloudimg-amd64.img"
|
||||||
|
;;
|
||||||
|
ubuntu22)
|
||||||
|
OSNAME="Ubuntu 22.04"
|
||||||
|
OSv="ubuntu22.04"
|
||||||
|
URL="$UBMIRROR/jammy/current/jammy-server-cloudimg-amd64.img"
|
||||||
|
;;
|
||||||
|
ubuntu24)
|
||||||
|
OSNAME="Ubuntu 24.04"
|
||||||
|
OSv="ubuntu24.04"
|
||||||
|
URL="$UBMIRROR/noble/current/noble-server-cloudimg-amd64.img"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Wrong value for OS variable!"
|
||||||
|
exit 111
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# freebsd15 -> used in zfs-qemu.yml
|
||||||
|
echo "$OS" > /var/tmp/os.txt
|
||||||
|
|
||||||
|
# freebsd14.0 -> used for virt-install
|
||||||
|
echo "$OSv" > /var/tmp/osvariant.txt
|
||||||
|
|
||||||
|
# FreeBSD 15 (Current) -> used for summary
|
||||||
|
echo "$OSNAME" > /var/tmp/osname.txt
|
||||||
|
|
||||||
|
IMG="/mnt/tests/cloudimg.qcow2"
|
||||||
|
DISK="/mnt/tests/openzfs.qcow2"
|
||||||
|
sudo mkdir -p "/mnt/tests"
|
||||||
|
sudo chown $(whoami) /mnt/tests
|
||||||
|
|
||||||
|
# we are downloading via axel, curl and wget are mostly slower and
|
||||||
|
# require more return value checking
|
||||||
|
if [ ! -z "$URLzs" ]; then
|
||||||
|
echo "Loading image $URLzs ..."
|
||||||
|
time axel -q -o "$IMG.zst" "$URLzs"
|
||||||
|
zstd -q -d --rm "$IMG.zst"
|
||||||
|
else
|
||||||
|
echo "Loading image $URL ..."
|
||||||
|
time axel -q -o "$IMG" "$URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 256k cluster seems the best in terms of speed for now
|
||||||
|
qemu-img convert -q -f qcow2 -O qcow2 -c \
|
||||||
|
-o compression_type=zstd,cluster_size=256k $IMG $DISK
|
||||||
|
rm -f $IMG
|
||||||
|
|
||||||
|
echo "Resizing image to 60GiB ..."
|
||||||
|
qemu-img resize -q $DISK 60G
|
||||||
|
|
||||||
|
PUBKEY=`cat ~/.ssh/id_ed25519.pub`
|
||||||
|
cat <<EOF > /tmp/user-data
|
||||||
|
#cloud-config
|
||||||
|
|
||||||
|
fqdn: $OS
|
||||||
|
|
||||||
|
# user:zfs password:1
|
||||||
|
users:
|
||||||
|
- name: root
|
||||||
|
shell: $BASH
|
||||||
|
- name: zfs
|
||||||
|
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||||
|
shell: $BASH
|
||||||
|
lock-passwd: false
|
||||||
|
passwd: \$1\$EjKAQetN\$O7Tw/rZOHaeBP1AiCliUg/
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- $PUBKEY
|
||||||
|
|
||||||
|
growpart:
|
||||||
|
mode: auto
|
||||||
|
devices: ['/']
|
||||||
|
ignore_growroot_disabled: false
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo virsh net-update default add ip-dhcp-host \
|
||||||
|
"<host mac='52:54:00:83:79:00' ip='192.168.122.10'/>" --live --config
|
||||||
|
|
||||||
|
# 12GiB RAM for building the module, TY Github :)
|
||||||
|
sudo virt-install \
|
||||||
|
--os-variant $OSv \
|
||||||
|
--name "openzfs" \
|
||||||
|
--cpu host-passthrough \
|
||||||
|
--virt-type=kvm --hvm \
|
||||||
|
--vcpus=4,sockets=1 \
|
||||||
|
--memory $((1024*12)) \
|
||||||
|
--memballoon model=virtio \
|
||||||
|
--graphics none \
|
||||||
|
--network bridge=virbr0,model=e1000,mac='52:54:00:83:79:00' \
|
||||||
|
--cloud-init user-data=/tmp/user-data \
|
||||||
|
--disk $DISK,bus=virtio,cache=none,format=qcow2,driver.discard=unmap \
|
||||||
|
--import --noautoconsole >/dev/null
|
||||||
|
|
||||||
|
# in case the directory isn't there already
|
||||||
|
mkdir -p $HOME/.ssh
|
||||||
|
|
||||||
|
cat <<EOF >> $HOME/.ssh/config
|
||||||
|
# no questions please
|
||||||
|
StrictHostKeyChecking no
|
||||||
|
|
||||||
|
# small timeout, used in while loops later
|
||||||
|
ConnectTimeout 1
|
||||||
|
EOF
|
|
@ -0,0 +1,199 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 3) install dependencies for compiling and loading
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
function archlinux() {
|
||||||
|
echo "##[group]Running pacman -Syu"
|
||||||
|
sudo pacman -Syu --noconfirm
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Install Development Tools"
|
||||||
|
sudo pacman -Sy --noconfirm base-devel bc cpio dhclient dkms fakeroot \
|
||||||
|
fio gdb inetutils jq less linux linux-headers lsscsi nfs-utils parted \
|
||||||
|
pax perf python-packaging python-setuptools qemu-guest-agent ksh samba \
|
||||||
|
sysstat rng-tools rsync wget
|
||||||
|
echo "##[endgroup]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function debian() {
|
||||||
|
export DEBIAN_FRONTEND="noninteractive"
|
||||||
|
|
||||||
|
echo "##[group]Running apt-get update+upgrade"
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get upgrade -y
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Install Development Tools"
|
||||||
|
sudo apt-get install -y \
|
||||||
|
acl alien attr autoconf bc cpio curl dbench dh-python \
|
||||||
|
dkms fakeroot fio gdb gdebi git ksh lcov isc-dhcp-client jq \
|
||||||
|
libacl1-dev libaio-dev libattr1-dev libblkid-dev \
|
||||||
|
libcurl4-openssl-dev libdevmapper-dev libelf-dev libffi-dev \
|
||||||
|
libmount-dev libpam0g-dev libselinux-dev libssl-dev libtool \
|
||||||
|
libtool-bin libudev-dev linux-headers-$(uname -r) lsscsi \
|
||||||
|
nfs-kernel-server pamtester parted python3 python3-all-dev \
|
||||||
|
python3-cffi python3-dev python3-distlib python3-packaging \
|
||||||
|
python3-setuptools python3-sphinx qemu-guest-agent rng-tools \
|
||||||
|
rpm2cpio rsync samba sysstat uuid-dev watchdog wget xfslibs-dev \
|
||||||
|
zlib1g-dev
|
||||||
|
echo "##[endgroup]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function freebsd() {
|
||||||
|
export ASSUME_ALWAYS_YES="YES"
|
||||||
|
|
||||||
|
echo "##[group]Install Development Tools"
|
||||||
|
sudo pkg install -y autoconf automake autotools base64 checkbashisms fio \
|
||||||
|
gdb gettext gettext-runtime git gmake gsed jq ksh93 lcov libtool lscpu \
|
||||||
|
pkgconf python python3 pamtester pamtester qemu-guest-agent rsync
|
||||||
|
sudo pkg install -xy \
|
||||||
|
'^samba4[[:digit:]]+$' \
|
||||||
|
'^py3[[:digit:]]+-cffi$' \
|
||||||
|
'^py3[[:digit:]]+-sysctl$' \
|
||||||
|
'^py3[[:digit:]]+-packaging$'
|
||||||
|
echo "##[endgroup]"
|
||||||
|
}
|
||||||
|
|
||||||
|
# common packages for: almalinux, centos, redhat
|
||||||
|
function rhel() {
|
||||||
|
echo "##[group]Running dnf update"
|
||||||
|
echo "max_parallel_downloads=10" | sudo -E tee -a /etc/dnf/dnf.conf
|
||||||
|
sudo dnf clean all
|
||||||
|
sudo dnf update -y --setopt=fastestmirror=1 --refresh
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Install Development Tools"
|
||||||
|
sudo dnf group install -y "Development Tools"
|
||||||
|
sudo dnf install -y \
|
||||||
|
acl attr bc bzip2 curl dbench dkms elfutils-libelf-devel fio gdb git \
|
||||||
|
jq kernel-rpm-macros ksh libacl-devel libaio-devel libargon2-devel \
|
||||||
|
libattr-devel libblkid-devel libcurl-devel libffi-devel ncompress \
|
||||||
|
libselinux-devel libtirpc-devel libtool libudev-devel libuuid-devel \
|
||||||
|
lsscsi mdadm nfs-utils openssl-devel pam-devel pamtester parted perf \
|
||||||
|
python3 python3-cffi python3-devel python3-packaging kernel-devel \
|
||||||
|
python3-setuptools qemu-guest-agent rng-tools rpcgen rpm-build rsync \
|
||||||
|
samba sysstat systemd watchdog wget xfsprogs-devel zlib-devel
|
||||||
|
echo "##[endgroup]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function tumbleweed() {
|
||||||
|
echo "##[group]Running zypper is TODO!"
|
||||||
|
sleep 23456
|
||||||
|
echo "##[endgroup]"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
case "$1" in
|
||||||
|
almalinux8)
|
||||||
|
echo "##[group]Enable epel and powertools repositories"
|
||||||
|
sudo dnf config-manager -y --set-enabled powertools
|
||||||
|
sudo dnf install -y epel-release
|
||||||
|
echo "##[endgroup]"
|
||||||
|
rhel
|
||||||
|
echo "##[group]Install kernel-abi-whitelists"
|
||||||
|
sudo dnf install -y kernel-abi-whitelists
|
||||||
|
echo "##[endgroup]"
|
||||||
|
;;
|
||||||
|
almalinux9|centos-stream9)
|
||||||
|
echo "##[group]Enable epel and crb repositories"
|
||||||
|
sudo dnf config-manager -y --set-enabled crb
|
||||||
|
sudo dnf install -y epel-release
|
||||||
|
echo "##[endgroup]"
|
||||||
|
rhel
|
||||||
|
echo "##[group]Install kernel-abi-stablelists"
|
||||||
|
sudo dnf install -y kernel-abi-stablelists
|
||||||
|
echo "##[endgroup]"
|
||||||
|
;;
|
||||||
|
archlinux)
|
||||||
|
archlinux
|
||||||
|
;;
|
||||||
|
debian*)
|
||||||
|
debian
|
||||||
|
echo "##[group]Install Debian specific"
|
||||||
|
sudo apt-get install -yq linux-perf dh-sequence-dkms
|
||||||
|
echo "##[endgroup]"
|
||||||
|
;;
|
||||||
|
fedora*)
|
||||||
|
rhel
|
||||||
|
;;
|
||||||
|
freebsd*)
|
||||||
|
freebsd
|
||||||
|
;;
|
||||||
|
tumbleweed)
|
||||||
|
tumbleweed
|
||||||
|
;;
|
||||||
|
ubuntu*)
|
||||||
|
debian
|
||||||
|
echo "##[group]Install Ubuntu specific"
|
||||||
|
sudo apt-get install -yq linux-tools-common libtirpc-dev \
|
||||||
|
linux-modules-extra-$(uname -r)
|
||||||
|
if [ "$1" != "ubuntu20" ]; then
|
||||||
|
sudo apt-get install -yq dh-sequence-dkms
|
||||||
|
fi
|
||||||
|
echo "##[endgroup]"
|
||||||
|
echo "##[group]Delete Ubuntu OpenZFS modules"
|
||||||
|
for i in `find /lib/modules -name zfs -type d`; do sudo rm -rvf $i; done
|
||||||
|
echo "##[endgroup]"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Start services
|
||||||
|
echo "##[group]Enable services"
|
||||||
|
case "$1" in
|
||||||
|
freebsd*)
|
||||||
|
# add virtio things
|
||||||
|
echo 'virtio_load="YES"' | sudo -E tee -a /boot/loader.conf
|
||||||
|
for i in balloon blk console random scsi; do
|
||||||
|
echo "virtio_${i}_load=\"YES\"" | sudo -E tee -a /boot/loader.conf
|
||||||
|
done
|
||||||
|
echo "fdescfs /dev/fd fdescfs rw 0 0" | sudo -E tee -a /etc/fstab
|
||||||
|
sudo -E mount /dev/fd
|
||||||
|
sudo -E touch /etc/zfs/exports
|
||||||
|
sudo -E sysrc mountd_flags="/etc/zfs/exports"
|
||||||
|
echo '[global]' | sudo -E tee /usr/local/etc/smb4.conf >/dev/null
|
||||||
|
sudo -E service nfsd enable
|
||||||
|
sudo -E service qemu-guest-agent enable
|
||||||
|
sudo -E service samba_server enable
|
||||||
|
;;
|
||||||
|
debian*|ubuntu*)
|
||||||
|
sudo -E systemctl enable nfs-kernel-server
|
||||||
|
sudo -E systemctl enable qemu-guest-agent
|
||||||
|
sudo -E systemctl enable smbd
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# All other linux distros
|
||||||
|
sudo -E systemctl enable nfs-server
|
||||||
|
sudo -E systemctl enable qemu-guest-agent
|
||||||
|
sudo -E systemctl enable smb
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
# Enable serial console and remove 'quiet' from linux kernel cmdline
|
||||||
|
case "$1" in
|
||||||
|
freebsd*)
|
||||||
|
# console is turned on @ FreeBSD images from here:
|
||||||
|
# https://github.com/mcmilk/zfs/tree/master
|
||||||
|
true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# should fit for most distros, may be optimized a bit later
|
||||||
|
echo "##[group]Enable serial output"
|
||||||
|
sudo sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="console=ttyS0,115200n8 random.trust_cpu=on/g; s/quiet //g' /etc/default/grub || true
|
||||||
|
for i in /boot/grub/grub.cfg /etc/grub2.cfg /etc/grub2-efi.cfg /boot/grub2/grub.cfg ; do
|
||||||
|
test -e $i || continue
|
||||||
|
echo sudo grub-mkconfig -o $i
|
||||||
|
sudo grub-mkconfig -o $i
|
||||||
|
done
|
||||||
|
echo "##[endgroup]"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# reset cloud-init configuration and poweroff
|
||||||
|
sudo cloud-init clean --logs
|
||||||
|
sleep 2 && sudo poweroff &
|
||||||
|
exit 0
|
|
@ -0,0 +1,148 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 4) configure and build openzfs modules
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
LOG="/var/tmp/build-stderr.txt"
|
||||||
|
echo "**************************************************"
|
||||||
|
echo "`date` ($*)"
|
||||||
|
echo "**************************************************"
|
||||||
|
(stdbuf -eL -oL $@ || echo $? > /tmp/rv) 3>&1 1>&2 2>&3 | tee -a $LOG
|
||||||
|
if [ -f /tmp/rv ]; then
|
||||||
|
RV=`cat /tmp/rv`
|
||||||
|
echo "**************************************************"
|
||||||
|
echo "exit with value=$RV ($*)"
|
||||||
|
echo "**************************************************"
|
||||||
|
exit $RV
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function freebsd() {
|
||||||
|
export MAKE="gmake"
|
||||||
|
echo "##[group]Autogen.sh"
|
||||||
|
run ./autogen.sh
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Configure"
|
||||||
|
run ./configure \
|
||||||
|
--prefix=/usr/local \
|
||||||
|
--with-libintl-prefix=/usr/local \
|
||||||
|
--enable-pyzfs \
|
||||||
|
--enable-debug \
|
||||||
|
--enable-debuginfo
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Build"
|
||||||
|
run gmake -j`sysctl -n hw.ncpu`
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Install"
|
||||||
|
run sudo gmake install
|
||||||
|
echo "##[endgroup]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function linux() {
|
||||||
|
echo "##[group]Autogen.sh"
|
||||||
|
run ./autogen.sh
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Configure"
|
||||||
|
run ./configure \
|
||||||
|
--prefix=/usr \
|
||||||
|
--enable-pyzfs \
|
||||||
|
--enable-debug \
|
||||||
|
--enable-debuginfo
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Build"
|
||||||
|
run make -j$(nproc)
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Install"
|
||||||
|
run sudo make install
|
||||||
|
echo "##[endgroup]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function rpm_build_and_install() {
|
||||||
|
EXTRA_CONFIG="${1:-}"
|
||||||
|
echo "##[group]Autogen.sh"
|
||||||
|
run ./autogen.sh
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Configure"
|
||||||
|
run ./configure --enable-debug --enable-debuginfo $EXTRA_CONFIG
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Build"
|
||||||
|
run make pkg-kmod pkg-utils
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Install"
|
||||||
|
run sudo yum -y --skip-broken localinstall $(ls *.rpm | grep -v src.rpm)
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function deb_build_and_install() {
|
||||||
|
echo "##[group]Autogen.sh"
|
||||||
|
run ./autogen.sh
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Configure"
|
||||||
|
run ./configure \
|
||||||
|
--prefix=/usr \
|
||||||
|
--enable-pyzfs \
|
||||||
|
--enable-debug \
|
||||||
|
--enable-debuginfo
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Build"
|
||||||
|
run make native-deb-kmod native-deb-utils
|
||||||
|
echo "##[endgroup]"
|
||||||
|
|
||||||
|
echo "##[group]Install"
|
||||||
|
# Do kmod install. Note that when you build the native debs, the
|
||||||
|
# packages themselves are placed in parent directory '../' rather than
|
||||||
|
# in the source directory like the rpms are.
|
||||||
|
run sudo apt-get -y install `find ../ | grep -E '\.deb$' | grep -Ev 'dkms|dracut'`
|
||||||
|
echo "##[endgroup]"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Debug: show kernel cmdline
|
||||||
|
if [ -e /proc/cmdline ] ; then
|
||||||
|
cat /proc/cmdline || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $HOME/zfs
|
||||||
|
export PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin"
|
||||||
|
|
||||||
|
# build
|
||||||
|
case "$1" in
|
||||||
|
freebsd*)
|
||||||
|
freebsd
|
||||||
|
;;
|
||||||
|
alma*|centos*)
|
||||||
|
rpm_build_and_install "--with-spec=redhat"
|
||||||
|
;;
|
||||||
|
fedora*)
|
||||||
|
rpm_build_and_install
|
||||||
|
;;
|
||||||
|
debian*|ubuntu*)
|
||||||
|
deb_build_and_install
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
linux
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# save some sysinfo
|
||||||
|
uname -a > /var/tmp/uname.txt
|
||||||
|
|
||||||
|
# reset cloud-init configuration and poweroff
|
||||||
|
sudo cloud-init clean --logs
|
||||||
|
sleep 2 && sudo poweroff &
|
||||||
|
exit 0
|
|
@ -0,0 +1,130 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 5) start test machines and load openzfs module
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# wait for poweroff to succeed
|
||||||
|
PID=`pidof /usr/bin/qemu-system-x86_64`
|
||||||
|
tail --pid=$PID -f /dev/null
|
||||||
|
sudo virsh undefine openzfs
|
||||||
|
|
||||||
|
PUBKEY=`cat ~/.ssh/id_ed25519.pub`
|
||||||
|
OSv=`cat /var/tmp/osvariant.txt`
|
||||||
|
OS=`cat /var/tmp/os.txt`
|
||||||
|
|
||||||
|
# definition of ressources per operating system
|
||||||
|
case "$OS" in
|
||||||
|
freebsd*)
|
||||||
|
# 2x CPU=4 RAM=6 -> FreeBSD 13 (2h 10m)
|
||||||
|
# 2x CPU=4 RAM=6 -> FreeBSD 14 (2h 10m)
|
||||||
|
VMs=2
|
||||||
|
CPU=4
|
||||||
|
RAM=6
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# 2x CPU=4 RAM=7 -> Almalinux 8 (3h 12m)
|
||||||
|
# 2x CPU=4 RAM=7 -> CentOS 9 (3h 2m)
|
||||||
|
# 2x CPU=4 RAM=7 -> Debian 11 (3h 11m)
|
||||||
|
# 2x CPU=4 RAM=7 -> Ubuntu 20 (2h 49m)
|
||||||
|
# 2x CPU=4 RAM=7 -> Ubuntu 22 (3h 26m)
|
||||||
|
# 2x CPU=4 RAM=7 -> Ubuntu 24 (3h 10m)
|
||||||
|
# 2x CPU=4 RAM=7 -> Fedora40 (3h 33m)
|
||||||
|
VMs=2
|
||||||
|
CPU=4
|
||||||
|
RAM=7
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# this can be different for each distro
|
||||||
|
echo $VMs > /var/tmp/vms.txt
|
||||||
|
|
||||||
|
# setup the testing vm's
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
echo "Generating disk for vm$i..."
|
||||||
|
sudo qemu-img create -q -f qcow2 -F qcow2 \
|
||||||
|
-o compression_type=zstd,cluster_size=256k \
|
||||||
|
-b /mnt/tests/openzfs.qcow2 "/mnt/tests/vm$i.qcow2"
|
||||||
|
|
||||||
|
cat <<EOF > /tmp/user-data
|
||||||
|
#cloud-config
|
||||||
|
|
||||||
|
fqdn: vm$i
|
||||||
|
|
||||||
|
# user:zfs password:1
|
||||||
|
users:
|
||||||
|
- name: root
|
||||||
|
shell: $BASH
|
||||||
|
- name: zfs
|
||||||
|
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||||
|
shell: $BASH
|
||||||
|
lock-passwd: false
|
||||||
|
passwd: \$1\$EjKAQetN\$O7Tw/rZOHaeBP1AiCliUg/
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- $PUBKEY
|
||||||
|
|
||||||
|
growpart:
|
||||||
|
mode: auto
|
||||||
|
devices: ['/']
|
||||||
|
ignore_growroot_disabled: false
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo virsh net-update default add ip-dhcp-host \
|
||||||
|
"<host mac='52:54:00:83:79:0$i' ip='192.168.122.1$i'/>" --live --config
|
||||||
|
|
||||||
|
sudo virt-install \
|
||||||
|
--os-variant $OSv \
|
||||||
|
--name "vm$i" \
|
||||||
|
--cpu host-passthrough \
|
||||||
|
--virt-type=kvm --hvm \
|
||||||
|
--vcpus=$CPU,sockets=1 \
|
||||||
|
--memory $((1024*RAM)) \
|
||||||
|
--memballoon model=virtio \
|
||||||
|
--graphics none \
|
||||||
|
--cloud-init user-data=/tmp/user-data \
|
||||||
|
--network bridge=virbr0,model=e1000,mac="52:54:00:83:79:0$i" \
|
||||||
|
--disk /mnt/tests/vm$i.qcow2,bus=virtio,cache=none,format=qcow2,driver.discard=unmap \
|
||||||
|
--import --noautoconsole >/dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
# setup cron job on the host side
|
||||||
|
case "$OS" in
|
||||||
|
freebsd*)
|
||||||
|
true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Linux based systems, trim the qcow2 files
|
||||||
|
echo "exec 1>/dev/null 2>/dev/null" > cronjob.sh
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
echo "virsh domfstrim vm$i" >> cronjob.sh
|
||||||
|
done
|
||||||
|
echo "fstrim /mnt" >> cronjob.sh
|
||||||
|
sudo chmod +x cronjob.sh
|
||||||
|
sudo mv -f cronjob.sh /root/cronjob.sh
|
||||||
|
echo '*/20 * * * * /root/cronjob.sh' > crontab.txt
|
||||||
|
sudo crontab crontab.txt
|
||||||
|
rm crontab.txt
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# check if the machines are okay
|
||||||
|
echo "Waiting for vm's to come up... (${VMs}x CPU=$CPU RAM=$RAM)"
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
while true; do
|
||||||
|
ssh 2>/dev/null zfs@192.168.122.1$i "uname -a" && break
|
||||||
|
done
|
||||||
|
done
|
||||||
|
echo "All $VMs VMs are up now."
|
||||||
|
|
||||||
|
# Save the VM's serial output (ttyS0) to /var/tmp/console.txt
|
||||||
|
# - ttyS0 on the VM corresponds to a local /dev/pty/N entry
|
||||||
|
# - use 'virsh ttyconsole' to lookup the /dev/pty/N entry
|
||||||
|
RESPATH="/var/tmp/test_results"
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
mkdir -p $RESPATH/vm$i
|
||||||
|
read "pty" <<< $(sudo virsh ttyconsole vm$i)
|
||||||
|
sudo nohup bash -c "cat $pty > $RESPATH/vm$i/console.txt" &
|
||||||
|
done
|
||||||
|
echo "Console logging for ${VMs}x $OS started."
|
|
@ -0,0 +1,81 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 6) load openzfs module and run the tests
|
||||||
|
#
|
||||||
|
# called on runner: qemu-6-tests.sh (without extra args)
|
||||||
|
# called on qemu-vm: qemu-6-tests.sh $OS $2/$3
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# called directly on the runner
|
||||||
|
if [ -f /var/tmp/vms.txt ]; then
|
||||||
|
cd "/var/tmp"
|
||||||
|
|
||||||
|
OS=`cat os.txt`
|
||||||
|
VMs=`cat vms.txt`
|
||||||
|
SSH=`which ssh`
|
||||||
|
|
||||||
|
BASE="$HOME/work/zfs/zfs"
|
||||||
|
TESTS='$HOME/zfs/.github/workflows/scripts/qemu-6-tests.sh'
|
||||||
|
COLOR="$BASE/scripts/zfs-tests-color.sh"
|
||||||
|
|
||||||
|
# df statistics - keep an eye on disk usage
|
||||||
|
echo "Disk usage before:" > disk-usage.txt
|
||||||
|
df -h /mnt/tests >> disk-usage.txt
|
||||||
|
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
IP="192.168.122.1$i"
|
||||||
|
daemonize -c /var/tmp -p vm${i}.pid -o vm${i}log.txt -- \
|
||||||
|
$SSH zfs@$IP $TESTS $OS $i $VMs
|
||||||
|
# give us the output of stdout + stderr - with prefix ;)
|
||||||
|
tail -fq vm${i}log.txt | $COLOR | sed -e "s/^/vm${i}: /g" &
|
||||||
|
echo $! > vm${i}log.pid
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
# wait for all vm's to finish
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
tail --pid=`cat vm${i}.pid` -f /dev/null
|
||||||
|
pid=`cat vm${i}log.pid`
|
||||||
|
rm -f vm${i}log.pid
|
||||||
|
kill $pid
|
||||||
|
done
|
||||||
|
|
||||||
|
# df statistics part 2
|
||||||
|
echo "Disk usage afterwards:" >> disk-usage.txt
|
||||||
|
df -h /mnt/tests >> disk-usage.txt
|
||||||
|
echo "VM files take this space:" >> disk-usage.txt
|
||||||
|
du -sh /mnt/tests >> disk-usage.txt
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# this part runs inside qemu vm
|
||||||
|
export PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/usr/local/bin"
|
||||||
|
case "$1" in
|
||||||
|
freebsd*)
|
||||||
|
# when freebsd's zfs is loaded, unload this one
|
||||||
|
sudo kldstat -n zfs 2>/dev/null && sudo kldunload zfs
|
||||||
|
sudo -E ./zfs/scripts/zfs.sh
|
||||||
|
sudo dmesg -c > /var/tmp/dmesg-prerun.txt
|
||||||
|
TDIR="/usr/local/share/zfs"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
sudo -E modprobe zfs
|
||||||
|
sudo dmesg -c > /var/tmp/dmesg-prerun.txt
|
||||||
|
TDIR="/usr/share/zfs"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# run functional testings
|
||||||
|
TAGS=$2/$3
|
||||||
|
#TAGS=casenorm,zpool_trim,trim,raidz
|
||||||
|
|
||||||
|
$TDIR/zfs-tests.sh -vK -s 3G -T $TAGS
|
||||||
|
RV=$?
|
||||||
|
|
||||||
|
# we wont fail here, this will be done later
|
||||||
|
echo $RV > /var/tmp/exitcode.txt
|
||||||
|
exit 0
|
|
@ -0,0 +1,72 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 7) prepare output of the results
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
cd /var/tmp
|
||||||
|
OS=`cat os.txt`
|
||||||
|
|
||||||
|
# check if building the module has failed
|
||||||
|
RESPATH="/var/tmp/test_results"
|
||||||
|
if [ ! -s vms.txt ]; then
|
||||||
|
mkdir -p $RESPATH
|
||||||
|
cd $RESPATH
|
||||||
|
# build some simple summary:
|
||||||
|
echo "!!! ZFS module didn't build successfully !!!" \
|
||||||
|
| tee summary.txt | tee clean-summary.txt
|
||||||
|
scp zfs@192.168.122.10:"/var/tmp/*.txt" $RESPATH || true
|
||||||
|
cp -f /var/tmp/*.txt $RESPATH || true
|
||||||
|
tar cf /tmp/qemu-$OS.tar -C $RESPATH -h . || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# build was okay
|
||||||
|
VMs=`cat vms.txt`
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
# vm${N}log.txt -> output of ssh/tail -> for merged summary.txt
|
||||||
|
#
|
||||||
|
# vm${N}/build-stderr.txt -> two copies -> moved to one file
|
||||||
|
# vm${N}/dmesg-prerun.txt -> dmesg output of vm start
|
||||||
|
# vm${N}/console.txt -> serial output of vm
|
||||||
|
# vm${N}/uname.txt -> output of uname -a on test vm
|
||||||
|
#
|
||||||
|
# vm${N}/current/log -> if not there, kernel panic loading
|
||||||
|
# vm${N}/current/results -> if not there, kernel panic testings
|
||||||
|
####################################################################
|
||||||
|
|
||||||
|
BASE="$HOME/work/zfs/zfs"
|
||||||
|
MERGE="$BASE/.github/workflows/scripts/merge_summary.awk"
|
||||||
|
|
||||||
|
# catch result files of testings
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
rsync -arL zfs@192.168.122.1$i:$RESPATH/current $RESPATH/vm$i || true
|
||||||
|
scp zfs@192.168.122.1$i:"/var/tmp/*.txt" $RESPATH/vm$i || true
|
||||||
|
done
|
||||||
|
cp -f /var/tmp/*.txt $RESPATH || true
|
||||||
|
cd $RESPATH
|
||||||
|
|
||||||
|
# Save a list of all failed test logs for easy access
|
||||||
|
awk '/\[FAIL\]|\[KILLED\]/{ show=1; print; next; }; \
|
||||||
|
/\[SKIP\]|\[PASS\]/{ show=0; } show' \
|
||||||
|
vm*/current/log >> summary-failure-logs.txt
|
||||||
|
|
||||||
|
$MERGE vm*log.txt > summary-clean.txt
|
||||||
|
$MERGE vm*log.txt | $BASE/scripts/zfs-tests-color.sh > summary.txt
|
||||||
|
|
||||||
|
# we should have "vm count" identical build-stderr.txt files, need only one
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
file="vm$i/build-stderr.txt"
|
||||||
|
test -s "$file" && mv -f $file build-stderr.txt
|
||||||
|
done
|
||||||
|
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
file="vm${i}log.txt"
|
||||||
|
test -s $file && cat $file | $BASE/scripts/zfs-tests-color.sh > $file.color
|
||||||
|
done
|
||||||
|
|
||||||
|
# artifact ready now
|
||||||
|
tar cf /tmp/qemu-$OS.tar -C $RESPATH -h . || true
|
|
@ -0,0 +1,78 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 7) output the prepared results
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# max size in KiB of debug output
|
||||||
|
DEBUG_MAX="100"
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
cd /var/tmp/test_results
|
||||||
|
OS=`cat os.txt`
|
||||||
|
RV=0
|
||||||
|
|
||||||
|
# helper function for showing some content with headline
|
||||||
|
function showfile() {
|
||||||
|
content=`dd if=$1 bs=1024 count=$DEBUG_MAX 2>/dev/null`
|
||||||
|
hl="$2"
|
||||||
|
SIZE=`stat --printf="%s" "$file"`
|
||||||
|
SIZE=$((SIZE/1024))
|
||||||
|
kb=" ($SIZE KiB)"
|
||||||
|
cat <<EOF > tmp$$
|
||||||
|
##[group]$hl${kb}
|
||||||
|
$content
|
||||||
|
##[endgroup]
|
||||||
|
EOF
|
||||||
|
cat tmp$$
|
||||||
|
rm -f tmp$$
|
||||||
|
}
|
||||||
|
|
||||||
|
# overview
|
||||||
|
cat summary.txt
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Full logs for download: $1"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "File listing:"
|
||||||
|
ls -l
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
file="build-stderr.txt"
|
||||||
|
test -s "$file" && showfile "$file" "Stderr of module build"
|
||||||
|
|
||||||
|
# all other logs are only generated with the testings
|
||||||
|
test -s vms.txt || exit 1
|
||||||
|
|
||||||
|
# build was okay
|
||||||
|
VMs=`cat vms.txt`
|
||||||
|
|
||||||
|
# Did we have a test failure?
|
||||||
|
if grep -vq 0 vm*/exitcode.txt; then
|
||||||
|
echo ""
|
||||||
|
file="summary-failure-logs.txt"
|
||||||
|
|
||||||
|
showfile "$file" "One or more tests failed, debug file"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
cat summary.txt
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Full logs for download: $1"
|
||||||
|
RV=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
file="vm$i/dmesg-prerun.txt"
|
||||||
|
test -s "$file" && showfile "$file" "vm$i: dmesg kernel"
|
||||||
|
|
||||||
|
file="vm$i/console.txt"
|
||||||
|
test -s "$file" && showfile "$file" "vm$i: serial console"
|
||||||
|
|
||||||
|
file="vm${i}log.txt.color"
|
||||||
|
test -s "$file" && showfile "$file" "vm$i: test results"
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $RV
|
|
@ -0,0 +1,77 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 8) generate github summary page of all the testings
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
function output() {
|
||||||
|
echo -e $* >> "out-$logfile.md"
|
||||||
|
}
|
||||||
|
|
||||||
|
function outfile() {
|
||||||
|
CUR=`stat --printf="%s" "out-$logfile.md"`
|
||||||
|
ADD=`stat --printf="%s" "$1"`
|
||||||
|
X=$((CUR+ADD))
|
||||||
|
if [ $X -gt $((1024*1023)) ]; then
|
||||||
|
logfile=$((logfile+1))
|
||||||
|
fi
|
||||||
|
cat "$1" >> "out-$logfile.md"
|
||||||
|
}
|
||||||
|
|
||||||
|
function send2github() {
|
||||||
|
test -f "$1" || exit 0
|
||||||
|
dd if="$1" bs=1023k count=1 >> $GITHUB_STEP_SUMMARY
|
||||||
|
}
|
||||||
|
|
||||||
|
# generate summary of one test
|
||||||
|
function generate() {
|
||||||
|
osname=`cat osname.txt`
|
||||||
|
VMs=`cat vms.txt`
|
||||||
|
|
||||||
|
logfile=$((logfile+1))
|
||||||
|
output "\n## Functional Tests: $osname\n"
|
||||||
|
for i in `seq 1 $VMs`; do
|
||||||
|
for f in uname.txt; do
|
||||||
|
test -s vm$i/$f && cat vm$i/$f >> $f
|
||||||
|
touch $f
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
output "<pre>"
|
||||||
|
outfile uname.txt
|
||||||
|
output "</pre>"
|
||||||
|
|
||||||
|
if [ -s "summary-clean.txt" ]; then
|
||||||
|
output "<pre>"
|
||||||
|
outfile "summary-clean.txt"
|
||||||
|
output "</pre>"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# https://docs.github.com/en/enterprise-server@3.6/actions/using-workflows/workflow-commands-for-github-actions#step-isolation-and-limits
|
||||||
|
# Job summaries are isolated between steps and each step is restricted to a maximum size of 1MiB.
|
||||||
|
# [ ] can not show all error findings here
|
||||||
|
# [x] split files into smaller ones and create additional steps
|
||||||
|
|
||||||
|
# first call, generate all summaries
|
||||||
|
if [ ! -f out-1.md ]; then
|
||||||
|
# create ./zts-report.py for generate()
|
||||||
|
TEMPLATE="tests/test-runner/bin/zts-report.py.in"
|
||||||
|
cat $TEMPLATE| sed -e 's|@PYTHON_SHEBANG@|python3|' > ./zts-report.py
|
||||||
|
chmod +x ./zts-report.py
|
||||||
|
|
||||||
|
logfile="0"
|
||||||
|
for tarfile in Logs-functional-*/qemu-*.tar; do
|
||||||
|
if [ ! -s "$tarfile" ]; then
|
||||||
|
output "\n# Functional Tests: unknown\n"
|
||||||
|
output ":exclamation: Tarfile $tarfile is empty :exclamation:"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
rm -rf vm* *.txt
|
||||||
|
tar xf "$tarfile"
|
||||||
|
generate
|
||||||
|
done
|
||||||
|
send2github out-1.md
|
||||||
|
else
|
||||||
|
send2github out-$1.md
|
||||||
|
fi
|
|
@ -0,0 +1,139 @@
|
||||||
|
name: zfs-qemu
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
qemu-vm:
|
||||||
|
name: qemu-vm
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
# all:
|
||||||
|
# os: [almalinux8, almalinux9, archlinux, centos-stream9, fedora39, fedora40, debian11, debian12, freebsd13, freebsd13r, freebsd14, freebsd14r, freebsd15, ubuntu20, ubuntu22, ubuntu24]
|
||||||
|
# openzfs:
|
||||||
|
os: [almalinux8, almalinux9, centos-stream9, fedora39, fedora40, freebsd13, freebsd13r, freebsd14, freebsd14r, freebsd15, ubuntu20, ubuntu22, ubuntu24]
|
||||||
|
# freebsd:
|
||||||
|
# os: [freebsd13, freebsd13r, freebsd14, freebsd14r]
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
|
- name: Setup QEMU
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: .github/workflows/scripts/qemu-1-setup.sh
|
||||||
|
|
||||||
|
- name: Start build machine
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: .github/workflows/scripts/qemu-2-start.sh ${{ matrix.os }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
timeout-minutes: 20
|
||||||
|
run: |
|
||||||
|
echo "Install dependencies in QEMU machine"
|
||||||
|
IP=192.168.122.10
|
||||||
|
while pidof /usr/bin/qemu-system-x86_64 >/dev/null; do
|
||||||
|
ssh 2>/dev/null zfs@$IP "uname -a" && break
|
||||||
|
done
|
||||||
|
scp .github/workflows/scripts/qemu-3-deps.sh zfs@$IP:qemu-3-deps.sh
|
||||||
|
PID=`pidof /usr/bin/qemu-system-x86_64`
|
||||||
|
ssh zfs@$IP '$HOME/qemu-3-deps.sh' ${{ matrix.os }}
|
||||||
|
# wait for poweroff to succeed
|
||||||
|
tail --pid=$PID -f /dev/null
|
||||||
|
sleep 5 # avoid this: "error: Domain is already active"
|
||||||
|
rm -f $HOME/.ssh/known_hosts
|
||||||
|
|
||||||
|
- name: Build modules
|
||||||
|
timeout-minutes: 30
|
||||||
|
run: |
|
||||||
|
echo "Build modules in QEMU machine"
|
||||||
|
sudo virsh start openzfs
|
||||||
|
IP=192.168.122.10
|
||||||
|
while pidof /usr/bin/qemu-system-x86_64 >/dev/null; do
|
||||||
|
ssh 2>/dev/null zfs@$IP "uname -a" && break
|
||||||
|
done
|
||||||
|
rsync -ar $HOME/work/zfs/zfs zfs@$IP:./
|
||||||
|
ssh zfs@$IP '$HOME/zfs/.github/workflows/scripts/qemu-4-build.sh' ${{ matrix.os }}
|
||||||
|
|
||||||
|
- name: Setup testing machines
|
||||||
|
timeout-minutes: 5
|
||||||
|
run: .github/workflows/scripts/qemu-5-setup.sh
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
timeout-minutes: 270
|
||||||
|
run: .github/workflows/scripts/qemu-6-tests.sh ${{ matrix.os }}
|
||||||
|
|
||||||
|
- name: Prepare artifacts
|
||||||
|
if: always()
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: .github/workflows/scripts/qemu-7-prepare.sh
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
id: artifact-upload
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: Logs-functional-${{ matrix.os }}
|
||||||
|
path: /tmp/qemu-${{ matrix.os }}.tar
|
||||||
|
if-no-files-found: ignore
|
||||||
|
|
||||||
|
- name: Test Summary
|
||||||
|
if: success() || failure()
|
||||||
|
run: .github/workflows/scripts/qemu-7-summary.sh '${{ steps.artifact-upload.outputs.artifact-url }}'
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if: always()
|
||||||
|
name: Cleanup
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ qemu-vm ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
- name: Generating summary
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 2
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 3
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 4
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 5
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 6
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 7
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 8
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 9
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 10
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 11
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 12
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 13
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 14
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 15
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 16
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 17
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 18
|
||||||
|
- name: Generating summary...
|
||||||
|
run: .github/workflows/scripts/qemu-8-summary.sh 19
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Summary Files
|
||||||
|
path: out-*
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/sh
|
#!/usr/bin/env bash
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
#
|
#
|
||||||
# CDDL HEADER START
|
# CDDL HEADER START
|
||||||
|
@ -208,6 +208,46 @@ find_runfile() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Given a TAGS with a format like "1/3" or "2/3" then divide up the test list
|
||||||
|
# into portions and print that portion. So "1/3" for "the first third of the
|
||||||
|
# test tags".
|
||||||
|
#
|
||||||
|
#
|
||||||
|
split_tags() {
|
||||||
|
# Get numerator and denominator
|
||||||
|
NUM=$(echo $TAGS | cut -d/ -f1)
|
||||||
|
DEN=$(echo $TAGS | cut -d/ -f2)
|
||||||
|
# At the point this is called, RUNFILES will contain a comma separated
|
||||||
|
# list of full paths to the runfiles, like:
|
||||||
|
#
|
||||||
|
# "/home/hutter/qemu/tests/runfiles/common.run,/home/hutter/qemu/tests/runfiles/linux.run"
|
||||||
|
#
|
||||||
|
# So to get tags for our selected tests we do:
|
||||||
|
#
|
||||||
|
# 1. Remove unneeded chars: [],\
|
||||||
|
# 2. Print out the last field of each tag line. This will be the tag
|
||||||
|
# for the test (like 'zpool_add').
|
||||||
|
# 3. Remove duplicates between the runfiles. If the same tag is defined
|
||||||
|
# in multiple runfiles, then when you do '-T <tag>' ZTS is smart
|
||||||
|
# enough to know to run the tag in each runfile. So '-T zpool_add'
|
||||||
|
# will run the zpool_add from common.run and linux.run.
|
||||||
|
# 4. Ignore the 'functional' tag since we only want individual tests
|
||||||
|
# 5. Print out the tests in our faction of all tests. This uses modulus
|
||||||
|
# so "1/3" will run tests 1,3,6,9 etc. That way the tests are
|
||||||
|
# interleaved so, say, "3/4" isn't running all the zpool_* tests that
|
||||||
|
# appear alphabetically at the end.
|
||||||
|
# 6. Remove trailing comma from list
|
||||||
|
#
|
||||||
|
# TAGS will then look like:
|
||||||
|
#
|
||||||
|
# "append,atime,bootfs,cachefile,checksum,cp_files,deadman,dos_attributes, ..."
|
||||||
|
|
||||||
|
cat ${RUNFILES/,/ } | tr -d [],\' | awk '/tags = /{print $NF}' | sort | \
|
||||||
|
uniq | grep -v functional | \
|
||||||
|
awk -v num=$NUM -v den=$DEN '{ if(NR % den == (num - 1)) {printf "%s,",$0}}' | \
|
||||||
|
sed -E 's/,$//'
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Symlink file if it appears under any of the given paths.
|
# Symlink file if it appears under any of the given paths.
|
||||||
#
|
#
|
||||||
|
@ -331,6 +371,10 @@ OPTIONS:
|
||||||
-t PATH|NAME Run single test at PATH relative to test suite,
|
-t PATH|NAME Run single test at PATH relative to test suite,
|
||||||
or search for test by NAME
|
or search for test by NAME
|
||||||
-T TAGS Comma separated list of tags (default: 'functional')
|
-T TAGS Comma separated list of tags (default: 'functional')
|
||||||
|
Alternately, specify a fraction like "1/3" or "2/3" to
|
||||||
|
run the first third of tests or 2nd third of the tests. This
|
||||||
|
is useful for splitting up the test amongst different
|
||||||
|
runners.
|
||||||
-u USER Run single test as USER (default: root)
|
-u USER Run single test as USER (default: root)
|
||||||
|
|
||||||
EXAMPLES:
|
EXAMPLES:
|
||||||
|
@ -489,6 +533,8 @@ fi
|
||||||
#
|
#
|
||||||
TAGS=${TAGS:='functional'}
|
TAGS=${TAGS:='functional'}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Attempt to locate the runfiles describing the test workload.
|
# Attempt to locate the runfiles describing the test workload.
|
||||||
#
|
#
|
||||||
|
@ -509,6 +555,23 @@ done
|
||||||
unset IFS
|
unset IFS
|
||||||
RUNFILES=${R#,}
|
RUNFILES=${R#,}
|
||||||
|
|
||||||
|
# The tag can be a fraction to indicate which portion of ZTS to run, Like
|
||||||
|
#
|
||||||
|
# "1/3": Run first one third of all tests in runfiles
|
||||||
|
# "2/3": Run second one third of all test in runfiles
|
||||||
|
# "6/10": Run 6th tenth of all tests in runfiles
|
||||||
|
#
|
||||||
|
# This is useful for splitting up the test across multiple runners.
|
||||||
|
#
|
||||||
|
# After this code block, TAGS will be transformed from something like
|
||||||
|
# "1/3" to a comma separate taglist, like:
|
||||||
|
#
|
||||||
|
# "append,atime,bootfs,cachefile,checksum,cp_files,deadman,dos_attributes, ..."
|
||||||
|
#
|
||||||
|
if echo $TAGS | grep -Eq '^[0-9]+/[0-9]+$' ; then
|
||||||
|
TAGS=$(split_tags)
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# This script should not be run as root. Instead the test user, which may
|
# 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
|
# be a normal user account, needs to be configured such that it can
|
||||||
|
|
Loading…
Reference in New Issue