Release NixOS 23.11
[NixPkgs.git] / nixos / tests / zfs.nix
blob3454fbaf78fe564142d7aef90d6c08a831d6f378
1 { system ? builtins.currentSystem,
2   config ? {},
3   pkgs ? import ../.. { inherit system config; }
4 }:
6 with import ../lib/testing-python.nix { inherit system pkgs; };
8 let
10   makeZfsTest = name:
11     { kernelPackage ? if enableUnstable
12                       then pkgs.zfsUnstable.latestCompatibleLinuxPackages
13                       else pkgs.linuxPackages
14     , enableUnstable ? false
15     , enableSystemdStage1 ? false
16     , extraTest ? ""
17     }:
18     makeTest {
19       name = "zfs-" + name;
20       meta = with pkgs.lib.maintainers; {
21         maintainers = [ adisbladis elvishjerricco ];
22       };
24       nodes.machine = { pkgs, lib, ... }:
25         let
26           usersharePath = "/var/lib/samba/usershares";
27         in {
28         virtualisation = {
29           emptyDiskImages = [ 4096 4096 ];
30           useBootLoader = true;
31           useEFIBoot = true;
32         };
33         boot.loader.systemd-boot.enable = true;
34         boot.loader.timeout = 0;
35         boot.loader.efi.canTouchEfiVariables = true;
36         networking.hostId = "deadbeef";
37         boot.kernelPackages = kernelPackage;
38         boot.supportedFilesystems = [ "zfs" ];
39         boot.zfs.enableUnstable = enableUnstable;
40         boot.initrd.systemd.enable = enableSystemdStage1;
42         environment.systemPackages = [ pkgs.parted ];
44         # /dev/disk/by-id doesn't get populated in the NixOS test framework
45         boot.zfs.devNodes = "/dev/disk/by-uuid";
47         specialisation.samba.configuration = {
48           services.samba = {
49             enable = true;
50             extraConfig = ''
51               registry shares = yes
52               usershare path = ${usersharePath}
53               usershare allow guests = yes
54               usershare max shares = 100
55               usershare owner only = no
56             '';
57           };
58           systemd.services.samba-smbd.serviceConfig.ExecStartPre =
59             "${pkgs.coreutils}/bin/mkdir -m +t -p ${usersharePath}";
60           virtualisation.fileSystems = {
61             "/tmp/mnt" = {
62               device = "rpool/root";
63               fsType = "zfs";
64             };
65           };
66         };
68         specialisation.encryption.configuration = {
69           boot.zfs.requestEncryptionCredentials = [ "automatic" ];
70           virtualisation.fileSystems."/automatic" = {
71             device = "automatic";
72             fsType = "zfs";
73           };
74           virtualisation.fileSystems."/manual" = {
75             device = "manual";
76             fsType = "zfs";
77           };
78           virtualisation.fileSystems."/manual/encrypted" = {
79             device = "manual/encrypted";
80             fsType = "zfs";
81             options = [ "noauto" ];
82           };
83           virtualisation.fileSystems."/manual/httpkey" = {
84             device = "manual/httpkey";
85             fsType = "zfs";
86             options = [ "noauto" ];
87           };
88         };
90         specialisation.forcepool.configuration = {
91           systemd.services.zfs-import-forcepool.wantedBy = lib.mkVMOverride [ "forcepool.mount" ];
92           systemd.targets.zfs.wantedBy = lib.mkVMOverride [];
93           boot.zfs.forceImportAll = true;
94           virtualisation.fileSystems."/forcepool" = {
95             device = "forcepool";
96             fsType = "zfs";
97             options = [ "noauto" ];
98           };
99         };
101         services.nginx = {
102           enable = true;
103           virtualHosts = {
104             localhost = {
105               locations = {
106                 "/zfskey" = {
107                   return = ''200 "httpkeyabc"'';
108                 };
109               };
110             };
111           };
112         };
113       };
115       testScript = ''
116         machine.wait_for_unit("multi-user.target")
117         machine.succeed(
118             "zpool status",
119             "parted --script /dev/vdb mklabel msdos",
120             "parted --script /dev/vdb -- mkpart primary 1024M -1s",
121             "parted --script /dev/vdc mklabel msdos",
122             "parted --script /dev/vdc -- mkpart primary 1024M -1s",
123         )
125         with subtest("sharesmb works"):
126             machine.succeed(
127                 "zpool create rpool /dev/vdb1",
128                 "zfs create -o mountpoint=legacy rpool/root",
129                 # shared datasets cannot have legacy mountpoint
130                 "zfs create rpool/shared_smb",
131                 "bootctl set-default nixos-generation-1-specialisation-samba.conf",
132                 "sync",
133             )
134             machine.crash()
135             machine.wait_for_unit("multi-user.target")
136             machine.succeed("zfs set sharesmb=on rpool/shared_smb")
137             machine.succeed(
138                 "smbclient -gNL localhost | grep rpool_shared_smb",
139                 "umount /tmp/mnt",
140                 "zpool destroy rpool",
141             )
143         with subtest("encryption works"):
144             machine.succeed(
145                 'echo password | zpool create -O mountpoint=legacy '
146                 + "-O encryption=aes-256-gcm -O keyformat=passphrase automatic /dev/vdb1",
147                 "zpool create -O mountpoint=legacy manual /dev/vdc1",
148                 "echo otherpass | zfs create "
149                 + "-o encryption=aes-256-gcm -o keyformat=passphrase manual/encrypted",
150                 "zfs create -o encryption=aes-256-gcm -o keyformat=passphrase "
151                 + "-o keylocation=http://localhost/zfskey manual/httpkey",
152                 "bootctl set-default nixos-generation-1-specialisation-encryption.conf",
153                 "sync",
154                 "zpool export automatic",
155                 "zpool export manual",
156             )
157             machine.crash()
158             machine.start()
159             machine.wait_for_console_text("Starting password query on")
160             machine.send_console("password\n")
161             machine.wait_for_unit("multi-user.target")
162             machine.succeed(
163                 "zfs get -Ho value keystatus manual/encrypted | grep -Fx unavailable",
164                 "echo otherpass | zfs load-key manual/encrypted",
165                 "systemctl start manual-encrypted.mount",
166                 "zfs load-key manual/httpkey",
167                 "systemctl start manual-httpkey.mount",
168                 "umount /automatic /manual/encrypted /manual/httpkey /manual",
169                 "zpool destroy automatic",
170                 "zpool destroy manual",
171             )
173         with subtest("boot.zfs.forceImportAll works"):
174             machine.succeed(
175                 "rm /etc/hostid",
176                 "zgenhostid deadcafe",
177                 "zpool create forcepool /dev/vdb1 -O mountpoint=legacy",
178                 "bootctl set-default nixos-generation-1-specialisation-forcepool.conf",
179                 "rm /etc/hostid",
180                 "sync",
181             )
182             machine.crash()
183             machine.wait_for_unit("multi-user.target")
184             machine.fail("zpool import forcepool")
185             machine.succeed(
186                 "systemctl start forcepool.mount",
187                 "mount | grep forcepool",
188             )
189       '' + extraTest;
191     };
194 in {
196   stable = makeZfsTest "stable" { };
198   unstable = makeZfsTest "unstable" {
199     enableUnstable = true;
200   };
202   unstableWithSystemdStage1 = makeZfsTest "unstable" {
203     enableUnstable = true;
204     enableSystemdStage1 = true;
205   };
207   installer = (import ./installer.nix { }).zfsroot;
209   expand-partitions = makeTest {
210     name = "multi-disk-zfs";
211     nodes = {
212       machine = { pkgs, ... }: {
213         environment.systemPackages = [ pkgs.parted ];
214         boot.supportedFilesystems = [ "zfs" ];
215         networking.hostId = "00000000";
217         virtualisation = {
218           emptyDiskImages = [ 20480 20480 20480 20480 20480 20480 ];
219         };
221         specialisation.resize.configuration = {
222           services.zfs.expandOnBoot = [ "tank" ];
223         };
224       };
225     };
227     testScript = { nodes, ... }:
228       ''
229         start_all()
230         machine.wait_for_unit("default.target")
231         print(machine.succeed('mount'))
233         print(machine.succeed('parted --script /dev/vdb -- mklabel gpt'))
234         print(machine.succeed('parted --script /dev/vdb -- mkpart primary 1M 70M'))
236         print(machine.succeed('parted --script /dev/vdc -- mklabel gpt'))
237         print(machine.succeed('parted --script /dev/vdc -- mkpart primary 1M 70M'))
239         print(machine.succeed('zpool create tank mirror /dev/vdb1 /dev/vdc1 mirror /dev/vdd /dev/vde mirror /dev/vdf /dev/vdg'))
240         print(machine.succeed('zpool list -v'))
241         print(machine.succeed('mount'))
242         start_size = int(machine.succeed('df -k --output=size /tank | tail -n1').strip())
244         print(machine.succeed("/run/current-system/specialisation/resize/bin/switch-to-configuration test >&2"))
245         machine.wait_for_unit("zpool-expand-pools.service")
246         machine.wait_for_unit("zpool-expand@tank.service")
248         print(machine.succeed('zpool list -v'))
249         new_size = int(machine.succeed('df -k --output=size /tank | tail -n1').strip())
251         if (new_size - start_size) > 20000000:
252           print("Disk grew appropriately.")
253         else:
254           print(f"Disk went from {start_size} to {new_size}, which doesn't seem right.")
255           exit(1)
256       '';
257   };