diff --git a/.buildkite/pipeline_cross.py b/.buildkite/pipeline_cross.py index ceb89d27f3d..d7cd261a3d0 100755 --- a/.buildkite/pipeline_cross.py +++ b/.buildkite/pipeline_cross.py @@ -21,10 +21,12 @@ instances_x86_64 = ["c5n.metal", "m5n.metal", "m6i.metal", "m6a.metal"] instances_aarch64 = ["m7g.metal"] commands = [ - "./tools/devtool -y sh ./tools/create_snapshot_artifact/main.py", - "mkdir -pv snapshots/{instance}_{kv}", - "sudo chown -Rc $USER: snapshot_artifacts", - "mv -v snapshot_artifacts/* snapshots/{instance}_{kv}", + "./tools/devtool -y test --no-build -- -m nonci -n4 integration_tests/functional/test_snapshot_phase1.py", + # punch holes in mem snapshot tiles and tar them so they are preserved in S3 + "find test_results/test_snapshot_phase1 -type f -name mem |xargs -P4 -t -n1 fallocate -d", + "mv -v test_results/test_snapshot_phase1 snapshot_artifacts", + "mkdir -pv snapshots", + "tar cSvf snapshots/{instance}_{kv}.tar snapshot_artifacts", ] pipeline.build_group( "📸 create snapshots", @@ -80,10 +82,10 @@ k_val = pytest_keyword_for_instance.get(dst_instance, "") step = { "command": [ - f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}/* .", - f"mv -v snapshots/{src_instance}_{src_kv} snapshot_artifacts", + f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}.tar .", + f"tar xSvf snapshots/{src_instance}_{src_kv}.tar", *pipeline.devtool_test( - pytest_opts=f"-m nonci {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py", + pytest_opts=f"-m nonci -n4 {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py", ), ], "label": f"🎬 {src_instance} {src_kv} ➡️ {dst_instance} {dst_kv}", diff --git a/README.md b/README.md index dde5c21e794..f98079fc81c 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ We test all combinations of: | Instance | Host OS & Kernel | Guest Rootfs | Guest Kernel | | :-------- | :---------------- | :----------- | :----------- | -| c5n.metal | al2 linux_5.10 | ubuntu 22.04 | linux_5.10 | +| c5n.metal | al2 linux_5.10 | ubuntu 24.04 | linux_5.10 | | m5n.metal | al2023 linux_6.1 | | linux_6.1 | | m6i.metal | | | | | m6a.metal | | | | diff --git a/docs/getting-started.md b/docs/getting-started.md index cb9a7fee9ee..644d31e78a8 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -9,7 +9,7 @@ You can check if your system meets the requirements by running `firecracker/tools/devtool checkenv`. An opinionated way to run Firecracker is to launch an -[EC2](https://aws.amazon.com/ec2/) `c5.metal` instance with Ubuntu 22.04. +[EC2](https://aws.amazon.com/ec2/) `c5.metal` instance with Ubuntu 24.04. Firecracker requires [the KVM Linux kernel module](https://www.linux-kvm.org/) to perform its virtualization and emulation tasks. @@ -95,24 +95,26 @@ For simplicity, this guide will not use the [`jailer`](../src/jailer/). To successfully start a microVM, you will need an uncompressed Linux kernel binary, and an ext4 file system image (to use as rootfs). This guide uses a 5.10 -kernel image with a Ubuntu 22.04 rootfs from our CI: +kernel image with a Ubuntu 24.04 rootfs from our CI: ```bash ARCH="$(uname -m)" -latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.10/x86_64/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep "(?<=)(firecracker-ci/v1.10/x86_64/vmlinux-5\.10\.[0-9]{3})(?=)" -o -P) +latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.10/$ARCH/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep -oP "(?<=)(firecracker-ci/v1.10/$ARCH/vmlinux-5\.10\.[0-9]{1,3})(?=)") # Download a linux kernel binary wget "https://s3.amazonaws.com/spec.ccfc.min/${latest}" # Download a rootfs -wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-22.04.ext4" - -# Download the ssh key for the rootfs -wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-22.04.id_rsa" - -# Set user read permission on the ssh key -chmod 400 ./ubuntu-22.04.id_rsa +wget -O ubuntu-24.04.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.squashfs" + +# Create an ssh key for the rootfs +unsquashfs ubuntu-24.04.squashfs.upstream +ssh-keygen -f id_rsa -N "" +cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys +mv -v id_rsa ./ubuntu-24.04.id_rsa +# re-squash +mksquashfs squashfs-root ubuntu-24.04.squashfs -all-root -noappend -comp zstd ``` ### Getting a Firecracker Binary @@ -238,7 +240,7 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \ }" \ "http://localhost/boot-source" -ROOTFS="./ubuntu-22.04.ext4" +ROOTFS="./ubuntu-24.04.ext4" # Set rootfs sudo curl -X PUT --unix-socket "${API_SOCKET}" \ @@ -280,13 +282,13 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \ sleep 2s # Setup internet access in the guest -ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2 "ip route add default via 172.16.0.1 dev eth0" +ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 "ip route add default via 172.16.0.1 dev eth0" # Setup DNS resolution in the guest -ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2 "echo 'nameserver 8.8.8.8' > /etc/resolv.conf" +ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 "echo 'nameserver 8.8.8.8' > /etc/resolv.conf" # SSH into the microVM -ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2 +ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 # Use `root` for both the login and password. # Run `reboot` to exit. diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index a9e0bc8dc4c..75ffd306e25 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -642,8 +642,8 @@ booting, to avoid this issue. We have a mechanism in place to experiment with snapshot compatibility across supported host kernel versions by generating snapshot artifacts through -[this tool](../../tools/create_snapshot_artifact) and checking devices' -functionality using +[this test](../../tests/integration_tests/functional/test_snapshot_phase1.py) +and checking devices' functionality using [this test](../../tests/integration_tests/functional/test_snapshot_restore_cross_kernel.py). The test restores the snapshot and ensures that all the devices set-up (network devices, disk, vsock, balloon and MMDS) are operational post-load. diff --git a/resources/guest_configs/ci.config b/resources/guest_configs/ci.config new file mode 100644 index 00000000000..7bbf1fb1f56 --- /dev/null +++ b/resources/guest_configs/ci.config @@ -0,0 +1,7 @@ +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_MSDOS_PARTITION=y +CONFIG_SQUASHFS_ZSTD=y +# aarch64 only TBD split into a separate file +CONFIG_DEVMEM=y +# CONFIG_ARM64_ERRATUM_3194386 is not set diff --git a/resources/guest_configs/debug.config b/resources/guest_configs/debug.config new file mode 100644 index 00000000000..6ff73f2162b --- /dev/null +++ b/resources/guest_configs/debug.config @@ -0,0 +1,5 @@ +CONFIG_FRAME_POINTER=y +# CONFIG_KGDB=y +# CONFIG_KGDB_SERIAL_CONSOLE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_DWARF4=y diff --git a/resources/guest_configs/ftrace.config b/resources/guest_configs/ftrace.config new file mode 100644 index 00000000000..b180c7f232a --- /dev/null +++ b/resources/guest_configs/ftrace.config @@ -0,0 +1,11 @@ +CONFIG_FTRACE=y +CONFIG_FUNCTION_TRACER=y +CONFIG_FUNCTION_GRAPH_TRACER=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_PREEMPT_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_FTRACE_MCOUNT_RECORD=y +CONFIG_FTRACE_SYSCALLS=y diff --git a/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch b/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch deleted file mode 100644 index ed1f683dce1..00000000000 --- a/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 85e406b23c086c446ccfd6f8c83670800cc4de3a Mon Sep 17 00:00:00 2001 -From: Patrick Roy -Date: Tue, 30 Jul 2024 13:59:04 +0100 -Subject: [PATCH] fix: Adjust config options for what is needed by our tests - -Additionally, set `CONFIG_MSDOS_PARTITION=y` for our PARTUUID tests, -`CONFIG_DEVMEM=y` on aarch64/5.10 (for various integration tests that -rely on /dev/mem), and CONFIG_IKCONFIG=y and CONFIG_IKCONFIG_PROC=y for -the spectre-meltdown-checker.sh tests to work on AMD. - -Signed-off-by: Patrick Roy ---- - .../guest_configs/microvm-kernel-ci-aarch64-5.10.config | 7 ++++--- - .../microvm-kernel-ci-x86_64-5.10-no-acpi.config | 5 +++-- - .../guest_configs/microvm-kernel-ci-x86_64-5.10.config | 5 +++-- - 3 files changed, 10 insertions(+), 7 deletions(-) - -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -index ac44904c..0555055c 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -@@ -110,7 +110,8 @@ CONFIG_RCU_STALL_COMMON=y - CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - --# CONFIG_IKCONFIG is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y - # CONFIG_IKHEADERS is not set - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -@@ -752,7 +753,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set -@@ -1726,7 +1727,7 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_HW_RANDOM_CCTRNG is not set - # CONFIG_HW_RANDOM_XIPHERA is not set - # CONFIG_HW_RANDOM_GRAVITON is not set --# CONFIG_DEVMEM is not set -+CONFIG_DEVMEM=y - # CONFIG_RAW_DRIVER is not set - # CONFIG_TCG_TPM is not set - # CONFIG_XILLYBUS is not set -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -index b87fb3e4..a27c1f84 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -@@ -134,7 +134,8 @@ CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - - CONFIG_BUILD_BIN2C=y --# CONFIG_IKCONFIG is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y - # CONFIG_IKHEADERS is not set - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -@@ -702,7 +703,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -index 09461c17..af9ec662 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -@@ -127,7 +127,8 @@ CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - - CONFIG_BUILD_BIN2C=y --# CONFIG_IKCONFIG is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y - # CONFIG_IKHEADERS is not set - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -@@ -739,7 +740,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set --- -2.34.1 - diff --git a/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch b/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch deleted file mode 100644 index 06604fd104a..00000000000 --- a/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 911b916fdc53acfc7229302b029fd615f1e670cf Mon Sep 17 00:00:00 2001 -From: Babis Chalios -Date: Fri, 23 Aug 2024 12:54:26 +0200 -Subject: [PATCH 2/2] ci: adjust 6.1 guest kernel configs for our CI - -Set CONFIG_MSDOS_PARTITION=y for our PARTUUID tests, -CONFIG_DEVMEM=y on aarch64 for various integration tests that rely on -/dev/mem being there and CONFIG_IKCONFIG=y, CONFIG_IKCONFIG_PROC=y for -the spectre-meltdown-checker.sh tests to work on AMD. - -Signed-off-by: Babis Chalios ---- - .../guest_configs/microvm-kernel-ci-aarch64-6.1.config | 7 ++++--- - .../guest_configs/microvm-kernel-ci-x86_64-6.1.config | 7 ++++--- - 2 files changed, 8 insertions(+), 6 deletions(-) - -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -index 26b87a65..5c0334f4 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -@@ -140,7 +140,8 @@ CONFIG_RCU_STALL_COMMON=y - CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - --# CONFIG_IKCONFIG is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y - # CONFIG_IKHEADERS is not set - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -@@ -753,7 +754,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set -@@ -1823,7 +1824,7 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_HW_RANDOM_XIPHERA is not set - CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=y - # CONFIG_HW_RANDOM_GRAVITON is not set --# CONFIG_DEVMEM is not set -+CONFIG_DEVMEM=y - # CONFIG_TCG_TPM is not set - # CONFIG_XILLYBUS is not set - CONFIG_RANDOM_TRUST_CPU=y -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -index 967e3203..8a2769c0 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -@@ -162,8 +162,9 @@ CONFIG_RCU_STALL_COMMON=y - CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - --# CONFIG_IKCONFIG is not set --# CONFIG_IKHEADERS is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+# CONFIG_IKHEADERS=y - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 - CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 -@@ -769,7 +770,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set --- -2.34.1 - diff --git a/resources/guest_configs/patches/0003-enable-ftrace.patch b/resources/guest_configs/patches/0003-enable-ftrace.patch deleted file mode 100644 index a836a6fb3a7..00000000000 --- a/resources/guest_configs/patches/0003-enable-ftrace.patch +++ /dev/null @@ -1,115 +0,0 @@ -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -index ac44904c1..2a6f2310f 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -@@ -3089,7 +3089,17 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y - CONFIG_HAVE_SYSCALL_TRACEPOINTS=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y - # CONFIG_STRICT_DEVMEM is not set -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -index 26b87a658..f0f765298 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -@@ -3309,7 +3309,17 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y - CONFIG_HAVE_SYSCALL_TRACEPOINTS=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - # CONFIG_STRICT_DEVMEM is not set - -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -index b87fb3e44..fc45dda19 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -@@ -2905,7 +2905,17 @@ CONFIG_HAVE_SYSCALL_TRACEPOINTS=y - CONFIG_HAVE_FENTRY=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y - CONFIG_STRICT_DEVMEM=y -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -index 09461c178..6d85bce2c 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -@@ -2987,7 +2987,17 @@ CONFIG_HAVE_SYSCALL_TRACEPOINTS=y - CONFIG_HAVE_FENTRY=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y - CONFIG_STRICT_DEVMEM=y -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -index 967e32031..d11ef968a 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -@@ -3185,7 +3185,17 @@ CONFIG_HAVE_OBJTOOL_MCOUNT=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y - CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y diff --git a/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch b/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch deleted file mode 100644 index f3f16925e41..00000000000 --- a/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -index ac44904c1..9f912a70b 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -@@ -341,6 +341,7 @@ CONFIG_ARM64_ERRATUM_1463225=y - CONFIG_ARM64_ERRATUM_1542419=y - CONFIG_ARM64_ERRATUM_1508412=y - CONFIG_ARM64_ERRATUM_2457168=y -+# CONFIG_ARM64_ERRATUM_3194386 is not set - CONFIG_CAVIUM_ERRATUM_22375=y - CONFIG_CAVIUM_ERRATUM_23144=y - CONFIG_CAVIUM_ERRATUM_23154=y -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -index 26b87a658..29fe130f2 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -@@ -362,6 +362,7 @@ CONFIG_ARM64_ERRATUM_2441009=y - CONFIG_ARM64_ERRATUM_2457168=y - CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD=y - CONFIG_ARM64_ERRATUM_2966298=y -+# CONFIG_ARM64_ERRATUM_3194386 is not set - CONFIG_CAVIUM_ERRATUM_22375=y - CONFIG_CAVIUM_ERRATUM_23144=y - CONFIG_CAVIUM_ERRATUM_23154=y diff --git a/resources/rebuild.sh b/resources/rebuild.sh index 9f6850d0555..90bac7addb7 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -20,25 +20,6 @@ function install_dependencies { apt install -y bc flex bison gcc make libelf-dev libssl-dev squashfs-tools busybox-static tree cpio curl patch docker.io } -function dir2ext4img { - # ext4 - # https://unix.stackexchange.com/questions/503211/how-can-an-image-file-be-created-for-a-directory - local DIR=$1 - local IMG=$2 - # Default size for the resulting rootfs image is 300M - local SIZE=${3:-300M} - local TMP_MNT=$(mktemp -d) - truncate -s "$SIZE" "$IMG" - mkfs.ext4 -F "$IMG" - mount "$IMG" "$TMP_MNT" - tar c -C $DIR . |tar x -C "$TMP_MNT" - # cleanup - # Use the -l flag for lazy unmounting since sometimes umount fails - # with "device busy" and simply calling `sync` doesn't help - umount -l "$TMP_MNT" - rmdir $TMP_MNT -} - function prepare_docker { nohup /usr/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 & @@ -67,7 +48,7 @@ function build_rootfs { cp -rvf overlay/* $rootfs - # curl -O https://cloud-images.ubuntu.com/minimal/releases/jammy/release/ubuntu-22.04-minimal-cloudimg-amd64-root.tar.xz + # curl -O https://cloud-images.ubuntu.com/minimal/releases/noble/release/ubuntu-24.04-minimal-cloudimg-amd64-root.tar.xz # # TBD use systemd-nspawn instead of Docker # sudo tar xaf ubuntu-22.04-minimal-cloudimg-amd64-root.tar.xz -C $rootfs @@ -89,26 +70,13 @@ EOF # TBD what abt /etc/hosts? echo | tee $rootfs/etc/resolv.conf - # Generate key for ssh access from host - if [ ! -s id_rsa ]; then - ssh-keygen -f id_rsa -N "" - fi - install -d -m 0600 "$rootfs/root/.ssh/" - cp id_rsa.pub "$rootfs/root/.ssh/authorized_keys" - id_rsa=$OUTPUT_DIR/$ROOTFS_NAME.id_rsa - cp id_rsa $id_rsa - - # -comp zstd but guest kernel does not support rootfs_img="$OUTPUT_DIR/$ROOTFS_NAME.squashfs" mv $rootfs/root/manifest $OUTPUT_DIR/$ROOTFS_NAME.manifest - mksquashfs $rootfs $rootfs_img -all-root -noappend - rootfs_ext4=$OUTPUT_DIR/$ROOTFS_NAME.ext4 - dir2ext4img $rootfs $rootfs_ext4 + mksquashfs $rootfs $rootfs_img -all-root -noappend -comp zstd rm -rf $rootfs for bin in fast_page_fault_helper fillmem init readmem; do rm $PWD/overlay/usr/local/bin/$bin done - rm -f id_rsa{,.pub} rm -f nohup.out } @@ -155,12 +123,6 @@ function clone_amazon_linux_repo { [ -d linux ] || git clone https://github.com/amazonlinux/linux linux } -function apply_kernel_patches_for_ci { - for p in $PWD/guest_configs/patches/* ; do - patch -p2 < $p - done -} - # prints the git tag corresponding to the newest and best matching the provided kernel version $1 # this means that if a microvm kernel exists, the tag returned will be of the form # @@ -200,8 +162,9 @@ function build_al_kernel { echo "FATAL: Unsupported architecture!" exit 1 fi - cp "$KERNEL_CFG" .config - + # Concatenate all config files into one. olddefconfig will then resolve + # as needed. Later values override earlier ones. + cat "$@" >.config make olddefconfig make -j $(nproc) $target LATEST_VERSION=$(cat include/config/kernel.release) @@ -226,16 +189,30 @@ function prepare_and_build_rootfs { compile_and_install $BIN/devmemread.c $BIN/devmemread fi - build_rootfs ubuntu-22.04 jammy + build_rootfs ubuntu-24.04 noble build_initramfs } +function vmlinux_split_debuginfo { + VMLINUX="$1" + DEBUGINFO="$VMLINUX.debug" + VMLINUX_ORIG="$VMLINUX" + if [ $ARCH = "aarch64" ]; then + # in aarch64, the debug info is in vmlinux + VMLINUX_ORIG=linux/vmlinux + fi + objcopy --only-keep-debug $VMLINUX_ORIG $DEBUGINFO + objcopy --preserve-dates --strip-debug --add-gnu-debuglink=$DEBUGINFO $VMLINUX + # gdb does not support compressed files, but compress them because they are huge + gzip -v $DEBUGINFO +} + function build_al_kernels { if [[ $# = 0 ]]; then local KERNEL_VERSION="all" elif [[ $# -ne 1 ]]; then die "Too many arguments in '$(basename $0) kernels' command. Please use \`$0 help\` for help." - else + else KERNEL_VERSION=$1 if [[ "$KERNEL_VERSION" != @(5.10|5.10-no-acpi|6.1) ]]; then die "Unsupported kernel version: '$KERNEL_VERSION'. Please use \`$0 help\` for help." @@ -244,22 +221,31 @@ function build_al_kernels { clone_amazon_linux_repo - # Apply kernel patches on top of AL configuration - apply_kernel_patches_for_ci + CI_CONFIG="$PWD/guest_configs/ci.config" if [[ "$KERNEL_VERSION" == @(all|5.10) ]]; then - build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config + build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config "$CI_CONFIG" fi if [[ $ARCH == "x86_64" && "$KERNEL_VERSION" == @(all|5.10-no-acpi) ]]; then - build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10-no-acpi.config + build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10-no-acpi.config "$CI_CONFIG" fi if [[ "$KERNEL_VERSION" == @(all|6.1) ]]; then - build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config 5.10 + build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config "$CI_CONFIG" fi - # Undo kernel patches on top of AL configuration - git restore $PWD/guest_configs - rm -rf $PWD/guest_configs/*.orig + # Build debug kernels + FTRACE_CONFIG="$PWD/guest_configs/ftrace.config" + DEBUG_CONFIG="$PWD/guest_configs/debug.config" + OUTPUT_DIR=$OUTPUT_DIR/debug + mkdir -pv $OUTPUT_DIR + if [[ "$KERNEL_VERSION" == @(all|5.10) ]]; then + build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config" "$CI_CONFIG" "$FTRACE_CONFIG" "$DEBUG_CONFIG" + vmlinux_split_debuginfo $OUTPUT_DIR/vmlinux-5.10.* + fi + if [[ "$KERNEL_VERSION" == @(all|6.1) ]]; then + build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config" "$CI_CONFIG" "$FTRACE_CONFIG" "$DEBUG_CONFIG" + vmlinux_split_debuginfo $OUTPUT_DIR/vmlinux-6.1.* + fi } function print_help { @@ -267,25 +253,25 @@ function print_help { Firecracker CI artifacts build script Usage: $(basename $0) [] [] - + Available commands: - + all (default) Build CI rootfs and default guest kernels using configurations from resources/guest_configs. This will patch the guest configurations with all the patches under resources/guest_configs/patches. This is the default command, if no command is chosen. - + rootfs Builds only the CI rootfs. - + kernels [version] Builds our the currently supported CI kernels. - + version: Optionally choose a kernel version to build. Supported versions are: 5.10, 5.10-no-acpi or 6.1. - + help Displays the help message and exits. EOF @@ -310,7 +296,7 @@ function main { fi set -x - + install_dependencies # Create the directory in which we will store the kernels and rootfs diff --git a/tests/README.md b/tests/README.md index 4fee1baee30..ea46ff56786 100644 --- a/tests/README.md +++ b/tests/README.md @@ -303,9 +303,9 @@ that are pre-initialized with specific guest kernels and rootfs: - `uvm_plain_any` is parametrized by the guest kernels [supported](../docs/kernel-policy.md) by Firecracker and a read-only Ubuntu - 22.04 squashfs as rootfs, + 24.04 squashfs as rootfs, - `uvm_plain` yields a Firecracker process pre-initialized with a 5.10 kernel - and the same Ubuntu 22.04 squashfs. + and the same Ubuntu 24.04 squashfs. Generally, tests should use the former if you are testing some interaction between the guest and Firecracker, while the latter should be used if diff --git a/tests/conftest.py b/tests/conftest.py index c77fee09039..8f4c2e51ff5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -307,14 +307,20 @@ def custom_cpu_template(request, record_property): @pytest.fixture( - params=list(static_cpu_templates_params()) + list(custom_cpu_templates_params()) + params=[ + pytest.param(None, id="NO_CPU_TMPL"), + *static_cpu_templates_params(), + *custom_cpu_templates_params(), + ], ) def cpu_template_any(request, record_property): - """This fixture combines static and custom CPU templates""" - if "name" in request.param: - record_property("custom_cpu_template", request.param["name"]) - else: - record_property("static_cpu_template", request.param) + """This fixture combines no template, static and custom CPU templates""" + cpu_template_name = request.param + if request.param is None: + cpu_template_name = "None" + elif "name" in request.param: + cpu_template_name = request.param["name"] + record_property("cpu_template", cpu_template_name) return request.param @@ -382,27 +388,24 @@ def rootfs_fxt(request, record_property): ) # Fixtures for all Ubuntu rootfs, and specific versions -rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("*.squashfs")) -rootfs_ubuntu_22 = pytest.fixture( - rootfs_fxt, params=rootfs_params("ubuntu-22*.squashfs") -) +rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("ubuntu-24*.squashfs")) rootfs_rw = pytest.fixture(rootfs_fxt, params=rootfs_params("*.ext4")) @pytest.fixture -def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22): +def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs): """Create a vanilla VM, non-parametrized kernel: 5.10 - rootfs: Ubuntu 22.04 + rootfs: Ubuntu 24.04 """ - return microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22) + return microvm_factory.build(guest_kernel_linux_5_10, rootfs) @pytest.fixture def uvm_plain_rw(microvm_factory, guest_kernel_linux_5_10, rootfs_rw): """Create a vanilla VM, non-parametrized kernel: 5.10 - rootfs: Ubuntu 22.04 + rootfs: Ubuntu 24.04 """ return microvm_factory.build(guest_kernel_linux_5_10, rootfs_rw) @@ -424,12 +427,24 @@ def artifact_dir(): @pytest.fixture -def uvm_plain_any(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def uvm_plain_any(microvm_factory, guest_kernel, rootfs): """All guest kernels kernel: all - rootfs: Ubuntu 22.04 + rootfs: Ubuntu 24.04 """ - return microvm_factory.build(guest_kernel, rootfs_ubuntu_22) + return microvm_factory.build(guest_kernel, rootfs) + + +guest_kernel_6_1_debug = pytest.fixture( + guest_kernel_fxt, + params=kernel_params("vmlinux-6.1*", artifact_dir=defs.ARTIFACT_DIR / "debug"), +) + + +@pytest.fixture +def uvm_plain_debug(microvm_factory, guest_kernel_6_1_debug, rootfs_rw): + """VM running a kernel with debug/trace Kconfig options""" + return microvm_factory.build(guest_kernel_6_1_debug, rootfs_rw) @pytest.fixture diff --git a/tests/framework/artifacts.py b/tests/framework/artifacts.py index f4e05a88c94..77584f02129 100644 --- a/tests/framework/artifacts.py +++ b/tests/framework/artifacts.py @@ -32,12 +32,12 @@ def select_supported_kernels(): return supported_kernels -def kernels(glob) -> Iterator: +def kernels(glob, artifact_dir: Path = ARTIFACT_DIR) -> Iterator: """Return supported kernels as kernels supported by the current combination of kernel and instance type. """ supported_kernels = select_supported_kernels() - for kernel in sorted(ARTIFACT_DIR.rglob(glob)): + for kernel in sorted(artifact_dir.glob(glob)): for kernel_regex in supported_kernels: if re.fullmatch(kernel_regex, kernel.name): yield kernel @@ -49,9 +49,11 @@ def disks(glob) -> Iterator: yield from sorted(ARTIFACT_DIR.glob(glob)) -def kernel_params(glob="vmlinux-*", select=kernels) -> Iterator: +def kernel_params( + glob="vmlinux-*", select=kernels, artifact_dir=ARTIFACT_DIR +) -> Iterator: """Return supported kernels""" - for kernel in select(glob): + for kernel in select(glob, artifact_dir): yield pytest.param(kernel, id=kernel.name) diff --git a/tests/framework/microvm_helpers.py b/tests/framework/microvm_helpers.py index 4239eb2489f..f29ae84a9a0 100644 --- a/tests/framework/microvm_helpers.py +++ b/tests/framework/microvm_helpers.py @@ -222,3 +222,26 @@ def run_in_netns(cmd): # add a route on the host for the clone address run(f"ip route add {ingress_ipv4} via {veth_guest_ip}") + + def trace_cmd_guest(self, fns, cmd, port=4321): + """Run trace-cmd on the guest, but transfer the data directly to the host.""" + docker_apt_install("trace-cmd") + print("host> trace-cmd listen") + _proc = subprocess.Popen( + [ + "ip", + "netns", + "exec", + self.vm.netns.id, + "trace-cmd", + "listen", + "-p", + str(port), + ] + ) + print("guest> trace-cmd record") + host_ip = self.vm.iface["eth0"]["iface"].host_ip + _guest_ps = self.vm.ssh.run( + f"trace-cmd record -N {host_ip}:{port} -p function {" ".join(fns)} {cmd}" + ) + return list(Path(".").glob("trace.*.dat")) diff --git a/tests/framework/utils_drive.py b/tests/framework/utils_drive.py index 2e67ff41f39..7bb623d73e0 100644 --- a/tests/framework/utils_drive.py +++ b/tests/framework/utils_drive.py @@ -23,17 +23,15 @@ class VhostUserBlkBackendType(Enum): CROSVM = "Crosvm" -def partuuid_and_disk_path(rootfs_ubuntu_22, disk_path): +def partuuid_and_disk_path(rootfs, disk_path): """ We create a new file with specified path, get its partuuid and use it as a rootfs. """ - initial_size = rootfs_ubuntu_22.stat().st_size + 50 * MB + initial_size = rootfs.stat().st_size + 50 * MB disk_path.touch() os.truncate(disk_path, initial_size) check_output(f"echo type=83 | sfdisk --no-tell-kernel {str(disk_path)}", shell=True) - check_output( - f"dd bs=1M seek=1 if={str(rootfs_ubuntu_22)} of={disk_path}", shell=True - ) + check_output(f"dd bs=1M seek=1 if={str(rootfs)} of={disk_path}", shell=True) ptuuid = check_output( f"blkid -s PTUUID -o value {disk_path}", shell=True, encoding="ascii" ).strip() diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index e1c53020fd0..7877b914d28 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -5,6 +5,7 @@ import ipaddress import random import string +import subprocess from dataclasses import dataclass, field from pathlib import Path @@ -67,9 +68,14 @@ def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None): self._on_error = on_error + @property + def user_host(self): + """remote address for in SSH format @""" + return f"{self.user}@{self.host}" + def remote_path(self, path): """Convert a path to remote""" - return f"{self.user}@{self.host}:{path}" + return f"{self.user_host}:{path}" def _scp(self, path1, path2, options): """Copy files to/from the VM using scp.""" @@ -111,21 +117,12 @@ def run(self, cmd_string, timeout=None, *, check=False, debug=False): If `debug` is set, pass `-vvv` to `ssh`. Note that this will clobber stderr. """ - command = [ - "ssh", - *self.options, - f"{self.user}@{self.host}", - cmd_string, - ] + command = ["ssh", *self.options, self.user_host, cmd_string] if debug: command.insert(1, "-vvv") - return self._exec( - command, - timeout, - check=check, - ) + return self._exec(command, timeout, check=check) def check_output(self, cmd_string, timeout=None, *, debug=False): """Same as `run`, but raises an exception on non-zero return code of remote command""" @@ -144,6 +141,27 @@ def _exec(self, cmd, timeout=None, check=False): raise + # pylint:disable=invalid-name + def Popen( + self, + cmd: str, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + **kwargs, + ) -> subprocess.Popen: + """Execute the command in the guest and return a Popen object. + + pop = uvm.ssh.Popen("while true; do echo $(date -Is) $RANDOM; sleep 1; done") + pop.stdout.read(16) + """ + cmd = ["ssh", *self.options, self.user_host, cmd] + if self.netns is not None: + cmd = ["ip", "netns", "exec", self.netns] + cmd + return subprocess.Popen( + cmd, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs + ) + def mac_from_ip(ip_address): """Create a MAC address based on the provided IP. diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 5aebe7b5265..27366529c39 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -895,7 +895,7 @@ def _drive_patch(test_microvm): "is_root_device": True, "cache_type": "Unsafe", "is_read_only": True, - "path_on_host": "/ubuntu-22.04.squashfs", + "path_on_host": "/" + test_microvm.rootfs_file.name, "rate_limiter": None, "io_engine": "Sync", "socket": None, @@ -1226,7 +1226,7 @@ def test_get_full_config(uvm_plain): "is_root_device": True, "cache_type": "Unsafe", "is_read_only": True, - "path_on_host": "/ubuntu-22.04.squashfs", + "path_on_host": "/" + test_microvm.rootfs_file.name, "rate_limiter": None, "io_engine": "Sync", "socket": None, diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index fd04b17c305..8357f54b568 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -148,12 +148,12 @@ def test_host_vs_guest_cpu_features_aarch64(uvm_nano): PLATFORM != "aarch64", reason="This is aarch64 specific test.", ) -def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_default_cpu_features(microvm_factory, guest_kernel, rootfs): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.basic_config() vm.add_net_iface() @@ -167,13 +167,13 @@ def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_22): reason="This is aarch64 specific test.", ) def test_cpu_features_with_static_template( - microvm_factory, guest_kernel, rootfs_ubuntu_22, cpu_template + microvm_factory, guest_kernel, rootfs, cpu_template ): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.basic_config(cpu_template=cpu_template) vm.add_net_iface() @@ -195,13 +195,13 @@ def test_cpu_features_with_static_template( reason="This is aarch64 specific test.", ) def test_cpu_features_with_custom_template( - microvm_factory, guest_kernel, rootfs_ubuntu_22, custom_cpu_template + microvm_factory, guest_kernel, rootfs, custom_cpu_template ): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.basic_config() vm.api.cpu_config.put(**custom_cpu_template["template"]) diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py index 3174e9dda6c..23818ddc6b1 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -560,7 +560,7 @@ def msr_cpu_template_fxt(request): @pytest.mark.timeout(900) @pytest.mark.nonci def test_cpu_rdmsr( - microvm_factory, msr_cpu_template, guest_kernel, rootfs_ubuntu_22, results_dir + microvm_factory, msr_cpu_template, guest_kernel, rootfs, results_dir ): """ Test MSRs that are available to the guest. @@ -595,7 +595,7 @@ def test_cpu_rdmsr( """ vcpus, guest_mem_mib = 1, 1024 - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.add_net_iface() vm.basic_config( @@ -664,9 +664,7 @@ def dump_msr_state_to_file(dump_fname, ssh_conn, shared_names): ) @pytest.mark.timeout(900) @pytest.mark.nonci -def test_cpu_wrmsr_snapshot( - microvm_factory, guest_kernel, rootfs_ubuntu_22, msr_cpu_template -): +def test_cpu_wrmsr_snapshot(microvm_factory, guest_kernel, rootfs, msr_cpu_template): """ This is the first part of the test verifying that MSRs retain their values after restoring from a snapshot. @@ -686,7 +684,7 @@ def test_cpu_wrmsr_snapshot( shared_names = SNAPSHOT_RESTORE_SHARED_NAMES vcpus, guest_mem_mib = 1, 1024 - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.add_net_iface() vm.basic_config( @@ -821,9 +819,7 @@ def dump_cpuid_to_file(dump_fname, ssh_conn): ) @pytest.mark.timeout(900) @pytest.mark.nonci -def test_cpu_cpuid_snapshot( - microvm_factory, guest_kernel, rootfs_ubuntu_22, msr_cpu_template -): +def test_cpu_cpuid_snapshot(microvm_factory, guest_kernel, rootfs, msr_cpu_template): """ This is the first part of the test verifying that CPUID remains the same after restoring from a snapshot. @@ -839,7 +835,7 @@ def test_cpu_cpuid_snapshot( vm = microvm_factory.build( kernel=guest_kernel, - rootfs=rootfs_ubuntu_22, + rootfs=rootfs, ) vm.spawn() vm.add_net_iface() @@ -1215,9 +1211,9 @@ def check_enabled_features(test_microvm, cpu_template): "enhanced REP MOVSB/STOSB": "true", "SMAP: supervisor mode access prevention": "true", # xsave_0xd_0 - "XCR0 supported: x87 state": "true", - "XCR0 supported: SSE state": "true", - "XCR0 supported: AVX state": "true", + "x87 state": "true", + "SSE state": "true", + "AVX state": "true", # xsave_0xd_1 "XSAVEOPT instruction": "true", # extended_080000001_edx diff --git a/tests/integration_tests/functional/test_drive_vhost_user.py b/tests/integration_tests/functional/test_drive_vhost_user.py index 31a11a75661..79cc41b0f3a 100644 --- a/tests/integration_tests/functional/test_drive_vhost_user.py +++ b/tests/integration_tests/functional/test_drive_vhost_user.py @@ -34,7 +34,7 @@ def _check_drives(test_microvm, assert_dict, keys_array): assert blockdev_out_line_cols[col] == assert_dict[key] -def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_vhost_user_block(microvm_factory, guest_kernel, rootfs): """ This test simply tries to boot a VM with vhost-user-block as a root device. @@ -44,13 +44,11 @@ def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) - vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True - ) + vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True) vm.add_net_iface() vhost_user_block_metrics = FcDeviceMetrics( "vhost_user_block", 1, aggr_supported=False @@ -67,7 +65,7 @@ def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22): vhost_user_block_metrics.validate(vm) -def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs): """ This test simply tries to boot a VM with vhost-user-block as a root device. @@ -78,14 +76,14 @@ def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubunt # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) # Create a rw rootfs file that is unique to the microVM rootfs_rw = Path(vm.chroot()) / "rootfs" - shutil.copy(rootfs_ubuntu_22, rootfs_rw) + shutil.copy(rootfs, rootfs_rw) vm.add_vhost_user_drive("rootfs", rootfs_rw, is_root_device=True) vm.add_net_iface() @@ -100,7 +98,7 @@ def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubunt _check_drives(vm, assert_dict, assert_dict.keys()) -def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs): """ Test that even if backend is killed, Firecracker is still responsive. """ @@ -109,13 +107,11 @@ def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubunt # We need to set up ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) - vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True - ) + vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True) vm.add_net_iface() vm.start() @@ -127,7 +123,7 @@ def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubunt _config = vm.api.vm_config.get().json() -def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_device_ordering(microvm_factory, guest_kernel, rootfs): """ Verify device ordering. @@ -139,7 +135,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) @@ -150,9 +146,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): vm.add_drive("scratch1", fs1.path) # Adding second block device (rootfs) - vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True - ) + vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True) # Adding third block device. fs2 = drive_tools.FilesystemFile(os.path.join(vm.fsfiles, "scratch2"), size=512) @@ -160,7 +154,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): # Create a rw rootfs file that is unique to the microVM rootfs_rw = Path(vm.chroot()) / "rootfs" - shutil.copy(rootfs_ubuntu_22, rootfs_rw) + shutil.copy(rootfs, rootfs_rw) # Adding forth block device. vm.add_vhost_user_drive("dummy_rootfs", rootfs_rw) @@ -171,7 +165,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): ) vm.start() - rootfs_size = rootfs_ubuntu_22.stat().st_size + rootfs_size = rootfs.stat().st_size # The devices were added in this order: fs1, rootfs, fs2. fs3 # However, the rootfs is the root device and goes first, @@ -203,7 +197,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): def test_partuuid_boot( microvm_factory, guest_kernel, - rootfs_ubuntu_22, + rootfs, ): """ Test the output reported by blockdev when booting with PARTUUID. @@ -213,15 +207,13 @@ def test_partuuid_boot( # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) # Create a rootfs with partuuid unique to this microVM - partuuid, disk_path = partuuid_and_disk_path( - rootfs_ubuntu_22, Path(vm.chroot()) / "disk.img" - ) + partuuid, disk_path = partuuid_and_disk_path(rootfs, Path(vm.chroot()) / "disk.img") vm.add_vhost_user_drive( "1", disk_path, is_root_device=True, partuuid=partuuid, is_read_only=True @@ -238,7 +230,7 @@ def test_partuuid_boot( _check_drives(vm, assert_dict, assert_dict.keys()) -def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_partuuid_update(microvm_factory, guest_kernel, rootfs): """ Test successful switching from PARTUUID boot to /dev/vda boot. """ @@ -247,7 +239,7 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) @@ -256,16 +248,14 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22): # Add the root block device specified through PARTUUID. vm.add_vhost_user_drive( "rootfs", - rootfs_ubuntu_22, + rootfs, is_root_device=True, partuuid="0eaa91a0-01", is_read_only=True, ) # Adding a drive with the same ID creates another backend with another socket. - vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True - ) + vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True) vhost_user_block_metrics = FcDeviceMetrics( "vhost_user_block", 1, aggr_supported=False diff --git a/tests/integration_tests/functional/test_drive_virtio.py b/tests/integration_tests/functional/test_drive_virtio.py index dbebefa11a1..9c61ead56a9 100644 --- a/tests/integration_tests/functional/test_drive_virtio.py +++ b/tests/integration_tests/functional/test_drive_virtio.py @@ -14,12 +14,12 @@ @pytest.fixture -def partuuid_and_disk_path_tmpfs(rootfs_ubuntu_22, tmp_path): +def partuuid_and_disk_path_tmpfs(rootfs, tmp_path): """ We create a new file in tmpfs, get its partuuid and use it as a rootfs. """ disk_path = tmp_path / "disk.img" - yield partuuid_and_disk_path(rootfs_ubuntu_22, disk_path) + yield partuuid_and_disk_path(rootfs, disk_path) disk_path.unlink() diff --git a/tests/integration_tests/functional/test_kernel_cmdline.py b/tests/integration_tests/functional/test_kernel_cmdline.py index 14e369790f1..9707eb8a92c 100644 --- a/tests/integration_tests/functional/test_kernel_cmdline.py +++ b/tests/integration_tests/functional/test_kernel_cmdline.py @@ -29,4 +29,4 @@ def test_init_params(uvm_plain): serial = Serial(vm) serial.open() # If the string does not show up, the test will fail. - serial.rx(token="Ubuntu 22.04") + serial.rx(token="Ubuntu 24.04") diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index e52389bc8b8..a804b8f90a8 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -99,7 +99,7 @@ def run_udp_offload_test(vm): # Start a UDP server in the guest # vm.ssh.check_output(f"nohup socat UDP-LISTEN:{port} - > {out_filename} &") vm.ssh.check_output( - f"nohup socat UDP-LISTEN:{port} OPEN:{out_filename},creat > /dev/null 2>&1 &" + f"nohup socat UDP4-LISTEN:{port} OPEN:{out_filename},creat > /dev/null 2>&1 &" ) # Try to send a UDP message from host with UDP offload enabled @@ -127,11 +127,11 @@ def test_tap_offload_booted(uvm_plain_any): run_udp_offload_test(vm) -def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs): """ Verify that tap offload features are configured for a restored VM. """ - src = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + src = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) src.spawn() src.basic_config() src.add_net_iface() diff --git a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py index 812e706b926..5584cfceac8 100644 --- a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py +++ b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py @@ -25,14 +25,14 @@ def mount_tmpfs_small(worker_id): def test_diff_snapshot_works_after_error( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, mount_tmpfs_small + microvm_factory, guest_kernel_linux_5_10, rootfs, mount_tmpfs_small ): """ Test that if a partial snapshot errors it will work after and not lose data """ uvm = microvm_factory.build( guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs, jailer_kwargs={"chroot_base": mount_tmpfs_small}, ) diff --git a/tests/integration_tests/functional/test_snapshot_phase1.py b/tests/integration_tests/functional/test_snapshot_phase1.py new file mode 100644 index 00000000000..7436c19d875 --- /dev/null +++ b/tests/integration_tests/functional/test_snapshot_phase1.py @@ -0,0 +1,108 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Creates snapshots for other tests like test_snapshot_restore_cross_kernel.py +""" + +import json +import platform +import re + +import pytest + +from framework.utils import ( + configure_mmds, + generate_mmds_get_request, + generate_mmds_session_token, +) + +if platform.machine() != "x86_64": + pytestmark = pytest.mark.skip("only x86_64 architecture supported") + +# Default IPv4 address to route MMDS requests. +IPV4_ADDRESS = "169.254.169.254" +NET_IFACE_FOR_MMDS = "eth3" + + +@pytest.mark.nonci +def test_snapshot_phase1( + microvm_factory, guest_kernel, rootfs, cpu_template_any, results_dir +): + """Create a snapshot and save it to disk""" + + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) + vm.spawn(log_level="Info") + vm.add_net_iface() + + static_cpu_template = None + cpu_template_name = "None" + if isinstance(cpu_template_any, str): + static_cpu_template = cpu_template_any + cpu_template_name = f"static_{cpu_template_any}" + elif isinstance(cpu_template_any, dict): + vm.api.cpu_config.put(**cpu_template_any["template"]) + cpu_template_name = f"custom_{cpu_template_any['name']}" + vm.basic_config( + vcpu_count=2, + mem_size_mib=512, + cpu_template=static_cpu_template, + ) + + guest_kernel_version = re.search("vmlinux-(.*)", vm.kernel_file.name) + snapshot_artifacts_dir = ( + results_dir + / f"{guest_kernel_version.group(1)}_{cpu_template_name}_guest_snapshot" + ) + + # Add 4 network devices + for i in range(4): + vm.add_net_iface() + # Add a vsock device + vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock") + # Add MMDS + configure_mmds(vm, ["eth3"], version="V2") + # Add a memory balloon. + vm.api.balloon.put(amount_mib=0, deflate_on_oom=True, stats_polling_interval_s=1) + + vm.start() + + # Populate MMDS. + data_store = { + "latest": { + "meta-data": { + "ami-id": "ami-12345678", + "reservation-id": "r-fea54097", + "local-hostname": "ip-10-251-50-12.ec2.internal", + "public-hostname": "ec2-203-0-113-25.compute-1.amazonaws.com", + } + } + } + + # MMDS should be empty. + assert vm.api.mmds.get().json() == {} + # Populate MMDS with data. + vm.api.mmds.put(**data_store) + # Ensure data is persistent inside the data store. + assert vm.api.mmds.get().json() == data_store + + # Iterate and validate connectivity on all ifaces after boot. + for i in range(4): + exit_code, _, _ = vm.ssh_iface(i).run("sync") + assert exit_code == 0 + + # Validate MMDS. + # Configure interface to route MMDS requests + vm.ssh.check_output(f"ip route add {IPV4_ADDRESS} dev {NET_IFACE_FOR_MMDS}") + + # Fetch metadata to ensure MMDS is accessible. + token = generate_mmds_session_token(vm.ssh, IPV4_ADDRESS, token_ttl=60) + cmd = generate_mmds_get_request(IPV4_ADDRESS, token=token) + _, stdout, _ = vm.ssh.run(cmd) + assert json.loads(stdout) == data_store + + # Copy snapshot files to be published to S3 for the 2nd part of the test + # Create snapshot artifacts directory specific for the kernel version used. + snapshot = vm.snapshot_full() + snapshot_artifacts_dir.mkdir(parents=True) + snapshot.save_to(snapshot_artifacts_dir) diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index 44de52ed2d5..fbb86c4c987 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -14,10 +14,10 @@ @pytest.fixture(scope="function", name="snapshot") -def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22): +def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs): """Create a snapshot of a microVM.""" - basevm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22) + basevm = microvm_factory.build(guest_kernel_linux_5_10, rootfs) basevm.spawn() basevm.basic_config(vcpu_count=2, mem_size_mib=256) basevm.add_net_iface() diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index 034ee6749a0..8437d78c7d3 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -70,14 +70,14 @@ def test_hugetlbfs_boot(uvm_plain): def test_hugetlbfs_snapshot( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, uffd_handler_paths + microvm_factory, guest_kernel_linux_5_10, rootfs, uffd_handler_paths ): """ Test hugetlbfs snapshot restore via uffd """ ### Create Snapshot ### - vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22) + vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs) vm.memory_monitor = None vm.spawn() vm.basic_config(huge_pages=HugePagesConfig.HUGETLBFS_2MB, mem_size_mib=128) @@ -152,7 +152,7 @@ def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain, uffd_handler_paths) def test_ept_violation_count( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs, uffd_handler_paths, metrics, huge_pages, @@ -163,7 +163,7 @@ def test_ept_violation_count( """ ### Create Snapshot ### - vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22) + vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs) vm.memory_monitor = None vm.spawn() vm.basic_config(huge_pages=huge_pages, mem_size_mib=256) diff --git a/tests/integration_tests/performance/test_vhost_user_metrics.py b/tests/integration_tests/performance/test_vhost_user_metrics.py index 45fb7a94114..fd20b34a47b 100644 --- a/tests/integration_tests/performance/test_vhost_user_metrics.py +++ b/tests/integration_tests/performance/test_vhost_user_metrics.py @@ -11,7 +11,7 @@ @pytest.mark.parametrize("vcpu_count", [1, 2], ids=["1vcpu", "2vcpu"]) def test_vhost_user_block_metrics( - microvm_factory, guest_kernel_acpi, rootfs_ubuntu_22, vcpu_count, metrics + microvm_factory, guest_kernel_acpi, rootfs, vcpu_count, metrics ): """ This test tries to boot a VM with vhost-user-block @@ -28,9 +28,7 @@ def test_vhost_user_block_metrics( # low->high->low->high and so the numbers are not in monotonic sequence. new_sizes = [20, 10, 30] # MB - vm = microvm_factory.build( - guest_kernel_acpi, rootfs_ubuntu_22, monitor_memory=False - ) + vm = microvm_factory.build(guest_kernel_acpi, rootfs, monitor_memory=False) vm.spawn(log_level="Info") vm.basic_config(vcpu_count=vcpu_count) vm.add_net_iface() diff --git a/tests/integration_tests/security/test_nv.py b/tests/integration_tests/security/test_nv.py index ce848c6a789..5dd5acb2308 100644 --- a/tests/integration_tests/security/test_nv.py +++ b/tests/integration_tests/security/test_nv.py @@ -20,17 +20,15 @@ @pytest.fixture -def uvm_with_cpu_template( - microvm_factory, guest_kernel, rootfs_ubuntu_22, cpu_template_any -): +def uvm_with_cpu_template(microvm_factory, guest_kernel, rootfs, cpu_template_any): """A microvm fixture parametrized with all possible templates""" - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22) + vm = microvm_factory.build(guest_kernel, rootfs) vm.spawn() cpu_template = None if isinstance(cpu_template_any, str): cpu_template = cpu_template_any vm.basic_config(cpu_template=cpu_template) - if cpu_template is None: + if isinstance(cpu_template_any, dict): vm.api.cpu_config.put(**cpu_template_any["template"]) vm.add_net_iface() vm.start() diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py index d00aeb9d3c8..fed9dbc96d7 100644 --- a/tests/integration_tests/security/test_vulnerabilities.py +++ b/tests/integration_tests/security/test_vulnerabilities.py @@ -67,13 +67,13 @@ def configure_microvm( def build_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs, ): """Fixture returning a factory function for a normal microvm""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs, firecracker=firecracker, jailer=jailer, ) @@ -81,13 +81,13 @@ def build_microvm( @pytest.fixture def build_microvm_with_template( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, cpu_template + microvm_factory, guest_kernel_linux_5_10, rootfs, cpu_template ): """Fixture returning a factory function for microvms with our built-in template""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs, firecracker=firecracker, jailer=jailer, cpu_template=cpu_template, @@ -96,13 +96,13 @@ def build_microvm_with_template( @pytest.fixture def build_microvm_with_custom_template( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, custom_cpu_template + microvm_factory, guest_kernel_linux_5_10, rootfs, custom_cpu_template ): """Fixture returning a factory function for microvms with custom cpu templates""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs, firecracker=firecracker, jailer=jailer, custom_cpu_template=custom_cpu_template, diff --git a/tools/create_snapshot_artifact/main.py b/tools/create_snapshot_artifact/main.py deleted file mode 100755 index 75d439c1185..00000000000 --- a/tools/create_snapshot_artifact/main.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -"""Script used to generate snapshots of microVMs.""" - -import json -import os -import platform -import re -import shutil -import sys -from pathlib import Path - -# Hack to be able to import testing framework functions. -sys.path.append(os.path.join(os.getcwd(), "tests")) # noqa: E402 - -# pylint: disable=wrong-import-position -from framework.artifacts import disks, kernels -from framework.microvm import MicroVMFactory -from framework.utils import ( - configure_mmds, - generate_mmds_get_request, - generate_mmds_session_token, -) -from framework.utils_cpu_templates import get_supported_cpu_templates -from host_tools.cargo_build import get_firecracker_binaries - -# pylint: enable=wrong-import-position - -# Default IPv4 address to route MMDS requests. -IPV4_ADDRESS = "169.254.169.254" -NET_IFACE_FOR_MMDS = "eth3" -# Root directory for the snapshot artifacts. -SNAPSHOT_ARTIFACTS_ROOT_DIR = "snapshot_artifacts" - - -def populate_mmds(microvm, data_store): - """Populate MMDS contents with json data provided.""" - # MMDS should be empty. - response = microvm.api.mmds.get() - assert response.json() == {} - - # Populate MMDS with data. - microvm.api.mmds.put(**data_store) - - # Ensure data is persistent inside the data store. - response = microvm.api.mmds.get() - assert response.json() == data_store - - -def validate_mmds(ssh_connection, data_store): - """Validate that MMDS contents fetched from the guest.""" - # Configure interface to route MMDS requests - cmd = "ip route add {} dev {}".format(IPV4_ADDRESS, NET_IFACE_FOR_MMDS) - _, stdout, stderr = ssh_connection.run(cmd) - assert stdout == stderr == "" - - # Fetch metadata to ensure MMDS is accessible. - token = generate_mmds_session_token(ssh_connection, IPV4_ADDRESS, token_ttl=60) - - cmd = generate_mmds_get_request(IPV4_ADDRESS, token=token) - _, stdout, _ = ssh_connection.run(cmd) - assert json.loads(stdout) == data_store - - -def main(): - """ - Run the main logic. - - Create snapshot artifacts from complex microVMs with all Firecracker's - functionality enabled. The kernels are parametrized to include all guest - supported versions. - - Artifacts are saved in the following format: - snapshot_artifacts - | - -> __guest_snapshot - | - -> vm.mem - -> vm.vmstate - -> ubuntu-22.04.id_rsa - -> ubuntu-22.04.ext4 - -> __guest_snapshot - | - ... - """ - # Create directory dedicated to store snapshot artifacts for - # each guest kernel version. - print("Cleanup") - shutil.rmtree(SNAPSHOT_ARTIFACTS_ROOT_DIR, ignore_errors=True) - vm_factory = MicroVMFactory(*get_firecracker_binaries()) - - cpu_templates = [] - if platform.machine() == "x86_64": - cpu_templates = ["None"] - cpu_templates += get_supported_cpu_templates() - - for cpu_template in cpu_templates: - for kernel in kernels(glob="vmlinux-*"): - for rootfs in disks(glob="ubuntu-*.squashfs"): - print(kernel, rootfs, cpu_template) - vm = vm_factory.build(kernel, rootfs) - vm.spawn(log_level="Info") - vm.basic_config( - vcpu_count=2, - mem_size_mib=1024, - cpu_template=cpu_template, - track_dirty_pages=True, - ) - # Add 4 network devices - for i in range(4): - vm.add_net_iface() - # Add a vsock device - vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock") - # Add MMDS - configure_mmds(vm, ["eth3"], version="V2") - # Add a memory balloon. - vm.api.balloon.put( - amount_mib=0, deflate_on_oom=True, stats_polling_interval_s=1 - ) - - vm.start() - - # Populate MMDS. - data_store = { - "latest": { - "meta-data": { - "ami-id": "ami-12345678", - "reservation-id": "r-fea54097", - "local-hostname": "ip-10-251-50-12.ec2.internal", - "public-hostname": "ec2-203-0-113-25.compute-1.amazonaws.com", - } - } - } - populate_mmds(vm, data_store) - - # Iterate and validate connectivity on all ifaces after boot. - for i in range(4): - exit_code, _, _ = vm.ssh_iface(i).run("sync") - assert exit_code == 0 - - # Validate MMDS. - validate_mmds(vm.ssh, data_store) - - # Snapshot the microVM. - snapshot = vm.snapshot_diff() - - # Create snapshot artifacts directory specific for the kernel version used. - guest_kernel_version = re.search("vmlinux-(.*)", kernel.name) - - snapshot_artifacts_dir = ( - Path(SNAPSHOT_ARTIFACTS_ROOT_DIR) - / f"{guest_kernel_version.group(1)}_{cpu_template}_guest_snapshot" - ) - snapshot_artifacts_dir.mkdir(parents=True) - snapshot.save_to(snapshot_artifacts_dir) - print(f"Copied snapshot to: {snapshot_artifacts_dir}.") - - vm.kill() - - -if __name__ == "__main__": - main() diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index eef52632a6a..f0c7c36f759 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -75,7 +75,7 @@ RUN apt-get update \ screen tmux \ tzdata \ tini \ - squashfs-tools \ + squashfs-tools zstd \ # for aws-lc-rs cmake \ # for Qemu vhost-user-blk backend @@ -83,7 +83,7 @@ RUN apt-get update \ # for crosvm (vhost-user-blk backend) libcap2 \ # for debugging - gdb strace \ + gdb strace trace-cmd \ && rm -rf /var/lib/apt/lists/* \ && pip3 install --upgrade poetry @@ -107,7 +107,7 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && rustup target add x86_64-unknown-linux-musl \ && rustup target add aarch64-unknown-linux-musl \ && rustup component add llvm-tools-preview clippy rustfmt \ - && cargo install --locked cargo-audit cargo-deny grcov cargo-sort cargo-afl \ + && cargo install --locked cargo-audit cargo-deny@0.16.1 grcov cargo-sort cargo-afl \ && cargo install --locked kani-verifier && cargo kani setup \ \ && apt-get update \ diff --git a/tools/devtool b/tools/devtool index e9eb3d48db0..00e453486e3 100755 --- a/tools/devtool +++ b/tools/devtool @@ -417,7 +417,7 @@ cmd_help() { echo " build_ci_artifacts [all|rootfs|kernels]" echo " Builds the rootfs and guest kernel artifacts we use for our CI." echo " Run './tools/devtool build_ci_artifacts help' for more details about the available commands." - echo "" + echo "" cat <]] @@ -562,14 +562,12 @@ ensure_ci_artifacts() { # Fetch all the artifacts so they are local say "Fetching CI artifacts from S3" - S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.10/$(uname -m) + S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.11/$(uname -m) ARTIFACTS=$MICROVM_IMAGES_DIR/$(uname -m) if [ ! -d "$ARTIFACTS" ]; then mkdir -pv $ARTIFACTS aws s3 sync --no-sign-request "$S3_URL" "$ARTIFACTS" - # fix permissions - find "$ARTIFACTS" -type f -name "*.id_rsa" |xargs chmod -c 400 - find "$ARTIFACTS/firecracker" -type f |xargs chmod -c 755 + cmd_sh "./tools/setup-ci-artifacts.sh" fi } diff --git a/tools/sandbox.py b/tools/sandbox.py index fb15eb17fab..3cdcec345a7 100755 --- a/tools/sandbox.py +++ b/tools/sandbox.py @@ -68,11 +68,12 @@ def parse_byte_size(param): else: bins = get_firecracker_binaries() -print("This step may take a while to compile Firecracker ...") cpu_template = None if args.cpu_template_path is not None: cpu_template = json.loads(args.cpu_template_path.read_text()) vmfcty = MicroVMFactory(*bins) + +print(f"uvm with kernel {args.kernel} ...") uvm = vmfcty.build(args.kernel, args.rootfs) uvm.help.enable_console() uvm.help.resize_disk(uvm.rootfs_file, args.rootfs_size) @@ -85,3 +86,15 @@ def parse_byte_size(param): print(cpu_template) uvm.start() uvm.get_all_metrics() + +kernel_dbg_dir = args.kernel.parent / "debug" +kernel_dbg = kernel_dbg_dir / args.kernel.name +print(f"uvm2 with kernel {kernel_dbg} ...") +uvm2 = vmfcty.build(kernel_dbg, args.rootfs) +uvm2.spawn() +uvm2.add_net_iface() +uvm2.basic_config(vcpu_count=args.vcpus, mem_size_mib=args.guest_mem_size // 2**20) +uvm2.start() +# trace-cmd needs this (DNS resolution?) +uvm2.help.enable_ip_forwarding() +files = uvm2.help.trace_cmd_guest(["-l", "read_msr"], cmd="sleep 5") diff --git a/tools/setup-ci-artifacts.sh b/tools/setup-ci-artifacts.sh new file mode 100755 index 00000000000..0d524658b51 --- /dev/null +++ b/tools/setup-ci-artifacts.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +# fail if we encounter an error, uninitialized variable or a pipe breaks +set -eu -o pipefail + +TOOLS_DIR=$(dirname $0) +source "$TOOLS_DIR/functions" + +say "Setup CI artifacts" +cd build/img/$(uname -m) + +say "Fix executable permissions" +find "firecracker" -type f |xargs chmod -c 755 + +say "Generate SSH key to connect from host" +if [ ! -s id_rsa ]; then + ssh-keygen -f id_rsa -N "" +fi + +for SQUASHFS in *.squashfs; do + say "Include SSH key in $SQUASHFS" + RSA=$(basename $SQUASHFS .squashfs).id_rsa + EXT4=$(basename $SQUASHFS .squashfs).ext4 + [ -s $SQUASHFS.orig ] && continue + unsquashfs $SQUASHFS + mkdir -pv squashfs-root/root/.ssh + # copy the SSH key into the rootfs + if [ ! -s $RSA ]; then + # append SSH key to the squashfs image + cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys + cp -v id_rsa $RSA + fi + # re-squash + mv -v $SQUASHFS $SQUASHFS.orig + mksquashfs squashfs-root $SQUASHFS -all-root -noappend -comp zstd + + # Create rw ext4 image from ro squashfs + [ -f $EXT4 ] && continue + say "Converting $SQUASHFS to $EXT4" + truncate -s 400M $EXT4 + mkfs.ext4 -F $EXT4 -d squashfs-root + rm -rf squashfs-root +done + +say "Uncompress debuginfo files" +find . -name "*.debug.gz" -print0 | xargs -P4 -0 -t -n1 gunzip