github.com/dmaizel/tests@v0.0.0-20210728163746-cae6a2d9cee8/functional/vfio/run.sh (about) 1 #!/bin/bash 2 # 3 # Copyright (c) 2021 Intel Corporation 4 # 5 # SPDX-License-Identifier: Apache-2.0 6 # 7 8 set -x 9 set -o errexit 10 set -o nounset 11 set -o pipefail 12 set -o errtrace 13 14 script_path=$(dirname "$0") 15 source "${script_path}/../../lib/common.bash" 16 17 declare -r container_id="vfiotest${RANDOM}" 18 19 tmp_data_dir="$(mktemp -d)" 20 trap cleanup EXIT 21 22 # kata-runtime options 23 SANDBOX_CGROUP_ONLY="" 24 HYPERVISOR= 25 MACHINE_TYPE= 26 IMAGE_TYPE= 27 28 cleanup() { 29 sudo ctr t kill -a -s 9 $(sudo ctr task list -q) && sleep 3 30 sudo ctr t rm -f $(sudo ctr task list -q) && sleep 3 31 sudo ctr c rm $(sudo ctr c list -q) 32 sudo rm -rf "${tmp_data_dir}" 33 } 34 35 get_eth_addr() { 36 lspci | grep "Ethernet controller" | grep "Virtio network device" | tail -1 | cut -d' ' -f1 37 } 38 39 unbind_pci_dev() { 40 addr="$1" 41 echo "0000:${addr}" | sudo tee "/sys/bus/pci/devices/0000:${addr}/driver/unbind" 42 } 43 44 get_pci_dev_vendor_id() { 45 addr="$1" 46 lspci -n -s "${addr}" | cut -d' ' -f3 | sed 's|:| |' 47 } 48 49 bind_to_vfio() { 50 dev_vendor_id="$1" 51 echo "${dev_vendor_id}" | sudo tee "/sys/bus/pci/drivers/vfio-pci/new_id" 52 } 53 54 get_vfio_path() { 55 addr="$1" 56 echo "/dev/vfio/$(basename $(realpath /sys/bus/pci/drivers/vfio-pci/0000:${addr}/iommu_group))" 57 } 58 59 create_bundle() { 60 bundle_dir="$1" 61 mkdir -p "${bundle_dir}" 62 63 # pull and export busybox image in tar file 64 rootfs_tar="${tmp_data_dir}/rootfs.tar" 65 image="quay.io/prometheus/busybox:latest" 66 sudo -E ctr i pull ${image} 67 sudo -E ctr i export "${rootfs_tar}" "${image}" 68 sudo chown ${USER}:${USER} "${rootfs_tar}" 69 sync 70 71 # extract busybox rootfs 72 rootfs_dir="${bundle_dir}/rootfs" 73 mkdir -p "${rootfs_dir}" 74 layers_dir="$(mktemp -d)" 75 tar -C "${layers_dir}" -pxf "${rootfs_tar}" 76 for ((i=0;i<$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers | length");i++)); do 77 tar -C ${rootfs_dir} -xf ${layers_dir}/$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers[${i}]") 78 done 79 sync 80 81 # Copy config.json 82 cp -a "${script_path}/config.json" "${bundle_dir}/config.json" 83 } 84 85 run_container() { 86 bundle_dir="$1" 87 sudo -E ctr run -d --runtime io.containerd.run.kata.v2 --config "${bundle_dir}/config.json" "${container_id}" 88 } 89 90 check_eth_dev() { 91 # container MUST have a eth net interface 92 sudo -E ctr t exec --exec-id 2 "${container_id}" ip a | grep "eth" 93 } 94 95 # Show help about this script 96 help(){ 97 cat << EOF 98 Usage: $0 [-h] [options] 99 Description: 100 This script runs a kata container and passthrough a vfio device 101 Options: 102 -h, Help 103 -i <string>, Specify initrd or image 104 -m <string>, Specify kata-runtime machine type for qemu hypervisor 105 -p <string>, Specify kata-runtime hypervisor 106 -s <value>, Set sandbox_cgroup_only in the configuration file 107 EOF 108 } 109 110 setup_configuration_file() { 111 local qemu_config_file="configuration-qemu.toml" 112 local clh_config_file="configuration-clh.toml" 113 local image_file="/usr/share/kata-containers/kata-containers.img" 114 local initrd_file="/usr/share/kata-containers/kata-containers-initrd.img" 115 local kata_config_file="" 116 117 for file in $(kata-runtime --kata-show-default-config-paths); do 118 if [ ! -f "${file}" ]; then 119 continue 120 fi 121 122 kata_config_file="${file}" 123 config_dir=$(dirname ${file}) 124 config_filename="" 125 126 if [ "$HYPERVISOR" = "qemu" ]; then 127 config_filename="${qemu_config_file}" 128 elif [ "$HYPERVISOR" = "clh" ]; then 129 config_filename="${clh_config_file}" 130 fi 131 132 config_file="${config_dir}/${config_filename}" 133 if [ -f "${config_file}" ]; then 134 rm -f "${kata_config_file}" 135 cp -a $(realpath "${config_file}") "${kata_config_file}" 136 break 137 fi 138 done 139 140 # machine type applies to configuration.toml and configuration-qemu.toml 141 if [ -n "$MACHINE_TYPE" ]; then 142 if [ "$HYPERVISOR" = "qemu" ]; then 143 sed -i 's|^machine_type.*|machine_type = "'${MACHINE_TYPE}'"|g' "${kata_config_file}" 144 else 145 warn "Variable machine_type only applies to qemu. It will be ignored" 146 fi 147 fi 148 149 if [ -n "${SANDBOX_CGROUP_ONLY}" ]; then 150 sed -i 's|^sandbox_cgroup_only.*|sandbox_cgroup_only='${SANDBOX_CGROUP_ONLY}'|g' "${kata_config_file}" 151 fi 152 153 # Change to initrd or image depending on user input. 154 # Non-default configs must be changed to specify either initrd or image, image is default. 155 if [ "$IMAGE_TYPE" = "initrd" ]; then 156 if $(grep -q "^image.*" ${kata_config_file}); then 157 if $(grep -q "^initrd.*" ${kata_config_file}); then 158 sed -i '/^image.*/d' "${kata_config_file}" 159 else 160 sed -i 's|^image.*|initrd = "'${initrd_file}'"|g' "${kata_config_file}" 161 fi 162 fi 163 else 164 if $(grep -q "^initrd.*" ${kata_config_file}); then 165 if $(grep -q "^image.*" ${kata_config_file}); then 166 sed -i '/^initrd.*/d' "${kata_config_file}" 167 else 168 sed -i 's|^initrd.*|image = "'${image_file}'"|g' "${kata_config_file}" 169 fi 170 fi 171 fi 172 173 # enable debug 174 sed -i -e 's/^#\(enable_debug\).*=.*$/\1 = true/g' \ 175 -e 's/^kernel_params = "\(.*\)"/kernel_params = "\1 agent.log=debug"/g' \ 176 "${kata_config_file}" 177 } 178 179 main() { 180 local OPTIND 181 while getopts "hi:m:p:s:" opt;do 182 case ${opt} in 183 h) 184 help 185 exit 0; 186 ;; 187 i) 188 IMAGE_TYPE="${OPTARG}" 189 ;; 190 m) 191 MACHINE_TYPE="${OPTARG}" 192 ;; 193 p) 194 HYPERVISOR="${OPTARG}" 195 ;; 196 s) 197 SANDBOX_CGROUP_ONLY="${OPTARG}" 198 ;; 199 ?) 200 # parse failure 201 help 202 die "Failed to parse arguments" 203 ;; 204 esac 205 done 206 shift $((OPTIND-1)) 207 208 setup_configuration_file 209 210 sudo systemctl restart containerd 211 sudo modprobe vfio 212 sudo modprobe vfio-pci 213 214 addr=$(get_eth_addr) 215 [ -n "${addr}" ] || die "virtio ethernet controller address not found" 216 217 unbind_pci_dev "${addr}" 218 219 dev_vendor_id="$(get_pci_dev_vendor_id "${addr}")" 220 bind_to_vfio "${dev_vendor_id}" 221 222 # get vfio information 223 vfio_device="$(get_vfio_path "${addr}")" 224 [ -n "${vfio_device}" ] || die "vfio device not found" 225 vfio_major="$(printf '%d' $(stat -c '0x%t' ${vfio_device}))" 226 vfio_minor="$(printf '%d' $(stat -c '0x%T' ${vfio_device}))" 227 228 # create container bundle 229 bundle_dir="${tmp_data_dir}/bundle" 230 231 # generate final config.json 232 config_json_in="${script_path}/config.json.in" 233 sed -e '/^#.*/d' \ 234 -e 's|@VFIO_PATH@|'"${vfio_device}"'|g' \ 235 -e 's|@VFIO_MAJOR@|'"${vfio_major}"'|g' \ 236 -e 's|@VFIO_MINOR@|'"${vfio_minor}"'|g' \ 237 -e 's|@ROOTFS@|'"${bundle_dir}/rootfs"'|g' \ 238 "${config_json_in}" > "${script_path}/config.json" 239 240 create_bundle "${bundle_dir}" 241 242 # run container 243 run_container "${bundle_dir}" 244 245 # run container checks 246 check_eth_dev 247 } 248 249 main $@