1import ./make-test-python.nix ({ pkgs, ...} :
2
3let
4 # Since we don't have access to the internet during the tests, we have to
5 # pre-fetch lxd containers beforehand.
6 #
7 # I've chosen to import Alpine Linux, because its image is turbo-tiny and,
8 # generally, sufficient for our tests.
9 alpine-meta = pkgs.fetchurl {
10 url = "https://tarballs.nixos.org/alpine/3.12/lxd.tar.xz";
11 hash = "sha256-1tcKaO9lOkvqfmG/7FMbfAEToAuFy2YMewS8ysBKuLA=";
12 };
13
14 alpine-rootfs = pkgs.fetchurl {
15 url = "https://tarballs.nixos.org/alpine/3.12/rootfs.tar.xz";
16 hash = "sha256-Tba9sSoaiMtQLY45u7p5DMqXTSDgs/763L/SQp0bkCA=";
17 };
18
19 lxd-config = pkgs.writeText "config.yaml" ''
20 storage_pools:
21 - name: default
22 driver: dir
23 config:
24 source: /var/lxd-pool
25
26 networks:
27 - name: lxdbr0
28 type: bridge
29 config:
30 ipv4.address: auto
31 ipv6.address: none
32
33 profiles:
34 - name: default
35 devices:
36 eth0:
37 name: eth0
38 network: lxdbr0
39 type: nic
40 root:
41 path: /
42 pool: default
43 type: disk
44 '';
45
46
47in {
48 name = "lxd";
49
50 meta = with pkgs.lib.maintainers; {
51 maintainers = [ patryk27 ];
52 };
53
54 machine = { lib, ... }: {
55 virtualisation = {
56 # Since we're testing `limits.cpu`, we've gotta have a known number of
57 # cores to lean on
58 cores = 2;
59
60 # Ditto, for `limits.memory`
61 memorySize = 512;
62
63 lxc.lxcfs.enable = true;
64 lxd.enable = true;
65 };
66 };
67
68 testScript = ''
69 machine.wait_for_unit("sockets.target")
70 machine.wait_for_unit("lxd.service")
71 machine.wait_for_file("/var/lib/lxd/unix.socket")
72
73 # It takes additional second for lxd to settle
74 machine.sleep(1)
75
76 # lxd expects the pool's directory to already exist
77 machine.succeed("mkdir /var/lxd-pool")
78
79 machine.succeed(
80 "cat ${lxd-config} | lxd init --preseed"
81 )
82
83 machine.succeed(
84 "lxc image import ${alpine-meta} ${alpine-rootfs} --alias alpine"
85 )
86
87 with subtest("Containers can be launched and destroyed"):
88 machine.succeed("lxc launch alpine test")
89 machine.succeed("lxc exec test true")
90 machine.succeed("lxc delete -f test")
91
92 with subtest("Containers are being mounted with lxcfs inside"):
93 machine.succeed("lxc launch alpine test")
94
95 ## ---------- ##
96 ## limits.cpu ##
97
98 machine.succeed("lxc config set test limits.cpu 1")
99
100 # Since Alpine doesn't have `nproc` pre-installed, we've gotta resort
101 # to the primal methods
102 assert (
103 "1"
104 == machine.succeed("lxc exec test grep -- -c ^processor /proc/cpuinfo").strip()
105 )
106
107 machine.succeed("lxc config set test limits.cpu 2")
108
109 assert (
110 "2"
111 == machine.succeed("lxc exec test grep -- -c ^processor /proc/cpuinfo").strip()
112 )
113
114 ## ------------- ##
115 ## limits.memory ##
116
117 machine.succeed("lxc config set test limits.memory 64MB")
118
119 assert (
120 "MemTotal: 62500 kB"
121 == machine.succeed("lxc exec test grep -- MemTotal /proc/meminfo").strip()
122 )
123
124 machine.succeed("lxc config set test limits.memory 128MB")
125
126 assert (
127 "MemTotal: 125000 kB"
128 == machine.succeed("lxc exec test grep -- MemTotal /proc/meminfo").strip()
129 )
130
131 machine.succeed("lxc delete -f test")
132
133 with subtest("Unless explicitly changed, lxd leans on iptables"):
134 machine.succeed("lsmod | grep ip_tables")
135 machine.fail("lsmod | grep nf_tables")
136 '';
137})