tvl-depot/tvix/tests
Florian Klink 242949ecfb fix(tvix/tests/tvix-init): run as pid1, support init=
We were previously not running as PID1, but were executing things via
uinitcmd (by u-root init).
This had some problems - a real system pid1 really wants to be pid1.

u-root init itself seems to be too complicated to configure as a
chainloader, so instead, we just provide init/pid1 ourselves and do the
little bit of mount setup / stage 1 that's necessary.

`tvix.exec` is renamed to `tvix.run`, to further distinguish it from the
`exec` bash function.

Our init will now also power off the machine if the shell, or the custom
tvix.run command finished. In the case of switch_root (`init=` being
passed), we terminate before, so it's up to the real system anyways.

Change-Id: If00c0c11ca9393968e76ae0d131594b5c135fa48
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9454
Autosubmit: flokli <flokli@flokli.de>
Reviewed-by: Connor Brewster <cbrewster@hey.com>
Tested-by: BuildkiteCI
2023-09-25 10:49:33 +00:00
..
default.nix fix(tvix/tests/tvix-init): run as pid1, support init= 2023-09-25 10:49:33 +00:00
README.md fix(tvix/tests/tvix-init): run as pid1, support init= 2023-09-25 10:49:33 +00:00
tvix-init.go fix(tvix/tests/tvix-init): run as pid1, support init= 2023-09-25 10:49:33 +00:00

tvix/tests

This directory provides a bunch of integration tests using tvix.

The currently most interesting (and only) ones ;-) are using a cloud-hypervisor VM.

//tvix/tests:test-docs

This is a test encapsulated in a nix build. It seeds a tvix-store with the tvix docs, then starts a VM, asks it to list all files in /nix/store, and ensures the store path is present, which acts as a nice smoketest.

//tvix/tests:runVM

A script spinning up a tvix-store virtiofs daemon, then starting a cloud- hypervisor VM.

The cloud-hypervisor VM is using a (semi-)minimal kernel image with virtiofs support, and a custom initrd (using u-root). It supports various command line options, to be able to do VM tests, act as an interactive shell or exec a binary from a closure.

It supports the following env vars:

  • CH_NUM_CPUS=1 controls the number of CPUs available to the VM
  • CH_MEM_SIZE=512M controls the memory availabe to the VM
  • CH_CMDLINE= controls the kernel cmdline (which can be used to control the boot)

Usage

First, ensure you have tvix-store in $PATH, as that's what run-tvix-vm expects:

Assuming you ran cargo build --profile=release-with-debug before, and are in the tvix directory:

export PATH=$PATH:$PWD/target/release-with-debug

Secondly, configure tvix to use the local backend:

export BLOB_SERVICE_ADDR=sled://$PWD/blobs.sled
export DIRECTORY_SERVICE_ADDR=sled://$PWD/directories.sled
export PATH_INFO_SERVICE_ADDR=sled://$PWD/pathinfo.sled

Potentially copy some data into tvix-store (via nar-bridge):

mg run //tvix:store -- daemon &
mg run //tvix:nar-bridge -- &
rm -Rf ~/.cache/nix; nix copy --to http://localhost:9000\?compression\=none $(mg build //third_party/nixpkgs:hello)
pkill nar-bridge; pkill tvix-store

Interactive shell

Run the VM like this:

CH_CMDLINE=tvix.shell mg run //tvix/tests:runVM --

You'll get dropped into an interactive shell, from which you can do things with the store:

  ______      _         ____      _ __
 /_  __/   __(_)  __   /  _/___  (_) /_
  / / | | / / / |/_/   / // __ \/ / __/
 / /  | |/ / />  <   _/ // / / / / /_
/_/   |___/_/_/|_|  /___/_/ /_/_/\__/

/# ls -la /nix/store/
dr-xr-xr-x root 0 0   Jan  1 00:00 .
dr-xr-xr-x root 0 989 Jan  1 00:00 aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8
dr-xr-xr-x root 0 3   Jan  1 00:00 jbwb8d8l28lg9z0xzl784wyb9vlbwss6-xgcc-12.3.0-libgcc
dr-xr-xr-x root 0 82  Jan  1 00:00 k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4
dr-xr-xr-x root 0 141 Jan  1 00:00 mdi7lvrn2mx7rfzv3fdq3v5yw8swiks6-hello-2.12.1
dr-xr-xr-x root 0 5   Jan  1 00:00 s2gi8pfjszy6rq3ydx0z1vwbbskw994i-libunistring-1.1

Once you exit the shell, the VM will power off itself.

Execute a specific binary

Run the VM like this:

hello_cmd=$(mg build //third_party/nixpkgs:hello)/bin/hello
CH_CMDLINE=tvix.run=$hello_cmd mg run //tvix/tests:runVM --

Observe it executing the file (and closure) from the tvix-store:

[    0.277486] Run /init as init process
  ______      _         ____      _ __
 /_  __/   __(_)  __   /  _/___  (_) /_
  / / | | / / / |/_/   / // __ \/ / __/
 / /  | |/ / />  <   _/ // / / / / /_
/_/   |___/_/_/|_|  /___/_/ /_/_/\__/

Hello, world!
2023/09/24 21:10:19 Nothing left to be done, powering off.
[    0.299122] ACPI: PM: Preparing to enter system sleep state S5
[    0.299422] reboot: Power down

Execute a NixOS system closure

It's also possible to invoke a system closure. To do this, tvix-init honors the init= cmdline option, and will switch_root to it.

CH_CMDLINE=init=/nix/store/…-nixos-system-…/init mg run //tvix/tests:runVM --
  ______      _         ____      _ __
 /_  __/   __(_)  __   /  _/___  (_) /_
  / / | | / / / |/_/   / // __ \/ / __/
 / /  | |/ / />  <   _/ // / / / / /_
/_/   |___/_/_/|_|  /___/_/ /_/_/\__/

2023/09/24 21:16:43 switch_root: moving mounts
2023/09/24 21:16:43 switch_root: Skipping "/run" as the dir does not exist
2023/09/24 21:16:43 switch_root: Changing directory
2023/09/24 21:16:43 switch_root: Moving /
2023/09/24 21:16:43 switch_root: Changing root!
2023/09/24 21:16:43 switch_root: Deleting old /
2023/09/24 21:16:43 switch_root: executing init

<<< NixOS Stage 2 >>>

[    0.322096] booting system configuration /nix/store/g657sdxinpqfcdv0162zmb8vv9b5c4c5-nixos-system-client-23.11.git.82102fc37da
running activation script...
setting up /etc...
starting systemd...
[    0.980740] systemd[1]: systemd 253.6 running in system mode (+PAM +AUDIT -SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK -XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified)

This effectively replaces the NixOS Stage 1 entirely.