xref: /kvm-unit-tests/scripts/vmm.bash (revision 34940cc963b097f2bba35a9aea1727941dde0b84)
1# The following parameters are enabled by default when running a test with
2# kvmtool:
3# --nodefaults: suppress VM configuration that cannot be disabled (like
4#               modifying the supplied kernel command line). Otherwise tests
5#               that use the command line will fail without this parameter.
6# --network mode=none: do not create a network device. kvmtool tries to help the
7#               user by automatically create one, and then prints a warning
8#               when the VM terminates if the device hasn't been initialized.
9# --loglevel=warning: reduce verbosity
10: "${KVMTOOL_DEFAULT_OPTS:="--nodefaults --network mode=none --loglevel=warning"}"
11
12##############################################################################
13# qemu_fixup_return_code translates the ambiguous exit status in Table1 to that
14# in Table2.  Table3 simply documents the complete status table.
15#
16# Table1: Before fixup
17# --------------------
18# 0      - Unexpected exit from QEMU (possible signal), or the unittest did
19#          not use debug-exit
20# 1      - most likely unittest succeeded, or QEMU failed
21#
22# Table2: After fixup
23# -------------------
24# 0      - Everything succeeded
25# 1      - most likely QEMU failed
26#
27# Table3: Complete table
28# ----------------------
29# 0      - SUCCESS
30# 1      - most likely QEMU failed
31# 2      - most likely a run script failed
32# 3      - most likely the unittest failed
33# 124    - most likely the unittest timed out
34# 127    - most likely the unittest called abort()
35# 1..127 - FAILURE (could be QEMU, a run script, or the unittest)
36# >= 128 - Signal (signum = status - 128)
37##############################################################################
38function qemu_fixup_return_code()
39{
40	local ret=$1
41	# Remove $ret from the list of arguments
42	shift 1
43	local errors=$*
44	local sig
45
46	[ $ret -eq 134 ] && echo "QEMU Aborted" >&2
47
48	if [ "$errors" ]; then
49		sig=$(grep 'terminating on signal' <<<"$errors")
50		if [ "$sig" ]; then
51			# This is too complex for ${var/search/replace}
52			# shellcheck disable=SC2001
53			sig=$(sed 's/.*terminating on signal \([0-9][0-9]*\).*/\1/' <<<"$sig")
54		fi
55	fi
56
57	if [ $ret -eq 0 ]; then
58		# Some signals result in a zero return status, but the
59		# error log tells the truth.
60		if [ "$sig" ]; then
61			((ret=sig+128))
62		else
63			# Exiting with zero (non-debugexit) is an error
64			ret=1
65		fi
66	elif [ $ret -eq 1 ]; then
67		# Even when ret==1 (unittest success) if we also got stderr
68		# logs, then we assume a QEMU failure. Otherwise we translate
69		# status of 1 to 0 (SUCCESS)
70	        if [ "$errors" ]; then
71			if ! grep -qvi warning <<<"$errors" ; then
72				ret=0
73			fi
74		else
75			ret=0
76		fi
77	fi
78
79	echo $ret
80}
81
82function qemu_parse_premature_failure()
83{
84	local log=$*
85
86	echo "$log" | grep "_NO_FILE_4Uhere_" |
87		grep -q -e "[Cc]ould not \(load\|open\) kernel" \
88			-e "error loading" \
89			-e "failed to load" &&
90		return 1
91	return 0
92}
93
94function kvmtool_fixup_return_code()
95{
96	local ret=$1
97
98	# Force run_test_status() to interpret the STATUS line.
99	if [ $ret -eq 0 ]; then
100		ret=1
101	fi
102
103	echo $ret
104}
105
106function kvmtool_parse_premature_failure()
107{
108	local log=$*
109
110	echo "$log" | grep "Fatal: Unable to open kernel _NO_FILE_4Uhere_" &&
111		return 1
112	return 0
113}
114
115declare -A vmm_optname=(
116	[qemu,args]='-append'
117	[qemu,default_opts]=''
118	[qemu,fixup_return_code]=qemu_fixup_return_code
119	[qemu,initrd]='-initrd'
120	[qemu,nr_cpus]='-smp'
121	[qemu,parse_premature_failure]=qemu_parse_premature_failure
122
123	[kvmtool,args]='--params'
124	[kvmtool,default_opts]="$KVMTOOL_DEFAULT_OPTS"
125	[kvmtool,fixup_return_code]=kvmtool_fixup_return_code
126	[kvmtool,initrd]='--initrd'
127	[kvmtool,nr_cpus]='--cpus'
128	[kvmtool,parse_premature_failure]=kvmtool_parse_premature_failure
129)
130
131function vmm_optname_args()
132{
133	echo ${vmm_optname[$(vmm_get_target),args]}
134}
135
136function vmm_default_opts()
137{
138	echo ${vmm_optname[$(vmm_get_target),default_opts]}
139}
140
141function vmm_fixup_return_code()
142{
143	${vmm_optname[$(vmm_get_target),fixup_return_code]} "$@"
144}
145
146function vmm_optname_initrd()
147{
148	echo ${vmm_optname[$(vmm_get_target),initrd]}
149}
150
151function vmm_optname_nr_cpus()
152{
153	echo ${vmm_optname[$(vmm_get_target),nr_cpus]}
154}
155
156function vmm_parse_premature_failure()
157{
158	${vmm_optname[$(vmm_get_target),parse_premature_failure]} "$@"
159}
160
161function vmm_get_target()
162{
163	if [[ -z "$TARGET" ]]; then
164		echo "qemu"
165	else
166		echo "$TARGET"
167	fi
168}
169
170function vmm_check_supported()
171{
172	# We're not interested in the return code for vmm_get_target().
173	# shellcheck disable=SC2155
174	local target=$(vmm_get_target)
175
176	case "$target" in
177	qemu)
178		return 0
179		;;
180	*)
181		echo "$0 does not support target '$target'"
182		exit 2
183		;;
184	esac
185}
186
187function vmm_unittest_params_name()
188{
189	# shellcheck disable=SC2155
190	local target=$(vmm_get_target)
191
192	case "$target" in
193	qemu)
194		echo "extra_params|qemu_params"
195		;;
196	kvmtool)
197		echo "kvmtool_params"
198		;;
199	*)
200		echo "$0 does not support '$target'"
201		exit 2
202		;;
203	esac
204}
205