blob: 5c10828e30f9d68e2fb089593e16a9474d15d37d [file] [log] [blame]
##############################################################################
# run_qemu translates the ambiguous exit status in Table1 to that in Table2.
# Table3 simply documents the complete status table.
#
# Table1: Before fixup
# --------------------
# 0 - Unexpected exit from QEMU (possible signal), or the unittest did
# not use debug-exit
# 1 - most likely unittest succeeded, or QEMU failed
#
# Table2: After fixup
# -------------------
# 0 - Everything succeeded
# 1 - most likely QEMU failed
#
# Table3: Complete table
# ----------------------
# 0 - SUCCESS
# 1 - most likely QEMU failed
# 2 - most likely a run script failed
# 3 - most likely the unittest failed
# 124 - most likely the unittest timed out
# 127 - most likely the unittest called abort()
# 1..127 - FAILURE (could be QEMU, a run script, or the unittest)
# >= 128 - Signal (signum = status - 128)
##############################################################################
run_qemu ()
{
local stdout errors ret sig
# stdout to {stdout}, stderr to $errors and stderr
exec {stdout}>&1
errors=$("${@}" </dev/null 2> >(tee /dev/stderr) > /dev/fd/$stdout)
ret=$?
exec {stdout}>&-
[ $ret -eq 134 ] && echo "QEMU Aborted" >&2
if [ "$errors" ]; then
sig=$(grep 'terminating on signal' <<<"$errors")
if [ "$sig" ]; then
sig=$(sed 's/.*terminating on signal \([0-9][0-9]*\).*/\1/' <<<"$sig")
fi
fi
if [ $ret -eq 0 ]; then
# Some signals result in a zero return status, but the
# error log tells the truth.
if [ "$sig" ]; then
((ret=sig+128))
else
# Exiting with zero (non-debugexit) is an error
ret=1
fi
elif [ $ret -eq 1 ]; then
# Even when ret==1 (unittest success) if we also got stderr
# logs, then we assume a QEMU failure. Otherwise we translate
# status of 1 to 0 (SUCCESS)
if [ -z "$(echo "$errors" | grep -vi warning)" ]; then
ret=0
fi
fi
return $ret
}
timeout_cmd ()
{
if [ "$TIMEOUT" ] && [ "$TIMEOUT" != "0" ]; then
echo "timeout -k 1s --foreground $TIMEOUT"
fi
}
qmp ()
{
echo '{ "execute": "qmp_capabilities" }{ "execute":' "$2" '}' | nc -U $1
}
run_migration ()
{
if ! command -v nc >/dev/null 2>&1; then
echo "$FUNCNAME needs nc (netcat)" >&2
exit 2
fi
qemu=$1
shift
migsock=`mktemp -u -t mig-helper-socket.XXXXXXXXXX`
migout1=`mktemp -t mig-helper-stdout1.XXXXXXXXXX`
qmp1=`mktemp -u -t mig-helper-qmp1.XXXXXXXXXX`
qmp2=`mktemp -u -t mig-helper-qmp2.XXXXXXXXXX`
qmpout1=/dev/null
qmpout2=/dev/null
trap 'rm -f ${migout1} ${migsock} ${qmp1} ${qmp2}' EXIT
$qemu "$@" -chardev socket,id=mon1,path=${qmp1},server,nowait \
-mon chardev=mon1,mode=control | tee ${migout1} &
$qemu "$@" -chardev socket,id=mon2,path=${qmp2},server,nowait \
-mon chardev=mon2,mode=control -incoming unix:${migsock} &
# The test must prompt the user to migrate, so wait for the "migrate" keyword
while ! grep -q -i "migrate" < ${migout1} ; do
sleep 1
done
qmp ${qmp1} '"migrate", "arguments": { "uri": "unix:'${migsock}'" }' > ${qmpout1}
# Wait for the migration to complete
migstatus=`qmp ${qmp1} '"query-migrate"' | grep return`
while ! grep -q '"completed"' <<<"$migstatus" ; do
sleep 1
migstatus=`qmp ${qmp1} '"query-migrate"' | grep return`
if grep -q '"failed"' <<<"$migstatus" ; then
echo "ERROR: Migration failed." >&2
qmp ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null
qmp ${qmp2} '"quit"'> ${qmpout2} 2>/dev/null
exit 2
fi
done
qmp ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null
qmp ${qmp2} '"inject-nmi"'> ${qmpout2}
wait
}
migration_cmd ()
{
if [ "$MIGRATION" = "yes" ]; then
echo "run_migration"
fi
}
search_qemu_binary ()
{
local save_path=$PATH
local qemucmd qemu
export PATH=$PATH:/usr/libexec
for qemucmd in ${QEMU:-qemu-system-$ARCH_NAME qemu-kvm}; do
if $qemucmd --help 2>/dev/null | grep -q 'QEMU'; then
qemu="$qemucmd"
break
fi
done
if [ -z "$qemu" ]; then
echo "A QEMU binary was not found."
echo "You can set a custom location by using the QEMU=<path> environment variable."
exit 2
fi
command -v $qemu
export PATH=$save_path
}