-
Notifications
You must be signed in to change notification settings - Fork 2k
CI: add draft xfstests workflow #18845
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| ###################################################################### | ||
| # Bake xfstests into the build VM image. | ||
| # | ||
| # Runs on the build machine (vm0) AFTER ZFS has been built and installed | ||
| # (qemu-4-build.sh, without --poweroff) | ||
| # Called on the runner as: | ||
| # ssh zfs@vm0 '$HOME/zfs/.github/workflows/scripts/qemu-xfstests-bake-vm.sh' $OS | ||
| # | ||
| # The script powers the VM off at the end (like qemu-4-build-vm.sh --poweroff) | ||
| ###################################################################### | ||
|
|
||
| set -eu | ||
|
|
||
| OS="$1" | ||
|
|
||
| # TODO: move the sources under openzfs | ||
| XFSTESTS_REPO="${XFSTESTS_REPO:-https://github.com/implr/xfstests}" | ||
| XFSTESTS_BRANCH="${XFSTESTS_BRANCH:-zfs}" | ||
|
|
||
| echo "##[group]Install xfstests dependencies" | ||
| case "$OS" in | ||
| debian*|ubuntu*) | ||
| sudo apt-get update | ||
| # Build toolchain + xfstests build/runtime deps | ||
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ | ||
| git build-essential autoconf automake libtool pkg-config gettext \ | ||
| uuid-dev libattr1-dev libacl1-dev libaio-dev libgdbm-dev libssl-dev \ | ||
| xfsprogs e2fsprogs attr acl quota gdisk parted | ||
| # optional extras for a couple tests | ||
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -y fio dbench || true | ||
| ;; | ||
| *) | ||
| echo "xfstests bake is only implemented for debian/ubuntu so far" >&2 | ||
| exit 1 | ||
| ;; | ||
| esac | ||
| echo "##[endgroup]" | ||
|
|
||
| echo "##[group]Create xfstests service users" | ||
| # xfstests insists on these accounts. Digit-leading name | ||
| # needs --badnames on modern shadow-utils. | ||
| sudo groupadd -f fsgqa | ||
| for u in fsgqa fsgqa2 123456-fsgqa; do | ||
| if ! id "$u" &>/dev/null; then | ||
| sudo useradd --badnames -g fsgqa -m "$u" 2>/dev/null \ | ||
| || sudo useradd -g fsgqa -m "$u" 2>/dev/null || true | ||
| fi | ||
| done | ||
|
|
||
| # xfstests runs as root and drops to fsgqa via `su` (common/rc _user_do/_su). | ||
| # Installing OpenZFS pulls in libpam-zfs, which registers pam_zfs_key.so in the | ||
| # PAM stack to unlock users' encrypted home datasets at login. Its *session* | ||
| # hook prompts "Password:" when root su's to fsgqa (to derive the key for the | ||
| # nonexistent rpool/home/fsgqa), and that prompt lands in test output and fails | ||
| # every _user_do-based test (generic/123, 128, 314, ...). We don't use encrypted | ||
| # homes here, so strip pam_zfs_key from the PAM config. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternately, OpenZFS could be built with |
||
| sudo pam-auth-update --package --remove zfs_key 2>/dev/null || true | ||
| sudo sed -i '/pam_zfs_key/d' \ | ||
| /etc/pam.d/common-auth /etc/pam.d/common-session \ | ||
| /etc/pam.d/common-password /etc/pam.d/common-account 2>/dev/null || true | ||
| echo "##[endgroup]" | ||
|
|
||
| echo "##[group]Clone + build xfstests ($XFSTESTS_BRANCH)" | ||
| rm -rf "$HOME/xfstests" | ||
| git clone --depth 1 -b "$XFSTESTS_BRANCH" "$XFSTESTS_REPO" "$HOME/xfstests" | ||
| cd "$HOME/xfstests" | ||
| make -j"$(nproc)" | ||
| echo "xfstests baked at $HOME/xfstests ($(git rev-parse --short HEAD))" | ||
| echo "##[endgroup]" | ||
|
|
||
| # reset cloud-init and power off | ||
| sudo cloud-init clean --logs | ||
| sync && sleep 2 && sudo poweroff & | ||
| exit 0 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| ###################################################################### | ||
| # Collect xfstests results off the test VM, tar them for upload, and | ||
| # write a short GitHub job summary. Runs on the runner; always() in the | ||
| # workflow so we still grab logs (and the console) on a guest crash. | ||
| ###################################################################### | ||
|
|
||
| set -eu | ||
|
|
||
| source /var/tmp/env.txt | ||
| RES="$RESPATH" # /var/tmp/test_results | ||
| mkdir -p "$RES" | ||
|
|
||
| # Pull results + logs off vm1 (best-effort; the VM may have crashed). | ||
| rsync -arL zfs@vm1:xfstests/results "$RES/" 2>/dev/null || true | ||
| scp zfs@vm1:xfstests/local.config "$RES/" 2>/dev/null || true | ||
| scp 'zfs@vm1:/var/tmp/dmesg-*.txt' "$RES/" 2>/dev/null || true | ||
| scp 'zfs@vm1:/var/tmp/tests-exitcode.txt' "$RES/" 2>/dev/null || true | ||
| cp -f /var/tmp/xfstests-run.log "$RES/" 2>/dev/null || true | ||
| # qemu-5-setup.sh already streams the VM serial console to $RES/vm1/console.txt. | ||
|
|
||
| TARNAME="xfstests-$OS" | ||
| TAR="/tmp/$TARNAME.tar.bz2" | ||
| mv "$RES" "$(dirname "$RES")/$TARNAME" | ||
| tar cjf "$TAR" -C "$(dirname "$RES")" -h "$TARNAME" || true | ||
| mv "$(dirname "$RES")/$TARNAME" "$RES" | ||
|
|
||
| # --- Job summary ---------------------------------------------------- | ||
| SUMMARY="${GITHUB_STEP_SUMMARY:-/dev/stdout}" | ||
| { | ||
| echo "## xfstests on ${OSNAME:-$OS}" | ||
| echo | ||
| if [ -f "$RES/tests-exitcode.txt" ]; then | ||
| rv=$(cat "$RES/tests-exitcode.txt") | ||
| if [ "$rv" = "0" ]; then | ||
| echo ":thumbsup: \`./check\` exited 0 — all selected tests passed." | ||
| else | ||
| echo ":warning: \`./check\` exited $rv — failures (or a notrun treated as error)." | ||
| fi | ||
| else | ||
| echo ":interrobang: no exit code recorded — the VM may have crashed mid-run." | ||
| fi | ||
| echo | ||
|
|
||
| # xfstests prints a "Failures:" / "Passed all N tests" line near the end of | ||
| # results/check.log. Surface the tail. | ||
| if [ -f "$RES/results/check.log" ]; then | ||
| echo '<details><summary>check.log (tail)</summary>' | ||
| echo | ||
| echo '```' | ||
| tail -n 40 "$RES/results/check.log" | ||
| echo '```' | ||
| echo '</details>' | ||
| fi | ||
| } >> "$SUMMARY" 2>/dev/null || true | ||
|
|
||
| exit 0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| ###################################################################### | ||
| # Run xfstests | ||
| # | ||
| # - called with 'guest' -> runs inside the test VM (vm1) | ||
| # called on runner: qemu-xfstests-run.sh | ||
| # called on qemu-vm: qemu-xfstests-run.sh guest | ||
| # | ||
| ###################################################################### | ||
|
|
||
| set -eu | ||
|
|
||
| ############################ | ||
| # Runner side (no args) | ||
| ############################ | ||
| if [ -z "${1:-}" ]; then | ||
| source /var/tmp/env.txt | ||
| SCRIPT='$HOME/zfs/.github/workflows/scripts/qemu-xfstests-run.sh' | ||
| # Pass the user ./check arguments through to the guest. | ||
| ssh zfs@vm1 "OS='$OS' XFSTESTS_OPTIONS='${XFSTESTS_OPTIONS:-}' $SCRIPT guest" \ | ||
| 2>&1 | stdbuf -oL tee /var/tmp/xfstests-run.log | ||
| exit "${PIPESTATUS[0]}" | ||
| fi | ||
|
|
||
| ############################ | ||
| # VM side | ||
| ############################ | ||
| OS="${OS:?}" | ||
| OPTS="${XFSTESTS_OPTIONS:--g quick}" | ||
| export PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin" | ||
|
|
||
| sudo -E modprobe zfs | ||
|
|
||
| # Longer RCU timeouts (as in qemu-6-tests.sh) | ||
| rcu="/sys/module/rcupdate/parameters/rcu_cpu_stall_timeout" | ||
| test -f "$rcu" && echo 120 | sudo tee "$rcu" >/dev/null || true | ||
|
|
||
| # Carve the 64 GiB tests disk (attached by qemu-5-setup.sh as the 2nd virtio | ||
| # disk) into a TEST_DEV partition + three SCRATCH pool members. | ||
| DEV=/dev/vdb | ||
| sudo wipefs -a "$DEV" || true | ||
| sudo sgdisk -Z "$DEV" | ||
| sudo sgdisk -n1:0:+20G -n2:0:+14G -n3:0:+14G -n4:0:0 "$DEV" | ||
| sudo partprobe "$DEV" | ||
| sleep 2 | ||
|
|
||
| # Persistent test pool/dataset. | ||
| # (acltype=posix + xattr=sa are required for several generic/ tests). | ||
| sudo zpool create -f \ | ||
| -O mountpoint=legacy -O acltype=posix -O xattr=sa \ | ||
| -O compression=off -O relatime=off \ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I presume compression=off and relatime=off are required for some tests as well?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general for now I was aiming for the config that passes the maximum amount of tests with minimal changes.
|
||
| testpool "${DEV}1" | ||
| sudo zfs create -o mountpoint=legacy -o recordsize=64K testpool/testfs | ||
|
behlendorf marked this conversation as resolved.
|
||
|
|
||
| sudo mkdir -p /mnt/test /mnt/scratch | ||
| sudo mount -t zfs testpool/testfs /mnt/test | ||
|
|
||
| cd "$HOME/xfstests" | ||
| cat > local.config <<EOF | ||
| export FSTYP=zfs | ||
| export TEST_DEV=testpool/testfs | ||
| export TEST_DIR=/mnt/test | ||
| export SCRATCH_MNT=/mnt/scratch | ||
| export SCRATCH_ZPOOL_NAME=scratchpool | ||
| export SCRATCH_DEV_POOL="${DEV}2 ${DEV}3 ${DEV}4" | ||
| EOF | ||
|
|
||
| # Apply the ZFS exclude list only for group runs; when a caller names tests | ||
| # explicitly they want exactly those (e.g. debugging an excluded failure). | ||
| EXCLUDE="" | ||
| case "$OPTS" in | ||
| *-g*) EXCLUDE="-E exclude.zfs.txt" ;; | ||
| esac | ||
|
|
||
| sudo dmesg -c > /var/tmp/dmesg-prerun.txt || true | ||
|
|
||
| RV=0 | ||
| # shellcheck disable=SC2086 # word-splitting of OPTS/EXCLUDE is intentional | ||
| sudo HOST_OPTIONS="$PWD/local.config" ./check $EXCLUDE $OPTS || RV=$? | ||
| echo "$RV" | sudo tee /var/tmp/tests-exitcode.txt >/dev/null | ||
|
|
||
| sudo dmesg > /var/tmp/dmesg-postrun.txt || true | ||
| sync | ||
| exit "$RV" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| name: zfs-qemu-xfstests | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| os: | ||
| type: string | ||
| required: false | ||
| default: "ubuntu24" | ||
| description: "Distribution to test on (e.g. ubuntu24, debian13)" | ||
| xfstests_options: | ||
| type: string | ||
| required: false | ||
| default: "-g quick" | ||
| description: "Arguments for xfstests' ./check (e.g. '-g quick', '-g auto', 'generic/467')" | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| xfstests: | ||
| name: xfstests-${{ inputs.os }} | ||
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha }} | ||
|
|
||
| - name: Setup QEMU | ||
| timeout-minutes: 60 | ||
| run: .github/workflows/scripts/qemu-1-setup.sh | ||
|
|
||
| - name: Start build machine | ||
| timeout-minutes: 10 | ||
| run: | | ||
| .github/workflows/scripts/qemu-2-start.sh ${{ inputs.os }} | ||
| # force single vm for now | ||
| sed -i 's/^VMs=.*/VMs="1"/' /var/tmp/env.txt | ||
|
|
||
| - name: Install dependencies | ||
| timeout-minutes: 60 | ||
| run: .github/workflows/scripts/qemu-3-deps.sh --poweroff ${{ inputs.os }} | ||
|
|
||
| # NOTE: no --poweroff here, unlike zfs-qemu.yml — we keep vm0 up so the | ||
| # bake step can install xfstests before the image is snapshotted. | ||
| - name: Build modules | ||
| timeout-minutes: 30 | ||
| run: .github/workflows/scripts/qemu-4-build.sh --enable-debug ${{ inputs.os }} | ||
|
|
||
| - name: Bake xfstests into image | ||
| timeout-minutes: 30 | ||
| run: ssh zfs@vm0 '$HOME/zfs/.github/workflows/scripts/qemu-xfstests-bake-vm.sh' ${{ inputs.os }} | ||
|
|
||
| - name: Setup testing machines | ||
| timeout-minutes: 5 | ||
| run: .github/workflows/scripts/qemu-5-setup.sh | ||
|
|
||
| - name: Run xfstests | ||
| timeout-minutes: 270 | ||
| run: .github/workflows/scripts/qemu-xfstests-run.sh | ||
| env: | ||
| XFSTESTS_OPTIONS: ${{ inputs.xfstests_options }} | ||
|
|
||
| - name: Prepare artifacts | ||
| if: always() | ||
| timeout-minutes: 10 | ||
| run: .github/workflows/scripts/qemu-xfstests-prepare.sh | ||
|
|
||
| - uses: actions/upload-artifact@v7 | ||
| id: artifact-upload | ||
| if: always() | ||
| with: | ||
| name: xfstests-${{ inputs.os }} | ||
| path: /tmp/xfstests-${{ inputs.os }}.tar.bz2 | ||
| archive: false | ||
| if-no-files-found: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy to create the repository under the openzfs organization so we have an official home for it. It looks like things are working well enough that it wouldn't be inconvenient. Just let me know when you're ready for this.