-
Notifications
You must be signed in to change notification settings - Fork 12
Orchestration of various Virtio devices (reopened) #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cbd3f8f
9b45ce0
39a0ec2
fab5ab3
f3d06e1
acdfb89
2bc9aea
79eaede
5657b7b
afffb7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ | |
| import re | ||
| import traceback | ||
| import signal | ||
| import tempfile | ||
| from enum import Enum | ||
| import platform | ||
| import psutil | ||
|
|
@@ -184,8 +185,9 @@ def __init__(self, config): | |
| self._config = config | ||
| self._allow_sudo = False # must be explicitly turned on at boot. | ||
| self._enable_kvm = False # must be explicitly turned on at boot. | ||
| self._sudo = False # Set to true if sudo is available | ||
| self._proc = None # A running subprocess | ||
| self._sudo = False # Set to true if sudo is available | ||
| self._proc = None # A running subprocess | ||
| self._tmp_dirs = [] # A list of tmp dirs created using tempfile module. Used for socket creation for automatic cleanup and garbage collection | ||
|
|
||
| # pylint: disable-next=unused-argument | ||
| 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): | |
| def __init__(self, config): | ||
| super().__init__(config) | ||
| self._proc = None | ||
| self._virtiofsd_proc = None | ||
| self._stopped = False | ||
| self._sudo = False | ||
| 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, | |
| return ["-device", device, | ||
| "-netdev", netdev] | ||
|
|
||
| def init_virtiocon(self, path): | ||
| """ creates a console device and redirects to the path given """ | ||
| qemu_args = ["-device", "virtio-serial-pci,disable-legacy=on,id=virtio-serial0"] | ||
| qemu_args += ["-device", "virtserialport,chardev=virtiocon0"] | ||
| qemu_args += ["-chardev", f"file,id=virtiocon0,path={path}"] | ||
|
|
||
| return qemu_args | ||
|
|
||
| def init_virtiofs(self, socket, shared, mem): | ||
| """ initializes virtiofs by launching virtiofsd and creating a virtiofs device """ | ||
| virtiofsd_args = ["virtiofsd", "--socket", socket, "--shared-dir", shared, "--sandbox", "none"] | ||
| self._virtiofsd_proc = subprocess.Popen(virtiofsd_args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # pylint: disable=consider-using-with | ||
|
|
||
| if self._virtiofsd_proc.poll(): | ||
| raise Exception("VirtioFSD failed to start") | ||
|
|
||
| info("Successfully started VirtioFSD!") | ||
|
|
||
| while not os.path.exists(socket): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will hang with no helpful information if the shared folder doesn't exist: You can reproduce this by adding this to vm.json And then booting with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is because poll() returns immediately and error might not have been raised before poll() have returned (this is a race). I quickly tried to add a time.sleep(0.1) and it didn't hang because poll then returns the error code and the failure exception is raised. We need another signal. Any suggestions on how to solve this? I know that tests use a "SUCCESS" to indicate a successful test. I think a similar pattern could be used here (error is printed early on error, a watch). |
||
| ... | ||
|
|
||
| qemu_args = ["-machine", "memory-backend=mem0"] | ||
| qemu_args += ["-chardev", f"socket,id=virtiofsd0,path={socket}"] | ||
| qemu_args += ["-device", "vhost-user-fs-pci,chardev=virtiofsd0,tag=vfs"] | ||
| qemu_args += ["-object", f"memory-backend-memfd,id=mem0,size={mem}M,share=on"] | ||
|
|
||
| return qemu_args | ||
|
|
||
| def init_pmem(self, path, size, pmem_id): | ||
| """ creates a pmem device with image path as memory mapped backend """ | ||
| qemu_args = ["-object", f"memory-backend-file,id=pmemdev{pmem_id},mem-path={path},size={size}M,share=on"] | ||
| qemu_args += ["-device", f"virtio-pmem-pci,memdev=pmemdev{pmem_id}"] | ||
|
|
||
| return qemu_args | ||
|
|
||
| def kvm_present(self): | ||
| """ returns true if KVM is present and available """ | ||
| if not self._enable_kvm: | ||
|
|
@@ -660,7 +698,7 @@ def boot_in_hypervisor(self, multiboot=True, debug = False, kernel_args = "", im | |
|
|
||
| mem_arg = [] | ||
| if "mem" in self._config: | ||
| mem_arg = ["-m", str(self._config["mem"])] | ||
| mem_arg = ["-m", f"size={self._config["mem"]},maxmem=1000G"] | ||
|
|
||
| vga_arg = ["-nographic" ] | ||
| if "vga" in self._config: | ||
|
|
@@ -674,6 +712,27 @@ def boot_in_hypervisor(self, multiboot=True, debug = False, kernel_args = "", im | |
| if "vfio" in self._config: | ||
| pci_arg = ["-device", "vfio-pci,host=" + self._config["vfio"]] | ||
|
|
||
| virtiocon_args = [] | ||
| if "virtiocon" in self._config: | ||
| virtiocon_args = self.init_virtiocon(self._config["virtiocon"]["path"]) | ||
|
|
||
| virtiofs_args = [] | ||
| if "virtiofs" in self._config: | ||
| tmp_virtiofs_dir = tempfile.TemporaryDirectory(prefix="virtiofs-") # pylint: disable=consider-using-with | ||
| self._tmp_dirs.append(tmp_virtiofs_dir) | ||
| socket_path = os.path.join(tmp_virtiofs_dir.name, "virtiofsd.sock") | ||
|
|
||
| shared = self._config["virtiofs"]["shared"] | ||
|
|
||
| virtiofs_args = self.init_virtiofs(socket_path, shared, self._config["mem"]) | ||
|
|
||
| virtiopmem_args = [] | ||
| if "virtiopmem" in self._config: | ||
| for pmem_id, virtiopmem in enumerate(self._config["virtiopmem"]): | ||
| image = virtiopmem["image"] | ||
| size = virtiopmem["size"] | ||
| virtiopmem_args += self.init_pmem(image, size, pmem_id) | ||
|
|
||
| # custom qemu binary/location | ||
| qemu_binary = "qemu-system-x86_64" | ||
| if "qemu" in self._config: | ||
|
|
@@ -703,7 +762,8 @@ def boot_in_hypervisor(self, multiboot=True, debug = False, kernel_args = "", im | |
|
|
||
| command += kernel_args | ||
| command += disk_args + debug_args + net_args + mem_arg + mod_args | ||
| command += vga_arg + trace_arg + pci_arg | ||
| command += vga_arg + trace_arg + pci_arg + virtiocon_args + virtiofs_args | ||
| command += virtiopmem_args | ||
|
|
||
| #command_str = " ".join(command) | ||
| #command_str.encode('ascii','ignore') | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So new device types for virtio console, fs and pmem - nice!