From: Vincent Fu Date: Fri, 6 Sep 2024 18:52:01 +0000 (+0000) Subject: ci: build and run a QEMU guest VM for testing X-Git-Tag: fio-3.38~12 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=12c4b854a34414bad23ef613efece7caca82445e;p=fio.git ci: build and run a QEMU guest VM for testing Since GitHub Actions' free runners now support nested virtualization, let's create a guest VM image and use it to run some tests that cannot be run directly via a GitHub Actions runner (because these runners do not allow insertion of kernel modules). This patch adds a workflow that runs nightly and: - creates a Debian guest VM image using libguestfs - builds QEMU - starts the VM - clones/builds fio on the VM - runs the test Separate instances of the job are spawned to run the following tests: - basic io_uring_cmd - NVMe protection information w/16-bit Guard PI - NVMe PI 4096+16 w/64-bit Guard PI - NVMe PI 4096+64 w/64-bit Guard PI - FDP - t/zbd/run-tests-against-nullb Signed-off-by: Vincent Fu --- diff --git a/.github/actions/build-qemu/action.yml b/.github/actions/build-qemu/action.yml new file mode 100644 index 00000000..06804b8b --- /dev/null +++ b/.github/actions/build-qemu/action.yml @@ -0,0 +1,31 @@ +name: 'Build and Install QEMU on Ubuntu' +desription: 'Build QEMU and Install on Ubuntu' + +inputs: + version: # What QEMU version to build/install + description: 'QEMU version to build and install' + required: false + default: '9.1.0' + + +runs: + using: "composite" + steps: + - name: Install QEMU build dependencies + run: sudo apt-get -qq install libglib2.0-dev libfdt-dev libpixman-1-dev ninja-build flex bison libsdl2-dev libaio-dev python3-tomli libslirp-dev + shell: bash + + - name: Build and install QEMU + run: | + wget -nv https://download.qemu.org/qemu-$INPUT_VER.tar.xz + tar xJf qemu-$INPUT_VER.tar.xz + rm qemu-$INPUT_VER.tar.xz + cd qemu-$INPUT_VER + ./configure --enable-kvm --target-list=x86_64-softmmu + make -j $(nproc) + sudo make install + cd .. + rm -rf qemu-$INPUT_VER + shell: bash + env: + INPUT_VER: ${{ inputs.version }} diff --git a/.github/actions/create-guest-image/action.yml b/.github/actions/create-guest-image/action.yml new file mode 100644 index 00000000..ce413378 --- /dev/null +++ b/.github/actions/create-guest-image/action.yml @@ -0,0 +1,45 @@ +name: 'Create guest image' +description: 'Create VM guest image on Ubuntu runner' + +inputs: + distro: + description: 'Linux distribution to use for guest image' + required: false + default: 'debian-12' + extra_pkgs: + description: 'Extra packages to install for guest image' + required: false + default: + +runs: + using: "composite" + steps: + - name: Install libguestfs + run: sudo apt-get -qq install libguestfs-tools + shell: bash + - name: Setup steps for virt-builder + run: | + sudo chmod a+r /boot/vmlinuz* + sudo chmod 0666 /dev/kvm + ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa + shell: bash + - name: Create Debian image + run: | + virt-builder ${{ inputs.distro }} \ + --quiet \ + --hostname fio-tester \ + --ssh-inject root \ + --run-command "ssh-keygen -A" \ + --run-command "sed -i 's/ens2/enp0s2/g' /etc/network/interfaces" \ + --append-line '/etc/environment:PYTHONUNBUFFERED=1' \ + --append-line '/etc/environment:GITHUB_SERVER_URL=${{ github.server_url }}' \ + --append-line '/etc/environment:GITHUB_REPOSITORY=${{ github.repository }}' \ + --append-line '/etc/environment:GITHUB_REF=${{ github.ref }}' \ + --append-line '/etc/environment:GITHUB_SHA=${{ github.sha }}' \ + --append-line '/etc/environment:GITHUB_JOB=${{ github.job }}' \ + --append-line '/etc/environment:EXTRA_PKGS=${{ inputs.extra_pkgs }}' \ + --append-line '/etc/environment:CI_TARGET_BUILD=${{ env.CI_TARGET_BUILD }}' \ + --append-line '/etc/environment:CI_TARGET_OS=${{ env.CI_TARGET_OS }}' + + shell: bash + diff --git a/.github/actions/start-vm/action.yml b/.github/actions/start-vm/action.yml new file mode 100644 index 00000000..d47977c4 --- /dev/null +++ b/.github/actions/start-vm/action.yml @@ -0,0 +1,54 @@ +name: 'Start QEMU VM' +description: 'Start QEMU virtual machine' + +inputs: + qemu: # QEMU binary to use + required: false + default: "qemu-system-x86_64" + image: # VM image file + required: true + ssh_fwd_port: # forward this host port to the guest's SSH port + required: false + default: 2022 + options: # Custom QEMU invocation options no \n at the end! + required: false + ram: # how much RAM to allocate to VM + required: false + default: "12G" + host_key: # If true add guest host key to known_hosts + required: false + default: "false" + +runs: + using: "composite" + steps: + - name: install wait-for-it + shell: bash + run: sudo apt-get -qq install wait-for-it + - name: Start VM in background + shell: bash + run: | + ${{ inputs.qemu }} \ + -cpu host \ + -drive file=${{ inputs.image }},format=raw,if=virtio \ + -enable-kvm \ + -smp $(nproc) \ + -nographic \ + -m ${{ inputs.ram }} \ + -display none \ + -machine q35,accel=kvm \ + -nic user,model=virtio-net-pci,hostfwd=tcp::${{ inputs.ssh_fwd_port }}-:22 \ + ${{ inputs.options }} \ + & + - name: Wait for VM to boot + shell: bash + run: | + wait-for-it localhost:${{ inputs.ssh_fwd_port }} -t 15 + sleep 3 + - name: Add guest host key to known_hosts + shell: bash + run: | + if echo ${{ inputs.host_key }} | grep -c "true" + then + ssh root@localhost -p ${{ inputs.ssh_fwd_port }} -o StrictHostKeyChecking=no echo + fi diff --git a/.github/workflows/qemu.yml b/.github/workflows/qemu.yml new file mode 100644 index 00000000..4ba8bfae --- /dev/null +++ b/.github/workflows/qemu.yml @@ -0,0 +1,104 @@ +name: CI + +on: + schedule: + - cron: "50 3 * * *" # daily at 4:50 UTC (00:50 EST) + +jobs: + qemu-guest: + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + include: + - config: basic io_uring_cmd tests + device: >- + -device nvme,id=nvme0,serial=deadbeef + -drive id=nvm-0,file=nvme0.img,format=raw,if=none,discard=unmap,media=disk + -device nvme-ns,id=nvm-0,drive=nvm-0,bus=nvme0,nsid=1 + test_cmd: "python3 t/run-fio-tests.py --nvmecdev /dev/ng0n1 --run-only 1014 1015" + extra_pkgs: "nvme-cli" + - config: 16-bit Guard PI tests (long) + device: >- + -device nvme,id=nvme0,serial=deadbeef + -drive id=nvm-0,file=nvme0.img,format=raw,if=none,discard=unmap,media=disk + -device nvme-ns,id=nvm-0,drive=nvm-0,bus=nvme0,nsid=1 + test_cmd: "python3 t/nvmept_pi.py --fio ./fio --dut /dev/ng0n1" + extra_pkgs: "nvme-cli" + - config: 4K+16 w/64-bit Guard PI + device: >- # 4K+16 w/64-bit Guard PI + -device nvme,id=nvme1,serial=deadbeee + -drive id=nvm-1,file=nvme0.img,format=raw,if=none,discard=unmap,media=disk + -device nvme-ns,id=nvm-1,drive=nvm-1,bus=nvme1,nsid=1,pif=2,ms=16,mset=1,pi=1,pil=0,logical_block_size=4096,physical_block_size=4096 + test_cmd: "python3 t/nvmept_pi.py --fio ./fio --dut /dev/ng0n1 --lbaf 6" + extra_pkgs: "nvme-cli" + - config: 4K+64 w/64-bit Guard PI + device: >- + -device nvme,id=nvme2,serial=deadeeef + -drive id=nvm-2,file=nvme0.img,format=raw,if=none,discard=unmap,media=disk + -device nvme-ns,id=nvm-2,drive=nvm-2,bus=nvme2,nsid=1,pif=2,ms=64,mset=1,pi=1,pil=0,logical_block_size=4096,physical_block_size=4096 + test_cmd: "python3 t/nvmept_pi.py --fio ./fio --dut /dev/ng0n1 --lbaf 7" + extra_pkgs: "nvme-cli" + - config: FDP + device: >- + -device nvme-subsys,id=nvme-subsys0,fdp=on,fdp.runs=128K,fdp.nrg=8,fdp.nruh=64 + -device nvme,id=nvme0,serial=deadbeef,subsys=nvme-subsys0 + -drive id=nvm-1,file=nvme0.img,format=raw,if=none,discard=unmap,media=disk + -device nvme-ns,id=nvm-1,drive=nvm-1,bus=nvme0,nsid=1,logical_block_size=4096,physical_block_size=4096,fdp.ruhs=0-63 + test_cmd: "nvme fdp status /dev/ng0n1 && python3 t/nvmept_fdp.py --fio ./fio --dut /dev/ng0n1" + extra_pkgs: "nvme-cli" + - config: ZBD + device: + test_cmd: "./t/zbd/run-tests-against-nullb" + extra_pkgs: sg3-utils + + env: + DISTRO: debian-12 + SSHCMD: ssh root@localhost -p 2022 + CI_TARGET_BUILD: linux + CI_TARGET_OS: debian + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Create guest VM image + uses: ./.github/actions/create-guest-image + with: + distro: ${{ env.DISTRO }} + extra_pkgs: ${{ matrix.extra_pkgs }} + + - name: Build and install QEMU + uses: ./.github/actions/build-qemu + + - name: Create backing file for NVMe device + run: truncate -s 1G nvme0.img + + - name: Start VM + uses: ./.github/actions/start-vm + with: + image: ${{ env.DISTRO }}.img + host_key: true + options: ${{ matrix.device }} + + - name: Clone fio on guest + run: | + $SSHCMD "apt-get update && apt-get install -qq git" + $SSHCMD "git clone https://github.com/taiki-e/checkout-action --branch v1.3.0" + $SSHCMD "mkdir fio && cd fio && ../checkout-action/main.sh && git log -1" + + - name: Install dependencies on guest + run: $SSHCMD "cd fio && ./ci/actions-install.sh" + + - name: Build fio on guest + run: $SSHCMD "cd fio && ./ci/actions-build.sh" + + - name: Show nvme device configuration + if: ${{ contains( matrix.extra_pkgs, 'nvme-cli' ) }} + run: | + $SSHCMD "nvme id-ns /dev/ng0n1 -H" + $SSHCMD "nvme nvm-id-ns /dev/ng0n1 -v" + + - name: Run test + run: $SSHCMD "cd fio && ${{ matrix.test_cmd }}" diff --git a/ci/actions-install.sh b/ci/actions-install.sh index 5ad7b959..5a32ec91 100755 --- a/ci/actions-install.sh +++ b/ci/actions-install.sh @@ -82,8 +82,9 @@ DPKGCFG python3-sphinx python3-statsmodels sudo + ${EXTRA_PKGS:-} ) - if [ "${GITHUB_JOB}" == "build-containers" ]; then + if [ "${GITHUB_JOB}" == "build-containers" ] || [ "${GITHUB_JOB}" == "qemu-guest" ]; then pkgs+=( bison build-essential @@ -121,6 +122,7 @@ install_fedora() { python3-sphinx sudo valgrind-devel + ${EXTRA_PKGS:-} ) case "${CI_TARGET_OS}" in