vuls: init at 0.27.0
[NixPkgs.git] / nixos / tests / incus / container.nix
blob2329721d9504fa567a0dddb8d4f62bf8e650a13b
1 import ../make-test-python.nix ({ pkgs, lib, extra ? {}, name ? "incus-container", incus ? pkgs.incus-lts, ... } :
3 let
4   releases = import ../../release.nix {
5     configuration = lib.recursiveUpdate {
6         # Building documentation makes the test unnecessarily take a longer time:
7         documentation.enable = lib.mkForce false;
9         boot.kernel.sysctl."net.ipv4.ip_forward" = "1";
10     }
11     extra;
12   };
14   container-image-metadata = "${releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system}}/tarball/nixos-system-${pkgs.stdenv.hostPlatform.system}.tar.xz";
15   container-image-rootfs = "${releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system}}/nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}.squashfs";
18   inherit name;
20   meta = {
21     maintainers = lib.teams.lxc.members;
22   };
24   nodes.machine = { ... }: {
25     virtualisation = {
26       # Ensure test VM has enough resources for creating and managing guests
27       cores = 2;
28       memorySize = 1024;
29       diskSize = 4096;
31       incus = {
32         enable = true;
33         package = incus;
34       };
35     };
36     networking.nftables.enable = true;
37   };
39   testScript = ''
40     def instance_is_up(_) -> bool:
41         status, _ = machine.execute("incus exec container --disable-stdin --force-interactive /run/current-system/sw/bin/systemctl -- is-system-running")
42         return status == 0
44     def set_container(config):
45         machine.succeed(f"incus config set container {config}")
46         machine.succeed("incus restart container")
47         with machine.nested("Waiting for instance to start and be usable"):
48           retry(instance_is_up)
50     def check_sysctl(instance):
51         with subtest("systemd sysctl settings are applied"):
52             machine.succeed(f"incus exec {instance} -- systemctl status systemd-sysctl")
53             sysctl = machine.succeed(f"incus exec {instance} -- sysctl net.ipv4.ip_forward").strip().split(" ")[-1]
54             assert "1" == sysctl, f"systemd-sysctl configuration not correctly applied, {sysctl} != 1"
56     machine.wait_for_unit("incus.service")
58     # no preseed should mean no service
59     machine.fail("systemctl status incus-preseed.service")
61     machine.succeed("incus admin init --minimal")
63     with subtest("Container image can be imported"):
64         machine.succeed("incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos")
66     with subtest("Container can be launched and managed"):
67         machine.succeed("incus launch nixos container")
68         with machine.nested("Waiting for instance to start and be usable"):
69           retry(instance_is_up)
70         machine.succeed("echo true | incus exec container /run/current-system/sw/bin/bash -")
72     with subtest("Container mounts lxcfs overlays"):
73         machine.succeed("incus exec container mount | grep 'lxcfs on /proc/cpuinfo type fuse.lxcfs'")
74         machine.succeed("incus exec container mount | grep 'lxcfs on /proc/meminfo type fuse.lxcfs'")
76     with subtest("resource limits"):
77         with subtest("Container CPU limits can be managed"):
78             set_container("limits.cpu 1")
79             cpuinfo = machine.succeed("incus exec container grep -- -c ^processor /proc/cpuinfo").strip()
80             assert cpuinfo == "1", f"Wrong number of CPUs reported from /proc/cpuinfo, want: 1, got: {cpuinfo}"
82             set_container("limits.cpu 2")
83             cpuinfo = machine.succeed("incus exec container grep -- -c ^processor /proc/cpuinfo").strip()
84             assert cpuinfo == "2", f"Wrong number of CPUs reported from /proc/cpuinfo, want: 2, got: {cpuinfo}"
86         with subtest("Container memory limits can be managed"):
87             set_container("limits.memory 64MB")
88             meminfo = machine.succeed("incus exec container grep -- MemTotal /proc/meminfo").strip()
89             meminfo_bytes = " ".join(meminfo.split(' ')[-2:])
90             assert meminfo_bytes == "62500 kB", f"Wrong amount of memory reported from /proc/meminfo, want: '62500 kB', got: '{meminfo_bytes}'"
92             set_container("limits.memory 128MB")
93             meminfo = machine.succeed("incus exec container grep -- MemTotal /proc/meminfo").strip()
94             meminfo_bytes = " ".join(meminfo.split(' ')[-2:])
95             assert meminfo_bytes == "125000 kB", f"Wrong amount of memory reported from /proc/meminfo, want: '125000 kB', got: '{meminfo_bytes}'"
97     with subtest("lxc-generator"):
98         with subtest("lxc-container generator configures plain container"):
99             # reuse the existing container to save some time
100             machine.succeed("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
101             check_sysctl("container")
103         with subtest("lxc-container generator configures nested container"):
104             machine.execute("incus delete --force container")
105             machine.succeed("incus launch nixos container --config security.nesting=true")
106             with machine.nested("Waiting for instance to start and be usable"):
107               retry(instance_is_up)
109             machine.fail("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
110             target = machine.succeed("incus exec container readlink -- -f /run/systemd/system/systemd-binfmt.service").strip()
111             assert target == "/dev/null", "lxc generator did not correctly mask /run/systemd/system/systemd-binfmt.service"
113             check_sysctl("container")
115         with subtest("lxc-container generator configures privileged container"):
116             machine.execute("incus delete --force container")
117             machine.succeed("incus launch nixos container --config security.privileged=true")
118             with machine.nested("Waiting for instance to start and be usable"):
119               retry(instance_is_up)
121             machine.succeed("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
123             check_sysctl("container")
125     with subtest("softDaemonRestart"):
126         with subtest("Instance remains running when softDaemonRestart is enabled and services is stopped"):
127             pid = machine.succeed("incus info container | grep 'PID'").split(":")[1].strip()
128             machine.succeed(f"ps {pid}")
129             machine.succeed("systemctl stop incus")
130             machine.succeed(f"ps {pid}")
131   '';