diff --git a/nixos/doc/manual/development/running-nixos-tests-interactively.section.md b/nixos/doc/manual/development/running-nixos-tests-interactively.section.md index 66be7d5f812be..513e7081fd871 100644 --- a/nixos/doc/manual/development/running-nixos-tests-interactively.section.md +++ b/nixos/doc/manual/development/running-nixos-tests-interactively.section.md @@ -77,52 +77,34 @@ An SSH-based backdoor to log into machines can be enabled with } ``` -::: {.warning} -Make sure to only enable the backdoor for interactive tests -(i.e. by using `interactive.sshBackdoor.enable`)! This is the only -supported configuration. - -Running a test in a sandbox with this will fail because `/dev/vhost-vsock` isn't available -in the sandbox. -::: - This creates a [vsock socket](https://man7.org/linux/man-pages/man7/vsock.7.html) for each VM to log in with SSH. This configures root login with an empty password. -When the VMs get started interactively with the test-driver, it's possible to -connect to `machine` with +On the host-side a UNIX domain-socket is used with +[vhost-device-vsock](https://github.com/rust-vmm/vhost-device/blob/main/vhost-device-vsock/README.md). +That way, it's not necessary to assign system-wide unique vsock numbers. ``` -$ ssh vsock/3 -o User=root +$ ssh vsock-mux//tmp/path/to/host -o User=root ``` -The socket numbers correspond to the node number of the test VM, but start -at three instead of one because that's the lowest possible -vsock number. The exact SSH commands are also printed out when starting -`nixos-test-driver`. - -On non-NixOS systems you'll probably need to enable -the SSH config from {manpage}`systemd-ssh-proxy(1)` yourself. - -If starting VM fails with an error like +The socket paths are printed when starting the test driver: ``` -qemu-system-x86_64: -device vhost-vsock-pci,guest-cid=3: vhost-vsock: unable to set guest cid: Address already in use +Note: this requires systemd-ssh-proxy(1) to be enabled (default on NixOS 25.05 and newer). + machine: ssh -o User=root vsock-mux//tmp/tmpg1rp9nti/machine_host.socket ``` -it means that the vsock numbers for the VMs are already in use. This can happen -if another interactive test with SSH backdoor enabled is running on the machine. +On non-NixOS systems you'll probably need to enable +the SSH config from {manpage}`systemd-ssh-proxy(1)` yourself. -In that case, you need to assign another range of vsock numbers. You can pick another -offset with +During a test-run, it's possible to print the SSH commands again by running -```nix -{ - sshBackdoor = { - enable = true; - vsockOffset = 23542; - }; -} +``` +In [2]: dump_machine_ssh() +SSH backdoor enabled, the machines can be accessed like this: +Note: this requires systemd-ssh-proxy(1) to be enabled (default on NixOS 25.05 and newer). + machine: ssh -o User=root vsock-mux//tmp/tmpg1rp9nti/machine_host.socket ``` ## Port forwarding to NixOS test VMs {#sec-nixos-test-port-forwarding} diff --git a/nixos/doc/manual/development/writing-nixos-tests.section.md b/nixos/doc/manual/development/writing-nixos-tests.section.md index f78d81c4fe397..fd8c2246ce62f 100644 --- a/nixos/doc/manual/development/writing-nixos-tests.section.md +++ b/nixos/doc/manual/development/writing-nixos-tests.section.md @@ -376,24 +376,16 @@ This can be done when something in the test fails, e.g. } ``` -For the AF_VSOCK feature to work, `/dev/vhost-vsock` is needed in the sandbox -which can be done with e.g. - -``` -nix-build -A nixosTests.foo --option sandbox-paths /dev/vhost-vsock -``` - This will halt the test execution on a test-failure and print instructions on how to enter the sandbox shell of the VM test. Inside, one can log into e.g. `machine` with ``` -ssh -F ./ssh_config vsock/3 +ssh -F ./ssh_config -o User=root vsock-mux//tmp/.../machine_host.socket ``` -As described in [](#sec-nixos-test-ssh-access), the numbers for vsock start at -`3` instead of `1`. So the first VM in the network (sorted alphabetically) can -be accessed with `vsock/3`. +The socket paths are printed at the beginning of the test. See +[](#sec-nixos-test-ssh-access) for more context. Alternatively, it's possible to explicitly set a breakpoint with `debug.breakpoint()`. This also has the benefit, that one can step through diff --git a/nixos/doc/manual/redirects.json b/nixos/doc/manual/redirects.json index e7a60706ecfe2..6b7d0d9763bc6 100644 --- a/nixos/doc/manual/redirects.json +++ b/nixos/doc/manual/redirects.json @@ -1984,9 +1984,6 @@ "test-opt-sshBackdoor.enable": [ "index.html#test-opt-sshBackdoor.enable" ], - "test-opt-sshBackdoor.vsockOffset": [ - "index.html#test-opt-sshBackdoor.vsockOffset" - ], "test-opt-enableDebugHook": [ "index.html#test-opt-enableDebugHook" ], diff --git a/nixos/lib/test-driver/default.nix b/nixos/lib/test-driver/default.nix index cb3729941d0e3..45dabc3abfd3a 100644 --- a/nixos/lib/test-driver/default.nix +++ b/nixos/lib/test-driver/default.nix @@ -11,6 +11,7 @@ ruff, tesseract4, vde2, + vhost-device-vsock, extraPythonPackages ? (_: [ ]), nixosTests, }: @@ -43,6 +44,7 @@ python3Packages.buildPythonApplication { qemu_pkg socat vde2 + vhost-device-vsock ] ++ lib.optionals enableOCR [ imagemagick_light diff --git a/nixos/lib/test-driver/src/test_driver/__init__.py b/nixos/lib/test-driver/src/test_driver/__init__.py index 422cf39172333..c0f3bc6617b96 100755 --- a/nixos/lib/test-driver/src/test_driver/__init__.py +++ b/nixos/lib/test-driver/src/test_driver/__init__.py @@ -115,9 +115,9 @@ def main() -> None: type=Path, ) arg_parser.add_argument( - "--dump-vsocks", + "--enable-ssh-backdoor", help="indicates that the interactive SSH backdoor is active and dumps information about it on start", - type=int, + action="store_true", ) args = arg_parser.parse_args() @@ -147,9 +147,10 @@ def main() -> None: args.keep_vm_state, args.global_timeout, debug=debugger, + enable_ssh_backdoor=args.enable_ssh_backdoor, ) as driver: - if offset := args.dump_vsocks: - driver.dump_machine_ssh(offset) + if args.enable_ssh_backdoor: + driver.dump_machine_ssh() if args.interactive: history_dir = os.getcwd() history_path = os.path.join(history_dir, ".nixos-test-history") diff --git a/nixos/lib/test-driver/src/test_driver/driver.py b/nixos/lib/test-driver/src/test_driver/driver.py index 361bb1c2a93d0..53e49bacf436e 100644 --- a/nixos/lib/test-driver/src/test_driver/driver.py +++ b/nixos/lib/test-driver/src/test_driver/driver.py @@ -1,12 +1,14 @@ import os import re import signal +import subprocess import sys import tempfile import threading import traceback from collections.abc import Callable, Iterator from contextlib import AbstractContextManager, contextmanager +from dataclasses import dataclass from pathlib import Path from typing import Any from unittest import TestCase @@ -57,18 +59,62 @@ def pythonize_name(name: str) -> str: return re.sub(r"^[^A-Za-z_]|[^A-Za-z0-9_]", "_", name) +@dataclass +class VsockPair: + guest: Path + host: Path + cid: int + + +class VHostDeviceVsock: + def __init__(self, tmp_dir: Path, machines: Iterator[str]): + self.temp_dir_handle = tempfile.TemporaryDirectory(dir=tmp_dir) + self.temp_dir = Path(self.temp_dir_handle.name) + self.sockets = { + machine: VsockPair( + self.temp_dir / f"{machine}_guest.socket", + self.temp_dir / f"{machine}_host.socket", + cid, + ) + for cid, machine in enumerate(machines, start=3) + } + + self.vhost_proc = subprocess.Popen( + ( + "vhost-device-vsock", + *( + arg + for vsock_pair in self.sockets.values() + for arg in ( + "--vm", + f"guest-cid={vsock_pair.cid},socket={vsock_pair.guest},uds-path={vsock_pair.host}", + ) + ), + ) + ) + + def __del__(self) -> None: + self.vhost_proc.kill() + self.temp_dir_handle.cleanup() + + class Driver: """A handle to the driver that sets up the environment and runs the tests""" tests: str - vlans: list[VLan] - machines: list[Machine] + vlans: list[VLan] = [] + machines: list[Machine] = [] polling_conditions: list[PollingCondition] global_timeout: int race_timer: threading.Timer + start_scripts: list[NixStartScript] + vlan_ids: list[int] + keep_vm_state: bool logger: AbstractLogger debug: DebugAbstract + vhost_vsock: VHostDeviceVsock | None = None + enable_ssh_backdoor: bool def __init__( self, @@ -80,40 +126,51 @@ def __init__( keep_vm_state: bool = False, global_timeout: int = 24 * 60 * 60 * 7, debug: DebugAbstract = DebugNop(), + enable_ssh_backdoor: bool = False, ): self.tests = tests self.out_dir = out_dir self.global_timeout = global_timeout - self.race_timer = threading.Timer(global_timeout, self.terminate_test) self.logger = logger self.debug = debug + self.vlan_ids = list(set(vlans)) + self.polling_conditions = [] + self.keep_vm_state = keep_vm_state + self.global_timeout = global_timeout + self.start_scripts = list(map(NixStartScript, start_scripts)) + self.enable_ssh_backdoor = enable_ssh_backdoor + def __enter__(self) -> "Driver": + self.race_timer = threading.Timer(self.global_timeout, self.terminate_test) tmp_dir = get_tmp_dir() with self.logger.nested("start all VLans"): - vlans = list(set(vlans)) - self.vlans = [VLan(nr, tmp_dir, self.logger) for nr in vlans] - - def cmd(scripts: list[str]) -> Iterator[NixStartScript]: - for s in scripts: - yield NixStartScript(s) + self.vlans = [VLan(nr, tmp_dir, self.logger) for nr in self.vlan_ids] - self.polling_conditions = [] + if self.enable_ssh_backdoor: + with self.logger.nested("start vhost-device-vsock"): + self.vhost_vsock = VHostDeviceVsock( + tmp_dir, (cmd.machine_name for cmd in self.start_scripts) + ) self.machines = [ Machine( start_command=cmd, - keep_vm_state=keep_vm_state, + keep_vm_state=self.keep_vm_state, name=cmd.machine_name, tmp_dir=tmp_dir, callbacks=[self.check_polling_conditions], out_dir=self.out_dir, logger=self.logger, + vsock_guest=( + self.vhost_vsock.sockets[cmd.machine_name].guest + if self.vhost_vsock is not None + else None + ), ) - for cmd in cmd(start_scripts) + for cmd in self.start_scripts ] - def __enter__(self) -> "Driver": return self def __exit__(self, *_: Any) -> None: @@ -131,6 +188,14 @@ def __exit__(self, *_: Any) -> None: except Exception as e: self.logger.error(f"Error during cleanup of vlan{vlan.nr}: {e}") + if self.enable_ssh_backdoor: + try: + del self.vhost_vsock + except Exception as e: + self.logger.error( + f"Error during cleanup of vhost-device-vsock process: {e}" + ) + def subtest(self, name: str) -> Iterator[None]: """Group logs under a given test name""" with self.logger.subtest(name): @@ -164,6 +229,7 @@ def subtest(name: str) -> Iterator[None]: Machine=Machine, # for typing t=AssertionTester(), debug=self.debug, + dump_machine_ssh=self.dump_machine_ssh, ) machine_symbols = {pythonize_name(m.name): m for m in self.machines} # If there's exactly one machine, make it available under the name @@ -183,18 +249,26 @@ def subtest(name: str) -> Iterator[None]: ) return {**general_symbols, **machine_symbols, **vlan_symbols} - def dump_machine_ssh(self, offset: int) -> None: - print("SSH backdoor enabled, the machines can be accessed like this:") - print( - f"{Style.BRIGHT}Note:{Style.RESET_ALL} this requires {Style.BRIGHT}systemd-ssh-proxy(1){Style.RESET_ALL} to be enabled (default on NixOS 25.05 and newer)." - ) - names = [machine.name for machine in self.machines] - longest_name = len(max(names, key=len)) - for num, name in enumerate(names, start=offset + 1): - spaces = " " * (longest_name - len(name) + 2) + def dump_machine_ssh(self) -> None: + if not self.enable_ssh_backdoor: + return + + assert self.vhost_vsock is not None + + if self.machines: + print("SSH backdoor enabled, the machines can be accessed like this:") print( - f" {name}:{spaces}{Style.BRIGHT}ssh -o User=root vsock/{num}{Style.RESET_ALL}" + f"{Style.BRIGHT}Note:{Style.RESET_ALL} this requires {Style.BRIGHT}systemd-ssh-proxy(1){Style.RESET_ALL} to be enabled (default on NixOS 25.05 and newer)." ) + names = [machine.name for machine in self.machines] + longest_name = len(max(names, key=len)) + for name in names: + spaces = " " * (longest_name - len(name) + 2) + print( + f" {name}:{spaces}{Style.BRIGHT}ssh -o User=root vsock-mux/{self.vhost_vsock.sockets[name].host}{Style.RESET_ALL}" + ) + else: + print("SSH backdoor enabled, but no machines defined") def test_script(self) -> None: """Run the test script""" @@ -285,6 +359,10 @@ def create_machine( cmd = NixStartScript(start_command) name = name or cmd.machine_name + if self.enable_ssh_backdoor: + self.logger.warning( + f"create_machine({name}): not enabling SSH backdoor, this is not supported for VMs created with create_machine!" + ) return Machine( tmp_dir=tmp_dir, diff --git a/nixos/lib/test-driver/src/test_driver/machine/__init__.py b/nixos/lib/test-driver/src/test_driver/machine/__init__.py index 5f17006f90dab..985ecbb4d372a 100644 --- a/nixos/lib/test-driver/src/test_driver/machine/__init__.py +++ b/nixos/lib/test-driver/src/test_driver/machine/__init__.py @@ -15,6 +15,7 @@ import time from collections.abc import Callable, Generator from contextlib import _GeneratorContextManager, contextmanager, nullcontext +from functools import cached_property from pathlib import Path from queue import Queue from typing import Any @@ -124,6 +125,7 @@ def cmd( qmp_socket_path: Path, shell_socket_path: Path, allow_reboot: bool = False, + vsock_guest: Path | None = None, ) -> str: display_opts = "" @@ -147,6 +149,12 @@ def cmd( if not allow_reboot: qemu_opts += " -no-reboot" + if vsock_guest is not None: + qemu_opts += ( + f" -chardev socket,id=vsock_ssh,reconnect=0,path={vsock_guest} " + f"-device vhost-user-vsock-pci,chardev=vsock_ssh " + ) + return ( f"{self._cmd}" f" -qmp unix:{qmp_socket_path},server=on,wait=off" @@ -180,10 +188,15 @@ def run( qmp_socket_path: Path, shell_socket_path: Path, allow_reboot: bool, + vsock_guest: Path | None = None, ) -> subprocess.Popen: return subprocess.Popen( self.cmd( - monitor_socket_path, qmp_socket_path, shell_socket_path, allow_reboot + monitor_socket_path, + qmp_socket_path, + shell_socket_path, + allow_reboot, + vsock_guest, ), stdin=subprocess.PIPE, stdout=subprocess.PIPE, @@ -204,7 +217,7 @@ class NixStartScript(StartCommand): def __init__(self, script: str): self._cmd = script - @property + @cached_property def machine_name(self) -> str: match = re.search("run-(.+)-vm$", self._cmd) name = "machine" @@ -225,6 +238,7 @@ class Machine: monitor_path: Path qmp_path: Path shell_path: Path + vsock_guest: Path | None start_command: StartCommand keep_vm_state: bool @@ -257,6 +271,7 @@ def __init__( name: str = "machine", keep_vm_state: bool = False, callbacks: list[Callable] | None = None, + vsock_guest: Path | None = None, ) -> None: self.out_dir = out_dir self.tmp_dir = tmp_dir @@ -266,6 +281,7 @@ def __init__( self.callbacks = callbacks if callbacks is not None else [] self.logger = logger self.full_console_log = [] + self.vsock_guest = vsock_guest # set up directories self.shared_dir = self.tmp_dir / "shared-xchg" @@ -1089,6 +1105,7 @@ def create_socket(path: Path) -> socket.socket: self.qmp_path, self.shell_path, allow_reboot, + self.vsock_guest, ) self.monitor, _ = monitor_socket.accept() self.shell, _ = shell_socket.accept() diff --git a/nixos/lib/test-script-prepend.py b/nixos/lib/test-script-prepend.py index 067fd20fe7c5f..bf8ad3ee0f690 100644 --- a/nixos/lib/test-script-prepend.py +++ b/nixos/lib/test-script-prepend.py @@ -55,3 +55,4 @@ def __call__( polling_condition: PollingConditionProtocol debug: DebugAbstract t: TestCase +dump_machine_ssh: Callable[[], None] diff --git a/nixos/lib/testing/driver.nix b/nixos/lib/testing/driver.nix index 6abfac7b31910..20bf144525e64 100644 --- a/nixos/lib/testing/driver.nix +++ b/nixos/lib/testing/driver.nix @@ -7,6 +7,8 @@ let inherit (lib) mkOption types literalMD; + inherit (config) sshBackdoor; + # Reifies and correctly wraps the python test driver for # the respective qemu version and with or without ocr support testDriver = hostPkgs.callPackage ../test-driver { @@ -209,5 +211,27 @@ in # make available on the test runner passthru.driver = config.driver; + + defaults = + { config, ... }: + { + # This is needed for the SSH backdoor to function. + # Set this to `true` by default to not change essential QEMU flags + # depending on whether debugging is enabled. + # + # If needed, this can still be turned off. + virtualisation.qemu.enableSharedMemory = lib.mkDefault true; + + assertions = [ + { + assertion = sshBackdoor.enable -> config.virtualisation.qemu.enableSharedMemory; + message = '' + When turning on the SSH backdoor of the NixOS test-framework, + `virtualisation.qemu.enableSharedMemory` MUST be `true` + (affected: ${config.networking.hostName}). + ''; + } + ]; + }; }; } diff --git a/nixos/lib/testing/nodes.nix b/nixos/lib/testing/nodes.nix index 1f562a5f4f263..1667917544202 100644 --- a/nixos/lib/testing/nodes.nix +++ b/nixos/lib/testing/nodes.nix @@ -15,6 +15,7 @@ let mkDefault mkIf mkMerge + mkRemovedOptionModule mkOption mkForce optional @@ -80,6 +81,12 @@ let in { + imports = [ + (mkRemovedOptionModule [ "sshBackdoor" "vsockOffset" ] '' + The option `sshBackdoor.vsockOffset` has been removed from the testing framework. + The functionality provided by it is not needed anymore. + '') + ]; options = { sshBackdoor = { @@ -89,22 +96,6 @@ in type = types.bool; description = "Whether to turn on the VSOCK-based access to all VMs. This provides an unauthenticated access intended for debugging."; }; - vsockOffset = mkOption { - default = 2; - type = types.ints.between 2 4294967296; - description = '' - This field is only relevant when multiple users run the (interactive) - driver outside the sandbox and with the SSH backdoor activated. - The typical symptom for this being a problem are error messages like this: - `vhost-vsock: unable to set guest cid: Address already in use` - - This option allows to assign an offset to each vsock number to - resolve this. - - This is a 32bit number. The lowest possible vsock number is `3` - (i.e. with the lowest node number being `1`, this is 2+1). - ''; - }; }; node.type = mkOption { @@ -203,7 +194,7 @@ in passthru.nodes = config.nodesCompat; extraDriverArgs = mkIf config.sshBackdoor.enable [ - "--dump-vsocks=${toString config.sshBackdoor.vsockOffset}" + "--enable-ssh-backdoor" ]; defaults = mkMerge [ @@ -228,12 +219,6 @@ in security.pam.services.sshd = { allowNullPassword = true; }; - - virtualisation.qemu.options = [ - "-device vhost-vsock-pci,guest-cid=${ - toString (config.virtualisation.test.nodeNumber + vsockOffset) - }" - ]; } )) ]; diff --git a/nixos/lib/testing/run.nix b/nixos/lib/testing/run.nix index e34e585241bec..28c2e84201fa7 100644 --- a/nixos/lib/testing/run.nix +++ b/nixos/lib/testing/run.nix @@ -79,6 +79,10 @@ in }; }; + imports = [ + ../../modules/misc/assertions.nix + ]; + config = { rawTestDerivation = hostPkgs.stdenv.mkDerivation config.rawTestDerivationArg; rawTestDerivationArg = @@ -127,7 +131,7 @@ in }; test = lib.lazyDerivation { # lazyDerivation improves performance when only passthru items and/or meta are used. - derivation = config.rawTestDerivation; + derivation = lib.asserts.checkAssertWarn config.assertions config.warnings config.rawTestDerivation; inherit (config) passthru meta; }; diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 6893d39382eaf..6482b8c4793d6 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -774,6 +774,8 @@ in }; virtualisation.qemu = { + enableSharedMemory = mkEnableOption "shared memory"; + package = mkOption { type = types.package; default = @@ -1273,6 +1275,10 @@ in "-device usb-kbd" "-device usb-tablet" ]) + (mkIf cfg.qemu.enableSharedMemory [ + "-object memory-backend-memfd,id=mem0,size=${toString config.virtualisation.memorySize}M,share=on" + "-machine memory-backend=mem0" + ]) ( let alphaNumericChars = lowerChars ++ upperChars ++ (map toString (range 0 9)); diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 66a599383a957..50f706ab9a5f9 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -162,6 +162,7 @@ in lib-extend = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./nixos-test-driver/lib-extend.nix { }; node-name = runTest ./nixos-test-driver/node-name.nix; busybox = runTest ./nixos-test-driver/busybox.nix; + ssh-backdoor = runTestOn [ "x86_64-linux" ] ./nixos-test-driver/ssh-backdoor.nix; console-log = runTest ./nixos-test-driver/console-log.nix; driver-timeout = pkgs.runCommand "ensure-timeout-induced-failure" diff --git a/nixos/tests/nixos-test-driver/ssh-backdoor.nix b/nixos/tests/nixos-test-driver/ssh-backdoor.nix new file mode 100644 index 0000000000000..b7fe3c064ac3b --- /dev/null +++ b/nixos/tests/nixos-test-driver/ssh-backdoor.nix @@ -0,0 +1,41 @@ +{ pkgs, lib, ... }: +{ + name = "ssh-backdoor"; + sshBackdoor.enable = true; + + nodes.machine = { }; + + testScript = '' + import subprocess + + start_all() + machine.wait_for_unit("multi-user.target") + + assert driver.vhost_vsock is not None + host_socket = driver.vhost_vsock.sockets["machine"].host + + with subtest("ssh from the host via systemd-ssh-proxy"): + subprocess.run( + [ + "${lib.getExe pkgs.openssh}", + "-vvv", + f"vsock-mux/{host_socket}", + "-o", + "User=root", + "-F", + # FIXME not needed anymore with systemd 258 + "${pkgs.writeText "ssh.conf" '' + Host vsock-mux/* + ProxyCommand ${pkgs.systemd}/lib/systemd/systemd-ssh-proxy %h %p + ProxyUseFdpass yes + CheckHostIP no + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + ''}", + "--", + "true" + ], + check=True + ) + ''; +} diff --git a/pkgs/by-name/vh/vhost-device-vsock/package.nix b/pkgs/by-name/vh/vhost-device-vsock/package.nix new file mode 100644 index 0000000000000..7dc820cbd48cf --- /dev/null +++ b/pkgs/by-name/vh/vhost-device-vsock/package.nix @@ -0,0 +1,43 @@ +{ + lib, + fetchFromGitHub, + rustPlatform, + installShellFiles, +}: + +rustPlatform.buildRustPackage (finalAttrs: { + pname = "vhost-device-vsock"; + version = "0.3.0"; + + src = fetchFromGitHub { + owner = "rust-vmm"; + repo = "vhost-device"; + tag = "vhost-device-vsock-v${finalAttrs.version}"; + hash = "sha256-g+u6WBJtizIgQwC0kkWdAcTiYCM1zMI4YBLVRU4MOrs="; + }; + + outputs = [ + "out" + "man" + ]; + + cargoBuildFlags = "-p vhost-device-vsock"; + cargoTestFlags = "-p vhost-device-vsock"; + cargoHash = "sha256-mtORRCY/TNeIEgRCQ1ZbjpsykteRm2FHRveKaQxD/Pw="; + + nativeBuildInputs = [ installShellFiles ]; + + postInstall = '' + installManPage vhost-device-vsock/*.1 + ''; + + meta = { + homepage = "https://github.com/rust-vmm/vhost-device/blob/main/vhost-device-vsock/README.md"; + maintainers = with lib.maintainers; [ ma27 ]; + license = with lib.licenses; [ + asl20 + bsd3 + ]; + platforms = lib.platforms.linux; + }; +})