1############################################################################## 2# run_qemu translates the ambiguous exit status in Table1 to that in Table2. 3# Table3 simply documents the complete status table. 4# 5# Table1: Before fixup 6# -------------------- 7# 0 - Unexpected exit from QEMU (possible signal), or the unittest did 8# not use debug-exit 9# 1 - most likely unittest succeeded, or QEMU failed 10# 11# Table2: After fixup 12# ------------------- 13# 0 - Everything succeeded 14# 1 - most likely QEMU failed 15# 16# Table3: Complete table 17# ---------------------- 18# 0 - SUCCESS 19# 1 - most likely QEMU failed 20# 2 - most likely a run script failed 21# 3 - most likely the unittest failed 22# 124 - most likely the unittest timed out 23# 127 - most likely the unittest called abort() 24# 1..127 - FAILURE (could be QEMU, a run script, or the unittest) 25# >= 128 - Signal (signum = status - 128) 26############################################################################## 27run_qemu () 28{ 29 local stdout errors ret sig 30 31 # stdout to {stdout}, stderr to $errors and stderr 32 exec {stdout}>&1 33 errors=$("${@}" </dev/null 2> >(tee /dev/stderr) > /dev/fd/$stdout) 34 ret=$? 35 exec {stdout}>&- 36 37 [ $ret -eq 134 ] && echo "QEMU Aborted" >&2 38 39 if [ "$errors" ]; then 40 sig=$(grep 'terminating on signal' <<<"$errors") 41 if [ "$sig" ]; then 42 sig=$(sed 's/.*terminating on signal \([0-9][0-9]*\).*/\1/' <<<"$sig") 43 fi 44 fi 45 46 if [ $ret -eq 0 ]; then 47 # Some signals result in a zero return status, but the 48 # error log tells the truth. 49 if [ "$sig" ]; then 50 ((ret=sig+128)) 51 else 52 # Exiting with zero (non-debugexit) is an error 53 ret=1 54 fi 55 elif [ $ret -eq 1 ]; then 56 # Even when ret==1 (unittest success) if we also got stderr 57 # logs, then we assume a QEMU failure. Otherwise we translate 58 # status of 1 to 0 (SUCCESS) 59 if [ -z "$(echo "$errors" | grep -vi warning)" ]; then 60 ret=0 61 fi 62 fi 63 64 return $ret 65} 66 67timeout_cmd () 68{ 69 if [ "$TIMEOUT" ] && [ "$TIMEOUT" != "0" ]; then 70 echo "timeout -k 1s --foreground $TIMEOUT" 71 fi 72} 73 74qmp () 75{ 76 echo '{ "execute": "qmp_capabilities" }{ "execute":' "$2" '}' | nc -U $1 77} 78 79run_migration () 80{ 81 if ! command -v nc >/dev/null 2>&1; then 82 echo "$FUNCNAME needs nc (netcat)" >&2 83 exit 2 84 fi 85 86 qemu=$1 87 shift 88 89 migsock=`mktemp -u -t mig-helper-socket.XXXXXXXXXX` 90 migout1=`mktemp -t mig-helper-stdout1.XXXXXXXXXX` 91 qmp1=`mktemp -u -t mig-helper-qmp1.XXXXXXXXXX` 92 qmp2=`mktemp -u -t mig-helper-qmp2.XXXXXXXXXX` 93 qmpout1=/dev/null 94 qmpout2=/dev/null 95 96 trap 'rm -f ${migout1} ${migsock} ${qmp1} ${qmp2}' EXIT 97 98 $qemu "$@" -chardev socket,id=mon1,path=${qmp1},server,nowait \ 99 -mon chardev=mon1,mode=control | tee ${migout1} & 100 101 $qemu "$@" -chardev socket,id=mon2,path=${qmp2},server,nowait \ 102 -mon chardev=mon2,mode=control -incoming unix:${migsock} & 103 104 # The test must prompt the user to migrate, so wait for the "migrate" keyword 105 while ! grep -q -i "migrate" < ${migout1} ; do 106 sleep 1 107 done 108 109 qmp ${qmp1} '"migrate", "arguments": { "uri": "unix:'${migsock}'" }' > ${qmpout1} 110 111 # Wait for the migration to complete 112 migstatus=`qmp ${qmp1} '"query-migrate"' | grep return` 113 while ! grep -q '"completed"' <<<"$migstatus" ; do 114 sleep 1 115 migstatus=`qmp ${qmp1} '"query-migrate"' | grep return` 116 if grep -q '"failed"' <<<"$migstatus" ; then 117 echo "ERROR: Migration failed." >&2 118 qmp ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null 119 qmp ${qmp2} '"quit"'> ${qmpout2} 2>/dev/null 120 exit 2 121 fi 122 done 123 qmp ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null 124 125 qmp ${qmp2} '"inject-nmi"'> ${qmpout2} 126 127 wait 128} 129 130migration_cmd () 131{ 132 if [ "$MIGRATION" = "yes" ]; then 133 echo "run_migration" 134 fi 135} 136 137search_qemu_binary () 138{ 139 local save_path=$PATH 140 local qemucmd qemu 141 142 export PATH=$PATH:/usr/libexec 143 for qemucmd in ${QEMU:-qemu-system-$ARCH_NAME qemu-kvm}; do 144 if $qemucmd --help 2>/dev/null | grep -q 'QEMU'; then 145 qemu="$qemucmd" 146 break 147 fi 148 done 149 150 if [ -z "$qemu" ]; then 151 echo "A QEMU binary was not found." 152 echo "You can set a custom location by using the QEMU=<path> environment variable." 153 exit 2 154 fi 155 command -v $qemu 156 export PATH=$save_path 157} 158 159initrd_create () 160{ 161 env_add_errata 162 unset INITRD 163 [ -f "$ENV" ] && INITRD="-initrd $ENV" 164} 165 166env_add_errata () 167{ 168 local line errata 169 170 if [ -f "$ENV" ] && grep -q '^ERRATA_' <(env); then 171 for line in $(grep '^ERRATA_' "$ENV"); do 172 errata=${line%%=*} 173 test -v $errata && continue 174 eval export "$line" 175 done 176 elif [ ! -f "$ENV" ]; then 177 env_generate_errata 178 fi 179 180 if grep -q '^ERRATA_' <(env); then 181 export ENV_OLD="$ENV" 182 export ENV=$(mktemp) 183 trap_exit_push 'rm -f $ENV; [ "$ENV_OLD" ] && export ENV="$ENV_OLD" || unset ENV; unset ENV_OLD' 184 [ -f "$ENV_OLD" ] && grep -v '^ERRATA_' "$ENV_OLD" > $ENV 185 grep '^ERRATA_' <(env) >> $ENV 186 fi 187} 188 189env_generate_errata () 190{ 191 local kernel_version_string=$(uname -r) 192 local kernel_version kernel_patchlevel kernel_sublevel 193 local line commit minver errata v p s have 194 195 IFS=. read kernel_version kernel_patchlevel kernel_sublevel <<<$kernel_version_string 196 kernel_sublevel=${kernel_sublevel%%[!0-9]*} 197 198 [ "$ENVIRON_DEFAULT" != "yes" ] && return 199 [ ! -f errata.txt ] && return 200 201 for line in $(grep -v '^#' errata.txt | tr -d '[:blank:]' | cut -d: -f1,2); do 202 commit=${line%:*} 203 minver=${line#*:} 204 205 errata="ERRATA_$commit" 206 test -v $errata && continue 207 208 IFS=. read v p s <<<$minver 209 s=${s%%[!0-9]*} 210 211 if (( $kernel_version > $v || 212 ($kernel_version == $v && $kernel_patchlevel > $p) )); then 213 have=y 214 elif (( $kernel_version == $v && $kernel_patchlevel == $p )); then 215 if [ "$kernel_sublevel" ] && [ "$s" ]; then 216 if (( $kernel_sublevel >= $s )); then 217 have=y 218 else 219 have=n 220 fi 221 elif [ "$s" ] && (( $s != 0 )); then 222 have=n 223 else 224 have=y 225 fi 226 else 227 have=n 228 fi 229 eval export "$errata=$have" 230 done 231} 232 233trap_exit_push () 234{ 235 local old_exit=$(trap -p EXIT | sed "s/^[^']*'//;s/'[^']*$//") 236 trap -- "$1; $old_exit" EXIT 237} 238