Skip to content

Commit

Permalink
ci: build and run a QEMU guest VM for testing
Browse files Browse the repository at this point in the history
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 <vincent.fu@samsung.com>
  • Loading branch information
vincentkfu committed Sep 26, 2024
1 parent 0710fce commit 12c4b85
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 1 deletion.
31 changes: 31 additions & 0 deletions .github/actions/build-qemu/action.yml
Original file line number Diff line number Diff line change
@@ -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 }}
45 changes: 45 additions & 0 deletions .github/actions/create-guest-image/action.yml
Original file line number Diff line number Diff line change
@@ -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

54 changes: 54 additions & 0 deletions .github/actions/start-vm/action.yml
Original file line number Diff line number Diff line change
@@ -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
104 changes: 104 additions & 0 deletions .github/workflows/qemu.yml
Original file line number Diff line number Diff line change
@@ -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 }}"
4 changes: 3 additions & 1 deletion ci/actions-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -121,6 +122,7 @@ install_fedora() {
python3-sphinx
sudo
valgrind-devel
${EXTRA_PKGS:-}
)

case "${CI_TARGET_OS}" in
Expand Down

0 comments on commit 12c4b85

Please sign in to comment.