Skip to content
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

Support testing different kernel versions #1100

Merged
merged 5 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Pull request integration tests on VM 5.15 x86_64
rafaelroquetto marked this conversation as resolved.
Show resolved Hide resolved

on:
push:
branches: [ 'main', 'release-*' ]
paths: [ 'bpf/**' ]
pull_request:
branches: [ 'main', 'release-*' ]
paths: [ 'bpf/**' ]

jobs:
test:
uses: ./.github/workflows/workflow_integration_tests_vm.yml
with:
arch: x86_64
kernel-version: 5.15.152
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Pull request integration tests on VM 6.10 x86_64

on:
push:
branches: [ 'main', 'release-*' ]
paths: [ 'bpf/**' ]
pull_request:
branches: [ 'main', 'release-*' ]
paths: [ 'bpf/**' ]

jobs:
test:
uses: ./.github/workflows/workflow_integration_tests_vm.yml
with:
arch: x86_64
kernel-version: 6.10.6
49 changes: 49 additions & 0 deletions .github/workflows/workflow_integration_tests_vm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Pull request integration tests on VM

on:
workflow_call:
inputs:
arch:
description: 'Target architecture to run the tests'
required: true
type: string
kernel-version:
description: 'Kernel version to use when running the tests'
required: true
type: string
jobs:
test:
name: test
runs-on: ubuntu-latest
strategy:
matrix:
go: [ '1.22' ]
steps:
- uses: actions/checkout@v3
- name: Clean up disk space
run: |
docker system prune -af
docker volume prune -f
- name: Install QEMU
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends qemu-utils qemu-system-x86
- name: Run VM integration tests
run: |
sudo make -C test/vm KERNEL_VER=${{ inputs.kernel-version }} ARCH=${{ inputs.arch }} && [ -f testoutput/success ]
timeout-minutes: 60
- name: Upload integration test logs
uses: actions/upload-artifact@v3
if: always()
with:
name: Test Logs
path: |
testoutput/*.log
testoutput/kind
- name: Report coverage
uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
file: ./testoutput/itest-covdata.txt
flags: integration-test
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@ run-integration-test-k8s:
go clean -testcache
go test -p 1 -failfast -v -timeout 60m -mod vendor -a ./test/integration/... --tags=integration_k8s

.PHONY: run-integration-test-vm
run-integration-test-vm:
@echo "### Running integration tests"
go test -p 1 -failfast -v -timeout 60m -mod vendor -a ./test/integration/... --tags=integration -run "^TestMultiProcess"

.PHONY: integration-test
integration-test: prereqs prepare-integration-test
$(MAKE) run-integration-test || (ret=$$?; $(MAKE) cleanup-integration-test && exit $$ret)
Expand Down
81 changes: 81 additions & 0 deletions test/vm/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
FROM golang:1.23-rc-alpine

# this is the toplevel Makefile target to be invoked
# see the contents of 'startup.sh' at the end of this file
ARG target=run-integration-test-vm

RUN apk update
RUN apk add --no-cache openrc
RUN apk add --no-cache docker
RUN apk add --no-cache docker-compose
RUN apk add --no-cache git
RUN apk add --no-cache make
RUN apk add --no-cache agetty
RUN apk add --no-cache openssh
RUN apk add --no-cache shadow
RUN ssh-keygen -A

# the default root password is 'root'
RUN echo "root:root" | chpasswd
RUN sed -i 's/^#PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config

RUN rc-update add localmount default
RUN rc-update add docker default

# not strictly required, but useful for debugging
RUN rc-update add sshd default

# enable auto root login
RUN echo ttyS0::respawn:/sbin/agetty --autologin root ttyS0 vt100 >> /etc/inittab

RUN mkdir -p /overlay/upper/testoutput /overlay/work
RUN mkdir /build
RUN mkdir /beyla

RUN cat <<EOF >> /etc/fstab
beyla /beyla 9p trans=virtio,version=9p2000.L 0 0
overlay /build overlay lowerdir=/beyla,upperdir=/overlay/upper,workdir=/overlay/work 0 0
tmpfs /tmp tmpfs rw,nodev,nosuid 0 0
devpts /dev/pts devpts defaults 0 0
tmpfs /run tmpfs defaults,size=4G 0 0
testout /build/testoutput 9p trans=virtio,version=9p2000.L 0 0
EOF

RUN echo beyla > /etc/hostname

RUN cat <<EOF > /etc/network/interfaces
auto eth0
iface eth0 inet dhcp

auto lo
iface lo inet loopback
EOF

RUN rc-update add networking default

RUN cat <<EOF > /etc/init.d/startup
#!/sbin/openrc-run

command="sh /startup.sh"
EOF

RUN chmod +x /etc/init.d/startup

# comment out this line to get a prompt instead
# of running the tests when the VM starts
RUN rc-update add startup default

RUN cat <<EOF > /startup.sh
#!/bin/sh

export PATH=$PATH:/usr/local/go/bin

if [[ -n "$target" ]]; then
cd /build && make $target && touch /build/testoutput/success
poweroff
else
echo "Entering interactive mode"
fi
EOF

RUN chmod +x /startup.sh
59 changes: 59 additions & 0 deletions test/vm/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
WORKDIR ?= $(HOME)
ARCH ?= x86_64
KERNEL_VER ?= 6.10.6
KERNEL ?= kernels/$(ARCH)/vmlinuz-linux-$(KERNEL_VER)
TARBALL ?= /tmp/rootfs.tar
# do NOT put ROOT_IMG on a tmpfs backed fs
ROOT_IMG ?= $(WORKDIR)/rootfs.qcow2
ROOT_IMAGE_RAW ?= $(WORKDIR)/rootfs.raw
REPO_ROOT ?= ../..
TARGET_TEST ?= run-integration-test-vm
TEST_OUTPUT = $(REPO_ROOT)/testoutput
MNT ?= mnt
IMG_SIZE ?= 20G
QEMU_BIN = qemu-system-$(ARCH)
QEMU := $(shell which $(QEMU_BIN))

.PHONY: all clean launchvm change-owner check_qemu

all: launchvm change-owner

check_qemu:
ifeq ($(QEMU),)
$(error "$(QEMU_BIN) binary not found. Cannot proceed.")
endif
@echo "QEMU is available at $(QEMU)"

# Ensure test output directory exists
$(TEST_OUTPUT):
mkdir -p $(TEST_OUTPUT)

$(ROOT_IMG): Dockerfile
# Build the Docker image and create a tarball
DOCKER_BUILDKIT=1 docker build -f Dockerfile --build-arg target=$(TARGET_TEST) --output "type=tar,dest=$(TARBALL)" .
# Create a raw image, format it, and extract the tarball
fallocate -l $(IMG_SIZE) $(ROOT_IMAGE_RAW)
mkfs.ext4 $(ROOT_IMAGE_RAW)
[ -d $(MNT) ] || mkdir -p $(MNT)
sudo mount -o loop $(ROOT_IMAGE_RAW) mnt
sudo tar -xf $(TARBALL) -C $(MNT)
sync -f $(MNT) && sudo umount -l $(MNT)
rm -f $(TARBALL) && rmdir $(MNT)
# Convert the raw image to qcow2 format
qemu-img convert $(ROOT_IMAGE_RAW) -O qcow2 $(ROOT_IMG) && rm $(ROOT_IMAGE_RAW)

launchvm: check_qemu $(ROOT_IMG) $(TEST_OUTPUT)
qemu-system-$(ARCH) -enable-kvm -cpu host -m 5120 -smp 8 -kernel $(KERNEL) -drive file=$(ROOT_IMG),format=qcow2 \
-append "earlyprintk=ttyS0 console=ttyS0 root=/dev/sda rw quiet" \
-virtfs local,path=$(REPO_ROOT),mount_tag=beyla,security_model=mapped,id=beyla \
-virtfs local,path=$(TEST_OUTPUT),mount_tag=testout,security_model=mapped,id=testout \
-net user,hostfwd=tcp::2222-:22 -net nic \
-nographic

change-owner:
@current_owner=$$(stat -c '%U' .); \
chown -R $$current_owner $(TEST_OUTPUT)

clean:
rm -f $(ROOT_IMG) $(ROOT_IMAGE_RAW) $(TARBALL)

87 changes: 87 additions & 0 deletions test/vm/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
VIRTUAL MACHINE TESTS
=====================

Virtual Machine Tests (VM tests) enables Beyla to be tested under different
kernel versions and architectures. This works by exposing the path to the
Beyla source code (i.e. this git repository) to the guest by means of mounting
it to the '/build' directory. This allows Makefile targets to be invoked from
within the guest, in particular those tied to integration tests. Analogous to
a Docker container, changes to the '/build' directory are volatile and are
neither reflected on the host nor preserved once the VM terminates.

The supported pre-compiled kernels can be found in the 'kernels/$arch/'
subdirectory, alongside their respective kernel config files.

USAGE
=====

Simply run 'make' to get started. This will build a new rootfs image and
launch the VM using the default kernel specified in the Makefile. To select a
different kernel version. The following environment variables can be used to
specify the kernel version or architecture to run:

- ARCH: the target architecture (currently only x86_64 is supported)

- KERNEL_VER: the kernel version to use OR;

- KERNEL: path the kernel image to use

- TARGET_TEST: the target to pass to Beyla's toplevel Makefile (defaults to
run-integration-test-vm). When set to empty, the VM will drop onto an
interactive shell

For debugging purposes, the VM also exposes an SSH endpoint at port 2222. The
access credentials are 'root:root'.

EXAMPLES
========

Running tests against kernel 6.10.6

KERNEL_VER=6.10.6 make

Running tests against a custom kernel

KERNEL=/tmp/bzImage make

Running tests against kernel 6.10.6 invoking a custom target

TARGET_TEST=test KERNEL_VER=6.10.6 make

Running an interactive shell

TARGET_TEST= make

ADDING A NEW KERNEL VERSION
===========================

In order to add a new kernel version, you will need to download the
corresponding sources from https://cdn.kernel.org/pub/linux/kernel/ and
configure it accordingly. Each kernel version requires slightly different
config flags to be set. All kernel features should be compiled as part of the
kernel - the VM DOES NOT support kernel modules at this time.

In order to test whether your newly compiled kernel works, simply run

KERNEL=path/linux-x.x.x/arch/<arch>/boot/bzImage make

After verifying the kernel works, copy its '.config' file to
'kernels/<arch>/linux-x.y.z.config' and the resulting 'bzImage' to
'kernels/<arch>/vmlinuz-linux-x.y.z'.


TECHNICAL NOTES
===============

- The VM relies on an Alpine root filesystem containing the minimal
dependencies to run the 'run-integration-test-vm' target.

- The Beyla sources are mounted using an 9p filesystem to /beyla

- For backwards compatibility, $BEYLA_REPO_ROOT/testoutput is mounted
using an 9p filesystem to /overlay/upper/testoutput - as such, the test
outputs are available back to the host in the respective directory

- The final work directory from which tests are run is an overlay of
/beyla and /overlay/upper mounted using overlayfs to /build

Loading
Loading