nixos/tests/incus: test incus-user
[NixPkgs.git] / nixos / tests / incus / incusd-options.nix
blob634d236b05d9ffa53b0517007dcd778f5c74e98a
1 # this is a set of tests for non-default options. typically the default options
2 # will be handled by the other tests
3 import ../make-test-python.nix (
4   {
5     pkgs,
6     lib,
7     incus ? pkgs.incus-lts,
8     ...
9   }:
11   let
12     releases = import ../../release.nix {
13       configuration = {
14         # Building documentation makes the test unnecessarily take a longer time:
15         documentation.enable = lib.mkForce false;
16       };
17     };
19     container-image-metadata = "${
20       releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system}
21     }/tarball/nixos-system-${pkgs.stdenv.hostPlatform.system}.tar.xz";
22     container-image-rootfs = "${
23       releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system}
24     }/nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}.squashfs";
25   in
26   {
27     name = "incusd-options";
29     meta = {
30       maintainers = lib.teams.lxc.members;
31     };
33     nodes.machine = {
34       virtualisation = {
35         cores = 2;
36         memorySize = 1024;
37         diskSize = 4096;
39         incus = {
40           enable = true;
41           package = incus;
42           softDaemonRestart = false;
44           preseed = {
45             networks = [
46               {
47                 name = "incusbr0";
48                 type = "bridge";
49                 config = {
50                   "ipv4.address" = "10.0.100.1/24";
51                   "ipv4.nat" = "true";
52                 };
53               }
54             ];
55             profiles = [
56               {
57                 name = "default";
58                 devices = {
59                   eth0 = {
60                     name = "eth0";
61                     network = "incusbr0";
62                     type = "nic";
63                   };
64                   root = {
65                     path = "/";
66                     pool = "default";
67                     size = "35GiB";
68                     type = "disk";
69                   };
70                 };
71               }
72             ];
73             storage_pools = [
74               {
75                 name = "default";
76                 driver = "dir";
77               }
78             ];
79           };
80         };
82       };
84       networking.nftables.enable = true;
86       users.users.testuser = {
87         isNormalUser = true;
88         shell = pkgs.bashInteractive;
89         group = "incus";
90         uid = 1000;
91       };
92     };
94     testScript = # python
95       ''
96         def wait_for_instance(name: str, project: str = "default"):
97             def instance_is_up(_) -> bool:
98                 status, _ = machine.execute(f"incus exec {name} --disable-stdin --force-interactive --project {project} -- /run/current-system/sw/bin/systemctl is-system-running")
99                 return status == 0
101             with machine.nested(f"Waiting for instance {name} to start and be usable"):
102               retry(instance_is_up)
104         machine.wait_for_unit("incus.service")
105         machine.wait_for_unit("incus-preseed.service")
107         with subtest("Container image can be imported"):
108             machine.succeed("incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos")
110         with subtest("Container can be launched and managed"):
111             machine.succeed("incus launch nixos instance1")
112             wait_for_instance("instance1")
113             machine.succeed("echo true | incus exec instance1 /run/current-system/sw/bin/bash -")
115         with subtest("Verify preseed resources created"):
116             machine.succeed("incus profile show default")
117             machine.succeed("incus network info incusbr0")
118             machine.succeed("incus storage show default")
120         with subtest("Instance is stopped when softDaemonRestart is disabled and services is stopped"):
121             pid = machine.succeed("incus info instance1 | grep 'PID'").split(":")[1].strip()
122             machine.succeed(f"ps {pid}")
123             machine.succeed("systemctl stop incus")
124             machine.fail(f"ps {pid}")
126         with subtest("incus-user allows restricted access for users"):
127             machine.fail("incus project show user-1000")
128             machine.succeed("su - testuser bash -c 'incus list'")
129             # a project is created dynamically for the user
130             machine.succeed("incus project show user-1000")
131             # users shouldn't be able to list storage pools
132             machine.fail("su - testuser bash -c 'incus storage list'")
134         with subtest("incus-user allows users to launch instances"):
135             machine.succeed("su - testuser bash -c 'incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos'")
136             machine.succeed("su - testuser bash -c 'incus launch nixos instance2'")
137             wait_for_instance("instance2", "user-1000")
138       '';
139   }