2020import  re 
2121import  traceback 
2222import  signal 
23+ import  tempfile 
2324from  enum  import  Enum 
2425import  platform 
2526import  psutil 
@@ -184,8 +185,9 @@ def __init__(self, config):
184185        self ._config  =  config 
185186        self ._allow_sudo  =  False  # must be explicitly turned on at boot. 
186187        self ._enable_kvm  =  False  # must be explicitly turned on at boot. 
187-         self ._sudo  =  False  # Set to true if sudo is available 
188-         self ._proc  =  None  # A running subprocess 
188+         self ._sudo  =  False        # Set to true if sudo is available 
189+         self ._proc  =  None         # A running subprocess 
190+         self ._tmp_dirs  =  []      # A list of tmp dirs created using tempfile module. Used for socket creation for automatic cleanup and garbage collection 
189191
190192    # pylint: disable-next=unused-argument 
191193    def  boot_in_hypervisor (self , multiboot = False , debug = False , kernel_args = "" , image_name = "" , allow_sudo  =  False , enable_kvm  =  False ):
@@ -418,6 +420,7 @@ class qemu(hypervisor):
418420    def  __init__ (self , config ):
419421        super ().__init__ (config )
420422        self ._proc  =  None 
423+         self ._virtiofsd_proc  =  None 
421424        self ._stopped  =  False 
422425        self ._sudo  =  False 
423426        self ._image_name  =  self ._config  if  "image"  in  self ._config  else  self .name () +  " vm" 
@@ -516,6 +519,41 @@ def net_arg(self, backend, device, if_name = "net0", mac = None, bridge = None,
516519        return  ["-device" , device ,
517520                "-netdev" , netdev ]
518521
522+     def  init_virtiocon (self , path ):
523+         """ creates a console device and redirects to the path given """ 
524+         qemu_args  =  ["-device" , "virtio-serial-pci,disable-legacy=on,id=virtio-serial0" ]
525+         qemu_args  +=  ["-device" , "virtserialport,chardev=virtiocon0" ]
526+         qemu_args  +=  ["-chardev" , f"file,id=virtiocon0,path={ path }  ]
527+ 
528+         return  qemu_args 
529+ 
530+     def  init_virtiofs (self , socket , shared , mem ):
531+         """ initializes virtiofs by launching virtiofsd and creating a virtiofs device """ 
532+         virtiofsd_args  =  ["virtiofsd" , "--socket" , socket , "--shared-dir" , shared , "--sandbox" , "none" ]
533+         self ._virtiofsd_proc  =  subprocess .Popen (virtiofsd_args , stdout = subprocess .DEVNULL , stderr = subprocess .DEVNULL ) # pylint: disable=consider-using-with 
534+ 
535+         if  self ._virtiofsd_proc .poll ():
536+             raise  Exception ("VirtioFSD failed to start" )
537+ 
538+         info ("Successfully started VirtioFSD!" )
539+ 
540+         while  not  os .path .exists (socket ):
541+             ...
542+ 
543+         qemu_args  =  ["-machine" , "memory-backend=mem0" ]
544+         qemu_args  +=  ["-chardev" , f"socket,id=virtiofsd0,path={ socket }  ]
545+         qemu_args  +=  ["-device" , "vhost-user-fs-pci,chardev=virtiofsd0,tag=vfs" ]
546+         qemu_args  +=  ["-object" , f"memory-backend-memfd,id=mem0,size={ mem }  ]
547+ 
548+         return  qemu_args 
549+ 
550+     def  init_pmem (self , path , size , pmem_id ):
551+         """ creates a pmem device with image path as memory mapped backend """ 
552+         qemu_args  =  ["-object" , f"memory-backend-file,id=pmemdev{ pmem_id } { path } { size }  ]
553+         qemu_args  +=  ["-device" , f"virtio-pmem-pci,memdev=pmemdev{ pmem_id }  ]
554+ 
555+         return  qemu_args 
556+ 
519557    def  kvm_present (self ):
520558        """ returns true if KVM is present and available """ 
521559        if  not  self ._enable_kvm :
@@ -660,7 +698,7 @@ def boot_in_hypervisor(self, multiboot=True, debug = False, kernel_args = "", im
660698
661699        mem_arg  =  []
662700        if  "mem"  in  self ._config :
663-             mem_arg  =  ["-m" , str ( self ._config ["mem" ]) ]
701+             mem_arg  =  ["-m" , f"size= { self ._config ["mem" ]} ,maxmem=1000G" 
664702
665703        vga_arg  =  ["-nographic"  ]
666704        if  "vga"  in  self ._config :
@@ -674,6 +712,27 @@ def boot_in_hypervisor(self, multiboot=True, debug = False, kernel_args = "", im
674712        if  "vfio"  in  self ._config :
675713            pci_arg  =  ["-device" , "vfio-pci,host="  +  self ._config ["vfio" ]]
676714
715+         virtiocon_args  =  []
716+         if  "virtiocon"  in  self ._config :
717+             virtiocon_args  =  self .init_virtiocon (self ._config ["virtiocon" ]["path" ])
718+ 
719+         virtiofs_args  =  []
720+         if  "virtiofs"  in  self ._config :
721+             tmp_virtiofs_dir  =  tempfile .TemporaryDirectory (prefix = "virtiofs-" ) # pylint: disable=consider-using-with 
722+             self ._tmp_dirs .append (tmp_virtiofs_dir )
723+             socket_path  =  os .path .join (tmp_virtiofs_dir .name , "virtiofsd.sock" )
724+ 
725+             shared  =  self ._config ["virtiofs" ]["shared" ]
726+ 
727+             virtiofs_args  =  self .init_virtiofs (socket_path , shared , self ._config ["mem" ])
728+ 
729+         virtiopmem_args  =  []
730+         if  "virtiopmem"  in  self ._config :
731+             for  pmem_id , virtiopmem  in  enumerate (self ._config ["virtiopmem" ]):
732+                 image  =  virtiopmem ["image" ]
733+                 size  =  virtiopmem ["size" ]
734+                 virtiopmem_args  +=  self .init_pmem (image , size , pmem_id )
735+ 
677736        # custom qemu binary/location 
678737        qemu_binary  =  "qemu-system-x86_64" 
679738        if  "qemu"  in  self ._config :
@@ -703,7 +762,8 @@ def boot_in_hypervisor(self, multiboot=True, debug = False, kernel_args = "", im
703762
704763        command  +=  kernel_args 
705764        command  +=  disk_args  +  debug_args  +  net_args  +  mem_arg  +  mod_args 
706-         command  +=  vga_arg  +  trace_arg  +  pci_arg 
765+         command  +=  vga_arg  +  trace_arg  +  pci_arg  +  virtiocon_args  +  virtiofs_args 
766+         command  +=  virtiopmem_args 
707767
708768        #command_str = " ".join(command) 
709769        #command_str.encode('ascii','ignore') 
0 commit comments