242949ecfb
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
137 lines
4 KiB
Nix
137 lines
4 KiB
Nix
{ depot, pkgs, ... }:
|
|
|
|
rec {
|
|
# A binary that sets up /nix/store from virtiofs, lists all store paths, and
|
|
# powers off the machine.
|
|
tvix-init = depot.nix.buildGo.program {
|
|
name = "tvix-init";
|
|
srcs = [
|
|
./tvix-init.go
|
|
];
|
|
};
|
|
|
|
# A kernel with virtiofs support baked in
|
|
kernel = pkgs.buildLinux ({ } // {
|
|
inherit (pkgs.linuxPackages_latest.kernel) src version modDirVersion;
|
|
autoModules = false;
|
|
kernelPreferBuiltin = true;
|
|
ignoreConfigErrors = true;
|
|
kernelPatches = [ ];
|
|
structuredExtraConfig = with pkgs.lib.kernel; {
|
|
FUSE_FS = option yes;
|
|
DAX_DRIVER = option yes;
|
|
DAX = option yes;
|
|
FS_DAX = option yes;
|
|
VIRTIO_FS = option yes;
|
|
VIRTIO = option yes;
|
|
ZONE_DEVICE = option yes;
|
|
};
|
|
});
|
|
|
|
# A build framework for minimal initrds
|
|
uroot = pkgs.buildGoModule {
|
|
pname = "u-root";
|
|
version = "unstable-2023-09-20";
|
|
src = pkgs.fetchFromGitHub {
|
|
owner = "u-root";
|
|
repo = "u-root";
|
|
rev = "72921548ce2e88c4c5b62e83c717cbd834b58067";
|
|
hash = "sha256-fEoUGqh6ZXprtSpJ55MeuSFe7L5A/rkIIVLCwxbPHzE=";
|
|
};
|
|
vendorHash = null;
|
|
|
|
doCheck = false; # Some tests invoke /bin/bash
|
|
};
|
|
|
|
# Use u-root to build a initrd with our tvix-init inside.
|
|
initrd = pkgs.stdenv.mkDerivation {
|
|
name = "initrd.cpio";
|
|
nativeBuildInputs = [ pkgs.go ];
|
|
# https://github.com/u-root/u-root/issues/2466
|
|
buildCommand = ''
|
|
mkdir -p /tmp/go/src/github.com/u-root/
|
|
cp -R ${uroot.src} /tmp/go/src/github.com/u-root/u-root
|
|
cd /tmp/go/src/github.com/u-root/u-root
|
|
chmod +w .
|
|
cp ${tvix-init}/bin/tvix-init tvix-init
|
|
|
|
export HOME=$(mktemp -d)
|
|
export GOROOT="$(go env GOROOT)"
|
|
|
|
GO111MODULE=off GOPATH=/tmp/go GOPROXY=off ${uroot}/bin/u-root -files ./tvix-init -initcmd "/tvix-init" -o $out
|
|
'';
|
|
};
|
|
|
|
# Start a `tvix-store` virtiofs daemon from $PATH, then a cloud-hypervisor
|
|
# pointed to it.
|
|
# Supports the following env vars (and defaults)
|
|
# CH_NUM_CPUS=1
|
|
# CH_MEM_SIZE=512M
|
|
# CH_CMDLINE=""
|
|
runVM = pkgs.writers.writeBashBin "run-tvix-vm" ''
|
|
tempdir=$(mktemp -d)
|
|
|
|
cleanup() {
|
|
kill $virtiofsd_pid
|
|
if [[ -n ''${work_dir-} ]]; then
|
|
chmod -R u+rw "$tempdir"
|
|
rm -rf "$tempdir"
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# Spin up the virtiofs daemon
|
|
tvix-store virtiofs -l $tempdir/tvix.sock &
|
|
virtiofsd_pid=$!
|
|
|
|
# Wait for the socket to exist.
|
|
until [ -e $tempdir/tvix.sock ]; do sleep 0.1; done
|
|
|
|
CH_NUM_CPUS="''${CH_NUM_CPUS:-1}"
|
|
CH_MEM_SIZE="''${CH_MEM_SIZE:-512M}"
|
|
CH_CMDLINE="''${CH_CMDLINE:-}"
|
|
|
|
# spin up cloud_hypervisor
|
|
${pkgs.cloud-hypervisor}/bin/cloud-hypervisor \
|
|
--cpus boot=$CH_NUM_CPU \
|
|
--memory mergeable=on,shared=on,size=$CH_MEM_SIZE \
|
|
--console null \
|
|
--serial tty \
|
|
--kernel ${kernel.dev}/vmlinux \
|
|
--initramfs ${initrd} \
|
|
--cmdline "console=ttyS0 $CH_CMDLINE" \
|
|
--fs tag=tvix,socket=$tempdir/tvix.sock,num_queues=1,queue_size=512
|
|
'';
|
|
|
|
# Seed a tvix-store with the tvix docs, then start a VM and search for the
|
|
# store path in the output.
|
|
test-docs = pkgs.stdenv.mkDerivation {
|
|
name = "run-vm";
|
|
nativeBuildInputs = [
|
|
depot.tvix.store
|
|
];
|
|
buildCommand = ''
|
|
touch $out
|
|
|
|
# Configure tvix to put data in the local working directory
|
|
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
|
|
|
|
# Seed the tvix store with some data
|
|
# Create a `docs` directory with the contents from ../docs
|
|
# Make sure it still is called "docs" when calling import, so we can
|
|
# predict the store path.
|
|
cp -R ${../docs} docs
|
|
outpath=$(tvix-store import docs)
|
|
|
|
echo "Store contents imported to $outpath"
|
|
|
|
CH_CMDLINE="tvix.find" ${runVM}/bin/run-tvix-vm 2>&1 | tee output.txt
|
|
grep ${../docs} output.txt
|
|
'';
|
|
requiredSystemFeatures = [ "kvm" ];
|
|
};
|
|
|
|
meta.ci.targets = [ "test-docs" ];
|
|
}
|