diff --git a/.github/workflows/checkstyle.yaml b/.github/workflows/checkstyle.yaml index b34ca1302873..a01a4fe8587c 100644 --- a/.github/workflows/checkstyle.yaml +++ b/.github/workflows/checkstyle.yaml @@ -1,64 +1,64 @@ name: checkstyle on: push: pull_request: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: checkstyle: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies run: | # for x in lxd core20 snapd; do sudo snap remove $x; done sudo apt-get purge -y snapd google-chrome-stable firefox - ONLY_DEPS=1 .github/workflows/scripts/qemu-3-deps.sh ubuntu22 + ONLY_DEPS=1 .github/workflows/scripts/qemu-3-deps-vm.sh ubuntu22 sudo apt-get install -y cppcheck devscripts mandoc pax-utils shellcheck sudo python -m pipx install --quiet flake8 # confirm that the tools are installed # the build system doesn't fail when they are not checkbashisms --version cppcheck --version flake8 --version scanelf --version shellcheck --version - name: Prepare run: | sed -i '/DEBUG_CFLAGS="-Werror"/s/^/#/' config/zfs-build.m4 ./autogen.sh - name: Configure run: | ./configure - name: Make run: | make -j$(nproc) --no-print-directory --silent - name: Checkstyle run: | make -j$(nproc) --no-print-directory --silent checkstyle - name: Lint run: | make -j$(nproc) --no-print-directory --silent lint - name: CheckABI id: CheckABI run: | docker run -v $PWD:/source ghcr.io/openzfs/libabigail make -j$(nproc) --no-print-directory --silent checkabi - name: StoreABI if: failure() && steps.CheckABI.outcome == 'failure' run: | docker run -v $PWD:/source ghcr.io/openzfs/libabigail make -j$(nproc) --no-print-directory --silent storeabi - name: Prepare artifacts if: failure() && steps.CheckABI.outcome == 'failure' run: | find -name *.abi | tar -cf abi_files.tar -T - - uses: actions/upload-artifact@v4 if: failure() && steps.CheckABI.outcome == 'failure' with: name: New ABI files (use only if you're sure about interface changes) path: abi_files.tar diff --git a/.github/workflows/scripts/qemu-2-start.sh b/.github/workflows/scripts/qemu-2-start.sh index 73496d4f3de6..7fd99b609c9a 100755 --- a/.github/workflows/scripts/qemu-2-start.sh +++ b/.github/workflows/scripts/qemu-2-start.sh @@ -1,232 +1,241 @@ #!/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 REPO="https://github.com/mcmilk/openzfs-freebsd-images" FREEBSD="$REPO/releases/download/v2024-12-14" 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" # default nic model for vm's NIC="virtio" 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" # dns sometimes fails with that url :/ echo "89.187.191.12 geo.mirror.pkgbuild.com" | sudo tee /etc/hosts > /dev/null ;; centos-stream10) OSNAME="CentOS Stream 10" # TODO: #16903 Overwrite OSv to stream9 for virt-install until it's added to osinfo OSv="centos-stream9" URL="https://cloud.centos.org/centos/10-stream/x86_64/images/CentOS-Stream-GenericCloud-10-latest.x86_64.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" ;; fedora40) OSNAME="Fedora 40" OSv="fedora-unknown" URL="https://download.fedoraproject.org/pub/fedora/linux/releases/40/Cloud/x86_64/images/Fedora-Cloud-Base-Generic.x86_64-40-1.14.qcow2" ;; fedora41) OSNAME="Fedora 41" OSv="fedora-unknown" URL="https://download.fedoraproject.org/pub/fedora/linux/releases/41/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-41-1.4.x86_64.qcow2" ;; freebsd13-3r) OSNAME="FreeBSD 13.3-RELEASE" OSv="freebsd13.0" URLzs="$FREEBSD/amd64-freebsd-13.3-RELEASE.qcow2.zst" BASH="/usr/local/bin/bash" NIC="rtl8139" ;; freebsd13-4r) OSNAME="FreeBSD 13.4-RELEASE" OSv="freebsd13.0" URLzs="$FREEBSD/amd64-freebsd-13.4-RELEASE.qcow2.zst" BASH="/usr/local/bin/bash" NIC="rtl8139" ;; freebsd14-1r) OSNAME="FreeBSD 14.1-RELEASE" OSv="freebsd14.0" URLzs="$FREEBSD/amd64-freebsd-14.1-RELEASE.qcow2.zst" BASH="/usr/local/bin/bash" ;; freebsd14-2r) OSNAME="FreeBSD 14.2-RELEASE" OSv="freebsd14.0" URLzs="$FREEBSD/amd64-freebsd-14.2-RELEASE.qcow2.zst" BASH="/usr/local/bin/bash" ;; freebsd13-4s) OSNAME="FreeBSD 13.4-STABLE" OSv="freebsd13.0" URLzs="$FREEBSD/amd64-freebsd-13.4-STABLE.qcow2.zst" BASH="/usr/local/bin/bash" NIC="rtl8139" ;; freebsd14-2s) OSNAME="FreeBSD 14.2-STABLE" OSv="freebsd14.0" URLzs="$FREEBSD/amd64-freebsd-14.2-STABLE.qcow2.zst" BASH="/usr/local/bin/bash" ;; freebsd15-0c) 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 # environment file ENV="/var/tmp/env.txt" echo "ENV=$ENV" >> $ENV # result path echo 'RESPATH="/var/tmp/test_results"' >> $ENV # FreeBSD 13 has problems with: e1000+virtio echo "NIC=$NIC" >> $ENV # freebsd15 -> used in zfs-qemu.yml echo "OS=$OS" >> $ENV # freebsd14.0 -> used for virt-install echo "OSv=\"$OSv\"" >> $ENV # FreeBSD 15 (Current) -> used for summary echo "OSNAME=\"$OSNAME\"" >> $ENV sudo mkdir -p "/mnt/tests" sudo chown -R $(whoami) /mnt/tests # we are downloading via axel, curl and wget are mostly slower and # require more return value checking IMG="/mnt/tests/cloudimg.qcow2" 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 DISK="/dev/zvol/zpool/openzfs" FORMAT="raw" sudo zfs create -ps -b 64k -V 80g zpool/openzfs while true; do test -b $DISK && break; sleep 1; done echo "Importing VM image to zvol..." sudo qemu-img dd -f qcow2 -O raw if=$IMG of=$DISK bs=4M rm -f $IMG PUBKEY=$(cat ~/.ssh/id_ed25519.pub) cat < /tmp/user-data #cloud-config fqdn: $OS users: - name: root shell: $BASH - name: zfs sudo: ALL=(ALL) NOPASSWD:ALL shell: $BASH ssh_authorized_keys: - $PUBKEY growpart: mode: auto devices: ['/'] ignore_growroot_disabled: false EOF sudo virsh net-update default add ip-dhcp-host \ "" --live --config 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=$NIC,mac='52:54:00:83:79:00' \ --cloud-init user-data=/tmp/user-data \ --disk $DISK,bus=virtio,cache=none,format=$FORMAT,driver.discard=unmap \ --import --noautoconsole >/dev/null +# Give the VMs hostnames so we don't have to refer to them with +# hardcoded IP addresses. +# +# vm0: Initial VM we install dependencies and build ZFS on. +# vm1..2 Testing VMs +for i in {0..9} ; do + echo "192.168.122.1$i vm$i" | sudo tee -a /etc/hosts +done + # in case the directory isn't there already mkdir -p $HOME/.ssh cat <> $HOME/.ssh/config # no questions please StrictHostKeyChecking no # small timeout, used in while loops later ConnectTimeout 1 EOF diff --git a/.github/workflows/scripts/qemu-3-deps.sh b/.github/workflows/scripts/qemu-3-deps-vm.sh similarity index 99% copy from .github/workflows/scripts/qemu-3-deps.sh copy to .github/workflows/scripts/qemu-3-deps-vm.sh index 9b8957734277..9bd86b5ba704 100755 --- a/.github/workflows/scripts/qemu-3-deps.sh +++ b/.github/workflows/scripts/qemu-3-deps-vm.sh @@ -1,229 +1,232 @@ #!/usr/bin/env bash ###################################################################### # 3) install dependencies for compiling and loading +# +# $1: OS name (like 'fedora41') ###################################################################### set -eu function archlinux() { echo "##[group]Running pacman -Syu" sudo btrfs filesystem resize max / sudo pacman -Syu --noconfirm echo "##[endgroup]" echo "##[group]Install Development Tools" sudo pacman -Sy --noconfirm base-devel bc cpio cryptsetup 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 xxhash 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 cryptsetup 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 libunwind-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 xxhash 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 xxhash 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" # Alma wants "Development Tools", Fedora 41 wants "development-tools" if ! sudo dnf group install -y "Development Tools" ; then echo "Trying 'development-tools' instead of 'Development Tools'" sudo dnf group install -y development-tools fi sudo dnf install -y \ acl attr bc bzip2 cryptsetup 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 xxhash \ 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|centos-stream10) 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*) echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections debian echo "##[group]Install Debian specific" sudo apt-get install -yq linux-perf dh-sequence-dkms echo "##[endgroup]" ;; fedora*) rhel + sudo dnf install -y libunwind-devel ;; 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 # This script is used for checkstyle + zloop deps also. # Install only the needed packages and exit - when used this way. test -z "${ONLY_DEPS:-}" || exit 0 # 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]" # Setup Kernel cmdline CMDLINE="console=tty0 console=ttyS0,115200n8" CMDLINE="$CMDLINE selinux=0" CMDLINE="$CMDLINE random.trust_cpu=on" CMDLINE="$CMDLINE no_timer_check" case "$1" in almalinux*|centos*|fedora*) GRUB_CFG="/boot/grub2/grub.cfg" GRUB_MKCONFIG="grub2-mkconfig" CMDLINE="$CMDLINE biosdevname=0 net.ifnames=0" echo 'GRUB_SERIAL_COMMAND="serial --speed=115200"' \ | sudo tee -a /etc/default/grub >/dev/null ;; ubuntu24) GRUB_CFG="/boot/grub/grub.cfg" GRUB_MKCONFIG="grub-mkconfig" echo 'GRUB_DISABLE_OS_PROBER="false"' \ | sudo tee -a /etc/default/grub >/dev/null ;; *) GRUB_CFG="/boot/grub/grub.cfg" GRUB_MKCONFIG="grub-mkconfig" ;; esac case "$1" in archlinux|freebsd*) true ;; *) echo "##[group]Edit kernel cmdline" sudo sed -i -e '/^GRUB_CMDLINE_LINUX/d' /etc/default/grub || true echo "GRUB_CMDLINE_LINUX=\"$CMDLINE\"" \ | sudo tee -a /etc/default/grub >/dev/null sudo $GRUB_MKCONFIG -o $GRUB_CFG echo "##[endgroup]" ;; esac # reset cloud-init configuration and poweroff sudo cloud-init clean --logs sleep 2 && sudo poweroff & exit 0 diff --git a/.github/workflows/scripts/qemu-3-deps.sh b/.github/workflows/scripts/qemu-3-deps.sh index 9b8957734277..184aed85b4e5 100755 --- a/.github/workflows/scripts/qemu-3-deps.sh +++ b/.github/workflows/scripts/qemu-3-deps.sh @@ -1,229 +1,15 @@ -#!/usr/bin/env bash - ###################################################################### -# 3) install dependencies for compiling and loading +# 3) Wait for VM to boot from previous step and launch dependencies +# script on it. +# +# $1: OS name (like 'fedora41') ###################################################################### -set -eu - -function archlinux() { - echo "##[group]Running pacman -Syu" - sudo btrfs filesystem resize max / - sudo pacman -Syu --noconfirm - echo "##[endgroup]" - - echo "##[group]Install Development Tools" - sudo pacman -Sy --noconfirm base-devel bc cpio cryptsetup 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 xxhash - 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 cryptsetup 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 libunwind-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 xxhash 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 xxhash - 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" - - # Alma wants "Development Tools", Fedora 41 wants "development-tools" - if ! sudo dnf group install -y "Development Tools" ; then - echo "Trying 'development-tools' instead of 'Development Tools'" - sudo dnf group install -y development-tools - fi - - sudo dnf install -y \ - acl attr bc bzip2 cryptsetup 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 xxhash \ - 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|centos-stream10) - 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*) - echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections - 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 - -# This script is used for checkstyle + zloop deps also. -# Install only the needed packages and exit - when used this way. -test -z "${ONLY_DEPS:-}" || exit 0 - -# 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]" - -# Setup Kernel cmdline -CMDLINE="console=tty0 console=ttyS0,115200n8" -CMDLINE="$CMDLINE selinux=0" -CMDLINE="$CMDLINE random.trust_cpu=on" -CMDLINE="$CMDLINE no_timer_check" -case "$1" in - almalinux*|centos*|fedora*) - GRUB_CFG="/boot/grub2/grub.cfg" - GRUB_MKCONFIG="grub2-mkconfig" - CMDLINE="$CMDLINE biosdevname=0 net.ifnames=0" - echo 'GRUB_SERIAL_COMMAND="serial --speed=115200"' \ - | sudo tee -a /etc/default/grub >/dev/null - ;; - ubuntu24) - GRUB_CFG="/boot/grub/grub.cfg" - GRUB_MKCONFIG="grub-mkconfig" - echo 'GRUB_DISABLE_OS_PROBER="false"' \ - | sudo tee -a /etc/default/grub >/dev/null - ;; - *) - GRUB_CFG="/boot/grub/grub.cfg" - GRUB_MKCONFIG="grub-mkconfig" - ;; -esac - -case "$1" in - archlinux|freebsd*) - true - ;; - *) - echo "##[group]Edit kernel cmdline" - sudo sed -i -e '/^GRUB_CMDLINE_LINUX/d' /etc/default/grub || true - echo "GRUB_CMDLINE_LINUX=\"$CMDLINE\"" \ - | sudo tee -a /etc/default/grub >/dev/null - sudo $GRUB_MKCONFIG -o $GRUB_CFG - echo "##[endgroup]" - ;; -esac - -# reset cloud-init configuration and poweroff -sudo cloud-init clean --logs -sleep 2 && sudo poweroff & -exit 0 +.github/workflows/scripts/qemu-wait-for-vm.sh vm0 +scp .github/workflows/scripts/qemu-3-deps-vm.sh zfs@vm0:qemu-3-deps-vm.sh +PID=`pidof /usr/bin/qemu-system-x86_64` +ssh zfs@vm0 '$HOME/qemu-3-deps-vm.sh' $1 +# 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 diff --git a/.github/workflows/scripts/qemu-4-build-vm.sh b/.github/workflows/scripts/qemu-4-build-vm.sh new file mode 100755 index 000000000000..766352ba824b --- /dev/null +++ b/.github/workflows/scripts/qemu-4-build-vm.sh @@ -0,0 +1,370 @@ +#!/usr/bin/env bash + +###################################################################### +# 4) configure and build openzfs modules. This is run on the VMs. +# +# Usage: +# +# qemu-4-build-vm.sh OS [--enable-debug][--dkms][--poweroff] +# [--release][--repo][--tarball] +# +# OS: OS name like 'fedora41' +# --enable-debug: Build RPMs with '--enable-debug' (for testing) +# --dkms: Build DKMS RPMs as well +# --poweroff: Power-off the VM after building +# --release Build zfs-release*.rpm as well +# --repo After building everything, copy RPMs into /tmp/repo +# in the ZFS RPM repository file structure. Also +# copy tarballs if they were built. +# --tarball: Also build a tarball of ZFS source +###################################################################### + +ENABLE_DEBUG="" +DKMS="" +POWEROFF="" +RELEASE="" +REPO="" +TARBALL="" +while [[ $# -gt 0 ]]; do + case $1 in + --enable-debug) + ENABLE_DEBUG=1 + shift + ;; + --dkms) + DKMS=1 + shift + ;; + --poweroff) + POWEROFF=1 + shift + ;; + --release) + RELEASE=1 + shift + ;; + --repo) + REPO=1 + shift + ;; + --tarball) + TARBALL=1 + shift + ;; + *) + OS=$1 + shift + ;; + esac +done + +set -eu + +function run() { + LOG="/var/tmp/build-stderr.txt" + echo "****************************************************" + echo "$(date) ($*)" + echo "****************************************************" + ($@ || echo $? > /tmp/rv) 3>&1 1>&2 2>&3 | stdbuf -eL -oL tee -a $LOG + if [ -f /tmp/rv ]; then + RV=$(cat /tmp/rv) + echo "****************************************************" + echo "exit with value=$RV ($*)" + echo "****************************************************" + echo 1 > /var/tmp/build-exitcode.txt + exit $RV + fi +} + +# Look at the RPMs in the current directory and copy/move them to +# /tmp/repo, using the directory structure we use for the ZFS RPM repos. +# +# For example: +# /tmp/repo/epel-testing/9.5 +# /tmp/repo/epel-testing/9.5/SRPMS +# /tmp/repo/epel-testing/9.5/SRPMS/zfs-2.3.99-1.el9.src.rpm +# /tmp/repo/epel-testing/9.5/SRPMS/zfs-kmod-2.3.99-1.el9.src.rpm +# /tmp/repo/epel-testing/9.5/kmod +# /tmp/repo/epel-testing/9.5/kmod/x86_64 +# /tmp/repo/epel-testing/9.5/kmod/x86_64/debug +# /tmp/repo/epel-testing/9.5/kmod/x86_64/debug/kmod-zfs-debuginfo-2.3.99-1.el9.x86_64.rpm +# /tmp/repo/epel-testing/9.5/kmod/x86_64/debug/libnvpair3-debuginfo-2.3.99-1.el9.x86_64.rpm +# /tmp/repo/epel-testing/9.5/kmod/x86_64/debug/libuutil3-debuginfo-2.3.99-1.el9.x86_64.rpm +# ... +function copy_rpms_to_repo { + # Pick a RPM to query. It doesn't matter which one - we just want to extract + # the 'Build Host' value from it. + rpm=$(ls zfs-*.rpm | head -n 1) + + # Get zfs version '2.2.99' + zfs_ver=$(rpm -qpi $rpm | awk '/Version/{print $3}') + + # Get "2.1" or "2.2" + zfs_major=$(echo $zfs_ver | grep -Eo [0-9]+\.[0-9]+) + + # Get 'almalinux9.5' or 'fedora41' type string + build_host=$(rpm -qpi $rpm | awk '/Build Host/{print $4}') + + # Get '9.5' or '41' OS version + os_ver=$(echo $build_host | grep -Eo '[0-9\.]+$') + + # Our ZFS version and OS name will determine which repo the RPMs + # will go in (regular or testing). Fedora always gets the newest + # releases, and Alma gets the older releases. + case $build_host in + almalinux*) + case $zfs_major in + 2.2) + d="epel" + ;; + *) + d="epel-testing" + ;; + esac + ;; + fedora*) + d="fedora" + ;; + esac + + prefix=/tmp/repo + dst="$prefix/$d/$os_ver" + + # Special case: move zfs-release*.rpm out of the way first (if we built them). + # This will make filtering the other RPMs easier. + mkdir -p $dst + mv zfs-release*.rpm $dst || true + + # Copy source RPMs + mkdir -p $dst/SRPMS + cp $(ls *.src.rpm) $dst/SRPMS/ + + if [[ "$build_host" =~ "almalinux" ]] ; then + # Copy kmods+userspace + mkdir -p $dst/kmod/x86_64/debug + cp $(ls *.rpm | grep -Ev 'src.rpm|dkms|debuginfo') $dst/kmod/x86_64 + cp *debuginfo*.rpm $dst/kmod/x86_64/debug + fi + + if [ -n "$DKMS" ] ; then + # Copy dkms+userspace + mkdir -p $dst/x86_64 + cp $(ls *.rpm | grep -Ev 'src.rpm|kmod|debuginfo') $dst/x86_64 + fi + + # Copy debug + mkdir -p $dst/x86_64/debug + cp $(ls *debuginfo*.rpm | grep -v kmod) $dst/x86_64/debug +} + +function freebsd() { + extra="${1:-}" + + 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-debuginfo $extra + 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() { + extra="${1:-}" + + echo "##[group]Autogen.sh" + run ./autogen.sh + echo "##[endgroup]" + + echo "##[group]Configure" + run ./configure \ + --prefix=/usr \ + --enable-pyzfs \ + --enable-debuginfo $extra + 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="${1:-}" + + # Build RPMs with XZ compression by default (since gzip decompression is slow) + echo "%_binary_payload w7.xzdio" >> ~/.rpmmacros + + echo "##[group]Autogen.sh" + run ./autogen.sh + echo "##[endgroup]" + + echo "##[group]Configure" + run ./configure --enable-debuginfo $extra + echo "##[endgroup]" + + echo "##[group]Build" + run make pkg-kmod pkg-utils + echo "##[endgroup]" + + if [ -n "$DKMS" ] ; then + echo "##[group]DKMS" + make rpm-dkms + echo "##[endgroup]" + fi + + if [ -n "$REPO" ] ; then + echo "Skipping install since we're only building RPMs and nothing else" + else + echo "##[group]Install" + run sudo dnf -y --nobest install $(ls *.rpm | grep -Ev 'dkms|src.rpm') + echo "##[endgroup]" + fi + + # Optionally build the zfs-release.*.rpm + if [ -n "$RELEASE" ] ; then + echo "##[group]Release" + pushd ~ + sudo dnf -y install rpm-build || true + # Check out a sparse copy of zfsonlinux.github.com.git so we don't get + # all the binaries. We just need a few kilobytes of files to build RPMs. + git clone --depth 1 --no-checkout \ + https://github.com/zfsonlinux/zfsonlinux.github.com.git + + cd zfsonlinux.github.com + git sparse-checkout set zfs-release + git checkout + cd zfs-release + + mkdir -p ~/rpmbuild/{BUILDROOT,SPECS,RPMS,SRPMS,SOURCES,BUILD} + cp RPM-GPG-KEY-openzfs* *.repo ~/rpmbuild/SOURCES + cp zfs-release.spec ~/rpmbuild/SPECS/ + rpmbuild -ba ~/rpmbuild/SPECS/zfs-release.spec + + # ZFS release RPMs are built. Copy them to the ~/zfs directory just to + # keep all the RPMs in the same place. + cp ~/rpmbuild/RPMS/noarch/*.rpm . + cp ~/rpmbuild/SRPMS/*.rpm . + popd + rm -fr ~/rpmbuild + echo "##[endgroup]" + fi + + if [ -n "$REPO" ] ; then + echo "##[group]Repo" + copy_rpms_to_repo + echo "##[endgroup]" + fi +} + +function deb_build_and_install() { + extra="${1:-}" + + echo "##[group]Autogen.sh" + run ./autogen.sh + echo "##[endgroup]" + + echo "##[group]Configure" + run ./configure \ + --prefix=/usr \ + --enable-pyzfs \ + --enable-debuginfo $extra + 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 [ -f /proc/cmdline ] ; then + cat /proc/cmdline || true +fi + +# Set our hostname to our OS name and version number. Specifically, we set the +# major and minor number so that when we query the Build Host field in the RPMs +# we build, we can see what specific version of Fedora/Almalinux we were using +# to build them. This is helpful for matching up KMOD versions. +# +# Examples: +# +# rhel8.10 +# almalinux9.5 +# fedora40 +source /etc/os-release +sudo hostname "$ID$VERSION_ID" + +# save some sysinfo +uname -a > /var/tmp/uname.txt + +cd $HOME/zfs +export PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" + +extra="" +if [ -n "$ENABLE_DEBUG" ] ; then + extra="--enable-debug" +fi + +# build +case "$OS" in + freebsd*) + freebsd "$extra" + ;; + alma*|centos*) + rpm_build_and_install "--with-spec=redhat $extra" + ;; + fedora*) + rpm_build_and_install "$extra" + ;; + debian*|ubuntu*) + deb_build_and_install "$extra" + ;; + *) + linux "$extra" + ;; +esac + +# Optionally build tarballs. The tarball's root directory name will be named +# after the current tag, like 'zfs-2.3.0' or 'master'. +if [ -n "$TARBALL" ] ; then + tag="$(git symbolic-ref -q --short HEAD || git describe --tags --exact-match)" + git archive --format=tar.gz -o $tag.tar.gz $tag + if [ -n "$REPO" ] ; then + mkdir -p /tmp/repo/releases + cp $tag.tar.gz /tmp/repo/releases + fi +fi + +# building the zfs module was ok +echo 0 > /var/tmp/build-exitcode.txt + +# reset cloud-init configuration and poweroff +if [ -n "$POWEROFF" ] ; then + sudo cloud-init clean --logs + sync && sleep 2 && sudo poweroff & +fi +exit 0 diff --git a/.github/workflows/scripts/qemu-4-build.sh b/.github/workflows/scripts/qemu-4-build.sh index 955f605f5bce..63c9bccaa446 100755 --- a/.github/workflows/scripts/qemu-4-build.sh +++ b/.github/workflows/scripts/qemu-4-build.sh @@ -1,153 +1,11 @@ #!/usr/bin/env bash ###################################################################### # 4) configure and build openzfs modules ###################################################################### +echo "Build modules in QEMU machine" -set -eu +# Bring our VM back up and copy over ZFS source +.github/workflows/scripts/qemu-prepare-for-build.sh -function run() { - LOG="/var/tmp/build-stderr.txt" - echo "****************************************************" - echo "$(date) ($*)" - echo "****************************************************" - ($@ || echo $? > /tmp/rv) 3>&1 1>&2 2>&3 | stdbuf -eL -oL tee -a $LOG - if [ -f /tmp/rv ]; then - RV=$(cat /tmp/rv) - echo "****************************************************" - echo "exit with value=$RV ($*)" - echo "****************************************************" - echo 1 > /var/tmp/build-exitcode.txt - 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 dnf -y --nobest install $(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 [ -f /proc/cmdline ] ; then - cat /proc/cmdline || true -fi - -# save some sysinfo -uname -a > /var/tmp/uname.txt - -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 - -# building the zfs module was ok -echo 0 > /var/tmp/build-exitcode.txt - -# reset cloud-init configuration and poweroff -sudo cloud-init clean --logs -sync && sleep 2 && sudo poweroff & -exit 0 +ssh zfs@vm0 '$HOME/zfs/.github/workflows/scripts/qemu-4-build-vm.sh' $@ diff --git a/.github/workflows/scripts/qemu-5-setup.sh b/.github/workflows/scripts/qemu-5-setup.sh index bc40e8894b22..5b5bf5d7f7bb 100755 --- a/.github/workflows/scripts/qemu-5-setup.sh +++ b/.github/workflows/scripts/qemu-5-setup.sh @@ -1,126 +1,124 @@ #!/usr/bin/env bash ###################################################################### # 5) start test machines and load openzfs module ###################################################################### set -eu # read our defined variables source /var/tmp/env.txt # wait for poweroff to succeed PID=$(pidof /usr/bin/qemu-system-x86_64) tail --pid=$PID -f /dev/null sudo virsh undefine openzfs # default values per test vm: VMs=2 CPU=2 # cpu pinning CPUSET=("0,1" "2,3") case "$OS" in freebsd*) # FreeBSD can't be optimized via ksmtuned RAM=6 ;; *) # Linux can be optimized via ksmtuned RAM=8 ;; esac # this can be different for each distro echo "VMs=$VMs" >> $ENV # create snapshot we can clone later sudo zfs snapshot zpool/openzfs@now # setup the testing vm's PUBKEY=$(cat ~/.ssh/id_ed25519.pub) for i in $(seq 1 $VMs); do echo "Creating disk for vm$i..." DISK="/dev/zvol/zpool/vm$i" FORMAT="raw" sudo zfs clone zpool/openzfs@now zpool/vm$i sudo zfs create -ps -b 64k -V 80g zpool/vm$i-2 cat < /tmp/user-data #cloud-config fqdn: vm$i users: - name: root shell: $BASH - name: zfs sudo: ALL=(ALL) NOPASSWD:ALL shell: $BASH ssh_authorized_keys: - $PUBKEY growpart: mode: auto devices: ['/'] ignore_growroot_disabled: false EOF sudo virsh net-update default add ip-dhcp-host \ "" --live --config sudo virt-install \ --os-variant $OSv \ --name "vm$i" \ --cpu host-passthrough \ --virt-type=kvm --hvm \ --vcpus=$CPU,sockets=1 \ --cpuset=${CPUSET[$((i-1))]} \ --memory $((1024*RAM)) \ --memballoon model=virtio \ --graphics none \ --cloud-init user-data=/tmp/user-data \ --network bridge=virbr0,model=$NIC,mac="52:54:00:83:79:0$i" \ --disk $DISK,bus=virtio,cache=none,format=$FORMAT,driver.discard=unmap \ --disk $DISK-2,bus=virtio,cache=none,format=$FORMAT,driver.discard=unmap \ --import --noautoconsole >/dev/null done # check the memory state from time to time cat < cronjob.sh # $OS exec 1>>/var/tmp/stats.txt exec 2>&1 echo "*******************************************************" date uptime free -m df -h /mnt/tests zfs list EOF sudo chmod +x cronjob.sh sudo mv -f cronjob.sh /root/cronjob.sh echo '*/5 * * * * /root/cronjob.sh' > crontab.txt sudo crontab crontab.txt rm crontab.txt # 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 + .github/workflows/scripts/qemu-wait-for-vm.sh vm$i 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 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." diff --git a/.github/workflows/scripts/qemu-7-prepare.sh b/.github/workflows/scripts/qemu-7-prepare.sh index a5fbd7213161..51a3dbe64e5f 100755 --- a/.github/workflows/scripts/qemu-7-prepare.sh +++ b/.github/workflows/scripts/qemu-7-prepare.sh @@ -1,123 +1,124 @@ #!/usr/bin/env bash ###################################################################### # 7) prepare output of the results # - this script pre-creates all needed logfiles for later summary ###################################################################### set -eu # read our defined variables cd /var/tmp source env.txt mkdir -p $RESPATH # check if building the module has failed if [ -z ${VMs:-} ]; then cd $RESPATH echo ":exclamation: ZFS module didn't build successfully :exclamation:" \ | tee summary.txt | tee /tmp/summary.txt cp /var/tmp/*.txt . tar cf /tmp/qemu-$OS.tar -C $RESPATH -h . || true exit 0 fi # build was okay BASE="$HOME/work/zfs/zfs" MERGE="$BASE/.github/workflows/scripts/merge_summary.awk" # catch result files of testings (vm's should be there) 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 + rsync -arL zfs@vm$i:$RESPATH/current $RESPATH/vm$i || true + scp zfs@vm$i:"/var/tmp/*.txt" $RESPATH/vm$i || true + scp zfs@vm$i:"/var/tmp/*.rpm" $RESPATH/vm$i || true done cp -f /var/tmp/*.txt $RESPATH || true cd $RESPATH # prepare result files for summary for i in $(seq 1 $VMs); do file="vm$i/build-stderr.txt" test -s $file && mv -f $file build-stderr.txt file="vm$i/build-exitcode.txt" test -s $file && mv -f $file build-exitcode.txt file="vm$i/uname.txt" test -s $file && mv -f $file uname.txt file="vm$i/tests-exitcode.txt" if [ ! -s $file ]; then # XXX - add some tests for kernel panic's here # tail -n 80 vm$i/console.txt | grep XYZ echo 1 > $file fi rv=$(cat vm$i/tests-exitcode.txt) test $rv != 0 && touch /tmp/have_failed_tests file="vm$i/current/log" if [ -s $file ]; then cat $file >> log awk '/\[FAIL\]|\[KILLED\]/{ show=1; print; next; }; \ /\[SKIP\]|\[PASS\]/{ show=0; } show' \ $file > /tmp/vm${i}dbg.txt fi file="vm${i}log.txt" fileC="/tmp/vm${i}log.txt" if [ -s $file ]; then cat $file >> summary cat $file | $BASE/scripts/zfs-tests-color.sh > $fileC fi done # create summary of tests if [ -s summary ]; then $MERGE summary | grep -v '^/' > summary.txt $MERGE summary | $BASE/scripts/zfs-tests-color.sh > /tmp/summary.txt rm -f summary else touch summary.txt /tmp/summary.txt fi # create file for debugging if [ -s log ]; then awk '/\[FAIL\]|\[KILLED\]/{ show=1; print; next; }; \ /\[SKIP\]|\[PASS\]/{ show=0; } show' \ log > summary-failure-logs.txt rm -f log else touch summary-failure-logs.txt fi # create debug overview for failed tests cat summary.txt \ | awk '/\(expected PASS\)/{ if ($1!="SKIP") print $2; next; } show' \ | while read t; do cat summary-failure-logs.txt \ | awk '$0~/Test[: ]/{ show=0; } $0~v{ show=1; } show' v="$t" \ > /tmp/fail.txt SIZE=$(stat --printf="%s" /tmp/fail.txt) SIZE=$((SIZE/1024)) # Test Summary: echo "##[group]$t ($SIZE KiB)" >> /tmp/failed.txt cat /tmp/fail.txt | $BASE/scripts/zfs-tests-color.sh >> /tmp/failed.txt echo "##[endgroup]" >> /tmp/failed.txt # Job Summary: echo -e "\n
\n$t ($SIZE KiB)
" >> failed.txt
   cat /tmp/fail.txt >> failed.txt
   echo "
