mirror of
				https://github.com/kata-containers/kata-containers.git
				synced 2025-10-31 09:26:52 +00:00 
			
		
		
		
	gha: vfio: Import jobs scripts from tests repo
This imports the vfio test scripts github.com/kata-containers/tests. The test case doesn't work yet but doing the changes in a separate commit will make it easier to track the changes. The only change in this commit is renaming vfio_jenkins_job_build.sh -> vfio_fedora_vm_wrapper.sh Fixes: #6555 Signed-off-by: Jeremi Piotrowski <jpiotrowski@microsoft.com>
This commit is contained in:
		| @@ -19,6 +19,7 @@ function install_dependencies() { | ||||
|  | ||||
| function run() { | ||||
| 	info "Running cri-containerd tests using ${KATA_HYPERVISOR} hypervisor" | ||||
| 	"${vfio_dir}"/vfio_fedora_vm_wrapper.sh | ||||
| } | ||||
|  | ||||
| function main() { | ||||
|   | ||||
							
								
								
									
										176
									
								
								tests/functional/vfio/guest-kernel.json.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								tests/functional/vfio/guest-kernel.json.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| # | ||||
| # Copyright (c) 2021 Intel Corporation | ||||
| # | ||||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # | ||||
| { | ||||
| 	"ociVersion": "1.0.0-rc2-dev", | ||||
| 	"platform": { | ||||
| 		"os": "linux", | ||||
| 		"arch": "amd64" | ||||
| 	}, | ||||
| 	"annotations": { | ||||
| 		"io.katacontainers.config.hypervisor.enable_iommu": "false", | ||||
| 		"io.katacontainers.config.runtime.vfio_mode": "guest-kernel" | ||||
| 	}, | ||||
| 	"process": { | ||||
| 		"terminal": false, | ||||
| 		"consoleSize": { | ||||
| 			"height": 0, | ||||
| 			"width": 0 | ||||
| 		}, | ||||
| 		"user": { | ||||
| 			"uid": 0, | ||||
| 			"gid": 0 | ||||
| 		}, | ||||
| 		"args": [ "/bin/tail", "-f", "/dev/null" ], | ||||
| 		"env": [ | ||||
| 			"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", | ||||
| 			"TERM=xterm" | ||||
| 		], | ||||
| 		"cwd": "/", | ||||
| 		"rlimits": [{ | ||||
| 			"type": "RLIMIT_NOFILE", | ||||
| 			"hard": 1024, | ||||
| 			"soft": 1024 | ||||
| 		}], | ||||
| 		"noNewPrivileges": true | ||||
| 	}, | ||||
| 	"root": { | ||||
| 		"path": "@ROOTFS@", | ||||
| 		"readonly": false | ||||
| 	}, | ||||
| 	"hostname": "vfio-test", | ||||
| 	"mounts": [{ | ||||
| 			"destination": "/proc", | ||||
| 			"type": "proc", | ||||
| 			"source": "proc" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/dev", | ||||
| 			"type": "tmpfs", | ||||
| 			"source": "tmpfs", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"strictatime", | ||||
| 				"mode=755", | ||||
| 				"size=65536k" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/dev/pts", | ||||
| 			"type": "devpts", | ||||
| 			"source": "devpts", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"newinstance", | ||||
| 				"ptmxmode=0666", | ||||
| 				"mode=0620", | ||||
| 				"gid=5" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/dev/shm", | ||||
| 			"type": "tmpfs", | ||||
| 			"source": "shm", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"nodev", | ||||
| 				"mode=1777", | ||||
| 				"size=65536k" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/dev/mqueue", | ||||
| 			"type": "mqueue", | ||||
| 			"source": "mqueue", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"nodev" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/sys", | ||||
| 			"type": "sysfs", | ||||
| 			"source": "sysfs", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"nodev", | ||||
| 				"ro" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/sys/fs/cgroup", | ||||
| 			"type": "cgroup", | ||||
| 			"source": "cgroup", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"nodev", | ||||
| 				"relatime", | ||||
| 				"ro" | ||||
| 			] | ||||
| 		} | ||||
| 	], | ||||
| 	"hooks": {}, | ||||
| 	"linux": { | ||||
| 		"devices": [{ | ||||
| 			"path": "@VFIO_PATH@", | ||||
| 			"type": "c", | ||||
| 			"major": @VFIO_MAJOR@, | ||||
| 			"minor": @VFIO_MINOR@, | ||||
| 			"fileMode": 384, | ||||
| 			"uid": 0, | ||||
| 			"gid": 0 | ||||
| 		}], | ||||
| 		"cgroupsPath": "kata/vfiotest", | ||||
| 		"resources": { | ||||
| 			"devices": [ | ||||
| 				{"allow":false,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":1,"minor":3,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":1,"minor":5,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":1,"minor":8,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":1,"minor":9,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":5,"minor":0,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":5,"minor":1,"access":"rwm"}, | ||||
| 				{"allow": true,"access": "rwm","major": @VFIO_MAJOR@,"minor": @VFIO_MINOR@,"type": "c"} | ||||
| 			] | ||||
| 		}, | ||||
| 		"namespaces": [{ | ||||
| 				"type": "pid" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "network" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "ipc" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "uts" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "mount" | ||||
| 			} | ||||
| 		], | ||||
| 		"maskedPaths": [ | ||||
| 			"/proc/kcore", | ||||
| 			"/proc/latency_stats", | ||||
| 			"/proc/timer_list", | ||||
| 			"/proc/timer_stats", | ||||
| 			"/proc/sched_debug", | ||||
| 			"/sys/firmware" | ||||
| 		], | ||||
| 		"readonlyPaths": [ | ||||
| 			"/proc/asound", | ||||
| 			"/proc/bus", | ||||
| 			"/proc/fs", | ||||
| 			"/proc/irq", | ||||
| 			"/proc/sys", | ||||
| 			"/proc/sysrq-trigger" | ||||
| 		] | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										341
									
								
								tests/functional/vfio/run.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										341
									
								
								tests/functional/vfio/run.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,341 @@ | ||||
| #!/bin/bash | ||||
| # | ||||
| # Copyright (c) 2021 Intel Corporation | ||||
| # | ||||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # | ||||
|  | ||||
| set -x | ||||
| set -o errexit | ||||
| set -o nounset | ||||
| set -o pipefail | ||||
| set -o errtrace | ||||
|  | ||||
| script_path=$(dirname "$0") | ||||
| source "${script_path}/../../common.bash" | ||||
|  | ||||
| addr= | ||||
| tmp_data_dir="$(mktemp -d)" | ||||
| rootfs_tar="${tmp_data_dir}/rootfs.tar" | ||||
| trap cleanup EXIT | ||||
|  | ||||
| # kata-runtime options | ||||
| SANDBOX_CGROUP_ONLY="" | ||||
| HYPERVISOR= | ||||
| MACHINE_TYPE= | ||||
| IMAGE_TYPE= | ||||
|  | ||||
| cleanup() { | ||||
| 	clean_env_ctr | ||||
| 	sudo rm -rf "${tmp_data_dir}" | ||||
|  | ||||
| 	[ -n "${host_pci}" ] && sudo driverctl unset-override "${host_pci}" | ||||
| } | ||||
|  | ||||
| host_pci_addr() { | ||||
| 	lspci -D | grep "Ethernet controller" | grep "Virtio.*network device" | tail -1 | cut -d' ' -f1 | ||||
| } | ||||
|  | ||||
| get_vfio_path() { | ||||
| 	local addr="$1" | ||||
| 	echo "/dev/vfio/$(basename $(realpath /sys/bus/pci/drivers/vfio-pci/${host_pci}/iommu_group))" | ||||
| } | ||||
|  | ||||
| pull_rootfs() { | ||||
| 	# pull and export busybox image in tar file | ||||
| 	local image="quay.io/prometheus/busybox:latest" | ||||
| 	sudo -E ctr i pull ${image} | ||||
| 	sudo -E ctr i export "${rootfs_tar}" "${image}" | ||||
| 	sudo chown ${USER}:${USER} "${rootfs_tar}" | ||||
| 	sync | ||||
| } | ||||
|  | ||||
| create_bundle() { | ||||
| 	local bundle_dir="$1" | ||||
| 	mkdir -p "${bundle_dir}" | ||||
|  | ||||
| 	# extract busybox rootfs | ||||
| 	local rootfs_dir="${bundle_dir}/rootfs" | ||||
| 	mkdir -p "${rootfs_dir}" | ||||
| 	local layers_dir="$(mktemp -d)" | ||||
| 	tar -C "${layers_dir}" -pxf "${rootfs_tar}" | ||||
| 	for ((i=0;i<$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers | length");i++)); do | ||||
| 		tar -C ${rootfs_dir} -xf ${layers_dir}/$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers[${i}]") | ||||
| 	done | ||||
| 	sync | ||||
|  | ||||
| 	# Copy config.json | ||||
| 	cp -a "${script_path}/config.json" "${bundle_dir}/config.json" | ||||
| } | ||||
|  | ||||
| run_container() { | ||||
| 	local container_id="$1" | ||||
| 	local bundle_dir="$2" | ||||
|  | ||||
| 	sudo -E ctr run -d --runtime io.containerd.kata.v2 --config "${bundle_dir}/config.json" "${container_id}" | ||||
| } | ||||
|  | ||||
|  | ||||
| get_ctr_cmd_output() { | ||||
| 	local container_id="$1" | ||||
| 	shift | ||||
| 	sudo -E ctr t exec --exec-id 2 "${container_id}" "${@}" | ||||
| } | ||||
|  | ||||
| check_guest_kernel() { | ||||
| 	local container_id="$1" | ||||
| 	# For vfio_mode=guest-kernel, the device should be bound to | ||||
| 	# the guest kernel's native driver.  To check this has worked, | ||||
| 	# we look for an ethernet device named 'eth*' | ||||
| 	get_ctr_cmd_output "${container_id}" ip a | grep "eth" || die "Missing VFIO network interface" | ||||
| } | ||||
|  | ||||
| check_vfio() { | ||||
| 	local cid="$1" | ||||
| 	# For vfio_mode=vfio, the device should be bound to the guest | ||||
| 	# vfio-pci driver. | ||||
|  | ||||
| 	# Check the control device is visible | ||||
| 	get_ctr_cmd_output "${cid}" ls /dev/vfio/vfio || die "Couldn't find VFIO control device in container" | ||||
|  | ||||
| 	# The device should *not* cause an ethernet interface to appear | ||||
| 	! get_ctr_cmd_output "${cid}" ip a | grep "eth" || die "Unexpected network interface" | ||||
|  | ||||
| 	# There should be exactly one VFIO group device (there might | ||||
| 	# be multiple IOMMU groups in the VM, but only one device | ||||
| 	# should be bound to the VFIO driver, so there should still | ||||
| 	# only be one VFIO device | ||||
| 	group="$(get_ctr_cmd_output "${cid}" ls /dev/vfio | grep -v vfio)" | ||||
| 	if [ $(echo "${group}" | wc -w) != "1" ] ; then | ||||
| 	    die "Expected exactly one VFIO group got: ${group}" | ||||
| 	fi | ||||
|  | ||||
| 	# There should be two devices in the IOMMU group: the ethernet | ||||
| 	# device we care about, plus the PCIe to PCI bridge device | ||||
| 	devs="$(get_ctr_cmd_output "${cid}" ls /sys/kernel/iommu_groups/"${group}"/devices)" | ||||
| 	if [ $(echo "${devs}" | wc -w) != "2" ] ; then | ||||
| 	    die "Expected exactly two devices got: ${devs}" | ||||
| 	fi | ||||
|  | ||||
| 	# The bridge device will always sort first, because it is on | ||||
| 	# bus zero, whereas the NIC will be on a non-zero bus | ||||
| 	guest_pci=$(echo "${devs}" | tail -1) | ||||
|  | ||||
| 	# This is a roundabout way of getting the environment | ||||
| 	# variable, but to use the more obvious "echo $PCIDEVICE_..." | ||||
| 	# we would have to escape the '$' enough to not be expanded | ||||
| 	# before it's injected into the container, but not so much | ||||
| 	# that it *is* expanded by the shell within the container. | ||||
| 	# Doing that with another shell function in between is very | ||||
| 	# fragile, so do it this way instead. | ||||
| 	guest_env="$(get_ctr_cmd_output "${cid}" env | grep ^PCIDEVICE_VIRTIO_NET | sed s/^[^=]*=//)" | ||||
| 	if [ "${guest_env}" != "${guest_pci}" ]; then | ||||
| 	    die "PCIDEVICE variable was \"${guest_env}\" instead of \"${guest_pci}\"" | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| get_dmesg() { | ||||
| 	local container_id="$1" | ||||
| 	get_ctr_cmd_output "${container_id}" dmesg | ||||
| } | ||||
|  | ||||
| # Show help about this script | ||||
| help(){ | ||||
| cat << EOF | ||||
| Usage: $0 [-h] [options] | ||||
|     Description: | ||||
|         This script runs a kata container and passthrough a vfio device | ||||
|     Options: | ||||
|         -h,          Help | ||||
|         -i <string>, Specify initrd or image | ||||
|         -m <string>, Specify kata-runtime machine type for qemu hypervisor | ||||
|         -p <string>, Specify kata-runtime hypervisor | ||||
|         -s <value>,  Set sandbox_cgroup_only in the configuration file | ||||
| EOF | ||||
| } | ||||
|  | ||||
| setup_configuration_file() { | ||||
| 	local qemu_config_file="configuration-qemu.toml" | ||||
| 	local clh_config_file="configuration-clh.toml" | ||||
| 	local image_file="/opt/kata/share/kata-containers/kata-containers.img" | ||||
| 	local initrd_file="/opt/kata/share/kata-containers/kata-containers-initrd.img" | ||||
| 	local kata_config_file="" | ||||
|  | ||||
| 	for file in $(kata-runtime --kata-show-default-config-paths); do | ||||
| 		if [ ! -f "${file}" ]; then | ||||
| 			continue | ||||
| 		fi | ||||
|  | ||||
| 		kata_config_file="${file}" | ||||
| 		config_dir=$(dirname ${file}) | ||||
| 		config_filename="" | ||||
|  | ||||
| 		if [ "$HYPERVISOR" = "qemu" ]; then | ||||
| 			config_filename="${qemu_config_file}" | ||||
| 		elif [ "$HYPERVISOR" = "clh" ]; then | ||||
| 			config_filename="${clh_config_file}" | ||||
| 		fi | ||||
|  | ||||
| 		config_file="${config_dir}/${config_filename}" | ||||
| 		if [ -f "${config_file}" ]; then | ||||
| 			rm -f "${kata_config_file}" | ||||
| 			cp -a $(realpath "${config_file}") "${kata_config_file}" | ||||
| 			break | ||||
| 		fi | ||||
| 	done | ||||
|  | ||||
| 	# machine type applies to configuration.toml and configuration-qemu.toml | ||||
| 	if [ -n "$MACHINE_TYPE" ]; then | ||||
| 		if [ "$HYPERVISOR" = "qemu" ]; then | ||||
| 			sed -i 's|^machine_type.*|machine_type = "'${MACHINE_TYPE}'"|g' "${kata_config_file}" | ||||
| 			# Make sure we have set hot_plug_vfio to a reasonable value | ||||
| 			sudo sed -i -e 's|^#hot_plug_vfio =.*$|hot_plug_vfio = "bridge-port"|' -e 's|^hot_plug_vfio = .*$|hot_plug_vfio = "bridge-port"|' "${kata_config_file}" | ||||
| 		else | ||||
| 			warn "Variable machine_type only applies to qemu. It will be ignored" | ||||
| 		fi | ||||
| 	fi | ||||
|  | ||||
| 	if [ -n "${SANDBOX_CGROUP_ONLY}" ]; then | ||||
| 	   sed -i 's|^sandbox_cgroup_only.*|sandbox_cgroup_only='${SANDBOX_CGROUP_ONLY}'|g' "${kata_config_file}" | ||||
| 	fi | ||||
|  | ||||
| 	# Change to initrd or image depending on user input. | ||||
| 	# Non-default configs must be changed to specify either initrd or image, image is default. | ||||
| 	if [ "$IMAGE_TYPE" = "initrd" ]; then | ||||
| 		if $(grep -q "^image.*" ${kata_config_file}); then | ||||
| 			if $(grep -q "^initrd.*" ${kata_config_file}); then | ||||
| 				sed -i '/^image.*/d' "${kata_config_file}" | ||||
| 			else | ||||
| 				sed -i 's|^image.*|initrd = "'${initrd_file}'"|g' "${kata_config_file}" | ||||
| 			fi | ||||
| 		fi | ||||
| 	else | ||||
| 		if $(grep -q "^initrd.*" ${kata_config_file}); then | ||||
| 			if $(grep -q "^image.*" ${kata_config_file}); then | ||||
| 				sed -i '/^initrd.*/d' "${kata_config_file}" | ||||
| 			else | ||||
| 				sed -i 's|^initrd.*|image = "'${image_file}'"|g' "${kata_config_file}" | ||||
| 			fi | ||||
| 		fi | ||||
| 	fi | ||||
|  | ||||
| 	# enable debug | ||||
| 	sed -i -e 's/^#\(enable_debug\).*=.*$/\1 = true/g' \ | ||||
| 	       -e 's/^#\(debug_console_enabled\).*=.*$/\1 = true/g' \ | ||||
| 	       -e 's/^kernel_params = "\(.*\)"/kernel_params = "\1 agent.log=debug"/g' \ | ||||
| 	       "${kata_config_file}" | ||||
|  | ||||
| 	# enable VFIO relevant hypervisor annotations | ||||
| 	sed -i -e 's/^\(enable_annotations\).*=.*$/\1 = ["enable_iommu"]/' \ | ||||
| 		"${kata_config_file}" | ||||
| } | ||||
|  | ||||
| run_test_container() { | ||||
| 	local container_id="$1" | ||||
| 	local bundle_dir="$2" | ||||
| 	local config_json_in="$3" | ||||
| 	local host_pci="$4" | ||||
|  | ||||
| 	# generate final config.json | ||||
| 	sed -e '/^#.*/d' \ | ||||
| 	    -e 's|@VFIO_PATH@|'"${vfio_device}"'|g' \ | ||||
| 	    -e 's|@VFIO_MAJOR@|'"${vfio_major}"'|g' \ | ||||
| 	    -e 's|@VFIO_MINOR@|'"${vfio_minor}"'|g' \ | ||||
| 	    -e 's|@VFIO_CTL_MAJOR@|'"${vfio_ctl_major}"'|g' \ | ||||
| 	    -e 's|@VFIO_CTL_MINOR@|'"${vfio_ctl_minor}"'|g' \ | ||||
| 	    -e 's|@ROOTFS@|'"${bundle_dir}/rootfs"'|g' \ | ||||
| 	    -e 's|@HOST_PCI@|'"${host_pci}"'|g' \ | ||||
| 	    "${config_json_in}" > "${script_path}/config.json" | ||||
|  | ||||
| 	create_bundle "${bundle_dir}" | ||||
|  | ||||
| 	# run container | ||||
| 	run_container "${container_id}" "${bundle_dir}" | ||||
|  | ||||
| 	# output VM dmesg | ||||
| 	get_dmesg "${container_id}" | ||||
| } | ||||
|  | ||||
| main() { | ||||
| 	local OPTIND | ||||
| 	while getopts "hi:m:p:s:" opt;do | ||||
| 		case ${opt} in | ||||
| 		h) | ||||
| 		    help | ||||
| 		    exit 0; | ||||
| 		    ;; | ||||
| 		i) | ||||
| 		    IMAGE_TYPE="${OPTARG}" | ||||
| 		    ;; | ||||
| 		m) | ||||
| 		    MACHINE_TYPE="${OPTARG}" | ||||
| 		    ;; | ||||
| 		p) | ||||
| 		    HYPERVISOR="${OPTARG}" | ||||
| 		    ;; | ||||
| 		s) | ||||
| 		    SANDBOX_CGROUP_ONLY="${OPTARG}" | ||||
| 		    ;; | ||||
| 		?) | ||||
| 		    # parse failure | ||||
| 		    help | ||||
| 		    die "Failed to parse arguments" | ||||
| 		    ;; | ||||
| 		esac | ||||
| 	done | ||||
| 	shift $((OPTIND-1)) | ||||
|  | ||||
| 	# | ||||
| 	# Get the device ready on the host | ||||
| 	# | ||||
| 	setup_configuration_file | ||||
|  | ||||
| 	restart_containerd_service | ||||
| 	sudo modprobe vfio | ||||
| 	sudo modprobe vfio-pci | ||||
|  | ||||
| 	host_pci=$(host_pci_addr) | ||||
| 	[ -n "${host_pci}" ] || die "virtio ethernet controller PCI address not found" | ||||
|  | ||||
| 	cat /proc/cmdline | grep -q "intel_iommu=on" || \ | ||||
| 		die "intel_iommu=on not found in kernel cmdline" | ||||
|  | ||||
| 	sudo driverctl set-override "${host_pci}" vfio-pci | ||||
|  | ||||
| 	vfio_device="$(get_vfio_path "${host_pci}")" | ||||
| 	[ -n "${vfio_device}" ] || die "vfio device not found" | ||||
| 	vfio_major="$(printf '%d' $(stat -c '0x%t' ${vfio_device}))" | ||||
| 	vfio_minor="$(printf '%d' $(stat -c '0x%T' ${vfio_device}))" | ||||
|  | ||||
| 	[ -n "/dev/vfio/vfio" ] || die "vfio control device not found" | ||||
| 	vfio_ctl_major="$(printf '%d' $(stat -c '0x%t' /dev/vfio/vfio))" | ||||
| 	vfio_ctl_minor="$(printf '%d' $(stat -c '0x%T' /dev/vfio/vfio))" | ||||
|  | ||||
| 	# Get the rootfs we'll use for all tests | ||||
| 	pull_rootfs | ||||
|  | ||||
| 	# | ||||
| 	# Run the tests | ||||
| 	# | ||||
|  | ||||
| 	# test for guest-kernel mode | ||||
| 	guest_kernel_cid="vfio-guest-kernel-${RANDOM}" | ||||
| 	run_test_container "${guest_kernel_cid}" \ | ||||
| 			   "${tmp_data_dir}/vfio-guest-kernel" \ | ||||
| 			   "${script_path}/guest-kernel.json.in" \ | ||||
| 			   "${host_pci}" | ||||
| 	check_guest_kernel "${guest_kernel_cid}" | ||||
|  | ||||
| 	# Remove the container so we can re-use the device for the next test | ||||
| 	clean_env_ctr | ||||
|  | ||||
| 	# test for vfio mode | ||||
| 	vfio_cid="vfio-vfio-${RANDOM}" | ||||
| 	run_test_container "${vfio_cid}" \ | ||||
| 			   "${tmp_data_dir}/vfio-vfio" \ | ||||
| 			   "${script_path}/vfio.json.in" \ | ||||
| 			   "${host_pci}" | ||||
| 	check_vfio "${vfio_cid}" | ||||
| } | ||||
|  | ||||
| main $@ | ||||
							
								
								
									
										187
									
								
								tests/functional/vfio/vfio.json.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								tests/functional/vfio/vfio.json.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| # | ||||
