@@ -180,6 +180,136 @@ def name(self):
180180 def image_name (self ):
181181 abstract ()
182182
183+ def start_process (self , cmdlist ):
184+
185+ if cmdlist [0 ] == "sudo" : # and have_sudo():
186+ print color .WARNING ("Running with sudo" )
187+ self ._sudo = True
188+
189+ # Start a subprocess
190+ self ._proc = subprocess .Popen (cmdlist ,
191+ stdout = subprocess .PIPE ,
192+ stderr = subprocess .PIPE ,
193+ stdin = subprocess .PIPE )
194+
195+ return self ._proc
196+
197+
198+ # Ukvm Hypervisor interface
199+ class ukvm (hypervisor ):
200+
201+ def __init__ (self , config ):
202+ # config is not yet used for ukvm
203+ super (ukvm , self ).__init__ (config )
204+ self ._proc = None
205+ self ._stopped = False
206+ self ._sudo = False
207+ self ._image_name = self ._config if "image" in self ._config else self .name () + " vm"
208+
209+ # Pretty printing
210+ self .info = Logger (color .INFO ("<" + type (self ).__name__ + ">" ))
211+
212+ def name (self ):
213+ return "Ukvm"
214+
215+ def image_name (self ):
216+ return self ._image_name
217+
218+ def drive_arg (self ):
219+ return ["--disk=" + INCLUDEOS_HOME + "dummy.disk" ]
220+
221+ def net_arg (self ):
222+ return ["--net=tap100" ]
223+
224+ def get_final_output (self ):
225+ return self ._proc .communicate ()
226+
227+ def boot (self , multiboot , kernel_args = "" , image_name = None ):
228+ self ._stopped = False
229+
230+ qkvm_bin = INCLUDEOS_HOME + "/includeos/x86_64/lib/ukvm-bin"
231+
232+ # Use provided image name if set, otherwise raise an execption
233+ if not image_name :
234+ raise Exception ("No image name provided as param" )
235+
236+ self ._image_name = image_name
237+
238+ command = ["sudo" , qkvm_bin ]
239+ command += self .drive_arg ()
240+ command += self .net_arg ()
241+ command += [self ._image_name ]
242+
243+ try :
244+ self .start_process (command )
245+ self .info ("Started process PID " ,self ._proc .pid )
246+ except Exception as e :
247+ raise e
248+
249+ def stop (self ):
250+
251+ signal = "-SIGTERM"
252+
253+ # Don't try to kill twice
254+ if self ._stopped :
255+ self .wait ()
256+ return self
257+ else :
258+ self ._stopped = True
259+
260+ if self ._proc and self ._proc .poll () == None :
261+
262+ if not self ._sudo :
263+ info ("Stopping child process (no sudo required)" )
264+ self ._proc .terminate ()
265+ else :
266+ # Find and terminate all child processes, since parent is "sudo"
267+ parent = psutil .Process (self ._proc .pid )
268+ children = parent .children ()
269+
270+ info ("Stopping" , self ._image_name , "PID" ,self ._proc .pid , "with" , signal )
271+
272+ for child in children :
273+ info (" + child process " , child .pid )
274+
275+ # The process might have gotten an exit status by now so check again to avoid negative exit
276+ if (not self ._proc .poll ()):
277+ subprocess .call (["sudo" , "kill" , signal , str (child .pid )])
278+
279+ # Wait for termination (avoids the need to reset the terminal etc.)
280+ self .wait ()
281+
282+ return self
283+
284+ def wait (self ):
285+ if (self ._proc ): self ._proc .wait ()
286+ return self
287+
288+ def read_until_EOT (self ):
289+ chars = ""
290+
291+ while (not self ._proc .poll ()):
292+ char = self ._proc .stdout .read (1 )
293+ if char == chr (4 ):
294+ return chars
295+ chars += char
296+
297+ return chars
298+
299+
300+ def readline (self ):
301+ if self ._proc .poll ():
302+ raise Exception ("Process completed" )
303+ return self ._proc .stdout .readline ()
304+
305+
306+ def writeline (self , line ):
307+ if self ._proc .poll ():
308+ raise Exception ("Process completed" )
309+ return self ._proc .stdin .write (line + "\n " )
310+
311+ def poll (self ):
312+ return self ._proc .poll ()
183313
184314# Qemu Hypervisor interface
185315class qemu (hypervisor ):
@@ -259,21 +389,6 @@ def kvm_present(self):
259389 # Note: if the command failed, we can't know until we have exit status,
260390 # but we can't wait since we expect no exit. Checking for program start error
261391 # is therefore deferred to the callee
262- def start_process (self , cmdlist ):
263-
264- if cmdlist [0 ] == "sudo" : # and have_sudo():
265- print color .WARNING ("Running with sudo" )
266- self ._sudo = True
267-
268- # Start a subprocess
269- self ._proc = subprocess .Popen (cmdlist ,
270- stdout = subprocess .PIPE ,
271- stderr = subprocess .PIPE ,
272- stdin = subprocess .PIPE )
273- self .info ("Started process PID " ,self ._proc .pid )
274-
275- return self ._proc
276-
277392
278393 def get_final_output (self ):
279394 return self ._proc .communicate ()
@@ -414,6 +529,7 @@ def boot(self, multiboot, debug = False, kernel_args = "", image_name = None):
414529
415530 try :
416531 self .start_process (command )
532+ self .info ("Started process PID " ,self ._proc .pid )
417533 except Exception as e :
418534 print self .INFO ,"Starting subprocess threw exception:" , e
419535 raise e
@@ -486,7 +602,7 @@ def poll(self):
486602# VM class
487603class vm :
488604
489- def __init__ (self , config = None , hyper = qemu ):
605+ def __init__ (self , config = None , hyper_name = " qemu" ):
490606
491607 self ._exit_status = None
492608 self ._exit_msg = ""
@@ -500,6 +616,11 @@ def __init__(self, config = None, hyper = qemu):
500616 panic_signature : self ._on_panic ,
501617 "SUCCESS" : self ._on_success }
502618
619+ if hyper_name == "ukvm" :
620+ hyper = ukvm
621+ else :
622+ hyper = qemu
623+
503624 # Initialize hypervisor with config
504625 assert (issubclass (hyper , hypervisor ))
505626 self ._hyper = hyper (self ._config )
0 commit comments