" >> failed.txt done if [ -e /tmp/have_failed_tests ]; then echo ":warning: Some tests failed!" >> failed.txt else echo ":thumbsup: All tests passed." >> failed.txt fi if [ ! -s uname.txt ]; then echo ":interrobang: Panic - where is my uname.txt?" > uname.txt fi # artifact ready now tar cf /tmp/qemu-$OS.tar -C $RESPATH -h . || true diff --git a/.github/workflows/scripts/qemu-prepare-for-build.sh b/.github/workflows/scripts/qemu-prepare-for-build.sh new file mode 100755 index 000000000000..a5a9e422ba6e --- /dev/null +++ b/.github/workflows/scripts/qemu-prepare-for-build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# Helper script to run after installing dependencies. This brings the VM back +# up and copies over the zfs source directory. +echo "Build modules in QEMU machine" +sudo virsh start openzfs +.github/workflows/scripts/qemu-wait-for-vm.sh vm0 +rsync -ar $HOME/work/zfs/zfs zfs@vm0:./ diff --git a/.github/workflows/scripts/qemu-test-repo-vm.sh b/.github/workflows/scripts/qemu-test-repo-vm.sh new file mode 100755 index 000000000000..e3cafcbb67cc --- /dev/null +++ b/.github/workflows/scripts/qemu-test-repo-vm.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# +# Do a test install of ZFS from an external repository. +# +# USAGE: +# +# ./qemu-test-repo-vm [URL] +# +# URL: URL to use instead of http://download.zfsonlinux.org +# If blank, use the default repo from zfs-release RPM. + +set -e + +source /etc/os-release +OS="$ID" +VERSION="$VERSION_ID" + +ALTHOST="" +if [ -n "$1" ] ; then + ALTHOST="$1" +fi + +# Write summary to /tmp/repo so our artifacts scripts pick it up +mkdir /tmp/repo +SUMMARY=/tmp/repo/$OS-$VERSION-summary.txt + +# $1: Repo 'zfs' 'zfs-kmod' 'zfs-testing' 'zfs-testing-kmod' +# $2: (optional) Alternate host than 'http://download.zfsonlinux.org' to +# install from. Blank means use default from zfs-release RPM. +function test_install { + repo=$1 + host="" + if [ -n "$2" ] ; then + host=$2 + fi + + args="--disablerepo=zfs --enablerepo=$repo" + + # If we supplied an alternate repo URL, and have not already edited + # zfs.repo, then update the repo file. + if [ -n "$host" ] && ! grep -q $host /etc/yum.repos.d/zfs.repo ; then + sudo sed -i "s;baseurl=http://download.zfsonlinux.org;baseurl=$host;g" /etc/yum.repos.d/zfs.repo + fi + + sudo dnf -y install $args zfs zfs-test + + # Load modules and create a simple pool as a sanity test. + sudo /usr/share/zfs/zfs.sh -r + truncate -s 100M /tmp/file + sudo zpool create tank /tmp/file + sudo zpool status + + # Print out repo name, rpm installed (kmod or dkms), and repo URL + baseurl=$(grep -A 5 "\[$repo\]" /etc/yum.repos.d/zfs.repo | awk -F'=' '/baseurl=/{print $2; exit}') + package=$(sudo rpm -qa | grep zfs | grep -E 'kmod|dkms') + + echo "$repo $package $baseurl" >> $SUMMARY + + sudo zpool destroy tank + sudo rm /tmp/file + sudo dnf -y remove zfs +} + +echo "##[group]Installing from repo" +# The openzfs docs are the authoritative instructions for the install. Use +# the specific version of zfs-release RPM it recommends. +case $OS in +almalinux*) + url='https://raw.githubusercontent.com/openzfs/openzfs-docs/refs/heads/master/docs/Getting%20Started/RHEL-based%20distro/index.rst' + name=$(curl -Ls $url | grep 'dnf install' | grep -Eo 'zfs-release-[0-9]+-[0-9]+') + sudo dnf -y install https://zfsonlinux.org/epel/$name$(rpm --eval "%{dist}").noarch.rpm 2>&1 + sudo rpm -qi zfs-release + test_install zfs $ALTHOST + test_install zfs-kmod $ALTHOST + test_install zfs-testing $ALTHOST + test_install zfs-testing-kmod $ALTHOST + ;; +fedora*) + url='https://raw.githubusercontent.com/openzfs/openzfs-docs/refs/heads/master/docs/Getting%20Started/Fedora/index.rst' + name=$(curl -Ls $url | grep 'dnf install' | grep -Eo 'zfs-release-[0-9]+-[0-9]+') + sudo dnf -y install -y https://zfsonlinux.org/fedora/$name$(rpm --eval "%{dist}").noarch.rpm + test_install zfs $ALTHOST + ;; +esac +echo "##[endgroup]" + +# Write out a simple version of the summary here. Later on we will collate all +# the summaries and put them into a nice table in the workflow Summary page. +echo "Summary: " +cat $SUMMARY diff --git a/.github/workflows/scripts/qemu-wait-for-vm.sh b/.github/workflows/scripts/qemu-wait-for-vm.sh new file mode 100755 index 000000000000..e8afdb3f7b98 --- /dev/null +++ b/.github/workflows/scripts/qemu-wait-for-vm.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# +# Wait for a VM to boot up and become active. This is used in a number of our +# scripts. +# +# $1: VM hostname or IP address + +while pidof /usr/bin/qemu-system-x86_64 >/dev/null; do + ssh 2>/dev/null zfs@$1 "uname -a" && break +done diff --git a/.github/workflows/scripts/replace-dupes-with-symlinks.sh b/.github/workflows/scripts/replace-dupes-with-symlinks.sh new file mode 100755 index 000000000000..5412c954ad2f --- /dev/null +++ b/.github/workflows/scripts/replace-dupes-with-symlinks.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# +# Recursively go though a directory structure and replace duplicate files with +# symlinks. This cuts down our RPM repo size by ~25%. +# +# replace-dupes-with-symlinks.sh [DIR] +# +# DIR: Directory to traverse. Defaults to current directory if not specified. +# + +src="$1" +if [ -z "$src" ] ; then + src="." +fi + +declare -A db + +pushd "$src" +while read line ; do + bn="$(basename $line)" + if [ -z "${db[$bn]}" ] ; then + # First time this file has been seen + db[$bn]="$line" + else + if diff -b "$line" "${db[$bn]}" &>/dev/null ; then + # Files are the same, make a symlink + rm "$line" + ln -sr "${db[$bn]}" "$line" + fi + fi +done <<< "$(find . -type f)" +popd diff --git a/.github/workflows/zfs-qemu-packages.yml b/.github/workflows/zfs-qemu-packages.yml new file mode 100644 index 000000000000..e4dd29581825 --- /dev/null +++ b/.github/workflows/zfs-qemu-packages.yml @@ -0,0 +1,140 @@ +# This workflow is used to build and test RPM packages. It is a +# 'workflow_dispatch' workflow, which means it gets run manually. +# +# The workflow has a dropdown menu with two options: +# +# Build RPMs - Build release RPMs and tarballs and put them into an artifact +# ZIP file. The directory structure used in the ZIP file mirrors +# the ZFS yum repo. +# +# Test repo - Test install the ZFS RPMs from the ZFS repo. On EL distos, this +# will do a DKMS and KMOD test install from both the regular and +# testing repos. On Fedora, it will do a DKMS install from the +# regular repo. All test install results will be displayed in the +# Summary page. Note that the workflow provides an optional text +# text box where you can specify the full URL to an alternate repo. +# If left blank, it will install from the default repo from the +# zfs-release RPM (http://download.zfsonlinux.org). +# +# Most users will never need to use this workflow. It will be used primary by +# ZFS admins for building and testing releases. +# +name: zfs-qemu-packages + +on: + workflow_dispatch: + inputs: + test_type: + type: choice + required: false + default: "Build RPMs" + description: "Build RPMs or test the repo?" + options: + - "Build RPMs" + - "Test repo" + repo_url: + type: string + required: false + default: "" + description: "(optional) repo URL (blank: use http://download.zfsonlinux.org)" +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + zfs-qemu-packages-jobs: + name: qemu-VMs + strategy: + fail-fast: false + matrix: + os: ['almalinux8', 'almalinux9', 'fedora40', 'fedora41'] + 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: | + .github/workflows/scripts/qemu-3-deps.sh ${{ matrix.os }} + + - name: Build modules or Test repo + timeout-minutes: 30 + run: | + set -e + if [ "${{ github.event.inputs.test_type }}" == "Test repo" ] ; then + # Bring VM back up and copy over zfs source + .github/workflows/scripts/qemu-prepare-for-build.sh + + mkdir -p /tmp/repo + ssh zfs@vm0 '$HOME/zfs/.github/workflows/scripts/qemu-test-repo-vm.sh' ${{ github.event.inputs.repo_url }} + else + .github/workflows/scripts/qemu-4-build.sh --repo --release --dkms --tarball ${{ matrix.os }} + fi + + - name: Prepare artifacts + if: always() + timeout-minutes: 10 + run: | + rsync -a zfs@vm0:/tmp/repo /tmp || true + .github/workflows/scripts/replace-dupes-with-symlinks.sh /tmp/repo + tar -cf ${{ matrix.os }}-repo.tar -C /tmp repo + + - uses: actions/upload-artifact@v4 + id: artifact-upload + if: always() + with: + name: ${{ matrix.os }}-repo + path: ${{ matrix.os }}-repo.tar + compression-level: 0 + retention-days: 2 + if-no-files-found: ignore + + combine_repos: + if: always() + needs: [zfs-qemu-packages-jobs] + name: "Results" + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + id: artifact-download + if: always() + - name: Test Summary + if: always() + run: | + for i in $(find . -type f -iname "*.tar") ; do + tar -xf $i -C /tmp + done + tar -cf all-repo.tar -C /tmp repo + + # If we're installing from a repo, print out the summary of the versions + # that got installed using Markdown. + if [ "${{ github.event.inputs.test_type }}" == "Test repo" ] ; then + cd /tmp/repo + for i in $(ls *.txt) ; do + nicename="$(echo $i | sed 's/.txt//g; s/-/ /g')" + echo "### $nicename" >> $GITHUB_STEP_SUMMARY + echo "|repo|RPM|URL|" >> $GITHUB_STEP_SUMMARY + echo "|:---|:---|:---|" >> $GITHUB_STEP_SUMMARY + awk '{print "|"$1"|"$2"|"$3"|"}' $i >> $GITHUB_STEP_SUMMARY + done + fi + + - uses: actions/upload-artifact@v4 + id: artifact-upload2 + if: always() + with: + name: all-repo + path: all-repo.tar + compression-level: 0 + retention-days: 5 + if-no-files-found: ignore diff --git a/.github/workflows/zfs-qemu.yml b/.github/workflows/zfs-qemu.yml index af26e135b91f..cf466bcf1aa3 100644 --- a/.github/workflows/zfs-qemu.yml +++ b/.github/workflows/zfs-qemu.yml @@ -1,203 +1,180 @@ name: zfs-qemu on: push: pull_request: workflow_dispatch: inputs: include_stream9: type: boolean required: false default: false description: 'Test on CentOS 9 stream' include_stream10: type: boolean required: false default: false description: 'Test on CentOS 10 stream' concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: test-config: name: Setup runs-on: ubuntu-24.04 outputs: test_os: ${{ steps.os.outputs.os }} ci_type: ${{ steps.os.outputs.ci_type }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Generate OS config and CI type id: os run: | FULL_OS='["almalinux8", "almalinux9", "debian11", "debian12", "fedora40", "fedora41", "freebsd13-3r", "freebsd13-4s", "freebsd14-1r", "freebsd14-2s", "freebsd15-0c", "ubuntu20", "ubuntu22", "ubuntu24"]' QUICK_OS='["almalinux8", "almalinux9", "debian12", "fedora41", "freebsd13-3r", "freebsd14-2r", "ubuntu24"]' # determine CI type when running on PR ci_type="full" if ${{ github.event_name == 'pull_request' }}; then head=${{ github.event.pull_request.head.sha }} base=${{ github.event.pull_request.base.sha }} ci_type=$(python3 .github/workflows/scripts/generate-ci-type.py $head $base) fi if [ "$ci_type" == "quick" ]; then os_selection="$QUICK_OS" else os_selection="$FULL_OS" fi os_json=$(echo ${os_selection} | jq -c) - + # Add optional runners if [ "${{ github.event.inputs.include_stream9 }}" == 'true' ]; then os_json=$(echo $os_json | jq -c '. += ["centos-stream9"]') fi if [ "${{ github.event.inputs.include_stream10 }}" == 'true' ]; then os_json=$(echo $os_json | jq -c '. += ["centos-stream10"]') fi - + echo $os_json echo "os=$os_json" >> $GITHUB_OUTPUT echo "ci_type=$ci_type" >> $GITHUB_OUTPUT - - - qemu-vm: name: qemu-x86 needs: [ test-config ] strategy: fail-fast: false matrix: # rhl: almalinux8, almalinux9, centos-stream9, fedora40, fedora41 # debian: debian11, debian12, ubuntu20, ubuntu22, ubuntu24 # misc: archlinux, tumbleweed # FreeBSD variants of 2024-12: # FreeBSD Release: freebsd13-3r, freebsd13-4r, freebsd14-1r, freebsd14-2r # FreeBSD Stable: freebsd13-4s, freebsd14-2s # FreeBSD Current: freebsd15-0c os: ${{ fromJson(needs.test-config.outputs.test_os) }} 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 + run: .github/workflows/scripts/qemu-3-deps.sh ${{ matrix.os }} - 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 }} + run: .github/workflows/scripts/qemu-4-build.sh --poweroff --enable-debug ${{ 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 env: CI_TYPE: ${{ needs.test-config.outputs.ci_type }} - 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: always() run: .github/workflows/scripts/qemu-8-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-9-summary-page.sh - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 2 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 3 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 4 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 5 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 6 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 7 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 8 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 9 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 10 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 11 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 12 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 13 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 14 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 15 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 16 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 17 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 18 - name: Generating summary... run: .github/workflows/scripts/qemu-9-summary-page.sh 19 - uses: actions/upload-artifact@v4 with: name: Summary Files path: out-* diff --git a/.github/workflows/zloop.yml b/.github/workflows/zloop.yml index 90d93c48e4bd..7b3bf49d90d5 100644 --- a/.github/workflows/zloop.yml +++ b/.github/workflows/zloop.yml @@ -1,77 +1,77 @@ name: zloop on: push: pull_request: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: zloop: runs-on: ubuntu-24.04 env: TEST_DIR: /var/tmp/zloop steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies run: | sudo apt-get purge -y snapd google-chrome-stable firefox - ONLY_DEPS=1 .github/workflows/scripts/qemu-3-deps.sh ubuntu24 + ONLY_DEPS=1 .github/workflows/scripts/qemu-3-deps-vm.sh ubuntu24 - name: Autogen.sh run: | sed -i '/DEBUG_CFLAGS="-Werror"/s/^/#/' config/zfs-build.m4 ./autogen.sh - name: Configure run: | ./configure --prefix=/usr --enable-debug --enable-debuginfo \ --enable-asan --enable-ubsan \ --enable-debug-kmem --enable-debug-kmem-tracking - name: Make run: | make -j$(nproc) - name: Install run: | sudo make install sudo depmod sudo modprobe zfs - name: Tests run: | sudo mkdir -p $TEST_DIR # run for 10 minutes or at most 6 iterations for a maximum runner # time of 60 minutes. sudo /usr/share/zfs/zloop.sh -t 600 -I 6 -l -m 1 -- -T 120 -P 60 - name: Prepare artifacts if: failure() run: | sudo chmod +r -R $TEST_DIR/ - name: Ztest log if: failure() run: | grep -B10 -A1000 'ASSERT' $TEST_DIR/*/ztest.out || tail -n 1000 $TEST_DIR/*/ztest.out - name: Gdb log if: failure() run: | sed -n '/Backtraces (full)/q;p' $TEST_DIR/*/ztest.gdb - name: Zdb log if: failure() run: | cat $TEST_DIR/*/ztest.zdb - uses: actions/upload-artifact@v4 if: failure() with: name: Logs path: | /var/tmp/zloop/*/ !/var/tmp/zloop/*/vdev/ if-no-files-found: ignore - uses: actions/upload-artifact@v4 if: failure() with: name: Pool files path: | /var/tmp/zloop/*/vdev/ if-no-files-found: ignore