1eb53c232Spaul luse# SPDX-License-Identifier: BSD-3-Clause 2eb53c232Spaul luse# Copyright (C) 2017 Intel Corporation 3eb53c232Spaul luse# All rights reserved. 4eb53c232Spaul luse# 5eb53c232Spaul luse 63d11b2feSBen Walker: ${SPDK_VHOST_VERBOSE=false} 78f44d126SBen Walker: ${VHOST_DIR="$HOME/vhost_test"} 86abaf4fcSMichal Berger: ${QEMU_BIN:="qemu-system-x86_64"} 9b9395621SKarol Latecki: ${QEMU_IMG_BIN="qemu-img"} 103d11b2feSBen Walker 11e422bf69SBen WalkerTEST_DIR=$(readlink -f $rootdir/..) 128f44d126SBen WalkerVM_DIR=$VHOST_DIR/vms 138f44d126SBen WalkerTARGET_DIR=$VHOST_DIR/vhost 14671874b7SPawel KaminskiVM_PASSWORD="root" 158f44d126SBen Walker 16a4a04624SMichal BergerVM_IMAGE=${VM_IMAGE:-"$DEPENDENCY_DIR/vhost/spdk_test_image.qcow2"} 17a4a04624SMichal BergerFIO_BIN=${FIO_BIN:-} 189c3ba11aSMichal Berger 199c3ba11aSMichal BergerWORKDIR=$(readlink -f "$(dirname "$0")") 20ad15da13SBen Walker 21b9395621SKarol Lateckiif ! hash $QEMU_IMG_BIN $QEMU_BIN; then 22fb41398aSMichal Berger echo 'ERROR: QEMU is not installed on this system. Unable to run vhost tests.' >&2 2376a2663eSMichal Berger return 1 24fdb03395Syidong0635fi 25fdb03395Syidong0635 268f44d126SBen Walkermkdir -p $VHOST_DIR 278f44d126SBen Walkermkdir -p $VM_DIR 288f44d126SBen Walkermkdir -p $TARGET_DIR 29ad25a95cSBen Walker 30ad25a95cSBen Walker# 31ad25a95cSBen Walker# Source config describing QEMU and VHOST cores and NUMA 32ad25a95cSBen Walker# 338be1517dSBen Walkersource $rootdir/test/vhost/common/autotest.config 349463523bSMichal Bergersource "$rootdir/test/scheduler/common.sh" 35ad25a95cSBen Walker 36844c8ec3SMichal Bergerfunction vhosttestinit() { 37683099e3SBen Walker if [ "$TEST_MODE" == "iso" ]; then 38683099e3SBen Walker $rootdir/scripts/setup.sh 39ee191fa8SMichal Berger fi 40ee191fa8SMichal Berger 416f5b9508SMichal Berger if [[ -e $VM_IMAGE.gz && ! -e $VM_IMAGE ]]; then 42ee191fa8SMichal Berger gzip -dc "$VM_IMAGE.gz" > "$VM_IMAGE" 43ee191fa8SMichal Berger fi 44123ccd10SBen Walker 45123ccd10SBen Walker # Look for the VM image 46123ccd10SBen Walker if [[ ! -f $VM_IMAGE ]]; then 47ee191fa8SMichal Berger [[ $1 != "--no_vm" ]] || return 0 48ee191fa8SMichal Berger echo "$VM_IMAGE is missing" >&2 49ee191fa8SMichal Berger return 1 50683099e3SBen Walker fi 51683099e3SBen Walker} 52683099e3SBen Walker 53844c8ec3SMichal Bergerfunction vhosttestfini() { 54683099e3SBen Walker if [ "$TEST_MODE" == "iso" ]; then 55683099e3SBen Walker $rootdir/scripts/setup.sh reset 56683099e3SBen Walker fi 57683099e3SBen Walker} 58683099e3SBen Walker 59844c8ec3SMichal Bergerfunction message() { 60074df1d8SPawel Kaminski local verbose_out 613d11b2feSBen Walker if ! $SPDK_VHOST_VERBOSE; then 62074df1d8SPawel Kaminski verbose_out="" 633d11b2feSBen Walker elif [[ ${FUNCNAME[2]} == "source" ]]; then 64074df1d8SPawel Kaminski verbose_out=" (file $(basename ${BASH_SOURCE[1]}):${BASH_LINENO[1]})" 653d11b2feSBen Walker else 66074df1d8SPawel Kaminski verbose_out=" (function ${FUNCNAME[2]}:${BASH_LINENO[1]})" 673d11b2feSBen Walker fi 683d11b2feSBen Walker 693d11b2feSBen Walker local msg_type="$1" 703d11b2feSBen Walker shift 717c4bb5e2SMaciej Wawryk echo -e "${msg_type}${verbose_out}: $*" 723d11b2feSBen Walker} 733d11b2feSBen Walker 74844c8ec3SMichal Bergerfunction fail() { 753d11b2feSBen Walker echo "===========" >&2 763d11b2feSBen Walker message "FAIL" "$@" >&2 773d11b2feSBen Walker echo "===========" >&2 783d11b2feSBen Walker exit 1 793d11b2feSBen Walker} 803d11b2feSBen Walker 81844c8ec3SMichal Bergerfunction error() { 823d11b2feSBen Walker echo "===========" >&2 833d11b2feSBen Walker message "ERROR" "$@" >&2 843d11b2feSBen Walker echo "===========" >&2 853d11b2feSBen Walker # Don't 'return 1' since the stack trace will be incomplete (why?) missing upper command. 863d11b2feSBen Walker false 873d11b2feSBen Walker} 883d11b2feSBen Walker 89844c8ec3SMichal Bergerfunction warning() { 903d11b2feSBen Walker message "WARN" "$@" >&2 913d11b2feSBen Walker} 923d11b2feSBen Walker 93844c8ec3SMichal Bergerfunction notice() { 943d11b2feSBen Walker message "INFO" "$@" 953d11b2feSBen Walker} 963d11b2feSBen Walker 97262c35fcSKarol Lateckifunction check_qemu_packedring_support() { 98262c35fcSKarol Latecki qemu_version=$($QEMU_BIN -version | grep -Po "(?<=version )\d+.\d+.\d+") 99262c35fcSKarol Latecki if [[ "$qemu_version" < "4.2.0" ]]; then 100262c35fcSKarol Latecki error "This qemu binary does not support packed ring" 101262c35fcSKarol Latecki fi 102262c35fcSKarol Latecki} 103262c35fcSKarol Latecki 104844c8ec3SMichal Bergerfunction get_vhost_dir() { 105fa563858SBen Walker local vhost_name="$1" 106fa563858SBen Walker 107fa563858SBen Walker if [[ -z "$vhost_name" ]]; then 108fa563858SBen Walker error "vhost name must be provided to get_vhost_dir" 109fa563858SBen Walker return 1 1103d11b2feSBen Walker fi 1113d11b2feSBen Walker 112fa563858SBen Walker echo "$TARGET_DIR/${vhost_name}" 1133d11b2feSBen Walker} 1143d11b2feSBen Walker 115844c8ec3SMichal Bergerfunction vhost_run() { 1169f5f5da8SKarol Latecki local OPTIND 1179f5f5da8SKarol Latecki local vhost_name 11880881761SKarol Latecki local run_gen_nvme=true 1195c385271SKarol Latecki local vhost_bin="vhost" 1204641aa53SMichal Berger local vhost_args=() 1214641aa53SMichal Berger local cmd=() 1223d11b2feSBen Walker 1234641aa53SMichal Berger while getopts "n:b:g" optchar; do 1249f5f5da8SKarol Latecki case "$optchar" in 1259f5f5da8SKarol Latecki n) vhost_name="$OPTARG" ;; 1265c385271SKarol Latecki b) vhost_bin="$OPTARG" ;; 1279f5f5da8SKarol Latecki g) 1289f5f5da8SKarol Latecki run_gen_nvme=false 1299f5f5da8SKarol Latecki notice "Skipping gen_nvme.sh NVMe bdev configuration" 1309f5f5da8SKarol Latecki ;; 1319f5f5da8SKarol Latecki *) 1329f5f5da8SKarol Latecki error "Unknown param $optchar" 1339f5f5da8SKarol Latecki return 1 1349f5f5da8SKarol Latecki ;; 1359f5f5da8SKarol Latecki esac 1369f5f5da8SKarol Latecki done 1374641aa53SMichal Berger shift $((OPTIND - 1)) 1384641aa53SMichal Berger 1394641aa53SMichal Berger vhost_args=("$@") 1409f5f5da8SKarol Latecki 141fa563858SBen Walker if [[ -z "$vhost_name" ]]; then 142fa563858SBen Walker error "vhost name must be provided to vhost_run" 143fa563858SBen Walker return 1 144fa563858SBen Walker fi 14580881761SKarol Latecki 146074df1d8SPawel Kaminski local vhost_dir 147074df1d8SPawel Kaminski vhost_dir="$(get_vhost_dir $vhost_name)" 1485c385271SKarol Latecki local vhost_app="$SPDK_BIN_DIR/$vhost_bin" 1493d11b2feSBen Walker local vhost_log_file="$vhost_dir/vhost.log" 1503d11b2feSBen Walker local vhost_pid_file="$vhost_dir/vhost.pid" 1513d11b2feSBen Walker local vhost_socket="$vhost_dir/usvhost" 1523d11b2feSBen Walker notice "starting vhost app in background" 1531b10706eSKarol Latecki [[ -r "$vhost_pid_file" ]] && vhost_kill $vhost_name 1543d11b2feSBen Walker [[ -d $vhost_dir ]] && rm -f $vhost_dir/* 1553d11b2feSBen Walker mkdir -p $vhost_dir 1563d11b2feSBen Walker 1573d11b2feSBen Walker if [[ ! -x $vhost_app ]]; then 1583d11b2feSBen Walker error "application not found: $vhost_app" 1593d11b2feSBen Walker return 1 1603d11b2feSBen Walker fi 1613d11b2feSBen Walker 1624641aa53SMichal Berger cmd=("$vhost_app" "-r" "$vhost_dir/rpc.sock" "${vhost_args[@]}") 163da242a6fSKarol Latecki if [[ "$vhost_bin" =~ vhost ]]; then 1644641aa53SMichal Berger cmd+=(-S "$vhost_dir") 165da242a6fSKarol Latecki fi 1663d11b2feSBen Walker 16734edd9f1SKamil Godzwon notice "Logging to: $vhost_log_file" 1683d11b2feSBen Walker notice "Socket: $vhost_socket" 16974519d80SMichal Berger notice "Command: ${cmd[*]}" 1703d11b2feSBen Walker 1713d11b2feSBen Walker timing_enter vhost_start 172a182f55bSKarol Latecki 173c6d73b5aSKarol Latecki iobuf_small_count=${iobuf_small_count:-16383} 174c6d73b5aSKarol Latecki iobuf_large_count=${iobuf_large_count:-2047} 175c6d73b5aSKarol Latecki 1764641aa53SMichal Berger "${cmd[@]}" --wait-for-rpc & 1773d11b2feSBen Walker vhost_pid=$! 1783d11b2feSBen Walker echo $vhost_pid > $vhost_pid_file 1793d11b2feSBen Walker 1803d11b2feSBen Walker notice "waiting for app to run..." 1813d11b2feSBen Walker waitforlisten "$vhost_pid" "$vhost_dir/rpc.sock" 182c6d73b5aSKarol Latecki 183c6d73b5aSKarol Latecki "$rootdir/scripts/rpc.py" -s "$vhost_dir/rpc.sock" \ 184c6d73b5aSKarol Latecki iobuf_set_options \ 185c6d73b5aSKarol Latecki --small-pool-count="$iobuf_small_count" \ 186c6d73b5aSKarol Latecki --large-pool-count="$iobuf_large_count" 187c6d73b5aSKarol Latecki 188c6d73b5aSKarol Latecki "$rootdir/scripts/rpc.py" -s "$vhost_dir/rpc.sock" \ 189c6d73b5aSKarol Latecki framework_start_init 190c6d73b5aSKarol Latecki 1913d11b2feSBen Walker #do not generate nvmes if pci access is disabled 19274519d80SMichal Berger if [[ "${cmd[*]}" != *"--no-pci"* ]] && [[ "${cmd[*]}" != *"-u"* ]] && $run_gen_nvme; then 1938c3e71f0STomasz Zawadzki $rootdir/scripts/gen_nvme.sh | $rootdir/scripts/rpc.py -s $vhost_dir/rpc.sock load_subsystem_config 1943d11b2feSBen Walker fi 1953d11b2feSBen Walker 1963d11b2feSBen Walker notice "vhost started - pid=$vhost_pid" 197a182f55bSKarol Latecki 1983d11b2feSBen Walker timing_exit vhost_start 1993d11b2feSBen Walker} 2003d11b2feSBen Walker 201844c8ec3SMichal Bergerfunction vhost_kill() { 2023d11b2feSBen Walker local rc=0 203fa563858SBen Walker local vhost_name="$1" 204fa563858SBen Walker 205fa563858SBen Walker if [[ -z "$vhost_name" ]]; then 206fa563858SBen Walker error "Must provide vhost name to vhost_kill" 207fa563858SBen Walker return 0 2083d11b2feSBen Walker fi 2093d11b2feSBen Walker 210074df1d8SPawel Kaminski local vhost_dir 211074df1d8SPawel Kaminski vhost_dir="$(get_vhost_dir $vhost_name)" 21251672da0SBen Walker local vhost_pid_file="$vhost_dir/vhost.pid" 2133d11b2feSBen Walker 2143d11b2feSBen Walker if [[ ! -r $vhost_pid_file ]]; then 2153d11b2feSBen Walker warning "no vhost pid file found" 2163d11b2feSBen Walker return 0 2173d11b2feSBen Walker fi 2183d11b2feSBen Walker 2193d11b2feSBen Walker timing_enter vhost_kill 220074df1d8SPawel Kaminski local vhost_pid 221074df1d8SPawel Kaminski vhost_pid="$(cat $vhost_pid_file)" 2223d11b2feSBen Walker notice "killing vhost (PID $vhost_pid) app" 2233d11b2feSBen Walker 22451672da0SBen Walker if kill -INT $vhost_pid > /dev/null; then 2253d11b2feSBen Walker notice "sent SIGINT to vhost app - waiting 60 seconds to exit" 2263d11b2feSBen Walker for ((i = 0; i < 60; i++)); do 22751672da0SBen Walker if kill -0 $vhost_pid; then 2283d11b2feSBen Walker echo "." 2293d11b2feSBen Walker sleep 1 2303d11b2feSBen Walker else 2313d11b2feSBen Walker break 2323d11b2feSBen Walker fi 2333d11b2feSBen Walker done 23451672da0SBen Walker if kill -0 $vhost_pid; then 2353d11b2feSBen Walker error "ERROR: vhost was NOT killed - sending SIGABRT" 23651672da0SBen Walker kill -ABRT $vhost_pid 2373d11b2feSBen Walker rc=1 2383d11b2feSBen Walker else 2393d11b2feSBen Walker while kill -0 $vhost_pid; do 2403d11b2feSBen Walker echo "." 2413d11b2feSBen Walker done 2423d11b2feSBen Walker fi 243*a711f445SMichal Berger # If this PID is our child, we should attempt to verify its status 244*a711f445SMichal Berger # to catch any "silent" crashes that may happen upon termination. 245*a711f445SMichal Berger if is_pid_child "$vhost_pid"; then 246*a711f445SMichal Berger notice "Checking status of $vhost_pid" 247*a711f445SMichal Berger wait "$vhost_pid" || rc=1 248*a711f445SMichal Berger fi 249*a711f445SMichal Berger 25051672da0SBen Walker elif kill -0 $vhost_pid; then 2513d11b2feSBen Walker error "vhost NOT killed - you need to kill it manually" 2523d11b2feSBen Walker rc=1 2533d11b2feSBen Walker else 25451672da0SBen Walker notice "vhost was not running" 2553d11b2feSBen Walker fi 2563d11b2feSBen Walker 2573d11b2feSBen Walker timing_exit vhost_kill 2583d11b2feSBen Walker 25951672da0SBen Walker rm -rf "$vhost_dir" 26051672da0SBen Walker 2613d11b2feSBen Walker return $rc 2623d11b2feSBen Walker} 2633d11b2feSBen Walker 264844c8ec3SMichal Bergerfunction vhost_rpc() { 265fa563858SBen Walker local vhost_name="$1" 266fa563858SBen Walker 267fa563858SBen Walker if [[ -z "$vhost_name" ]]; then 268fa563858SBen Walker error "vhost name must be provided to vhost_rpc" 269fa563858SBen Walker return 1 270c66685deSBen Walker fi 271c66685deSBen Walker shift 272c66685deSBen Walker 273fdc82d3bSMaciej Wawryk $rootdir/scripts/rpc.py -s $(get_vhost_dir $vhost_name)/rpc.sock "$@" 274c66685deSBen Walker} 275c66685deSBen Walker 2763d11b2feSBen Walker### 2773d11b2feSBen Walker# Mgmt functions 2783d11b2feSBen Walker### 2793d11b2feSBen Walker 280844c8ec3SMichal Bergerfunction assert_number() { 2813d11b2feSBen Walker [[ "$1" =~ [0-9]+ ]] && return 0 2823d11b2feSBen Walker 283c9c7c281SJosh Soref error "Invalid or missing parameter: need number but got '$1'" 284844c8ec3SMichal Berger return 1 2853d11b2feSBen Walker} 2863d11b2feSBen Walker 2874f31e107SPawel Kaminski# Run command on vm with given password 2884f31e107SPawel Kaminski# First argument - vm number 2894f31e107SPawel Kaminski# Second argument - ssh password for vm 2904f31e107SPawel Kaminski# 291844c8ec3SMichal Bergerfunction vm_sshpass() { 2924f31e107SPawel Kaminski vm_num_is_valid $1 || return 1 2934f31e107SPawel Kaminski 294074df1d8SPawel Kaminski local ssh_cmd 295074df1d8SPawel Kaminski ssh_cmd="sshpass -p $2 ssh \ 2964f31e107SPawel Kaminski -o UserKnownHostsFile=/dev/null \ 2974f31e107SPawel Kaminski -o StrictHostKeyChecking=no \ 2984f31e107SPawel Kaminski -o User=root \ 2994f31e107SPawel Kaminski -p $(vm_ssh_socket $1) $VM_SSH_OPTIONS 127.0.0.1" 3004f31e107SPawel Kaminski 3014f31e107SPawel Kaminski shift 2 3024f31e107SPawel Kaminski $ssh_cmd "$@" 3034f31e107SPawel Kaminski} 3044f31e107SPawel Kaminski 3053d11b2feSBen Walker# Helper to validate VM number 3063d11b2feSBen Walker# param $1 VM number 3073d11b2feSBen Walker# 308844c8ec3SMichal Bergerfunction vm_num_is_valid() { 3093d11b2feSBen Walker [[ "$1" =~ ^[0-9]+$ ]] && return 0 3103d11b2feSBen Walker 311c9c7c281SJosh Soref error "Invalid or missing parameter: vm number '$1'" 312844c8ec3SMichal Berger return 1 3133d11b2feSBen Walker} 3143d11b2feSBen Walker 3153d11b2feSBen Walker# Print network socket for given VM number 3163d11b2feSBen Walker# param $1 virtual machine number 3173d11b2feSBen Walker# 318844c8ec3SMichal Bergerfunction vm_ssh_socket() { 3193d11b2feSBen Walker vm_num_is_valid $1 || return 1 3208f44d126SBen Walker local vm_dir="$VM_DIR/$1" 3213d11b2feSBen Walker 3223d11b2feSBen Walker cat $vm_dir/ssh_socket 3233d11b2feSBen Walker} 3243d11b2feSBen Walker 325844c8ec3SMichal Bergerfunction vm_fio_socket() { 3263d11b2feSBen Walker vm_num_is_valid $1 || return 1 3278f44d126SBen Walker local vm_dir="$VM_DIR/$1" 3283d11b2feSBen Walker 3293d11b2feSBen Walker cat $vm_dir/fio_socket 3303d11b2feSBen Walker} 3313d11b2feSBen Walker 33297df5bccSBen Walker# Execute command on given VM 3333d11b2feSBen Walker# param $1 virtual machine number 3343d11b2feSBen Walker# 335844c8ec3SMichal Bergerfunction vm_exec() { 3363d11b2feSBen Walker vm_num_is_valid $1 || return 1 3373d11b2feSBen Walker 33897df5bccSBen Walker local vm_num="$1" 3393d11b2feSBen Walker shift 34097df5bccSBen Walker 341671874b7SPawel Kaminski sshpass -p "$VM_PASSWORD" ssh \ 34297df5bccSBen Walker -o UserKnownHostsFile=/dev/null \ 34397df5bccSBen Walker -o StrictHostKeyChecking=no \ 34497df5bccSBen Walker -o User=root \ 34597df5bccSBen Walker -p $(vm_ssh_socket $vm_num) $VM_SSH_OPTIONS 127.0.0.1 \ 34697df5bccSBen Walker "$@" 3473d11b2feSBen Walker} 3483d11b2feSBen Walker 3493d11b2feSBen Walker# Execute scp command on given VM 3503d11b2feSBen Walker# param $1 virtual machine number 3513d11b2feSBen Walker# 352844c8ec3SMichal Bergerfunction vm_scp() { 3533d11b2feSBen Walker vm_num_is_valid $1 || return 1 3543d11b2feSBen Walker 35597df5bccSBen Walker local vm_num="$1" 3563d11b2feSBen Walker shift 35797df5bccSBen Walker 358671874b7SPawel Kaminski sshpass -p "$VM_PASSWORD" scp \ 35997df5bccSBen Walker -o UserKnownHostsFile=/dev/null \ 36097df5bccSBen Walker -o StrictHostKeyChecking=no \ 36197df5bccSBen Walker -o User=root \ 36297df5bccSBen Walker -P $(vm_ssh_socket $vm_num) $VM_SSH_OPTIONS \ 36397df5bccSBen Walker "$@" 3643d11b2feSBen Walker} 3653d11b2feSBen Walker 3663d11b2feSBen Walker# check if specified VM is running 3673d11b2feSBen Walker# param $1 VM num 368844c8ec3SMichal Bergerfunction vm_is_running() { 3693d11b2feSBen Walker vm_num_is_valid $1 || return 1 3708f44d126SBen Walker local vm_dir="$VM_DIR/$1" 3713d11b2feSBen Walker 3723d11b2feSBen Walker if [[ ! -r $vm_dir/qemu.pid ]]; then 3733d11b2feSBen Walker return 1 3743d11b2feSBen Walker fi 3753d11b2feSBen Walker 376074df1d8SPawel Kaminski local vm_pid 377074df1d8SPawel Kaminski vm_pid="$(cat $vm_dir/qemu.pid)" 3783d11b2feSBen Walker 3793d11b2feSBen Walker if /bin/kill -0 $vm_pid; then 3803d11b2feSBen Walker return 0 3813d11b2feSBen Walker else 3823d11b2feSBen Walker if [[ $EUID -ne 0 ]]; then 3833d11b2feSBen Walker warning "not root - assuming VM running since can't be checked" 3843d11b2feSBen Walker return 0 3853d11b2feSBen Walker fi 3863d11b2feSBen Walker 3873d11b2feSBen Walker # not running - remove pid file 3881efd5745SMichal Berger rm -f $vm_dir/qemu.pid 3893d11b2feSBen Walker return 1 3903d11b2feSBen Walker fi 3913d11b2feSBen Walker} 3923d11b2feSBen Walker 3933d11b2feSBen Walker# check if specified VM is running 3943d11b2feSBen Walker# param $1 VM num 395844c8ec3SMichal Bergerfunction vm_os_booted() { 3963d11b2feSBen Walker vm_num_is_valid $1 || return 1 3978f44d126SBen Walker local vm_dir="$VM_DIR/$1" 3983d11b2feSBen Walker 3993d11b2feSBen Walker if [[ ! -r $vm_dir/qemu.pid ]]; then 4003d11b2feSBen Walker error "VM $1 is not running" 4013d11b2feSBen Walker return 1 4023d11b2feSBen Walker fi 4033d11b2feSBen Walker 40497df5bccSBen Walker if ! VM_SSH_OPTIONS="-o ControlMaster=no" vm_exec $1 "true" 2> /dev/null; then 4053d11b2feSBen Walker # Shutdown existing master. Ignore errors as it might not exist. 40697df5bccSBen Walker VM_SSH_OPTIONS="-O exit" vm_exec $1 "true" 2> /dev/null 4073d11b2feSBen Walker return 1 4083d11b2feSBen Walker fi 4093d11b2feSBen Walker 4103d11b2feSBen Walker return 0 4113d11b2feSBen Walker} 4123d11b2feSBen Walker 4133d11b2feSBen Walker# Shutdown given VM 4143d11b2feSBen Walker# param $1 virtual machine number 4153d11b2feSBen Walker# return non-zero in case of error. 416844c8ec3SMichal Bergerfunction vm_shutdown() { 4173d11b2feSBen Walker vm_num_is_valid $1 || return 1 4188f44d126SBen Walker local vm_dir="$VM_DIR/$1" 4193d11b2feSBen Walker if [[ ! -d "$vm_dir" ]]; then 4203d11b2feSBen Walker error "VM$1 ($vm_dir) not exist - setup it first" 4213d11b2feSBen Walker return 1 4223d11b2feSBen Walker fi 4233d11b2feSBen Walker 4243d11b2feSBen Walker if ! vm_is_running $1; then 4253d11b2feSBen Walker notice "VM$1 ($vm_dir) is not running" 4263d11b2feSBen Walker return 0 4273d11b2feSBen Walker fi 4283d11b2feSBen Walker 4293d11b2feSBen Walker # Temporarily disabling exit flag for next ssh command, since it will 4303d11b2feSBen Walker # "fail" due to shutdown 4313d11b2feSBen Walker notice "Shutting down virtual machine $vm_dir" 4323d11b2feSBen Walker set +e 43397df5bccSBen Walker vm_exec $1 "nohup sh -c 'shutdown -h -P now'" || true 4343d11b2feSBen Walker notice "VM$1 is shutting down - wait a while to complete" 4353d11b2feSBen Walker set -e 4363d11b2feSBen Walker} 4373d11b2feSBen Walker 4383d11b2feSBen Walker# Kill given VM 4393d11b2feSBen Walker# param $1 virtual machine number 4403d11b2feSBen Walker# 441844c8ec3SMichal Bergerfunction vm_kill() { 4423d11b2feSBen Walker vm_num_is_valid $1 || return 1 4438f44d126SBen Walker local vm_dir="$VM_DIR/$1" 4443d11b2feSBen Walker 4453d11b2feSBen Walker if [[ ! -r $vm_dir/qemu.pid ]]; then 4463d11b2feSBen Walker return 0 4473d11b2feSBen Walker fi 4483d11b2feSBen Walker 449074df1d8SPawel Kaminski local vm_pid 450074df1d8SPawel Kaminski vm_pid="$(cat $vm_dir/qemu.pid)" 4513d11b2feSBen Walker 4523d11b2feSBen Walker notice "Killing virtual machine $vm_dir (pid=$vm_pid)" 4533d11b2feSBen Walker # First kill should fail, second one must fail 4543d11b2feSBen Walker if /bin/kill $vm_pid; then 4553d11b2feSBen Walker notice "process $vm_pid killed" 456ad15da13SBen Walker rm -rf $vm_dir 4573d11b2feSBen Walker elif vm_is_running $1; then 4583d11b2feSBen Walker error "Process $vm_pid NOT killed" 4593d11b2feSBen Walker return 1 4603d11b2feSBen Walker fi 4613d11b2feSBen Walker} 4623d11b2feSBen Walker 4638f44d126SBen Walker# List all VM numbers in VM_DIR 4643d11b2feSBen Walker# 465844c8ec3SMichal Bergerfunction vm_list_all() { 4664641aa53SMichal Berger local vms=() 4674641aa53SMichal Berger vms=("$VM_DIR"/+([0-9])) 4684641aa53SMichal Berger if ((${#vms[@]} > 0)); then 4694641aa53SMichal Berger basename --multiple "${vms[@]}" 4703d11b2feSBen Walker fi 4713d11b2feSBen Walker} 4723d11b2feSBen Walker 4738f44d126SBen Walker# Kills all VM in $VM_DIR 4743d11b2feSBen Walker# 475844c8ec3SMichal Bergerfunction vm_kill_all() { 4763d11b2feSBen Walker local vm 4773d11b2feSBen Walker for vm in $(vm_list_all); do 4783d11b2feSBen Walker vm_kill $vm 4793d11b2feSBen Walker done 480ad15da13SBen Walker 4818f44d126SBen Walker rm -rf $VM_DIR 4823d11b2feSBen Walker} 4833d11b2feSBen Walker 4848f44d126SBen Walker# Shutdown all VM in $VM_DIR 4853d11b2feSBen Walker# 486844c8ec3SMichal Bergerfunction vm_shutdown_all() { 487ea340dc4SMichal Berger local timeo=${1:-90} vms vm 4883d11b2feSBen Walker 489ea340dc4SMichal Berger vms=($(vm_list_all)) 4903d11b2feSBen Walker 491ea340dc4SMichal Berger for vm in "${vms[@]}"; do 492ea340dc4SMichal Berger vm_shutdown "$vm" 4933d11b2feSBen Walker done 4943d11b2feSBen Walker 4953d11b2feSBen Walker notice "Waiting for VMs to shutdown..." 496ea340dc4SMichal Berger while ((timeo-- > 0 && ${#vms[@]} > 0)); do 497ea340dc4SMichal Berger for vm in "${!vms[@]}"; do 498ea340dc4SMichal Berger vm_is_running "${vms[vm]}" || unset -v "vms[vm]" 4993d11b2feSBen Walker done 5003d11b2feSBen Walker sleep 1 5013d11b2feSBen Walker done 5023d11b2feSBen Walker 503ea340dc4SMichal Berger if ((${#vms[@]} == 0)); then 504ea340dc4SMichal Berger notice "All VMs successfully shut down" 505ea340dc4SMichal Berger return 0 506ea340dc4SMichal Berger fi 507ad15da13SBen Walker 508ea340dc4SMichal Berger warning "Not all VMs were shut down. Leftovers: ${vms[*]}" 509ea340dc4SMichal Berger 510ea340dc4SMichal Berger for vm in "${vms[@]}"; do 511ea340dc4SMichal Berger vm_print_logs "$vm" 512ea340dc4SMichal Berger done 513ea340dc4SMichal Berger 514ea340dc4SMichal Berger return 1 5153d11b2feSBen Walker} 5163d11b2feSBen Walker 517844c8ec3SMichal Bergerfunction vm_setup() { 51834ae1172SSeth Howell xtrace_disable 5193d11b2feSBen Walker local OPTIND optchar vm_num 5203d11b2feSBen Walker 5213d11b2feSBen Walker local os="" 5223d11b2feSBen Walker local os_mode="" 523e1ddec2cSMichal Berger local qemu_args=() 5243d11b2feSBen Walker local disk_type_g=NOT_DEFINED 5253d11b2feSBen Walker local read_only="false" 52664471319SMichal Berger # List created of a strings separated with a ":" 52764471319SMichal Berger local disks=() 5283d11b2feSBen Walker local raw_cache="" 5293d11b2feSBen Walker local vm_incoming="" 5303d11b2feSBen Walker local vm_migrate_to="" 5313d11b2feSBen Walker local force_vm="" 5323d11b2feSBen Walker local guest_memory=1024 533074df1d8SPawel Kaminski local vhost_dir 534262c35fcSKarol Latecki local packed=false 535074df1d8SPawel Kaminski vhost_dir="$(get_vhost_dir 0)" 5363d11b2feSBen Walker while getopts ':-:' optchar; do 5373d11b2feSBen Walker case "$optchar" in 5383d11b2feSBen Walker -) 5393d11b2feSBen Walker case "$OPTARG" in 540074df1d8SPawel Kaminski os=*) os="${OPTARG#*=}" ;; 541074df1d8SPawel Kaminski os-mode=*) os_mode="${OPTARG#*=}" ;; 542e1ddec2cSMichal Berger qemu-args=*) qemu_args+=("${OPTARG#*=}") ;; 543074df1d8SPawel Kaminski disk-type=*) disk_type_g="${OPTARG#*=}" ;; 544074df1d8SPawel Kaminski read-only=*) read_only="${OPTARG#*=}" ;; 54564471319SMichal Berger disks=*) IFS=":" read -ra disks <<< "${OPTARG#*=}" ;; 546074df1d8SPawel Kaminski raw-cache=*) raw_cache=",cache${OPTARG#*=}" ;; 547074df1d8SPawel Kaminski force=*) force_vm=${OPTARG#*=} ;; 548074df1d8SPawel Kaminski memory=*) guest_memory=${OPTARG#*=} ;; 549074df1d8SPawel Kaminski incoming=*) vm_incoming="${OPTARG#*=}" ;; 550074df1d8SPawel Kaminski migrate-to=*) vm_migrate_to="${OPTARG#*=}" ;; 551074df1d8SPawel Kaminski vhost-name=*) vhost_dir="$(get_vhost_dir ${OPTARG#*=})" ;; 5523d11b2feSBen Walker spdk-boot=*) local boot_from="${OPTARG#*=}" ;; 553262c35fcSKarol Latecki packed) packed=true ;; 5543d11b2feSBen Walker *) 5553d11b2feSBen Walker error "unknown argument $OPTARG" 5563d11b2feSBen Walker return 1 557844c8ec3SMichal Berger ;; 5583d11b2feSBen Walker esac 5593d11b2feSBen Walker ;; 5603d11b2feSBen Walker *) 5613d11b2feSBen Walker error "vm_create Unknown param $OPTARG" 5623d11b2feSBen Walker return 1 5633d11b2feSBen Walker ;; 5643d11b2feSBen Walker esac 5653d11b2feSBen Walker done 5663d11b2feSBen Walker 5673d11b2feSBen Walker # Find next directory we can use 5681ccc878eSKarol Latecki if [[ -n $force_vm ]]; then 5693d11b2feSBen Walker vm_num=$force_vm 5703d11b2feSBen Walker 5713d11b2feSBen Walker vm_num_is_valid $vm_num || return 1 5728f44d126SBen Walker local vm_dir="$VM_DIR/$vm_num" 5733d11b2feSBen Walker [[ -d $vm_dir ]] && warning "removing existing VM in '$vm_dir'" 5743d11b2feSBen Walker else 5753d11b2feSBen Walker local vm_dir="" 5763d11b2feSBen Walker 5773d11b2feSBen Walker set +x 5783d11b2feSBen Walker for ((i = 0; i <= 256; i++)); do 5798f44d126SBen Walker local vm_dir="$VM_DIR/$i" 5803d11b2feSBen Walker [[ ! -d $vm_dir ]] && break 5813d11b2feSBen Walker done 58234ae1172SSeth Howell xtrace_restore 5833d11b2feSBen Walker 5843d11b2feSBen Walker vm_num=$i 5853d11b2feSBen Walker fi 5863d11b2feSBen Walker 5876b9e48dfSSeth Howell if [[ $vm_num -eq 256 ]]; then 5883d11b2feSBen Walker error "no free VM found. do some cleanup (256 VMs created, are you insane?)" 5893d11b2feSBen Walker return 1 5903d11b2feSBen Walker fi 5913d11b2feSBen Walker 5921ccc878eSKarol Latecki if [[ -n "$vm_migrate_to" && -n "$vm_incoming" ]]; then 5933d11b2feSBen Walker error "'--incoming' and '--migrate-to' cannot be used together" 5943d11b2feSBen Walker return 1 5951ccc878eSKarol Latecki elif [[ -n "$vm_incoming" ]]; then 5964d0c5091SPawel Kaminski if [[ -n "$os_mode" || -n "$os" ]]; then 5973d11b2feSBen Walker error "'--incoming' can't be used together with '--os' nor '--os-mode'" 5983d11b2feSBen Walker return 1 5993d11b2feSBen Walker fi 6003d11b2feSBen Walker 6013d11b2feSBen Walker os_mode="original" 6028f44d126SBen Walker os="$VM_DIR/$vm_incoming/os.qcow2" 6031ccc878eSKarol Latecki elif [[ -n "$vm_migrate_to" ]]; then 6043d11b2feSBen Walker [[ "$os_mode" != "backing" ]] && warning "Using 'backing' mode for OS since '--migrate-to' is used" 6053d11b2feSBen Walker os_mode=backing 6063d11b2feSBen Walker fi 6073d11b2feSBen Walker 6083d11b2feSBen Walker notice "Creating new VM in $vm_dir" 6093d11b2feSBen Walker mkdir -p $vm_dir 6103d11b2feSBen Walker 6113d11b2feSBen Walker if [[ "$os_mode" == "backing" ]]; then 6123d11b2feSBen Walker notice "Creating backing file for OS image file: $os" 6136d1e0c0eSJaroslaw Chachulski if ! $QEMU_IMG_BIN create -f qcow2 -b $os $vm_dir/os.qcow2 -F qcow2; then 6143d11b2feSBen Walker error "Failed to create OS backing file in '$vm_dir/os.qcow2' using '$os'" 6153d11b2feSBen Walker return 1 6163d11b2feSBen Walker fi 6173d11b2feSBen Walker 6183d11b2feSBen Walker local os=$vm_dir/os.qcow2 6193d11b2feSBen Walker elif [[ "$os_mode" == "original" ]]; then 6203d11b2feSBen Walker warning "Using original OS image file: $os" 6213d11b2feSBen Walker elif [[ "$os_mode" != "snapshot" ]]; then 6223d11b2feSBen Walker if [[ -z "$os_mode" ]]; then 6233d11b2feSBen Walker notice "No '--os-mode' parameter provided - using 'snapshot'" 6243d11b2feSBen Walker os_mode="snapshot" 6253d11b2feSBen Walker else 6263d11b2feSBen Walker error "Invalid '--os-mode=$os_mode'" 6273d11b2feSBen Walker return 1 6283d11b2feSBen Walker fi 6293d11b2feSBen Walker fi 6303d11b2feSBen Walker 6313d11b2feSBen Walker local qemu_mask_param="VM_${vm_num}_qemu_mask" 6323d11b2feSBen Walker local qemu_numa_node_param="VM_${vm_num}_qemu_numa_node" 6333d11b2feSBen Walker 6343d11b2feSBen Walker if [[ -z "${!qemu_mask_param}" ]] || [[ -z "${!qemu_numa_node_param}" ]]; then 6353d11b2feSBen Walker error "Parameters ${qemu_mask_param} or ${qemu_numa_node_param} not found in autotest.config file" 6363d11b2feSBen Walker return 1 6373d11b2feSBen Walker fi 6383d11b2feSBen Walker 6393d11b2feSBen Walker local task_mask=${!qemu_mask_param} 6403d11b2feSBen Walker 6413d11b2feSBen Walker notice "TASK MASK: $task_mask" 642e1ddec2cSMichal Berger local cmd=(taskset -a -c "$task_mask" "$QEMU_BIN") 6433d11b2feSBen Walker local vm_socket_offset=$((10000 + 100 * vm_num)) 6443d11b2feSBen Walker 6453d11b2feSBen Walker local ssh_socket=$((vm_socket_offset + 0)) 6463d11b2feSBen Walker local fio_socket=$((vm_socket_offset + 1)) 6473d11b2feSBen Walker local monitor_port=$((vm_socket_offset + 2)) 6483d11b2feSBen Walker local migration_port=$((vm_socket_offset + 3)) 6493d11b2feSBen Walker local gdbserver_socket=$((vm_socket_offset + 4)) 6503d11b2feSBen Walker local vnc_socket=$((100 + vm_num)) 6513d11b2feSBen Walker local qemu_pid_file="$vm_dir/qemu.pid" 652632342a0SMichal Berger local cpu_list 653632342a0SMichal Berger local cpu_num=0 queue_number=0 6543d11b2feSBen Walker 655632342a0SMichal Berger cpu_list=($(parse_cpu_list <(echo "$task_mask"))) 656632342a0SMichal Berger cpu_num=${#cpu_list[@]} queue_number=$cpu_num 6573d11b2feSBen Walker 658632342a0SMichal Berger # Let's be paranoid about it 659632342a0SMichal Berger ((cpu_num > 0 && queue_number > 0)) || return 1 6603d11b2feSBen Walker 661905c4dcfSMichal Berger # Normalize tcp ports to make sure they are available 662905c4dcfSMichal Berger ssh_socket=$(get_free_tcp_port "$ssh_socket") 663905c4dcfSMichal Berger fio_socket=$(get_free_tcp_port "$fio_socket") 664905c4dcfSMichal Berger monitor_port=$(get_free_tcp_port "$monitor_port") 665905c4dcfSMichal Berger migration_port=$(get_free_tcp_port "$migration_port") 666905c4dcfSMichal Berger gdbserver_socket=$(get_free_tcp_port "$gdbserver_socket") 667905c4dcfSMichal Berger vnc_socket=$(get_free_tcp_port "$vnc_socket") 668905c4dcfSMichal Berger 66934ae1172SSeth Howell xtrace_restore 6703d11b2feSBen Walker 6713d11b2feSBen Walker local node_num=${!qemu_numa_node_param} 6723d11b2feSBen Walker local boot_disk_present=false 6733d11b2feSBen Walker notice "NUMA NODE: $node_num" 674e1ddec2cSMichal Berger cmd+=(-m "$guest_memory" --enable-kvm -cpu host -smp "$cpu_num" -vga std -vnc ":$vnc_socket" -daemonize) 675e1ddec2cSMichal Berger cmd+=(-object "memory-backend-file,id=mem,size=${guest_memory}M,mem-path=/dev/hugepages,share=on,prealloc=yes,host-nodes=$node_num,policy=bind") 676e1ddec2cSMichal Berger [[ $os_mode == snapshot ]] && cmd+=(-snapshot) 677e1ddec2cSMichal Berger [[ -n "$vm_incoming" ]] && cmd+=(-incoming "tcp:0:$migration_port") 678e1ddec2cSMichal Berger cmd+=(-monitor "telnet:127.0.0.1:$monitor_port,server,nowait") 679e1ddec2cSMichal Berger cmd+=(-numa "node,memdev=mem") 680e1ddec2cSMichal Berger cmd+=(-pidfile "$qemu_pid_file") 681e1ddec2cSMichal Berger cmd+=(-serial "file:$vm_dir/serial.log") 682e1ddec2cSMichal Berger cmd+=(-D "$vm_dir/qemu.log") 683e1ddec2cSMichal Berger cmd+=(-chardev "file,path=$vm_dir/seabios.log,id=seabios" -device "isa-debugcon,iobase=0x402,chardev=seabios") 684e1ddec2cSMichal Berger cmd+=(-net "user,hostfwd=tcp::$ssh_socket-:22,hostfwd=tcp::$fio_socket-:8765") 685e1ddec2cSMichal Berger cmd+=(-net nic) 6863d11b2feSBen Walker if [[ -z "$boot_from" ]]; then 687e1ddec2cSMichal Berger cmd+=(-drive "file=$os,if=none,id=os_disk") 688e1ddec2cSMichal Berger cmd+=(-device "ide-hd,drive=os_disk,bootindex=0") 6893d11b2feSBen Walker fi 6903d11b2feSBen Walker 69164471319SMichal Berger if ((${#disks[@]} == 0)) && [[ $disk_type_g == virtio* ]]; then 69264471319SMichal Berger disks=("default_virtio.img") 69364471319SMichal Berger elif ((${#disks[@]} == 0)); then 69464471319SMichal Berger error "No disks defined, aborting" 69564471319SMichal Berger return 1 6963d11b2feSBen Walker fi 6973d11b2feSBen Walker 69864471319SMichal Berger for disk in "${disks[@]}"; do 69964471319SMichal Berger # Each disk can define its type in a form of a disk_name,type. The remaining parts 70064471319SMichal Berger # of the string are dropped. 70164471319SMichal Berger IFS="," read -r disk disk_type _ <<< "$disk" 70264471319SMichal Berger [[ -z $disk_type ]] && disk_type=$disk_type_g 7033d11b2feSBen Walker 7043d11b2feSBen Walker case $disk_type in 7053d11b2feSBen Walker virtio) 7063d11b2feSBen Walker local raw_name="RAWSCSI" 7073d11b2feSBen Walker local raw_disk=$vm_dir/test.img 7083d11b2feSBen Walker 7093d11b2feSBen Walker # Create disk file if it not exist or it is smaller than 1G 710bf93cbdfSMichal Berger if [[ -f $disk && $(stat --printf="%s" $disk) -ge $((1024 * 1024 * 1024)) ]]; then 711bf93cbdfSMichal Berger raw_disk=$disk 712bf93cbdfSMichal Berger notice "Using existing image $raw_disk" 713bf93cbdfSMichal Berger else 7143d11b2feSBen Walker notice "Creating Virtio disc $raw_disk" 7153d11b2feSBen Walker dd if=/dev/zero of=$raw_disk bs=1024k count=1024 7163d11b2feSBen Walker fi 7173d11b2feSBen Walker 718e1ddec2cSMichal Berger cmd+=(-device "virtio-scsi-pci,num_queues=$queue_number") 719e1ddec2cSMichal Berger cmd+=(-device "scsi-hd,drive=hd$i,vendor=$raw_name") 720e1ddec2cSMichal Berger cmd+=(-drive "if=none,id=hd$i,file=$raw_disk,format=raw$raw_cache") 7213d11b2feSBen Walker ;; 7223d11b2feSBen Walker spdk_vhost_scsi) 7233d11b2feSBen Walker notice "using socket $vhost_dir/naa.$disk.$vm_num" 724e1ddec2cSMichal Berger cmd+=(-chardev "socket,id=char_$disk,path=$vhost_dir/naa.$disk.$vm_num") 725e1ddec2cSMichal Berger cmd+=(-device "vhost-user-scsi-pci,id=scsi_$disk,num_queues=$queue_number,chardev=char_$disk") 7263d11b2feSBen Walker if [[ "$disk" == "$boot_from" ]]; then 727e1ddec2cSMichal Berger cmd[-1]+=,bootindex=0 7283d11b2feSBen Walker boot_disk_present=true 7293d11b2feSBen Walker fi 7303d11b2feSBen Walker ;; 7313d11b2feSBen Walker spdk_vhost_blk) 7323d11b2feSBen Walker notice "using socket $vhost_dir/naa.$disk.$vm_num" 733e1ddec2cSMichal Berger cmd+=(-chardev "socket,id=char_$disk,path=$vhost_dir/naa.$disk.$vm_num") 734e1ddec2cSMichal Berger cmd+=(-device "vhost-user-blk-pci,num-queues=$queue_number,chardev=char_$disk") 7353d11b2feSBen Walker if [[ "$disk" == "$boot_from" ]]; then 736e1ddec2cSMichal Berger cmd[-1]+=,bootindex=0 7373d11b2feSBen Walker boot_disk_present=true 7383d11b2feSBen Walker fi 739262c35fcSKarol Latecki 740262c35fcSKarol Latecki if $packed; then 741262c35fcSKarol Latecki check_qemu_packedring_support 742262c35fcSKarol Latecki notice "Enabling packed ring support for VM $vm_num, controller $vhost_dir/naa.$disk.$vm_num" 743262c35fcSKarol Latecki cmd[-1]+=,packed=on 744262c35fcSKarol Latecki fi 7453d11b2feSBen Walker ;; 7463d11b2feSBen Walker kernel_vhost) 7473d11b2feSBen Walker if [[ -z $disk ]]; then 7483d11b2feSBen Walker error "need WWN for $disk_type" 7493d11b2feSBen Walker return 1 7503d11b2feSBen Walker elif [[ ! $disk =~ ^[[:alpha:]]{3}[.][[:xdigit:]]+$ ]]; then 7513d11b2feSBen Walker error "$disk_type - disk(wnn)=$disk does not look like WNN number" 7523d11b2feSBen Walker return 1 7533d11b2feSBen Walker fi 7543d11b2feSBen Walker notice "Using kernel vhost disk wwn=$disk" 755e1ddec2cSMichal Berger cmd+=(-device "vhost-scsi-pci,wwpn=$disk,num_queues=$queue_number") 7563d11b2feSBen Walker ;; 7575c385271SKarol Latecki vfio_user) 7585c385271SKarol Latecki notice "using socket $VM_DIR/$vm_num/domain/muser$disk/$disk/cntrl" 75939f5b26bSChangpeng Liu cmd+=(-device "vfio-user-pci,x-msg-timeout=5000,socket=$VM_DIR/$vm_num/muser/domain/muser$disk/$disk/cntrl") 7605c385271SKarol Latecki if [[ "$disk" == "$boot_from" ]]; then 7615c385271SKarol Latecki cmd[-1]+=",bootindex=0" 7625c385271SKarol Latecki boot_disk_present=true 7635c385271SKarol Latecki fi 7645c385271SKarol Latecki ;; 7656d7f012aSChangpeng Liu vfio_user_virtio) 7666d7f012aSChangpeng Liu notice "using socket $VM_DIR/vfu_tgt/virtio.$disk" 7676d7f012aSChangpeng Liu cmd+=(-device "vfio-user-pci,x-msg-timeout=5000,socket=$VM_DIR/vfu_tgt/virtio.$disk") 7686d7f012aSChangpeng Liu if [[ "$disk" == "$boot_from" ]]; then 7696d7f012aSChangpeng Liu cmd[-1]+=",bootindex=0" 7706d7f012aSChangpeng Liu boot_disk_present=true 7716d7f012aSChangpeng Liu fi 7726d7f012aSChangpeng Liu ;; 7733d11b2feSBen Walker *) 7746d7f012aSChangpeng Liu error "unknown mode '$disk_type', use: virtio, spdk_vhost_scsi, spdk_vhost_blk, kernel_vhost, vfio_user or vfio_user_virtio" 7753d11b2feSBen Walker return 1 77616e16c77SMichal Berger ;; 7773d11b2feSBen Walker esac 7783d11b2feSBen Walker done 7793d11b2feSBen Walker 7803d11b2feSBen Walker if [[ -n $boot_from ]] && [[ $boot_disk_present == false ]]; then 7813d11b2feSBen Walker error "Boot from $boot_from is selected but device is not present" 7823d11b2feSBen Walker return 1 7833d11b2feSBen Walker fi 7843d11b2feSBen Walker 785e1ddec2cSMichal Berger ((${#qemu_args[@]})) && cmd+=("${qemu_args[@]}") 7863d11b2feSBen Walker notice "Saving to $vm_dir/run.sh" 78708f0abebSMichal Berger cat <<- RUN > "$vm_dir/run.sh" 78808f0abebSMichal Berger #!/bin/bash 7892d8b9911SMichal Berger shopt -s nullglob extglob 7906872c67eSMichal Berger rootdir=$rootdir 7916872c67eSMichal Berger source "\$rootdir/test/scheduler/common.sh" 792d9d62e11SMichal Berger qemu_log () { 793d9d62e11SMichal Berger echo "=== qemu.log ===" 794d9d62e11SMichal Berger [[ -s $vm_dir/qemu.log ]] && cat $vm_dir/qemu.log 795d9d62e11SMichal Berger echo "=== qemu.log ===" 796d9d62e11SMichal Berger } 79708f0abebSMichal Berger 79808f0abebSMichal Berger if [[ \$EUID -ne 0 ]]; then 79908f0abebSMichal Berger echo "Go away user come back as root" 80008f0abebSMichal Berger exit 1 80108f0abebSMichal Berger fi 80208f0abebSMichal Berger 803d9d62e11SMichal Berger trap "qemu_log" EXIT 80408f0abebSMichal Berger 805d9d62e11SMichal Berger qemu_cmd=($(printf '%s\n' "${cmd[@]}")) 806d9d62e11SMichal Berger chmod +r $vm_dir/* 80708f0abebSMichal Berger echo "Running VM in $vm_dir" 80808f0abebSMichal Berger rm -f $qemu_pid_file 8096872c67eSMichal Berger cgroup=\$(get_cgroup \$$) 8106872c67eSMichal Berger set_cgroup_attr_top_bottom \$$ cgroup.subtree_control "+cpuset" 8116872c67eSMichal Berger create_cgroup \$cgroup/qemu.$vm_num 8126872c67eSMichal Berger set_cgroup_attr "\$cgroup/qemu.$vm_num" cpuset.mems "$node_num" 8136872c67eSMichal Berger set_cgroup_attr "\$cgroup/qemu.$vm_num" cpuset.cpus "$task_mask" 81408f0abebSMichal Berger "\${qemu_cmd[@]}" 815d9d62e11SMichal Berger 81608f0abebSMichal Berger echo "Waiting for QEMU pid file" 81708f0abebSMichal Berger sleep 1 81808f0abebSMichal Berger [[ ! -f $qemu_pid_file ]] && sleep 1 81908f0abebSMichal Berger [[ ! -f $qemu_pid_file ]] && echo "ERROR: no qemu pid file found" && exit 1 8206872c67eSMichal Berger set_cgroup_attr "\$cgroup/qemu.$vm_num" cgroup.threads \$(< "$qemu_pid_file") 821d9d62e11SMichal Berger exit 0 82208f0abebSMichal Berger # EOF 82308f0abebSMichal Berger RUN 8243d11b2feSBen Walker chmod +x $vm_dir/run.sh 8253d11b2feSBen Walker 8263d11b2feSBen Walker # Save generated sockets redirection 8273d11b2feSBen Walker echo $ssh_socket > $vm_dir/ssh_socket 8283d11b2feSBen Walker echo $fio_socket > $vm_dir/fio_socket 8293d11b2feSBen Walker echo $monitor_port > $vm_dir/monitor_port 8303d11b2feSBen Walker 8313d11b2feSBen Walker rm -f $vm_dir/migration_port 8323d11b2feSBen Walker [[ -z $vm_incoming ]] || echo $migration_port > $vm_dir/migration_port 8333d11b2feSBen Walker 8343d11b2feSBen Walker echo $gdbserver_socket > $vm_dir/gdbserver_socket 8353d11b2feSBen Walker echo $vnc_socket >> $vm_dir/vnc_socket 8363d11b2feSBen Walker 8378f44d126SBen Walker [[ -z $vm_incoming ]] || ln -fs $VM_DIR/$vm_incoming $vm_dir/vm_incoming 8388f44d126SBen Walker [[ -z $vm_migrate_to ]] || ln -fs $VM_DIR/$vm_migrate_to $vm_dir/vm_migrate_to 8393d11b2feSBen Walker} 8403d11b2feSBen Walker 841844c8ec3SMichal Bergerfunction vm_run() { 8423d11b2feSBen Walker local OPTIND optchar vm 8433d11b2feSBen Walker local run_all=false 8443d11b2feSBen Walker local vms_to_run="" 8453d11b2feSBen Walker 8463d11b2feSBen Walker while getopts 'a-:' optchar; do 8473d11b2feSBen Walker case "$optchar" in 8483d11b2feSBen Walker a) run_all=true ;; 8493d11b2feSBen Walker *) 8503d11b2feSBen Walker error "Unknown param $OPTARG" 8513d11b2feSBen Walker return 1 8523d11b2feSBen Walker ;; 8533d11b2feSBen Walker esac 8543d11b2feSBen Walker done 8553d11b2feSBen Walker 8563d11b2feSBen Walker if $run_all; then 8573d11b2feSBen Walker vms_to_run="$(vm_list_all)" 8583d11b2feSBen Walker else 8593d11b2feSBen Walker shift $((OPTIND - 1)) 860fdc82d3bSMaciej Wawryk for vm in "$@"; do 8613d11b2feSBen Walker vm_num_is_valid $1 || return 1 8628f44d126SBen Walker if [[ ! -x $VM_DIR/$vm/run.sh ]]; then 8633d11b2feSBen Walker error "VM$vm not defined - setup it first" 8643d11b2feSBen Walker return 1 8653d11b2feSBen Walker fi 8663d11b2feSBen Walker vms_to_run+=" $vm" 8673d11b2feSBen Walker done 8683d11b2feSBen Walker fi 8693d11b2feSBen Walker 8703d11b2feSBen Walker for vm in $vms_to_run; do 8713d11b2feSBen Walker if vm_is_running $vm; then 8728f44d126SBen Walker warning "VM$vm ($VM_DIR/$vm) already running" 8733d11b2feSBen Walker continue 8743d11b2feSBen Walker fi 8753d11b2feSBen Walker 8768f44d126SBen Walker notice "running $VM_DIR/$vm/run.sh" 8778f44d126SBen Walker if ! $VM_DIR/$vm/run.sh; then 8783d11b2feSBen Walker error "FAILED to run vm $vm" 8793d11b2feSBen Walker return 1 8803d11b2feSBen Walker fi 8813d11b2feSBen Walker done 8823d11b2feSBen Walker} 8833d11b2feSBen Walker 884844c8ec3SMichal Bergerfunction vm_print_logs() { 8853d11b2feSBen Walker vm_num=$1 8863d11b2feSBen Walker warning "================" 8873d11b2feSBen Walker warning "QEMU LOG:" 8888f44d126SBen Walker if [[ -r $VM_DIR/$vm_num/qemu.log ]]; then 8898f44d126SBen Walker cat $VM_DIR/$vm_num/qemu.log 8903d11b2feSBen Walker else 8913d11b2feSBen Walker warning "LOG qemu.log not found" 8923d11b2feSBen Walker fi 8933d11b2feSBen Walker 8943d11b2feSBen Walker warning "VM LOG:" 8958f44d126SBen Walker if [[ -r $VM_DIR/$vm_num/serial.log ]]; then 8968f44d126SBen Walker cat $VM_DIR/$vm_num/serial.log 8973d11b2feSBen Walker else 8983d11b2feSBen Walker warning "LOG serial.log not found" 8993d11b2feSBen Walker fi 9003d11b2feSBen Walker 9013d11b2feSBen Walker warning "SEABIOS LOG:" 9028f44d126SBen Walker if [[ -r $VM_DIR/$vm_num/seabios.log ]]; then 9038f44d126SBen Walker cat $VM_DIR/$vm_num/seabios.log 9043d11b2feSBen Walker else 9053d11b2feSBen Walker warning "LOG seabios.log not found" 9063d11b2feSBen Walker fi 9073d11b2feSBen Walker warning "================" 9083d11b2feSBen Walker} 9093d11b2feSBen Walker 9103d11b2feSBen Walker# Wait for all created VMs to boot. 9113d11b2feSBen Walker# param $1 max wait time 912844c8ec3SMichal Bergerfunction vm_wait_for_boot() { 9133d11b2feSBen Walker assert_number $1 9143d11b2feSBen Walker 91534ae1172SSeth Howell xtrace_disable 9163d11b2feSBen Walker 9173d11b2feSBen Walker local all_booted=false 9183d11b2feSBen Walker local timeout_time=$1 9193d11b2feSBen Walker [[ $timeout_time -lt 10 ]] && timeout_time=10 920074df1d8SPawel Kaminski local timeout_time 921074df1d8SPawel Kaminski timeout_time=$(date -d "+$timeout_time seconds" +%s) 9223d11b2feSBen Walker 9233d11b2feSBen Walker notice "Waiting for VMs to boot" 9243d11b2feSBen Walker shift 925eda1ec69SSeth Howell if [[ "$*" == "" ]]; then 9268f44d126SBen Walker local vms_to_check="$VM_DIR/[0-9]*" 9273d11b2feSBen Walker else 9283d11b2feSBen Walker local vms_to_check="" 929fdc82d3bSMaciej Wawryk for vm in "$@"; do 9308f44d126SBen Walker vms_to_check+=" $VM_DIR/$vm" 9313d11b2feSBen Walker done 9323d11b2feSBen Walker fi 9333d11b2feSBen Walker 9343d11b2feSBen Walker for vm in $vms_to_check; do 935074df1d8SPawel Kaminski local vm_num 936074df1d8SPawel Kaminski vm_num=$(basename $vm) 9373d11b2feSBen Walker local i=0 9383d11b2feSBen Walker notice "waiting for VM$vm_num ($vm)" 9393d11b2feSBen Walker while ! vm_os_booted $vm_num; do 9403d11b2feSBen Walker if ! vm_is_running $vm_num; then 9413d11b2feSBen Walker warning "VM $vm_num is not running" 9423d11b2feSBen Walker vm_print_logs $vm_num 94334ae1172SSeth Howell xtrace_restore 9443d11b2feSBen Walker return 1 9453d11b2feSBen Walker fi 9463d11b2feSBen Walker 9473d11b2feSBen Walker if [[ $(date +%s) -gt $timeout_time ]]; then 9483d11b2feSBen Walker warning "timeout waiting for machines to boot" 9493d11b2feSBen Walker vm_print_logs $vm_num 95034ae1172SSeth Howell xtrace_restore 9513d11b2feSBen Walker return 1 9523d11b2feSBen Walker fi 9533d11b2feSBen Walker if ((i > 30)); then 9543d11b2feSBen Walker local i=0 9553d11b2feSBen Walker echo 9563d11b2feSBen Walker fi 9573d11b2feSBen Walker echo -n "." 9583d11b2feSBen Walker sleep 1 9593d11b2feSBen Walker done 9603d11b2feSBen Walker echo "" 9613d11b2feSBen Walker notice "VM$vm_num ready" 9623d11b2feSBen Walker #Change Timeout for stopping services to prevent lengthy powerdowns 9633d11b2feSBen Walker #Check that remote system is not Cygwin in case of Windows VMs 964074df1d8SPawel Kaminski local vm_os 965074df1d8SPawel Kaminski vm_os=$(vm_exec $vm_num "uname -o") 9663d11b2feSBen Walker if [[ "$vm_os" != "Cygwin" ]]; then 96797df5bccSBen Walker vm_exec $vm_num "echo 'DefaultTimeoutStopSec=10' >> /etc/systemd/system.conf; systemctl daemon-reexec" 9683d11b2feSBen Walker fi 9693d11b2feSBen Walker done 9703d11b2feSBen Walker 9713d11b2feSBen Walker notice "all VMs ready" 97234ae1172SSeth Howell xtrace_restore 9733d11b2feSBen Walker return 0 9743d11b2feSBen Walker} 9753d11b2feSBen Walker 976844c8ec3SMichal Bergerfunction vm_start_fio_server() { 9773d11b2feSBen Walker local OPTIND optchar 9783d11b2feSBen Walker local readonly='' 979d3e367a5SKarol Latecki local fio_bin='' 9803d11b2feSBen Walker while getopts ':-:' optchar; do 9813d11b2feSBen Walker case "$optchar" in 9823d11b2feSBen Walker -) 9833d11b2feSBen Walker case "$OPTARG" in 9843d11b2feSBen Walker fio-bin=*) local fio_bin="${OPTARG#*=}" ;; 9853d11b2feSBen Walker readonly) local readonly="--readonly" ;; 9863d11b2feSBen Walker *) error "Invalid argument '$OPTARG'" && return 1 ;; 9873d11b2feSBen Walker esac 9883d11b2feSBen Walker ;; 9893d11b2feSBen Walker *) error "Invalid argument '$OPTARG'" && return 1 ;; 9903d11b2feSBen Walker esac 9913d11b2feSBen Walker done 9923d11b2feSBen Walker 9933d11b2feSBen Walker shift $((OPTIND - 1)) 994fdc82d3bSMaciej Wawryk for vm_num in "$@"; do 9953d11b2feSBen Walker notice "Starting fio server on VM$vm_num" 9963d11b2feSBen Walker if [[ $fio_bin != "" ]]; then 99713c6c8dbSPawel Kaminski vm_exec $vm_num 'cat > /root/fio; chmod +x /root/fio' < $fio_bin 99897df5bccSBen Walker vm_exec $vm_num /root/fio $readonly --eta=never --server --daemonize=/root/fio.pid 9993d11b2feSBen Walker else 100097df5bccSBen Walker vm_exec $vm_num fio $readonly --eta=never --server --daemonize=/root/fio.pid 10013d11b2feSBen Walker fi 10023d11b2feSBen Walker done 10033d11b2feSBen Walker} 10043d11b2feSBen Walker 1005844c8ec3SMichal Bergerfunction vm_check_scsi_location() { 10063d11b2feSBen Walker # Script to find wanted disc 10076956b0ecSMaciej Wawryk local script='shopt -s nullglob; 10086956b0ecSMaciej Wawryk for entry in /sys/block/sd*; do 10096956b0ecSMaciej Wawryk disk_type="$(cat $entry/device/vendor)"; 10106956b0ecSMaciej Wawryk if [[ $disk_type == INTEL* ]] || [[ $disk_type == RAWSCSI* ]] || [[ $disk_type == LIO-ORG* ]]; then 10116956b0ecSMaciej Wawryk fname=$(basename $entry); 10126956b0ecSMaciej Wawryk echo -n " $fname"; 10136956b0ecSMaciej Wawryk fi; 10143d11b2feSBen Walker done' 10153d11b2feSBen Walker 101697df5bccSBen Walker SCSI_DISK="$(echo "$script" | vm_exec $1 bash -s)" 10173d11b2feSBen Walker 10183d11b2feSBen Walker if [[ -z "$SCSI_DISK" ]]; then 10193d11b2feSBen Walker error "no test disk found!" 10203d11b2feSBen Walker return 1 10213d11b2feSBen Walker fi 10223d11b2feSBen Walker} 10233d11b2feSBen Walker 10243d11b2feSBen Walker# Script to perform scsi device reset on all disks in VM 10253d11b2feSBen Walker# param $1 VM num 10263d11b2feSBen Walker# param $2..$n Disks to perform reset on 1027844c8ec3SMichal Bergerfunction vm_reset_scsi_devices() { 10283d11b2feSBen Walker for disk in "${@:2}"; do 10293d11b2feSBen Walker notice "VM$1 Performing device reset on disk $disk" 103097df5bccSBen Walker vm_exec $1 sg_reset /dev/$disk -vNd 10313d11b2feSBen Walker done 10323d11b2feSBen Walker} 10333d11b2feSBen Walker 1034844c8ec3SMichal Bergerfunction vm_check_blk_location() { 10353d11b2feSBen Walker local script='shopt -s nullglob; cd /sys/block; echo vd*' 103697df5bccSBen Walker SCSI_DISK="$(echo "$script" | vm_exec $1 bash -s)" 10373d11b2feSBen Walker 10383d11b2feSBen Walker if [[ -z "$SCSI_DISK" ]]; then 10393d11b2feSBen Walker error "no blk test disk found!" 10403d11b2feSBen Walker return 1 10413d11b2feSBen Walker fi 10423d11b2feSBen Walker} 10433d11b2feSBen Walker 10445c385271SKarol Lateckifunction vm_check_nvme_location() { 10457cd8de9cSMichal Berger SCSI_DISK="$(vm_exec $1 "grep -l SPDK /sys/class/nvme/*/model" | awk -F/ '{print $5"n1"}')" 10465c385271SKarol Latecki if [[ -z "$SCSI_DISK" ]]; then 10475c385271SKarol Latecki error "no vfio-user nvme test disk found!" 10485c385271SKarol Latecki return 1 10495c385271SKarol Latecki fi 10505c385271SKarol Latecki} 10515c385271SKarol Latecki 1052844c8ec3SMichal Bergerfunction run_fio() { 10533d11b2feSBen Walker local arg 10543d11b2feSBen Walker local job_file="" 10553d11b2feSBen Walker local fio_bin="" 10563d11b2feSBen Walker local vms=() 10573d11b2feSBen Walker local out="" 10583d11b2feSBen Walker local vm 10593d11b2feSBen Walker local run_server_mode=true 1060a0e6c88dSKarol Latecki local run_plugin_mode=false 1061a70d47beSKarol Latecki local fio_start_cmd 1062a70d47beSKarol Latecki local fio_output_format="normal" 1063757eddebSKarol Latecki local fio_gtod_reduce=false 106401425928SKarol Latecki local wait_for_fio=true 10653d11b2feSBen Walker 1066fdc82d3bSMaciej Wawryk for arg in "$@"; do 10673d11b2feSBen Walker case "$arg" in 10683d11b2feSBen Walker --job-file=*) local job_file="${arg#*=}" ;; 10693d11b2feSBen Walker --fio-bin=*) local fio_bin="${arg#*=}" ;; 10703d11b2feSBen Walker --vm=*) vms+=("${arg#*=}") ;; 10713d11b2feSBen Walker --out=*) 10723d11b2feSBen Walker local out="${arg#*=}" 10733d11b2feSBen Walker mkdir -p $out 10743d11b2feSBen Walker ;; 10753d11b2feSBen Walker --local) run_server_mode=false ;; 1076a0e6c88dSKarol Latecki --plugin) 1077a0e6c88dSKarol Latecki notice "Using plugin mode. Disabling server mode." 1078a0e6c88dSKarol Latecki run_plugin_mode=true 1079844c8ec3SMichal Berger run_server_mode=false 1080844c8ec3SMichal Berger ;; 1081a70d47beSKarol Latecki --json) fio_output_format="json" ;; 1082a70d47beSKarol Latecki --hide-results) hide_results=true ;; 108301425928SKarol Latecki --no-wait-for-fio) wait_for_fio=false ;; 1084757eddebSKarol Latecki --gtod-reduce) fio_gtod_reduce=true ;; 10853d11b2feSBen Walker *) 10863d11b2feSBen Walker error "Invalid argument '$arg'" 10873d11b2feSBen Walker return 1 10883d11b2feSBen Walker ;; 10893d11b2feSBen Walker esac 10903d11b2feSBen Walker done 10913d11b2feSBen Walker 10921ccc878eSKarol Latecki if [[ -n "$fio_bin" && ! -r "$fio_bin" ]]; then 10933d11b2feSBen Walker error "FIO binary '$fio_bin' does not exist" 10943d11b2feSBen Walker return 1 10953d11b2feSBen Walker fi 10963d11b2feSBen Walker 10972c7ba231SKarol Latecki if [[ -z "$fio_bin" ]]; then 10982c7ba231SKarol Latecki fio_bin="fio" 10992c7ba231SKarol Latecki fi 11002c7ba231SKarol Latecki 11013d11b2feSBen Walker if [[ ! -r "$job_file" ]]; then 11023d11b2feSBen Walker error "Fio job '$job_file' does not exist" 11033d11b2feSBen Walker return 1 11043d11b2feSBen Walker fi 11053d11b2feSBen Walker 1106a70d47beSKarol Latecki fio_start_cmd="$fio_bin --eta=never " 1107a70d47beSKarol Latecki 1108074df1d8SPawel Kaminski local job_fname 1109074df1d8SPawel Kaminski job_fname=$(basename "$job_file") 11103eb1aa93SKarol Latecki log_fname="${job_fname%%.*}.log" 11113eb1aa93SKarol Latecki fio_start_cmd+=" --output=$out/$log_fname --output-format=$fio_output_format " 1112a70d47beSKarol Latecki 11133d11b2feSBen Walker # prepare job file for each VM 1114fdc82d3bSMaciej Wawryk for vm in "${vms[@]}"; do 11153d11b2feSBen Walker local vm_num=${vm%%:*} 11163d11b2feSBen Walker local vmdisks=${vm#*:} 11173d11b2feSBen Walker 1118ce6550a9SMichal Berger sed "s@filename=@filename=$vmdisks@;s@description=\(.*\)@description=\1 (VM=$vm_num)@" "$job_file" \ 1119ce6550a9SMichal Berger | vm_exec $vm_num "cat > /root/$job_fname" 1120757eddebSKarol Latecki 1121757eddebSKarol Latecki if $fio_gtod_reduce; then 1122757eddebSKarol Latecki vm_exec $vm_num "echo 'gtod_reduce=1' >> /root/$job_fname" 1123757eddebSKarol Latecki fi 1124757eddebSKarol Latecki 112597df5bccSBen Walker vm_exec $vm_num cat /root/$job_fname 1126a70d47beSKarol Latecki 1127a70d47beSKarol Latecki if $run_server_mode; then 1128a70d47beSKarol Latecki fio_start_cmd+="--client=127.0.0.1,$(vm_fio_socket $vm_num) --remote-config /root/$job_fname " 1129a70d47beSKarol Latecki fi 1130a70d47beSKarol Latecki 11313d11b2feSBen Walker if ! $run_server_mode; then 11321ccc878eSKarol Latecki if [[ -n "$fio_bin" ]]; then 1133a4a04624SMichal Berger if ! $run_plugin_mode && [[ -e $fio_bin ]]; then 113413c6c8dbSPawel Kaminski vm_exec $vm_num 'cat > /root/fio; chmod +x /root/fio' < $fio_bin 1135a0e6c88dSKarol Latecki vm_fio_bin="/root/fio" 1136a0e6c88dSKarol Latecki else 1137a4a04624SMichal Berger vm_fio_bin=$fio_bin 1138a0e6c88dSKarol Latecki fi 11393d11b2feSBen Walker fi 11403d11b2feSBen Walker 11413d11b2feSBen Walker notice "Running local fio on VM $vm_num" 114201425928SKarol Latecki vm_exec $vm_num "$vm_fio_bin --output=/root/$log_fname --output-format=$fio_output_format /root/$job_fname & echo \$! > /root/fio.pid" & 11439fc706f4SKarol Latecki vm_exec_pids+=("$!") 11443d11b2feSBen Walker fi 11453d11b2feSBen Walker done 11463d11b2feSBen Walker 11473d11b2feSBen Walker if ! $run_server_mode; then 114801425928SKarol Latecki if ! $wait_for_fio; then 114901425928SKarol Latecki return 0 115001425928SKarol Latecki fi 11519fc706f4SKarol Latecki echo "Waiting for guest fio instances to finish.." 11529fc706f4SKarol Latecki wait "${vm_exec_pids[@]}" 11539fc706f4SKarol Latecki 11549fc706f4SKarol Latecki for vm in "${vms[@]}"; do 11559fc706f4SKarol Latecki local vm_num=${vm%%:*} 11563eb1aa93SKarol Latecki vm_exec $vm_num cat /root/$log_fname > "$out/vm${vm_num}_${log_fname}" 11579fc706f4SKarol Latecki done 11583d11b2feSBen Walker return 0 11593d11b2feSBen Walker fi 11603d11b2feSBen Walker 1161a70d47beSKarol Latecki $fio_start_cmd 11622c7ba231SKarol Latecki sleep 1 1163a70d47beSKarol Latecki 1164782681e0SKarol Latecki if [[ "$fio_output_format" == "json" ]]; then 1165782681e0SKarol Latecki # Fio in client-server mode produces a lot of "trash" output 1166782681e0SKarol Latecki # preceding JSON structure, making it not possible to parse. 1167782681e0SKarol Latecki # Remove these lines from file. 1168782681e0SKarol Latecki # shellcheck disable=SC2005 1169782681e0SKarol Latecki echo "$(grep -vP '^[<\w]' "$out/$log_fname")" > "$out/$log_fname" 1170782681e0SKarol Latecki fi 1171782681e0SKarol Latecki 1172a70d47beSKarol Latecki if [[ ! $hide_results ]]; then 11733eb1aa93SKarol Latecki cat $out/$log_fname 1174a70d47beSKarol Latecki fi 11753d11b2feSBen Walker} 11763d11b2feSBen Walker 1177c3dc7fb5SKarol Latecki# Parsing fio results for json output and client-server mode only! 1178c3dc7fb5SKarol Lateckifunction parse_fio_results() { 1179c3dc7fb5SKarol Latecki local fio_log_dir=$1 1180c3dc7fb5SKarol Latecki local fio_log_filename=$2 1181c3dc7fb5SKarol Latecki local fio_csv_filename 1182c3dc7fb5SKarol Latecki 1183c3dc7fb5SKarol Latecki # Variables used in parsing loop 1184c3dc7fb5SKarol Latecki local log_file 1185c3dc7fb5SKarol Latecki local rwmode mixread mixwrite 1186c3dc7fb5SKarol Latecki local lat_key lat_divisor 1187c3dc7fb5SKarol Latecki local client_stats iops bw 1188c3dc7fb5SKarol Latecki local read_avg_lat read_min_lat read_max_lat 1189c3dc7fb5SKarol Latecki local write_avg_lat write_min_lat write_min_lat 119051a8f16eSMichal Berger local clients 1191c3dc7fb5SKarol Latecki 1192c3dc7fb5SKarol Latecki declare -A results 1193c3dc7fb5SKarol Latecki results["iops"]=0 1194c3dc7fb5SKarol Latecki results["bw"]=0 1195c3dc7fb5SKarol Latecki results["avg_lat"]=0 1196c3dc7fb5SKarol Latecki results["min_lat"]=0 1197c3dc7fb5SKarol Latecki results["max_lat"]=0 1198c3dc7fb5SKarol Latecki 1199c3dc7fb5SKarol Latecki # Loop using the log filename to see if there are any other 1200c3dc7fb5SKarol Latecki # matching files. This is in case we ran fio test multiple times. 1201c3dc7fb5SKarol Latecki log_files=("$fio_log_dir/$fio_log_filename"*) 1202c3dc7fb5SKarol Latecki for log_file in "${log_files[@]}"; do 120351a8f16eSMichal Berger # Save entire array to avoid opening $log_file multiple times 120451a8f16eSMichal Berger clients=$(jq -r '.client_stats' "$log_file") 120551a8f16eSMichal Berger [[ -n $clients ]] 120651a8f16eSMichal Berger rwmode=$(jq -r '.[0]["job options"]["rw"]' <<< "$clients") 1207c3dc7fb5SKarol Latecki mixread=1 1208c3dc7fb5SKarol Latecki mixwrite=1 1209c3dc7fb5SKarol Latecki if [[ $rwmode = *"rw"* ]]; then 121051a8f16eSMichal Berger mixread=$(jq -r '.[0]["job options"]["rwmixread"]' <<< "$clients") 1211c3dc7fb5SKarol Latecki mixread=$(bc -l <<< "scale=3; $mixread/100") 1212c3dc7fb5SKarol Latecki mixwrite=$(bc -l <<< "scale=3; 1-$mixread") 1213c3dc7fb5SKarol Latecki fi 1214c3dc7fb5SKarol Latecki 121551a8f16eSMichal Berger client_stats=$(jq -r '.[] | select(.jobname == "All clients")' <<< "$clients") 121651a8f16eSMichal Berger if [[ -z $client_stats ]]; then 121751a8f16eSMichal Berger # Potentially single client (single VM) 121851a8f16eSMichal Berger client_stats=$(jq -r '.[]' <<< "$clients") 121951a8f16eSMichal Berger fi 1220c3dc7fb5SKarol Latecki 1221c3dc7fb5SKarol Latecki # Check latency unit and later normalize to microseconds 1222c3dc7fb5SKarol Latecki lat_key="lat_us" 1223c3dc7fb5SKarol Latecki lat_divisor=1 1224c3dc7fb5SKarol Latecki if jq -er '.read["lat_ns"]' &> /dev/null <<< $client_stats; then 1225c3dc7fb5SKarol Latecki lat_key="lat_ns" 1226c3dc7fb5SKarol Latecki lat_divisor=1000 1227c3dc7fb5SKarol Latecki fi 1228c3dc7fb5SKarol Latecki 1229c9c7c281SJosh Soref # Horrific bash float point arithmetic operations below. 1230c3dc7fb5SKarol Latecki # Viewer discretion is advised. 1231c3dc7fb5SKarol Latecki iops=$(jq -r '[.read["iops"],.write["iops"]] | add' <<< $client_stats) 1232c3dc7fb5SKarol Latecki bw=$(jq -r '[.read["bw"],.write["bw"]] | add' <<< $client_stats) 1233c3dc7fb5SKarol Latecki read_avg_lat=$(jq -r --arg lat_key $lat_key '.read[$lat_key]["mean"]' <<< $client_stats) 1234c3dc7fb5SKarol Latecki read_min_lat=$(jq -r --arg lat_key $lat_key '.read[$lat_key]["min"]' <<< $client_stats) 1235c3dc7fb5SKarol Latecki read_max_lat=$(jq -r --arg lat_key $lat_key '.read[$lat_key]["max"]' <<< $client_stats) 1236c3dc7fb5SKarol Latecki write_avg_lat=$(jq -r --arg lat_key $lat_key '.write[$lat_key]["mean"]' <<< $client_stats) 1237c3dc7fb5SKarol Latecki write_min_lat=$(jq -r --arg lat_key $lat_key '.write[$lat_key]["min"]' <<< $client_stats) 1238c3dc7fb5SKarol Latecki write_max_lat=$(jq -r --arg lat_key $lat_key '.write[$lat_key]["max"]' <<< $client_stats) 1239c3dc7fb5SKarol Latecki 1240c3dc7fb5SKarol Latecki results["iops"]=$(bc -l <<< "${results[iops]} + $iops") 1241c3dc7fb5SKarol Latecki results["bw"]=$(bc -l <<< "${results[bw]} + $bw") 1242c3dc7fb5SKarol Latecki results["avg_lat"]=$(bc -l <<< "${results[avg_lat]} + ($mixread*$read_avg_lat + $mixwrite*$write_avg_lat)/$lat_divisor") 1243c3dc7fb5SKarol Latecki results["min_lat"]=$(bc -l <<< "${results[min_lat]} + ($mixread*$read_min_lat + $mixwrite*$write_min_lat)/$lat_divisor") 1244c3dc7fb5SKarol Latecki results["max_lat"]=$(bc -l <<< "${results[max_lat]} + ($mixread*$read_max_lat + $mixwrite*$write_max_lat)/$lat_divisor") 1245c3dc7fb5SKarol Latecki done 1246c3dc7fb5SKarol Latecki 1247c3dc7fb5SKarol Latecki results["iops"]=$(bc -l <<< "scale=3; ${results[iops]} / ${#log_files[@]}") 1248c3dc7fb5SKarol Latecki results["bw"]=$(bc -l <<< "scale=3; ${results[bw]} / ${#log_files[@]}") 1249c3dc7fb5SKarol Latecki results["avg_lat"]=$(bc -l <<< "scale=3; ${results[avg_lat]} / ${#log_files[@]}") 1250c3dc7fb5SKarol Latecki results["min_lat"]=$(bc -l <<< "scale=3; ${results[min_lat]} / ${#log_files[@]}") 1251c3dc7fb5SKarol Latecki results["max_lat"]=$(bc -l <<< "scale=3; ${results[max_lat]} / ${#log_files[@]}") 1252c3dc7fb5SKarol Latecki 1253c3dc7fb5SKarol Latecki fio_csv_filename="${fio_log_filename%%.*}.csv" 1254c3dc7fb5SKarol Latecki cat <<- EOF > "$fio_log_dir/$fio_csv_filename" 1255c3dc7fb5SKarol Latecki iops,bw,avg_lat,min_lat,max_lat 1256c3dc7fb5SKarol Latecki ${results["iops"]},${results["bw"]},${results["avg_lat"]},${results["min_lat"]},${results["max_lat"]} 1257c3dc7fb5SKarol Latecki EOF 1258c3dc7fb5SKarol Latecki} 1259c3dc7fb5SKarol Latecki 12603d11b2feSBen Walker# Shutdown or kill any running VM and SPDK APP. 12613d11b2feSBen Walker# 1262844c8ec3SMichal Bergerfunction at_app_exit() { 1263fa563858SBen Walker local vhost_name 12643d11b2feSBen Walker 12653d11b2feSBen Walker notice "APP EXITING" 12663d11b2feSBen Walker notice "killing all VMs" 12673d11b2feSBen Walker vm_kill_all 12683d11b2feSBen Walker # Kill vhost application 12693d11b2feSBen Walker notice "killing vhost app" 12703d11b2feSBen Walker 127119e48a66SMaciej Wawryk for vhost_name in "$TARGET_DIR"/*; do 1272feb68300SMichal Berger vhost_kill "$(basename "$vhost_name")" 12733d11b2feSBen Walker done 12743d11b2feSBen Walker 12753d11b2feSBen Walker notice "EXIT DONE" 12763d11b2feSBen Walker} 12773d11b2feSBen Walker 1278844c8ec3SMichal Bergerfunction error_exit() { 12793d11b2feSBen Walker trap - ERR 12803d11b2feSBen Walker print_backtrace 12813d11b2feSBen Walker set +e 12823d11b2feSBen Walker error "Error on $1 $2" 12833d11b2feSBen Walker 12843d11b2feSBen Walker at_app_exit 12853d11b2feSBen Walker exit 1 12863d11b2feSBen Walker} 12877c764edfSMichal Berger 12887c764edfSMichal Bergerfunction lookup_dev_irqs() { 12897c764edfSMichal Berger local vm=$1 irqs=() cpus=() 12907c764edfSMichal Berger local script_get_irqs script_get_cpus 12917c764edfSMichal Berger 12927c764edfSMichal Berger mkdir -p "$VHOST_DIR/irqs" 12937c764edfSMichal Berger 12947c764edfSMichal Berger # All vhost tests depend either on virtio_blk or virtio_scsi drivers on the VM side. 12957c764edfSMichal Berger # Considering that, simply iterate over virtio bus and pick pci device corresponding 12967c764edfSMichal Berger # to each virtio device. 12977c764edfSMichal Berger # For vfio-user setup, look for bare nvme devices. 12987c764edfSMichal Berger 12997c764edfSMichal Berger script_get_irqs=$( 13007c764edfSMichal Berger cat <<- 'SCRIPT' 13017c764edfSMichal Berger shopt -s nullglob 13027c764edfSMichal Berger for virtio in /sys/bus/virtio/devices/virtio*; do 13037c764edfSMichal Berger irqs+=("$(readlink -f "$virtio")/../msi_irqs/"*) 13047c764edfSMichal Berger done 13057c764edfSMichal Berger irqs+=(/sys/class/nvme/nvme*/device/msi_irqs/*) 13067c764edfSMichal Berger printf '%u\n' "${irqs[@]##*/}" 13077c764edfSMichal Berger SCRIPT 13087c764edfSMichal Berger ) 13097c764edfSMichal Berger 13107c764edfSMichal Berger script_get_cpus=$( 13117c764edfSMichal Berger cat <<- 'SCRIPT' 13127c764edfSMichal Berger cpus=(/sys/devices/system/cpu/cpu[0-9]*) 13137c764edfSMichal Berger printf '%u\n' "${cpus[@]##*cpu}" 13147c764edfSMichal Berger SCRIPT 13157c764edfSMichal Berger ) 13167c764edfSMichal Berger 13177c764edfSMichal Berger irqs=($(vm_exec "$vm" "$script_get_irqs")) 13187c764edfSMichal Berger cpus=($(vm_exec "$vm" "$script_get_cpus")) 13197c764edfSMichal Berger ((${#irqs[@]} > 0 && ${#cpus[@]} > 0)) 13207c764edfSMichal Berger 13217c764edfSMichal Berger printf '%u\n' "${irqs[@]}" > "$VHOST_DIR/irqs/$vm.irqs" 13227c764edfSMichal Berger printf '%u\n' "${cpus[@]}" > "$VHOST_DIR/irqs/$vm.cpus" 13237c764edfSMichal Berger} 13247c764edfSMichal Berger 13257c764edfSMichal Bergerfunction irqs() { 13267c764edfSMichal Berger local vm 13277c764edfSMichal Berger for vm; do 13287c764edfSMichal Berger vm_exec "$vm" "while :; do cat /proc/interrupts; sleep 1s; done" > "$VHOST_DIR/irqs/$vm.interrupts" & 13297c764edfSMichal Berger irqs_pids+=($!) 13307c764edfSMichal Berger done 13317c764edfSMichal Berger} 13327c764edfSMichal Berger 13337c764edfSMichal Bergerfunction parse_irqs() { 13347c764edfSMichal Berger local iter=${1:-1} 13357c764edfSMichal Berger "$rootdir/test/vhost/parse_irqs.sh" "$VHOST_DIR/irqs/"*.interrupts 13367c764edfSMichal Berger rm "$VHOST_DIR/irqs/"*.interrupts 13377c764edfSMichal Berger 13387c764edfSMichal Berger mkdir -p "$VHOST_DIR/irqs/$iter" 13397c764edfSMichal Berger mv "$VHOST_DIR/irqs/"*.parsed "$VHOST_DIR/irqs/$iter/" 13407c764edfSMichal Berger} 1341c1d2bdfeSMichal Berger 1342c1d2bdfeSMichal Bergerfunction collect_perf() { 1343c1d2bdfeSMichal Berger local cpus=$1 outf=$2 runtime=$3 delay=$4 1344c1d2bdfeSMichal Berger 1345c1d2bdfeSMichal Berger mkdir -p "$VHOST_DIR/perf" 1346c1d2bdfeSMichal Berger 1347c1d2bdfeSMichal Berger perf record -g \ 1348c1d2bdfeSMichal Berger ${cpus:+-C "$cpus"} \ 1349c1d2bdfeSMichal Berger ${outf:+-o "$outf"} \ 1350c1d2bdfeSMichal Berger ${delay:+-D $((delay * 1000))} \ 1351c1d2bdfeSMichal Berger -z \ 1352c1d2bdfeSMichal Berger ${runtime:+ -- sleep $((runtime + delay))} 1353c1d2bdfeSMichal Berger} 1354c1d2bdfeSMichal Berger 1355c1d2bdfeSMichal Bergerfunction parse_perf() { 1356c1d2bdfeSMichal Berger local iter=${1:-1} 1357c1d2bdfeSMichal Berger local report out 1358c1d2bdfeSMichal Berger 1359c1d2bdfeSMichal Berger mkdir -p "$VHOST_DIR/perf/$iter" 1360c1d2bdfeSMichal Berger shift 1361c1d2bdfeSMichal Berger 1362c1d2bdfeSMichal Berger for report in "$@" "$VHOST_DIR/perf/"*.perf; do 1363c1d2bdfeSMichal Berger [[ -f $report ]] || continue 1364c1d2bdfeSMichal Berger perf report \ 1365c1d2bdfeSMichal Berger -n \ 1366c1d2bdfeSMichal Berger -i "$report" \ 1367c1d2bdfeSMichal Berger --header \ 1368c1d2bdfeSMichal Berger --stdio > "$VHOST_DIR/perf/$iter/${report##*/}.parsed" 1369c1d2bdfeSMichal Berger cp "$report" "$VHOST_DIR/perf/$iter/" 1370c1d2bdfeSMichal Berger done 1371c1d2bdfeSMichal Berger rm "$VHOST_DIR/perf/"*.perf 1372c1d2bdfeSMichal Berger} 1373c1d2bdfeSMichal Berger 1374c1d2bdfeSMichal Bergerfunction get_from_fio() { 1375c1d2bdfeSMichal Berger local opt=$1 conf=$2 1376c1d2bdfeSMichal Berger 1377c1d2bdfeSMichal Berger [[ -n $opt && -f $conf ]] || return 1 1378c1d2bdfeSMichal Berger 1379c1d2bdfeSMichal Berger awk -F= "/^$opt/{print \$2}" "$conf" 1380c1d2bdfeSMichal Berger} 1381905c4dcfSMichal Berger 1382905c4dcfSMichal Bergerfunction get_free_tcp_port() { 1383905c4dcfSMichal Berger local port=$1 to=${2:-1} sockets=() 1384905c4dcfSMichal Berger 1385905c4dcfSMichal Berger mapfile -t sockets < /proc/net/tcp 1386905c4dcfSMichal Berger 1387905c4dcfSMichal Berger # If there's a TCP socket in a listening state keep incrementing $port until 1388905c4dcfSMichal Berger # we find one that's not used. $to determines how long should we look for: 1389905c4dcfSMichal Berger # 0: don't increment, just check if given $port is in use 1390905c4dcfSMichal Berger # >0: increment $to times 1391905c4dcfSMichal Berger # <0: no increment limit 1392905c4dcfSMichal Berger 1393905c4dcfSMichal Berger while [[ ${sockets[*]} == *":$(printf '%04X' "$port") 00000000:0000 0A"* ]]; do 1394905c4dcfSMichal Berger ((to-- && ++port <= 65535)) || return 1 1395905c4dcfSMichal Berger done 1396905c4dcfSMichal Berger 1397905c4dcfSMichal Berger echo "$port" 1398905c4dcfSMichal Berger} 13999463523bSMichal Berger 1400b86184c5SMichal Bergerfunction gen_cpu_vm_spdk_config() ( 1401b86184c5SMichal Berger local vm_count=$1 vm_cpu_num=$2 vm 1402b86184c5SMichal Berger local spdk_cpu_num=${3:-1} spdk_cpu_list=${4:-} spdk_cpus 1403b86184c5SMichal Berger local nodes=("${@:5}") node 1404b86184c5SMichal Berger local env 1405b86184c5SMichal Berger 1406b86184c5SMichal Berger spdk_cpus=spdk_cpu_num 1407b86184c5SMichal Berger [[ -n $spdk_cpu_list ]] && spdk_cpus=spdk_cpu_list 1408b86184c5SMichal Berger 1409b86184c5SMichal Berger if ((${#nodes[@]} > 0)); then 1410b86184c5SMichal Berger ((${#nodes[@]} == 1)) && node=${nodes[0]} 1411b86184c5SMichal Berger for ((vm = 0; vm < vm_count; vm++)); do 1412b86184c5SMichal Berger env+=("VM${vm}_NODE=${nodes[vm]:-$node}") 1413b86184c5SMichal Berger done 1414b86184c5SMichal Berger fi 1415b86184c5SMichal Berger 1416b86184c5SMichal Berger env+=("$spdk_cpus=${!spdk_cpus}") 1417b86184c5SMichal Berger env+=("vm_count=$vm_count") 1418b86184c5SMichal Berger env+=("vm_cpu_num=$vm_cpu_num") 1419b86184c5SMichal Berger 1420b86184c5SMichal Berger export "${env[@]}" 1421b86184c5SMichal Berger 1422b86184c5SMichal Berger "$rootdir/scripts/perf/vhost/conf-generator" -p cpu 1423b86184c5SMichal Berger) 1424