1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
{ 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" ];
}
|