99import shlex
1010import shutil
1111import subprocess
12+ import sys
1213
1314import utils
1415
@@ -22,6 +23,7 @@ def __init__(self):
2223
2324 # Properties that can be adjusted by the user or class
2425 self .cmdline = []
26+ self .interactive = False
2527 self .kernel = None
2628 self .kernel_dir = None
2729 # It may be tempting to use self.use_kvm during initialization of
@@ -30,6 +32,7 @@ def __init__(self):
3032 # be confined to run().
3133 self .use_kvm = self ._can_use_kvm ()
3234 self .smp = 0
35+ self .timeout = ''
3336
3437 self ._default_kernel_path = None
3538 self ._initrd_arch = None
@@ -140,6 +143,8 @@ def run(self):
140143 )
141144
142145 # Kernel options
146+ if self .interactive :
147+ self .cmdline .append ('rdinit=/bin/sh' )
143148 if self .cmdline :
144149 self ._qemu_args += ['-append' , ' ' .join (self .cmdline )]
145150 self ._qemu_args += ['-kernel' , self .kernel ]
@@ -161,9 +166,26 @@ def run(self):
161166 utils .green (f"QEMU version: \033 [0m{ self ._get_qemu_ver_string ()} " )
162167
163168 # Pretty print and run QEMU command
164- qemu_cmd = [qemu_path , * self ._qemu_args ]
169+ qemu_cmd = []
170+
171+ if not self .interactive :
172+ utils .check_cmd ('timeout' )
173+ qemu_cmd += ['timeout' , '--foreground' , self .timeout ]
174+
175+ utils .check_cmd ('stdbuf' )
176+ qemu_cmd += ['stdbuf' , '-eL' , '-oL' ]
177+
178+ qemu_cmd += [qemu_path , * self ._qemu_args ]
179+
165180 print (f"$ { ' ' .join (shlex .quote (str (elem )) for elem in qemu_cmd )} " )
166- subprocess .run (qemu_cmd , check = True )
181+ try :
182+ subprocess .run (qemu_cmd , check = True )
183+ except subprocess .CalledProcessError as err :
184+ if err .returncode == 124 :
185+ utils .red ("ERROR: QEMU timed out!" )
186+ else :
187+ utils .red ("ERROR: QEMU did not exit cleanly!" )
188+ sys .exit (err .returncode )
167189
168190
169191class X86QEMURunner (QEMURunner ):
@@ -220,6 +242,16 @@ def parse_arguments():
220242 '--no-kvm' ,
221243 action = 'store_true' ,
222244 help = 'Do not use KVM for accelration even when supported.' )
245+ parser .add_argument (
246+ '-i' ,
247+ '--interactive' ,
248+ '--shell' ,
249+ action = 'store_true' ,
250+ help = 'Instead of immediately shutting down machine, spawn a shell.' )
251+ parser .add_argument ('-t' ,
252+ '--timeout' ,
253+ default = '3m' ,
254+ help = "Value to pass to 'timeout' (default: '3m')" )
223255
224256 return parser .parse_args ()
225257
@@ -244,4 +276,7 @@ def parse_arguments():
244276 if args .no_kvm :
245277 runner .use_kvm = False
246278
279+ runner .interactive = args .interactive
280+ runner .timeout = args .timeout
281+
247282 runner .run ()
0 commit comments