| # Copyright (c) 2021 Intel Corporation | ||||
| # | ||||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # | ||||
| { | ||||
| 	"ociVersion": "1.0.0-rc2-dev", | ||||
| 	"platform": { | ||||
| 		"os": "linux", | ||||
| 		"arch": "amd64" | ||||
| 	}, | ||||
| 	"annotations": { | ||||
| 		"io.katacontainers.config.hypervisor.enable_iommu": "true", | ||||
| 		"io.katacontainers.config.runtime.vfio_mode": "vfio" | ||||
| 	}, | ||||
| 	"process": { | ||||
| 		"terminal": false, | ||||
| 		"consoleSize": { | ||||
| 			"height": 0, | ||||
| 			"width": 0 | ||||
| 		}, | ||||
| 		"user": { | ||||
| 			"uid": 0, | ||||
| 			"gid": 0 | ||||
| 		}, | ||||
| 		"args": [ "/bin/tail", "-f", "/dev/null" ], | ||||
| 		"env": [ | ||||
| 			"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", | ||||
| 			"TERM=xterm", | ||||
| 			"PCIDEVICE_VIRTIO_NET=@HOST_PCI@" | ||||
| 		], | ||||
| 		"cwd": "/", | ||||
| 		"rlimits": [{ | ||||
| 			"type": "RLIMIT_NOFILE", | ||||
| 			"hard": 1024, | ||||
| 			"soft": 1024 | ||||
| 		}], | ||||
| 		"noNewPrivileges": true | ||||
| 	}, | ||||
| 	"root": { | ||||
| 		"path": "@ROOTFS@", | ||||
| 		"readonly": false | ||||
| 	}, | ||||
| 	"hostname": "vfio-test", | ||||
| 	"mounts": [{ | ||||
| 			"destination": "/proc", | ||||
| 			"type": "proc", | ||||
| 			"source": "proc" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/dev", | ||||
| 			"type": "tmpfs", | ||||
| 			"source": "tmpfs", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"strictatime", | ||||
| 				"mode=755", | ||||
| 				"size=65536k" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/dev/pts", | ||||
| 			"type": "devpts", | ||||
| 			"source": "devpts", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"newinstance", | ||||
| 				"ptmxmode=0666", | ||||
| 				"mode=0620", | ||||
| 				"gid=5" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/dev/shm", | ||||
| 			"type": "tmpfs", | ||||
| 			"source": "shm", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"nodev", | ||||
| 				"mode=1777", | ||||
| 				"size=65536k" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/dev/mqueue", | ||||
| 			"type": "mqueue", | ||||
| 			"source": "mqueue", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"nodev" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/sys", | ||||
| 			"type": "sysfs", | ||||
| 			"source": "sysfs", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"nodev", | ||||
| 				"ro" | ||||
| 			] | ||||
| 		}, | ||||
| 		{ | ||||
| 			"destination": "/sys/fs/cgroup", | ||||
| 			"type": "cgroup", | ||||
| 			"source": "cgroup", | ||||
| 			"options": [ | ||||
| 				"nosuid", | ||||
| 				"noexec", | ||||
| 				"nodev", | ||||
| 				"relatime", | ||||
| 				"ro" | ||||
| 			] | ||||
| 		} | ||||
| 	], | ||||
| 	"hooks": {}, | ||||
| 	"linux": { | ||||
| 		"devices": [{ | ||||
| 			"path": "/dev/vfio/vfio", | ||||
| 			"type": "c", | ||||
| 			"major": @VFIO_CTL_MAJOR@, | ||||
| 			"minor": @VFIO_CTL_MINOR@, | ||||
| 			"fileMode": 438, | ||||
| 			"uid": 0, | ||||
| 			"gid": 0 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"path": "@VFIO_PATH@", | ||||
| 			"type": "c", | ||||
| 			"major": @VFIO_MAJOR@, | ||||
| 			"minor": @VFIO_MINOR@, | ||||
| 			"fileMode": 384, | ||||
| 			"uid": 0, | ||||
| 			"gid": 0 | ||||
| 		}], | ||||
| 		"cgroupsPath": "kata/vfiotest", | ||||
| 		"resources": { | ||||
| 			"devices": [ | ||||
| 				{"allow":false,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":1,"minor":3,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":1,"minor":5,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":1,"minor":8,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":1,"minor":9,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":5,"minor":0,"access":"rwm"}, | ||||
| 				{"allow":true,"type":"c","major":5,"minor":1,"access":"rwm"}, | ||||
| 				{"allow": true,"access": "rwm","major": @VFIO_CTL_MAJOR@,"minor": @VFIO_CTL_MINOR@,"type": "c"}, | ||||
| 				{"allow": true,"access": "rwm","major": @VFIO_MAJOR@,"minor": @VFIO_MINOR@,"type": "c"} | ||||
| 			] | ||||
| 		}, | ||||
| 		"namespaces": [{ | ||||
| 				"type": "pid" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "network" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "ipc" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "uts" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "mount" | ||||
| 			} | ||||
| 		], | ||||
| 		"maskedPaths": [ | ||||
| 			"/proc/kcore", | ||||
| 			"/proc/latency_stats", | ||||
| 			"/proc/timer_list", | ||||
| 			"/proc/timer_stats", | ||||
| 			"/proc/sched_debug", | ||||
| 			"/sys/firmware" | ||||
| 		], | ||||
| 		"readonlyPaths": [ | ||||
| 			"/proc/asound", | ||||
| 			"/proc/bus", | ||||
| 			"/proc/fs", | ||||
| 			"/proc/irq", | ||||
| 			"/proc/sys", | ||||
| 			"/proc/sysrq-trigger" | ||||
| 		] | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										320
									
								
								tests/functional/vfio/vfio_fedora_vm_wrapper.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										320
									
								
								tests/functional/vfio/vfio_fedora_vm_wrapper.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,320 @@ | ||||
| #!/bin/bash | ||||
| # | ||||
| # Copyright (c) 2020 Intel Corporation | ||||
| # | ||||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # | ||||
|  | ||||
| # Run the .ci/jenkins_job_build.sh script in a VM | ||||
| # that supports VFIO, then run VFIO functional tests | ||||
|  | ||||
| set -o xtrace | ||||
| set -o errexit | ||||
| set -o nounset | ||||
| set -o pipefail | ||||
| set -o errtrace | ||||
|  | ||||
| cidir=$(dirname "$0") | ||||
|  | ||||
| source /etc/os-release || source /usr/lib/os-release | ||||
| # <CHANGES HERE> | ||||
| #source "${cidir}/lib.sh" | ||||
| export WORKSPACE="${WORKSPACE:-${cidir}/../../..}" | ||||
| export GIT_URL="https://github.com/kata-containers/kata-containers.git" | ||||
| # </CHANGES> | ||||
|  | ||||
| http_proxy=${http_proxy:-} | ||||
| https_proxy=${https_proxy:-} | ||||
| vm_ip="127.0.15.1" | ||||
| vm_port="10022" | ||||
| # Don't save data in /tmp, we need it after rebooting the system | ||||
| data_dir="${HOME}/functional-vfio-test" | ||||
| ssh_key_file="${data_dir}/key" | ||||
| arch=$(uname -m) | ||||
| artifacts_dir="${WORKSPACE}/artifacts" | ||||
|  | ||||
| kill_vms() { | ||||
| 	sudo killall -9 qemu-system-${arch} | ||||
| } | ||||
|  | ||||
| cleanup() { | ||||
| 	mkdir -p ${artifacts_dir} | ||||
| 	sudo chown -R ${USER} ${artifacts_dir} | ||||
| 	scp_vm ${artifacts_dir}/* ${artifacts_dir} || true | ||||
| 	kill_vms | ||||
| } | ||||
|  | ||||
| create_ssh_key() { | ||||
| 	rm -f "${ssh_key_file}" | ||||
| 	ssh-keygen -f "${ssh_key_file}" -t rsa -N "" | ||||
| } | ||||
|  | ||||
| create_meta_data() { | ||||
| 	file="$1" | ||||
| 	cat <<EOF > "${file}" | ||||
| { | ||||
|   "uuid": "d1b4aafa-5d75-4f9c-87eb-2ceabe110c39", | ||||
|   "hostname": "test" | ||||
| } | ||||
| EOF | ||||
| } | ||||
|  | ||||
| create_user_data() { | ||||
| 	file="$1" | ||||
| 	ssh_pub_key_file="$2" | ||||
|  | ||||
| 	ssh_pub_key="$(cat "${ssh_pub_key_file}")" | ||||
| 	dnf_proxy="" | ||||
| 	service_proxy="" | ||||
| 	docker_user_proxy="{}" | ||||
| 	environment=$(env | egrep "ghprb|WORKSPACE|KATA|GIT|JENKINS|_PROXY|_proxy" | \ | ||||
| 	                    sed -e "s/'/'\"'\"'/g" \ | ||||
| 	                        -e "s/\(^[[:alnum:]_]\+\)=/\1='/" \ | ||||
| 	                        -e "s/$/'/" \ | ||||
| 	                        -e 's/^/    export /') | ||||
|  | ||||
| 	if [ -n "${http_proxy}" ] && [ -n "${https_proxy}" ]; then | ||||
| 		dnf_proxy="proxy=${http_proxy}" | ||||
| 		service_proxy='[Service] | ||||
|     Environment="HTTP_PROXY='${http_proxy}'" "HTTPS_PROXY='${https_proxy}'" "NO_PROXY='${no_proxy}'"' | ||||
| 		docker_user_proxy='{"proxies": { "default": { | ||||
|     "httpProxy": "'${http_proxy}'", | ||||
|     "httpsProxy": "'${https_proxy}'", | ||||
|     "noProxy": "'${no_proxy}'" | ||||
|     } } }' | ||||
| 	fi | ||||
|  | ||||
| 	cat <<EOF > "${file}" | ||||
| #cloud-config | ||||
| package_upgrade: false | ||||
| runcmd: | ||||
| - chown -R ${USER}:${USER} /home/${USER} | ||||
| - touch /.done | ||||
| users: | ||||
| - gecos: User | ||||
|   gid: "1000" | ||||
|   lock-passwd: true | ||||
|   name: ${USER} | ||||
|   shell: /bin/bash | ||||
|   ssh-authorized-keys: | ||||
|   - ${ssh_pub_key} | ||||
|   sudo: ALL=(ALL) NOPASSWD:ALL | ||||
|   uid: "1000" | ||||
| write_files: | ||||
| - content: | | ||||
| ${environment} | ||||
|   path: /etc/environment | ||||
| - content: | | ||||
|     ${service_proxy} | ||||
|   path: /etc/systemd/system/docker.service.d/http-proxy.conf | ||||
| - content: | | ||||
|     ${service_proxy} | ||||
|   path: /etc/systemd/system/containerd.service.d/http-proxy.conf | ||||
| - content: | | ||||
|     ${docker_user_proxy} | ||||
|   path: ${HOME}/.docker/config.json | ||||
| - content: | | ||||
|     ${docker_user_proxy} | ||||
|   path: /root/.docker/config.json | ||||
| - content: | | ||||
|     set -x | ||||
|     set -o errexit | ||||
|     set -o nounset | ||||
|     set -o pipefail | ||||
|     set -o errtrace | ||||
|     . /etc/environment | ||||
|     . /etc/os-release | ||||
|  | ||||
|     [ "\$ID" = "fedora" ] || (echo >&2 "$0 only supports Fedora"; exit 1) | ||||
|  | ||||
|     echo "${dnf_proxy}" | sudo tee -a /etc/dnf/dnf.conf | ||||
|  | ||||
|     for i in \$(seq 1 50); do | ||||
|         [ -f /.done ] && break | ||||
|         echo "waiting for cloud-init to finish" | ||||
|         sleep 5; | ||||
|     done | ||||
|  | ||||
|     export FORCE_JENKINS_JOB_BUILD=1 | ||||
|     export DEBUG=true | ||||
|     export CI_JOB="VFIO" | ||||
|     export GOPATH=\${WORKSPACE}/go | ||||
|     export PATH=\${GOPATH}/bin:/usr/local/go/bin:/usr/sbin:\${PATH} | ||||
|     export GOROOT="/usr/local/go" | ||||
|     export KUBERNETES="no" | ||||
|     export USE_DOCKER="true" | ||||
|     export ghprbPullId | ||||
|     export ghprbTargetBranch | ||||
|  | ||||
|     # Make sure the packages were installed | ||||
|     # Sometimes cloud-init is unable to install them | ||||
|     sudo dnf makecache | ||||
|     sudo dnf install -y git make pciutils driverctl | ||||
|  | ||||
|     git config --global user.email "foo@bar" | ||||
|     git config --global user.name "Foo Bar" | ||||
|  | ||||
|     tests_repo="github.com/kata-containers/tests" | ||||
|     tests_repo_dir="\${GOPATH}/src/\${tests_repo}" | ||||
|     trap "cd \${tests_repo_dir}; sudo -E PATH=\$PATH .ci/teardown.sh ${artifacts_dir} || true; sudo chown -R \${USER} ${artifacts_dir}" EXIT | ||||
|  | ||||
|     curl -OL https://raw.githubusercontent.com/kata-containers/tests/\${ghprbTargetBranch}/.ci/ci_entry_point.sh | ||||
|     bash -x ci_entry_point.sh "${GIT_URL}" | ||||
|  | ||||
|   path: /home/${USER}/run.sh | ||||
|   permissions: '0755' | ||||
| EOF | ||||
| } | ||||
|  | ||||
| create_config_iso() { | ||||
| 	iso_file="$1" | ||||
| 	ssh_pub_key_file="${ssh_key_file}.pub" | ||||
| 	iso_data_dir="${data_dir}/d" | ||||
| 	meta_data_file="${iso_data_dir}/openstack/latest/meta_data.json" | ||||
| 	user_data_file="${iso_data_dir}/openstack/latest/user_data" | ||||
|  | ||||
| 	mkdir -p $(dirname "${user_data_file}") | ||||
|  | ||||
| 	create_meta_data "${meta_data_file}" | ||||
| 	create_user_data "${user_data_file}" "${ssh_pub_key_file}" | ||||
|  | ||||
| 	[ -f "${iso_file}" ] && rm -f "${iso_file}" | ||||
|  | ||||
| 	xorriso -as mkisofs -R -V config-2 -o "${iso_file}" "${iso_data_dir}" | ||||
| } | ||||
|  | ||||
| pull_fedora_cloud_image() { | ||||
| 	fedora_img="$1" | ||||
| 	fedora_version=37 | ||||
| 	# Add a version to the image cache, otherwise the tests are going to  | ||||
| 	# use always the same image without rebuilding it, regardless the version | ||||
| 	# set in fedora_version | ||||
| 	fedora_img_cache="${fedora_img}.cache.${fedora_version}" | ||||
| 	fedora_img_url="https://download.fedoraproject.org/pub/fedora/linux/releases/${fedora_version}/Cloud/${arch}/images/Fedora-Cloud-Base-${fedora_version}-1.7.${arch}.raw.xz" | ||||
|  | ||||
| 	if [ ! -f "${fedora_img_cache}" ]; then | ||||
| 		curl -sL ${fedora_img_url} -o "${fedora_img_cache}.xz" | ||||
| 		xz -f -d "${fedora_img_cache}.xz" | ||||
| 		sync | ||||
| 	fi | ||||
|  | ||||
| 	cp -a "${fedora_img_cache}" "${fedora_img}" | ||||
| 	sync | ||||
|  | ||||
| 	# setup cloud image | ||||
| 	sudo losetup -D | ||||
| 	loop=$(sudo losetup --show -Pf "${fedora_img}") | ||||
| 	sudo mount "${loop}p2" /mnt | ||||
|  | ||||
| 	# add intel_iommu=on to the guest kernel command line | ||||
| 	kernelopts="intel_iommu=on iommu=pt selinux=0" | ||||
| 	entries=$(sudo ls /mnt/loader/entries/) | ||||
| 	for entry in ${entries}; do | ||||
| 		sudo sed -i '/^options /  s/$/ intel_iommu=on iommu=pt selinux=0 /g' /mnt/loader/entries/"${entry}" | ||||
| 	done | ||||
| 	sudo sed -i 's|kernelopts="|kernelopts="'"${kernelopts}"'|g' /mnt/grub2/grub.cfg | ||||
| 	sudo sed -i 's|kernelopts=|kernelopts='"${kernelopts}"'|g' /mnt/grub2/grubenv | ||||
|  | ||||
| 	# cleanup | ||||
| 	sudo umount -R /mnt/ | ||||
| 	sudo losetup -d "${loop}" | ||||
|  | ||||
| 	qemu-img resize -f raw "${fedora_img}" +20G | ||||
| } | ||||
|  | ||||
| run_vm() { | ||||
| 	image="$1" | ||||
| 	config_iso="$2" | ||||
| 	disable_modern="off" | ||||
| 	hostname="$(hostname)" | ||||
| 	memory="16384M" | ||||
| 	cpus=$(nproc) | ||||
| 	machine_type="q35" | ||||
|  | ||||
| 	/usr/bin/qemu-system-${arch} -m "${memory}" -smp cpus="${cpus}" \ | ||||
| 	   -cpu host,host-phys-bits \ | ||||
| 	   -machine ${machine_type},accel=kvm,kernel_irqchip=split \ | ||||
| 	   -device intel-iommu,intremap=on,caching-mode=on,device-iotlb=on \ | ||||
| 	   -drive file=${image},if=virtio,aio=threads,format=raw \ | ||||
| 	   -drive file=${config_iso_file},if=virtio,media=cdrom \ | ||||
| 	   -daemonize -enable-kvm -device virtio-rng-pci -display none -vga none \ | ||||
| 	   -netdev user,hostfwd=tcp:${vm_ip}:${vm_port}-:22,hostname="${hostname}",id=net0 \ | ||||
| 	   -device virtio-net-pci,netdev=net0,disable-legacy=on,disable-modern="${disable_modern}",iommu_platform=on,ats=on \ | ||||
| 	   -netdev user,id=net1 \ | ||||
| 	   -device virtio-net-pci,netdev=net1,disable-legacy=on,disable-modern="${disable_modern}",iommu_platform=on,ats=on | ||||
| } | ||||
|  | ||||
| install_dependencies() { | ||||
| 	case "${ID}" in | ||||
| 		ubuntu) | ||||
| 			# cloud image dependencies | ||||
| 			deps=(xorriso curl qemu-utils openssh-client) | ||||
|  | ||||
| 			sudo apt-get update | ||||
| 			sudo apt-get install -y ${deps[@]} | ||||
| 			sudo apt-get install --reinstall -y qemu-system-x86 | ||||
| 			;; | ||||
| 		fedora) | ||||
| 			# cloud image dependencies | ||||
| 			deps=(xorriso curl qemu-img openssh) | ||||
|  | ||||
| 			sudo dnf install -y ${deps[@]} qemu-system-x86-core | ||||
| 			sudo dnf reinstall -y qemu-system-x86-core | ||||
| 			;; | ||||
|  | ||||
| 		"*") | ||||
| 			die "Unsupported distro: ${ID}" | ||||
| 			;; | ||||
| 	esac | ||||
| } | ||||
|  | ||||
| ssh_vm() { | ||||
| 	cmd=$@ | ||||
| 	ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i "${ssh_key_file}" -p "${vm_port}" "${USER}@${vm_ip}" "${cmd}" | ||||
| } | ||||
|  | ||||
| scp_vm() { | ||||
| 	guest_src=$1 | ||||
| 	host_dest=$2 | ||||
| 	scp -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i "${ssh_key_file}" -P "${vm_port}" ${USER}@${vm_ip}:${guest_src} ${host_dest} | ||||
| } | ||||
|  | ||||
| wait_for_vm() { | ||||
| 	for i in $(seq 1 30); do | ||||
| 		if ssh_vm true; then | ||||
| 			return 0 | ||||
| 		fi | ||||
| 		info "waiting for VM to start" | ||||
| 		sleep 5 | ||||
| 	done | ||||
| 	return 1 | ||||
| } | ||||
|  | ||||
| main() { | ||||
| 	trap cleanup EXIT | ||||
|  | ||||
| 	config_iso_file="${data_dir}/config.iso" | ||||
| 	fedora_img="${data_dir}/image.img" | ||||
|  | ||||
| 	mkdir -p "${data_dir}" | ||||
|  | ||||
| 	install_dependencies | ||||
|  | ||||
| 	create_ssh_key | ||||
|  | ||||
| 	create_config_iso "${config_iso_file}" | ||||
|  | ||||
| 	for i in $(seq 1 5); do | ||||
| 		pull_fedora_cloud_image "${fedora_img}" | ||||
| 		run_vm "${fedora_img}" "${config_iso_file}" | ||||
| 		if wait_for_vm; then | ||||
| 			break | ||||
| 		fi | ||||
| 		info "Couldn't connect to the VM. Stopping VM and starting a new one." | ||||
| 		kill_vms | ||||
| 	done | ||||
|  | ||||
| 	ssh_vm "/home/${USER}/run.sh" | ||||
| } | ||||
|  | ||||
| main $@ | ||||
		Reference in New Issue
	
	Block a user